Oct 13 2008

Mover todos los archivos encontrados a un directorio en la consola de Linux {

Tag: Bash, Mini Tips

Hoy alguien me preguntaba como mover todos los archivos encontrados en uno o más directorios usando el comando find y tenía una idea de como hacerlo, pero no tenía una máquina con Linux para probarla, en realidad es algo muy simple, en este caso moveremos todas las fotos encontradas en /home/nuevosprogramadores y todos sus subdirectorios a una nueva ubicación en /home/nuevosprogramadores/fotos y lo haremos con una sola línea.

$ mv `find /home/nuevosprogramadores -iname *.jpg ` /home/nuevosprogramadores/fotos

Ahora vamos a identificar las partes de ésta línea, primero el comando mv que se encarga de mover ficheros:

$ mv origen destino


ahora el comando find, tal cual lo usamos:

$ find directorio-origen -iname nombre-archivo


Lo que hicimos fue concatenar ambos comandos, utilizando la salida del comando find como entrada del comando mv, para lo cual encerramos al comando find con las comillas simples: “ resumiendo, nuestro comando sería:

$ mv `find directorio-origen -iname nombre-archivo` destino

Una aclaración más, el parámetro iname se utiliza para buscar por nombre ignorando mayúsculas y minúsculas.

}


Oct 03 2008

Head First Design Patterns - Aprendiendo Patrones de Diseño {

Tag: Libros, Patrones

Me acaba de llegar el libro Head First Design Patterns, el segundo de la serie Head First de O’Reilly que tengo en mi poder, (el primero es Head First C#).

Vi este libro hace un tiempo y lo empecé a leer, después de leer el patrón estrategia, decidí que tenía que comprar este libro, por lo que de ahora en adelante postearé los conocimientos que vaya obteniendo acerca de Patrones de Diseño.

El libro trae ejemplos en Java, pero yo voy a intentar crear mis propios ejemplos y en más de un lenguaje!

Head First Design Patterns - O\'Reilly

}


Sep 10 2008

Aprendamos a usar Expresiones Regulares (parte 1) {

Tag: RegEx

Una expresión regular es un conjunto de caracteres y símbolos que definen una cadena según un patrón y no por sus elementos; por ejemplo, si queremos representar una cadena de caracteres que sólo puede estar formada por las letras a, b, c y los números del 1 al 3, utilizaremos el siguiente patrón: ^([a,b,c,1,2,3]+)$.

Ahora veamos los signos básicos en las expresiones regulares y su significado:

^ Inicio de la cadena
$ Fin de la cadena
[] Cualquier caracter del conjunto, por ejemplo [xyz] representa el conjunto formado por las letras x,y,z y encontrará cualquiera de esos caracteres.
[^] Cualquier caracter no incluido en el conjunto, por ejemplo[^xyz] representa cualquier caracter no incluido en el conjunto formado por las letras x,y,z
? Cero o una ocurrencia de lo que precede al símbolo, por ejemplo para encontrar cero o una ocurrencia de www. utilizaremos el patrón (www\.)?
+ El caracter que le precede debe aparecer al menos una vez, por ejemplo Google, Gooogle, Gooooooogle se representa con la siguiente expresión regular: Goo+gle
* El caracter que le precede debe aparecer cero, una o más veces, utilizando el ejemplo anterior, Gooo*gle representa Google, Goooogle, Goooooogle.
{x} x ocurrencias del caracter que lo precede, por ejemplo www. podría ser representado con el patrón w{3}\.
{x,z} Entre x y z ocurrencias del caracter que lo precede, con el ejemplo de Google, si quisiéramos que hubieran mínimo 2 letras o y máximo 5, utilizaríamos el patrón Go{2,5}gle
{x,} x o más ocurrencias de lo que lo precede, con el ejemplo de Google, para tener 2 o más letras o usaríamos la expresión regular Go{2,}gle

Esos son los signos básicos de las expresiones regulares, también tenemos la barra invertida, que se utiliza como caracter de escape en ciertos casos, cuando se desea incuir un caracter especial como ., * o ?, y para definir tipos de caracteres en otros, vemos algunos casos.

\. Un punto dentro del patrón, como definimos en uno de los ejemplos anteriores, la expresión w{3}\. define la cadena www.
\s Representa un espacio en blanco
\d Un dígito numérico
\w Un caracter alfanumérico
\n Un salto de línea
\r Representa el caracter de retorno de carro
\t Tabulador
\S Cualquier caracter excepto un espacio en blanco
\D Cualquier caracter excepto un dígito numérico
\W Representa cualquier caracter no alfanumérico

Esta es una introducción muy básica al uso de expresiones regulares, simplemente hemos visto algunos de los signos más básicos, en la próxima parte de este artículos veremos como crear algunas expresiones un poco más complejas. Mientras tanto pueden ir probando algunas expresiones en regexpal.com, un intérprete online de expresiones regulares.

}


Ago 18 2008

Ceibal Jam 2 - Programando para las XO del Plan Ceibal (OLPC) {

Tag: Varios

Laptop XO - Plan Ceibal - OLPC
En Uruguay el plan OLPC se llama Plan Ceibal, y cada tanto se organizan los llamados Ceibal JAM, lo cual es basicamente una reunión de programación donde hay charlas y se organizan actividades para crear programas para las XO.

Este segundo Ceibal Jam se llevará a cabo los días 30/08 y 06/09 en la sede de la Universidad Católica del Uruguay. Siguiendo este enlace podrán ver el cronograma preliminar de actividades.

Via: Varrojo@Linux

}


Ago 14 2008

Nace PyUy - Grupo de Usuarios Python del Uruguay {

Tag: Varios

Python logo
Marcelo Ramos escribe en su blog:

Acabo de crear el grupo PyUy en Google Groups para que podamos comenzar a darle forma al grupo y por supuesto hablar de todo lo relativo a Python.

Así que invito a todos los interesados a anotarse en la siguiente dirección:

http://groups.google.com/group/pyuy

Nos vemos en PyUy!

Ya estoy adentro para apoyar la iniciativa, además de que Python es uno de los lenguajes que quiero aprender desde hace bastante tiempo. Vamos a ver que resulta… se verá en los posts de programación en Python que aparezcan en el blog.

Además Fernando ya registró el canal IRC #pyuy en irc.freenode.net

}


Ago 14 2008

Como filtrar una lista de objetos con LINQ y ver las propiedades por Reflection (VB.Net) {

Tag: LINQ, VB.Net

LINQ es un proyecto de Microsoft que agrega a los lenguajes del .Net Framework la capacidad de utilizar consultas de sintáxis parecida a SQL. Inicialmente sólo se itegró a C# y VB.Net.

En el sitio de Microsoft hay una traducción de la página del proyecto LINQ donde se puede leer más al respecto.

En nuestro ejemplo utilizaremos LINQ To Objects, que es el término que se utiliza para definir la utilización de LINQ con cualquier colección que implemente las interfaces IEnumerable o IEnumerable(T).

En nuestro caso hemos definido una clase Objeto que tiene las propiedades ID : Integer, Tipo : String, Tamaño : Decimal y Habilitado : Boolean. Para utilizar LINQ hemos creado una colección del tipo List(Of Objeto) la cual cargamos con varias instancias de nuestra clase Objeto.

La idea es crear un filtro dinámico, para dar la posibilidad al usuario de seleccionar el valor para 2 propiedades y crear un filtro con OR o AND, o sea Propiedad1 = a OR/AND Propiedad2 = b.

Nuestra intención es poder reutilizar el código, entonces no podemos crear 2 ComboBox y cargar las propiedades a mano, por lo que recurriremos al namespace System.Reflection para extraer las propiedades de nuestra clase Objeto.

Según Microsoft: El espacio de nombres System.Reflection contiene clases e interfaces que proporcionan una vista administrada de los campos, los métodos y los tipos cargados, con la posibilidad de crear e invocar tipos dinámicamente.

Private Sub CargarPropiedades()
	Dim propiedades1 As New List(Of String)
	Dim propiedades2 As New List(Of String)
 
	' Recorremos todos los miembros de la clase
	For Each propiedad As System.Reflection.MemberInfo In System.Reflection.Assembly.GetExecutingAssembly.GetType("Objeto").GetMembers()
		' Filtramos para seleccionar solamente las propiedades
		If propiedad.MemberType = System.Reflection.MemberTypes.Property Then
			propiedades1.Add(propiedad.Name)
			propiedades2.Add(propiedad.Name)
		End If
	Next
 
	Me.cmbField1.DataSource = propiedades1 'Asignamos el DataSource a nuestros ComboBox
	Me.cmbField2.DataSource = propiedades2
End Sub

Con ese código tan simple ya tenemos 2 combos cargados con las propiedades de nuestra clase Objeto. En este caso ob tuvimos el tipo Objeto del mismo ensamblado, (Assembly), en el que estamos trabajando, pero pudimos haberlo buscado en otro Assembly.
Cabe aclarar que se utilizan 2 listas, una para cada combo porque si seteamos la misma lista como DataSource para los 2 ComboBox, al cambiar el valor seleccionado en uno, se cambia también en el otro.

Sólo resta armar nuestra sentencia LINQ para filtrar la coleeción de Objeto. Para ello tenemos que tomar: 1) la primera propiedad seleccionada por el usuario, 2) el valor que ingresó para esa propiedad, 3) la condición que seleccionó (AND/OR), 4) la segunda propiedad seleccionada, 5) el valor ingresado para la segunda propiedad.

Lo que haremos será armar la sentencia de la siguiente manera:

  • Seleccionar todos los objetos con PropiedadSeleccionada1 = ValorIngresado1
  • AND Si el usuario seleccionó ‘AND’ PropiedadSeleccionada2 = ValorIngresado2, sino True
  • OR Si el usuario seleccionó ‘OR’ PropiedadSeleccionada2 = ValorIngresado2 sino False.

Entonces la sentencia, en pseudo-código se vería de una se las siguientes maneras:

  • Seleccionar todos los objetos con Propiedad1 = Valor1 AND Propiedad2 = Valor2 OR False
  • Seleccionar todos los objetos con Propiedad1 = Valor2 AND True OR Propiedad2 = Valor2

De esa manera con una misma sentencia se cubren los 2 casos, veamos el código:

Private Sub btnSelect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSelect.Click
	If ValidarEntrada() Then ' Chequeaar que el usuario haya ingresado todos los valores necesarios
		Try
			' LINQ To Objects
			Dim resSelect = From obj In mObjetos _
				Select obj _
				Where obj.GetType().GetProperty(Me.cmbField1.SelectedItem.ToString()).GetValue(obj, Nothing) = Me.txtCond1.Text _
				And (IIf(cmbJoin.SelectedItem = "AND", obj.GetType().GetProperty(Me.cmbField2.SelectedItem.ToString()).GetValue(obj, Nothing) = Me.txtCond2.Text, True)) _
				Or (IIf(cmbJoin.SelectedItem = "OR", obj.GetType().GetProperty(Me.cmbField2.SelectedItem.ToString()).GetValue(obj, Nothing) = Me.txtCond2.Text, False))
 
			Me.lstSelect.Items.Clear() ' Limpiar la lista antes de mostrar el resultado de la consulta
			For Each item In resSelect
				Me.lstSelect.Items.Add(item)
			Next
		Catch ex As Exception
			If MessageBox.Show(String.Format("Error: {0}{1}Desea ver más información acerca de este error?", ex.Message.ToString(), Environment.NewLine), "Error", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk) = Windows.Forms.DialogResult.Yes Then
				MessageBox.Show(ex.ToString(), "Detalle del error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
			End If
		End Try
	End If
End Sub

Descargar el ejemplo de LINQ y reflection (42.24 KB)

}


Ago 08 2008

Category2Post en el directorio de plugins de Wordpress.org {

Tag: Category2Post

Así es, la semana pasada hice una solicitud para incluir Category2Post en el repositorio oficial de plugins de Wordpress y la solicitud fue aceptada, así que desde ahora el plugin figura en el directorio y tiene su repositorio SVN correspondiente.

Página en el directorio de plugins: http://wordpress.org/extend/plugins/category2post/

Repositorio SVN: http://svn.wp-plugins.org/category2post/

}


Jul 28 2008

Como reemplazar texto de un documento usando JavaScript y expresiones regulares {

Tag: JavaScript, RegEx

Seguramente todos han visto alguna vez una página que resalta las palabras clave nuestra búsqueda, y eso es lo que podemos lograr con estas 2 funciones de JavaScript y las siempre útiles expresiones regulares, por supuesto se puede hacer todo en una misma función, pero la idea es poder reusar el código.

La primera función se encargará de extraer el valor de un parámetro de nuestra URL usando expresiones regulares y sólo devolverá el valor. Se tuvo en cuenta que un parámetro de URL siempre estará precedido por uno de estos signos: ? ó & y que el valor del mismo se encontrará precedido del signo = y podrá ser sucedido por uno de los siguientes: & ó #.
A la hora de devolver el valor del parámetro seleccionado se utiliza una nueva expresión regular para reemplazar los signos + ó %20 por espacios en blanco, y en caso de que no se encuentre el parámetro devuelve un string vacío.

function leerParametros() {
	var parametro = 's'; //nombre del parámetro con las palabras de la búsqueda
	var regex = new RegExp('(\\?|&)('+ parametro + '=)([^&#]*)', 'i'); //regex para extraer el valor del parámetro
	var resultado = regex.exec(window.location.href); //ejecuta la regex sobre nuestra URL actual
 
	if(resultado != null) {
		replaceRegex = new RegExp('\\+|%20', 'g'); //regex para reemplazar signos por espacios
		return resultado[3].replace(replaceRegex, ' '); // devuelve la 3 coincidencia de la regex con el reemplazo para los espacios
	} else {
		return ""; //si la regex no encuentra el parámetro se devuelve un string vacío
	}
}

Luego utilizamos la función que realmente va a resaltar nuestras palabras clave, lo que haremos será obtener el valor del parámetro con la función anterior y mediante una expresión regular rodearemos cada instancia del texto con un tag <span> que tendrá un atributo style para darle la apariencia mediante css.

En esta expresión regular utilizamos paréntesis para poder capturar la coincidencia de texto como $1, ya que sino la estaríamos reemplazando por el texto buscado y es muy posible que no se respete la capitalización del texto original.

function resaltar() {
	var textoOriginal = leerParametros(); //obtiene el valor del parámetro
	var textoNuevo = "<span style=\"background-color: #ff0; font-weight: bold;\">$1</span>"; //define el texto a insertar por cada coincidencia de la regex
	var regex = new RegExp('('+textoOriginal+')', 'ig'); regex con modificadores ig, o sea no sensible a mayúsculas y minúsculas (i) y reemplazar todas las existencias (g)
	document.body.innerHTML = document.body.innerHTML.replace(regex, textoNuevo); //reemplazo sobre el html del body
}

Por último sólo resta hacer el llamado en el documento de destino, para lo cual lo ideal sería asignar la función resaltar() al evento onload del documento, pero eso no me funcionó, por lo que lo inserté al final del mismo:

		<script type="text/javascript">
				resaltar();
		</script>
	</body>
</html>

Sigue este enlace para ver el ejemplo funcionando.

}


Jul 28 2008

Como hacer un plugin para Wordpress {

Tag: PHP, Wordpress

Luego de escribir mi primer plugin, voy a explicar a grandes rasgos lo que se necesita para escribir un plugin, éste está compuesto de 2 archivos, uno con la funcionalidad del plugin y otro con la página de opciones para el panel de administración de wordpress.

Lo primero que haremos será escribir el encabezado para el plugin, ésto es lo que permitirá que Wordpress reconozca el plugin.

/* 
Plugin Name: Category 2 Post 
Plugin URI: http://nuevosprogramadores.com/category2post/ 
Description: Allows to include posts from one selected category 2 your post or page body. 
Version: 0.1 Author: Pablo Rodríguez Author URI: http://nuevosprogramadores.com 
*/ 
/*  Copyright 2008  Pablo Rodríguez  (email : prodriguez@nuevosprogramadores.com)      
This program is free software; you can redistribute it and/or modify     
it under the terms of the GNU General Public License as published by     
the Free Software Foundation; either version 2 of the License, or     
(at your option) any later version.      
This program is distributed in the hope that it will be useful,     
but WITHOUT ANY WARRANTY; without even the implied warranty of     
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     
GNU General Public License for more details.      
 
You should have received a copy of the GNU General Public License     
along with this program; if not, write to the Free Software     
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/

Como se puede apreciar, el encabezado está compuesto de 2 comentarios, sólo el primero es obligatorio, el segundo especifica que el plugin es publicado bajo licencia GPL.

Luego escribiremos la funcionalidad del plugin, en nuestro caso es una función que recorre los posts de una determinada categoría, arma un html con el contenido y por último reemplaza el comentario <!--category2post--> por el html con los posts que encontró anteriormente.

function category2post($c2p_content) { 
	$c2p_IDCategory = stripslashes(get_option('c2p_IDCategory')); 
	$c2p_NumberOfPosts = stripslashes(get_option('c2p_NumberOfPosts')); 
	$c2p_ShowAllContent = stripslashes(get_option('c2p_ShowAllContent')); 
	$c2p_result = ""; $c2p_posts = array(); 
 
	switch($c2p_NumberOfPosts) { 
		case 0: 
			c2p_posts = get_posts("category=$c2p_IDCategory"); 
			break; 
		default: 
			$c2p_posts = get_posts("numberposts=$c2p_NumberOfPosts&amp;category=$c2p_IDCategory"); 
			break; 
		} 
		if(sizeof($c2p_posts)) { 
			foreach($c2p_posts as $c2p_post) { 
			$c2p_result .= "<h3><a href="\">guid."\" id=\"".$c2p_post-&gt;ID."\"&gt;".$c2p_post-&gt;post_title."</a></h3>\n";
			if($c2p_ShowAllContent == '0') { 
				$c2p_result .= $c2p_post-&gt;post_excerpt."\n"; 
			} else { 
				$c2p_result .= $c2p_post-&gt;post_content."\n"; 
			} 
		} 
	} 
	return preg_replace('<!-- category2post -->|', $c2p_result, $c2p_content); 
}

Es muy importante buscar que los nombres de las funciones para no tener problemas con otros plugins y si las hubiese, hay que aplicar el mismo criterio con las variables. En mi caso utilicé el mismo prefijo para todo.

Como este plugin requiere de configuración, escribiremos también una función que agregue la página al panel de Wordpress.

function c2p_add_option_page() { 
	add_options_page('Opciones', 'Category2Post', 'manage_options', 'category2post/options-c2p.php'); 
}

Y por último haremos que todo esto funcione:

add_action('admin_head', 'c2p_add_option_page'); add_filter('the_content', 'category2post');

La primera línea asigna nuestra función c2p_add_option_page a la acción admin_head de Wordpress, mientras que la segunda indica que nuestra función category2post se debe ejecutar con el filtro the_content.

Por suerte Wordpress cuenta con una buena Referencia de Funciones, que nos sirve como guía para nuestras creaciones, además contamos con otros plugins que podemos utilizar como referencia para ver el código.

Hasta aquí las funciones que utilizamos son: get_option que nos permite obtener el valor de una opción desde la base de datos, get_posts para obtener los posts que cumplan con cierto criterio, en nuestro caso buscamos los que pertenezcan a una categoría y de ser necesario, que sólo devuelva x cantidad de posts, add_options_page para agregar nuestra página de opciones al panel de administración de Wordpress y por último add_action y add_filter.

}


Jul 26 2008

Plugin para Wordpress - Category2Post - v0.1 {

Después de mucho tiempo diciendo “algún día voy a hacer un plugin para Wordpress”, finalmente llegó el día, desde hoy se encuentra funcionando en Nuevos Programadores el plugin Category2Post que se encarga de recopilar las entradas publicadas bajo la categoría Mini Tips y mostrarlos en la página del mismo nombre.

El plugin está totalmente escrito en php y utiliza funciones de la muy documentada API de Wordpress para seleccionar los posts y mostrarlos. Si hay algún curioso que desee ver como funcionan los plugins de Wordpress, éste es bastante simple, lo suficiente como para entender la lógica para escribir un plugin e incluir una página para la configuración de opciones.

En un próximo post voy a explicar lo básico de la experiencia que fue escribir mi primer plugin para wordpress, mientras tanto si alguien lo prueba y encuentra algún bug o se le ocurre que se podría agregar una nueva funcionalidad, puede dejar un comentario o comunicarse conmigo a través del formulario de contacto del blog.

Descargar Category2Post

}


Página 1 de 11