<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 <title>BatU's Stack</title>
 <updated>2010-08-29T10:41:25+02:00</updated>
 <id>http://blog.inbatu.com/</id>
 <author>
   <name>Alvaro Bautista</name>
   <email>alvarobp@gmail.com</email>
 </author>
 
 
 <entry>
   <title>Isolating gem sets under Passenger with RVM</title>
   <link href="http://blog.inbatu.com/2010/05/29/isolated-gem-sets-under-passenger/"/>
   <updated>2010-05-29T00:00:00+02:00</updated>
   <id>http://blog.inbatu.com//2010/05/29/isolated-gem-sets-under-passenger</id>
   <content type="html">&lt;p&gt;For those who are thinking about deploying more than one ruby application on the same machine, and find it tricky to deal with different gem versions, here it is a short guide to having distinct gem paths for each project. I believe it suits small applications running under low load.&lt;/p&gt;

&lt;p&gt;I started from a clean Debian installation, however I will assume here that apache2 is already installed and ruby is still not.&lt;/p&gt;

&lt;h3&gt;Installing RVM&lt;/h3&gt;

&lt;p&gt;As &lt;a href=&quot;http://rvm.beginrescueend.com/rvm/install&quot;&gt;RVM documentation&lt;/a&gt; says, run:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;bash &amp;lt; &amp;lt;( curl http://rvm.beginrescueend.com/releases/rvm-install-head )
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;then follow the instructions to add rvm to your path.&lt;/p&gt;

&lt;h3&gt;Installing Ruby&lt;/h3&gt;

&lt;p&gt;Once RVM is installed, running &lt;code&gt;rvm notes&lt;/code&gt; will tell you what is required in order to install ruby versions. As I wanted to install the MRI interpreter (at first) I did install the following packages:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;aptitude install curl bison build-essential zlib1g zlib1g-dev libssl-dev libreadline5-dev libreadline6-dev libxml2-dev git-core subversion autoconf
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we are ready to compile our first ruby interpreter, I chose to install ruby 1.8.7&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;rvm install 1.8.7-head
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I like to run my applications using the Ruby Enterprise Edition interpreter, therefore I installed it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;rvm install ree
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I also set it as the default interpreter:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;rvm ree --default --passenger
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You may be wondering what we need the MRI interpreter for, well, I basically installed it because the REE installation script is written in Ruby.&lt;/p&gt;

&lt;h3&gt;Installing Passenger&lt;/h3&gt;

&lt;p&gt;In a nutshell:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gem install passenger
rvmsudo passenger-install-apache2-module
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Edit your &lt;code&gt;/etc/apache2/apache2.conf&lt;/code&gt; (or whatever file inside which you load the passenger module) and set:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;PassengerRuby /home/user/.rvm/bin/passenger_ruby
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Configuring an application&lt;/h3&gt;

&lt;p&gt;First of all, we need to create a gemset within which the application required gems will be installed:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;rvm gemset create wadusappset
rvm gemset use wadusappset
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we would do whatever it takes to have the needed gems properly installed (eg &lt;code&gt;rake gems:install&lt;/code&gt; or &lt;code&gt;bundle install&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Finally, we are going to tell Passenger where to find the gems. To find that place run:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;rvm ree@wadusappset; rvm gemdir
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And apply this formula:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;GEM_HOME=`rvm ree@wadusappset; rvm gemdir`
GEM_PATH=$GEM_HOME:$GEM_PATH
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, those environment values are set through the apache &lt;code&gt;mod_env&lt;/code&gt; module:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;VirtualHost *:80&amp;gt;
  ServerName www.wadusapp.com

  DocumentRoot /var/www/wadusapp/current/public

  SetEnv GEM_HOME /home/user/.rvm/gems/ree-1.8.7-2010.01@wadusappset
  SetEnv GEM_PATH /home/user/.rvm/gems/ree-1.8.7-2010.01@wadusappset:/home/user/.rvm/gems/ree-1.8.7-2010.01:/home/user/.rvm/gems/ree-1.8.7-2010.01@global
&amp;lt;/VirtualHost&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I did not find a better way of setting the variables so I went with copy &amp;amp; paste.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Fix a not too risky mess</title>
   <link href="http://blog.inbatu.com/2010/01/09/fix-a-not-too-risky-mess/"/>
   <updated>2010-01-09T00:00:00+01:00</updated>
   <id>http://blog.inbatu.com//2010/01/09/fix-a-not-too-risky-mess</id>
   <content type="html">&lt;p&gt;First of all, what I describe in this post was done in a concrete non critical situation. This worked fine for me but you should be careful.&lt;/p&gt;

&lt;p&gt;What I needed to fix was just a typo and I didn't want to add another commit to my repository just to change one character, so I looked for a &lt;a href=&quot;http://blog.jacius.info/2008/6/22/git-tip-fix-a-mistake-in-a-previous-commit/&quot;&gt;possible solution&lt;/a&gt; and I used a reduced version consisting of the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Edit the files and make the correction. That is in case you want to fix your last commit. If you have more recent commits you will have to previously use &lt;code&gt;git rebase&lt;/code&gt; as explained in the post linked earlier.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;git commit --amend&lt;/code&gt; and save the file. At this point the commit is fixed up.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once my local repository was as I wanted it to be I found that I could not push to the public repository. Then was when I reached the risky part. I did what is not recommended in &lt;a href=&quot;http://stackoverflow.com/questions/253055/how-do-i-push-amended-commit-to-the-remote-git-repo/253726#253726&quot;&gt;this comment&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git push origin +master:master
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note: I guess this command is just a shortcut for &lt;code&gt;git push -f origin master&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</content>
 </entry>
 
 <entry>
   <title>Trivial friendly URL routing for Ruby on Rails</title>
   <link href="http://blog.inbatu.com/2009/08/28/trivial-friendly-url-system-for-ruby-on-rails/"/>
   <updated>2009-08-28T00:00:00+02:00</updated>
   <id>http://blog.inbatu.com//2009/08/28/trivial-friendly-url-system-for-ruby-on-rails</id>
   <content type="html">&lt;p&gt;Back to the times I was programming in PHP (it hasn't been that long but it feels like an eternity has passed), I worked in a company own made CMS. One of my biggest headaches was tuning and reimplementing the friendly URL generator.&lt;/p&gt;

&lt;p&gt;Having the need to implement friendly URLs for a little and very specific CMS using Rails I found that it was a trivial matter. So I basically came up with a model acting as a tree (let's call it Page), a route and a class method.&lt;/p&gt;

&lt;p&gt;First thing I did was creating a model Page with the fields I needed plus, a &lt;code&gt;slug&lt;/code&gt; string field, plus a &lt;code&gt;parent_id&lt;/code&gt; integer field. I installed the &lt;code&gt;acts_as_tree&lt;/code&gt; plugin and made my model use it.&lt;/p&gt;

&lt;p&gt;Then I set up a route:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;ruby&quot;&gt;
   map.connect '*slugs', :controller =&gt; 'pages', :action =&gt; 'show'
&lt;/pre&gt;


&lt;p&gt;Next thing was creating a class method to process the slugs chain:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;ruby&quot;&gt;
class Page &amp;lt; ActiveRecord::Base
  def self.locate_by_slugs(slugs, parent_id=nil)
    page = if slugs.size == 1
      Page.find_by_slug_and_parent_id!(slugs.first, parent_id)
    else
      parent_page = Page.find_by_slug!(slugs.shift, :select =&amp;gt; &amp;#x27;id&amp;#x27;)
      Page.locate_by_slugs(slugs, parent_page.id)
    end
  end
end
&lt;/pre&gt;


&lt;p&gt;Lastly, I created the show action on PagesController:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;ruby&quot;&gt;
class PagesController &amp;lt; ApplicationController  
  def show
    @page = Page.locate_by_slugs(params[:slugs].dup)
  end
end
&lt;/pre&gt;


&lt;p&gt;Well, I haven't carried out a revolution, it's nothing fancy, it's been done a million times before, I don't even talk about the slug generation process. This post is just another evidence of how amazing the Ruby on Rails framework is.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Testear ActiveRecord sin Rails</title>
   <link href="http://blog.inbatu.com/2009/03/19/testear-activerecord-sin-rails/"/>
   <updated>2009-03-19T00:00:00+01:00</updated>
   <id>http://blog.inbatu.com//2009/03/19/testear-activerecord-sin-rails</id>
   <content type="html">&lt;p&gt;Hace unos días andaba algo ocioso y me puse a probar como escribir un plugin/gema para rails. Este plugin resultó en una muy sencilla extensión para modelos ActiveRecord, que simplemente mantiene una copia de los valores inversos de created_at y updated_at como enteros, con lo que podemos hacer consultas ordenando por estos campos de forma descendente.&lt;/p&gt;

&lt;p&gt;Nada sofisticado. Pero a la hora de escribir los tests me encontré con que quería hacer esos tests independientes de Rails, pues solo afectan a ActiveRecord, y sin necesidad de ningún tipo de configuración. Para ello utilicé varios modelos de ActiveRecord y como base de datos sqlite.&lt;/p&gt;

&lt;p&gt;Primero definimos un schema con las tablas de nuestros modelos:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;ruby&quot;&gt;
ActiveRecord::Schema.define(:version =&amp;gt; 0) do
  create_table :with_created_models, :force =&amp;gt; true do |t|
    t.column :something, :string    
    t.column :created_at, :datetime
    t.column :updated_at, :datetime    
    t.column :created_at_inverse, :integer
  end
end
&lt;/pre&gt;


&lt;p&gt;Una vez definido el schema, establecemos nuestro entorno de test, por ejemplo en &lt;code&gt;test_helper.rb&lt;/code&gt;:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;ruby&quot;&gt;
require &amp;#x27;test/unit&amp;#x27;

require &amp;#x27;rubygems&amp;#x27;
require &amp;#x27;active_record&amp;#x27;
require &amp;#x27;shoulda&amp;#x27;

require File.dirname(__FILE__) + &amp;#x27;/../lib/inverse_sortable&amp;#x27;

ActiveRecord::Base.establish_connection({
    :adapter =&amp;gt; &amp;quot;sqlite3&amp;quot;,
    :dbfile =&amp;gt; &amp;quot;test/test.db&amp;quot;
})

class WithCreatedModel &amp;lt; ActiveRecord::Base
end

load(File.dirname(__FILE__) + &amp;quot;/schema.rb&amp;quot;)
&lt;/pre&gt;


&lt;p&gt;En este fichero, le decimos a ActiveRecord que utilice como base de datos un fichero de sqlite (test.db), definimos un modelo correspondiente a la tabla en nuestro schema.rb (declarando una clase que hereda de ActiveRecord::Base y con el nombre de la tabla en singular) y por último cargamos dicho schema.&lt;/p&gt;

&lt;p&gt;Con esto ya disponemos de un modelo que podemos usar para testear el comportamiento de la extensión inverse_sortable, por ejemplo en &lt;code&gt;inverse_sortable_test.rb&lt;/code&gt;:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;ruby&quot;&gt;
require File.join(File.dirname(__FILE__), &amp;#x27;test_helper&amp;#x27;)

class WithCreatedModel
  acts_as_inverse_sortable
end

class InverseSortableTest &amp;lt; Test::Unit::TestCase
  context &amp;quot;A model that acts as an inverse sortable&amp;quot; do    
    should &amp;quot;have the inverse of its created_at time when is created if created_at_inverse is available&amp;quot; do
      with_created = WithCreatedModel.create(:something =&amp;gt; &amp;quot;Testing&amp;quot;)
      
      assert_not_nil with_created.created_at_inverse
      assert_equal -with_created.created_at.to_i, with_created.created_at_inverse
    end
    # ...
end
&lt;/pre&gt;


&lt;p&gt;Para quién pueda interesar, tanto el plugin como los tests están en &lt;a href=&quot;http://github.com/alvarobp/inverse_sortable&quot;&gt;http://github.com/alvarobp/inverse_sortable&lt;/a&gt;, donde además hay un pequeño benchmark, sobre lo cual quizá comente en otro post.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Crear un repositorio Git remoto</title>
   <link href="http://blog.inbatu.com/2009/01/24/crear-un-repositorio-git-remoto/"/>
   <updated>2009-01-24T00:00:00+01:00</updated>
   <id>http://blog.inbatu.com//2009/01/24/crear-un-repositorio-git-remoto</id>
   <content type="html">&lt;p&gt;A modo de receta, he aquí la secuencia de comandos necesaria para la creación de un repositorio Git remoto, a través de SSH.&lt;/p&gt;

&lt;p&gt;El primer paso es crear el repositorio en sí, para ello o bien creamos un directorio vacío donde empezar a meter el código de nuestra aplicación, o bien vamos al directorio donde tenemos ya nuestro código:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;bash&quot;&gt;
cd appname
git init
&lt;/pre&gt;


&lt;p&gt;Acto seguido añadimos el contenido al repositorio y comiteamos el cambio:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;bash&quot;&gt;
git add .
git commit -m &quot;inicilizacion del repositorio&quot;
&lt;/pre&gt;


&lt;p&gt;El último paso consiste en crear una copia del repositorio la cual subiremos al servidor (o moveremos dentro de la misma máquina, según proceda) y que contiene solamente la información interna de git y no una copia de trabajo:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;bash&quot;&gt;
git clone --bare appname appname.git
scp -r appname.git ssh://user@yourserver/path/to/git/
&lt;/pre&gt;


&lt;p&gt;Por último, para comenzar a trabajar sobre el repositorio tenemos dos opciones, clonarlo desde su ubicación remota:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;bash&quot;&gt;
cd algunsitio
git clone ssh://user@yourserver/path/to/git/appname.git
&lt;/pre&gt;


&lt;p&gt;lo que nos creará un directorio &lt;code&gt;appname&lt;/code&gt; en &lt;code&gt;algunsitio&lt;/code&gt; con la copia de trabajo, o bien añadimos el repositorio remoto a la copia actual (creada en el primer paso):&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;bash&quot;&gt;
git remote add origin ssh://user@yourserver/path/to/git/appname.git
&lt;/pre&gt;

</content>
 </entry>
 
 <entry>
   <title>Codeigniter - Framework PHP</title>
   <link href="http://blog.inbatu.com/2007/08/08/codeigniter-framework-php/"/>
   <updated>2007-08-08T00:00:00+02:00</updated>
   <id>http://blog.inbatu.com//2007/08/08/codeigniter-framework-php</id>
   <content type="html">&lt;p&gt;He estado probando estos días el framework PHP (a la rails) &lt;a href=&quot;http://www.codeigniter.com&quot;&gt;CodeIgniter&lt;/a&gt;. De momento la impresión es buena. En mi línea, pongo un ejemplo.&lt;/p&gt;

&lt;p&gt;Modificando un par de ficheros de configuración o tres (un par de líneas en cada uno) y creando los siguientes dos ficheros he obtenido una sencilla aplicación que muestra las entradas de mi blog de wordpress.&lt;/p&gt;

&lt;p&gt;El fichero del controlador (&lt;tt&gt;controllers/blog.php&lt;/tt&gt;):&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;

class Blog extends Controller {
  function Blog() {
    parent::Controller();

    $this-&gt;load-&gt;scaffolding('bb_posts');
  }

  function index() {
    $data['title'] = &quot;BatU's Stack&quot;;
    $data['heading'] = &quot;piling up experiences...&quot;;
    $this-&gt;db-&gt;orderby(&quot;post_date&quot;, &quot;desc&quot;);
    $data['query'] = $this-&gt;db-&gt;get('bb_posts');

    $this-&gt;load-&gt;view('blog_view', $data);
  }
}
&lt;/pre&gt;


&lt;p&gt;El fichero de la vista correspondiente (&lt;tt&gt;views/blog_view.php&lt;/tt&gt;):&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;html&quot;&gt;
&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.0 Transitional//EN&amp;quot;
  &amp;quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&amp;quot;&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;meta http-equiv=&amp;quot;Content-type&amp;quot; content=&amp;quot;text/html;
    charset=utf-8&amp;quot;&amp;gt;
  &amp;lt;title&amp;gt;Blog&amp;lt;/title&amp;gt;

  &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/bblog/css/style.css&amp;quot; 
    type=&amp;quot;text/css&amp;quot; media=&amp;quot;screen&amp;quot;
    title=&amp;quot;no title&amp;quot; charset=&amp;quot;utf-8&amp;quot;&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;div id=&amp;quot;box&amp;quot;&amp;gt;
    &amp;lt;div id=&amp;quot;header&amp;quot;&amp;gt;
      &amp;lt;h1&amp;gt;&amp;lt;?=$title?&amp;gt;&amp;lt;/h1&amp;gt;
      &amp;lt;h2&amp;gt;&amp;lt;?=$heading?&amp;gt;&amp;lt;/h2&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div id=&amp;quot;posts&amp;quot;&amp;gt;
      &amp;lt;?php foreach($query-&amp;gt;result() as $post): ?&amp;gt;
        &amp;lt;div class=&amp;quot;post&amp;quot;&amp;gt;
          &amp;lt;h3&amp;gt;&amp;lt;?=$post-&amp;gt;post_title?&amp;gt;&amp;lt;/h3&amp;gt;

          &amp;lt;div class=&amp;quot;post_content&amp;quot;&amp;gt;
            &amp;lt;?=$post-&amp;gt;post_content?&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;?php endforeach; ?&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;




&lt;p class=&quot;strike&quot;&gt;Dejo aquí la URL del ejemplo: &lt;a href=&quot;http://testing.inbatu.com/bblog/index.php/blog&quot;&gt;http://testing.inbatu.com/bblog/index.php/blog&lt;/a&gt;&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>imaplib - Ejemplo muy básico</title>
   <link href="http://blog.inbatu.com/2007/07/23/imaplib-ejemplo-muy-basico/"/>
   <updated>2007-07-23T00:00:00+02:00</updated>
   <id>http://blog.inbatu.com//2007/07/23/imaplib-ejemplo-muy-basico</id>
   <content type="html">&lt;p&gt;Estoy de vuelta con python, que desde antes de exámenes no había tocado nada. Y como estoy llegando al final del Learning Python, donde he visto que existe la librería poplib, me ha dado por probar &lt;code&gt;imaplib&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Dejo aquí un sencillo ejemplo que muestra todos los mensajes de un buzón IMAP.&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;python&quot;&gt;
#!/usr/bin/python

import imaplib, getpass

if __name__ == '__main__':
    
    host = raw_input('Host: ')
    user = raw_input('User: ')
    passw = getpass.getpass('Password: ')
        
    mail = imaplib.IMAP4(host)
    mail.login(user,passw)
    mail.select()
    
    typ, data = mail.search(None, 'ALL')
    for num in data[0].split():
        typ, data = mail.fetch(num, '(RFC822)')
        print '\\n----------------------------------\\n',
        print 'Message %s' % num,
        print '\\n----------------------------------\\n',
        print '\\n%s\\n' % data[0][1]
        raw_input('Next message...')
        
    mail.close()
    mail.logout()
&lt;/pre&gt;

</content>
 </entry>
 
 <entry>
   <title>Mordiendo la manzana</title>
   <link href="http://blog.inbatu.com/2007/06/23/mordiendo-la-manzana/"/>
   <updated>2007-06-23T00:00:00+02:00</updated>
   <id>http://blog.inbatu.com//2007/06/23/mordiendo-la-manzana</id>
   <content type="html">&lt;p&gt;Después de unos meses sin escribir nada, señal de que tengo poco que contar y que he estado bastante liado este último cuatrimestre, comunico que hace unos días (4) he adquirido un MacBook 13,3 (2.16GHz).&lt;/p&gt;

&lt;p&gt;La experiencia está siendo grata. Quizás demasiado pues de momento estoy tirando con MacOSX (ya me he flagelado por ello :P) que estoy de exámenes y no es plan de ponerme a trastear para meterle una Ubuntu.&lt;/p&gt;

&lt;p&gt;Sobre MacOSX, la verdad la impresión es bastante buena y lo sería aún más si no fuera por el &quot;insignificante detalle&quot; de que su escritorio es software propietario.&lt;/p&gt;

&lt;p&gt;Y poco más puedo decir que la mayoría de gente que pueda estar leyendo esto (osea nadie) no sepa sobre estos portátiles. Espero que este nuevo miembro de la familia se porte bien durante su estancia en Irlanda y que haga su papel en mi experiencia erasmus.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Argumentos con OptionParser</title>
   <link href="http://blog.inbatu.com/2007/03/05/argumentos-mediante-optparser/"/>
   <updated>2007-03-05T00:00:00+01:00</updated>
   <id>http://blog.inbatu.com//2007/03/05/argumentos-mediante-optparser</id>
   <content type="html">&lt;p&gt;En la versión 2.3 de Python se añadió el módulo &lt;a href=&quot;http://docs.python.org/lib/module-optparse.html&quot;&gt;optparse&lt;/a&gt; a la librería estándar, el cual nos sirve para parsear las opciones y argumentos que se pasan a nuestros programas, haciendo fácil y cómodo el lidiar con ellos.&lt;/p&gt;

&lt;p&gt;Pondré un ejemplo:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;python&quot;&gt;
from optparse import OptionParser

if __name__ == '__main__':
    usage = &quot;%prog [options] arg1 arg2&quot;

    parser = OptionParser(usage=usage, version=&quot;%prog 1.0&quot;)
    parser.add_option('-v','--verbose', action='store_true',
                      dest='verbose', help='shows detailed information')
    parser.add_option('-q','--quiet', action='store_false',
                      dest='verbose', help='hides detailed information')
    parser.add_option('-f','--filename', action='store',
                      dest='filename', help='name of the file to load')


    (options, args) = parser.parse_args()

    if options.verbose:
        print &quot;Extra info enabled&quot;
    else:
        print &quot;Extra info disabled&quot;
    if options.filename:
        print &quot;I'll open&quot;, options.filename, &quot;file.&quot;
    if args &gt; 0:
        print &quot;\nArguments:&quot;
        for x in args:
            print &quot;  &quot;,x
&lt;/pre&gt;


&lt;p&gt;Ahora veamos algunos resultados según los argumentos que pasemos (en negrita el comando ejecutado):&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;bash&quot;&gt;
&lt;b&gt;$ python option.py&lt;/b&gt;

Extra info disabled
&lt;/pre&gt;




&lt;pre name=&quot;code&quot; class=&quot;python&quot;&gt;
&lt;b&gt;$ python option.py -v&lt;/b&gt;

Extra info enabled
&lt;/pre&gt;




&lt;pre name=&quot;code&quot; class=&quot;python&quot;&gt;
&lt;b&gt;$ python option.py -h&lt;/b&gt;

usage: option.py [options] arg1 arg2

options:
  --version             show program's version number and exit
  -h, --help            show this help message and exit
  -v, --verbose         shows detailed information
  -q, --quiet           hides detailed information
  -f FILENAME, --filename=FILENAME
                        name of the file to load
&lt;/pre&gt;




&lt;pre name=&quot;code&quot; class=&quot;python&quot;&gt;
&lt;b&gt;$ python option.py -f fichero.txt &quot;First&quot; &quot;Second&quot; &quot;Last argument&quot;&lt;/b&gt;

Extra info disabled
I'll open fichero.txt file.

Arguments:
   First
   Second
   Last argument
&lt;/pre&gt;


&lt;p&gt;Fijaos que distingue las opciones de los argumentos, como se puede ver en el último ejemplo.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Nota:&lt;/em&gt; He escrito los ejemplos en inglés para no desencajar, porque las cadenas que imprime el módulo están en inglés, aunque estaría bien que pudiera hacerlo en otros idiomas.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Parsear HTML con BeautifulSoup</title>
   <link href="http://blog.inbatu.com/2007/02/28/parsear-html-con-beautifulsoup/"/>
   <updated>2007-02-28T00:00:00+01:00</updated>
   <id>http://blog.inbatu.com//2007/02/28/parsear-html-con-beautifulsoup</id>
   <content type="html">&lt;p&gt;Voy a poner un ejemplo de uso de &lt;a href=&quot;http://www.crummy.com/software/BeautifulSoup/&quot;&gt;BeautifulSoup&lt;/a&gt;, un módulo para Python con el que podemos parsear HTML.&lt;/p&gt;

&lt;p&gt;Lo primero que tenemos que hacer es descargar la librería desde &lt;a href=&quot;http://www.crummy.com/software/BeautifulSoup/download/BeautifulSoup.tar.gz&quot;&gt;aquí&lt;/a&gt;.
Una vez instalado vamos a ver un sencillo ejemplo:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;python&quot;&gt;
from BeautifulSoup import BeautifulSoup

html = &amp;#x27;&amp;#x27;&amp;#x27;&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Titulo de la pagina&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
  &amp;lt;div id=&amp;quot;cabecera&amp;quot;&amp;gt;&amp;lt;h1&amp;gt;Cabecera&amp;lt;/h1&amp;gt;&amp;lt;/div&amp;gt;
  &amp;lt;div id=&amp;quot;contenido&amp;quot;&amp;gt;
    Vamos a poner una lista.

    Lista:
    &amp;lt;ul id=&amp;quot;lista1&amp;quot;&amp;gt;
      &amp;lt;li&amp;gt;Elemento 1&amp;lt;/li&amp;gt;
      &amp;lt;li&amp;gt;Elemento 2&amp;lt;/li&amp;gt;
      &amp;lt;li&amp;gt;Elemento 3&amp;lt;/li&amp;gt;
      &amp;lt;li&amp;gt;Elemento 4&amp;lt;/li&amp;gt;
    &amp;lt;/ul&amp;gt;
    
  &amp;lt;/div&amp;gt;
  &amp;lt;/body&amp;gt;
  &amp;lt;/html&amp;gt;&amp;#x27;&amp;#x27;&amp;#x27;

soup = BeautifulSoup(html)

# Mostramos el titulo de la pagina
print soup.head.title.string

# Mostramos la cabecera
print soup.find(&amp;quot;div&amp;quot;,{&amp;quot;id&amp;quot;:&amp;quot;cabecera&amp;quot;}).contents

# Mostramos el contenido
contenido = soup.find(&amp;quot;div&amp;quot;,{&amp;quot;id&amp;quot;:&amp;quot;contenido&amp;quot;})
print contenido.contents

# Ahora mostramos todos los elementos de lista1
lista = contenido.find(&amp;quot;ul&amp;quot;,{&amp;quot;id&amp;quot;:&amp;quot;lista1&amp;quot;})
for x in lista:
    print x.string
&amp;lt;/pre&amp;gt;

Si en lugar de pasar una cadena con el c&amp;oacute;digo html quisieramos leer de una url lo podr&amp;iacute;amos hacer as&amp;iacute;:

&amp;lt;pre name=&amp;quot;code&amp;quot; class=&amp;quot;python&amp;quot;&amp;gt;
...
import urllib2

sock = urllib2.urlopen(&amp;quot;http://servidor/documento.html&amp;quot;)
soup = BeautifulSoup(sock.read())
...
&lt;/pre&gt;


&lt;p&gt;Esto es un ejemplo muy sencillo de lo que se puede hacer, para más detalles leer la &lt;a href=&quot;http://www.crummy.com/software/BeautifulSoup/documentation.html&quot;&gt;documentación&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Operador const de C++ (Resumen)</title>
   <link href="http://blog.inbatu.com/2007/01/27/operador-const-de-c-resumen/"/>
   <updated>2007-01-27T00:00:00+01:00</updated>
   <id>http://blog.inbatu.com//2007/01/27/operador-const-de-c-resumen</id>
   <content type="html">&lt;h3&gt;Variables constantes&lt;/h3&gt;


&lt;ul&gt;
&lt;li&gt;&lt;code&gt;const int entero;&lt;/code&gt;
Entero constante, una vez inicializada la variable entero no podrá ser cambiado su valor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;const int * pentero;   ó   int const * pentero;&lt;/code&gt;
Puntero a entero constante, el contenido del puntero pentero no se podrá cambiar.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;int * const pentero;&lt;/code&gt;
Puntero constante a entero, no se podrá cambiar el puntero.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Como regla general const afecta al elemento que está inmediatamente a su izquierda, si no hay nada al que está inmediatamente a su derecha.&lt;/p&gt;

&lt;h3&gt;Valores constantes de retorno de función&lt;/h3&gt;




&lt;pre name=&quot;code&quot; class=&quot;cpp&quot;&gt;
const char * Funcion()
{ return &quot;Un texto&quot;; }

Funcion()[1] = 'a'; // Error
&lt;/pre&gt;


&lt;p&gt;La variable devuelta no se puede modificar pues es constante.&lt;/p&gt;

&lt;h3&gt;Parámetros constantes&lt;/h3&gt;




&lt;pre name=&quot;code&quot; class=&quot;python&quot;&gt;
void mostrarPila(const Pila &amp;p);
&lt;/pre&gt;


&lt;p&gt;Como mostrarPila no debe modificar la pila pasamos el objeto pila a mostrar por referencia y constante. De esta manera no podremos modificar el objeto p, ni acceder a métodos de este que no se hayan declarado como const.&lt;/p&gt;

&lt;h3&gt;Métodos constantes&lt;/h3&gt;




&lt;pre name=&quot;code&quot; class=&quot;python&quot;&gt;
class Tipo {
...
  void imprime() const;
...
}
&lt;/pre&gt;


&lt;p&gt;Evita que el método imprime pueda modificar los miembros del objeto.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Naudo</title>
   <link href="http://blog.inbatu.com/2007/01/23/naudo/"/>
   <updated>2007-01-23T00:00:00+01:00</updated>
   <id>http://blog.inbatu.com//2007/01/23/naudo</id>
   <content type="html">&lt;p&gt;&lt;b&gt;Samba pa ti (Santana)&lt;/b&gt;&lt;/p&gt;

&lt;!-- &lt;object style=&quot;height: 344px; width: 425px&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://www.youtube.com/v/8FBbzL3G8Vw&quot;&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;&gt;&lt;embed src=&quot;http://www.youtube.com/v/8FBbzL3G8Vw&quot; type=&quot;application/x-shockwave-flash&quot; allowfullscreen=&quot;true&quot; allowScriptAccess=&quot;always&quot; width=&quot;425&quot; height=&quot;344&quot;&gt;&lt;/object&gt; --&gt;


&lt;p&gt;&lt;b&gt;Every little thing she does is magic (Police)&lt;/b&gt;&lt;/p&gt;

&lt;!-- &lt;object style=&quot;height: 344px; width: 425px&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://www.youtube.com/v/Sk46ugkD-Ww&quot;&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;&gt;&lt;embed src=&quot;http://www.youtube.com/v/Sk46ugkD-Ww&quot; type=&quot;application/x-shockwave-flash&quot; allowfullscreen=&quot;true&quot; allowScriptAccess=&quot;always&quot; width=&quot;425&quot; height=&quot;344&quot;&gt;&lt;/object&gt; --&gt;


&lt;p&gt;Impresionantes las versiones de este guitarrista. Les da un toque muy personal. En youtube hay &lt;a href=&quot;http://www.youtube.com/results?search_query=Naudo&quot;&gt;un buen puñado de videos&lt;/a&gt; de él.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Twitter Updater</title>
   <link href="http://blog.inbatu.com/2007/01/20/twitter-updater/"/>
   <updated>2007-01-20T00:00:00+01:00</updated>
   <id>http://blog.inbatu.com//2007/01/20/twitter-updater</id>
   <content type="html">&lt;p&gt;A raíz de ver &lt;a href=&quot;http://blog.n2kp3.com/articles/2007/01/17/de-basecamp-a-twitter&quot;&gt;el script que se hizo felipe&lt;/a&gt;, para twittear los todos del basecamp, me he hecho yo uno (más sencillo aún)  en Python para simplemente twittear desde consola. Así por ejemplo hago Alt+F2 en KDE o desde la consola escribo &lt;code&gt;twupdater &quot;Ya hemos acbado los examenes (ojala)&quot;&lt;/code&gt; y ya está.&lt;/p&gt;

&lt;p&gt;Pues eso, nada existencial, pero me ha dado para un ratillo de frikeo, y de paso he toquiteado http desde python.&lt;/p&gt;

&lt;p&gt;Aquí dejo el script:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/drawer/2007/01/twupdater_v02.tar.gz&quot;&gt;twupdater_v02.tar.gz&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Actualización:&lt;/b&gt; El script ahora pide usuario y contraseña si no se configuran.&lt;/p&gt;


&lt;p&gt;&lt;b&gt;Ultima actualizacion:&lt;/b&gt; Ahora además comprueba el usuario y contraseña antes de enviar el estado.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Reordenar PDFs</title>
   <link href="http://blog.inbatu.com/2007/01/17/reordenar-pdfs/"/>
   <updated>2007-01-17T00:00:00+01:00</updated>
   <id>http://blog.inbatu.com//2007/01/17/reordenar-pdfs</id>
   <content type="html">&lt;p&gt;Buscando como unir PDFs he encontrado &lt;a href=&quot;http://www.kriptopolis.org/node/2662&quot; target=&quot;_blank&quot;&gt;este post&lt;/a&gt; en kriptopolis, y he conocido la herramienta &lt;a href=&quot;http://www.accesspdf.com/index.php?topic=pdftk&quot; target=&quot;_blank&quot;&gt;PDFTK&lt;/a&gt; que nos permite hacer cosas como unir, encriptar, descomprimir pdfs y más.&lt;/p&gt;

&lt;p&gt;Pondré unos ejemplos:&lt;/p&gt;


&lt;ul&gt;&lt;li&gt;&lt;code&gt;pdftk 1.pdf 2.pdf 3.pdf cat output 123.pdf&lt;/code&gt;&lt;br /&gt;Une los tres ficheros (1.pdf, 2.pdf y 3.pdf) en uno solo (123.pdf).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pdftk A=1.pdf B=2.pdf cat A1-7 B1-5 A8 output combined.pdf&lt;/code&gt;&lt;br /&gt;Crea un nuevo pdf extrayendo páginas, en este caso el nuevo pdf se compondría de las paginas 1 a 7 de 1.pdf, luego 1 a 5 de 2.pdf y por último la 8 de 1.pdf&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pdftk doc.pdf output doc_enc.pdf owner_pw contra&lt;/code&gt;&lt;br /&gt;Encripta el PDF con todos los permisos deshabilitados excepto ver el fichero&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pdftk doc.pdf output doc_enc.pdf owner_pw contra user_pw contra2&lt;/code&gt;&lt;br /&gt;Igual que el anterior pero ahora pedirá password para abrirlo.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Existen más opciones que se pueden ver en la página del programa, para mí con los dos primeros ejemplos ya me es bastante útil.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Nuevo libro recibido</title>
   <link href="http://blog.inbatu.com/2007/01/03/nuevo-libro-recibido/"/>
   <updated>2007-01-03T00:00:00+01:00</updated>
   <id>http://blog.inbatu.com//2007/01/03/nuevo-libro-recibido</id>
   <content type="html">&lt;p&gt;Esta mañana estaba durmiendo como un lirón cuando han empezado a llamar al timbre, la verdad, un poco frenéticamente. Bastante mosqueado, pues me habían interrumpido el sueño me dirigo hacia el aparatito y cuando pregunto quien era: &quot;Cartero, traigo un libro para Alvaro...&quot; WOW. El Programming Python 3a Edición (Agosto 2006) que encargue el 13 de diciembre me ha llegado hoy. Menuda sorpesa pues lo esperaba para marzo, después de examenes.&lt;/p&gt;

&lt;p&gt;El libro ha llegado en bastante buen estado, aparte de un par de arañazos en las tapas todo perfecto (por si alguien no lo sabe, el libro es de segunda mano), por cierto es bastante tocho casi el doble que el Programming Perl.  Al final de todo se puede decir que me han alegrado el día, si si un libro me alegra el día.&lt;/p&gt;

&lt;p&gt;En fin que el libro ya está aparcado junto con los demás, y no creo que lo toque demasiado hasta después de exámenes, aunque claro como decía en un post anterior cuando menos toca es cuando más frikeo.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Primer post</title>
   <link href="http://blog.inbatu.com/2007/01/01/%25c2%25a1feliz-2007/"/>
   <updated>2007-01-01T00:00:00+01:00</updated>
   <id>http://blog.inbatu.com//2007/01/01/%c2%a1feliz-2007</id>
   <content type="html">&lt;p&gt;No creo que nadie esté leyendo esto en los mismos instantes de publicar esta entrada, estareis todos emborrachandoos y deseando poder escaquearos de casa para salir a esparramarla un poquillo. Bueno la verdad, no penseis que lo primero de todo que haré en el 2007 será sentarme a postear, esto está programado. En fin,
&lt;strong&gt;&lt;b&gt;Feliz año 2007&lt;/b&gt;&lt;/strong&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>De vacaciones navideñas</title>
   <link href="http://blog.inbatu.com/2006/12/28/de-vacaciones-navidenas/"/>
   <updated>2006-12-28T00:00:00+01:00</updated>
   <id>http://blog.inbatu.com//2006/12/28/de-vacaciones-navidenas</id>
   <content type="html">&lt;p&gt;Un año más, y si no el último casi, estoy en las vacaciones de navidad, si esa época en que te venden felicidad por todos los costados. Dejando aparte mi espíritu antinavideño (y anticristiano en general), lo importante es que no hay clases y que puedo dedicar mi tiempo en cosas útiles tales como estudiar, meterle más caña a Python, probar cosillas en el servidor, salir por ahí... Pero vaya contradicción ahora que tengo más tiempo es cuando menos hago, aún no me he sentado ni un sólo día a estudiar, Python desde de antes de nochebuena (creo) no he vuelto a leer ningún capítulo más del Learning Python, salir... si bueno algo salgo pero ya no como antes. La verdad es que siempre me pasa igual cuanto más agobiado estoy y más se supone que tengo que estudiar, en época de exámenes, es cuando más me paro a probar esto y lo otro.&lt;/p&gt;

&lt;p&gt;En fin que ya no se ni lo que escribo, lo que hay que hacer para rellenar el blog...&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Feliz falsedad a todos y próspero año nuevo.&lt;/em&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Mi primer programa</title>
   <link href="http://blog.inbatu.com/2006/12/09/mi-primer-programa/"/>
   <updated>2006-12-09T00:00:00+01:00</updated>
   <id>http://blog.inbatu.com//2006/12/09/mi-primer-programa</id>
   <content type="html">&lt;p&gt;En septiembre comencé a desarrollar una sencilla aplicación de gestión de almacén para el gabinete de estética de mi prima. En un principio pensé en hacerlo en Java, pues era el lenguaje que estudié el año pasado. Pero el desarrollo de interfaces gráficas para este lenguaje no me resultaba demasiado cómodo. Así que decidí hacerlo con C++ utilizando Qt, retomando así un lenguaje y una librería que se me habían quedado un poco pendientes.&lt;/p&gt;

&lt;p&gt;El programa en sí es bastante sencillo (de momento), estará lleno de bugs, mal diseñado... también hay que tener en cuenta que es lo primero más o menos serio que hago en el campo de la programación.&lt;/p&gt;

&lt;p&gt;Como ya he dicho utilizo Qt (4.2) no solo para las interfaces sino en general. Utilizo las estructuras de datos que vienen con la librería, las clases de acceso a bases de datos... SQLite fue mi elección ya que como no va a ser una base de datos de tamaño excesivo pensé que estaría bien, además para las copias de seguridad basta con copiar el fichero de la base de datos a un lugar seguro.&lt;/p&gt;

&lt;p&gt;En fin, que ya tengo digamos una primera versión utilizable del programa, aunque no funciona como me gustaría si que por lo menos &quot;funciona&quot;. La gestión de productos es un poco tediosa y tal. Pero bueno para empezar ya se puede manejar toda la información que creemos que es necesaria.&lt;/p&gt;

&lt;p&gt;El código del programa se puede obtener mediante subversion:&lt;/p&gt;

&lt;p&gt;Para la versión en desarrollo:&lt;/p&gt;

&lt;pre&gt;svn co http://svn.inbatu.com/almacen/trunk almacen&lt;/pre&gt;


&lt;p&gt;Para la primera versión que he considerado &quot;estable&quot; (más bien funcional):&lt;/p&gt;

&lt;pre&gt;svn co http://svn.inbatu.com/almacen/branches/almacen-0.5&lt;/pre&gt;


&lt;p&gt;Bueno y unas capturas de pantalla (un poco feas):&lt;/p&gt;

&lt;div class=&quot;gallery&quot;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;/drawer/2006/12/almacen-05_principal.png&quot;&gt;&lt;img src=&quot;/drawer/2006/12/almacen-05_principal.miniatura.png&quot; alt=&quot;vprincipal&quot; /&gt;&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/drawer/2006/12/almacen-05_entrada.png&quot;&gt;&lt;img src=&quot;/drawer/2006/12/almacen-05_entrada.miniatura.png&quot; alt=&quot;Almacen 0.5 - Ventana entrada de producto&quot; /&gt;&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/drawer/2006/12/almacen-05_nuevo.png&quot;&gt;&lt;img src=&quot;/drawer/2006/12/almacen-05_nuevo.miniatura.png&quot; alt=&quot;Almacen 0.5 - Ventana nuevo producto&quot; /&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;


&lt;p&gt;Ejem, quizá falte maquear un poco más las cosas. El pedazo de hueco blanco de la ventana principal es un textarea que puse para rellenar, más adelante quiero poner una lista de albaranes en su lugar.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Tengo un Slash en mi cuarto!</title>
   <link href="http://blog.inbatu.com/2006/12/01/tengo-un-slash-en-mi-cuarto/"/>
   <updated>2006-12-01T00:00:00+01:00</updated>
   <id>http://blog.inbatu.com//2006/12/01/tengo-un-slash-en-mi-cuarto</id>
   <content type="html">&lt;p&gt;Esta tarde ni corto ni perezoso he visto un muñeco del Slash muy guapo, y bastante barato,  no me he podido resistir y me lo he comprado.
El nivel de detalles es impresionante, lleva la pua, una Gibson Les Paul, con las cuerdas de nilon, la marca Gibson en la pala, también cadenas, el pañuelo colgando, sus chapas... Ah y además lleva un Marshall :P&lt;/p&gt;

&lt;p&gt;Dejo unas fotillos, aunque no se aprecian muy bien los detalles.&lt;/p&gt;

&lt;div class=&quot;gallery&quot;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;/drawer/2006/12/100_0362_2.jpg&quot;&gt;&lt;img src=&quot;/drawer/2006/12/100_0362_2.miniatura.jpg&quot; alt=&quot;Slash 1&quot; /&gt;&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/drawer/2006/12/100_0368_2.jpg&quot;&gt;&lt;img src=&quot;/drawer/2006/12/100_0368_2.miniatura.jpg&quot; alt=&quot;Slash 2&quot; /&gt;&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/drawer/2006/12/100_0369_2.jpg&quot;&gt;&lt;img src=&quot;/drawer/2006/12/100_0369_2.miniatura.jpg&quot; alt=&quot;Slash 3&quot; /&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;

</content>
 </entry>
 
 <entry>
   <title>Haciendo amigos en C++</title>
   <link href="http://blog.inbatu.com/2006/11/03/haciendo-amigos-en-c-2/"/>
   <updated>2006-11-03T00:00:00+01:00</updated>
   <id>http://blog.inbatu.com//2006/11/03/haciendo-amigos-en-c-2</id>
   <content type="html">&lt;p&gt;Mediante el uso de la palabra clave &lt;code&gt;friend&lt;/code&gt; podemos permitir el acceso a miembros privados o protegidos de una clase a funciones que no pertenecen a esa clase o a permitir el acceso a otras clases. Veremos dos casos ejemplo, declarando una función como &lt;code&gt;friend&lt;/code&gt; dentro de la interfaz pública de una clase y declarando una clase como amiga.&lt;/p&gt;

&lt;h3&gt;Funciones friend&lt;/h3&gt;


&lt;p&gt;Cuando declaramos una función como friend en una clase estamos indicando que esa función tendrá acceso a los miembros privados de la clase, pero la función en cuestión no forma parte del ámbito de la clase. Veamos un ejemplo:&lt;/p&gt;

&lt;p&gt;Supongamos que tenemos una clase que representa un número racional como un par de números enteros. Queremos que este tipo nuevo se pueda usar de igual forma que &lt;code&gt;int, double,...&lt;/code&gt; así:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;cpp&quot;&gt;
Racional r(2,3);
cout &amp;lt;&amp;lt; r &amp;lt;&amp;lt; endl;
&lt;/pre&gt;


&lt;p&gt;Para poder hacer esto necesitamos sobrecargar el operador de inserción binario &lt;code&gt;operator&amp;lt;&amp;lt;&lt;/code&gt; :&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;cpp&quot;&gt;
class Racional
{
     friend ostream &amp;amp;operator&amp;lt;&amp;lt;(ostream &amp;amp;out, const Racional &amp;amp;r);
     public:
     
     Racional(int numerador, int denominador);
     ~Racional();
     // ...
};
&lt;/pre&gt;


&lt;p&gt;De esta manera la función friend obtiene acceso completo a los miembros de Racional. La implementación de esta función se haría, fijándonos en que no pertenece al ámbito de la clase:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;cpp&quot;&gt;
ostream &amp;amp;operator&amp;lt;&amp;lt;(ostream &amp;amp;out, const Racional &amp;amp;r)
{
     // Acceso a los miembros privados de Racional para mostrar r.
     // ...

     return out;
}
&lt;/pre&gt;


&lt;p&gt;Podríamos haber declarado la función como no &lt;code&gt;friend&lt;/code&gt;, entonces tendríamos que usar métodos públicos get(), set() para obtener los valores, usando friend podemos acceder directamente a los miembros, y además la función forma parte de la interfaz pública de la clase Racional.&lt;/p&gt;

&lt;h3&gt;Clases friend&lt;/h3&gt;


&lt;p&gt;Además de declarar una función no miembro como friend, podemos declarar funciones miembro de otras clases como friend, así como otras clases como clases amigas.&lt;/p&gt;

&lt;p&gt;Las clases amigas se usan en casos donde una clase está íntimamente ligada a otra. Por ejemplo supongamos que tenemos una clase Punto que representa una coordenada, y una clase ColeccionPunto que guarda una lista de puntos. Como la colección quizá necesite manipular objetos Punto, podemos declarar ColeccionPunto como amiga de la clase Punto:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;cpp&quot;&gt;
// Clase Punto
class Punto
{
     friend ColeccionPunto;

     public:
     Punto(double x, double y) :
     m_x(x),
     m_y(y)
     {
     }

     ~Punto();
     // ...

     private:
     double m_x;
     double m_y;
};
&lt;/pre&gt;


&lt;p&gt;Como la clase ColeccionPunto esta declarada como friend, puede acceder a los datos internos de cualquier objeto Punto. Una cosa importante es que esta amistad no es mútua, aunque ColeccionPunto puede acceder a Punto no se da el caso inverso. Además la amistad no es heredable, las clases que deriven de ColeccionPunto no podrán acceder a Punto. El principio detrás de esto es que la amistad no se concede de forma implícita sino que cada clase debe especificar de forma explícita sus amigos.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>GNU/Emacs - Comandos básicos I</title>
   <link href="http://blog.inbatu.com/2006/11/03/combinaciones-de-gnuemacs/"/>
   <updated>2006-11-03T00:00:00+01:00</updated>
   <id>http://blog.inbatu.com//2006/11/03/combinaciones-de-gnuemacs</id>
   <content type="html">&lt;p&gt;Los comandos que pongo aquí son de la forma &lt;tt&gt;C-x&lt;/tt&gt;, &lt;tt&gt;M-x&lt;/tt&gt;, esto quiere decir, en el caso de &lt;tt&gt;C-x&lt;/tt&gt; que debemos pulsar la tecla &lt;tt&gt;CONTROL&lt;/tt&gt; y a la vez la tecla &lt;tt&gt;x&lt;/tt&gt;. En el caso de &lt;tt&gt;M-x&lt;/tt&gt; debemos pulsar la tecla &lt;tt&gt;META&lt;/tt&gt; (&lt;tt&gt;ALT&lt;/tt&gt; ó &lt;tt&gt;ESC&lt;/tt&gt;) y a la vez la tecla &lt;tt&gt;x&lt;/tt&gt;. Bueno, una vez aclarado esto paso a listar un resumen de los comandos básicos.&lt;/p&gt;

&lt;p&gt;Nota: Entre paréntesis pondré el nombre largo del comando por ejemplo &lt;i&gt;find-file&lt;/i&gt;, que se corresponde con el atajo &lt;tt&gt;C-x C-f&lt;/tt&gt;, con lo cual podremos ejecutar este comando o bien mediante el atajo o bien haciendo &lt;tt&gt;M-x find-file RETURN&lt;/tt&gt;.&lt;/p&gt;

&lt;h4&gt;Abrir, insertar y guardar ficheros&lt;/h4&gt;


&lt;ul&gt;
&lt;li&gt;&lt;b&gt;C-x C-f&lt;/b&gt; (&lt;i&gt;find-file&lt;/i&gt;): Abre un fichero existente o si no abre uno nuevo.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;C-x C-v&lt;/b&gt; (&lt;i&gt;find-alternate-file&lt;/i&gt;): Carga un fichero diferente en ese mismo buffer, nos sirve si por ejemplo queriamos abrir un fichero y nos hemos equivocado al escribir el nombre.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;C-x i&lt;/b&gt; (&lt;i&gt;insert-file&lt;/i&gt;): Inserta el contenido de un fichero dentro del buffer actual (en la posición del cursor).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;C-x C-s&lt;/b&gt; (&lt;i&gt;save-buffer&lt;/i&gt;): Guarda el contenido del buffer en el fichero asociado (y si no lo tiene pregunta el nombre de fichero con el que guardarlo).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;C-x C-w&lt;/b&gt; (&lt;i&gt;write-file&lt;/i&gt;): Guarda el contenido del buffer preguntando el nombre del fichero en el que guardar.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;C-x C-c&lt;/b&gt; : Sale de emacs, preguntando si guardar los cambios o no en caso de que hayan buffers modificados sin guardar.
&lt;/li&gt;&lt;/ul&gt;




&lt;h4&gt;Ayuda&lt;/h4&gt;


&lt;ul&gt;
&lt;li&gt;&lt;b&gt;C-h ?&lt;/b&gt; (&lt;i&gt;help&lt;/i&gt;): Muestra las opciones de ayuda de Emacs.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;C-h t&lt;/b&gt; (&lt;i&gt;help-with-tutorial&lt;/i&gt;): Inicia un tutorial de introducción a Emacs.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;C-h k&lt;/b&gt; (&lt;i&gt;describe-key&lt;/i&gt;): Muestra información sobre una combinación de teclas. Por ejemplo &lt;tt&gt;C-h k C-x i&lt;/tt&gt; muestra una descripción del comando &lt;i&gt;insert-file&lt;/i&gt;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;C-h f&lt;/b&gt; (&lt;i&gt;describe-function&lt;/i&gt;): Muestra información sobre un comando. La información mostrada es la misma que en el anterior pero en lugar de pasarle una combinación de teclas le pasamos el comando directamente.&lt;/li&gt;
&lt;/ul&gt;




&lt;h4&gt;Moviéndonos por los ficheros&lt;/h4&gt;


&lt;ul&gt;
&lt;li&gt;&lt;b&gt;C-f&lt;/b&gt; (&lt;i&gt;forward-char&lt;/i&gt;): Mueve el cursor un carácter hacia adelante.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;C-b&lt;/b&gt; (&lt;i&gt;backward-char&lt;/i&gt;): Mueve el cursor un carácter hacia atrás.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;C-p&lt;/b&gt; (&lt;i&gt;previous-line&lt;/i&gt;): Mueve el cursor a la línea anterior.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;C-n&lt;/b&gt; (&lt;i&gt;next-line&lt;/i&gt;): Mueve el cursor a la línea siguiente.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;M-f&lt;/b&gt; (&lt;i&gt;forward-word&lt;/i&gt;): Mueve el cursor una palabra hacia adelante.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;M-b&lt;/b&gt; (&lt;i&gt;backward-word&lt;/i&gt;): Mueve el cursor una palabra hacia atrás.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;C-a&lt;/b&gt; (&lt;i&gt;beginning-of-line&lt;/i&gt;): Mueve el cursor al principio de la línea.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;C-e&lt;/b&gt; (&lt;i&gt;end-of-line&lt;/i&gt;): Mueve el cursor al final de la línea.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;M-a&lt;/b&gt; (&lt;i&gt;backward-sentece&lt;/i&gt;): Mueve el cursor una frase hacia atrás.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;M-e&lt;/b&gt; (&lt;i&gt;forward-sentece&lt;/i&gt;): Mueve el cursor una frase hacia adelante.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;M-{&lt;/b&gt; (&lt;i&gt;backward-paragraph&lt;/i&gt;): Mueve el cursor un párrafo hacia atrás.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;M-}&lt;/b&gt; (&lt;i&gt;forward-paragraph&lt;/i&gt;): Mueve el cursor un párrafo hacia adelante.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;C-x [&lt;/b&gt; (&lt;i&gt;backward-page&lt;/i&gt;): Mueve el cursor una página hacia atrás.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;C-x ]&lt;/b&gt; (&lt;i&gt;forward-page&lt;/i&gt;): Mueve el cursor una página hacia adelante.&lt;p&gt;Nota: Emacs se mueve entre páginas usando un delimitador de página (que se define mediante la variable &lt;i&gt;page-delimiter&lt;/i&gt;). En el modo texto el delimitador de página (no imprimible) se puede insertar mediante &lt;tt&gt;C-q C-l&lt;/tt&gt; (L minúscula), que insertará &lt;tt&gt;^L&lt;/tt&gt; que aunque parezcan dos carácteres es uno solo.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;b&gt;C-v&lt;/b&gt; (&lt;i&gt;scroll-up&lt;/i&gt;): Avanza una pantalla hacia adelante, mostrando dos líneas de la pantalla anterior.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;M-v&lt;/b&gt; (&lt;i&gt;scroll-down&lt;/i&gt;): Avanza una pantalla hacia atrás&lt;/li&gt;
&lt;li&gt;&lt;b&gt;M-&amp;gt;&lt;/b&gt; (&lt;i&gt;end-of-buffer&lt;/i&gt;): Lleva el cursor al final del fichero.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;M-&amp;lt;&lt;/b&gt; (&lt;i&gt;beginning-of-buffer&lt;/i&gt;): Lleva el cursor al principio del fichero.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;M-x goto-line &lt;i&gt;n&lt;/i&gt; RETURN&lt;/b&gt;: Mueve el cursor a la línea &lt;i&gt;n&lt;/i&gt; del fichero.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;M-x goto-char &lt;i&gt;n&lt;/i&gt; RETURN&lt;/b&gt;: Mueve el cursor al carácter &lt;i&gt;n&lt;/i&gt; del fichero.&lt;/li&gt;
&lt;/ul&gt;




&lt;h4&gt;Repetir comandos&lt;/h4&gt;


&lt;ul&gt;
&lt;li&gt;&lt;b&gt;M &lt;i&gt;n&lt;/i&gt;&lt;/b&gt; (&lt;i&gt;digit-argument&lt;/i&gt;): Repite el comando escrito a continuación &lt;i&gt;n&lt;/i&gt; veces.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;C-u &lt;i&gt;n&lt;/i&gt;&lt;/b&gt; (&lt;i&gt;universal-argument&lt;/i&gt;): Hace exactamente lo mismo que la anterior.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;C-u&lt;/b&gt;: Este comando sin argumentos repite el comando escrito a continuación 4 veces. Si hacemos &lt;tt&gt;C-u C-u&lt;/tt&gt; lo repetiría 16 veces, &lt;tt&gt;C-u C-u C-u&lt;/tt&gt; 64 veces, etc.
&lt;/li&gt;&lt;/ul&gt;




&lt;h4&gt;Redibujar la pantalla&lt;/h4&gt;


&lt;ul&gt;&lt;li&gt;&lt;b&gt;C-l&lt;/b&gt; (&lt;i&gt;recenter&lt;/i&gt;): Redibuja la pantalla, poniendo la línea actual en el centro.&lt;p&gt;Este comando es útil cuando por ejemplo estamos editando en consola y el kernel nos tira mensajes, con este comando emacs redibuja la pantalla con la información del buffer. También nos es útil si estamos editando una porción de texto que nos aparece al final del display, usamos este comando y nos centra la línea actual, así vemos lo que tenemos por encima y por debajo.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;

</content>
 </entry>
 
 <entry>
   <title>Creación de un repositorio Debian (2ª parte)</title>
   <link href="http://blog.inbatu.com/2006/10/15/creacion-de-un-repositorio-debian-2%25c2%25aa-parte/"/>
   <updated>2006-10-15T00:00:00+02:00</updated>
   <id>http://blog.inbatu.com//2006/10/15/creacion-de-un-repositorio-debian-2%c2%aa-parte</id>
   <content type="html">&lt;p&gt;Conforme terminamos lo explicado en la primera parte nuestro repositorio no utiliza firmas. Para ello deberemos firmar los &lt;tt&gt;Release&lt;/tt&gt; con gpg, para lo cual necesitamos habernos creado una clave.&lt;/p&gt;

&lt;h3&gt;Generación de una clave&lt;/h3&gt;


&lt;p&gt;Simplemente hemos de ejecutar el siguiente comando:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gpg --gen-key&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Nos hará una serie de preguntas, entre ellas nos pedira un passphrase, que sera la clave privada.&lt;/p&gt;

&lt;p&gt;Más adelante necesitaremos importar la clave pública para usar el repositorio, la exportamos con el siguiente comando:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gpg -a --export &amp;gt; clave_publica.gpg&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;Firma de los Release&lt;/h3&gt;


&lt;p&gt;Ahora que ya poseemos una clave para firmar el repositorio tenemos que firmar los &lt;tt&gt;Release&lt;/tt&gt; de cada uno de los directorios:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;bash&quot;&gt;
cd dists/sarge
gpg -bao Release.gpg Release

cd main/binary-i386
gpg -bao Release.gpg Release
&lt;/pre&gt;


&lt;p&gt;Esto nos pide el passphrase que introdujimos al generar la clave, y nos genera un fichero &lt;tt&gt;Release.gpg&lt;/tt&gt;. Pues bien una vez hemos firmado todos los ficheros &lt;tt&gt;Release&lt;/tt&gt; ya tenemos firmado el repositorio.&lt;/p&gt;

&lt;h3&gt;Importando la clave pública&lt;/h3&gt;


&lt;p&gt;Ahora lo único que nos falta es importar la clave pública exportada anteriormente en cada una de las máquinas que utilizan el repositorio:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;apt-key add clave_publica.gpg&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Si no hacemos este último paso el apt de cada máquina no reconocerá como firmados los &lt;tt&gt;Release&lt;/tt&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Creación de un repositorio Debian automático</title>
   <link href="http://blog.inbatu.com/2006/10/14/creacion-de-un-repositorio-debian-automatico/"/>
   <updated>2006-10-14T00:00:00+02:00</updated>
   <id>http://blog.inbatu.com//2006/10/14/creacion-de-un-repositorio-debian-automatico</id>
   <content type="html">&lt;p&gt;En este post voy a explicar cómo crear un repositorio para alojar nuestros propios paquetes .deb . Para ello necesitaremos tener instalado el paquete &lt;tt&gt;apt-utils&lt;/tt&gt; que seguramente ya lo estará.&lt;/p&gt;

&lt;h3&gt;Preparando el repositorio&lt;/h3&gt;


&lt;p&gt;Antes que nada deberemos crear un directorio raíz donde se hallará el resto de directorios y ficheros. Por ejemplo creamos el directorio &lt;tt&gt;/var/repo&lt;/tt&gt;.&lt;/p&gt;

&lt;p&gt;Una vez creado el raíz habrá que crear dentro de el la estructura de directorios, por ejemplo para la distribución sarge creamos la siguiente estructura:&lt;/p&gt;

&lt;pre&gt;
/dists
/dists/sarge
/dists/sarge/contrib
/dists/sarge/contrib/binary-i386
/dists/sarge/contrib/source
/dists/sarge/main
/dists/sarge/main/binary-i386
/dists/sarge/main/source
/dists/sarge/non-free
/dists/sarge/non-free/binary-i386
/dists/sarge/non-free/source
&lt;/pre&gt;


&lt;p&gt;Donde vemos que primero se crea el directorio dists, donde luego habrá un directorio por cada distribución (en nuestro caso solo sarge). Dentro de la distribución (sarge) tendremos las diferentes secciones, &lt;tt&gt;main&lt;/tt&gt; para paquetes libres, &lt;tt&gt;non-free&lt;/tt&gt; para paquetes no libres, y &lt;tt&gt;contrib&lt;/tt&gt; para paquetes libres que dependen de otros paquetes que no lo son.&lt;/p&gt;

&lt;p&gt;Una vez creadas las secciones creamos un directorio para los binarios, &lt;tt&gt;binary-&lt;arquitectura&gt;&lt;/tt&gt; en este caso como serán exclusivamente para arquitectura i386 solo necesitaremos &lt;tt&gt;binary-i386&lt;/tt&gt;, y un directorio para los fuentes, &lt;tt&gt;source&lt;/tt&gt;.&lt;/p&gt;

&lt;h3&gt;Llenando el repositorio&lt;/h3&gt;


&lt;p&gt;Una vez creada la estructura ya podemos alojar nuestros paquetes. Para ello tenemos que copiar los .deb correspondientes a paquetes binarios en los directorios &lt;tt&gt;binary-i386&lt;/tt&gt; de cada sección. Si además queremos distribuir los fuentes copiaremos los ficheros &lt;tt&gt;.dsc  -diff.tar.gz .orig.tar.bz&lt;/tt&gt; en los directorios &lt;tt&gt;source&lt;/tt&gt;.&lt;/p&gt;

&lt;p&gt;En cada directorio &lt;tt&gt;binary-i386&lt;/tt&gt; y &lt;tt&gt;source&lt;/tt&gt; necesitamos un fichero &lt;tt&gt;Release&lt;/tt&gt; cuyo contenido sería el siguiente:&lt;/p&gt;

&lt;pre&gt;
Archive: stable
Component: main
Origin: &amp;lt;Tu nombre u organizacion&amp;gt;
Label: &amp;lt;Una etiqueta descriptiva&amp;gt;
Architecture: &amp;lt;Arquitectura de tu procesador o &amp;quot;source&amp;quot; 
                        para los directorios de fuentes&amp;gt;
&lt;/pre&gt;


&lt;h3&gt;Ficheros de configuración&lt;/h3&gt;


&lt;p&gt;Necesitamos dos ficheros de configuración:&lt;/p&gt;


&lt;ul&gt;
    &lt;li&gt;&lt;tt&gt;apt-sarge-release.conf&lt;/tt&gt;&lt;/li&gt;
    &lt;li&gt;&lt;tt&gt;apt-ftparchive.conf&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Ambos ficheros los pondremos en el directorio raíz del repositorio. Y su contenido sería el siguiente:&lt;/p&gt;

&lt;h4&gt;apt-sarge-release.conf&lt;/h4&gt;


&lt;pre&gt;
APT::FTPArchive::Release::Origin &quot;Tu nombre u organizacion&quot;;
APT::FTPArchive::Release::Label &quot;Etiqueta descriptiva&quot;;
APT::FTPArchive::Release::Suite &quot;stable&quot;;
APT::FTPArchive::Release::Codename &quot;sarge&quot;;
APT::FTPArchive::Release::Architectures &quot;i386 source&quot;;
APT::FTPArchive::Release::Components &quot;main contrib non-free&quot;;
APT::FTPArchive::Release::Description &quot;Descripcion detallada&quot;;
&lt;/pre&gt;


&lt;h4&gt;apt-ftparchive.conf&lt;/h4&gt;




&lt;pre&gt;
Dir {
  ArchiveDir &quot;.&quot;;
  CacheDir &quot;.&quot;;
};

Default {
  Packages::Compress &quot;gzip bzip2&quot;;
  Sources::Compress &quot;gzip bzip2&quot;;
  Contents::Compress &quot;gzip bzip2&quot;;
};

BinDirectory &quot;dists/sarge/main/binary-i386&quot; {
  Packages &quot;dists/sarge/main/binary-i386/Packages&quot;;
  Contents &quot;dists/sarge/Contents-i386&quot;;
  SrcPackages &quot;dists/sarge/main/source/Sources&quot;;
};

BinDirectory &quot;dists/sarge/contrib/binary-i386&quot; {
  Packages &quot;dists/sarge/contrib/binary-i386/Packages&quot;;
  Contents &quot;dists/sarge/Contents-i386&quot;;
  SrcPackages &quot;dists/sarge/contrib/source/Sources&quot;;
};

BinDirectory &quot;dists/sarge/non-free/binary-i386&quot; {
  Packages &quot;dists/sarge/non-free/binary-i386/Packages&quot;;
  Contents &quot;dists/sarge/Contents-i386&quot;;
  SrcPackages &quot;dists/sarge/non-free/source/Sources&quot;;
};

Tree &quot;dists/sarge&quot; {
  Sections &quot;main contrib non-free&quot;;
  Architectures &quot;i386 source&quot;;
};

Default {
  Packages {
    Extensions &quot;.deb&quot;;
  };
};
&lt;/pre&gt;


&lt;p&gt;Una vez tenemos los ficheros de configuración adecuados a nuestras necesidades hemos de ejecutar un par de comandos, los cuales podemos meter en un script llamado por ejemplo &lt;tt&gt;update-archive.sh&lt;/tt&gt;:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;bash&quot;&gt;
#!/bin/sh
apt-ftparchive generate apt-ftparchive.conf
apt-ftparchive -c apt-dapper-release.conf release dists/dapper/ 
               &gt;dists/dapper/Release
&lt;/pre&gt;




&lt;h3&gt;Actualizando el repositorio&lt;/h3&gt;


&lt;p&gt;Una vez hemos puesto los paquetes dentro de los directorios correspondientes de su sección ejecutamos el script &lt;tt&gt;update-archive.sh&lt;/tt&gt;, obteniendo una salida como la siguiente:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;bash&quot;&gt;
$ ./update-archive.sh
 dists/sarge/main/binary-i386: 21 files 42.7MB 2s
 dists/sarge/contrib/binary-i386: 0 files 0B 0s
 dists/sarge/non-free/binary-i386: 4 files 114MB 5s
 dists/sarge/main/binary-i386/: 21 files 42.7MB 0s
 dists/sarge/contrib/binary-i386/: 0 files 0B 0s
 dists/sarge/non-free/binary-i386/: 4 files 114MB 0s
 dists/sarge/main/source/: 2 pkgs in 0s
 dists/sarge/contrib/source/: 0 pkgs in 0s
 dists/sarge/non-free/source/: 0 pkgs in 0s
Done Packages, Starting contents.
Done. 314MB in 50 archives. Took 7s
&lt;/pre&gt;




&lt;h3&gt;Usando el repositorio&lt;/h3&gt;


&lt;p&gt;Después de los pasos anteriores ya podemos utilizar el repositorio modificando el fichero &lt;tt&gt;/etc/apt/sources.list&lt;/tt&gt;:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Para acceso local
&lt;tt&gt;deb file:///var/repo sarge main contrib non-free&lt;/tt&gt;&lt;/li&gt;
    &lt;li&gt;Para acceso remoto (si por ejemplo hacemos un enlace simbólico a /var/svn dentro del direcorio de un servidor http):
&lt;tt&gt;deb http://nuestro.servidor/repositorio sarge main contrib non-free&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Nota&lt;/h3&gt;


&lt;p&gt;Este post es prácticamente una traducción de un howto cuyo link es &lt;a href=&quot;http://people.connexer.com/~roberto/howtos/debrepository&quot;&gt;este&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;En un próximo post pondré como añadir nuestra firma al repositorio con gpg.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Probando con Swing</title>
   <link href="http://blog.inbatu.com/2006/04/24/probando-con-swing/"/>
   <updated>2006-04-24T00:00:00+02:00</updated>
   <id>http://blog.inbatu.com//2006/04/24/probando-con-swing</id>
   <content type="html">&lt;p&gt;Pues ya que lo estoy dando en clase, me ha dado por probar un poco con swing. El resultado es un pequeño, sencillo y poco usable programa que me he hecho para gestionar libros, mediante una base de datos mysql.&lt;/p&gt;

&lt;p&gt;En concreto usando JDBC con el driver de mysql. Tiene muchos fallos y no funciona demasiado bien, pero ahi esta.&lt;/p&gt;

&lt;p&gt;&lt;a id=&quot;p55&quot; href=&quot;/drawer/2006/04/libros_v01tar.bz2&quot;&gt;Código fuente&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Por fin tengo un portátil</title>
   <link href="http://blog.inbatu.com/2006/04/24/por-fin-tengo-un-portatil/"/>
   <updated>2006-04-24T00:00:00+02:00</updated>
   <id>http://blog.inbatu.com//2006/04/24/por-fin-tengo-un-portatil</id>
   <content type="html">&lt;p&gt;Pues sí, me salio una oferta y no la pude dejar pasar. El cacharro en cuestión es un HP Pavilion ze4930ea (1.5Ghz, 512 RAM, 40 Gb de disco, tarjeta wireless Intel PRO Wireless 2200...).&lt;/p&gt;

&lt;p&gt;Empecé poniendole una Ubuntu Breezy, pero la tarjeta inalámbrica me daba muchos fallos (kernel panic), despues probé una fedora core 5 y más de lo mismo. Compilando el driver a mano, con ndiswrapper y nada. Al final he puesto una Ubuntu Dapper y va a las mil maravillas.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Encontrar procesos zombi</title>
   <link href="http://blog.inbatu.com/2005/11/23/encontrar-procesos-zombi/"/>
   <updated>2005-11-23T00:00:00+01:00</updated>
   <id>http://blog.inbatu.com//2005/11/23/encontrar-procesos-zombi</id>
   <content type="html">&lt;p&gt;Cuando tenemos una máquina que no funciona correctamente es posible que los procesos estén en estado zombi. Para poder ver los procesos en este estado usamos el comando siguiente:&lt;/p&gt;

&lt;pre&gt;
ps -el | grep 'Z'
&lt;/pre&gt;


&lt;p&gt;Con el comando &lt;tt&gt;ps -el&lt;/tt&gt; se puede obtener una salida en la que la segunda columna indica el estado del proceso. Existen varios estados:&lt;/p&gt;

&lt;pre&gt;
S : sleeping
R : running
D : waiting
T : gestopt (suspended)
Z : zombie (defunct)
&lt;/pre&gt;


&lt;p&gt;Un ejemplo podría ser el siguiente:&lt;/p&gt;

&lt;pre&gt;
# ps -el | grep 'Z'
F S   UID   PID  PPID  C PRI  NI ADDR    SZ WCHAN  TTY   TIME CMD
1 Z     0  1213   589  0  75   0    -     0 funct&amp;gt; ?    00:00:00 find
&lt;/pre&gt;


&lt;p&gt;Donde vemos que el proceso &lt;tt&gt;dovecot-auth&lt;/tt&gt; está en estado zombi.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Creación de paquetes</title>
   <link href="http://blog.inbatu.com/2005/11/21/creacion-de-paquetes/"/>
   <updated>2005-11-21T00:00:00+01:00</updated>
   <id>http://blog.inbatu.com//2005/11/21/creacion-de-paquetes</id>
   <content type="html">&lt;p&gt;Hoy he descubierto un programa bastante interesante para generar paquetes para las distribuciones más usadas, entre ellas como no Debian. El programa en cuestión es Checkinstall. Nos permite generarnos debs a partir del código fuente  de forma tan fácil como:&lt;/p&gt;

&lt;pre&gt;
./configure
make
checkinstall
&lt;/pre&gt;


&lt;p&gt;Al ejecutar el checkinstall este nos pregunta acerca de la descripción que queremos poner al paquete, el tipo de paquete(RPM, DEB o SLACKWARE TGZ), así como el maintainer, version, licencia... Y después de indicárselo tendremos en el directorio nuestro programa en forma de paquete deb/rpm/tgz. Además el programa nos permite poner documentación que luego se instalará en /usr/share/doc, también podemos ejecutar scripts preinstall/postinstall y preremove/postremove y puede que más cosas que no he mirado.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Crear debs de Java</title>
   <link href="http://blog.inbatu.com/2005/10/27/crear-debs-de-java/"/>
   <updated>2005-10-27T00:00:00+02:00</updated>
   <id>http://blog.inbatu.com//2005/10/27/crear-debs-de-java</id>
   <content type="html">&lt;p&gt;Existe una forma cómoda, fácil y rápida de tener java (ya sea jre o jsdk) en un deb, mediante el paquete java-package de debian. Los pasos son los siguientes:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;Instalar &lt;i&gt;java-package&lt;/i&gt; (apt-get install java-package)&lt;/li&gt;
&lt;li&gt;Bajar de la web de sun el jsdk por ejemplo el &lt;a href=&quot;http://java.sun.com/j2se/1.5.0/download.jsp&quot;&gt;jdk 5.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ejecutar &lt;i&gt;make-jpkg jdk-1_5_0-linux-i586.bin&lt;/i&gt; (lo que nos generará el .deb)&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;Ahora ya podremos hacer &lt;i&gt;dpkg -i sun-j2sdk1.5_1.5.0_i386.deb&lt;/i&gt; , lo que nos instalará el entorno  en /usr/lib/j2sdk1.5-sun.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Configurar Gateway</title>
   <link href="http://blog.inbatu.com/2005/09/20/configurar-gateway/"/>
   <updated>2005-09-20T00:00:00+02:00</updated>
   <id>http://blog.inbatu.com//2005/09/20/configurar-gateway</id>
   <content type="html">&lt;p&gt;Lo que voy a explicar es una forma de hacer que una máquina (servidor) actúe como pasarela a internet, es decir compartir la conexión a internet entre varios equipos. Para ello nuestro servidor deberá constar de dos tarjetas de red. Una de ellas conectada a &quot;internet&quot; (modem) y la otra a otro equipo ya sea otro pc o un switch.&lt;/p&gt;

&lt;p&gt;
Bueno pues lo primero que necesitaremos que nuestro kernel debe soportar iptables (versiones 2.4 en adelante) así como realizar nat mediante este. Para ello tenemos que tener activados los modulos
ip_tables e iptable_nat. &lt;/p&gt;


&lt;p&gt;Una vez nos aseguramos de ello deberemos ejecutar lo siguiente: &lt;/p&gt;


&lt;pre&gt;iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth0 -j MASQUERADE&lt;/pre&gt;


&lt;p&gt;
Donde 192.168.0.0/24 indica que redireccionaremos a toda la subred 192.168.0.0 (con máscara 255.255.255.0) y eth0 es la interfaz de red conectada a internet.&lt;br /&gt; &lt;br /&gt;Después debemos activar el ip forwarding de la ejecutando lo siguiente:&lt;/p&gt;


&lt;p&gt;
&lt;tt&gt;echo &quot;1&quot; &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;/tt&gt;&lt;/p&gt;


&lt;p&gt;
Con esto ya tenemos a nuestra máquina haciendo funciones de pasarela. Pero en este punto si reiniciamos el ordenador se perderá la configuración y tendremos que volver a ejecutar los dos comandos anteriores. Para solucionar esto los metemos en un script, algo así como:&lt;/p&gt;


&lt;pre name=&quot;code&quot; class=&quot;bash&quot;&gt;
#! /bin/sh
echo -n &quot;Iniciando Gateway... &quot;
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth0 -j MASQUERADE

echo &quot;1&quot; &amp;gt; /proc/sys/net/ipv4/ip_forward
echo &quot;Iniciado.&quot;
&lt;/pre&gt;


&lt;p&gt;Guardamos este script como /etc/init.d/gateway, por ejemplo, le damos permisos de ejecución y creamos enlaces simbólicos a él para los runlevels que nos interesen, p. ej para el 2, como sigue:&lt;/p&gt;


&lt;p&gt;&lt;tt&gt;ln -s /etc/init.d/gateway /etc/rc2.d/S99gateway&lt;/tt&gt;&lt;/p&gt;


&lt;p&gt;Solo resta configurar los clientes, utilizando como puerta de enlace la ip de nuestro servidor (p. ej. 192.168.0.1 en caso de que hayamos configurado esa ip en la segunda tarjeta de red de nuestro servidor) y para las DNS tenemos dos posibilidades:&lt;/p&gt;


&lt;ul&gt;
&lt;li&gt;Poner directamente las DNS de nuestro proveedor de servicios.&lt;/li&gt;
&lt;li&gt;Instalar bind en nuestra máquina servidor (lo que se escapa de esta explicación).&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 <entry>
   <title>Probando subversion</title>
   <link href="http://blog.inbatu.com/2005/09/15/probando-subversion/"/>
   <updated>2005-09-15T00:00:00+02:00</updated>
   <id>http://blog.inbatu.com//2005/09/15/probando-subversion</id>
   <content type="html">&lt;p&gt;He estado trasteando un poco (bastante poco la verdad) con el tan resonado software de control de versiones Subversion y la verdad, creía que no me serviría hasta que fuera a hacer algo serio y tal, pero es muy útil y fácil de utilizar.&lt;/p&gt;

&lt;p&gt;Según he entendido, básicamente es un sistema de ficheros (o algo parecido) que guarda información en una base de datos acerca de todos los cambios que se realizan sobre los ficheros añadidos a los diferentes repositorios. Un repositorio (se pueden tener todos los que se quiera) no es más, a mi entender, que un contenedor de directorios y ficheros, en el que los usuarios van guardando archivos nuevos, actualizando existentes, eliminando... dando para cada una de estas acciones comentarios sobre lo que y porque lo hacen. De esta manera el sistema subversion guarda un historial de todos esos cambios referentes a cada acción, teniendo así un alto control del proyecto. Todos estos cambios se pueden extraer en un ChangeLog.&lt;/p&gt;

&lt;p&gt;Bueno esa es la visión global que he tenido en un ratito. Dejo aquí algunos comandos para ilustrar la facilidad de este sistema:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Crear un repositorio: &lt;p&gt;&lt;code&gt;svnadmin create /directorio/directorio&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;Importar un proyecto ya existente en un repositorio: &lt;p&gt;&lt;code&gt;svn import /directorio/dir http://server/dir -m &quot;Comentario&quot;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Los repositorios se indican con URLs (file://, http://...)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;Añadir un fichero al proyecto:&lt;p&gt;&lt;code&gt;svn add fichero&lt;br /&gt;svn commit fichero -m &quot;comentario&quot;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Con add indicamos a subversion que vamos a controlar ese fichero y con commit subimos los cambios (la primera vez pues subimos el original)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;Actualizar nuestra copia local de trabajo:&lt;p&gt;&lt;code&gt;svn update&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Desde el directorio que queremos actualizar.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;


&lt;p&gt;Y bueno muchas más cosas interesantes. Será cuestión de intentar darle uso durante este curso, de hecho un amigo y yo ya hemos pensado usarlo para pasar a LaTeX los apuntes de matemáticas. Todo se andará.&lt;/p&gt;

&lt;p&gt;Salu2&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>De vuelta</title>
   <link href="http://blog.inbatu.com/2005/09/12/de-vuelta/"/>
   <updated>2005-09-12T00:00:00+02:00</updated>
   <id>http://blog.inbatu.com//2005/09/12/de-vuelta</id>
   <content type="html">&lt;p&gt;Bueno, ya llegó septiembre. Después de todo el verano sin apenas acercarme a los pc's, ahora vuelta a la carga. De aquí a dos semanas empezaré segundo... este año tendre que meter caña. Y nada a ver si empiezo a poner más cosillas por aquí, supongo que proximámente pondré cosillas de java (como me toca estudiarlo este año), a ver si continúo con Qt que lo dejé bastante parado y claro ahora mismo ya casi no me acuerdo de nada. :P&lt;/p&gt;

&lt;p&gt;Salu2 (al Maca porque no se si lo leerá alguien más)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Me he pasado a Qt</title>
   <link href="http://blog.inbatu.com/2005/06/30/me-he-pasado-a-qt/"/>
   <updated>2005-06-30T00:00:00+02:00</updated>
   <id>http://blog.inbatu.com//2005/06/30/me-he-pasado-a-qt</id>
   <content type="html">&lt;p&gt;Pues si, hace ya varias semanas que me dió por probar con qt, así esporádicamente y... me quedé.&lt;/p&gt;

&lt;p&gt;Quizá al principio me liaba un poco, debido a que había estado probando gtkmm, pero después ya me acostumbré. Como opinión propia (la de un novato en esto de la programación), me gusta más Qt pues quizá por las razones que daba la gente y por las cuales me empujé a probarla: la documentación es muchísimo mejor (muy completa), las interfaces (repito, en mi opinión) se construyen de forma más fácil e intuitiva (sobretodo gastando Qt Designer, una maravilla), y bueno también me gustó que las señales y los slots las maneja la propia librería (en gtkmm utiliza sigc).&lt;/p&gt;

&lt;p&gt;De momento estoy leyendo el libro &quot;oficial&quot; de Qt: &lt;a href=&quot;http://www.trolltech.com/products/qt/book.html&quot;&gt;C++ GUI Programming with Qt 3&lt;/a&gt;. Está bastante bien, claro que se suponen unos conocimientos de C++ tirando a avanzados. De momento lo estoy entendiendo, y me he hecho una &lt;a href=&quot;/drawer/2005/06/bacal_source.tar.bz2&quot;&gt;calculadora&lt;/a&gt; (bastante simple y que no funciona de manera ideal).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Sarge ve la luz hoy</title>
   <link href="http://blog.inbatu.com/2005/06/06/sarge-ve-la-luz-hoy/"/>
   <updated>2005-06-06T00:00:00+02:00</updated>
   <id>http://blog.inbatu.com//2005/06/06/sarge-ve-la-luz-hoy</id>
   <content type="html">&lt;p&gt;Pues si, si, no es una broma. Hoy por fín, y después de 3 años sin públicarse ninguna versión estable, se publica Sarge (versión 3.1rc0). En este momento aún no se puede ver en la web oficial ningún anuncio sobre esto, pero si que se ve como se están replicando los mirrors, llenándose con las isos para las diferentes arquitecturas soportadas.&lt;/p&gt;

&lt;p&gt;Supongo que una vez ya se han realizado las réplicas harán el anuncio oficial, y entonces ya de manera definitiva la versión estable será Sarge.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Actualización:&lt;/b&gt; Confirmado &lt;a href=&quot;http://www.debian.org/News/2005/20050606&quot;&gt;aquí&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Mundo conocido</title>
   <link href="http://blog.inbatu.com/2005/05/24/mundo-conocido/"/>
   <updated>2005-05-24T00:00:00+02:00</updated>
   <id>http://blog.inbatu.com//2005/05/24/mundo-conocido</id>
   <content type="html">&lt;p&gt;Pues navegando, concretamente en la página de un desarrollador de kde, &lt;a href=&quot;http://developer.kde.org/~wheeler/&quot;&gt;Scott Wheeler&lt;/a&gt;, me he encontrado con una &lt;a href=&quot;http://www.world66.com/myworld66&quot;&gt;web&lt;/a&gt; que  entre otras cosas (yo solo he probado esta), puedes generar mapas con los paises que has visitado. Esta curioso. :P&lt;/p&gt;

&lt;p&gt;Así mi mapa de paises visitados actualmente es así:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.world66.com/myworld66/visitedCountries/worldmap?visited=ES&quot; alt=&quot;Mundo actual conocido&quot; width=&quot;400&quot; height=&quot;200&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Claro que por lo menos me gustaría que estuviera así:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.world66.com/myworld66/visitedCountries/worldmap?visited=USMXCUJMAREGMAFRDEGRITNLESSEUKINJP&quot; alt=&quot;Mundo por conocer...&quot; width=&quot;400&quot; height=&quot;200&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Tampoco es mucho pedir, ¿no?&lt;/p&gt;

&lt;p&gt;Pues eso, una curiosidad.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Algoritmos de Aritmética de Computadores</title>
   <link href="http://blog.inbatu.com/2005/05/19/algoritmos-de-aritmetica-de-computadores/"/>
   <updated>2005-05-19T00:00:00+02:00</updated>
   <id>http://blog.inbatu.com//2005/05/19/algoritmos-de-aritmetica-de-computadores</id>
   <content type="html">&lt;p&gt;Dejo &lt;a href=&quot;/drawer/2005/05/alg_aritmeticos.pdf&quot;&gt;aquí&lt;/a&gt; un pdf con los diagramas de los algoritmos aritméticos vistos en clase de computadores.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Paquetes en Debian (algunas utilidades)</title>
   <link href="http://blog.inbatu.com/2005/05/18/paquetes-en-debian-algunas-utilidades/"/>
   <updated>2005-05-18T00:00:00+02:00</updated>
   <id>http://blog.inbatu.com//2005/05/18/paquetes-en-debian-algunas-utilidades</id>
   <content type="html">&lt;p&gt;Existen una serie de opciones en los comandos típicos de gestión de paquetes de Debian que son bastante útiles y/o curiosas, que quizá se desconocen (o yo por lo menos desconocía o no las había usado). Algunos de estos usos de los comandos son:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;dpkg --get-selections &amp;gt; fichero.txt&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Nos da una lista del estado de todos los paquetes de nuestro sistema. Otra forma de obtenerlo es mediante &lt;code&gt;dpkg -l &amp;gt; fichero.txt&lt;/code&gt; que nos da ademas la version del paquete y la descripción. Este último se puede usar también para saber si tenemos un paquete instalado (&lt;code&gt;dpkg -l &amp;lt;paquete&amp;gt;&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;dpkg --audit&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Nos muestra los paquetes  que se han quedado a medio instalar o en los que halla fallado la configuración, y los que tengan cualquier estado de error.&lt;/p&gt;



&lt;p&gt;Para bloquear o desbloquear la actualización de un paquete.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;aptitude -f --with-recommends dist-upgrade&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Se realizará una actualización completa del sistema, esto es, se instalarán las versiones más recientes de los paquetes y se resolverán todos los posibles cambios de dependencias entre los paquetes de diferentes versiones. Si fuera necesario, se instalarían paquetes nuevos (normalmente, versiones nuevas de las bibliotecas o paquetes que han cambiado de nombre), y se eliminarían los paquetes obsoletos conflictivos.&lt;/p&gt;

&lt;p&gt;Se puede utilizar aptitude facilmente (con comandos de consola) para instalar desinstalar programas, actualizar el sistema... de la misma manera que apt-get (claro que aptitude es un front-end de este), por ejemplo &quot;&lt;code&gt;aptitude install libncurses5-dev&lt;/code&gt;&quot; , &quot;&lt;code&gt;aptitude purge libncurses5-dev&lt;/code&gt;&quot;.  Aun más fácil es usarlo con su interfaz.&lt;/p&gt;

&lt;p&gt;Seguro que además de estas pocas hay muchísimas que desconozco (seguro que muchos también) y que si leemos atentamente los man seguro que las encontramos.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Intentándolo con Gtkmm II</title>
   <link href="http://blog.inbatu.com/2005/05/15/intentandolo-con-gtkmm-ii/"/>
   <updated>2005-05-15T00:00:00+02:00</updated>
   <id>http://blog.inbatu.com//2005/05/15/intentandolo-con-gtkmm-ii</id>
   <content type="html">&lt;p&gt;Bueno, pues me puse con el tutorial, y empezé a probar más cosillas en el HolaMundo. Y nada, después de unas pocas (como unas 60 quizá) líneas de código más, tengo lo que ya no es un HolaMundo, sino lo que le llamo Intentando Gtkmm (voy por la version 0.3), jajaja, si me entra risa.&lt;/p&gt;

&lt;p&gt;Pues el programita en cuestión (si esque llega a programita) consta de un par de botones, unas cuantas etiquetas, tres RadioButton, dos CheckButton, un par de HScale, y la última adición una Entry. Con estos widgets, lo que he hecho no es otra cosa que mostrar de forma muy sencilla su funcionamiento básico. Aquí pongo una captura:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/drawer/2005/05/intentando.png&quot; title=&quot;Ejemplo intentándolo con gtkmm II&quot;&gt;&lt;img src=&quot;/drawer/2005/05/intentando.miniatura.png&quot; alt=&quot;Ejemplo intentándolo con gtkmm II&quot; /&gt;&lt;/a&gt;
&lt;em&gt;Hacer click para ampliar&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Además de lo que es en sí la librería también estoy desarrollando mi ejercicio como si se tratase de un programa medio útil, es decir, utilizando un proyecto de Anjuta configurado con autotools/automake ... y me voy haciendo &lt;em&gt;make distcheck&lt;/em&gt; y veo el resultado de instalarlo como si se tratase de un programa real, distribuido como código fuente.&lt;/p&gt;

&lt;p&gt;En resumen, que me está gustando bastante esto de programar con interfaz gráfica.&lt;/p&gt;

&lt;p&gt;Dudo que alguien lea esto pero si le apetece ver de lo que hablo bajaroslo de &lt;a href=&quot;/drawer/2005/05/intentandogtkmm03tar.gz&quot;&gt;aquí&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;P.D: En vez de estar estudiando, pos no, programando en gtk!! :P&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Intentándolo con Gtkmm</title>
   <link href="http://blog.inbatu.com/2005/05/12/intentandolo-con-gtkmm/"/>
   <updated>2005-05-12T00:00:00+02:00</updated>
   <id>http://blog.inbatu.com//2005/05/12/intentandolo-con-gtkmm</id>
   <content type="html">&lt;p&gt;Ayer tarde decidí probar, ahora que tengo unas nociones un poco más amplias de C++ y de la programación en general (y orientada a objetos en particula), el uso de la librería Gtkmm. Por si alguien no sabe lo que es, es una interfaz de C++ para GTK+.&lt;/p&gt;

&lt;p&gt;Empezando con el &lt;a href=&quot;http://www.gtkmm.org/docs/gtkmm-2.4/docs/tutorial/html/index.html&quot;&gt;tutorial&lt;/a&gt; que se encuentra en la &lt;a href=&quot;http://www.gtkmm.org&quot;&gt;web oficial&lt;/a&gt; del proyecto, he visto de forma escueta los principios muy muy básicos. Vamos el HolaMundo.&lt;/p&gt;

&lt;p&gt;Por ejemplo, añadiendo el include &lt;em&gt; &amp;lt;gtkmm .h&amp;gt;&lt;/em&gt;  y mediante el siguiente código creamos una ventana principal vacía y la mostramos:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;cpp&quot;&gt;
Gtk::Main kit(argc, argv[]);
Gtk::Window w;
Gtk::Main::run(w);
&lt;/pre&gt;


&lt;p&gt;Y bueno, el hola mundo, que simplemente consta de un botón que muestra una cadena en la consola, ya es un pelín más complicado.&lt;/p&gt;

&lt;p&gt;Resumiendo, que por ahora me voy enterando de lo que gasto, porque y, más o menos como funciona. Lo que no entiendo muy bien, porque aún no lo he estudiado/mirado, son temas como la herencia, los miembros virtual... Pero vamos que con las nociones básicas que tengo de las clases, ya comprendo mejor todo el tema.&lt;/p&gt;

&lt;p&gt;Asi es que seguiré en ello hasta por lo menos terminar este tutorial, espero llegar y haberlo comprendido.&lt;/p&gt;

&lt;p&gt;Saludos&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Se abre el telón</title>
   <link href="http://blog.inbatu.com/2005/05/09/se-abre-el-telon/"/>
   <updated>2005-05-09T00:00:00+02:00</updated>
   <id>http://blog.inbatu.com//2005/05/09/se-abre-el-telon</id>
   <content type="html">&lt;p&gt;Pues nada, que viendo que un colega había puesto un blog de estos, me he dicho: &quot;voy a probarlo&quot; y nada... Dudo que alguien aparte de mi lea esto pero bueno. Si acaso Saludos&lt;/p&gt;

&lt;p&gt;&lt;code&gt;:-)&lt;/code&gt;&lt;/p&gt;
</content>
 </entry>
 
</feed>