But before all, I love to learn. For example, I learned many programming languages: C, C++, Objective-C, Python, Java, Perl, awk, bash, zsh, LaTeX, Metapost, camL… And I’ve got the same passion about computer science research, computer security, philosophy and many other things.
+
But before all, I love to learn. For example, I learned many programming languages: C, C++, Objective-C, Python, Java, Perl, awk, bash, zsh, LaTeX, Metapost, camL… And I’ve got the same passion about computer science research, computer security, philosophy and many other things.
@@ -118,7 +118,7 @@
Then I had a post Ph. D. Degree position in the Hubert Curien Laboratory at St-Etienne. My mission consisted to develop a scientific application (SEDiL). This application should be used by biologist and should have a simple and nice user interface.
Sincerely, I don’t understand ack don’t become a common command on all UNIX systems. I can no more live without. For me it is as essential as which or find.
+
Sincerely, I don’t understand ack don’t become a common command on all UNIX systems. I can no more live without. For me it is as essential as which or find.
@@ -71,35 +74,38 @@
One of the my main usage of grep is
-
-grep 'pattern' **/*(.)
-
+
+
+
grep 'pattern' **/*(.)
+
+
Most of time it is enough.
But it is far better with colored output.
ack-grep in Ubuntu does that.
-As I couldn’t install it on my ‘Evil Company Server’,
+As I couldn’t install it on my ‘Evil Company Server’,
I had done one myself in very few lines:
For my team and I it is usable enough.
diff --git a/output/Scratch/en/blog/03_losthighway/03_losthighway_1/index.html b/output/Scratch/en/blog/03_losthighway/03_losthighway_1/index.html
index ff431986f..ccd15282f 100644
--- a/output/Scratch/en/blog/03_losthighway/03_losthighway_1/index.html
+++ b/output/Scratch/en/blog/03_losthighway/03_losthighway_1/index.html
@@ -10,6 +10,7 @@
+
@@ -17,6 +18,8 @@
+
+
@@ -56,7 +59,7 @@
-
Movie’s keys
+
Movie’s keys
@@ -64,32 +67,32 @@
-
In a first, it is clear for me, it is not a fantastic movie. If you follow this line, you’ll face many problem explaining some scenes.
+
In a first, it is clear for me, it is not a fantastic movie. If you follow this line, you’ll face many problem explaining some scenes.
-
My hypothesis is the movie describe the Fred’s representation of reality.
+
My hypothesis is the movie describe the Fred’s representation of reality.
Each of his tries to escape reality will fail.
-
Fred had commited an horrible act, a murder, and try to repair his memory to accepts it. He’ll then create alternative realities.
+
Fred had commited an horrible act, a murder, and try to repair his memory to accepts it. He’ll then create alternative realities.
In a first time he kills his wife (Renee) because he believes she cheated at him.
-
In the second part, he’s weaker and will be manipulated by the blond equivalent of Renee to kill Dick Laurent.
+
In the second part, he’s weaker and will be manipulated by the blond equivalent of Renee to kill Dick Laurent.
In a third part, he kills Dick Laurent
Why this interpretation can be valid?
-
Because of the dialog at the begining of the movie. Cops ask Fred if he’s own a video camera:
+
Because of the dialog at the begining of the movie. Cops ask Fred if he’s own a video camera:
-
“Do you own a video camera?”
-“No, Fred hates them.”
-“I like to remember things my own way.”
-“What do you mean by that?”
-“How I remember them, not necessarily the way they happened.”
+
“Do you own a video camera?”
+“No, Fred hates them.”
+“I like to remember things my own way.”
+“What do you mean by that?”
+“How I remember them, not necessarily the way they happened.”
-
Then, what we see is not reality but the Fred’s perception. Fred is the God of the reality we see. This is why some God/Devil interpretation of the movie works not so bad.
+
Then, what we see is not reality but the Fred’s perception. Fred is the God of the reality we see. This is why some God/Devil interpretation of the movie works not so bad.
Who’s this mysterious man? He tells Fred it’s him who invited him in his house. He’s present at the party and in the house of Fred in the same time. Eyes wide open, looking everything Fred’s doing?
+
Who’s this mysterious man? He tells Fred it’s him who invited him in his house. He’s present at the party and in the house of Fred in the same time. Eyes wide open, looking everything Fred’s doing?
-
It’s a key of the movie. In my humble opinion, I believe it represents the bad part of Fred. Certainly jalousy. If I was catholic, I’ll said he’s Satan. He observe, film but don’t act. He helps Fred to kill Dick Laurent.
+
It’s a key of the movie. In my humble opinion, I believe it represents the bad part of Fred. Certainly jalousy. If I was catholic, I’ll said he’s Satan. He observe, film but don’t act. He helps Fred to kill Dick Laurent.
Fred had let him enter and cannot let him go.
As Iago of Shakespeare is imprisonned by its own jalousy.
The Mysterious Man help Fred doing the acts of violence.
It also force Fred to remember the reality.
-
When he makes love to his wife (Renee), he sees the face of the Mysterious Man instead of his wife’s face. In reality, it’s the same person for Fred. It should be her who’s the origin of his interior badness.
+
When he makes love to his wife (Renee), he sees the face of the Mysterious Man instead of his wife’s face. In reality, it’s the same person for Fred. It should be her who’s the origin of his interior badness.
@@ -173,7 +176,7 @@ It also force Fred to remember the reality.
The second hypothesis seems better. We can make much more interpretation with it. It explain in most part the strange phone call from Dick Laurent to Pete.
-But the first hypothesis remain coherent. And, we should probably make an in depth explanantion using the first hypothesis. And I’m not sure it would be better.
+But the first hypothesis remain coherent. And, we should probably make an in depth explanantion using the first hypothesis. And I’m not sure it would be better.
One of the strength of this movie is to understand there is many other coherent hypothesis. It is an expression of the Rashomon effect. Many different persons could describe in a coherent manner what they saw. But each description contradicts the others.
@@ -85,9 +88,9 @@ But the first hypothesis remain coherent. And, we should probably make an in dep
There is much to tell about this movie. But I believe I put all essential keys here. It is a proof this movie is not a random one.
-
I believe it is essential to remember the “test of Rorschach effet” when watching this movie.
+
I believe it is essential to remember the “test of Rorschach effet” when watching this movie.
-
I’d like to know or opinion ; is my interpration wrong?
+
I’d like to know or opinion ; is my interpration wrong?
...this movie must be watched knowing you'll cannot resolve the solution. At his best you'll can suggest an interpretation close to the one of David Lynch. I believe I had found a coherent interpretation which allow to follow the movie without being totally lost. I believed it can give the keys necessary to make its own idea of the movie...
@@ -72,10 +75,10 @@ Here some of explanations of Lost Highway I found on the Internet:
Fred make a pact with the devil incarnated by the Mysterious Man,
Mysterious Man is a video camera,
-
Just the first part of the story is real. The rest is in the Fred’s imagination,
+
Just the first part of the story is real. The rest is in the Fred’s imagination,
-
and I don’t speak about many point of view found in forums.
+
and I don’t speak about many point of view found in forums.
I finished to find two good site talking about this movie. But none of them still totally convinced me:
@@ -84,24 +87,24 @@ Here some of explanations of Lost Highway I found on the Internet:
the second which state almost the same interpretation about the movie and explain with even more details is on jasonweb
-
Nonetheless, this movie must be watched knowing you’ll cannot resolve the solution. At his best you’ll can suggest an interpretation close to the one of David Lynch.
+
Nonetheless, this movie must be watched knowing you’ll cannot resolve the solution. At his best you’ll can suggest an interpretation close to the one of David Lynch.
I believe I had found a coherent interpretation which allow to follow the movie without being totally lost. I believed it can give the keys necessary to make its own idea of the movie.
The Rorschach test
-
+
leftblogimage(‘rorschach.gif’ , ‘test de Rorschach’)
-
Like the protagonist, everybody see what he want to see in this movie. It is an invitation to think. Watch this movie is a little like watch a Rorschach’s test. What do we see in it? Everybody put its own personnality in the interpretation of the movie.
+
Like the protagonist, everybody see what he want to see in this movie. It is an invitation to think. Watch this movie is a little like watch a Rorschach’s test. What do we see in it? Everybody put its own personnality in the interpretation of the movie.
-
If you are mystic, you’ll see in the mysterious man a devil,
-
If you are more psychanalytics, you’ll see an inconscient part of the protagonist…
+
If you are mystic, you’ll see in the mysterious man a devil,
+
If you are more psychanalytics, you’ll see an inconscient part of the protagonist…
-
Generally, we stay in this movie and we fail explaining everything. There is almost always a point that don’t fit within the interpretation of the movie. This is why trying to find a unique good interpretation of this movie is a mistake.
+
Generally, we stay in this movie and we fail explaining everything. There is almost always a point that don’t fit within the interpretation of the movie. This is why trying to find a unique good interpretation of this movie is a mistake.
-
Interprétation ≠ Explanation
+
Interprétation ≠ Explanation
I give an interpretation and not an explanation. Just to tell my vision of the movie should be very different from yours.
There is certainly many coherent explanations.
@@ -219,7 +222,7 @@ There is certainly many coherent explanations.
Result, my wife would never buy any TV show on iTunes. She don’t like DVD because it is not as easy to buy and to use than to simply download episodes.
+
Result, my wife would never buy any TV show on iTunes. She don’t like DVD because it is not as easy to buy and to use than to simply download episodes.
@@ -74,8 +77,8 @@ Therefore far less money for you EVIL Copyrighter!!!!!
-
My wife won’t see these episodes.
-This is a ‘LOSE-LOSE’ cooperation.
+
My wife won’t see these episodes.
+This is a ‘LOSE-LOSE’ cooperation.
diff --git a/output/Scratch/en/blog/05_git_create_remote_branch/code/git-create-new-branch.sh b/output/Scratch/en/blog/05_git_create_remote_branch/code/git-create-new-branch.sh
index b72b97815..6b36930d3 100644
--- a/output/Scratch/en/blog/05_git_create_remote_branch/code/git-create-new-branch.sh
+++ b/output/Scratch/en/blog/05_git_create_remote_branch/code/git-create-new-branch.sh
@@ -1,4 +1,3 @@
-
#!/usr/bin/env zsh
if (($#<1)); then
diff --git a/output/Scratch/en/blog/05_git_create_remote_branch/index.html b/output/Scratch/en/blog/05_git_create_remote_branch/index.html
index d62006edc..4970151d4 100644
--- a/output/Scratch/en/blog/05_git_create_remote_branch/index.html
+++ b/output/Scratch/en/blog/05_git_create_remote_branch/index.html
@@ -12,6 +12,7 @@
+
@@ -19,6 +20,8 @@
+
+
@@ -63,23 +66,24 @@ branch to be created remotely.
Of course, I suppose origin is already configured.
diff --git a/output/Scratch/en/blog/06_How_I_use_git/code/git-create-new-branch b/output/Scratch/en/blog/06_How_I_use_git/code/git-create-new-branch
index add959c52..4ce31d7cd 100644
--- a/output/Scratch/en/blog/06_How_I_use_git/code/git-create-new-branch
+++ b/output/Scratch/en/blog/06_How_I_use_git/code/git-create-new-branch
@@ -1,4 +1,3 @@
-
#!/usr/bin/env zsh
if (($#<1)); then
diff --git a/output/Scratch/en/blog/06_How_I_use_git/code/git-get-remote-branches b/output/Scratch/en/blog/06_How_I_use_git/code/git-get-remote-branches
index ca1ef8c3b..dd2b3ebc3 100644
--- a/output/Scratch/en/blog/06_How_I_use_git/code/git-get-remote-branches
+++ b/output/Scratch/en/blog/06_How_I_use_git/code/git-get-remote-branches
@@ -1,4 +1,3 @@
-
#!/usr/bin/env zsh
# recup branches not on local
diff --git a/output/Scratch/en/blog/06_How_I_use_git/index.html b/output/Scratch/en/blog/06_How_I_use_git/index.html
index 609f49896..02310d213 100644
--- a/output/Scratch/en/blog/06_How_I_use_git/index.html
+++ b/output/Scratch/en/blog/06_How_I_use_git/index.html
@@ -12,6 +12,7 @@
+
@@ -19,6 +20,8 @@
+
+
@@ -58,7 +61,7 @@
I use Git to manage my personnal projects.
I have a centralized repository which all my computer should synchronize with.
-Unfortunately I didn’t find clearly what I needed on the official Git documentation.
+Unfortunately I didn’t find clearly what I needed on the official Git documentation.
In two words, if you want to use an SVN workflow with Git (and all its advantages) here is how to proceed.
@@ -70,15 +73,18 @@ Unfortunately I didn’t find clearly what I needed on the official Git docu
Initialisation
-
Suppose I’ve got a directory on my local computer containing a project I want to manage via Git. Here what to do:
+
Suppose I’ve got a directory on my local computer containing a project I want to manage via Git. Here what to do:
-
-cd to/project/directory/
+
+
+
cd to/project/directory/
git init
git add
git commit
-
+
+
+
Now all files in the to/project/directory/ are versionned.
@@ -87,31 +93,40 @@ If you want not to follow some just edit the file .gitignore
For now I didn’t compiled it to work also on Tiger and Leopard. I don’t know XCode enought to know how to make the Garbage collector to be disabled on 32 bits version and enabled on 64 bits version.
+
For now I didn’t compiled it to work also on Tiger and Leopard. I don’t know XCode enought to know how to make the Garbage collector to be disabled on 32 bits version and enabled on 64 bits version.
It was a bit difficult to discover these informations. Hope this post helped someone.
Then from my laptop or my local computer I just have to launch the marvelous
-
-ssh -p 443 -D 9050 username@host
-
+
+
+
ssh -p 443 -D 9050 username@host
+
+
+
and a local socks proxy listening on port 9050 is launched. The socks proxy will transfer local requests via the ssh tunnel. Therefore I can surf locally as if I was on my own computer. I can put password and card number without fear the local wifi network to be sniffed. I simply need to configure my web browser to user the socks proxy on localhost and port 9050.
synchronize to a temporary folder then swap the name therefore the website isn’t accessible only during the swap time. It takes only the time of two rename.
+
synchronize to a temporary folder then swap the name therefore the website isn’t accessible only during the swap time. It takes only the time of two rename.
reiterate all operations until they work (for example, renaming).
For now I use rsync which in fact is no more efficient than a simple cp with WebDav. And I should use a method to keep track of elements who have changed. before the publication.
-
In fact when I’m on a Mac, I use Transmit which is very cool and far more efficient than the Finder to synchronize files. After the synchronization, I swap the directories.
+
In fact when I’m on a Mac, I use Transmit which is very cool and far more efficient than the Finder to synchronize files. After the synchronization, I swap the directories.
My script take a -s option in order to make only the swap option. It also take a -a in order to put the new index.html which should point to the new homepage (not the iWeb one).
In order to keep this script working for you, just modify the username by yours (the value of the mobileMeUser).
-# Script synchronisant le site sur me.com
-# normalement, le site est indisponible le moins de temps possible
-# le temps de deux renommages de répertoire
-mobileMeUser="yann.esposito"
-siteName="siteName"
+
#!/usr/bin/env zsh
-# Depending of my hostname the
-if [[ $(hostname)=='ubuntu' ]];then
- iDisk='/mnt/iDisk'
-else
- iDisk="/Volumes/$mobileMeUser"
-fi
+# Script synchronisant le site sur me.com
+# normalement, le site est indisponible le moins de temps possible
+# le temps de deux renommages de répertoire
-root=$HOME/Sites/$siteName
-destRep=$iDisk/Web/Sites/$siteName
+mobileMeUser="yann.esposito"
+siteName="siteName"
-[[ ! -d $root ]] && {
- print -- "$root n'existe pas ; vérifiez la conf">&2;
+# Depending of my hostname the
+if [[ $(hostname) == 'ubuntu' ]]; then
+ iDisk='/mnt/iDisk'
+else
+ iDisk="/Volumes/$mobileMeUser"
+fi
+
+root=$HOME/Sites/$siteName
+destRep=$iDisk/Web/Sites/$siteName
+
+[[ ! -d $root ]] && {
+ print -- "$root n'existe pas ; vérifiez la conf" >&2;
exit 1
}
-[[ ! -d $destRep ]] && {
- print -- "$destRep n'existe pas, veuillez remonter le FS">&2;
+[[ ! -d $destRep ]] && {
+ print -- "$destRep n'existe pas, veuillez remonter le FS" >&2;
exit 1
}
-if [[ $1=='-h' ]];then
- print -- "usage: $0:h [-h|-a|-s]"
- print -- " -a sychronise aussi l'index"
- print -- " -h affiche l'aide"
- print -- " -s swappe simplement les répertoires"
-fi
+if [[ $1 == '-h' ]]; then
+ print -- "usage: $0:h [-h|-a|-s]"
+ print -- " -a sychronise aussi l'index"
+ print -- " -h affiche l'aide"
+ print -- " -s swappe simplement les répertoires"
+fi
-if [[ $1=='-a' ]];then
- print -- "Synchronisation de l'index (${destRep:h})"
- rsync -av $root/index.html ${destRep:h}/index.html
-fi
+if [[ $1 == '-a' ]]; then
+ print -- "Synchronisation de l'index (${destRep:h})"
+ rsync -av $root/index.html ${destRep:h}/index.html
+fi
-print -- "Root = $root"
-print -- "Dest = $destRep"
+print -- "Root = $root"
+print -- "Dest = $destRep"
-if [[ !$1 = '-s' ]];then
- [[ ! -d $destRep.tmp ]] && mkdir $destRep.tmp
- print -P -- "%B[Sync => tmp]%b"
+if [[ ! $1 = '-s' ]]; then
+ [[ ! -d $destRep.tmp ]] && mkdir $destRep.tmp
+ print -P -- "%B[Sync => tmp]%b"
result=1
essai=1
- while (( $result> 0 ));do
- rsync -arv $root/Scratch/ $destRep.tmp
- result=$?
- if (( $result> 0 ));then
- print -P -- "%BEchec du rsync%b (essai n°$essai)">&2
- fi
+ while (( $result > 0 )); do
+ rsync -arv $root/Scratch/ $destRep.tmp
+ result=$?
+ if (( $result > 0 )); then
+ print -P -- "%BEchec du rsync%b (essai n°$essai)" >&2
+ fi
((essai++))
- done
-fi
+ done
+fi
-# SWAP
-print -P -- "%B[Swap des Répertoires (tmp <=> target)]%b"
+# SWAP
+print -P -- "%B[Swap des Répertoires (tmp <=> target)]%b"
essai=1
-while [[ -e $destRep.old ]];do
- print -n -- "suppression de $destRep.old"
- if ((essai>1));then
- print " (essai n°$essai)"
- else
+while [[ -e $destRep.old ]]; do
+ print -n -- "suppression de $destRep.old"
+ if ((essai>1)); then
+ print " (essai n°$essai)"
+ else
print
- fi
+ fi
((essai++))
- \rm -rf $destRep.old
-done
+ \rm -rf $destRep.old
+done
-print -- " renommage du repertoire sandard vers le .old"
+print -- " renommage du repertoire sandard vers le .old"
essai=1
-while [[ -e $destRep ]];do
- mv $destRep$destRep.old
- (($?)) && print -- "Echec du renommage (essai n°$essai)">&2
+while [[ -e $destRep ]]; do
+ mv $destRep $destRep.old
+ (($?)) && print -- "Echec du renommage (essai n°$essai)" >&2
((essai++))
-done
+done
-print -- " renommage du repertoire tmp (nouveau) vers le standard"
-print -P -- " %BSite Indisponible%b $(date)"
+print -- " renommage du repertoire tmp (nouveau) vers le standard"
+print -P -- " %BSite Indisponible%b $(date)"
essai=1
-while [[ ! -e $destRep ]];do
- mv $destRep.tmp $destRep
- (($?)) && print -P -- "%B[Site Indisponible]%b(essai n°$essai) Echec du renommage (mv $destRep.tmp $destRep)">&2
+while [[ ! -e $destRep ]]; do
+ mv $destRep.tmp $destRep
+ (($?)) && print -P -- "%B[Site Indisponible]%b(essai n°$essai) Echec du renommage (mv $destRep.tmp $destRep)" >&2
((essai++))
-done
+done
-print -P -- "\t===\t%BSITE DISPONIBLE%b\t==="
+print -P -- "\t===\t%BSITE DISPONIBLE%b\t==="
-print -- " renommage du repertoire old vers le tmp"
+print -- " renommage du repertoire old vers le tmp"
essai=1
-while [[ ! -e $destRep ]];do
- mv $destRep.old $destRep.tmp
- (($?)) && print -P -- "Echec du renommage n°$essai">&2
+while [[ ! -e $destRep ]]; do
+ mv $destRep.old $destRep.tmp
+ (($?)) && print -P -- "Echec du renommage n°$essai" >&2
((essai++))
-done
+done
+
+print -P -- " publication terminée"
+
In fact this method works for old threads. But it fails to create new post threads. This is why I tried and be conquered by intensedebate, as you can see in the bottom of this page.
-
Remark I didn’t have any comment on my blog when I switched. Therefore my lack of influence was a good thing :-).
+
Remark I didn’t have any comment on my blog when I switched. Therefore my lack of influence was a good thing :-).
@@ -72,7 +75,7 @@
I also know there is a jQuery plugin to make just that. Unfortunately I had some issue with CSS.
-
Now let’s begin.
+
Now let’s begin.
@@ -85,7 +88,7 @@
Why should I want to load the disqus javascript asynchronously?
-
Efficiency: I don’t want my page to wait the complete execution of disqus script to load.
+
Efficiency: I don’t want my page to wait the complete execution of disqus script to load.
More independance: when disqus is down, my page is blocked!
@@ -97,27 +100,33 @@
How?
-
I give a solution with jQuery, but I’m certain it will work with many other js library.
+
I give a solution with jQuery, but I’m certain it will work with many other js library.
If you forget the window.disqus_no_style=true; then your page will be blank. Simply because without this option, the javascript use a document.write action after the document was closed, which cause a complete erasing of it.
@@ -127,7 +136,7 @@
But with this option you still need to provide a CSS. This is why you have to copy the css code from the embed.js file and rewrite it in a CSS file. You can download the CSS I obtained.
-
Now it’s done. I believe all should be fine but I just finished the manip for my own site only 1 hour ago. Therefore there should be some error, tell me if it is the case.
+
Now it’s done. I believe all should be fine but I just finished the manip for my own site only 1 hour ago. Therefore there should be some error, tell me if it is the case.
I made a blog entry about how I tried to integrate Disqus. I had to wait Disqus comment to be displayed before loading correctly my page. This is why I tried to include it in a “non-blocking” way. Unfortunately, I had difficulties to make it works correctly.
+
I made a blog entry about how I tried to integrate Disqus. I had to wait Disqus comment to be displayed before loading correctly my page. This is why I tried to include it in a “non-blocking” way. Unfortunately, I had difficulties to make it works correctly.
Furthermore, it was not trivial to make comment to be shared between multiple version of the same page (each page has three differents representations, one for each language and one more for the multi-language version).
@@ -64,22 +67,28 @@
During the time I tried to integrate Disqus I never tried Intense Debate. Now that I have tried, i must confess it does exactly what I needed.
-
In order to make it fully asynchronous, you’ve just to download their common js and replace the following line:
+
In order to make it fully asynchronous, you’ve just to download their common js and replace the following line:
Add for free buttons like “share to any” and load them asynchronously.
+
Load Asynchronously ; don’t block my website
+
Add for free buttons like “share to any” and load them asynchronously.
Voilà.
diff --git a/output/Scratch/en/blog/2009-09-jQuery-Tag-Cloud/index.html b/output/Scratch/en/blog/2009-09-jQuery-Tag-Cloud/index.html
index fc4077f8e..8551825f8 100644
--- a/output/Scratch/en/blog/2009-09-jQuery-Tag-Cloud/index.html
+++ b/output/Scratch/en/blog/2009-09-jQuery-Tag-Cloud/index.html
@@ -12,6 +12,7 @@
+
@@ -19,6 +20,8 @@
+
+
@@ -59,7 +62,7 @@ All my site is static and pages are generated with
-
@@ -2321,179 +2333,197 @@ But you can easily translate from Ruby to Javascript.
Here is how I generate this using nanoc 2.
-
If you want to make it fully jQuery one, it shouldn’t be
+
If you want to make it fully jQuery one, it shouldn’t be
too difficult, to use my ruby code and translate it into javascript.
In a first time tags correpond of the list of all tags.
-
-deftags
- return@items.tags.join(', ')
-end
-
+
+
+
def tags
+ return @items.tags.join(', ')
+end
+
+
+
A function to create a data structure associating to each
tag its occurence.
-
-# generate an hash tag => number of occurence of tag
-deftagNumber
- tags={}
- @items.eachdo |p|
- if p.tags.nil?
- next
- end
- p.tags.eachdo |t|
- if tags[t]
- tags[t]+=1
- else
- tags[t]=1
- end
- end
- end
- return tags
-end
-
+
+
+
# generate an hash tag => number of occurence of tag
+def tagNumber
+ tags={}
+ @items.each do |p|
+ if p.tags.nil?
+ next
+ end
+ p.tags.each do |t|
+ if tags[t]
+ tags[t]+=1
+ else
+ tags[t]=1
+ end
+ end
+ end
+ return tags
+end
+
+
+
I also need a data structure who associate to each
tag a list of pages (at least url and title).
-
-# generate an hash tag => [ page1, page2 ... ]
-deftagRefs
- tagLinks={}
- @items.eachdo |p|
- if p.tags.nil?
- next
- end
- p.tags.eachdo |t|
- if tagLinks[t].nil?
- tagLinks[t]=[ p ]
- else
- tagLinks[t] <<= p
- end
- end
- end
- return tagLinks
-end
-
+
+
+
# generate an hash tag => [ page1, page2 ... ]
+def tagRefs
+ tagLinks={}
+ @items.each do |p|
+ if p.tags.nil?
+ next
+ end
+ p.tags.each do |t|
+ if tagLinks[t].nil?
+ tagLinks[t]=[ p ]
+ else
+ tagLinks[t] <<= p
+ end
+ end
+ end
+ return tagLinks
+end
+
+
+
Calculate the real size of each tag to be displayed.
I choosen not to use the full range of size for all the tag. Because if no
-tag has more than n (here 10) occurences, then it doesn’t deserve to be
+tag has more than n (here 10) occurences, then it doesn’t deserve to be
of the maximal size.
-
-deftagRealSize
- tags=tagNumber
- max=tags.values.max
- min=tags.values.min
-# size in CSS em.
- minSize=1.0
- maxSize=2.5
- tagSize={}
- tags.eachdo |t,n|
- if ( max == min )
- tagSize[t]=minSize
- else
-# normalized value between 0 and 1
-# if not tag appear more than 10 times,
-# then it cannot have the maximal size
- tagSize[t]=[ ( n - min +0.0 ) / ( max - min ) ,
- (n - min) /10.0 ].min
-# from normalized size to real size
- tagSize[t]=( tagSize[t] ) * (maxSize - minSize) + minSize
- end
- end
- return tagSize
-end
-
+
+
+
def tagRealSize
+ tags=tagNumber
+ max=tags.values.max
+ min=tags.values.min
+ # size in CSS em.
+ minSize=1.0
+ maxSize=2.5
+ tagSize={}
+ tags.each do |t,n|
+ if ( max == min )
+ tagSize[t]=minSize
+ else
+ # normalized value between 0 and 1
+ # if not tag appear more than 10 times,
+ # then it cannot have the maximal size
+ tagSize[t]=[ ( n - min + 0.0 ) / ( max - min ) ,
+ (n - min) / 10.0 ].min
+ # from normalized size to real size
+ tagSize[t]=( tagSize[t] ) * (maxSize - minSize) + minSize
+ end
+ end
+ return tagSize
+end
+
+
+
Finaly a function to generate the XHTML/jQuery code
-
-# generate an XHTML/jQuery code for tag cloud
-deftagCloud
- tagLinks=tagRefs
- tagSize=tagRealSize
-# begin to write the code
- tagCloud=%{<script type="text/javascript">
- $(document).ready( function(){$('.list').hide();} );
- function tagSelected(id) {
- $('.list').hide();
- $('#'+id).fadeIn();
- $('.tag.selected').removeClass('selected');
- $('#tag_'+id).addClass('selected');
-}
- </script><div id="tagcloud">}
-# Creation of the tags <span>
- tagSize.sort{|a,b| a[0].downcase<=> b[0].downcase}.eachdo |t,s|
- tag_in_id=t.gsub(/\W/,'_')
-# HTML protected version of the tag
-# for example, replace ' ' by ' '
- protected=t.gsub(/&/,'&').gsub(//,' ').gsub(/</,'<').gsub(/>/,'>')
- tagCloud <<=%{
- <span style="font-size: #{s}em;"
- class="tag"
- onClick="tagSelected('#{tag_in_id}')"
- id="tag_#{tag_in_id}">
-#{protected}
- </span> }
- end
- tagCloud <<=%{</div><div id="hiddenDivs" >}
-# Creation of the divs containing links associated to a tag.
- tagLinks.eachdo |t,l|
- tag_in_id=t.gsub(/\W/,'_')
- tagCloud <<=%{
- <div id="#{tag_in_id}" class="list">
- <h4>#{t}</h4><ul>}
-# generate the link list
- l.eachdo |p|
- tagCloud <<=%{<li><a href="#{p.path}">#{p.title}</a></li>}
- end
- tagCloud <<=%{</ul></div>}
- end
- tagCloud <<=%{</div>}
- return tagCloud # yeah I know it is not necessary
-end
-
+
+
# generate an XHTML/jQuery code for tag cloud
+def tagCloud
+ tagLinks=tagRefs
+ tagSize=tagRealSize
+
+ # begin to write the code
+ tagCloud=%{<script type="text/javascript">
+ $(document).ready( function(){$('.list').hide();} );
+ function tagSelected(id) {
+ $('.list').hide();
+ $('#'+id).fadeIn();
+ $('.tag.selected').removeClass('selected');
+ $('#tag_'+id).addClass('selected');
+ }
+ </script><div id="tagcloud">}
+ # Creation of the tags <span>
+ tagSize.sort{|a,b| a[0].downcase <=> b[0].downcase}.each do |t,s|
+ tag_in_id=t.gsub(/\W/,'_')
+ # HTML protected version of the tag
+ # for example, replace ' ' by ' '
+ protected=t.gsub(/&/,'&').gsub(/ /,' ').gsub(/</,'<').gsub(/>/,'>')
+ tagCloud <<= %{
+ <span style="font-size: #{s}em;"
+ class="tag"
+ onClick="tagSelected('#{tag_in_id}')"
+ id="tag_#{tag_in_id}">
+ #{protected}
+ </span> }
+ end
+ tagCloud <<= %{</div><div id="hiddenDivs" >}
+ # Creation of the divs containing links associated to a tag.
+ tagLinks.each do |t,l|
+ tag_in_id=t.gsub(/\W/,'_')
+ tagCloud <<= %{
+ <div id="#{tag_in_id}" class="list">
+ <h4>#{t}</h4><ul>}
+ # generate the link list
+ l.each do |p|
+ tagCloud <<= %{<li><a href="#{p.path}">#{p.title}</a></li>}
+ end
+ tagCloud <<= %{</ul></div>}
+ end
+ tagCloud <<= %{</div>}
+ return tagCloud # yeah I know it is not necessary
+end
+
// Change the color when mouse over
-.tag:hover {
- color: #cc0000; }
+.tag:hover {
+ color: #cc0000; }
// Change the color when tag selected
-.tag.selected {
- color: #6c0000; }
+.tag.selected {
+ color: #6c0000; }
// a bit of space and pointer cursor
-.tag {
- cursor: pointer;
- margin-left: .5em;
- margin-right: .5em; }
-
I want to filter a text except some part of it. I can match easily the part I don’t want to be filtered. For example
+
I want to filter a text except some part of it. I can match easily the part I don’t want to be filtered. For example
-
-...
+
+
+
...
text
...
BEGIN not to filter
@@ -71,66 +75,77 @@ END not to filter
...
text
...
-
+
+
+
I searched a better way to do that, but the best I can do is using split and scan.
-
-defallExceptCode( f, content )
-# Beware the behaviour will change if you add
-# parenthesis (groups) to the regexp!
- regexp=/<code[^>]*>.*?<\/code>|<pre[^>]*>.*?<\/pre>/m
- tmp=""
- mem=[]
- content.scan(regexp).eachdo |c|
- mem <<= c
- end
- i=0
- content.split(regexp).eachdo |x|
- tmp <<=send(f,x)
- ifnot mem[i].nil?
- tmp <<= mem[i]
- i+=1
- end
- end
+
+
+
def allExceptCode( f, content )
+ # Beware the behaviour will change if you add
+ # parenthesis (groups) to the regexp!
+ regexp=/<code[^>]*>.*?<\/code>|<pre[^>]*>.*?<\/pre>/m
+ tmp=""
+ mem=[]
+ content.scan(regexp).each do |c|
+ mem <<= c
+ end
+ i=0
+ content.split(regexp).each do |x|
+ tmp <<= send(f,x)
+ if not mem[i].nil?
+ tmp <<= mem[i]
+ i+=1
+ end
+ end
tmp
-end
-
-# !!!!!!!!!! THIS SYNTAX DOES NOT WORK !!!!!!! #
-defallExceptCode( f, content )
- regexp=/<code[^>]*>.*?<\/code>/m
- tmp=""
- content.split(regexp).eachdo |x|
- separator=$&
- tmp <<=send(f,x)
- ifnot separator.nil?
- tmp <<= separator
- end
- end
+
+
+
# !!!!!!!!!! THIS SYNTAX DOES NOT WORK !!!!!!! #
+def allExceptCode( f, content )
+ regexp=/<code[^>]*>.*?<\/code>/m
+ tmp=""
+ content.split(regexp).each do |x|
+ separator=$&
+ tmp <<= send(f,x)
+ if not separator.nil?
+ tmp <<= separator
+ end
+ end
tmp
-end
-
+end
+
+
+
I would expect the split make a search on a regular expression and then give the matched expression into the $& variable. But it is not the case.
Here is my new script, it first create a map which associate to each file its hash. After that it compare this file to the remote one. Then for each different file, update the content.
-
Even with this script I also have some problem. Mostly due to ‘webdav’ issues. For example, renaming a folder work really badly (on Linux at least). I use webdavfs. For example:
+
Even with this script I also have some problem. Mostly due to ‘webdav’ issues. For example, renaming a folder work really badly (on Linux at least). I use webdavfs. For example:
-
-mv folder folder2
-
+
-
It returns OK and I’ve got:
+
mv folder folder2
+
-
-$ ls
+
+
+
It returns OK and I’ve got:
+
+
+
+
$ ls
folder folder2
-
+
-
Booh….
+
-
In order to handle most webdav issues I use a framework in zsh. It handle almost all except the correct renaming of folder. Working on it… Anyway here is the code I use.
In order to handle most webdav issues I use a framework in zsh. It handle almost all except the correct renaming of folder. Working on it… Anyway here is the code I use.
#!/usr/bin/env zsh
function samelineprint {
- print -n -P -- "\r$*"
+ print -n -P -- "\r$*"
}
-# avec 1 essai par seconde: 300 = 5 minutes
+# avec 1 essai par seconde: 300 = 5 minutes
maxessais=300
-# try to create a directory until success
+# try to create a directory until success
function trymkdir {
- target="$1"
- print -- mkdir -p $target
+ target="$1"
+ print -- mkdir -p $target
local essai=1
- while! mkdir -p $target;do
- samelineprint "Echec: essai n°$essai"
+ while ! mkdir -p $target; do
+ samelineprint "Echec: essai n°$essai"
((essai++))
- ((essai>maxessais)) && exit 5
- done
+ ((essai>maxessais)) && exit 5
+ done
print
}
-# try to copy until success
+# try to copy until success
function trycp {
- element="$1"
- target="$2"
- if [[ ! -d ${target:h} ]];then
- trymkdir ${target:h}
- fi
+ element="$1"
+ target="$2"
+ if [[ ! -d ${target:h} ]]; then
+ trymkdir ${target:h}
+ fi
local essai=1
- print -- cp $element$target
- while!\cp $element$target;do
- samelineprint "Echec: essai n°$essai"
+ print -- cp $element $target
+ while ! \cp $element $target; do
+ samelineprint "Echec: essai n°$essai"
((essai++))
- ((essai>maxessais)) && exit 5
- done
+ ((essai>maxessais)) && exit 5
+ done
print
}
-# try to remove until success
+# try to remove until success
function tryrm {
- target="$1"
+ target="$1"
local essai=1
- local options=''
- [[ -d $target ]] && options='-rf'
- print -- rm $options$target
- while! rm $options$target;do
- samelineprint "Echec: essai n°$essai"
+ local options=''
+ [[ -d $target ]] && options='-rf'
+ print -- rm $options $target
+ while ! rm $options $target; do
+ samelineprint "Echec: essai n°$essai"
((essai++))
- ((essai>maxessais)) && exit 5
- done
+ ((essai>maxessais)) && exit 5
+ done
essai=1
- while [[ -e $element ]];do
- samelineprint "rm reussi mais fichier source non disparu n°$essai"
+ while [[ -e $element ]]; do
+ samelineprint "rm reussi mais fichier source non disparu n°$essai"
sleep 1
((essai++))
- ((essai>maxessais)) && exit 5
- done
+ ((essai>maxessais)) && exit 5
+ done
print
}
-# try to rename until success
+# try to rename until success
function tryrename {
- element="$1"
- target="$2"
+ element="$1"
+ target="$2"
local essai=1
- while [[ -e $target ]];do
- samelineprint "Echec n°$essai le fichier $target existe déjà"
+ while [[ -e $target ]]; do
+ samelineprint "Echec n°$essai le fichier $target existe déjà"
((essai++))
- ((essai>maxessais)) && exit 5
+ ((essai>maxessais)) && exit 5
sleep 1
- done
- print -- mv $element$target
- while! mv $element$target;do
- samelineprint "Echec: essai n°$essai"
+ done
+ print -- mv $element $target
+ while ! mv $element $target; do
+ samelineprint "Echec: essai n°$essai"
((essai++))
- ((essai>maxessais)) && exit 4
- done
+ ((essai>maxessais)) && exit 4
+ done
essai=1
- while [[ -e $element ]];do
- samelineprint "mv reussi mais fichier source non disparu n°$essai"
+ while [[ -e $element ]]; do
+ samelineprint "mv reussi mais fichier source non disparu n°$essai"
sleep 1
((essai++))
- ((essai>maxessais)) && exit 5
- done
+ ((essai>maxessais)) && exit 5
+ done
print
}
-# try to move until success
+# try to move until success
function trymv {
- element="$1"
- target="$2"
+ element="$1"
+ target="$2"
local essai=1
- print -- mv $element$target
- while! mv $element$target;do
- samelineprint "Echec: essai n°$essai"
+ print -- mv $element $target
+ while ! mv $element $target; do
+ samelineprint "Echec: essai n°$essai"
((essai++))
- ((essai>maxessais)) && exit 5
- done
+ ((essai>maxessais)) && exit 5
+ done
essai=1
- while [[ -e $element ]];do
- samelineprint "mv reussi mais fichier source non disparu n°$essai"
+ while [[ -e $element ]]; do
+ samelineprint "mv reussi mais fichier source non disparu n°$essai"
sleep 1
((essai++))
- ((essai>maxessais)) && exit 5
- done
+ ((essai>maxessais)) && exit 5
+ done
print
}
-
-
+
+
+
And here is the code on how I synchronize my website. There is a little cryptic code. It correspond a problem caused by the bluecloth filter which is a markdown program made in ruby. Each time my email is written it is transformed differently. This is why I remove this part from the content of each html file. Without it, all my files containing email are different at each regeneration of my website.
-# Script synchronisant le site sur me.com
-# normalement, le site est indisponible le moins de temps possible
-# le temps de deux renommages de répertoire
-# get configuration
-# mostly directories
-source $0:h/config
+
#!/usr/bin/env zsh
-# get trycp function (copy until success)
-source $0:h/webdav-framework
+# Script synchronisant le site sur me.com
+# normalement, le site est indisponible le moins de temps possible
+# le temps de deux renommages de répertoire
-if [[ $1=='-h' ]];then
- print -- "usage : $0:h [-h|-s|-d]"
- print -- " -a sychronise aussi l'index"
- print -- " -h affiche l'aide"
- print -- " -d modification directe (pas de swap)"
- print -- " -s swappe simplement les répertoires"
-fi
+# get configuration
+# mostly directories
+source $0:h/config
-# publication incrementale
+# get trycp function (copy until success)
+source $0:h/webdav-framework
+
+if [[ $1 == '-h' ]]; then
+ print -- "usage : $0:h [-h|-s|-d]"
+ print -- " -a sychronise aussi l'index"
+ print -- " -h affiche l'aide"
+ print -- " -d modification directe (pas de swap)"
+ print -- " -s swappe simplement les répertoires"
+fi
+
+# publication incrementale
function incrementalPublish {
- local ydestRep=$destRep$suffix
- localRef="$srcRep/map.yrf"
- print -- "Creation du fichier de references"
- create-reference-file.sh >$localRef
- remoteRef="/tmp/remoteSiteMapRef.$$.yrf"
- if [[ ! -e "$ydestRep/map.yrf" ]];then
- # pas de fichier de reference sur la cible
- print -- "pas de fichier de reference sur la cible, passage en mode rsync"
+ local ydestRep=$destRep$suffix
+ localRef="$srcRep/map.yrf"
+ print -- "Creation du fichier de references"
+ create-reference-file.sh > $localRef
+ remoteRef="/tmp/remoteSiteMapRef.$$.yrf"
+ if [[ ! -e "$ydestRep/map.yrf" ]]; then
+ # pas de fichier de reference sur la cible
+ print -- "pas de fichier de reference sur la cible, passage en mode rsync"
rsyncPublish
swap
- else
- trycp "$ydestRep/map.yrf""$remoteRef"
+ else
+ trycp "$ydestRep/map.yrf" "$remoteRef"
typeset -U filesToUpdate
- filesToUpdate=( $(diff $localRef$remoteRef| awk '/^[<>]/ {print $2}') )
- if ((${#filesToUpdate} == 1));then
- print -- "Seul le fichier ${filesToUpdate} sera téléversé"
- elif ((${#filesToUpdate}<10));then
- print -- "${#filesToUpdate} fichiers seront téléversés :"
- print -- "${filesToUpdate}"
- else
- print -- "${#filesToUpdate} fichiers seront téléversés"
- fi
- # copy all file with some differences
- # except the map in case of error
- for element in$filesToUpdate;do
- if [[ $element=="/map.yrf" ]];then
- continue
- fi
- if [[ -e $srcRep$element ]];then
- trycp $srcRep$element$ydestRep$element
- else
- tryrm $ydestRep$element
- fi
- done
- # if all went fine, copy the map file
- trycp $srcRep/map.yrf $ydestRep/map.yrf
- # remove the temporary file
- \rm $remoteRef
- # if we have used the tmp directory we swap
- if [[ "$suffix"!="" ]];then
+ filesToUpdate=( $(diff $localRef $remoteRef | awk '/^[<>]/ {print $2}' ) )
+ if ((${#filesToUpdate} == 1)); then
+ print -- "Seul le fichier ${filesToUpdate} sera téléversé"
+ elif ((${#filesToUpdate}<10)); then
+ print -- "${#filesToUpdate} fichiers seront téléversés :"
+ print -- "${filesToUpdate}"
+ else
+ print -- "${#filesToUpdate} fichiers seront téléversés"
+ fi
+ # copy all file with some differences
+ # except the map in case of error
+ for element in $filesToUpdate; do
+ if [[ $element == "/map.yrf" ]]; then
+ continue
+ fi
+ if [[ -e $srcRep$element ]]; then
+ trycp $srcRep$element $ydestRep$element
+ else
+ tryrm $ydestRep$element
+ fi
+ done
+ # if all went fine, copy the map file
+ trycp $srcRep/map.yrf $ydestRep/map.yrf
+ # remove the temporary file
+ \rm $remoteRef
+ # if we have used the tmp directory we swap
+ if [[ "$suffix" != "" ]]; then
swap
- fi
- fi
+ fi
+ fi
}
-# publication via rsync
+# publication via rsync
function rsyncPublish {
result=1
essai=1
- while (( $result> 0 ));do
- print -- rsync -arv $srcRep/ $destRep.tmp
- if ((!testmode));then
- rsync -arv $srcRep/ $destRep.tmp
- fi
- result=$?
- if (( $result> 0 ));then
- print -P -- "%BEchec du rsync%b (essai n°$essai)">&2
- fi
+ while (( $result > 0 )); do
+ print -- rsync -arv $srcRep/ $destRep.tmp
+ if ((!testmode)); then
+ rsync -arv $srcRep/ $destRep.tmp
+ fi
+ result=$?
+ if (( $result > 0 )); then
+ print -P -- "%BEchec du rsync%b (essai n°$essai)" >&2
+ fi
((essai++))
- done
+ done
}
-# swap
+# swap
function swap {
- print -P -- "%B[Directory Swap (tmp <=> target)]%b"
- [[ -e $destRep.old ]] && tryrm $destRep.old
+ print -P -- "%B[Directory Swap (tmp <=> target)]%b"
+ [[ -e $destRep.old ]] && tryrm $destRep.old
- print -- " renommage du repertoire sandard vers le .old"
- tryrename $destRep$destRep.old
+ print -- " renommage du repertoire sandard vers le .old"
+ tryrename $destRep $destRep.old
- print -- " renommage du repertoire tmp (nouveau) vers le standard"
- print -P -- "%B[Site Indisponible]%b $(date)"
- tryrename $destRep.tmp $destRep
- print -P -- "%B[Site Disponible]%b $(date)"
+ print -- " renommage du repertoire tmp (nouveau) vers le standard"
+ print -P -- "%B[Site Indisponible]%b $(date)"
+ tryrename $destRep.tmp $destRep
+ print -P -- "%B[Site Disponible]%b $(date)"
- print -- " renommage du repertoire old vers le tmp"
- tryrename $destRep.old $destRep.tmp
+ print -- " renommage du repertoire old vers le tmp"
+ tryrename $destRep.old $destRep.tmp
- print -P -- " publication terminée"
+ print -P -- " publication terminée"
}
-print -- "Root = $webroot"
-print -- "Dest = $destRep"
+print -- "Root = $webroot"
+print -- "Dest = $destRep"
-if [[ "$1" = "-s" ]];then
+if [[ "$1" = "-s" ]]; then
swap
-else
- if [[ "$1" = "-d" ]];then
- suffix=""
- else
- suffix=".tmp"
- fi
- print -P -- "%BSync%b[${Root:t} => ${destRep:t}$suffix]"
+else
+ if [[ "$1" = "-d" ]]; then
+ suffix=""
+ else
+ suffix=".tmp"
+ fi
+ print -P -- "%BSync%b[${Root:t} => ${destRep:t}$suffix]"
incrementalPublish
-fi
-
-
+fi
+
+
+
This is my way to replace rsync with filesystem not handling it.
-Hope it is usefull. I’ll be happy to hear a way to handle the webdav rename folder problem. This is really annoying.
+Hope it is usefull. I’ll be happy to hear a way to handle the webdav rename folder problem. This is really annoying.
diff --git a/output/Scratch/en/blog/2009-10-30-How-to-handle-evil-IE/code/ie.js b/output/Scratch/en/blog/2009-10-30-How-to-handle-evil-IE/code/ie.js
index 661daa2f2..6b047dbb2 100644
--- a/output/Scratch/en/blog/2009-10-30-How-to-handle-evil-IE/code/ie.js
+++ b/output/Scratch/en/blog/2009-10-30-How-to-handle-evil-IE/code/ie.js
@@ -1,4 +1,3 @@
-
// Remove all CSS I don't want to use on IE
$('link[rel=stylesheet]').each(function(i)
{
diff --git a/output/Scratch/en/blog/2009-10-30-How-to-handle-evil-IE/index.html b/output/Scratch/en/blog/2009-10-30-How-to-handle-evil-IE/index.html
index f914c8435..263109b62 100644
--- a/output/Scratch/en/blog/2009-10-30-How-to-handle-evil-IE/index.html
+++ b/output/Scratch/en/blog/2009-10-30-How-to-handle-evil-IE/index.html
@@ -12,6 +12,7 @@
+
@@ -19,6 +20,8 @@
+
+
@@ -56,38 +59,43 @@
For developer IE is a nightmare. This is why, I use a method to disable my standard CSS and enable a IE only CSS. I use jQuery to accomplish that.
-
-$(document).ready( function() {
- if ($.browser["msie"]) {
- // include the ie.js file
- $('head').append('<script type="text/javascript" src="/js/ie.js"></scr'+'ipt>');
+
+
+
$(document).ready( function() {
+ if ($.browser["msie"]) {
+ // include the ie.js file
+ $('head').append('<script type="text/javascript" src="/js/ie.js"></scr' + 'ipt>');
}
});
-
// Remove all CSS I don't want to use on IE
+$('link[rel=stylesheet]').each(function(i)
{
- if (this.getAttribute('href') =='/css/layout.css')
- this.disabled=true;
- if (this.getAttribute('href') =='/css/shadows.css')
- this.disabled=true;
- if (this.getAttribute('href') =='/css/gen.css')
- this.disabled=true;
+ if (this.getAttribute('href') == '/css/layout.css')
+ this.disabled = true;
+ if (this.getAttribute('href') == '/css/shadows.css')
+ this.disabled = true;
+ if (this.getAttribute('href') == '/css/gen.css')
+ this.disabled = true;
}) ;
-// Append the CSS for IE only
-$('head').append('<link rel="stylesheet" type="text/css" href="/css/ie.css"/>');
+// Append the CSS for IE only
+$('head').append('<link rel="stylesheet" type="text/css" href="/css/ie.css"/>');
-// I also add a message on top of the page
-$('body').prepend('<div id="iemessage"><p><span class="fr"><em>Avec <a href="http://www.firefox.com"> Firefox </a> et <a href="http://www.apple.com/safari">Safari</a> cette page est bien plus jolie !</em></span><span class="en"><em>This page is far nicer with <a href="http://www.firefox.com"> Firefox </a> and <a href="http://www.apple.com/safari">Safari</a>!</em></span></p>.</div>');
+// I also add a message on top of the page
+$('body').prepend('<div id="iemessage"><p><span class="fr"><em>Avec <a href="http://www.firefox.com"> Firefox </a> et <a href="http://www.apple.com/safari">Safari</a> cette page est bien plus jolie !</em></span><span class="en"><em>This page is far nicer with <a href="http://www.firefox.com"> Firefox </a> and <a href="http://www.apple.com/safari">Safari</a>!</em></span></p>.</div>');
-
I believe the goal researched by minimalism is Focus. But I don’t believe minimalism should be the goal. Focus should be the goal, and I believe minimalism isn’t necessary to reach it.
+
I believe the goal researched by minimalism is Focus. But I don’t believe minimalism should be the goal. Focus should be the goal, and I believe minimalism isn’t necessary to reach it.
-
This is why my design is not minimalist, but I decided to remove most of the navigation stuff of all pages of my website. May be I’ll prefer to hide the menu only when you are on blog article. For now, I hide the menu everywhere on the website.
+
This is why my design is not minimalist, but I decided to remove most of the navigation stuff of all pages of my website. May be I’ll prefer to hide the menu only when you are on blog article. For now, I hide the menu everywhere on the website.
@@ -71,57 +74,66 @@
The HTML:
-
-<divid="menuButton"></div>
-<divid="entete">#content of the menu</div>
-
+
+
+
<div id="menuButton"></div>
+<div id="entete">#content of the menu</div>
+
I first tried to integrate queryLoader, but it didn’t fill my needs.
+
I first tried to integrate queryLoader, but it didn’t fill my needs.
The plugin add a black div to hide all the content. But as the script had to be launched at the end of the source code my website show for a small time.
@@ -90,21 +93,25 @@
In a first time, I added at the top of the body the div hiding all the content.
-
-...
-<body>
-<divid="blackpage">
+
+
+
...
+<body>
+<div id="blackpage">
content to display during the loading.
-</div>
+</div>
...
-
-// will hide the menu in 5 seconds
-// if the variable 'last' has not changed its value
-functionautoHideMenu(value) {
- setTimeout(function(){
- if ( last == value ) { hideMenu(); }
- },5000);
+
var last=0;
+
+// will hide the menu in 5 seconds
+// if the variable 'last' has not changed its value
+function autoHideMenu(value) {
+ setTimeout(function(){
+ if ( last == value ) { hideMenu(); }
+ },5000);
}
-$(document).ready( function() {
- // show the menu when the mouse is on
- // the good area
- $('#menuButton').hover(showMenu);
+$(document).ready( function() {
+ // show the menu when the mouse is on
+ // the good area
+ $('#menuButton').hover(showMenu);
- // If the mouse is on the menu change the
- // value of 'last'
- // try to hide the menu when the mouse
- // go out off the menu.
- $('#entete').hover(
- function(){last+=1;},
- function(){autoHideMenu(last);} );
- autoHideMenu(0);
+ // If the mouse is on the menu change the
+ // value of 'last'
+ // try to hide the menu when the mouse
+ // go out off the menu.
+ $('#entete').hover(
+ function(){last+=1;},
+ function(){autoHideMenu(last);} );
+ autoHideMenu(0);
});
-// show / hide menu functions details
+// show / hide menu functions details
-// move to the left
-functionhideMenu() {
- $('#entete').animate({left:"-10em"}, 500 );
+// move to the left
+function hideMenu() {
+ $('#entete').animate({left:"-10em"}, 500 );
}
-// move to right and will try to hide in 5 sec.
-functionshowMenu() {
- $('#entete').animate({left:"0em"}, 500 );
- last+=1;
+// move to right and will try to hide in 5 sec.
+function showMenu() {
+ $('#entete').animate({left:"0em"}, 500 );
+ last+=1;
autoHideMenu(last);
}
-
+
-
Simple and lightweight. No timer (almost), no memory leak, no Date…
+
+
+
Simple and lightweight. No timer (almost), no memory leak, no Date…
Here is a tip, I don’t know why, but I almost always forgot how to do that.
+
Here is a tip, I don’t know why, but I almost always forgot how to do that.
When you want to launch a command and this command should not be killed after you close your terminal. Here is how to accomplish that from command line:
I explain why I had so much difficulties to use Git. There is an “untaught rule” that make hard to work without. Until I read the good document.
+
I explain why I had so much difficulties to use Git. There is an “untaught rule” that make hard to work without. Until I read the good document.
-
“Cheap branches” aren’t designed to be totally isolated branches but rather should follow a “Master Branch”. There is a Standard Workflow to follow. If you don’t follow it, you prepare yourself with some hard time with Git.
+
“Cheap branches” aren’t designed to be totally isolated branches but rather should follow a “Master Branch”. There is a Standard Workflow to follow. If you don’t follow it, you prepare yourself with some hard time with Git.
@@ -72,7 +75,7 @@
I must say I was completely convinced. And the more you learn about DCVS the more you see good reason to use them.
-
I then needed a versioning system for my team. As they were not used to open source versioning system except those heavy, with a GUI and with and administrator†
+
I then needed a versioning system for my team. As they were not used to open source versioning system except those heavy, with a GUI and with and administrator†
After some web searches, I founded three main choices:
After trying each other I chosen Bazaar. It has the simplest User Interface*. My choice was done.
+
After trying each other I chosen Bazaar. It has the simplest User Interface*. My choice was done.
From Bazaar to Git
@@ -91,21 +94,21 @@
After some times, reading on many blogs, I realize Git is far more popular and by influent people.
I then decide to use Git in particular to version this current website.
-But after trying it, I found it difficult and couter intuitive (I’ll speak a work about it later).
+But after trying it, I found it difficult and couter intuitive (I’ll speak a work about it later).
After calling for some help, when I say Bazaar is much simpler to learn, some people answer me that Git:
-
— SO-MUCH-EASY my 12 year old daughter uses it to version its school documents. She has no difficulties at all, creating branches, blah, blah, blah…
+
— SO-MUCH-EASY my 12 year old daughter uses it to version its school documents. She has no difficulties at all, creating branches, blah, blah, blah…
If a 12 years old girl has no problem with Git and I (with my Computer Science Ph.D.) have difficulties to uses it like I want, it is frustrating and humiliating. But what makes Git natural for some people and confusing for me?
-
I finally understood why reading a document I didn’t read before. It was the untaught part of the conception. The part every developer found so natural it is not necessary to say a word about it. But it was not natural for me.
+
I finally understood why reading a document I didn’t read before. It was the untaught part of the conception. The part every developer found so natural it is not necessary to say a word about it. But it was not natural for me.
* - I never really given its chance to Mercurial. The terminology they chosen was too far from the svn one. And I was used to it.
+
* - I never really given its chance to Mercurial. The terminology they chosen was too far from the svn one. And I was used to it.
@@ -113,7 +116,7 @@ But after trying it, I found it difficult and couter intuitive (I’ll speak
-
When you see explanation about branches and DCVS we imagine each branch is totally uncorrelated to each other, except when merging. Everything is magic. This is the “Parallel World” explanation. This way of seeing is explained more in depth in the real good article about branches on betterexplained.
+
When you see explanation about branches and DCVS we imagine each branch is totally uncorrelated to each other, except when merging. Everything is magic. This is the “Parallel World” explanation. This way of seeing is explained more in depth in the real good article about branches on betterexplained.
Git was designed to manage the Linux Kernel. Git was designed using the concept of Patch instead of Parallel Worlds.
@@ -124,11 +127,11 @@ But after trying it, I found it difficult and couter intuitive (I’ll speak
While Git seem base on the Patch model which will implie the creation of Parallel Worlds.
-
I will not argument about which is the best. Just tell my vision of DCVS come from the Parallel World vision and Git was designed the other way‡.
+
I will not argument about which is the best. Just tell my vision of DCVS come from the Parallel World vision and Git was designed the other way‡.
From Theory to Real Life Usage
-
I believe I understood conceptual mechanism under Git. But I had some difficulties with real usage. The worst point, the one I didn’t get before long was because I didn’t get really well the notion of Cheap Branching.
+
I believe I understood conceptual mechanism under Git. But I had some difficulties with real usage. The worst point, the one I didn’t get before long was because I didn’t get really well the notion of Cheap Branching.
What is a Cheap Branch? If like me you come from Bazaar, it is a totally new notion. It is in fact the ability to create a branches all of them using the same directory.
@@ -136,10 +139,10 @@ But after trying it, I found it difficult and couter intuitive (I’ll speak
In theory, Cheap Branches are exactly like Bazaar branches. The word used is Branch and not Cheap Branch. But there is a slight difference between them. A slight difference between a Cloned Branch and a Cheap Branch.
-
A “Standard branch” is what is theoretically a kind of new Parallel World.
+
A “Standard branch” is what is theoretically a kind of new Parallel World.
But Cheap branch was designed to be future Patch for the main branch of the directory/Cloned branch.
-
Of course, I know anybody can state you can totally use Cheap branches as Cloned branches. But they weren’t designed for that. On daily usage, it is a bit uneasy to use it like this.
+
Of course, I know anybody can state you can totally use Cheap branches as Cloned branches. But they weren’t designed for that. On daily usage, it is a bit uneasy to use it like this.
Here how Git cheap branches should be used (for more details see Git for Designers):
@@ -148,11 +151,11 @@ But Cheap branch was designed to be future Patch for the main
creation of a Cheap branch containing differences which have to be patched somewhere in the future into The Great Repository
-
Here’s how you should not use Git:
+
Here’s how you should not use Git:
Get or creation of a repository
-
Create a cheap branch which will never push it’s modification to the main repository.
+
Create a cheap branch which will never push it’s modification to the main repository.
This simple minor difference of point of view confused me a lot.
@@ -170,23 +173,35 @@ And I return exactly in branches Bazaar provided me.
For now, I prefer (from far) Bazaar terminology. They are cleaner and more understandable.
-
bzr revert
-
+
+
+
bzr revert
+
+
Is clearer than
-
git reset --hard HEAD
-
+
+
+
git reset --hard HEAD
+
+
We can tell the same thing about
-
bzr revert -r -3
-
+
+
+
bzr revert -r -3
+
+
which seems preferable to
-
git reset --hard HEAD~3
-
+
+
+
git reset --hard HEAD~3
+
+
Until now, it is not big business. But now, things will go worse.
If we want to revert time on all the tree we use the keyword reset.
@@ -195,34 +210,49 @@ If we want to revert time on all the tree we use the keyword reset.
Now, if I want to revert time on on file. We should naturally imagine the command will be:
-
git reset --hard FILE
-
+
+
+
git reset --hard FILE
+
+
**OF COURSE NOT!**
The solution is:
-
git checkout FILE
-
+
+
+
git checkout FILE
+
+
What? checkout !? Well, ok. I accept. why not?
With Bazaar it is:
-
git revert FILE
-
+
+
+
git revert FILE
+
+
What I personally found far more natural.
But the command to change the current cheap branch is really hard to be accepted (from the User Interface point of view).
With Bazaar it is:
-
cd ../branch
-
+
+
+
cd ../branch
+
+
Well yes. With Bazaar you have to change your directory to change your branch. It needs more disk resources but it is really clear. Which is my current branch, is just a pwd away. For Git here is the command:
-
git checkout branch
-
+
+
+
git checkout branch
+
+
WTF? I believed checkout was the key to get a file in some state (not the entire tree).
@@ -232,15 +262,15 @@ With Bazaar it is:
-
— Try to find the good keyword for this operation
-
— Wrong! Try again!
-
— False, it is not yet right!
+
— Try to find the good keyword for this operation
+
— Wrong! Try again!
+
— False, it is not yet right!
-
That were the Git bad side. But It has many advantages. Once you’ve understood the cheap branching paradigm. All became clearer for me after. Even if there is also some difficulties with the edit of the .git/config files (not user friendly at all).
+
That were the Git bad side. But It has many advantages. Once you’ve understood the cheap branching paradigm. All became clearer for me after. Even if there is also some difficulties with the edit of the .git/config files (not user friendly at all).
-
‡ I must precise that I worked a lot with multi-modal logic and particularly about “Temporal Logics” (linear or not). This is why I was more inclined to see things this way. “Ah ! Just to remember my firsts love with computer science !”
+
‡ I must precise that I worked a lot with multi-modal logic and particularly about “Temporal Logics” (linear or not). This is why I was more inclined to see things this way. “Ah ! Just to remember my firsts love with computer science !”
@@ -257,15 +287,15 @@ Such as working on a fix on a totally isolated branches.
Is Git better than Bazaar?
-
Speaking about features I’ll tell Git is the best.
-But Git was too much in my way. Is was exactly what I didn’t want for my first DCVS.
+
Speaking about features I’ll tell Git is the best.
+But Git was too much in my way. Is was exactly what I didn’t want for my first DCVS.
-
I shouldn’t have had those difficulties about understanding cheap branching which must be a patch. In reality, Git make a difference between the Tree and the Branch. Which is obviously not the case for Bazaar. Conceptually, bazaar is simpler to understand.
+
I shouldn’t have had those difficulties about understanding cheap branching which must be a patch. In reality, Git make a difference between the Tree and the Branch. Which is obviously not the case for Bazaar. Conceptually, bazaar is simpler to understand.
Finally
In conclusion, I use Git more often than Bazaar and I must say, that I have some preferences for Git. However, Git lack hardly clear commands name like revert.
-For now I don’t made alias to correct that. But may be one day I should do that.
+For now I don’t made alias to correct that. But may be one day I should do that.
In consequence of what, the new file, play the role of backup. If you break everything, you can always return in the last state by overwriting your modifications.
-Of course, this method is not very professional and is a bit limited. If you make many modifications, you’ll end with many files with strange names like:
+
When you modify a somehow critical file you don’t want to loose. You copy naturally this file with another name. For example:
-
-fichier_important.c.bak
+
+
$ cp fichier_important.c fichier_important.c.bak
+
+
+
+
In consequence of what, the new file, play the role of backup. If you break everything, you can always return in the last state by overwriting your modifications.
+Of course, this method is not very professional and is a bit limited. If you make many modifications, you’ll end with many files with strange names like:
If you want to make it works correctly, you’ll have to use naming convention. Files take many place even if you modify most of time only some lines.
+
If you want to make it works correctly, you’ll have to use naming convention. Files take many place even if you modify most of time only some lines.
Fortunately, versions system are here to help.
@@ -105,13 +114,13 @@ old.fichier_important.c
Once upon a time versions were managed for each file separately. I think about CVS. Then it naturally appears projects are a coherent set of files. Recover each file separately was a tedious work. This is why versions number passed from files to the entire project.
-
It is therefore possible to say, “I want to get back three days earlier”.
+
It is therefore possible to say, “I want to get back three days earlier”.
-
What gives versions system? (I didn’t mention everything at all)
+
What gives versions system? (I didn’t mention everything at all)
automatic backups: back in time,
@@ -128,14 +137,17 @@ old.fichier_important.c
Version Systems are already useful to manage its own projects. They help to organize and resolve partially backup problems. I say partially because you have to backup your repository on a decent file system. But versions system are really interesting is on projects done by many people.
-
Let’s begin by an example, a two person project ; Alex and Beatrice. On a file containing a Lovecraft’s gods list:
+
Let’s begin by an example, a two person project ; Alex and Beatrice. On a file containing a Lovecraft’s gods list:
-
-Cthulhu
+
+
+
Cthulhu
Shubniggurath
Yogsototh
-
+
+
+
Say Alex is home and modify the file:
<div style="width: 10em; margin-left: auto; margin-right: auto">
@@ -187,7 +199,7 @@ Yogsototh
get without any problem others modifications,
send without any problem its own modifications to others,
-
manage conflicts. I didn’t speak about it, but sometimes a conflict can occur (when two different people modify the same line on a file for example). SVC help to resolve such problem. More on that later,
+
manage conflicts. I didn’t speak about it, but sometimes a conflict can occur (when two different people modify the same line on a file for example). SVC help to resolve such problem. More on that later,
help to know who done what and when.
@@ -199,7 +211,7 @@ Yogsototh
This word became popular only recently about CVS. And it mainly means two things:
-
First, until really recently (SVN), you’ll have to be connected to the distant server to get informations about a project. Like get the history. New decentralized systems work with a local REPOSITORY (directory containing backups and many informations linked to the versions system functionalities). Hence, one can view the history of a project without the need of being connected.
+
First, until really recently (SVN), you’ll have to be connected to the distant server to get informations about a project. Like get the history. New decentralized systems work with a local REPOSITORY (directory containing backups and many informations linked to the versions system functionalities). Hence, one can view the history of a project without the need of being connected.
All instances of a project can live independently.
@@ -212,7 +224,7 @@ Yogsototh
Typical example:
-
I develop my project. I’m ameliorating something. An urgent bug is reported.
+
I develop my project. I’m ameliorating something. An urgent bug is reported.
With a DCVS I can easily, get back to the version with the bug. Fix it. Send the fix. Get back to my feature work. And even, use the fix for the new version with my new feature.
@@ -237,7 +249,7 @@ Yogsototh
To resume
-
Let’s resume what we can easily do with DCVS:
+
Let’s resume what we can easily do with DCVS:
Versions Systems
@@ -263,7 +275,7 @@ Yogsototh
Easily manipulate branches
-
Now let’s see how to obtain all these things easily with Git.
+
Now let’s see how to obtain all these things easily with Git.
Conflicts can arise when you change the same line of code on the same file from another branch you’re merging. It can seems a bit intimidating, but with Git this kind of thing is really simple to handle.
+
Conflicts can arise when you change the same line of code on the same file from another branch you’re merging. It can seems a bit intimidating, but with Git this kind of thing is really simple to handle.
All was done to code and decide how to organize your versions after. In other VCS it is not as natural as in Git.
-
With Git you can depend of many different sources. Then, there is not necessarily a ‘master’ repository where everybody puts its modifications.
+
With Git you can depend of many different sources. Then, there is not necessarily a ‘master’ repository where everybody puts its modifications.
-
What changes the most with Git when you come from SVN, it’s the idea of a centralized project on one server. With Git many people could work on the same project but not necessarily on the same repository as main reference. One can easily fix a bug and send a patch to many different versions of a project.
+
What changes the most with Git when you come from SVN, it’s the idea of a centralized project on one server. With Git many people could work on the same project but not necessarily on the same repository as main reference. One can easily fix a bug and send a patch to many different versions of a project.
[color]
branch = auto
diff = auto
status = auto
@@ -97,24 +107,28 @@ $ sudo port install git-core
lg = log --pretty=oneline --graph
logfull = log --pretty=fuller --graph --stat -p
unstage = reset HEAD
- # there should be an article on what this command do
- uncommit = !zsh -c '"if (($0)); then nb=$(( $0 - 1 )); else nb=0; fi; i=0; while ((i<=nb)); do git revert -n --no-edit HEAD~$i; ((i++)); done; git commit -m \"revert to $0 version(s) back\""'
+ # there should be an article on what this command do
+ uncommit = !zsh -c '"if (($0)); then nb=$(( $0 - 1 )); else nb=0; fi; i=0; while ((i<=nb)); do git revert -n --no-edit HEAD~$i; ((i++)); done; git commit -m \"revert to $0 version(s) back\""'
undomerge = reset --hard ORIG_HEAD
- conflict = !gitk --left-right HEAD...MERGE_HEAD
- # under Mac OS X, you should use gitx instead
- # conflict = !gitx --left-right HEAD...MERGE_HEAD
+ conflict = !gitk --left-right HEAD...MERGE_HEAD
+ # under Mac OS X, you should use gitx instead
+ # conflict = !gitx --left-right HEAD...MERGE_HEAD
[branch]
autosetupmerge = true
-
-
+
+
+
You can achieve the same result using for each entry the command: git config --global. Next, configure your name and your email. For example, if your name is John Doe and your email is john.doe@email.com. Launch the following commands:
-
-$ git config --global user.name John Doe
+
+
+
$ git config --global user.name John Doe
$ git config --global user.email john.doe@email.com
-
+
+
+
Here it is. Base configuration is over. The file containing alias will help to type shorter commands.
If a project is already versionned with Git you should have an URL of the sources. Then use the following command:
-
-$ cd ~/Projets
+
+
+
$ cd ~/Projets
$ git clone git://main.server/path/to/file
-
+
-
If there is no git server but you’ve got an ssh access. Just replace the git://host by ssh://user@host. In order not to type your password each time, use:
+
-
-$ ssh-keygen -t rsa
-
+
If there is no git server but you’ve got an ssh access. Just replace the git://host by ssh://user@host. In order not to type your password each time, use:
+
+
+
+
$ ssh-keygen -t rsa
+
+
+
Reply to question and *do not enter a password. Then copy your keys to the distant server. This is not the safest way to do this. The safest being, using ssh-agent.
Let do a small remark. If you don’t want to version every file. Typically intermediate compilation file, swap files… Then you need to exclude them. Just before launching the git add . command. You need to create a .gitignore file in the root directory of your project. This file will contain all exclude pattern. For example:
+
-
-*.o
+
Let do a small remark. If you don’t want to version every file. Typically intermediate compilation file, swap files… Then you need to exclude them. Just before launching the git add . command. You need to create a .gitignore file in the root directory of your project. This file will contain all exclude pattern. For example:
+
+
+
+
*.o
*.bak
*.swp
*~
-
+
+
+
Now, if you want to create a repository on a distant server, it must not be in bare mode. The repository will contain only versionning informations, but not the files of the project. To achieve that:
-
-$ cd /path/to/local/project
+
+
+
$ cd /path/to/local/project
$ git clone --bare . ssh://server/path/to/project
-
A detailed tutorial of Git for people knowing very few about versions systems. You’ll understand utility of such program and how we use modern version control system. I try to stay as pragmatic as possible.
+
A detailed tutorial of Git for people knowing very few about versions systems. You’ll understand utility of such program and how we use modern version control system. I try to stay as pragmatic as possible.
# get modifications from other
git pull
-# read what was done
+# read what was done
git log
-# Make local changes to files
+# Make local changes to files
hack, hack, hack...
-# list the modified files
+# list the modified files
git status
-# show what I've done
+# show what I've done
git diff
-# tell git to version a new file
+# tell git to version a new file
git add new/file
-# commit its own modifications
-# to its local branch
-git commit -a -m "Fix bug #321"
+# commit its own modifications
+# to its local branch
+git commit -a -m "Fix bug #321"
-# send local modifications to other
+# send local modifications to other
git push
-
+
-
This article is written for people knowing very few about versionning systems. It is also written for those who had didn’t followed progress since CVS or subversion (SVN). This is why, in a first time I’ll explain quickly which are the goal of such systems. Secondly, I’ll explain how to install and configure Git. Then, I give the command for each feature a DCVS must have.
+
+
+
This article is written for people knowing very few about versionning systems. It is also written for those who had didn’t followed progress since CVS or subversion (SVN). This is why, in a first time I’ll explain quickly which are the goal of such systems. Secondly, I’ll explain how to install and configure Git. Then, I give the command for each feature a DCVS must have.
It is unbelievable you cannot filter your call with an iPhone! The only reason I see for that is a negotiation with phone operator to force users to get phone advertising. It is simple unacceptable.
-
I’m a λ iPhone’s user. The only way to filter your call and to manage blacklist is to jailbreak your iPhone. And I don’t want to do that. Then, if like me you find it unacceptable, just write a line to Apple: http://www.apple.com/feedback/iphone.html
+
I’m a λ iPhone’s user. The only way to filter your call and to manage blacklist is to jailbreak your iPhone. And I don’t want to do that. Then, if like me you find it unacceptable, just write a line to Apple: http://www.apple.com/feedback/iphone.html
Why even if I believe git has many bad point I believe it is the best DCVS around to work with. This is why I first tell why I prefer Bazaar over Git. Secondly I’ll talk about the only advantage of git against Bazaar which lead me to prefer it.
+
Why even if I believe git has many bad point I believe it is the best DCVS around to work with. This is why I first tell why I prefer Bazaar over Git. Secondly I’ll talk about the only advantage of git against Bazaar which lead me to prefer it.
@@ -74,7 +77,7 @@
There is two way of perceive version control system. Either you think in term of branches (see the really good article on betterexplained) or think in term of patches. Another way to say that, is weather you concentrate on vertices or on transitions of the graph of possible states of your project.
-
This is the second approach who was behind git and this is the first behind Bazaar. git was created by Linus Torvald in order to close some gap in the version system used to develop the Linux kernel. And patches is a term which is more present than ‘state’ in the development community.
+
This is the second approach who was behind git and this is the first behind Bazaar. git was created by Linus Torvald in order to close some gap in the version system used to develop the Linux kernel. And patches is a term which is more present than ‘state’ in the development community.
I first was convinced by Bazaar. Why? Argument in favor of Bazaar were: user friendly, terminology close to the subversion one. And I tried a bit the two, and it was clearly more natural for me to use Bazaar. But after seeing so many people using git I decided to give it a serious try.
@@ -84,45 +87,63 @@
The first example, checkout is used to make only one thing from the technical point of vue. But from the user perspective, you make many different things with this word. Example:
-
-git checkout pipo
-
+
+
+
git checkout pipo
+
+
+
undo the current modification of the file pipo
-
-git checkout pipo
-
+
+
+
git checkout pipo
+
+
+
change the current branch to the branch pipo
And, like me, you remark, it is exactly the same command to make two completely different things. What occur when you have a pipo branch and a pipo file? By default, it change the current branch. In order to leave the ambiguity you have to use the following syntax:
-
-git checkout ./pipo
-
+
-
Yes, hum…
+
git checkout ./pipo
+
+
+
+
+
Yes, hum…
It works, but it is clearly not really user friendly. Furthermore, checkout had a complete different signification in older CSV like cvs et svn. checkout was used to get a distant project locally.
-
Bazaar terminology is far more natural, because there is no command to change the current branch as there is only one branch per directory. Changing a branch in Bazaar is changing the current directory. I also believe it is the biggest problem of Bazaar, I’ll tell you why. And to undo things in Bazaar:
+
Bazaar terminology is far more natural, because there is no command to change the current branch as there is only one branch per directory. Changing a branch in Bazaar is changing the current directory. I also believe it is the biggest problem of Bazaar, I’ll tell you why. And to undo things in Bazaar:
-
-bzr revert pipo
-
+
+
+
bzr revert pipo
+
+
+
Furthermore, most Bazaar command take a revision number in parameter. For example, to get back 3 versions earlier, it is enough to write:
-
-bzr revert -r -3 pipo
-
+
+
+
bzr revert -r -3 pipo
+
+
+
The git equivalent is far more cryptic:
-
-bzr checkout HEAD~3 pipo
-
+
+
+
bzr checkout HEAD~3 pipo
+
+
+
One more time, Bazaar is far more readable.
@@ -130,65 +151,82 @@ bzr checkout HEAD~3 pipo
with Bazaar:
-
-bzr revert -r -3 pipo
-
+
+
+
bzr revert -r -3 pipo
+
+
+
and with git? git checkout? Of course not! It would be too simple. What we find in the documentation (man) and everywhere on the net:
-
-git reset --hard HEAD~3
-
+
+
+
git reset --hard HEAD~3
+
+
+
Except that this command is horrible. It forget revisions! Then you must use it with prudence. And you cannot tell other people working on the project you discard some changes. If someone had pulled the bad version, you are doomed. This is why you can also use:
Just to keep a backup branch. Without it we can definitively loose the current version HEAD. But some error may rest when there were some addition and deletion of files. The unique way to be really clean without any risk is to use the following command:
for i in $(seq 0 2); do
+ git revert -n --no-edit head~$i;
+done
+git commit -m "reverted 3 versions back"
+
+
+
And with this command this is the only good way to undo things in a project and tell other contributor you reverted something. You simply revert version in backward order.
The rule is simple: NEVER use the git reset command on a version somebody else could have fetched
-
It was said. Discover the best method took me some time. I’d made many different tries. The safer and best way of reverting back your tree is to use this method. If you want to make it automatic just had the following alias in your ~/.gitconfig. Of course this alias will work only on environment having zsh installed. Which is the cas for most UNIX (Ubuntu, Mac OS X…).
+
It was said. Discover the best method took me some time. I’d made many different tries. The safer and best way of reverting back your tree is to use this method. If you want to make it automatic just had the following alias in your ~/.gitconfig. Of course this alias will work only on environment having zsh installed. Which is the cas for most UNIX (Ubuntu, Mac OS X…).
[alias]
+ uncommit = !zsh -c '"if (($0)); then nb=$(( $0 - 1 )); else nb=0; fi; i=0; while ((i<=nb)); do git revert -n --no-edit HEAD~$i; ((i++)); done; git commit -m \"revert to $0 version(s) back\""'
+
+
+
What make git by far the best DCVS today
-
After talking about the negatives points of git, now it’s time to speak about the very positive feature that make git the best DCVS in my humble opinion.
+
After talking about the negatives points of git, now it’s time to speak about the very positive feature that make git the best DCVS in my humble opinion.
Cheap branching
You always work into the same main directory. For example, you can work on two fix in the same time. Say fix1 require you to work on file1 and fix2 to work on file2. You can work in any order on file1 and file2 in the master branch. And then go to branch fix1, commit file1 into it. Then go to branch fix2 and commit file2 into it. And finally merge the two branches fix1 and fix2 into master.
And this is great not to worry about working in the good branch and coding in the same time. You just worry about your code and then about the versionning system.
I just found a way to change the default shell on Mac OS X. This note is mostly for me, but somebody else should find it useful. Just launch the following command:
-if str.match(regexp) and
- not str.match(other_regexp)
+
+
+
if str.match(regexp) and
+ not str.match(other_regexp)
do_something
-
+
+
+
and you have to make this behaviour with only one regular expression.
But, there exists a major problem: the complementary of a regular language might not be regular.
Then, for some expression it is absolutely impossible to negate a regular expression.
-
But sometimes with some simple regular expression it should be possible†. Say you want to match everything containing the some word say bull but don’t want to match bullshit. Here is a nice way to do that:
+
But sometimes with some simple regular expression it should be possible†. Say you want to match everything containing the some word say bull but don’t want to match bullshit. Here is a nice way to do that:
-
-# match all string containing 'bull' (bullshit comprised)
-/bull/
+
-# match all string containing 'bull' except 'bullshit'
-/bull([^s]|$)|
-bulls([^h]|$)|
-bullsh([^i]|$)|
-bullshi([^t]|$)/
+
# match all string containing 'bull' (bullshit comprised)
+/bull/
-# another way to write it would be
-/bull([^s]|$|s([^h]|$)|sh([^i]|$)|shi([^t]|$))/
-
+# match all string containing 'bull' except 'bullshit'
+/bull([^s]|$)|
+bulls([^h]|$)|
+bullsh([^i]|$)|
+bullshi([^t]|$)/
+
+# another way to write it would be
+/bull([^s]|$|s([^h]|$)|sh([^i]|$)|shi([^t]|$))/
+
+
+
Let look closer. In the first line the expression is:
bull([^s]|$), why does the $ is needed?
@@ -95,34 +104,40 @@ contains bull followed by a letter different from s. <
And this is it. I hope it could help you.
Notice this method is not always the best. For example try to write a regular expression equivalent to the following conditional expression:
-
-# Begin with 'a': ^a
-# End with 'a': c$
-# Contain 'b': .*b.*
-# But isn't 'axbxc'
-if str.match(/^a.*b.*c$/) and
- not str.match(/^axbxc$/)
+
+
+
# Begin with 'a': ^a
+# End with 'a': c$
+# Contain 'b': .*b.*
+# But isn't 'axbxc'
+if str.match(/^a.*b.*c$/) and
+ not str.match(/^axbxc$/)
do_something
-end
-
This solution uses the maximal length of the string not to be matched.
There certainly exists many other methods. But the important lesson is
it is not straightforward to exclude something of a regular expression.
In my previous post I had given some trick to match all except something. On the same idea, the trick to match the smallest possible string. Say you want to match the string between ‘a’ and ‘b’, for example, you want to match:
+
In my previous post I had given some trick to match all except something. On the same idea, the trick to match the smallest possible string. Say you want to match the string between ‘a’ and ‘b’, for example, you want to match:
The next natural way, is to change the greediness. But it is not enough as you will match from the first a to the first b.
-Then a simple constatation is that our matching string shouldn’t contain any a nor b. Which lead to the last elegant solution.
+Then a simple constatation is that our matching string shouldn’t contain any a nor b. Which lead to the last elegant solution.
/a[^ab]*b/
@@ -85,64 +88,82 @@ a.....a......b..b..a....Until now, that was, easy.
Now, just pass at the case you need to match not between a and b, but between strings.
For example:
-
-<li>...<li>
-
+
+
+
<li>...<li>
+
+
+
This is a bit difficult. You need to match
-
-<li>[anything not containing <li>]</li>
-
+
+
+
<li>[anything not containing <li>]</li>
+
+
+
The first method would be to use the same reasoning as in my previous post. Here is a first try:
-
-<li>([^<]|<[^l]|<l[^i]|<li[^>])*</li>
-
+
+
+
<li>([^<]|<[^l]|<l[^i]|<li[^>])*</li>
+
+
+
But what about the following string:
-
-<li>...<li</li>
-
+
-
That string should not match. This is why if we really want to match it correctly† we need to add:
Yes a bit complicated. But what if the string I wanted to match was even longer?
Here is the algorithm way to handle this easily. You reduce the problem to the first one letter matching:
-
-# transform a simple randomly choosen character
-# to an unique ID
-# (you should verify the identifier is REALLY unique)
-# beware the unique ID must not contain the
-# choosen character
-s/X/_was_x_/g
-s/Y/_was_y_/g
+
-# transform the long string in this simple character
-s/<li>/X/g
-s/<\/li>/Y/g
+
# transform a simple randomly choosen character
+# to an unique ID
+# (you should verify the identifier is REALLY unique)
+# beware the unique ID must not contain the
+# choosen character
+s/X/_was_x_/g
+s/Y/_was_y_/g
-# use the first method
-s/X([^X]*)Y//g
+# transform the long string in this simple character
+s/<li>/X/g
+s/<\/li>/Y/g
-# retransform choosen letter by string
-s/X/<li>/g
-s/Y/<\/li>/g
+# use the first method
+s/X([^X]*)Y//g
-# retransform the choosen character back
-s/_was_x_/X/g
-s/_was_y_/Y/g
-
+# retransform choosen letter by string
+s/X/<li>/g
+s/Y/<\/li>/g
+
+# retransform the choosen character back
+s/_was_x_/X/g
+s/_was_y_/Y/g
+
+
+
And it works in only 9 lines for any beginning and ending string. This solution should look less I AM THE GREAT REGEXP M45T3R, URAN00B, but is more convenient in my humble opinion. Further more, using this last solution prove you master regexp, because you know it is difficult to manage such problems with only a regexp.
-
† I know I used an HTML syntax example, but in my real life usage, I needed to match between en: and ::. And sometimes the string could finish with e::.
+
† I know I used an HTML syntax example, but in my real life usage, I needed to match between en: and ::. And sometimes the string could finish with e::.
Strangely enough, I didn’t find any built-in tool to split a file by keyword. I made one myself in awk. I put it here mostly for myself. But it could also helps someone else.
+
Strangely enough, I didn’t find any built-in tool to split a file by keyword. I made one myself in awk. I put it here mostly for myself. But it could also helps someone else.
The following code split a file for each line containing the word UTC.
At first sight I believed that the regexp should be faster than the split because it could be many . in a filename. But in reality, most of time there is only one dot and I realized the split will be faster. But not the fastest way. There is a function dedicated to this work in the File module.
An arrow from A to B means, you can merge A in B. If there is no arrow from A to B that means it is forbidden to merge A in B. Here is the corresponding rubycode:
-# architecture
-#
-# master <-> dev
-# master -> client
-# clien -> clientA | clientB
-#
-# merge using two of these branches should be
-# restricted to these rules
-# merge to one of these branch and an unknown one should
-# raise a warning, and may the option to add this new branch
-# to the hierarchy
-$architecture={
- :master => [ :dev, :client ],
- :dev => [ :master ],
- :client => [ :clientA, :clientB ] }
+
#!/usr/bin/env ruby
+# encoding: utf-8
-defget_current_branch()
- (`git branch --no-color | awk '$1 == "*" {print $2}'`).chop.intern
-end
+# architecture
+#
+# master <-> dev
+# master -> client
+# clien -> clientA | clientB
+#
+# merge using two of these branches should be
+# restricted to these rules
+# merge to one of these branch and an unknown one should
+# raise a warning, and may the option to add this new branch
+# to the hierarchy
-ifARGV.length==0
- puts %{usage: $0:t [git_command or local_command]
-
-local commands:
- allmerges: merge from top to down}
- exit 0
-end
+$architecture={
+ :master => [ :dev, :client ],
+ :dev => [ :master ],
+ :client => [ :clientA, :clientB ] }
-require'set'
-$known_branches=Set.new
-$architecture.eachdo |k,v|
- $known_branches.add(k)
- v.each { |b| $known_branches.add(b) }
-end
+def get_current_branch()
+ (`git branch --no-color | awk '$1 == "*" {print $2}'`).chop.intern
+end
-defrec_merge(branch)
- if$architecture[branch].nil?
- return
- end
- $architecture[branch].eachdo |b|
- if$flag.has_key?(b.to_s+ branch.to_s)
- next
- end
- flagname=branch.to_s+ b.to_s
- if$flag.has_key?(flagname)
- next
- end
- if system %{eng checkout #{b}}
- if get_current_branch != b
- puts "Can't checkout to #{b}"
- exit 2
- end
- if system %{eng merge #{branch}}
- $flag[flagname]=true
- rec_merge(b)
- else
- exit 1
- end
- else
- exit 1
- end
- end
-end
+if ARGV.length == 0
+ puts %{usage: $0:t [git_command or local_command]
+
+local commands:
+ allmerges: merge from top to down}
+ exit 0
+end
-defdo_all_merges
- puts 'Will merge from father to sons'
- current_branch=get_current_branch
- $flag={}
- rec_merge(:master)
- system %{git co #{current_branch}}
-end
+require 'set'
+$known_branches=Set.new
+$architecture.each do |k,v|
+ $known_branches.add(k)
+ v.each { |b| $known_branches.add(b) }
+end
-defdo_merge
- current_branch=get_current_branch
- src_branch=ARGV[1].intern
- puts %{do_merge: #{src_branch} => #{current_branch}}
- if$known_branches.include?(current_branch)
- if$known_branches.include?(src_branch)
- if$architecture.has_key?(src_branch) and
- $architecture[src_branch].include?(current_branch)
- system %{git merge #{src_branch}}
- else
- puts %{Forbidden merge: #{src_branch} => #{current_branch}}
- end
- else
- puts %{Warning! #{src_branch} not mentionned in rb configuration}
- sleep 2
- system %{git merge #{src_branch}}
- puts %{Warning! #{src_branch} not mentionned in rb configuration}
- end
- end
-end
+def rec_merge(branch)
+ if $architecture[branch].nil?
+ return
+ end
+ $architecture[branch].each do |b|
+ if $flag.has_key?(b.to_s + branch.to_s)
+ next
+ end
+ flagname=branch.to_s + b.to_s
+ if $flag.has_key?(flagname)
+ next
+ end
+ if system %{eng checkout #{b}}
+ if get_current_branch != b
+ puts "Can't checkout to #{b}"
+ exit 2
+ end
+ if system %{eng merge #{branch}}
+ $flag[flagname]=true
+ rec_merge(b)
+ else
+ exit 1
+ end
+ else
+ exit 1
+ end
+ end
+end
-caseARGV[0]
- when'allmerges'then do_all_merges
- when'merge'then do_merge
- else system %{git #{ARGV.join('')}}
-end
-
-
+def do_all_merges
+ puts 'Will merge from father to sons'
+ current_branch=get_current_branch
+ $flag={}
+ rec_merge(:master)
+ system %{git co #{current_branch}}
+end
+
+def do_merge
+ current_branch=get_current_branch
+ src_branch=ARGV[1].intern
+ puts %{do_merge: #{src_branch} => #{current_branch}}
+ if $known_branches.include?(current_branch)
+ if $known_branches.include?(src_branch)
+ if $architecture.has_key?(src_branch) and
+ $architecture[src_branch].include?(current_branch)
+ system %{git merge #{src_branch}}
+ else
+ puts %{Forbidden merge: #{src_branch} => #{current_branch}}
+ end
+ else
+ puts %{Warning! #{src_branch} not mentionned in rb configuration}
+ sleep 2
+ system %{git merge #{src_branch}}
+ puts %{Warning! #{src_branch} not mentionned in rb configuration}
+ end
+ end
+end
+
+case ARGV[0]
+ when 'allmerges' then do_all_merges
+ when 'merge' then do_merge
+ else system %{git #{ARGV.join(' ')}}
+end
+
+
+
All you need to do to make it work is simply to copy eng in a directory contained in your PATH.
The more you wait to do something, the more difficult it is to start doing it.
-
I had to write another post for this blog. I had added many article idea in my todolist. But, I made many other things, and I’ve always said (until now), I’ll do this later. What changed my mind is the haunt of this simple remark about how to be productive in programming.
+
I had to write another post for this blog. I had added many article idea in my todolist. But, I made many other things, and I’ve always said (until now), I’ll do this later. What changed my mind is the haunt of this simple remark about how to be productive in programming.
> Stop write TODO in your code and make it now!
-> You’ll be surprised by the results.
+> You’ll be surprised by the results.
In short:
> Just do it! ou Juste fait le comme auraient dit les nuls.
-
Finally I’ll certainly write blog post more often for a short period of time.
+
Finally I’ll certainly write blog post more often for a short period of time.
What did I do?
@@ -77,7 +80,7 @@
I also have a real life. I enjoyed some vacancies with my family.
-
I work with Luc on a simple ruby REST/JSON/API oriented framework. It works fairly well, with really few bug until now. We planify to make a simple todolist tutorial. May be in two to three blog posts. This framework is not public for now. It will certainly be after we’ll create some simple web service with it and made a nice website for it.
+
I work with Luc on a simple ruby REST/JSON/API oriented framework. It works fairly well, with really few bug until now. We planify to make a simple todolist tutorial. May be in two to three blog posts. This framework is not public for now. It will certainly be after we’ll create some simple web service with it and made a nice website for it.
There is some random in some of these achivement mostly because they don’t depend totally on me.
+
There is some random in some of these achivement mostly because they don’t depend totally on me.
diff --git a/output/Scratch/en/blog/2010-05-19-How-to-cut-HTML-and-repair-it/code/repair_xml.rb b/output/Scratch/en/blog/2010-05-19-How-to-cut-HTML-and-repair-it/code/repair_xml.rb
index 1121d4ef1..bc18f6ccd 100644
--- a/output/Scratch/en/blog/2010-05-19-How-to-cut-HTML-and-repair-it/code/repair_xml.rb
+++ b/output/Scratch/en/blog/2010-05-19-How-to-cut-HTML-and-repair-it/code/repair_xml.rb
@@ -1,4 +1,3 @@
-
# repair cutted XML code by closing the tags
# work even if the XML is cut into a tag.
# example:
diff --git a/output/Scratch/en/blog/2010-05-19-How-to-cut-HTML-and-repair-it/index.html b/output/Scratch/en/blog/2010-05-19-How-to-cut-HTML-and-repair-it/index.html
index 7b211f2bb..4eafea2f7 100644
--- a/output/Scratch/en/blog/2010-05-19-How-to-cut-HTML-and-repair-it/index.html
+++ b/output/Scratch/en/blog/2010-05-19-How-to-cut-HTML-and-repair-it/index.html
@@ -12,6 +12,7 @@
+
@@ -19,6 +20,8 @@
+
+
@@ -62,104 +65,100 @@
Here is an example:
-
-<divclass="corps">
- <divclass="intro">
- <p>Introduction</p>
- </div>
- <p>The first paragraph</p>
- <imgsrc="/img/img.png"alt="an image"/>
- <p>Another long paragraph</p>
-</div>
-
In fact, it is not as difficult as it should sound first. The secret is, you don’t need to keep the complete tree structure to repair it, but only the list of not closed parents.
+
In fact, it is not as difficult as it should sound first. The secret is, you don’t need to keep the complete tree structure to repair it, but only the list of not closed parents.
Given with our example, when we are after the first paragraph. we only have to close the div for class corps and the XML is repaired. Of course, when you cut inside a tag, you sould go back, as if you where just before it. Delete this tag and all is ok.
Then, all you have to do, is not remember all the XML tree, but only the heap containing your parents. Suppose we treat the complete first example, the stack will pass through the following state, in order:
The algorihm, is then really simple:
-<pre class="twilight">
-let res be the XML as a string ;
+
The algorihm, is then really simple:
+
+
let res be the XML as a string ;
read res and each time you encouter a tag:
if it is an opening one:
push it to the stack
else if it is a closing one:
- pop the stack.
+ pop the stack.
-
remove any malformed/cutted tag in the end of res
+remove any malformed/cutted tag in the end of res
for each tag in the stack, pop it, and write:
- res = res + closed tag
+ res = res + closed tag
-
return res
-</pre>
+return res
+
And res contain the repaired XML.
Finally, this is the code in ruby I use. The xml variable contain the cutted XML.
-# repair cutted XML code by closing the tags
-# work even if the XML is cut into a tag.
-# example:
-# transform '<div> <span> toto </span> <p> hello <a href="http://tur'
-# into '<div> <span> toto </span> <p> hello </p></div>'
-defrepair_xml( xml )
- parents=[]
- depth=0
- xml.scan( %r{<(/?)(\w*)[^>]*(/?)>} ).eachdo |m|
- if m[2] =="/"
- next
- end
- if m[0] ==""
- parents[depth]=m[1]
- depth+=1
- else
- depth-=1
- end
- end
- res=xml.sub(/<[^>]*$/m,'')
- depth-=1
- depth.downto(0).each { |x| res<<=%{</#{parents[x]}>} }
- res
-end
-
I don’t know if the code can help you, but the raisonning should definitively be known.
+
# repair cutted XML code by closing the tags
+# work even if the XML is cut into a tag.
+# example:
+# transform '<div> <span> toto </span> <p> hello <a href="http://tur'
+# into '<div> <span> toto </span> <p> hello </p></div>'
+def repair_xml( xml )
+ parents=[]
+ depth=0
+ xml.scan( %r{<(/?)(\w*)[^>]*(/?)>} ).each do |m|
+ if m[2] == "/"
+ next
+ end
+ if m[0] == ""
+ parents[depth]=m[1]
+ depth+=1
+ else
+ depth-=1
+ end
+ end
+ res=xml.sub(/<[^>]*$/m,'')
+ depth-=1
+ depth.downto(0).each { |x| res<<= %{</#{parents[x]}>} }
+ res
+end
+
+
+
I don’t know if the code can help you, but the raisonning should definitively be known.