viernes, marzo 15, 2013

Volver a ROM Samsung Galaxy S2 oficial 4.1.2-root desde CyanogenMod



Voy a describir los pasos necesarios para volver desde una CyanogenMod (9.1 en mi caso, pero también sirve para las 10.x) a la ROM oficial de SAMSUNG XWLSD_FOPLS4 (Febrero 2013). Ojo, sólo he probado lo siguiente en esa versión de ROM, así que no recomiendo realizar los mismos pasos y usar los mismos programas para otras (no puedo certificar nada para versiones diferentes).

En mi caso vuelvo a la ROM oficial porque estoy cansado de trastear con el teléfono. Creo que la versión 4.1.2 ya es suficientemente completa para mi uso diario y no quiero perder más tiempo con el teléfono más allá de usarlo y disfrutarlo. Poner la ROM oficial te limita mucho así que un término medio entre Custom ROM y ROM oficial es poner la ROM oficial y un kernel custom que te "regala" root+CWM+BLN.

Básicamente, el procedimiento consiste en:

  1. Descargar todos los ficheros necesarios (ROM, kernel, ODIN, apks para liberar el móvil, etc)
  2. Hacer backup del contenido del móvil (carpeta /efs, nandroid, aplicaciones, etc)
  3. Instalar ROM oficial con ODIN.
  4. Rootear el teléfono con un kernel custom y ODIN.
  5. Liberar de nuevo la SIM del teléfono.
  6. Quitar el triángulo amarillo de aviso de que el móvil ha sido modificado.
  7. Recuperar nuestras aplicaciones y personalizar de nuevo las configuraciones.

Comencemos:


COSAS A DESCARGAR:

Buscamos en google (normalmente es fácil de encontrar y están enlazadas en htcmania o xda-developers):

  • Samsung Kies (si no lo tienes ya instalado, hay que instalarlo para que Windows reconozca el teléfono).
  • Odin 3 v1.85 (para instalar la ROM)
  • Odin 3 v3.07 (para instalar el kernel Siyah con root)
  • Siyah-s2-v6.0b5.tar (kernel con root y soporte BLN)
  • GalaxSimUnlock.apk (para re-liberar el móvil)
  • TriangleAway237.apk (para quitar el triángulo amarillo que avisa en el arranque de que el móvil ha sido modificado)
  • ROM I9100XWLSD_I9100FOPLS4_FOP.zip (descargada de sammobile, ahora explico cómo).



DESCARGAR LA ROM:

  • Necesitaremos crear una cuenta para poder descargar ficheros. Creamos una cuenta nueva.
  • Una vez en /firmwares/, pulsamos arriba en FIRMWARES donde pone "HOME - CHECK YOUR FIRMWARE - FIRMWARES"
  • En el cajetín de búsqueda ponemos "SmartPhone" - "Android" - "GT-I9100 - Galaxy SII" - "Spain - FOP". La versión FOP es la versión libre. Podemos instalar también (están en ese desplegable) las de las operadoras Movistar, Vodafone, Orange y Yoigo (yo prefiero la libre).
  • Abajo nos aparecerán los posibles firmwares a descargar. Por ejemplo:


Country  Date Version    PDA     CSC             Kies
Spain 2013 February 4.1.2 I9100XWLSD I9100FOPLS4
Spain 2013 January 4.1.2 I9100XWLS8 I9100FOPLS3


  • Pulsamos sobre I9100XWLSD, que es la última versión. Es la misma que la XWLS8 con un parche de 21MB que salió a las 2 semanas vía OTA. Esto nos llevará a un enlace directo en hotfile, de donde bajamos la ROM (552.7MB).
  • Desempaquetamos el ZIP y obtendremos un fichero .tar.md5 que es el que usaremos en ODIN.



HACER COPIAS:

  • Si somos root en el dispositivo (lo normal si usamos Cyanogenmod), es muy recomendable hacer una copia del directorio /efs. Este directorio es importante porque contiene el IMEI de nuestro teléfono, y si lo perdemos podemos tener bastantes problemas después para hacer llamadas. De hecho, este backup deberíais hacerlo desde el primer día y guardarlo, estéis cambiando de rom o no. EFS  cuelga de /, no de /mnt/sdcard que es la raíz que vemos en la mayoría de gestores de ficheros. Yo hice la copia con el FX File Explorer explorando / en modo root, pulsación larga sobre EFS, Comprimir, en /emmc/backup/efs.tar.gz . Es necesario un tar.gz para que se preserven propietarios y permisos de los ficheros porque la SD suele ser formato FAT. También hay aplicaciones específicas para hacer copias de la carpeta EFS. En teoría no se debería sobreescribir este directorio porque es una partición diferente de data, system y /, pero por si acaso (y por si algún día se os corrompe) haced este backup.
  • Instalar MyBackup o Titanium Backup hacer copia de las apps instaladas (sólo APKs, no APKs+DATOS). Los datos no nos servirán porque no son compatibles entre versiones, sólo los APKs.
  • Hacer una copia de la /sdcard/DCIM (las fotos y vídeos) a la microSD, para tenerlas por si acaso.
  • Entramos en Ajustes - Desarrollo y activamos Depuración USB.
  • Si tenemos Clockworkmod, entrar en modo recovery (encender el teléfono pulsando POWER + HOME + VOLUP) y hacer nandroid en formato tar del sistema, en la microSD.
  • Apagar el teléfono, poner la microSD en el PC y hacer una copia de sus contenidos (de los backups y los datos a conservar, vamos).
  • Aprovechar para crear una carpeta "OLD" en la microSD y MOVER alli todas las carpetas de "android" (android, data, databases, whatsapp, etc) que hay en la microSD, propias de Android o de aplicaciones, para que las cree limpias en el mismo sistema. Dejar solo las carpetas nuestras personales (Download, musica, etc).
  • Entrar en modo recovery de nuevo y hacer "Wipe Cache", "Wipe Battery Stats", "Wipe Dalvik Cache" y "Wipe Data / Factory Reset". Acabamos de resetear totalmente el teléfono.



INSTALAR LA ROM 4.1.2 OFICIAL:

  • Cargar batería del móvil al 100% por seguridad. Si el procedimiento lo hacemos desde un portátil conectado a la luz y con la batería cargada, mejor.
  • Instalar Samsung Kyes (si no lo tenemos ya).
  • Reiniciar Windows.
  • Insertar el teléfono para que instale los drivers. Esperar hasta que esté reconocido el teléfono (avisará de una serie de drivers instalados).
  • Desconectar el teléfono.
  • Matar Kyes con (Inicio -> ejecutar -> taskmgr -> procesos -> eliminar Kyes.exe).
  • Abrir Odin 3 v1.85
  • Quitar cable del teléfono y del PC.
  • Arrancar el teléfono en modo download (apagar, encender con VOLDOWN+POWER+HOME y soltarlo cuando salga una pregunta a la que contestaremos con la VOLUP para continue).
  • Conectar el cable al teléfono y al PC, y esperar a que lo detecte Windows y ODIN.
  • En PDA seleccionar el tar.md5 de la rom a flashear. Asegurarse de que sólo están marcadas las opciones "AutoReboot" y "F. Reset Time". NO MARCAR NINGUNA OTRA OPCION.
  • Darle a START. Esperar unos minutos, NO DESCONECTAR EL CABLE NI TOCAR NI EL PC NI EL TELEFONO.
  • El teléfono se reiniciará (desconectar entonces los cables ya sin problemas).
  • Arrancará 4.1.2 JB. Configuradlo pero no pongáis cuenta de google aún.
  • No marcar todavía las opciones de "Hacer copia de este dispositivo" y "Restaurar el dispositivo".
  • Meter el PIN de red. Luego (al menos en mi caso) nos pedirá un código para desbloquear la SIM porque si el teléfono era liberado, probablemente ya no lo estará. En este segundo punto cancelamos/descartamos para seguir usando el teléfono sin SIM.


Este procedimiento lo podéis ver más o menos en este vídeo:

http://www.youtube.com/watch?v=XCYU0XNNQh8&feature=player_embedded


ROOTEAR EL TELEFONO E INSTALAR KERNEL CON SOPORTE BLN:

Como véis, la ROM original no tiene root por lo que estamos limitados para ciertas cosas y además si era un teléfono liberado, es posible que necesitemos root para liberarlo de nuevo. Instalando un kernel personalizado podemos tener root y además cosas adicionales, como soporte BLN.

El soporte BLN es IMPRESCINDIBLE. Nuestro móvil no tiene LED de avisos, como sí tienen otros móviles, así que si alguien te escribe por Whatsapp o te llama y no estás delante del teléfono, cuando lo tienes de nuevo delante no te enteras a menos que enciendas la pantalla y veas las notificaciones. Con el soporte BLN y la aplicación del market BLN Control, se encenderán las luces de la parte de abajo de la pantalla (menú y volver) como si fueran leds de notificación, de forma que sólo mirando el teléfono puedes saber si tienes algún mensaje nuevo. No gastan tanta batería como podáis pensar. Lo único que tuve que hacer yo para que no estuvieran siempre encendidas (por culpa del correo) fue quitar las notificaciones de gmail y poner un widget de gmail que tiene un numerito con los correos sin leer.

Aunque no queráis soporte BLN, tenéis que instalar este kernel para tener root, luego no tenéis por qué activar el BLN (ni descargar siquiera BLN Control) si no queréis.

  • Abrir Odin 3 v3.07
  • Quitar cables del teléfono y del PC.
  • Arrancar el teléfono en modo download (apagar, encender con VOLDOWN+POWER+HOME y soltarlo cuando salga una pregunta a la que contestaremos con la VOLUP para continue).
  • Conectar el cable al teléfono y al PC, y esperar a que lo detecte Windows y ODIN.
  • En PDA seleccionar el tar.md5 de Siyah-s2-v6.0b5.tar. Asegurarse de que sólo están marcadas las opciones "AutoReboot" y "F. Reset Time".
  • Darle a START. Acabará muy rápido y reiniciará el teléfono (podemos quitar los cables).
  • Meter el PIN de red. Luego nos pedirá un código para desbloquear la SIM porque si el teléfono era liberado, probablemente ya no lo estará. En este segundo punto cancelamos/descartamos para seguir usando el teléfono sin SIM.
  • Ir a "Cajón de aplicaciones" -> "Ajustes" -> "Seguridad" -> "Fuentes desconocidas" y activarlo.
  • Ir a las aplicaciones, Archivos e instalar GalaxSimUnlock.apk. Ejecutarlo y desbloquear la SIM.
  • Reiniciar, esta vez sí nos aceptará el PIN.



QUITAR EL TRIANGULO DE AVISO DE TELEFONO MODIFICADO

Al modificar el teléfono (hacerse root) siempre sale un triángulo amarillo de aviso al arrancar. Podemos quitarlo así:


  • Instalar TriangleAway237.apk y ejecutarlo. 
  • Reiniciar para comprobar que ya no aparece.



RECUPERAR TODAS LAS APLICACIONES:

Ahora viene lo peor, dejar el teléfono como estaba antes de meternos en faena (con todas sus aplicaciones y configuraciones):

  • Activar copia de seguridad y restauración ("Ajustes" -> "Copia de seguridad").
  • Configuramos nuestra cuenta de Google en "Ajustes" -> "Cuentas" -> "Google".

Y ahora, recuperamos las aplicaciones:
  • Opción A: Entrar en google play, sección aplicaciones, todas, y descargar manualmente las aplicaciones que queramos descargar.
  • Opción B: Instalar MyBackup o Titanium Backup y restaurar las apps instaladas. Ojo, tendréis que desmarcar algunas de las aplicaciones para que no las restaure (cosas de Cyanogen como su cámara, sus salvapantallas, el ROM manager, etc). Si restauramos desde backup, deberá ser SOLO los APKs, no los datos. Tendremos que configurar las aplicaciones otra vez (al restaurar sólo los APKs no están configuradas).
  • Hay que tener paciencia en este paso, y restaurar sólo lo que vayamos a usar y no meter "basura" que venía de Cyanogen.
  • Si tenemos titaniumBackup, "congelar" (o desinstalar) aplicaciones que puedan consumir recursos o que sean de Samsung.
  • Configuramos el launcher, ponemos los iconos en su sitio, agregamos los widgets deseados, etc etc etc...

Algunas aplicaciones que se pueden congelar con seguridad (visto en htcmania y xda-developers):

Actualizacion de software
Allshare service
Almacenamiento de contenido protegido por DRM
Dias
Dispositivos cercanos
DSMForwarding
DSMLawmo
Enterprise SysScope Service
Kies mediante wifi
MAPServiceSamsung
Rastreador móvil
Samsung browser syncadapter
Samsung calendar syncadapter
Samsung contact syncadapter
Samsung syncadapter
SamsungAppsUNA2
SASlideShow
SysScope
Weather widget
wssyncmlnps
ChatOn
Video Hub
Readers Hub
Music Hub

En XDA hay un hilo con más aplicaciones que se pueden congelar (o deinstalar) para reducir el consumo de batería:

http://forum.xda-developers.com/showthread.php?t=2016419

Espero que os haya sido de utilidad :-) . Por si acaso, yo no me responsabilizo del resultado de la ejecución de los anteriores pasos, sólo diré que lo he hecho en mi teléfono con éxito y que la semana que viene lo haré en otro S2 para dejarlo también en la versión oficial.

miércoles, marzo 13, 2013

Control de volumen usando el teclado en XFCE



Si queremos manejar rápidamente el volumen desde el teclado en XFCE y no tenemos ningún teclado con teclas de función especiales (o no las detecta), podéis usar los símbolos +, -, * y / del teclado numérico junto a la tecla CONTROL de la siguiente forma:

Menú → Configuración → Teclado → Atajos de aplicación


Añadir los siguientes atajos:


Comando:  amixer set Master 5%+
Atajo:    Ctrl+KEYPAD_+

Comando:  amixer set Master 5%-
Atajo:    Ctrl+KEYPAD_-

Comando:  amixer set Master 100%-
Atajo:    Ctrl+KEYPAD_*

Comando:  amixer set Master 100%-
Atajo:    Ctrl+KEYPAD_/


Otra posible opción a añadir es la de alternar el canal de audio con:

amixer set Master toggle

Pero presenta el problema de que es posible que al hacer un toggle a mute, necesitemos deshacer el mute del PCM (y de los HeadPhone, si se tercia) para recuperar el audio:

amixer set PCM 100% unmute

(Esto implicaría tener que usar un script para el toggle, y no un simple comando como en los casos anteriores, de ahí que prefiera el paso de volumen a cero con CTRL+KEYPAD_/)


EDIT: 

No me he podido resistir a añadir también lo siguiente para controlar banshee:


Comando:  banshee --toggle-playing
Atajo:    Ctrl+KEYPAD_5

Comando:  banshee --previous
Atajo:    Ctrl+KEYPAD_4

Comando:  banshee --next
Atajo:    Ctrl+KEYPAD_6


Espero que os resulte útil.


jueves, marzo 07, 2013

Astyle - reformateando código desde CLI o vim


En la anterior entrega comenté los diferentes estilos de formato de código y cómo reconfigurar el formateador de código de Eclipse para formatear con el Estilo Allman .

Pero ... ¿y los programadores de C, C++ o Java que no utilizan Eclipse? ¿Alguna buena opción para reformatear el código a un estándar si todos los ficheros del proyecto no lo cumplen?

La solución es AStyle.

Según la documentación, una vez instalado (bien descargado manualmente o bien con "yum install" o "apt-get install" astyle, podemos hacer cosas como:


astyle --style=allman ~/project/foo.cpp

astyle --style=allman --recursive ~/project/*.cpp  ~/project/*.h




astyle [options] < OriginalSourceFile > BeautifiedSourceFile


Si no especificamos ninguna opción adicional, se usarán 4 espacios para los tabuladores.

Si no queremos tener que especificar manualmente ni el estilo ni las opciones largas, podemos crear un fichero $HOME/.astylerc en Linux o %USERPROFILE%\astylerc en Windows, conteniendo las opciones por defecto que queremos, así como opciones que por defecto no podríamos solicitar por la línea de comandos:


#The best formatting style:
--style=allman

# Options:
--indent-classes
--indent-switches
--indent-cases
--indent-namespaces
--indent-labels
--indent-preprocessor
--indent-col1-comments
--break-blocks
--convert-tabs
#--add-brackets <-- add="" after="" codelines="" else...="" font="" if="" single="" to="">

# Short options:
-s4 -p


Además de llamarlo desde línea de comandos, podemos formatear el buffer actual entero en Vim en modo comando con:


:%!astyle


Con esto se filtrará el buffer entero a través de astyle, sustituyendo al actual texto. Se utilizarán los parámetros del .astylerc.

De hecho, si lo usamos normalmente, lo habitual será mapearse una tecla para ello:


map <F8> :%!astyle



Ojo, esto reformateará el archivo entero, ya que tal y como lo estamos haciendo, si le pasamos a Astyle texto seleccionado (:!astyle en una selección) no verá el contexto lo formateará, pero dejándolo en indentado 0 (algo que podríamos solucionar después con >>)...




martes, marzo 05, 2013

Autoformateo de código en Eclipse: Curly Brackets y Max Line Length


La convención de formato para código Java parece indicar que las llaves (curly brackets o braces) que abren clases, métodos y sentencias de control van a la derecha de la definición/sentencia, en la misma línea:

class MiClase {
    ...
}

if( condicion ) {
    ...
}

No obstante, yo, desde hace 15 años (en C) estoy acostumbrado a poner la llave en la siguiente línea, indentada al mismo nivel que la línea de cierre:

class MiClase 
{
    ...
}

if( condicion ) 
{
    ...
}

Sinceramente, a mí me parece más legible e intuitivo para encontrar los diferentes niveles de indentado de código, por lo que no termino de acostumbrarme a poner la llave de apertura a la derecha en la misma línea.

Entiendo que esto se realiza para poder diferenciar estas llaves de las llaves que se pueden usar para definir ámbitos locales para variables:

{
    {
        int i;
        for i in (blah; ... )
        {
        }

    } // i desaparece con este cierre de ámbito
}

Pero, insisto, yo me he acostumbrado a ponerlas en una nueva línea y mucho más desde que programo en Python, donde tengo la costumbre de indentar perfectamente y con 4 espacios, y que ahora me hace casi imposible escribir código Java de la forma "habitual" para los demás desarrolladores.

El problema que tengo es que cuando pulso CTRL+ALT+F (formatting) en Eclipse, me formatea todo el código con la convención "habitual".

Por suerte, he visto que se puede cambiar, tanto eso como el tamaño máximo de línea:

[stackoverflow]/how-do-i-change-the-code-convention-in-eclipse

+


Window -> Preferences -> Java -> Code style -> Formatter view

Create a new profile based on the eclipse built in, then go to braces tab and change "same line" to next line everywhere. Then set the new profile to default.


[stackoverflow]/eclipse-set-maximum-line-length-for-auto-formatting


In preferences Java -> Code Style -> Formatter, edit your profile. Under the Line Wrapping tab is the option for line width (Maximum line width:).

Comments have their own line length setting at the bottom of the setting page Java -> Code style -> Formatter -> Edit... -> Comments



EL DEBATE: CONVENCIÓN VS ESTILO PERSONAL


Tengo sentimientos encontrados al respecto de este cambio.

Por un lado, pienso que es un error ir contra las convenciones generales, porque es importante mantener un estilo similar en todo el código. Y si trabajas en equipo, esto es un problema. Tal vez lo ideal sería acostumbrarse a la convención habitual.

Por otro, para mí es MUCHO más legible el código en este formato. Veo mucho más claro el ámbito de cada clase, método, función o bloque de código en una sentencia de control. Es una reminiscencia de Python, entiendo, pero me ocurre. Y claro, al no ser un programador profesional (como amablemente me recuerda constantemente Fede), el código que voy a crear y mantener probablemente será siempre sólo y exclusivamente mío... Ahora bien, esto es lo que me dice el corazón. La cabeza me dice que cuanto antes me acostumbre a la convención original más fácil me resultaré después leer el código de otros, utilizar código de otros o que otros trabajen conmigo, incluso en otros lenguajes.

La postura oficial de convención para código de Sun y de Oracle es clara al respecto:

[oracle.com]/Code Conventions for the Java TM Programming Language


6.4 Class and Interface Declarations

When coding Java classes and interfaces, the following formatting rules should be followed:
  • No space between a method name and the parenthesis "(" starting its parameter list
  • Open brace "{" appears at the end of the same line as the declaration statement
  • Closing brace "}" starts a line by itself indented to match its corresponding opening statement, except when it is a null statement the "}" should appear immediately after the "{"
class Sample extends Object {
    int ivar1;
    int ivar2;

    Sample(int i, int j) {
        ivar1 = i;
        ivar2 = j;
    }

    int emptyMethod() {}

    ...
}
  • Methods are separated by a blank line


Es decir, la llave en la misma línea :-(.

Me gusta un poco más lo que se propone aquí para PHP:

[github.com]/PSR-2 Coding Style Guide


1.1. Example

This example encompasses some of the rules below as a quick overview:
php
namespace Vendor\Package;

use FooInterface;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

class Foo extends Bar implements FooInterface
{
    public function sampleFunction($a, $b = null)
    {
        if ($a === $b) {
            bar();
        } elseif ($a > $b) {
            $foo->bar($arg1);
        } else {
            BazClass::bar($arg2, $arg3);
        }
    }

    final public static function bar()
    {
        // method body
    }
}


Un mix: clases, métodos y funciones con las llaves en la siguiente línea, ifs, whiles, etc con las llaves en la misma. Eso sí, el elseif y el else junto a las llaves de cierre me provocan dolor de ojos...

¿Opiniones?


EDIT:

Veo que lo mío con las llaves tiene nombre: "Allman Style", y no soy el único que defiende este formato de código (el creador de C++ también lo utiliza). Es una variante del Estilo K&R:

http://en.wikipedia.org/wiki/Indent_style



K&R style

The K&R style, so named because it was used in Kernighan and Ritchie's book The C Programming Language, is commonly used in C. It is also used for C++C#, and others.[citation needed]
When adhering to K&R, each function has its opening brace at the next line on the same indentation level as its header, the statements within the braces are indented, and the closing brace at the end is on the same indentation level as the header of the function at a line of its own. The blocks inside a function, however, have their opening braces at the same line as their respective control statements; closing braces remain in a line of their own, unless followed by an else or while keyword.[citation needed]
In this style a control statement with only a single statement in its scope may omit the braces. The C Programming Language refers to this as fertile soil for bugs (programming logical errors) and discourages it.
int main(int argc, char *argv[])
{
    ...
    while (x == y) {
        something();
        somethingelse();
 
        if (some_error) {
            /* the curly braces around this code block could be omitted */
            do_correct();
        } else
            continue_as_usual();
    }
 
    finalthing();
    ...
}




Allman style

The Allman style is named after Eric Allman. It has been incorrectly referred to as "ANSI style"[7] supposedly for its use in the documents describing the ANSI C standard (later adopted as the ISO C international standard), though in fact those documents use K&R style.[8] It is also sometimes known as "BSD style" since Allman wrote many of the utilities for BSD Unix(although this should not be confused with the different "BSD KNF style"; see below). This style has also been adopted by Bjarne Stroustrup in his books, The C++ Programming Language.
This style puts the brace associated with a control statement on the next line, indented to the same level as the control statement. Statements within the braces are indented to the next level.
while (x == y)
{
    something();
    somethingelse();
}
 
finalthing();
This style is similar to the standard indentation used by the Pascal programming language and Transact-SQL, where the braces are equivalent to the begin and end keywords.
Advantages of this style are that the indented code is clearly set apart from the containing statement by lines that are almost completely whitespace, improving readability, and the closing brace lines up in the same column as the opening brace, making it easy to find matching braces. Additionally, the blocking style delineates the actual block of code from the associated control statement itself. Commenting out the control statement, removing the control statement entirely, refactoring, or removing of the block of code is less likely to introduce syntax errors because of dangling or missing brackets.
For example, the following is still syntactically correct:
//while (x == y)
{
    something();
    somethingelse();
}
As is this:
//for (int i=0; i < x; i++)
//while (x == y)
if (x == y)
{
    something();
    somethingelse();
}
Even like this, with conditional compilation:
char c;
#ifdef HAS_GETCH
while ((c = getch()) != EOF)
#else
while ((c = getchar()) != EOF)
#endif
{
    do_something(c);
}
Each of the enclosing braces occupies an entire line by itself without adding any actual code. Whether this makes the code easier or harder to read is debated.


Por lo que veo en Stackexchange o StackOverflow, no soy el único que ha iniciado debates similares:

[programmers.stackexchange.com]/should-curly-braces-appear-on-their-own-line


En la siguiente encuesta gana por goleada el Allman Style (sólo seguido, con el 50% de los votos que el Allman, por el K&R):

[terminally-incoherent.com]/the-only-correct-indent-style

Sin embargo, sí que puede tener consecuencias negativas en Javascript, con "return":

[stackoverflow]/dangerous-implications-of-allman-style-in-javascript

El debate sigue abierto ... en otros foros donde lo he lanzado, la mayoría de la gente opina que me ciña a la convención general del lenguaje, pero cuanto más código miro con la convención general de Java, más claro y simple me parece el estillo Allman...

sábado, marzo 02, 2013

Parsear el XML del backup de Blogger.



Hoy he visto que Blogger permite realizar un backup en XML de tu blog en:


  • Configuración -> Otros -> Herramientas del blog -> Exportar blog


El fichero XML resultante contiene de todo: Usuarios, Configuración, Posts, Comentarios ... por lo que si quieres extraer sólo los posts realizados hay que realizar algo de trabajo con el XML.

En la siguiente URL ( http://www.benjaminhorn.se/post/blogspot-backup-xml-parser/ ) se habla de una clase PHP para parsear el XML exportado por blogger. La clase está disponible en:

https://github.com/beije/Blogspotparser

Y su uso es tan "sencillo" como:

/**
 * Blogspotparser 
 * 
 * Blogspotparser is a class that takes the backup xml file from blogspot and parses it
 * into a basic array, returning the posts as is, with html markup or as clean text.
 * 
 * @author      : Benjamin Horn
 * @project     : Fiinixdesign.eu
 * @file        : class.blogspot.parser.php
 * @version     : 1.0.0
 * @created     : 2012-09-22
 * @updated     : 2012-09-22
 *
 * @usage       :
 *
 * $p = new Blogspotparser( $XMLDATASTRING );   // Initiate class
 * $p->fetch_entries_clean();            // Output posts as clean data
 * $p->fetch_entries();              // Output posts with original markup
 * $p->fetch_amount_of_entries();        // Fetch amount of posts in backup
 *
 */

Habrá que probarlo :)

Utilizar subversion y git en Eclipse


Yo, que programo principalmente en python habitualmente usando vim y control de versiones con subversion o git, me veo un poco descolocado al verme "obligado" a usar Eclipse para los proyectos Java.

Ayer me planteé la duda de si puedo "versionar" el código en subversion o git y al mismo tiempo ser compatible con programar en Eclipse.

Lo normal en mi procedimiento diario con python es crear un proyecto con un "main.py", versionarlo, borrar el directorio original y bajar el código versionado, y entonces ya subo los cambios, y añado los nuevos ficheros al subversion/git conforme los voy creando. 

Me gusta (no, más bien, *necesito*) tener el código versionado para tener control de versiones, poder revertir cambios, poder tener un histórico de los cambios realizados, taggear versiones, hacer una rama alternativa para probar cosas, poder mantener el mismo código desde diferentes ordenadores, etc etc etc...

No tenía claro si esto se podía realizar en eclipse, es decir, crear un proyecto, subirlo al repositorio, BORRAR la carpeta del proyecto y descargarlo desde el repositorio... ¿cómo le sentará a Eclipse la aparición de los ficheros de versionado en la carpeta del proyecto?

Tendría supongo que estar también pendiente de todos los ficheros que va creando Eclipse internamente y de los que no te informa, y supongo que para hacer un update del código desde el repositorio tendrá que estar Eclipse cerrado, porque igual no vé los cambios si vienen desde fuera...

Total, que esa era mi duda, que ha sido fácilmente despejada con los siguientes recursos:

Por lo visto no se puede (debe) hacer manualmente sino a través de un plugin:


Subversion:

http://www.ibm.com/developerworks/library/os-ecl-subversion/
http://tratandodeentenderlo.blogspot.com.es/2009/09/manejo-de-subversion-desde-eclipse.html


Git:

http://www.vogella.com/articles/EGit/article.html
http://blog.art4software.com/2013/02/usando-git-desde-eclipse/
http://blog.farmerdev.com/?p=26


GitHub:

http://eclipse.github.com/

Así que, bueno, ya no hay excusa para no versionar emoticon

viernes, marzo 01, 2013

"Extended" history in bash


I've found a nice article on http://jeetworks.org/node/80 that I'm going to reproduce here, to have a copy in case the original page ever disappears (I hope he doesn't mind while I include authorship, original link, etc):



Supplementary Command History Logging in Bash: Tracking Working Directory, Date/Times, etc.







Here is a way to create a secondary shell history log (i.e., one that supplements the primary "~/.bash_history") that tracks a range of other information, such as the working directory, hostname, time and date etc. Using the "HISTTIMEFORMAT" variable, it is in fact possible to store the time and date with the primary history, but the storing of the other information is not as readibly do-able. Here, I present an approach based on this excellent post on StackOverflow.
The main differences between this approach and the original is:
  • I remove the option to log the extra information to the primary history file: I prefer to keep this history clean.
  • I add history number, host name, time/date stamp etc. to the supplementary history log by default.
  • I add field separators, making it easy to apply 'awk' commands.
The (Supplementary) History Logger Function
First, add or source the following to your "~/.bashrc":

_loghistory() { # From: https://gist.github.com/jeetsukumaran/2202879/raw/16e92b805cbcf69ca18e5033c0f26bfebb165efe/loghistory.sh
# Detailed history log of shell activities, including time stamps, working directory etc. # # Based on 'hcmnt' by Dennis Williamson - 2009-06-05 - updated 2009-06-19 # (http://stackoverflow.com/questions/945288/saving-current-directory-to-bash-history) # # Add this function to your '~/.bashrc': # # Set the bash variable PROMPT_COMMAND to the name of this function and include # these options: # # e - add the output of an extra command contained in the histentrycmdextra variable # h - add the hostname # y - add the terminal device (tty) # n - don't add the directory # t - add the from and to directories for cd commands # l - path to the log file (default = $HOME/.bash_log) # ext or a variable # # See bottom of this function for examples. # # make sure this is not changed elsewhere in '.bashrc'; # if it is, you have to update the reg-ex's below export HISTTIMEFORMAT="[%F %T] ~~~ " local script=$FUNCNAME local histentrycmd= local cwd= local extra= local text= local logfile="$HOME/.bash_log" local hostname= local histentry= local histleader= local datetimestamp= local histlinenum= local options=":hyntel:" local option= OPTIND=1 local usage="Usage: $script [-h] [-y] [-n|-t] [-e] [text] [-l logfile]" local ExtraOpt= local NoneOpt= local ToOpt= local tty= local ip= # *** process options to set flags *** while getopts $options option do case $option in h ) hostname=$HOSTNAME;; y ) tty=$(tty);; n ) if [[ $ToOpt ]] then echo "$script: can't include both -n and -t." echo $usage return 1 else NoneOpt=1 # don't include path fi;; t ) if [[ $NoneOpt ]] then echo "$script: can't include both -n and -t." echo $usage return 1 else ToOpt=1 # cd shows "from -> to" fi;; e ) ExtraOpt=1;; # include histentrycmdextra l ) logfile=$OPTARG;; : ) echo "$script: missing filename: -$OPTARG." echo $usage return 1;; * ) echo "$script: invalid option: -$OPTARG." echo $usage return 1;; esac done text=($@) # arguments after the options are saved to add to the comment text="${text[*]:$OPTIND - 1:${#text[*]}}" # add the previous command(s) to the history file immediately # so that the history file is in sync across multiple shell sessions history -a # grab the most recent command from the command history histentry=$(history 1) # parse it out histleader=`expr "$histentry" : ' *\([0-9]* \[[0-9]*-[0-9]*-[0-9]* [0-9]*:[0-9]*:[0-9]*\]\)'` histlinenum=`expr "$histleader" : ' *\([0-9]* \)'` datetimestamp=`expr "$histleader" : '.*\(\[[0-9]*-[0-9]*-[0-9]* [0-9]*:[0-9]*:[0-9]*\]\)'` histentrycmd=${histentry#*~~~ } # protect against relogging previous command # if all that was actually entered by the user # was a (no-op) blank line if [[ -z $__PREV_HISTLINE || -z $__PREV_HISTCMD ]] then # new shell; initialize variables for next command export __PREV_HISTLINE=$histlinenum export __PREV_HISTCMD=$histentrycmd return elif [[ $histlinenum == $__PREV_HISTLINE && $histentrycmd == $__PREV_HISTCMD ]] then # no new command was actually entered return else # new command entered; store for next comparison export __PREV_HISTLINE=$histlinenum export __PREV_HISTCMD=$histentrycmd fi if [[ -z $NoneOpt ]] # are we adding the directory? then if [[ ${histentrycmd%% *} == "cd" || ${histentrycmd%% *} == "jd" ]] # if it's a cd command, we want the old directory then # so the comment matches other commands "where *were* you when this was done?" if [[ -z $OLDPWD ]] then OLDPWD="$HOME" fi if [[ $ToOpt ]] then cwd="$OLDPWD -> $PWD" # show "from -> to" for cd else cwd=$OLDPWD # just show "from" fi else cwd=$PWD # it's not a cd, so just show where we are fi fi if [[ $ExtraOpt && $histentrycmdextra ]] # do we want a little something extra? then extra=$(eval "$histentrycmdextra") fi # strip off the old ### comment if there was one so they don't accumulate # then build the string (if text or extra aren't empty, add them with some decoration) histentrycmd="${datetimestamp} ${text:+[$text] }${tty:+[$tty] }${ip:+[$ip] }${extra:+[$extra] }~~~ ${hostname:+$hostname:}$cwd ~~~ ${histentrycmd# * ~~~ }" # save the entry in a logfile echo "$histentrycmd" >> $logfile || echo "$script: file error." ; return 1 } # END FUNCTION _loghistory


Activating the Logger
Then you need to set this function to execute on every command by adding it to your "$PROMPT_COMMAND" variable, so you need the following entry in your "~/.bashrc":
export PROMPT_COMMAND='_loghistory'
There are a number of options that the logging function takes, including the adding terminal information, the adding of arbitrary text or the execution of a function or function(s) that generate appropriate text. See the function documentation for more info.

Add Some Useful Aliases
Add the following to your "~/.bashrc":
# dump regular history log
alias h='history'
# dump enhanced history log
alias hh="cat $HOME/.bash_log"
# dump history of directories visited
alias histdirs="cat $HOME/.bash_log | awk -F ' ~~~ ' '{print $2}' | uniq"
Checkout the Results! The 'histdirs' command is very useful to quickly list, select (via copy and pasting) and jumping back to a directory.
$ h
14095 [2011-11-23 15:36:20] ~~~ jd nuim
14096 [2011-11-23 15:36:21] ~~~ ll
14097 [2011-11-23 15:36:23] ~~~ git status
14098 [2011-11-23 15:36:33] ~~~ jd pytb
14099 [2011-11-23 15:36:36] ~~~ git status
14100 [2011-11-23 15:36:53] ~~~ git rm --cached config/*
14101 [2011-11-23 15:37:00] ~~~ git pull
14102 [2011-11-23 15:37:11] ~~~ e .gitignore
14103 [2011-11-23 15:37:28] ~~~ git status
14104 [2011-11-23 15:37:35] ~~~ e .gitignore
14105 [2011-11-23 15:37:44] ~~~ git status
14106 [2011-11-23 15:38:10] ~~~ git commit -a -m "stuff"
14107 [2011-11-23 15:38:12] ~~~ git pushall
14108 [2011-11-23 15:50:38] ~~~ ll build_c/
14109 [2011-11-23 15:53:16] ~~~ cd
14110 [2011-11-23 15:53:18] ~~~ ls -l
14111 [2011-11-23 16:00:12] ~~~ cd Documents/Projects/Phyloinformatics/DendroPy/dendropy
14112 [2011-11-23 16:00:15] ~~~ ls -l
14113 [2011-11-23 16:00:22] ~~~ cd dendropy/
14114 [2011-11-23 16:00:24] ~~~ vim *.py
$ hh
[2011-11-23 15:36:20] ~~~ /Users/jeet ~~~ jd nuim
[2011-11-23 15:36:21] ~~~ /Users/jeet/Documents/Projects/Phyloinformatics/nuim ~~~ ll
[2011-11-23 15:36:23] ~~~ /Users/jeet/Documents/Projects/Phyloinformatics/nuim ~~~ git status
[2011-11-23 15:36:33] ~~~ /Users/jeet/Documents/Projects/Phyloinformatics/nuim ~~~ jd pytb
[2011-11-23 15:36:36] ~~~ /Users/jeet/Documents/Projects/Phyloinformatics/pytbeaglehon ~~~ git status
[2011-11-23 15:36:53] ~~~ /Users/jeet/Documents/Projects/Phyloinformatics/pytbeaglehon ~~~ git rm --cached config/*
[2011-11-23 15:37:00] ~~~ /Users/jeet/Documents/Projects/Phyloinformatics/pytbeaglehon ~~~ git pull
[2011-11-23 15:37:11] ~~~ /Users/jeet/Documents/Projects/Phyloinformatics/pytbeaglehon ~~~ e .gitignore
[2011-11-23 15:37:28] ~~~ /Users/jeet/Documents/Projects/Phyloinformatics/pytbeaglehon ~~~ git status
[2011-11-23 15:37:35] ~~~ /Users/jeet/Documents/Projects/Phyloinformatics/pytbeaglehon ~~~ e .gitignore
[2011-11-23 15:37:44] ~~~ /Users/jeet/Documents/Projects/Phyloinformatics/pytbeaglehon ~~~ git status
[2011-11-23 15:38:10] ~~~ /Users/jeet/Documents/Projects/Phyloinformatics/pytbeaglehon ~~~ git commit -a -m "stuff"
[2011-11-23 15:38:12] ~~~ /Users/jeet/Documents/Projects/Phyloinformatics/pytbeaglehon ~~~ git pushall
[2011-11-23 15:50:38] ~~~ /Users/jeet/Documents/Projects/Phyloinformatics/pytbeaglehon ~~~ ll build_c/
[2011-11-23 15:53:16] ~~~ /Users/jeet/Documents/Projects/Phyloinformatics/pytbeaglehon ~~~ cd
[2011-11-23 15:53:18] ~~~ /Users/jeet ~~~ ls -l
[2011-11-23 16:00:12] ~~~ /Users/jeet ~~~ cd Documents/Projects/Phyloinformatics/DendroPy/dendropy
[2011-11-23 16:00:15] ~~~ /Users/jeet/Documents/Projects/Phyloinformatics/DendroPy/dendropy ~~~ ls -l
[2011-11-23 16:00:22] ~~~ /Users/jeet/Documents/Projects/Phyloinformatics/DendroPy/dendropy ~~~ cd dendropy/
[2011-11-23 16:00:24] ~~~ /Users/jeet/Documents/Projects/Phyloinformatics/DendroPy/dendropy/dendropy ~~~ vim *.py
$ histdirs
/Users/jeet
/Users/jeet/Documents/Projects/Phyloinformatics/nuim
/Users/jeet/Documents/Projects/Phyloinformatics/pytbeaglehon
/Users/jeet
/Users/jeet/Documents/Projects/Phyloinformatics/DendroPy/dendropy
/Users/jeet/Documents/Projects/Phyloinformatics/DendroPy/dendropy/dendropy
Further Reading

User comments:



I tried added what you



I tried added what you suggested above and it does not seem to log to the default log file. Doesn't seem like anything is even logging. Even tried adding the location of the logfile and still nothing.
export PROMPT_COMMAND='_loghistory -e -h -y -t'


minor modification required



#need to allow spaces before the nubmers in bash history
histleader=`expr "$histentry" : ' *\([0-9]* \[[0-9]*-[0-9]*-[0-9]* [0-9]*:[0-9]*:[0-9]*\]\)'`
histentrycmd=${histentry# *[0-9]* \[[0-9\-\: ]*\] }

Thanks for this nice article!