If you need to compare two CSS files, the freestyle formatting can drive you crazy. You can use this little Perl script to reformat / reindent them. Or if you just want a tidier file.
#!/usr/bin/perl
# Formats a CSS file from STDIN
# Angel Ortega <angel@triptico.com>
# Public domain
my $css = join('', <STDIN>);
$css =~ s/\s+/ /g;
my $in = 0;
foreach my $c (split(/(\s*\{\s*)|(\s*\}\s*)/, $css)) {
if ($c =~ /\{/) {
print " {\n";
$in = 1;
}
elsif ($c =~ /\}/) {
print "}\n";
$in = 0;
}
else {
if ($in) {
foreach my $sc (split(/\s*;\s*/, $c)) {
print "\t$sc;\n";
}
}
else {
print $c;
}
}
}
I agree that, if comparing two CSS files is the aim, sorting the entries alphabetically would also be great; I left that as an exercise for the reader.
It seems that Pavel has gotten permission from the source to reproduce Antichthon Universalis. He is searching for publishers like crazy, but I'm afraid they won't find the document as interesting as he does (provided that he can find anybody not on holidays these days).
I told him to try self-publishing as I did with Terra Incognita (1997) using services like those provided by Lulu.com. They're cheap and easy, but there is no distribution, other than the possibility to end up in Amazon (but I'm afraid that without a visible promotion...).
He says he doesn't have the technical knowledge to do it; maybe I'll help him. Who knows, it's not impossible that I even become the editor...
There are still no words from the language teacher on the subject.
On my part, I've finished taking a look at the book itself. I'm almost sure it's a forgery like the Oera Linda, but funny to look at anyway.
Pavel has sent to me some scans of Antichthon Universalis, the recently found encrypted text, and it's a rather curious document. The drawings are certainly strange and hard to understand, but what I find more surprising is the scripting:
All text is equally separated, glyph by glyph, as if it was a Chinese or Japanese text. I'm not sure if it's meant to be read horizontally or vertically.
Pavel is in contact with an old friend of him that is a linguistic scholar and had just sent him the book to have a more experienced opinion on it. It's certainly not a known script; some letters resemble Alchemical symbols, others seem deformations of the Enochian alphabet.
I'm busy these days so I had not time to dive into it yet; as soon as I have more information, I'll publish it here.
My friend Pavel Kolsinki has told me about a newly found document, called Antichthon Universalis, written in a strange, unknown language or code, with glyphs similar to those in the Rohonc Codex or other traditional cryptos. It also contains some very bizarre illustrations about plants, animals and what look like very symbolic maps.
For what he tells me, I think it's more like a Codex Seraphinianus than a Voynich manuscript, but let's see. I'm looking forward to seeing some scannings he's about to send me.
Carl Sagan, El Mundo y sus Demonios:
"Mis padres murieron hace años. Yo estaba muy unido a ellos. Todavía los echo terriblemente de menos. Sé que siempre será así. Anhelo creer que su esencia, sus personalidades, lo que tanto amé de ellos, existe –real y verdaderamente- en alguna otra parte. No pediría mucho, sólo cinco o diez minutos al año, por ejemplo, para hablarles de sus nietos, para ponerlos al día de las últimas novedades, para recordarles que los quiero. Hay una parte de mí –por muy infantil que suene- que se pregunta dónde estarán. «¿Os va todo bien?», me gustaría preguntarles. La última palabra que se me ocurrió decirle a mi padre en el momento de su muerte fue: «Cuídate».
"A veces sueño que hablo con mis padres y, de pronto, inmerso todavía en el funcionamiento del sueño, se apodera de mí la abrumadora constatación de que en realidad no murieron, que todo ha sido una especie de error horrible. En fin, están aquí, sanos y salvos, mi padre contando chistes malos, mi madre aconsejándome con total seriedad que me ponga una bufanda porque hace mucho frío. Cuando me despierto emprendo un breve proceso de lamentación. Sencillamente, algo dentro de mí se afan por creer en la vida después de la muerte. Y no tiene el más mínimo interés en saber si hay alguna prueba consistente de que exista."
Sé que no estás en ningún sitio, papá. Pero te echo de menos igual.
The soon to be released, 8bit-like, retro-looking game The Incident looks pretty similar to a game I wrote for the ZX Spectrum back in the 80's, Rubbish Rain (aka Scrollisis). It can be downloaded in Z80 format from my page of ZX Spectrum programs.
It features a character trying to survive and unending cascade of objects falling from the sky. It even includes the player trying to move up/fly by becoming a bubble.
A curious case of prior art (though I'm pretty sure these people do not know my game).
Estas cosas han aparecido en los registros del Apache esta semana.
Lo divertido no es la duda (todos dudamos) sino el cómo se formula.
Respecto a la última: eso digo yo.
Y, en general, todo tipo de cosas de las que pueda haber o imaginarse un tríptico.
Confieso que la de las «nubes de coronado» me tiene intrigado.
Los algoritmos de Google han debido mejorar, porque estas cosas aparecen mucho menos que antes.
La última tiene gracia: es algo que la gente busca mucho. Y claro, todos acaban en mi dibujo Cum Speculum In Enigmate.
La torpeza es creativa:
De aquí he quitado todos los destrozos hechos por malas conversiones entre juegos de caracteres; si no, la lista sería infinita.
Lo dirás tú. Pero cuando ocurra, hay que
C:\WINDOWS\system32\OGAAddin.dll a OGAAddin2.dll.
A partir de ese momento, MS Office 2007 ya es original.
Otra opción es usar OpenOffice.org, pero será como cambiar a Leatherface por Hannibal Lecter.
To see all preprocessor macros defined by GCC, type
echo | gcc -E -dM -
Fuck you, Apple. Your interface is shit no matter what your fanboys say.
All this is for the touch wheel ones, never used one of these new touch thingies. Yes, I'm an old fart.
When you talk about Entering an URL, you are implying that it's a real URL, that is, a string prefixed by an URL schema (the http+colon+slash+slash funny gibberish). By fixing this in your 'Import blog' option in your Notes application you can save several minutes of time to insignificant morons like me.
Or may be this is just a problem in the spanish translation.
The crappy way: Alt-174 for « and Alt-175 for ».
The more definitive, but not at all not cumbersome way: download a thing called Microsoft Keyboard Layout Creator from http://www.microsoft.com/downloads/details.aspx?familyid=FB7B3DCD-D4C1-4943-9C74... and create your own keyboard layout, probably using a standard one as template. This program will prepare a .msi installer for you. After executing it go to Control Panel and set your layout as the default one.
You most probably want to set « to AltGr-Z and » to AltGr-X, as any Linux user know and love.
Or take my spanish keyboard layout: keybspao.msi with source keybspao.klc.
Update: If you use Windows Vista, you'll need at least Microsoft Keyboard Layout Creator 1.4. My keyboard layout source file is still functional, but you need one of this installers instead:
I use mod_rewrite intensively on this site, mainly to make the
transition from the old static files layout to this new, dynamic one
based on my Gruta CMS. Following the premise that
URLs must be eternal, I've
used mod_rewrite magic to make old URLs like
http://triptico.com/software/mp.html
still be accesible, but be interally redirected to
http://triptico.com/?t=STORY;topic=software;id=mp
Anyway, it may prove useful to only do this redirection if a file with that path and name does not already exist in the filesystem. This can be used, for example, to serve special, manually crafted HTML pages, statistics made by other software, or to 'freeze' a special page to avoid too much server load.
So these are the magic words:
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f
RewriteRule ^ %{DOCUMENT_ROOT}%{REQUEST_URI} [L]
They must be entered before any other rewriting directives.
What they mean is, if a file exists (-f) with a path formed by the
site's document root plus the requested uri, rewrite the query to it and
stop rewriting ([L]).
File locking in Perl is done with the flock() function. It's portable among architectures, is advisory-only and locks full files.
It accepts two arguments: a file handle and an operation id. As expected, it allows only one writer or many simultaneous readers, with no wait. Locks are automatically released on closing. The usage is simple:
flock() with the file handle, and a second argument of 1 (if reading) or 2 (if writing).
And that's it. The magic numbers 1 and 2 can also be used as LOCK_* constants imported from the Flock module. The perldoc documentation is comprehensive, take a look at it.
Example reader:
open F, 'index.db'; # open for reading
# lock file. If a writer has it locked, it will
# wait until released. Many readers will read the
# file simultaneously without blocking.
flock F, 1;
while (<F>) {
# do things...
}
# lock is released
close F;
And a writer:
open F, '>index.db'; # open for writing # lock file for writing. If there is another reader # or writer using the lock, it will block until # released. flock F, 2; # file is now locked # write stuff to the file... # lock is released; any readers or writers waiting # will unblock and go on with its business close F;
As these locking semantics are advisory-only, anyone can screw everything by writing without locking, so take care.
I store all my git repositories under the same directory, unsurprisingly called ~/git. I needed a way to have a quick list of what I have done in all of them in a given time, so I wrote a script named (probably incorrectly) my-git-metachangelog.sh. This script iterates all subdirectories, finds all that are git repositories, takes a shortlog for all of them, and sorts by date. The fields shown are: date, time, project and the first line of the commit message.
By default, shows the short log for the last 6 months. It accepts an optional unique argument with the number of months to summarize.
This is an example of its output:
2008-12-11 18:25:29 gruta: Changed all POD docum. in templates to head2. 2008-12-11 17:04:37 gruta: New templates 'main_top' and 'main_bottom'. 2008-12-11 10:57:19 grutatxt: The option 'no-pure-verbatim' has been docum. 2008-12-11 10:25:26 grutatxt: Don't move to 'blockquote' if in 'pre' mode. 2008-12-11 10:19:44 grutatxt: Strip bold form head2 documentation. 2008-12-11 10:17:11 grutatxt: 'pod2grutatxt' creates 'NAME' (Closes: #1016). 2008-12-11 10:08:07 grutatxt: Improved header generation in pod2grutatxt. 2008-12-11 09:49:30 grutatxt: New '--no-pure-verbatim' mode (Closes: #1015). 2008-12-10 14:24:06 mp-5.x: Updated TODO. 2008-12-10 07:25:44 gruta: New field 'description' (Closes: #1050). 2008-12-09 20:20:52 mp-5.x: Small documentation tweaks. 2008-12-09 13:47:48 gruta: More comments in templates. 2008-12-07 19:58:33 mp-5.x: New syntax color for special doc. blocks. 2008-12-07 08:42:38 mp-5.x: Version 5.1.1 RELEASED. ...
And the script:
#!/bin/sh
# my-git-metachangelog.sh
# Angel Ortega <angel@triptico.com> - public domain
MONTHS=$1
[ -z "$MONTHS" ] && MONTHS=6
for r in *
do [ -d ${r}/.git ] &&
(cd $r ; git-log --no-merges \
--since="$MONTHS months ago" \
--pretty="format:%ai $r: %s%n")
done | \
grep -v '^$' | sed -e 's/+[0-9][0-9][0-9][0-9] //' | \
sort -r | less
Sometimes is useful to have columns that are automatically created using operations with other ones. Certainly this violates the Relational Model, but sometimes you don't have a choice if the database schema was given to you by a legacy system.
In my case, I found a living system with a table like this:
CREATE TABLE users ( first_name VARCHAR, family_name VARCHAR, full_name VARCHAR PRIMARY KEY );
It's certainly aberrant; the full_name column is just a concatenation of the other two. For additional fun, it's the primary key.
PostgreSQL makes maintaining this monster easier by using triggers.
First, create the following function (this is in plpgsql, but it could be done in any programming language linked to the PostgreSQL engine):
CREATE FUNCTION build_user_full_name_func () RETURNS trigger AS ' BEGIN NEW.full_name = NEW.first_name || '' '' || NEW.family_name; RETURN NEW; END; ' LANGUAGE plpgsql;
What this function does should be obvious: update full_name concatenating the other two columns with a space in between.
The magic is done creating this trigger:
CREATE TRIGGER build_user_full_name_trg BEFORE INSERT OR UPDATE
ON users FOR EACH ROW
EXECUTE PROCEDURE build_user_full_name_func ();
Whenever users is affected by an INSERT or UPDATE, the trigger is called, and full_name (re)built.
If you are having an attack from an IP and want to ban it right now, use this ban_ip script:
ban_ip() { iptables -A INPUT -s $1 -j DROP; }
Just set the following environment variable:
export SDL_VIDEO_X11_DGAMOUSE=0
nif() { echo $1$(expr substr TRWAGMYFPDXBNJZSQVHLCKET $(($1 % 23 + 1)) 1) ; }
Acepta como primer argumento el número de NIF (sin ceros por delante, si los llevara). Útil para añadir a ~/.bashrc.
http://hardware.slashdot.org/article.pl?sid=08/11/06/1549256
The following two interesting tools are referred there:
"par2 is a program for creating and using PAR2 files to detect damage in data files and repair them if necessary. It can be used with any kind of file."
"dvdisaster provides a margin of safety against data loss on CD and DVD media caused by scratches or aging media. It creates error correction data which is used to recover unreadable sectors if the disc becomes damaged at a later time."
Dvdisaster approach is specially interesting, as it can append its error correction information to an existing .iso file, using as much space as available to fill the smallest medium size (CD, DVD or DVD9). That information seems to be invisible, so it does not interfere with the media content.
dvdisaster -i cd.iso -mRS02 -c
Links:
What I use here to emulate static pages:
RewriteEngine On RewriteRule /(img|download)/.* - [L] RewriteRule ^/(.+)/index\.html$ /?t=TOPIC&topic=$1 [PT] RewriteRule ^/(.+)/(.+)\.html$ /?t=STORY&topic=$1&id=$2 [PT] RewriteRule ^/(.+)/$ /?t=TOPIC&topic=$1 [PT] RewriteRule ^/rss\.xml$ /?t=RSS [PT] RewriteRule ^/sitemap\.xml$ /?t=SITEMAP [PT]
In a clone of a remote repository, start a branch to hold your code:
git-checkout -b my-changes
Do your work and commit changes as you like.
When you are happy with your work, create a temporary directory:
mkdir /tmp/patches
Then change back to the master branch and build a set of patches from your branch with git-format-patch:
git-checkout master git-format-patch -n master..my-changes -o /tmp/patches
A bunch of files, one per changeset, have been created in /tmp/patches. Now, use the git-send-email to send them, one per email, to the original author.
git-send-email --no-thread --from me@here --to author@remote /tmp/patches
If author@remote acknowledges your changes, you can just merge your changes to the current master head and delete your temporary branch:
git-merge my-changes git-branch -d my-changes
If author@remote uses mutt, he can move to his working copy, call it and type |git-am on each message.
Git-svn is a useful tool to communicate with a Subversion repository from git. You usually clone a repository with a command like:
git-svn clone svn+ssh://angel@svn.example.com/path/to/prj/trunk prj
And a prj directory is created with a full git repository. Then, you get another people changes with git-svn rebase and commit yours with git-svn dcommit.
It has one drawback, though; authors are mangled to something like
Author: angel <angel@2e99d34b-3c1d-0410-9ca7-923d03b5684e>
which is not only ugly but completely useless.
To map this monstrosity to real user email addresses and names, use the following steps:
First, create the file ~/.gitusers with content like this:
angel = Ángel Ortega <angel@triptico.com> otheruser = Other User <ouser@example.net>
If you converted your SVN repository from CVS with something like cvs2svn you'll also find entries like this:
Author: (no author) <(no author)@2e99d34b-3c1d-0410-9ca7-923d03b5684e>
Those ones can be converted with another line in ~/.gitusers.
(no author) = Really Me <email@example.org>
And now, instead of the usual git-svn clone command, use the following ones:
mkdir prj cd prj git-svn init svn+ssh://angel@svn.example.com/path/to/prj/trunk git config svn.authorsfile ~/.gitusers git-svn fetch
Add this to your ~/.bashrc:
[ -z "$DISPLAY" ] || wmctrl -r :ACTIVE: -b add,maximized_vert,maximized_horz
git config --global user.name "Angel Ortega" git config --global user.email angel@triptico.com
pppd noauth 192.168.33.1:192.168.33.2 \
pty 'ssh root@REMOTE_HOST pppd notty noauth'
The remote host needs a passwordless authorized key.