diff --git a/Rules b/Rules index fd19960a0..28a46170d 100644 --- a/Rules +++ b/Rules @@ -14,25 +14,25 @@ compile '/css/*' do filter :rainpress end route '/css/*' do - '/Scratch/assets' + item.identifier.chop + '.css' + '/n3blog/assets' + item.identifier.chop + '.css' end compile '/img/*' do end route '/img/*' do - '/Scratch/assets' + item.identifier.chop + '.png' + '/n3blog/assets' + item.identifier.chop + '.png' end compile '/css/raw/*' do end route '/css/raw/*' do - '/Scratch' + item.identifier.sub(/raw\//,'').chop + '.css' + '/n3blog' + item.identifier.sub(/raw\//,'').chop + '.css' end # JS compile '/js/*' do end route '/js/*' do - '/Scratch/assets' + item.identifier.chop + '.js' + '/n3blog/assets' + item.identifier.chop + '.js' end compile '/html' do @@ -81,7 +81,7 @@ compile '/html/*' do end route '/html/*' do - '/Scratch' + item.identifier.sub('/html','') + 'index.html' + '/n3blog' + item.identifier.sub('/html','') + 'index.html' end # feed @@ -90,17 +90,17 @@ compile '/xml/*' do end route '/xml/en/*' do - '/Scratch/en/blog/feed/feed.xml' + '/n3blog/en/blog/feed/feed.xml' end route '/xml/fr/*' do - '/Scratch/fr/blog/feed/feed.xml' + '/n3blog/fr/blog/feed/feed.xml' end compile '/sitemap/*' do layout 'sitemap' end route '/sitemap/*' do - '/Scratch/sitemap.xml' + '/n3blog/sitemap.xml' end layout '*', :erb diff --git a/config.yaml b/config.yaml index 47a40d1b8..cc4403483 100644 --- a/config.yaml +++ b/config.yaml @@ -5,7 +5,7 @@ data_sources: type: filesystem_unified output_dir: output ultraviolet_theme: "twilight" -webprefix: "/Scratch" +webprefix: "/n3blog" base_url: "http://yannesposito.com" author_uri: "http://yannesposito.com" rss_uri: diff --git a/content/html/en/about.md b/content/html/en/about.md index cb899c88d..1ad941c3c 100644 --- a/content/html/en/about.md +++ b/content/html/en/about.md @@ -5,7 +5,7 @@ menupriority: 4 ## To better know me -![Une photo de moi](/Scratch/img/about/yann1.jpg) +![Une photo de moi](/n3blog/img/about/yann1.jpg)
diff --git a/content/html/en/about/contact.md b/content/html/en/about/contact.md index 697e08783..b6003f13b 100644 --- a/content/html/en/about/contact.md +++ b/content/html/en/about/contact.md @@ -4,7 +4,7 @@ menupriority: 1 ----- # How to contact me -Avatar +Avatar <%= mail_perso %> Follow me on [twitter](http://twitter.com/yogsototh) diff --git a/content/html/en/about/cv.erb b/content/html/en/about/cv.erb index 6a2ba787b..f3fa94373 100644 --- a/content/html/en/about/cv.erb +++ b/content/html/en/about/cv.erb @@ -16,8 +16,8 @@ menupriority: 3 -----
- - preview cv + + preview cv ↓ pdf version
diff --git a/content/html/en/blog.erb b/content/html/en/blog.erb index 42657d540..43c2e244e 100644 --- a/content/html/en/blog.erb +++ b/content/html/en/blog.erb @@ -7,7 +7,7 @@ noSubMenu: true <% number_of_articles=5 number_of_char_for_resume=800 - language=@item_rep.path.sub(/\/Scratch\//,'').sub(/\/.*$/,'') + language=@item_rep.path.sub(/\/n3blog\//,'').sub(/\/.*$/,'') last_articles = @items.select do |a| a.reps[0].path =~ /\/#{language}\// && a[:kind] == 'article' end diff --git a/content/html/en/blog/06_How_I_use_git.md b/content/html/en/blog/06_How_I_use_git.md index c054ec9fe..f90174f1d 100644 --- a/content/html/en/blog/06_How_I_use_git.md +++ b/content/html/en/blog/06_How_I_use_git.md @@ -47,10 +47,10 @@ for example mine is: *.swp .DS_Store ikog.py.bak -output/Scratch/assets -output/Scratch/en -output/Scratch/fr -output/Scratch/multi +output/n3blog/assets +output/n3blog/en +output/n3blog/fr +output/n3blog/multi
diff --git a/content/html/en/blog/10_Synchronize_Custom_WebSite_with_mobileMe.md b/content/html/en/blog/10_Synchronize_Custom_WebSite_with_mobileMe.md index 33a8abc1e..ac116699f 100644 --- a/content/html/en/blog/10_Synchronize_Custom_WebSite_with_mobileMe.md +++ b/content/html/en/blog/10_Synchronize_Custom_WebSite_with_mobileMe.md @@ -19,7 +19,7 @@ tags: # Update (2009/10/28) -I [updated my script](/Scratch/en/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-) which is now incremental. Since the writing of this article, Apple(c) had made many efforts about the bandwith of its European servers. +I [updated my script](/n3blog/en/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-) which is now incremental. Since the writing of this article, Apple(c) had made many efforts about the bandwith of its European servers. newcorps @@ -116,7 +116,7 @@ if [[ ! $1 = '-s' ]]; then result=1 essai=1 while (( $result > 0 )); do - rsync -arv $root/Scratch/ $destRep.tmp + rsync -arv $root/n3blog/ $destRep.tmp result=$? if (( $result > 0 )); then print -P -- "%BEchec du rsync%b (essai n°$essai)" >&2 @@ -222,7 +222,7 @@ if [[ ! $1 = '-s' ]]; then result=1 essai=1 while (( $result > 0 )); do - rsync -arv $root/Scratch/ $destRep.tmp + rsync -arv $root/n3blog/ $destRep.tmp result=$? if (( $result > 0 )); then print -P -- "%Brsync failed%b (try n°$essai)" >&2 diff --git a/content/html/en/blog/11_Load_Disqus_Asynchronously.md b/content/html/en/blog/11_Load_Disqus_Asynchronously.md index f7c1e8969..82d677a6b 100644 --- a/content/html/en/blog/11_Load_Disqus_Asynchronously.md +++ b/content/html/en/blog/11_Load_Disqus_Asynchronously.md @@ -71,7 +71,7 @@ If you forget the `window.disqus_no_style=true;` then your page will be blank. S ### CSS -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](/Scratch/en/blog/11_Load_Disqus_Asynchronously/code/original_disqus.css) I obtained. +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](/n3blog/en/blog/11_Load_Disqus_Asynchronously/code/original_disqus.css) I obtained. --- diff --git a/content/html/en/blog/2009-09-Disqus-versus-Intense-Debate--Why-I-switched-.md b/content/html/en/blog/2009-09-Disqus-versus-Intense-Debate--Why-I-switched-.md index effaefde6..4d39532de 100644 --- a/content/html/en/blog/2009-09-Disqus-versus-Intense-Debate--Why-I-switched-.md +++ b/content/html/en/blog/2009-09-Disqus-versus-Intense-Debate--Why-I-switched-.md @@ -16,7 +16,7 @@ tags: # [Disqus](http://disqus.com/) *vs.* [Intense Debate](http://intensedebate.com/) -I made a blog entry about how I tried to integrate [Disqus](http://disqus.com). 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](/Scratch/en/blog/11_Load_Disqus_Asynchronously/). +I made a blog entry about how I tried to integrate [Disqus](http://disqus.com). 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](/n3blog/en/blog/11_Load_Disqus_Asynchronously/). 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). diff --git a/content/html/en/blog/2009-09-jQuery-Tag-Cloud.md b/content/html/en/blog/2009-09-jQuery-Tag-Cloud.md index 0206fa8e4..c2511a5c5 100644 --- a/content/html/en/blog/2009-09-jQuery-Tag-Cloud.md +++ b/content/html/en/blog/2009-09-jQuery-Tag-Cloud.md @@ -230,7 +230,7 @@ end -You can [download the complete file](/Scratch/en/blog/2009-09-jQuery-Tag-Cloud/code/tag.rb) to put in your 'lib' directory. +You can [download the complete file](/n3blog/en/blog/2009-09-jQuery-Tag-Cloud/code/tag.rb) to put in your 'lib' directory. Of course to be nice you need the associated CSS diff --git a/content/html/en/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-.md b/content/html/en/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-.md index 21842ab57..845458814 100644 --- a/content/html/en/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-.md +++ b/content/html/en/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-.md @@ -15,7 +15,7 @@ tags: - script ----- -I already talked about how [I synchronized my website with mobileme](/Scratch/en/blog/10_Synchronize_Custom_WebSite_with_mobileMe). I ameliorated this script in order to make it incremental. +I already talked about how [I synchronized my website with mobileme](/n3blog/en/blog/10_Synchronize_Custom_WebSite_with_mobileMe). I ameliorated this script in order to make it incremental. 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. diff --git a/content/html/en/blog/2009-10-How-to-preload-your-site-with-style.md b/content/html/en/blog/2009-10-How-to-preload-your-site-with-style.md index ab364ee05..4e6b64a9c 100644 --- a/content/html/en/blog/2009-10-How-to-preload-your-site-with-style.md +++ b/content/html/en/blog/2009-10-How-to-preload-your-site-with-style.md @@ -22,7 +22,7 @@ Here is a live example of what appear while loading my pages.

Click me to see me disapear again.

Loading... - loading logo + loading logo
- - + + + <%= @item[:title] %> @@ -46,7 +46,7 @@
↓ Menu ↓
<%= languages.map do |l| - dest=@item_rep.path.sub(/^\/Scratch\/..\//, %{/Scratch/#{l}/}) + dest=@item_rep.path.sub(%r{#{@config[:webprefix]}/../}, %{#{config[:webprefix]}/#{l}/}) if @item_rep.path != dest %{#{ tradOfKeywordIn(:switchTo,l)}} else @@ -168,12 +168,12 @@ nanoc
- Validation + Validation [xhtml] . [css] . - [rss] + [rss]
diff --git a/layouts/default.html b/layouts/default.html index e3f0c10a8..0f1ca26b1 100644 --- a/layouts/default.html +++ b/layouts/default.html @@ -7,13 +7,13 @@ <%= meta_tags %> - - + + <%= meta_alternate %> - - - + + + @@ -21,7 +21,7 @@ @@ -37,7 +37,7 @@ <% end %> - Presentation drawing + Presentation drawing

<%= @item[:content_for_title].nil? ? @item[:title] : @item[:content_for_title] %> @@ -82,12 +82,12 @@ nanoc

- Validation + Validation [xhtml] . [css] . - [rss] + [rss]
diff --git a/layouts/error.html b/layouts/error.html index 483277090..58fdfc2af 100644 --- a/layouts/error.html +++ b/layouts/error.html @@ -10,10 +10,10 @@ <% if t.length > 0 %> <% end %> - - - - + + + + @@ -22,7 +22,7 @@
- Presentation drawing + Presentation drawing

<%= @item[:title] %> @@ -55,12 +55,12 @@ nanoc

- Validation + Validation [xhtml] . [css] . - [rss] + [rss]
diff --git a/layouts/feed.html b/layouts/feed.html index bb95269fe..a307915b3 100644 --- a/layouts/feed.html +++ b/layouts/feed.html @@ -1,7 +1,7 @@ ----- ----- <% -language=@item_rep.path.sub(/\/Scratch\//,'').sub(/\/.*$/,'') +language=@item_rep.path.sub(%r{#{@config[:webprefix]}/},'').sub(/\/.*$/,'') number_of_char_for_resume=800 %><%= atom_feed( { diff --git a/lib/gitmtime.rb b/lib/gitmtime.rb index 2da6f2184..49f8cf571 100644 --- a/lib/gitmtime.rb +++ b/lib/gitmtime.rb @@ -1,5 +1,5 @@ def gitmtime - filepath=@item.path.sub('/Scratch/','content/html/').sub(/\/$/,'') + filepath=@item.path.sub(@config[:webprefix]+'/','content/html/').sub(/\/$/,'') ext=%{.#{@item[:extension]}} filepath<<=ext if not FileTest.exists?(filepath) diff --git a/lib/html.rb b/lib/html.rb index 683b2b29f..716b14e88 100644 --- a/lib/html.rb +++ b/lib/html.rb @@ -22,7 +22,7 @@ end def choixlang @conf.languages.map do |l| - dest=@item_rep.path.sub(/^\/Scratch\/..\//, %{/Scratch/#{l}/}) + dest=@item_rep.path.sub(%r{#{@config[:webprefix]}/../}, %{#{@config[:webprefix]}/#{l}/}) if @item_rep.path != dest %{#{ tradOfKeywordIn(:switchTo,l)}} else diff --git a/lib/intenseDebate.rb b/lib/intenseDebate.rb index e040c4dea..7a63779c0 100644 --- a/lib/intenseDebate.rb +++ b/lib/intenseDebate.rb @@ -21,6 +21,6 @@ def generateIntenseDebateThread var idcomments_post_url = 'http://yannesposito.com#{protectedPath}'; - + } end diff --git a/lib/nanoc_item_conf.rb b/lib/nanoc_item_conf.rb index 477c51add..a99a53426 100644 --- a/lib/nanoc_item_conf.rb +++ b/lib/nanoc_item_conf.rb @@ -14,7 +14,7 @@ end def setItemConf # -- init variables -- conf=LocalConf.new - language=@item_rep.path.sub(/\/Scratch\//,'').sub(/\/.*$/,'') + language=@item_rep.path.sub(%r{#{@config[:webprefix]}/},'').sub(/\/.*$/,'') if language != '' conf.language=language else diff --git a/lib/tag.rb b/lib/tag.rb index 471fb810e..4b3ac5bda 100644 --- a/lib/tag.rb +++ b/lib/tag.rb @@ -11,9 +11,9 @@ def alltags language=@item.path - language =~ %r{/Scratch/([^/]*)/} + language =~ %r{#{@config[:webprefix]}/([^/]*)/} language = $1 - @items.select {|p| p.path =~ %r{/Scratch/#{language}/} and p[:kind].to_s == "article" and p.parent[:kind].to_s == 'blog'} + @items.select {|p| p.path =~ %r{#{@config[:webprefix]}/#{language}/} and p[:kind].to_s == "article" and p.parent[:kind].to_s == 'blog'} end def tagNumber @@ -92,7 +92,7 @@ end tagCloud <<= %{
} language=@item.path - language =~ %r{/Scratch/([^/]*)/} + language =~ %r{#{@config[:webprefix]}/([^/]*)/} language = $1 tagLinks.sort{|a,b| a[0].downcase <=> b[0].downcase}.each do |t,l| protected=t.gsub(/\W/,'_') diff --git a/multi/about/contact.md b/multi/about/contact.md index e194f11b8..3806c9e90 100644 --- a/multi/about/contact.md +++ b/multi/about/contact.md @@ -6,8 +6,8 @@ menupriority: 1 en: # How to contact me fr: # Comment me contacter -en: Avatar -fr: Avatar +en: Avatar +fr: Avatar <%= mail_perso %> en: Follow me on [twitter](http://twitter.com/yogsototh) diff --git a/multi/blog.erb b/multi/blog.erb index c056dbf6d..633b6e0a4 100644 --- a/multi/blog.erb +++ b/multi/blog.erb @@ -7,7 +7,7 @@ noSubMenu: true <% number_of_articles=5 number_of_char_for_resume=800 - language=@item_rep.path.sub(/\/Scratch\//,'').sub(/\/.*$/,'') + language=@item_rep.path.sub(/\/n3blog\//,'').sub(/\/.*$/,'') last_articles = @items.select do |a| a.reps[0].path =~ /\/#{language}\// && a[:kind] == 'article' end diff --git a/multi/blog/2010-06-15-Get-my-blog-engine.md b/multi/blog/2010-06-15-Get-my-blog-engine.md index 7f54aeb9e..34fe6ecda 100644 --- a/multi/blog/2010-06-15-Get-my-blog-engine.md +++ b/multi/blog/2010-06-15-Get-my-blog-engine.md @@ -119,7 +119,7 @@ multi/blog/2010-06-01-the-title/third_part.md ### mobileme -All files are intended to be generated into the `output/Scratch` directory. +All files are intended to be generated into the `output/n3blog` directory. This was made like that to work nicely with iWeb organisation of websites. ### menu diff --git a/multi/blog/2010-06-17-hide-yourself-to-analytics.md b/multi/blog/2010-06-17-hide-yourself-to-analytics.md index c4cb1badd..6a807e86e 100644 --- a/multi/blog/2010-06-17-hide-yourself-to-analytics.md +++ b/multi/blog/2010-06-17-hide-yourself-to-analytics.md @@ -19,10 +19,10 @@ fr: - cacher ----- fr: Voici un moyen très simple de ne plus être comptabilisé dans les visites de son propre site. -fr: Tout d'abord, vous devriez jeter un coup d'œil sur comment [je gère les systèmes de récupération de statistiques](/Scratch/fr/blog/2010-06-17-track-events-with-google-analytics). +fr: Tout d'abord, vous devriez jeter un coup d'œil sur comment [je gère les systèmes de récupération de statistiques](/n3blog/fr/blog/2010-06-17-track-events-with-google-analytics). fr: Je centralise tout dans un seul fichier javascript ce qui facilite le travail. en: This is a way not to count your own visits to your blog. -en: First you should look on how [I handle analytics](/Scratch/en/blog/2010-06-17-track-events-with-google-analytics). All analytics are handled in one javascript file, this make things really convenient. +en: First you should look on how [I handle analytics](/n3blog/en/blog/2010-06-17-track-events-with-google-analytics). All analytics are handled in one javascript file, this make things really convenient. fr: Cette méthode nécessite l'utilisation de `jquery-cookie`. en: Then you need to know my method use the `jquery-cookie`. diff --git a/multi/blog/2010-08-23-Now-heberged-on-heroku.md b/multi/blog/2010-08-23-Now-heberged-on-heroku.md index fee4341eb..01520891c 100644 --- a/multi/blog/2010-08-23-Now-heberged-on-heroku.md +++ b/multi/blog/2010-08-23-Now-heberged-on-heroku.md @@ -70,7 +70,7 @@ use Rack::TryStatic, :urls => %w[/], # match all requests :try => ['.html', 'index.html', '/index.html'] # try these postfixes sequentially -errorFile='output/Scratch/en/error/404-not_found/index.html' +errorFile='output/n3blog/en/error/404-not_found/index.html' run lambda { [404, { "Last-Modified" => File.mtime(errorFile).httpdate, "Content-Type" => "text/html", diff --git a/multi/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes.md b/multi/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes.md index 470ebb94c..91923e6e4 100644 --- a/multi/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes.md +++ b/multi/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes.md @@ -31,7 +31,7 @@ fr: Voici comment je m'y prend avec [nanoc](http://nanoc.stoneship.org) : def gitmtime - filepath=@item.path.sub('/Scratch/','content/html/').sub(/\/$/,'') + filepath=@item.path.sub('/n3blog/','content/html/').sub(/\/$/,'') ext=%{.#{@item[:extension]}} filepath<<=ext if not FileTest.exists?(filepath) diff --git a/multi/blog/2010-10-06-New-Blog-Design-Constraints.md b/multi/blog/2010-10-06-New-Blog-Design-Constraints.md index c6b56c7c8..02d4e1fe4 100644 --- a/multi/blog/2010-10-06-New-Blog-Design-Constraints.md +++ b/multi/blog/2010-10-06-New-Blog-Design-Constraints.md @@ -27,7 +27,7 @@ en: Now it should be far cleaner. en: I believe I use no CSS3 feature and far less javascript. en: Of course before my website was perfectly browsable without javascript. en: Unfortunately some CSS3 feature are not mature enough on some browser. -en: For more details you can read my older [blog entry](/Scratch/en/blog/2010-07-07-CSS-rendering-problems-by-navigator). +en: For more details you can read my older [blog entry](/n3blog/en/blog/2010-07-07-CSS-rendering-problems-by-navigator). en: But the major problem came from, `font-shadow` and gradients. en: Then my new design obey to the following rules: diff --git a/multi/index.erb b/multi/index.erb index 901199526..c3722f9d3 100644 --- a/multi/index.erb +++ b/multi/index.erb @@ -17,7 +17,7 @@ no_entete: true
en:
en:

-en: +en: en: Blog en: » en: @@ -28,7 +28,7 @@ en:

en:

en:
en:

-en: +en: en: Softwares en: » en: @@ -41,7 +41,7 @@ en:

en:

en:
en:

-en: Contact +en: Contact en: » en: en:

@@ -53,7 +53,7 @@ en:
fr:
fr:

-fr: +fr: fr: Blog fr: » fr: @@ -64,7 +64,7 @@ fr:

fr:

fr:
fr:

-fr: +fr: fr: Logiciels fr: » fr: @@ -77,7 +77,7 @@ fr:

fr:

fr:
fr:

-fr: +fr: fr: Contact fr: » fr: diff --git a/multi/softwares.md b/multi/softwares.md index cc8189eeb..bf2860942 100644 --- a/multi/softwares.md +++ b/multi/softwares.md @@ -5,23 +5,23 @@ noSubMenu: true hidden: false ----- <%= block( %{YPassword}, -en: %{/Scratch/en/softwares/ypassword}, +en: %{/n3blog/en/softwares/ypassword}, en: %{YPassword is a password manager that make your web life more secure} -fr: %{/Scratch/fr/softwares/ypassword}, +fr: %{/n3blog/fr/softwares/ypassword}, fr: %{YPassword est un outil de gestion de mots de passe pour rendre votre vie en ligne plus sûre.} ) %> <%= block( %{YAquaBubbles}, -en: %{/Scratch/en/softwares/yaquabubbles}, +en: %{/n3blog/en/softwares/yaquabubbles}, en: %{Nice underwater floating bubbles} -fr: %{/Scratch/fr/softwares/yaquabubbles}, +fr: %{/n3blog/fr/softwares/yaquabubbles}, fr: %{Des bulles se déplaçant sous l'eau} ) %> <%= block( %{YClock}, -en: %{/Scratch/en/softwares/yclock}, +en: %{/n3blog/en/softwares/yclock}, en: %{Biohazard logo inspired clock}, -fr: %{/Scratch/fr/softwares/yclock}, +fr: %{/n3blog/fr/softwares/yclock}, fr: %{Une horloge inspirée par le symbole "biohazard"}, "right" ) %> diff --git a/multi/softwares/yaquabubbles.md b/multi/softwares/yaquabubbles.md index 4162e8e66..136e7b906 100644 --- a/multi/softwares/yaquabubbles.md +++ b/multi/softwares/yaquabubbles.md @@ -7,7 +7,7 @@ noSubMenu: true hidden: false ----- -[ ![Screenshot](/Scratch/img/softwares/yaquabubbles/screenshot1.png 'screenshot') ][yaquabubbles] +[ ![Screenshot](/n3blog/img/softwares/yaquabubbles/screenshot1.png 'screenshot') ][yaquabubbles] fr: YAquaBubbles est un économiseur d'écran réalisé avec QuartzComposer. fr: Il s'agissait d'un simple essai mais le résultat était plaisant. @@ -17,4 +17,4 @@ en: It was one of my first try but the result was nice. [ YAquaBubbles.dmg][yaquabubbles] -[yaquabubbles]: /Scratch/files/YAquaBubbles.dmg +[yaquabubbles]: /n3blog/files/YAquaBubbles.dmg diff --git a/multi/softwares/yclock.md b/multi/softwares/yclock.md index c09478c3f..9a5f5de9a 100644 --- a/multi/softwares/yclock.md +++ b/multi/softwares/yclock.md @@ -6,7 +6,7 @@ hidden: false ----- -[ ![Screenshot](/Scratch/img/softwares/yclock/screenshot1.png 'screenshot') ][yclock] +[ ![Screenshot](/n3blog/img/softwares/yclock/screenshot1.png 'screenshot') ][yclock] fr: YClock est un économiseur d'écran qui vous donne l'heure.i fr: Il a trois thèmes clair, rouge et noir. @@ -17,4 +17,4 @@ en: It is based on a QuartzComposition and with some little Objective-C code to [ YClock.dmg][yclock] -[yclock]: /Scratch/files/YClock.dmg +[yclock]: /n3blog/files/YClock.dmg diff --git a/multi/softwares/ypassword.md b/multi/softwares/ypassword.md index f96c6b766..a248bd35a 100644 --- a/multi/softwares/ypassword.md +++ b/multi/softwares/ypassword.md @@ -8,24 +8,24 @@ en: _Easy_, _Secure_ and _Portable_ way to manage your web passwords. fr: Une gestion _simple_, _sécurisée_ et _portable_ de ses mots de passes web. en: Remember only _one_ strong password. And the rest follow. -en: See my [blog entry](/Scratch/en/blog/ypassword.html) for the details. +en: See my [blog entry](/n3blog/en/blog/ypassword.html) for the details. fr: Souvenez vous d'_un_ seul mot de passe de bonne qualité, le reste suis. -fr: Lisez mon [article](/Scratch/fr/blog/ypassword.html) pour les détails. +fr: Lisez mon [article](/n3blog/fr/blog/ypassword.html) pour les détails. en: Here you can find: fr: Ici vous trouverez : -en: - A [Dashboard Widget](/Scratch/files/YPassword-1.6.zip), -en: - An [Applescript](/Scratch/files/forcePaste.app.zip) to simulate copy/paste in protected fields, -en: - An alpha [Web Application](/Scratch/en/softwares/ypassword/web/) made with [Cappuccino](http://cappuccino.org), -en: - An alpha [Web Application](/Scratch/en/softwares/ypassword/iphoneweb/) for iPhone, -en: - A [command line tool](/Scratch/files/getpass). +en: - A [Dashboard Widget](/n3blog/files/YPassword-1.6.zip), +en: - An [Applescript](/n3blog/files/forcePaste.app.zip) to simulate copy/paste in protected fields, +en: - An alpha [Web Application](/n3blog/en/softwares/ypassword/web/) made with [Cappuccino](http://cappuccino.org), +en: - An alpha [Web Application](/n3blog/en/softwares/ypassword/iphoneweb/) for iPhone, +en: - A [command line tool](/n3blog/files/getpass). -fr: - Un [widget](/Scratch/files/YPassword-1.6.zip) ; -fr: - un [Applescript](/Scratch/files/forcePaste.app.zip) pour simuler la copie dans les champs textes protégés ; -fr: - une [application web](/Scratch/fr/softwares/ypassword/web/) écrite avec [Cappuccino](http://cappuccino.org), -fr: - une [application web](/Scratch/fr/softwares/ypassword/iphoneweb/) pour iPhone ; -fr: - un [script utilisable en ligne de commande](/Scratch/files/getpass). +fr: - Un [widget](/n3blog/files/YPassword-1.6.zip) ; +fr: - un [Applescript](/n3blog/files/forcePaste.app.zip) pour simuler la copie dans les champs textes protégés ; +fr: - une [application web](/n3blog/fr/softwares/ypassword/web/) écrite avec [Cappuccino](http://cappuccino.org), +fr: - une [application web](/n3blog/fr/softwares/ypassword/iphoneweb/) pour iPhone ; +fr: - un [script utilisable en ligne de commande](/n3blog/files/getpass). en: I'll soon release an iPhone application. fr: Dans peu de temps je créerai une application iPhone pour YPassword. diff --git a/output/index.html b/output/index.html index e955353d1..cbe2e83cc 100644 --- a/output/index.html +++ b/output/index.html @@ -5,14 +5,14 @@ - - + + - - - + + + @@ -20,13 +20,13 @@
- Presentation drawing + Presentation drawing

@@ -62,7 +62,7 @@

- + Blog » @@ -73,7 +73,7 @@

- + Softwares » @@ -86,7 +86,7 @@

- Contact + Contact »

@@ -101,7 +101,7 @@

- + Blog » @@ -112,7 +112,7 @@

- + Logiciels » @@ -125,7 +125,7 @@

- Modified: 04/13/2011 + Modified: 04/20/2011
Entirely done with @@ -197,12 +197,12 @@ nanoc
diff --git a/output/n3blog/assets/css/main.css b/output/n3blog/assets/css/main.css new file mode 100644 index 000000000..29dbf463f --- /dev/null +++ b/output/n3blog/assets/css/main.css @@ -0,0 +1 @@ +table.description tr td{border:1px solid#eee}.assombris20{background-color:#eee}body{color:#111;background-color:#fff}#content{color:#111;background-color:#fff}a:hover{text-shadow:0 0 2px#faa}a,a:link,a:visited,a:active,a:hover,#clickcomment{text-decoration:none;outline:none}a,a:link,a:visited,a:active,#clickcomment{color:#111}a:hover,#clickcomment:hover{color:#d50000}hr{color:#eee;border-top:1px solid#eee;border-bottom:none;border-left:none;border-right:none}ul{list-style:square}ol,ul{padding-left:0}ol li,ul li{margin:.5em 0}ol li ul,ol li ol,ul li ol,ul li ul{margin:.5em 1.5em;list-style:circle}body,h1,h2,h3,h4,#entete,.tag{font-family:Georgia,Palatino,"Century Schoolbook L","Times New Roman",Times,serif;line-height:1.4em}pre{background-color:#111;color:#fff;padding:1em;line-height:1.2em}pre,code{font-family:monaco,monospace;font-size:.7em}p code{font-family:monospace;font-size:1em}p{margin-bottom:1.2em}blockquote{font-style:italic;padding:.5em 1em;color:#555}blockquote a:hover{color:#d50000}blockquote strong,blockquote b,blockquote i,blockquote em{font-weight:400;font-style:normal;color:#111}abbr,acronym{font-variant:small-caps;text-decoration:none;border-bottom-width:0}#titre{letter-spacing:-0.06em;border-bottom:4px double#ccc;border-top:4px double#ccc}#liens .active,#sousliens{color:#111;background-color:#eee;border-top:none}#liens .active a,#sousliens a{color:#666}#liens .active a:hover,#sousliens a:hover{color:#e25f2f}#liens .active a:hover strong,#liens .active a:hover b,#liens .active a:hover i,#liens .active a:hover em,#liens .active a:hover .nicer,#sousliens a:hover strong,#sousliens a:hover b,#sousliens a:hover i,#sousliens a:hover em,#sousliens a:hover .nicer{color:#ffbe96}#liens .active hr,#sousliens hr{color:#666;border-top:1px solid#666}#liens .active strong,#liens .active b,#liens .active i,#liens .active em,#sousliens strong,#sousliens b,#sousliens i,#sousliens em{color:#111}#lastmod{font-size:.8em}.nojsbutton{font-size:2.5em}#clickcomment{cursor:pointer;font-size:1.2em}.small{font-size:.8em}.sc{font-variant:small-caps}.impact,.darkimpact{font-size:2em;margin:0 auto 1em auto;line-height:1.3em}h1 > .date{font-size:.6em;color:#111}.date{font-size:.8em;color:#fff;border:1px solid#111;text-align:center;width:4.1em;line-height:1.5em;display:inline-block;vertical-align:middle;margin-right:1em}.date .day,.date .month,.date .year{display:block}.date .day{color:#111;background-color:#fff;float:left;width:1.7em}.date .month{float:right;width:2.3em;background-color:#111;color:#fff}.date .year{line-height:3ex;clear:both;color:#111;background-color:#eee}.date .year a{color:#666}.date .year a:hover{color:#e25f2f}.date .year a:hover strong,.date .year a:hover b,.date .year a:hover i,.date .year a:hover em,.date .year a:hover .nicer{color:#ffbe96}.date .year hr{color:#666;border-top:1px solid#666}.date .year strong,.date .year b,.date .year i,.date .year em{color:#111}body{text-align:center;font-size:.9em}body > #entete{position:absolute;left:0;top:.5em;width:100%;min-width:50em;z-index:8000;padding-bottom:1em;margin-bottom:3em}body > #content > #entete > #choix > #choixrss > #rss{font-size:1em}#titre h2{width:80%;margin-left:auto;margin-right:auto;text-align:center;color:#ccc}#titre{text-align:center;width:100%}#titre h1,#titre h2{padding-left:1em;padding-right:1em}#bottom{clear:right;margin-right:0;padding:1.5em;line-height:1.5em;color:#ccc;margin-top:2em;text-align:center}#bottom a{color:#ccc}#bottom a:hover{color:#d50000}#sousliens{padding:1em 0;line-height:2em}#sousliens ul{list-style:none;margin-left:4em}ul.horizontal li{display:inline;font-size:.9em}ul.horizontal{margin-top:0;margin-bottom:0}#entete{padding-top:.1em;border-top:1px solid#ccc;border-bottom:1px solid#ccc}#liens{width:100%;padding:0;clear:both;margin-top:.5em}#liens ul{width:100%;clear:both;padding:0;margin:0}#liens ul li{display:inline-block;height:4em;margin-left:.2em;margin-right:.2em;width:23%}#liens ul li a,#liens ul li span{width:100%;display:block;line-height:4em}.clear{clear:both}#content{line-height:4em;margin-left:auto;margin-right:auto;margin-top:0;position:relative;clear:both;width:52em}#content > #choix{margin-top:1em}.encadre,.black,.red,.intro,.resume,.shadow{padding-left:2em;padding-right:2em;margin-top:2em;margin-bottom:2em}.encadre,.black,.red,.shadow{color:#111;background-color:#eee}.encadre a,.black a,.red a,.shadow a{color:#666}.encadre a:hover,.black a:hover,.red a:hover,.shadow a:hover{color:#e25f2f}.encadre a:hover strong,.encadre a:hover b,.encadre a:hover i,.encadre a:hover em,.encadre a:hover .nicer,.black a:hover strong,.black a:hover b,.black a:hover i,.black a:hover em,.black a:hover .nicer,.red a:hover strong,.red a:hover b,.red a:hover i,.red a:hover em,.red a:hover .nicer,.shadow a:hover strong,.shadow a:hover b,.shadow a:hover i,.shadow a:hover em,.shadow a:hover .nicer{color:#ffbe96}.encadre hr,.black hr,.red hr,.shadow hr{color:#666;border-top:1px solid#666}.encadre strong,.encadre b,.encadre i,.encadre em,.black strong,.black b,.black i,.black em,.red strong,.red b,.red i,.red em,.shadow strong,.shadow b,.shadow i,.shadow em{color:#111}.intro,.resume{font-size:.9em;font-style:italic;padding:.5em 1em;color:#555}.intro a:hover,.resume a:hover{color:#d50000}.intro strong,.intro b,.intro i,.intro em,.resume strong,.resume b,.resume i,.resume em{font-weight:400;font-style:normal;color:#111}#afterheader > h1{width:100%;padding-top:1.5em;text-align:left}#afterheader{padding-left:0;padding-right:0}#sousliens{margin-top:3em;margin-bottom:3em;font-size:1.2em;letter-spacing:1px;text-align:left;clear:both}.twilight{line-height:1.1em}.corps{font-family:Georgia,Palatino,"Century Schoolbook L","Times New Roman",Times,serif;font-size:1.25em;line-height:1.6em;text-align:justify;text-align:left;padding:3em 3em;margin:0;border-bottom:1px#ccc solid;clear:both}.corps img{max-width:30em;border:1px solid#ccc;background-color:#fff;padding:.5em;box-shadow:0 10px 15px#ccc}img.clean{border:none}#address{clear:both}.definitionCell{width:5em;vertical-align:top;font-weight:700;text-align:center}.valueCell{text-align:right}.smallblock{float:left;width:50%;font-size:1em;font-weight:700}.largeblock{float:right;width:70%;font-size:1em}#blackpage,#nojsredirect{top:0;left:0;width:100%;height:100%;margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;position:fixed;text-align:center}#blackpage{color:#666;padding-top:10em;background-color:#eee;z-index:9000;cursor:wait}#blackpage img{background:none;border:none}#blackpage a{cursor:pointer}#nojsredirect{z-index:9001}.nojsbutton{width:50%;padding:1em;border:solid 3px white;margin-left:auto;margin-right:auto;margin-top:2em;z-index:9002}.file{font-size:.8em;text-align:right;padding-right:1em;margin-right:.1;margin-bottom:0;background:#111}.file a{color:#fff}.flush{clear:both}table.description{border-spacing:5px;border-collapse:separate;margin-right:auto;margin-left:auto}table.description tr td{padding-left:.5em;padding-right:.5em;padding-top:.5ex;padding-bottom:.5ex;vertical-align:middle;margin-right:5px}ul.long li{margin-bottom:1em}img{display:block;margin-left:auto;margin-right:auto;background:none;border:none}img.left{float:left;max-width:30%;margin-right:1em}img.inside{display:inline;vertical-align:middle}pre{overflow:hidden}.withfile pre{margin-top:0;overflow:hidden}.navigationprev,.navigationnext{padding:0;margin-left:.2em;margin-right:.2em;margin-bottom:0;margin-top:3em;width:45%}.navigation .navigationprev,.navigation .navigationnext{width:30%;margin-top:0}.navigation{height:4em;border-bottom:#ccc solid 1px}.presarticleleft,.presarticleright{font-size:1em}.navigationprev{float:left;text-align:left}.navigationnext{float:right;text-align:right}.impact,.darkimpact{text-align:left;width:66%;padding-left:.25em;padding-right:.25em}table.impact{text-align:left}table.impact tr td{padding-left:.25em;padding-right:.25em}#liens{font-size:1.2em}#iemessage{font-size:1.2em}.tag{display:inline;cursor:pointer;margin-left:.5em;margin-right:.5em}.list{margin-top:3em}#menuMessage{font-size:1.2em;line-height:1.5em;width:100%;text-align:center}#choixrss{float:right;width:25%;line-height:2em}#choixlang{line-height:2em}#choix a{color:#888}#choix a:hover{color:#d50000}#choixlang a{display:block;width:25%;line-height:4em;text-align:center}#next_before_articles{clear:both;width:100%;font-size:1.2em;padding-top:1em;padding-bottom:1em}#previous_articles,#next_articles{color:#888;font-style:italic;font-size:.8em}#previous_articles{float:left;margin-left:1em;width:45%;text-align:left}.previous_article,.next_article{margin-top:1em}#next_articles{float:right;width:45%;margin-right:1em;text-align:right}#clickcomment{margin-left:0;width:25%}#rss{font-size:1.2em;text-align:center;display:block;width:100%;float:right;padding:1em .1em}.return a{text-align:center;float:right;width:25%}.corps .return a{color:#eee;padding:.1em;line-height:1.5em;font-size:1.5em;height:1.5em;float:left;font-size:2em;margin-top:-0.5em;margin-left:-2em;width:1.5em}a.return{color:#eee;padding:.1em;line-height:1.5em;font-size:1.5em;height:1.5em;font-size:2em;width:1.5em;display:block}a.return:hover{color:#888}.corps .return a:hover{color:#d50000}.footnotes{font-size:.8em}.fontnotes ol{margin-left:0}.typeset img{display:inline;border:none;margin:0;padding:0}strong,b,i,em{font-weight:400;color:#888}strong a,b a,i a,em a{color:#111}strong a:hover,b a:hover,i a:hover,em a:hover{color:#d50000}.corps p strong,.corps p b,.corps p i,.corps p em{color:#555}a:hover strong,a:hover b,a:hover i,a:hover em{color:#e25f2f}a:hover .nicer{color:#ffbe96}.nicer{color:#ccc;font-family:"Lucida Grande",Tahoma}.block{width:31%;text-align:left;line-height:1em;margin-left:1%;margin-right:1%;font-size:.8em}.block a{color:#111}.block a:hover{color:#d50000}.block h3{margin:0;font-size:1.3em}.block p{line-height:1.2em}.left{float:left}.right{float:right}.corps p a,.corps ul a{color:#555}.corps p a:hover,.corps ul a:hover{color:#d50000}ul.bloglist,.archive ul{list-style-type:none;margin:0}ul.bloglist li,.archive ul li{margin-bottom:1em}.button{cursor:pointer;text-align:center} \ No newline at end of file diff --git a/output/n3blog/blank.html b/output/n3blog/blank.html new file mode 100644 index 000000000..e69de29bb diff --git a/output/n3blog/css/iPhone.css b/output/n3blog/css/iPhone.css new file mode 100644 index 000000000..c13a8ce51 --- /dev/null +++ b/output/n3blog/css/iPhone.css @@ -0,0 +1,2 @@ +#content { width: 100%; font-size: 20px; } +.corps { padding-right: 2px; padding-left: 2px;} diff --git a/output/n3blog/css/idc.css b/output/n3blog/css/idc.css new file mode 100644 index 000000000..576532670 --- /dev/null +++ b/output/n3blog/css/idc.css @@ -0,0 +1,8 @@ +#idc-container-parent h3 { + display: inline; + left: auto; + border: none; + box-shadow: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; +} diff --git a/output/n3blog/css/img/background.png b/output/n3blog/css/img/background.png new file mode 100644 index 000000000..6b82629b0 Binary files /dev/null and b/output/n3blog/css/img/background.png differ diff --git a/output/n3blog/css/img/codeColor.png b/output/n3blog/css/img/codeColor.png new file mode 100644 index 000000000..443fd491c Binary files /dev/null and b/output/n3blog/css/img/codeColor.png differ diff --git a/output/n3blog/css/img/mainColor.png b/output/n3blog/css/img/mainColor.png new file mode 100644 index 000000000..810940a8c Binary files /dev/null and b/output/n3blog/css/img/mainColor.png differ diff --git a/output/n3blog/css/img/revealColor.png b/output/n3blog/css/img/revealColor.png new file mode 100644 index 000000000..31006edf3 Binary files /dev/null and b/output/n3blog/css/img/revealColor.png differ diff --git a/output/n3blog/css/img/secondColor.png b/output/n3blog/css/img/secondColor.png new file mode 100644 index 000000000..868d81648 Binary files /dev/null and b/output/n3blog/css/img/secondColor.png differ diff --git a/output/n3blog/css/img/separator.png b/output/n3blog/css/img/separator.png new file mode 100644 index 000000000..e54394370 Binary files /dev/null and b/output/n3blog/css/img/separator.png differ diff --git a/output/n3blog/css/twilight.css b/output/n3blog/css/twilight.css new file mode 100644 index 000000000..948e56312 --- /dev/null +++ b/output/n3blog/css/twilight.css @@ -0,0 +1,141 @@ +pre.twilight { + padding: .8em; +} + +pre.twilight .DiffInserted { + /* background-color: #253B22; */ + color: #F8F8F8; +} +pre.twilight .DiffHeader { + /* background-color: #0E2231; */ + color: #F8F8F8; + font-style: italic; +} +pre.twilight .CssPropertyValue { + color: #F9EE98; +} +pre.twilight .CCCPreprocessorDirective { + color: #AFC4DB; +} +pre.twilight .Constant { + color: #CF6A4C; +} +pre.twilight .DiffChanged { + /* background-color: #4A410D; */ + color: #F8F8F8; +} +pre.twilight .EmbeddedSource { + /* background-color: #A3A6AD; */ +} +pre.twilight .Support { + color: #9B859D; +} +pre.twilight .MarkupList { + color: #F9EE98; +} +pre.twilight .CssConstructorArgument { + color: #8F9D6A; +} +pre.twilight .Storage { + color: #F9EE98; +} +pre.twilight .line-numbers { + /* background-color: #DDF0FF; */ + color: #000000; +} +pre.twilight .CssClass { + color: #9B703F; +} +pre.twilight .StringConstant { + color: #DDF2A4; +} +pre.twilight .CssAtRule { + color: #8693A5; +} +pre.twilight .MetaTagInline { + color: #E0C589; +} +pre.twilight .MarkupHeading { + color: #CF6A4C; +} +pre.twilight .CssTagName { + color: #CDA869; +} +pre.twilight .SupportConstant { + color: #CF6A4C; +} +pre.twilight .DiffDeleted { + /* background-color: #420E09; */ + color: #F8F8F8; +} +pre.twilight .CCCPreprocessorLine { + color: #8996A8; +} +pre.twilight .StringRegexpSpecial { + color: #CF7D34; +} +pre.twilight .EmbeddedSourceBright { + /* background-color: #9C9EA4; */ +} +pre.twilight .InvalidIllegal { + /* background-color: #241A24; */ + color: #F8F8F8; +} +pre.twilight .SupportFunction { + color: #DAD085; +} +pre.twilight .CssAdditionalConstants { + color: #CA7840; +} +pre.twilight .MetaTagAll { + color: #AC885B; +} +pre.twilight .StringRegexp { + color: #E9C062; +} +pre.twilight .StringEmbeddedSource { + color: #DAEFA3; +} +pre.twilight .EntityInheritedClass { + color: #9B5C2E; + font-style: italic; +} +pre.twilight .CssId { + color: #8B98AB; +} +pre.twilight .CssPseudoClass { + color: #8F9D6A; +} +pre.twilight .StringVariable { + color: #8A9A95; +} +pre.twilight .String { + color: #8F9D6A; +} +pre.twilight .Keyword { + color: #CDA869; +} +pre.twilight { + /* background-color: #141414; */ + color: #F8F8F8; +} +pre.twilight .CssPropertyName { + color: #C5AF75; +} +pre.twilight .DoctypeXmlProcessing { + color: #494949; +} +pre.twilight .InvalidDeprecated { + color: #D2A8A1; + font-style: italic; +} +pre.twilight .Variable { + color: #7587A6; +} +pre.twilight .Entity { + color: #9B703F; +} +pre.twilight .Comment { + color: #5F5A60; + font-style: italic; +} diff --git a/output/n3blog/en/about/contact/index.html b/output/n3blog/en/about/contact/index.html new file mode 100644 index 000000000..e82ff9dd4 --- /dev/null +++ b/output/n3blog/en/about/contact/index.html @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + Contact + + + + +
+ + + + Presentation drawing +
+

+ Contact +

+ +
+ +
+ + + + + +
+ +
+
+

How to contact me

+ +

Avatar

+ +

yann.esposito@gmail.com
+ Follow me on twitter
+ My preferred bookmarks diigo
+ Open Source github
+stackoverflow

+ + + + +
+
+ +
+ Modified: 01/06/2011 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/about/cv/index.html b/output/n3blog/en/about/cv/index.html new file mode 100644 index 000000000..34a59c02a --- /dev/null +++ b/output/n3blog/en/about/cv/index.html @@ -0,0 +1,559 @@ + + + + + + + + + + + + + + + + Curriculum Vitæ + + + + +
+ + + + Presentation drawing +
+

+ Curriculum Vitæ +

+ +
+ +
+ + + + + +
+ +
+ + +
+ + +

+ + Professional background +

+
+
+ from 2009 GridPocket co-founder, Sophia Antipolis, France
+ from 2007 Airfrance consultant, Astek, Sophia Antipolis, France
+ 2006-2007 Post PhD in the Laboratory Hubert Curien, Saint-Etienne, France
+ 2004-2006 ATER, (College Degree Teacher)
+ 2001-2004 Allocataire Moniteur (PhD student with a grant + a teach grant)
+ 1999-2000 College degree teaching
+ + + +
+ +
+ + +

+ + Education +

+
+
+ 2004 PhD Degree in computer science in the + LIF, + Université de Provence, + Marseille (France)
+ 2001 DEA in computer science
+ 2000 Maîtrise in computer science
+ 1999 Licence in computer science
+ 1998 DEUG MIAS (Math)
+ 1995 BAC S
+ + + +
+ +
+ + +

+ + Research activities + +

+ +

+ + Background +

+ +
    +
  • Machine Learning,
  • +
  • Data Mining,
  • +
  • Grammatical Inference
  • +
+ + + +

+ + studied objects +

+ + +
    +
  • Markov chains,
  • +
  • Hidden Markov Models,
  • +
  • Multiplicity Automata,
  • +
  • Weighted Transducer,
  • +
  • Tree Weighted Automata,
  • +
  • Tree Edit Distance
  • +
+ + + +

+ + main theoretical results +

+
    +
  • + + Multiplicity Automata Algorithm which identifie the class of + rational stocastic languages in the limit with probability one, +
  • +
  • + + The problem to know whether an MA generates a + probabilistic distribution is undecidable (was left open in + Probabilistic Automata, Azaria Paz, 1977), +
  • +
  • + + Algorithm of identification in the limit with + probability one of some subclass of non deterministic HMM +
  • + +
+ +

+ + Softwares +

+ +

SEDiL

+

+ + SEDiL: + Software aimed to learn tree edit distances. + Developped in JAVA (11.000 lines with javadoc comments) ; + +

+ +

+ + main features: +

+
    +
  • + + edition operations cost matrix learning, +
  • +
  • + + tree or string edit distance computation, + +
  • +
  • + + + tree and strings visualisation, +
  • +
  • + + + classification using the K nearest + neighbor algorithm, +
  • +
  • + + + Tree pairs generation, +
  • +
+ +

DEES

+ + + + DEES: + Software of Multiplicity Automata inference + written in C++ (7.500 lines, 10.000 with comments) ; + +

+ + Main features: +

+
    +
  • + + Multiplicity Automata Inference, +
  • +
  • + + Probabilistic Automata Inference + (Hidden Markov Model Inference ; learn Parameters + and Structure), + +
  • +
  • + + + Deterministic Probabilistic Automata Inference +
  • +
  • + + Baum Welch Algorithm + (learn parameter of an + + HMM from a sample), +
  • +
  • + + + GraphViz export, +
  • +
  • + + + Sample generation from an MA, +
  • +
  • And many others...
  • +
+ + +
+ +
+ + +

+ + Scientific Publications +

+
+
+ + + International Journal + + [Fundamenta Informaticæ, 2008] + [Pattern Recognition, 2004] +
+ + + French Journal + + [JEDAI 2003] +
+ + +International conferences + + [ECML 2008] [ICGI 2006] [COLT 2006] [COLT 2004] + [ICALP 2003] [ICGI 2002]
+ + + Conférences nationales [CAp'06] [CAp'04] [CAp'03]
+ Workshop [TAGI'05]
+ + PhD Thesis + [Université de Provence 2004]
+ + +
+ +
+ + +

+ + Skills +

+
+ +
+ + + Computer languages + +
    +
  • Perl,
  • +
  • Ruby,
  • +
  • Awk,
  • +
  • Python,
  • +
  • Java,
  • +
  • C++,
  • +
  • C,
  • +
  • Objective-C,
  • +
  • PHP,
  • +
  • scripts shell (zsh et bash),
  • +
  • LaTeX, ConTeXt, Metapost
  • +
+
    +
  • CamL
  • +
+
+ + WEB +
    +
  • HTML,
  • +
  • XHTML,
  • +
  • CSS,
  • +
  • SVG,
  • +
  • PHP,
  • +
  • MySQL,
  • +
  • PostGreSQL
  • +
+
+ + + Computer Networks + +
    +
  • Ethernet,
  • +
  • TCP/IP,
  • +
  • UDP,
  • +
  • DHCP,
  • +
  • DNS,
  • +
  • tcpdump,
  • +
  • ethereal,
  • +
  • VPN
  • +
+
+ + + Security + +
    +
  • + + Encryption, +
  • +
  • PGP, GPG,
  • +
  • + + Anonymous Networks, +
  • +
  • Network security
  • +
+
+ + + Project Management + +
    +
  • UML,
  • +
  • Merise,
  • +
  • SVN,
  • +
  • CVS
  • +
+
+ + API + +
    +
  • System V,
  • +
  • POSIX,
  • +
  • STL (C++),
  • +
  • Cocoa (Mac OS X)
  • +
+
+ + + Software + +
    +
  • Entreprise Miner (SAS),
  • +
  • Weka,
  • +
  • Quartz Composer
  • +
+
+ + + Learning Methods + +
    +
  • + + + Attribute selection, + +
  • +
  • + Naïve Bayes, +
  • +
  • + + + Decision Tree, + +
  • +
  • + + + K nearest neighboor, + +
  • +
  • + + + Markov Chains (bigrams, trigrams...), + +
  • +
  • + + + Hidden Markov Models (HMM), + +
  • +
  • + + + Neural Network (Multilayer Perceptron), + +
  • +
  • + SVM, +
  • +
  • + Boosting +
  • +
+
+ + +
+ +
+ + +

+ + Miscellaneous +

+ +

+ + Network Project +

+ +

+ + + I have done with + Emmanuel Godard + the conception of an + + anonymous network protocol (- in french -). + +

+ +

+ + Mac Softwares +

+

+ + I've done some + Mac sofwares. + Such as screen saver using Quartz Composer, Dashboard widgets and + Objective-C. + +

+ +

Web

+

+ + You can see details on how I did this website. +

+ + + +
+
+ +
+ Modified: 04/13/2011 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/about/index.html b/output/n3blog/en/about/index.html new file mode 100644 index 000000000..bfd7d90ed --- /dev/null +++ b/output/n3blog/en/about/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + About + + + + +
+ +
+
+ + +
+ +
+
+
+ + Presentation drawing +
+

+ About +

+ +
+ +
+ + + + + +
+ +
+
+

To better know me

+ +

Une photo de moi

+ +
+
+
+ Name Yann Esposito
+ Education Post Ph. D. in Computer Science
+ School Université de Provence
+ Job IT at Sophia Antipolis (France)
+
+ +

Books I like:

+ +
    +
  • Goëdel, Escher & Bach [Hofstadter]
  • +
  • On Numbers And Games [Conway]
  • +
  • Baudolino [Eco]
  • +
+ +

Movies I like:

+ +
    +
  • Eraserhead [Lynch]
  • +
  • Mullholland Drive [Lynch]
  • +
  • Naked Lunch [Cronenberg]
  • +
  • eXistenZ [Cronenberg]
  • +
+ +

My online bookmarks

+ + +
+ +
+ + +

In two words

+ +

I’m a passionate guy. Passionate about

+ + + +

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.

+ + +
+ +
+ + +

My little story

+ +

I had my Ph. D degree in Computer Science in december 2004 at the LIF (Marseille). During the 3 years of my formation, not only I made my research but I also teach computer science and programming to University degree students. I also developed a program to experiment my theoretical results.

+ +

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.

+ +

Today I work for AirFrance© via Astek. This job need many differents skills, CMS and Web technologies, Perl, JSP, meta-programming…

+ + + + +
+
+ +
+ Modified: 04/29/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/about/old/index.html b/output/n3blog/en/about/old/index.html new file mode 100644 index 000000000..457ef4ae2 --- /dev/null +++ b/output/n3blog/en/about/old/index.html @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + Other website + + + + +
+ + + + Presentation drawing +
+

+ Other website +

+ +
+ +
+ + + + + +
+ +
+
+
+

+ Research + » + +

+

+ My research activities. +

+
+ +
+

+ Student website + » + +

+

+ My student website. ✞ 2007 +

+
+ +
+ + + + +
+
+ +
+ Modified: 10/04/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/about/technical_details/index.html b/output/n3blog/en/about/technical_details/index.html new file mode 100644 index 000000000..f90b54abf --- /dev/null +++ b/output/n3blog/en/about/technical_details/index.html @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + Technical details + + + + +
+ + + + Presentation drawing +
+

+ Technical details +

+ +

+ How this website live. +

+ +
+ +
+ + + + + +
+ +
+
+

This website was completely made from scratch. Most is done using +Vim and I generate pages using +nanoc.

+ +

+ +Pictures were done with +Inkscape and +Gimp. +My website is versionned using the + + DCVS + +Git. + +

+ +

Blog comments are externalized to disqus intense debate. +All I need is a static web server, no PHP, Java, ASP or CGI. +Main advantages of this method concerns the load +and the security of the server.

+ +

+ +If you didn't understood anything, just remember I used only +Opensource +and I mostly all done myself from scratch. + +

+ +

If you want all the gory details I suggest you to read +my article about nanoc.

+ + + + +
+
+ +
+ Modified: 09/28/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/01_nanoc/index.html b/output/n3blog/en/blog/01_nanoc/index.html new file mode 100644 index 000000000..18ce2c0ae --- /dev/null +++ b/output/n3blog/en/blog/01_nanoc/index.html @@ -0,0 +1,190 @@ + + + + + + + + + + + + + + + + + + + + + Nanoc + + + + +
+ + +
+

+ Nanoc +

+ +
+ +
+ + + + + +
+
+
+

What is nanoc?

+ +

It is not exactly a +CMS. +But a Framework to generate static web pages.

+ +

You have to program yourself webpages, the code +to generate the menu…

+ +

I added feature to make my website multilingual for example

+ +

You’ll can find many informations on the +official nanoc website.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Created: 10/10/2008 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/02_ackgrep/code/ack b/output/n3blog/en/blog/02_ackgrep/code/ack new file mode 100644 index 000000000..38a093374 --- /dev/null +++ b/output/n3blog/en/blog/02_ackgrep/code/ack @@ -0,0 +1,14 @@ + +#!/usr/bin/env zsh +(($#<1)) && { print 'usage: ack "regexp"' >&2; exit 1 } + +listeFic=( **/*(.) ) +autoload zargs +zargs -- $listeFic -- grep $1 | perl -ne 'use Term::ANSIColor; +if (m/([^:]*)(:.*)('$1')(.*)/) { + print color("green").$1; + print color("reset").$2; + print color("black","on_yellow").$3; + print color("reset").$4."\n"; +} ' + \ No newline at end of file diff --git a/output/n3blog/en/blog/02_ackgrep/index.html b/output/n3blog/en/blog/02_ackgrep/index.html new file mode 100644 index 000000000..7776fb828 --- /dev/null +++ b/output/n3blog/en/blog/02_ackgrep/index.html @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + + Better than Grep + + + + +
+ + +
+

+ Better than Grep +

+ +
+ +
+ + + + + +
+
+
+

update

+ +

As Andy Lester told me ack is a simple file you only have to copy in your ~/bin folder. Now I’ve got ack on my professional server.

+ +

Go on http://betterthangrep.com to download it.

+ +

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.

+ + +
+ +
+ + +

Better than grep

+ +

One of the my main usage of grep is

+ +
+
+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’, +I had done one myself in very few lines:

+ +
+
+
+#!/usr/bin/env zsh
+(($#<1)) && { print 'usage: ack "regexp"' >&2; exit 1 }
+
+listeFic=( **/*(.) )
+autoload zargs
+zargs -- $listeFic -- grep $1 | perl -ne 'use Term::ANSIColor;
+if (m/([^:]*)(:.*)('$1')(.*)/) {
+    print color("green").$1;
+    print color("reset").$2;
+    print color("black","on_yellow").$3;
+    print color("reset").$4."\n";
+} '
+    
+
+
+
+ +

For my team and I it is usable enough. +I hope it could help.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Created: 07/22/2009 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/03_losthighway/03_losthighway_1/index.html b/output/n3blog/en/blog/03_losthighway/03_losthighway_1/index.html new file mode 100644 index 000000000..e476cb8dd --- /dev/null +++ b/output/n3blog/en/blog/03_losthighway/03_losthighway_1/index.html @@ -0,0 +1,229 @@ + + + + + + + + + + + + + + + + + + + + + A try to demystify 'Lost Highway' + + + + +
+ + +
+

+ A try to demystify 'Lost Highway' +

+ +

+ Movie's keys +

+ +
+ +
+ + + + + +
+
+
+

Movie’s keys

+ +
+ + All is in Fred's memory + +
+ +

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. +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.

+ +
    +
  • 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 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:

+ +
+

“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.

+ +
+ + + +
+ + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Created: 08/04/2009 + Modified: 07/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/03_losthighway/03_losthighway_2/index.html b/output/n3blog/en/blog/03_losthighway/03_losthighway_2/index.html new file mode 100644 index 000000000..d58e3ef07 --- /dev/null +++ b/output/n3blog/en/blog/03_losthighway/03_losthighway_2/index.html @@ -0,0 +1,208 @@ + + + + + + + + + + + + + + + + + + + + + A try to demystify 'Lost Highway' + + + + +
+ + +
+

+ A try to demystify 'Lost Highway' +

+ +

+ Who is the mystery man? +

+ +
+ +
+ + + + + +
+
+
+

Who is the mysterious man?

+ +

l'homme mystérieux

+ +

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. +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.

+ +
+ + + +
+ + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Created: 08/04/2009 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/03_losthighway/03_losthighway_3/index.html b/output/n3blog/en/blog/03_losthighway/03_losthighway_3/index.html new file mode 100644 index 000000000..7fc103411 --- /dev/null +++ b/output/n3blog/en/blog/03_losthighway/03_losthighway_3/index.html @@ -0,0 +1,204 @@ + + + + + + + + + + + + + + + + + + + + + A try to demystify 'Lost Highway' + + + + +
+ + +
+

+ A try to demystify 'Lost Highway' +

+ +

+ Who's at the origin of the video tapes? +

+ +
+ +
+ + + + + +
+
+
+

Who’s at the origin of the video tapes?

+ +

Certainly it’s the mysterious man (Fred himself) who makes them. +Their reason should be:

+ +
    +
  • Remember the reality to Fred. From Fred point-of-view, video tapes are the reality. He tries to forget reality. But, finally, the video tapes go to the end: the murder of his wife.
  • +
  • It may also be a reference to pornographic video tapes, made by Renee.
  • +
+ +
+ + + +
+ + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Created: 08/04/2009 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/03_losthighway/03_losthighway_4/index.html b/output/n3blog/en/blog/03_losthighway/03_losthighway_4/index.html new file mode 100644 index 000000000..48cf2cc47 --- /dev/null +++ b/output/n3blog/en/blog/03_losthighway/03_losthighway_4/index.html @@ -0,0 +1,227 @@ + + + + + + + + + + + + + + + + + + + + + A try to demystify 'Lost Highway' + + + + +
+ + +
+

+ A try to demystify 'Lost Highway' +

+ +

+ What really happened? +

+ +
+ +
+ + + + + +
+
+
+

What really happened?

+ +

There is many possibilities here. But we have many indices. Here is a supposition.

+ +

#1 Hypothesis

+ +

The protagonist is a garagist fallen in love with a porno actress. He believe the producer is the bad guy who go again his will. Then he kills Dick Laurent.

+ +

#2 Hypothesis

+ +

He was really married, he had killed his wife. The the remorse let him create an alternate self, which live in a kind of perfect world. But after the time pass, his obsession about the murder came again. And nobody could know if he had killed Andy or not.

+ +

which one then?

+ +

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.

+ +

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.

+ + +
+ +
+ + +

Conclusion

+ +

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’d like to know or opinion ; is my interpration wrong?

+ +
+ + + +
+ + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Created: 08/04/2009 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/03_losthighway/index.html b/output/n3blog/en/blog/03_losthighway/index.html new file mode 100644 index 000000000..d570b90d8 --- /dev/null +++ b/output/n3blog/en/blog/03_losthighway/index.html @@ -0,0 +1,246 @@ + + + + + + + + + + + + + + + + + + + + + + + A try to demystify 'Lost Highway' + + + + +
+ + +
+

+ A try to demystify 'Lost Highway' +

+ +

+ introduction +

+ +
+ +
+ + + + + +
+
+
+

Lost Highway

+ +
+...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... +
+ +

Lost Higway is a really good movie. You keep watching it event it seem totally obscure. This is one of the strength of David Lynch.

+ +

The first time I watched Lost Highway, I was a bit lost. +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,
  • +
+ +

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:

+ +
    +
  • the first is mediacircus,
  • +
  • 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.

+ +

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

+ +

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.

+ +
    +
  • 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.

+ +

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.

+ +

I write this post because I believe I had found an interpretation which seems coherent for most of the movie.

+ +
+ + + +
+ + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Created: 08/04/2009 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/04_drm/index.html b/output/n3blog/en/blog/04_drm/index.html new file mode 100644 index 000000000..1c55e83a8 --- /dev/null +++ b/output/n3blog/en/blog/04_drm/index.html @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + DRM are EVIL + + + + +
+ + +
+

+ DRM are EVIL +

+ +

+ DRM are bad (+1) +

+ +
+ +
+ + + + + +
+
+
+

DRM are EVIL (+1)

+ +

My wife bought about 500€ (at least) of TV Shows on iTunes. She bought the first season of Battlestar Gallactica in english (she notified the language after the dowload). DRM make it impossible to play it with french sub-titles.

+ +
+

WTF?

+
+ +

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.

+ +
+ +Therefore far less money for you EVIL Copyrighter!!!!! + +
+ +

My wife won’t see these episodes.
+This is a ‘LOSE-LOSE’ cooperation.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Created: 08/15/2009 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/05_git_create_remote_branch/code/git-create-new-branch.sh b/output/n3blog/en/blog/05_git_create_remote_branch/code/git-create-new-branch.sh new file mode 100644 index 000000000..b72b97815 --- /dev/null +++ b/output/n3blog/en/blog/05_git_create_remote_branch/code/git-create-new-branch.sh @@ -0,0 +1,14 @@ + +#!/usr/bin/env zsh + +if (($#<1)); then + print -- "usage: $0:t branch_name" >&2 + exit 1 +fi + +branch=$1 +git br ${branch} +git co ${branch} +git config branch.${branch}.remote origin +git config branch.${branch}.merge refs/heads/${branch} + \ No newline at end of file diff --git a/output/n3blog/en/blog/05_git_create_remote_branch/index.html b/output/n3blog/en/blog/05_git_create_remote_branch/index.html new file mode 100644 index 000000000..ac5722afc --- /dev/null +++ b/output/n3blog/en/blog/05_git_create_remote_branch/index.html @@ -0,0 +1,220 @@ + + + + + + + + + + + + + + + + + + + + + + + Git remote branch creation + + + + +
+ + +
+

+ Git remote branch creation +

+ +
+ +
+ + + + + +
+
+
+

easiest remote Git branch creation

+ +

I use git simply to synchronize stuff for personnal projects. +Therefore, when I create a local branch I want most of time this +branch to be created remotely.

+ +

Here is the script I use to achieve that:

+ +
+
+
+#!/usr/bin/env zsh
+
+if (($#<1)); then
+    print -- "usage: $0:t branch_name" >&2
+    exit 1
+fi
+
+branch=$1
+git br ${branch}
+git co ${branch}
+git config branch.${branch}.remote origin
+git config branch.${branch}.merge refs/heads/${branch}
+    
+
+
+
+ +

Of course, I suppose origin is already configured.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+ +
+ + +
+ +
+ Created: 08/17/2009 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/06_How_I_use_git/code/git-create-new-branch b/output/n3blog/en/blog/06_How_I_use_git/code/git-create-new-branch new file mode 100644 index 000000000..add959c52 --- /dev/null +++ b/output/n3blog/en/blog/06_How_I_use_git/code/git-create-new-branch @@ -0,0 +1,13 @@ + +#!/usr/bin/env zsh + +if (($#<1)); then + print -- "usage: $0:t branch_name" >&2 + exit 1 +fi + +branch=$1 +git br ${branch} +git co ${branch} +git config branch.${branch}.remote origin +git config branch.${branch}.merge refs/heads/${branch} diff --git a/output/n3blog/en/blog/06_How_I_use_git/code/git-get-remote-branches b/output/n3blog/en/blog/06_How_I_use_git/code/git-get-remote-branches new file mode 100644 index 000000000..ca1ef8c3b --- /dev/null +++ b/output/n3blog/en/blog/06_How_I_use_git/code/git-get-remote-branches @@ -0,0 +1,14 @@ + +#!/usr/bin/env zsh + +# recup branches not on local +localbranches=( $(git br | sed 's/\*/ /') ) +remoteMissingBranches=( $(git br -r | \ + egrep -v "origin/HEAD|(${(j:|:)localbranches})" ) ) +for br in $remoteMissingBranches; do + branch=${br#origin/} + print "get remote branch $branch" + git br ${branch} + git config branch.${branch}.remote origin + git config branch.${branch}.merge refs/heads/${branch} +done diff --git a/output/n3blog/en/blog/06_How_I_use_git/index.html b/output/n3blog/en/blog/06_How_I_use_git/index.html new file mode 100644 index 000000000..37edfe210 --- /dev/null +++ b/output/n3blog/en/blog/06_How_I_use_git/index.html @@ -0,0 +1,368 @@ + + + + + + + + + + + + + + + + + + + + + + + Git for self + + + + +
+ + +
+

+ Git for self +

+ +
+ +
+ + + + + +
+
+
+

central architecture

+ +

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.

+ +

In two words, if you want to use an SVN workflow with Git (and all its advantages) here is how to proceed.

+ + +
+ +
+ + +

Initialisation

+ +

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/
+git init
+git add
+git commit
+
+
+ +

Now all files in the to/project/directory/ are versionned. +If you want not to follow some just edit the file .gitignore

+ +

for example mine is:

+ +
+
+*.swp
+.DS_Store
+ikog.py.bak
+output/n3blog/assets
+output/n3blog/en
+output/n3blog/fr
+output/n3blog/multi
+
+
+ +

Next, you want to put your project on a directory accessible from the web:

+ +
+
+git clone --bare . /path/to/repository
+
+
+ +

Now on any computer you can do:

+ +
+
+git clone protocol://path/to/repository local_directory
+
+
+ +

and local_directory will contain an up-to-date project.

+ +
+You should make this operation also on the computer used to create the repository. Just to verify all will be okay. + + +
+ + +
+ +
+ + +

The workflow

+ +

To resume you now have one repository on the Internet, and one or many computer associated with it. Now, what you want is to synchronize everything.

+ +

Before begining your work, the first thing to do is to get all modification from the Internet to your local host:

+ +
+
+git pull
+
+
+ +

After that you can do (many times):

+ +
+
+hack, hack, hack...
+git add some files
+git commit
+
+
+ +

When you want your local modification to be on the Internet just do a simple:

+ +
+
+git push
+
+
+ +

All should be ok.

+ +

If you have some trouble with the push and pull verify your .git/config file ; it should contain the following lines:

+ +
+
+...
+[remote "origin"]
+	url = protocol://url/of/the/repository
+	fetch = +refs/heads/*:refs/remotes/origin/*
+[branch "master"]
+	remote = origin
+	merge = refs/heads/master
+...
+
+
+ +

Branches Synchronisation

+ +

Well, now, all seems ok, but you have to worry about two little things. Git is all about decentralisation and branches. It is very easy to manage one branch, or many branches on the same host. But synchronize branches on many hosts is not a natural operation.

+ +

This is why I created two simple scripts to automate this. One for creating a branch locally and remotely. And one to get remotely created branched on your local host.

+ +

Then when you want to create a new branch (locally and remotely) ; you simply have to do a:

+ +
git-create-new-branch branch_name
+
+ +

and when you are on another computer and want to get locally all the remote branches you execute:

+ +
git-get-remote-branches
+
+ +

Here are the code of theese two scripts:

+ +
+
+
+#!/usr/bin/env zsh
+
+if (($#<1)); then
+    print -- "usage: $0:t branch_name" >&2
+    exit 1
+fi
+
+branch=$1
+git br ${branch}
+git co ${branch}
+git config branch.${branch}.remote origin
+git config branch.${branch}.merge refs/heads/${branch}
+
+
+
+ +
+
+
+#!/usr/bin/env zsh
+
+# recup branches not on local
+localbranches=( $(git br | sed 's/\*/ /') )
+remoteMissingBranches=( $(git br -r | \
+    egrep -v "origin/HEAD|(${(j:|:)localbranches})" ) )
+for br in $remoteMissingBranches; do
+  branch=${br#origin/}
+  print "get remote branch $branch"
+  git br ${branch}
+  git config branch.${branch}.remote origin
+  git config branch.${branch}.merge refs/heads/${branch}
+done
+
+
+
+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ + + + +
+ +
+ Created: 08/18/2009 + Modified: 11/17/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/07_Screensaver_compilation_option_for_Snow_Leopard/index.html b/output/n3blog/en/blog/07_Screensaver_compilation_option_for_Snow_Leopard/index.html new file mode 100644 index 000000000..f5564ab81 --- /dev/null +++ b/output/n3blog/en/blog/07_Screensaver_compilation_option_for_Snow_Leopard/index.html @@ -0,0 +1,204 @@ + + + + + + + + + + + + + + + + + + + + + + + Screensaver compilation option for Snow Leopard<sub>©</sub> + + + + +
+ + +
+

+ Screensaver compilation option for Snow Leopard© +

+ +
+ +
+ + + + + +
+
+
+

How to recompile your screensaver to be Snow Leopard© compatible

+ +

I upgraded to Mac OS X 10.6 Snow Leopard©, and my YClock screensaver didn’t work on it. After searching on google, the problem seems to be just a recompilation away. +Unfortunately, event recompiling it in 64 bit it didn’t work either. +After a bit more research (thanks to ElectricSheep ).

+ +

I discovered the good parameters for compilation.

+ +

XCode configuration

+ +

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.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+ +
+ + +
+ +
+ Created: 09/06/2009 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/08_Configure_ssh_to_listen_the_port_443_on_Snow_Leopard/code/ssh-443.plist b/output/n3blog/en/blog/08_Configure_ssh_to_listen_the_port_443_on_Snow_Leopard/code/ssh-443.plist new file mode 100644 index 000000000..9cccfce9d --- /dev/null +++ b/output/n3blog/en/blog/08_Configure_ssh_to_listen_the_port_443_on_Snow_Leopard/code/ssh-443.plist @@ -0,0 +1,35 @@ + + + + + + Disabled + + Label + local.sshd + Program + /usr/libexec/sshd-keygen-wrapper + ProgramArguments + + /usr/sbin/sshd + -i + + Sockets + + Listeners + + SockServiceName + https + + + inetdCompatibility + + Wait + + + StandardErrorPath + /dev/null + SHAuthorizationRight + system.preferences + + diff --git a/output/n3blog/en/blog/08_Configure_ssh_to_listen_the_port_443_on_Snow_Leopard/index.html b/output/n3blog/en/blog/08_Configure_ssh_to_listen_the_port_443_on_Snow_Leopard/index.html new file mode 100644 index 000000000..b39ee948c --- /dev/null +++ b/output/n3blog/en/blog/08_Configure_ssh_to_listen_the_port_443_on_Snow_Leopard/index.html @@ -0,0 +1,266 @@ + + + + + + + + + + + + + + + + + + + + + + + ssh to Listen 443 on Snow Leopard + + + + +
+ + +
+

+ ssh to Listen 443 on Snow Leopard +

+ +
+ +
+ + + + + +
+
+
+

Surf everywhere as if you were at home

+ +

In order to bypass evil company firewall and to surf safely on unsafe wifi. I keep an ssh server listening on the port 443.

+ +

Then from my laptop or my local computer I just have to launch the marvelous

+ +
+
+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.

+ +

I get this information from this post.

+ +

Ssh and Snow Leopard©

+ +

Here I don’t want to talk about how great socks proxy via ssh tunneling is but how to configure my local server.

+ +

I have Mac with Snow Leopard© at home and it is far from enough to modify the /etc/sshd.config file. The system use launchd to launch starting daemons.

+ +

I posted the question on Apple Discussions in this discussion thread. Thanks to all guys who helped me. And the solution is:

+ +

Create the file /Library/LaunchDaemons/ssh-443.plist containing:

+ +
+
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>Disabled</key>
+	<false/>
+	<key>Label</key>
+	<string>local.sshd</string>
+	<key>Program</key>
+	<string>/usr/libexec/sshd-keygen-wrapper</string>
+	<key>ProgramArguments</key>
+	<array>
+		<string>/usr/sbin/sshd</string>
+		<string>-i</string>
+	</array>
+	<key>Sockets</key>
+	<dict>
+		<key>Listeners</key>
+		<dict>
+			<key>SockServiceName</key>
+			<string>https</string>
+		</dict>
+	</dict>
+	<key>inetdCompatibility</key>
+	<dict>
+		<key>Wait</key>
+		<false/>
+	</dict>
+	<key>StandardErrorPath</key>
+	<string>/dev/null</string>
+        <key>SHAuthorizationRight</key>
+        <string>system.preferences</string>
+</dict>
+</plist>
+
+
+
+ +

It is a copy of /System/Library/LaunchDaemons/ssh.plist with some modifications:

+ +
    +
  • the SockServiceName from ssh to https.
  • +
  • the Label from com.openssh.sshd to something not existing as local.sshd
  • +
+ +

Tell me if it was helpfull or if you have any question.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ + + + +
+ +
+ Created: 09/07/2009 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/09_Why_I_didn-t_keep_whosamung-us/index.html b/output/n3blog/en/blog/09_Why_I_didn-t_keep_whosamung-us/index.html new file mode 100644 index 000000000..2dfd0d576 --- /dev/null +++ b/output/n3blog/en/blog/09_Why_I_didn-t_keep_whosamung-us/index.html @@ -0,0 +1,204 @@ + + + + + + + + + + + + + + + + + + + + + + + Why I didn't keep whos.amung.us + + + + +
+ + +
+

+ Why I didn't keep whos.amung.us +

+ +
+ +
+ + + + + +
+
+
+

I changed from whos.amung.us to Google Analytics.

+ +

Most of time I prefer not to use the same product as everybody and try some new. But this time I believe whosamung.us had too much ads on the page. I had to put their image on my website and they only give then number of user currently on the website, not the number of visits.

+ +

This is why I now use google analytics. The only problem, remains for pages with no javascript support.

+ +

Then for now: +<div class="encadre"> +Theorem:

+
+Google Analytics > Who's Amung Us +
+
+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ + + + +
+ +
+ Created: 09/11/2009 + Modified: 09/02/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/10_Synchronize_Custom_WebSite_with_mobileMe/code/publish b/output/n3blog/en/blog/10_Synchronize_Custom_WebSite_with_mobileMe/code/publish new file mode 100644 index 000000000..466320d4f --- /dev/null +++ b/output/n3blog/en/blog/10_Synchronize_Custom_WebSite_with_mobileMe/code/publish @@ -0,0 +1,102 @@ + +#!/usr/bin/env zsh + +# Author: Yann Esposito +# Mail: yann.esposito@gmail.com +# Synchronize with "mobileMe" iDisk account. + +mobileMeUser="firstname.lastname" +siteName="siteName" + +# 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 does not exist ; please verify the configuration ($0)" >&2; + exit 1 +} + +[[ ! -d $destRep ]] && { + print -- "$destRep does not exist, please mount the filesystem" >&2; + exit 1 +} + +if [[ $1 == '-h' ]]; then + print -- "usage: $0:h [-h|-a|-s]" + print -- " -a sychronize primary index" + print -- " -h show this help" + print -- " -s only swap directories" +fi + +if [[ $1 == '-a' ]]; then + print -- "Index synchronisation (${destRep:h})" + rsync -av $root/index.html ${destRep:h}/index.html +fi + +print -- "Root = $root" +print -- "Dest = $destRep" + +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/n3blog/ $destRep.tmp + result=$? + if (( $result > 0 )); then + print -P -- "%Brsync failed%b (try n°$essai)" >&2 + fi + ((essai++)) + done +fi + +# SWAP +print -P -- "%B[Directory Swap (tmp <=> target)]%b" +essai=1 +while [[ -e $destRep.old ]]; do + print -n -- "remove $destRep.old" + if ((essai>1)); then + print " (try n°$essai)" + else + print + fi + ((essai++)) + \rm -rf $destRep.old +done + +print -- " renommage du repertoire sandard vers le .old" +essai=1 +while [[ -e $destRep ]]; do + mv $destRep $destRep.old + (($?)) && print -- "Failed to rename (try n°$essai)" >&2 + ((essai++)) +done + +print -- " renaming folder tmp (new) to the standard one" +print -P -- " %BThe WebSite isn't working%b $(date)" +essai=1 +while [[ ! -e $destRep ]]; do + mv $destRep.tmp $destRep + (($?)) && print -P -- "%B[WebSite not working]%b(try n°$essai) Failed to rename (mv $destRep.tmp $destRep)" >&2 + ((essai++)) +done + +print -P -- "\t===\t%BWEBSITE SHOULD WORK NOW%b\t===" + +print -- " rename old folder to tmp folder" +essai=1 +while [[ ! -e $destRep ]]; do + mv $destRep.old $destRep.tmp + (($?)) && print -P -- "Failed to rename n°$essai" >&2 + ((essai++)) +done + +print -P -- " Publish terminated" diff --git a/output/n3blog/en/blog/10_Synchronize_Custom_WebSite_with_mobileMe/index.html b/output/n3blog/en/blog/10_Synchronize_Custom_WebSite_with_mobileMe/index.html new file mode 100644 index 000000000..590a722a4 --- /dev/null +++ b/output/n3blog/en/blog/10_Synchronize_Custom_WebSite_with_mobileMe/index.html @@ -0,0 +1,443 @@ + + + + + + + + + + + + + + + + + + + + + + + Synchronize Custom WebSite with mobileMe + + + + +
+ + +
+

+ Synchronize Custom WebSite with mobileMe +

+ +
+ +
+ + + + + +
+
+
+

Update (2009/10/28)

+ +

I updated my script which is now incremental. Since the writing of this article, Apple© had made many efforts about the bandwith of its European servers.

+ + +
+ +
+ + +

WebDav terror

+ +

I live in France and iDisk upload is just terrible. Upload speed remind me the old 56k modem. Most operations such as list the content of a directory take at least 30 seconds (for 15 elements). Renaming a directory fail most of time.

+ +

Apple© use a WebDav server to host files. It works on port 80 (like http). I realized WebDav via https work better (2 to 3 times faster with far less errors). But even https is too slow.

+ +

I upload from my Mac and sometimes from an Ubuntu PC (iDisk mounted with webdavfs).

+ +

Synchronize safely the website

+ +

Here is the script I use in order to synchronize my website with maximum safety. It try each operations until it works.

+ +

The idea are:

+ +
    +
  • Synchroniser vers un répertoire temporaire sur le serveur distant, puis “swapper” les noms des répertoires. Ainsi le site ne reste indisponible que le temps du “swap” du nom des deux répertoires.
  • +
  • Réitérer toutes les opérations jusqu’à ce qu’elle aient réussi (par exemple pour le renommage)
  • +
+ +

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.

+ +

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).

+ +
+
+
+#!/usr/bin/env zsh
+
+# 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"
+
+# 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; 
+    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 == '-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"
+
+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/n3blog/ $destRep.tmp
+        result=$?
+        if (( $result > 0 )); then
+            print -P -- "%BEchec du rsync%b (essai n°$essai)" >&2
+        fi
+        ((essai++))
+    done
+fi
+
+# 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
+        print
+    fi
+    ((essai++))
+    \rm -rf $destRep.old
+done
+
+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
+    ((essai++))
+done
+
+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
+    ((essai++))
+done
+
+print -P -- "\t===\t%BSITE DISPONIBLE%b\t==="
+
+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
+    ((essai++))
+done
+
+print -P -- "  publication terminée"
+
+
+
+ +
+
+
+#!/usr/bin/env zsh
+
+# Author: Yann Esposito
+#   Mail: yann.esposito@gmail.com
+# Synchronize with "mobileMe" iDisk account.
+
+mobileMeUser="firstname.lastname"
+siteName="siteName"
+
+# 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 does not exist ; please verify the configuration ($0)" >&2; 
+    exit 1 
+}
+
+[[ ! -d $destRep ]] && { 
+    print -- "$destRep does not exist, please mount the filesystem" >&2; 
+    exit 1 
+}
+
+if [[ $1 == '-h' ]]; then
+    print -- "usage: $0:h [-h|-a|-s]"
+    print -- "  -a sychronize primary index"
+    print -- "  -h show this help"
+    print -- "  -s only swap directories"
+fi
+
+if [[ $1 == '-a' ]]; then
+    print -- "Index synchronisation (${destRep:h})"
+    rsync -av $root/index.html ${destRep:h}/index.html
+fi
+
+print -- "Root = $root"
+print -- "Dest = $destRep"
+
+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/n3blog/ $destRep.tmp
+        result=$?
+        if (( $result > 0 )); then
+            print -P -- "%Brsync failed%b (try n°$essai)" >&2
+        fi
+        ((essai++))
+    done
+fi
+
+# SWAP
+print -P -- "%B[Directory Swap (tmp <=> target)]%b"
+essai=1
+while [[ -e $destRep.old ]]; do
+    print -n -- "remove $destRep.old"
+    if ((essai>1)); then 
+        print " (try n°$essai)"
+    else
+        print
+    fi
+    ((essai++))
+    \rm -rf $destRep.old
+done
+
+print -- "  renommage du repertoire sandard vers le .old"
+essai=1
+while [[ -e $destRep ]]; do
+    mv $destRep $destRep.old 
+    (($?)) && print -- "Failed to rename (try n°$essai)" >&2
+    ((essai++))
+done
+
+print -- "  renaming folder tmp (new) to the standard one"
+print -P -- "  %BThe WebSite isn't working%b $(date)"
+essai=1
+while [[ ! -e $destRep ]]; do
+    mv $destRep.tmp $destRep
+    (($?)) && print -P -- "%B[WebSite not working]%b(try n°$essai) Failed to rename (mv $destRep.tmp $destRep)" >&2
+    ((essai++))
+done
+
+print -P -- "\t===\t%BWEBSITE SHOULD WORK NOW%b\t==="
+
+print -- "  rename old folder to tmp folder"
+essai=1
+while [[ ! -e $destRep ]]; do
+    mv $destRep.old $destRep.tmp
+    (($?)) && print -P -- "Failed to rename n°$essai" >&2
+    ((essai++))
+done
+
+print -P -- "  Publish terminated"
+
+
+
+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ + + + +
+ +
+ Created: 09/11/2009 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/11_Load_Disqus_Asynchronously/index.html b/output/n3blog/en/blog/11_Load_Disqus_Asynchronously/index.html new file mode 100644 index 000000000..48245b46d --- /dev/null +++ b/output/n3blog/en/blog/11_Load_Disqus_Asynchronously/index.html @@ -0,0 +1,265 @@ + + + + + + + + + + + + + + + + + + + + + + + Load Disqus Asynchronously + + + + +
+ + +
+

+ Load Disqus Asynchronously +

+ +
+ +
+ + + + + +
+
+
+

Update

+ +

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 :-).

+ + +
+ +
+ + +

Before begining, I must state that I love Disqus.

+ +

I know there is a similar blog entry at Trephine.org. Here I just add a straight and easy way to load disqus asynchronously using jQuery.

+ +

I also know there is a jQuery plugin to make just that. Unfortunately I had some issue with CSS.

+ +

Now let’s begin.

+ + +
+ +
+ + +

Why?

+ +

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.
  • +
  • More independance: when disqus is down, my page is blocked!
  • +
+ + +
+ +
+ + +

How?

+ +

I give a solution with jQuery, but I’m certain it will work with many other js library.

+ +

Javascript

+ +

replace:

+ +
+
+<script type="text/javascript" src="http://disqus.com/forums/YOUR_DISQUS_ID/embed.js"></script>
+
+
+ +

by

+ +
+
+window.disqus_no_style=true;
+$(document).ready(function(){
+    $.getScript("http://disqus.com/forums/YOUR_DISQUS_ID/embed.js");
+});
+
+
+ +

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.

+ +

CSS

+ +

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.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ + + + +
+ +
+ Created: 09/17/2009 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2009-09-Disqus-versus-Intense-Debate--Why-I-switched-/index.html b/output/n3blog/en/blog/2009-09-Disqus-versus-Intense-Debate--Why-I-switched-/index.html new file mode 100644 index 000000000..ab782f01e --- /dev/null +++ b/output/n3blog/en/blog/2009-09-Disqus-versus-Intense-Debate--Why-I-switched-/index.html @@ -0,0 +1,229 @@ + + + + + + + + + + + + + + + + + + + + + + + Disqus versus Intense Debate (Why I switched) + + + + +
+ + +
+

+ Disqus versus Intense Debate (Why I switched) +

+ +
+ +
+ + + + + +
+
+
+

Disqus vs. Intense Debate

+ +

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).

+ +

I am a bit sad to quit Disqus because I must confess giannii had helped me has efficiently as he could. But the problem I had with disqus are inherent to some design choice not simply technical ones.

+ +

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:

+ +
+
+document.getElementsByTagName("head")[0].appendChild(commentScript);
+
+
+ +

by:

+ +
+
+$(document).ready( function() {
+    document.getElementsByTagName("head")[0].appendChild(commentScript);
+});
+
+
+ +

And the Winner is: Intense Debate

+ +

To conclude, main advantages (for me) of Intense Debate over Disqus:

+ +
    +
  • Load Asynchronously ; don’t block my website
  • +
  • Add for free buttons like “share to any” and load them asynchronously.
  • +
+ +

Voilà.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Created: 09/28/2009 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2009-09-jQuery-Tag-Cloud/index.html b/output/n3blog/en/blog/2009-09-jQuery-Tag-Cloud/index.html new file mode 100644 index 000000000..dc5d1c31d --- /dev/null +++ b/output/n3blog/en/blog/2009-09-jQuery-Tag-Cloud/index.html @@ -0,0 +1,2028 @@ + + + + + + + + + + + + + + + + + + + + + + + jQuery Tag Cloud + + + + +
+ + +
+

+ jQuery Tag Cloud +

+ +
+ +
+ + + + + +
+
+
+

Here is how I done the tag cloud of my blog. It is done mostly in jQuery. +All my site is static and pages are generated with nanoc. +It is (in my humble opinion) the modern geek way to make a website. +The tagcloud should work for machine with and without javascript.

+ +

This is why I’ll give only a Ruby Generator, not a full javascript generator. +But you can easily translate from Ruby to Javascript.

+ +

Here is what you should obtain:

+ + +
+ +
+ + +
+

alternate reality

analyser

analytics

Apple

Asynchronous

awk

Bazaar

blacklist

blog

branch

branches

bzr

Cappuccino

Chrome

Cocoa

comments

CSS

David Lynch

DCVS

dcvs

design

disqus

diverged

drm

email

extension

file

filter

Firefox

Fonts

git

Google

hide

HTML

indecidability

intense debate

iPhone

iTunes

javascript

jQuery

Linux

local

Lost Highway

mac

Mac

mathematics

mobileme

movie

multi-language

nanoc

Objective-C

OS X

philosophy

programming

Programming

protection

regexp

regular expression

remote

ruby

S/MIME

Safari

science

screensaver

script

security

shell

ssh

statistics

svn

synchronisation

theory

tip

tree

Ubuntu

User

web

WebDav

webdesign

workflow

zsh

+
+ + +
+ +
+ + +

jQuery

+ +

Here is the simple jQuery code:

+ +
+
+    $(document).ready( function(){$('.list').hide();} );
+    function tagSelected(id) {
+        $('.list').hide();
+        $('#'+id).fadeIn();
+        $('.tag.selected').removeClass('selected');
+        $('#tag_'+id).addClass('selected');
+    }
+
+
+ +

This code will hide all the div containing links to articles containing the tag. And create a function do show the div containing the tag.

+ +

For each tag I create a span element:

+ +
+
+    <span   style="font-size: 1.0em;" 
+            class="tag" 
+            onClick="tagSelected('[TAG]')" 
+            id="tag_[TAG]">
+        [TAG]
+    </span> 
+
+
+ +

and a div containing links associtated to this tag:

+ +
+
+    <div id="[TAG]">
+        <h4>[TAG]</h4>
+        <ul>
+            <li> LINK 1 </li>
+            <li> LINK 2 </li>
+        </ul>
+    </div> 
+
+
+ + +
+ +
+ + +

nanoc

+ +

Here is how I generate this using nanoc 2.

+ +

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.

+ +
+
+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
+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 ... ]
+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 +of the maximal size.

+ +
+
+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
+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 '&nbsp;'
+        protected=t.gsub(/&/,'&amp;').gsub(/ /,'&nbsp;').gsub(/</,'&lt;').gsub(/>/,'&gt;')
+        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
+
+
+ +

You can download the complete file to put in your ‘lib’ directory.

+ +

Of course to be nice you need the associated CSS

+ +
+
+
+// Change the color when mouse over
+.tag:hover {
+  color: #cc0000; }
+
+// Change the color when tag selected
+.tag.selected {
+  color: #6c0000; }
+
+// a bit of space and pointer cursor
+.tag {
+  cursor: pointer;
+  margin-left: .5em;
+  margin-right: .5em; }
+
+
+ +

That’s all folks.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ + + + +
+ +
+ Created: 09/23/2009 + Modified: 06/17/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2009-09-replace-all-except-some-part/index.html b/output/n3blog/en/blog/2009-09-replace-all-except-some-part/index.html new file mode 100644 index 000000000..bf777ff82 --- /dev/null +++ b/output/n3blog/en/blog/2009-09-replace-all-except-some-part/index.html @@ -0,0 +1,271 @@ + + + + + + + + + + + + + + + + + + + + + + + replace all except some part + + + + +
+ + +
+

+ replace all except some part +

+ +
+ +
+ + + + + +
+
+
+

My problem is simple:

+ +

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
+...
+text
+...
+END not to filter
+...
+text
+...
+
+
+ +

I searched a better way to do that, but the best I can do is using split and scan.

+ +
+
+def allExceptCode( f, content )
+    regexp=/<code[^>]*>.*?<\/code>/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
+
+
+ +

An usage is:

+ +
+
+def filter(content)
+    content.gsub(/e/,'X')
+end
+...
+allExceptCode(:filter, content)
+...
+
+
+ +

A better syntax would be:

+ +
+
+# !!!!!!!!!! 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
+
+
+ +

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.

+ +

If someone know a nicer way to do that I will be happy to know how.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ + + + +
+ +
+ Created: 09/22/2009 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/code/publish b/output/n3blog/en/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/code/publish new file mode 100644 index 000000000..884fc5ee3 --- /dev/null +++ b/output/n3blog/en/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/code/publish @@ -0,0 +1,119 @@ + +#!/usr/bin/env zsh + +# 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 + +# 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" + rsyncPublish + swap + 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 + swap + fi + fi +} + +# 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 + ((essai++)) + done +} + +# swap +function swap { + 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 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 -P -- " publication terminée" +} + +print -- "Root = $webroot" +print -- "Dest = $destRep" + +if [[ "$1" = "-s" ]]; then + swap +else + if [[ "$1" = "-d" ]]; then + suffix="" + else + suffix=".tmp" + fi + print -P -- "%BSync%b[${Root:t} => ${destRep:t}$suffix]" + incrementalPublish +fi diff --git a/output/n3blog/en/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/code/webdav-framework b/output/n3blog/en/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/code/webdav-framework new file mode 100644 index 000000000..f83af7601 --- /dev/null +++ b/output/n3blog/en/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/code/webdav-framework @@ -0,0 +1,109 @@ + +#!/usr/bin/env zsh + +function samelineprint { + print -n -P -- "\r$*" +} + +# avec 1 essai par seconde: 300 = 5 minutes +maxessais=300 + +# try to create a directory until success +function trymkdir { + target="$1" + print -- mkdir -p $target + local essai=1 + while ! mkdir -p $target; do + samelineprint "Echec: essai n°$essai" + ((essai++)) + ((essai>maxessais)) && exit 5 + done + print +} + +# try to copy until success +function trycp { + 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" + ((essai++)) + ((essai>maxessais)) && exit 5 + done + print +} + +# try to remove until success +function tryrm { + 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" + ((essai++)) + ((essai>maxessais)) && exit 5 + done + essai=1 + while [[ -e $element ]]; do + samelineprint "rm reussi mais fichier source non disparu n°$essai" + sleep 1 + ((essai++)) + ((essai>maxessais)) && exit 5 + done + print +} + +# try to rename until success +function tryrename { + element="$1" + target="$2" + local essai=1 + while [[ -e $target ]]; do + samelineprint "Echec n°$essai le fichier $target existe déjà" + ((essai++)) + ((essai>maxessais)) && exit 5 + sleep 1 + done + print -- mv $element $target + while ! mv $element $target; do + samelineprint "Echec: essai n°$essai" + ((essai++)) + ((essai>maxessais)) && exit 4 + done + essai=1 + while [[ -e $element ]]; do + samelineprint "mv reussi mais fichier source non disparu n°$essai" + sleep 1 + ((essai++)) + ((essai>maxessais)) && exit 5 + done + print +} + +# try to move until success +function trymv { + element="$1" + target="$2" + local essai=1 + print -- mv $element $target + while ! mv $element $target; do + samelineprint "Echec: essai n°$essai" + ((essai++)) + ((essai>maxessais)) && exit 5 + done + essai=1 + while [[ -e $element ]]; do + samelineprint "mv reussi mais fichier source non disparu n°$essai" + sleep 1 + ((essai++)) + ((essai>maxessais)) && exit 5 + done + print +} diff --git a/output/n3blog/en/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/index.html b/output/n3blog/en/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/index.html new file mode 100644 index 000000000..b1ad7014b --- /dev/null +++ b/output/n3blog/en/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/index.html @@ -0,0 +1,452 @@ + + + + + + + + + + + + + + + + + + + + + + + custom website synchronisation with mobileme (2) + + + + +
+ + +
+

+ custom website synchronisation with mobileme (2) +

+ +
+ +
+ + + + + +
+
+
+

I already talked about how I synchronized my website with mobileme. I ameliorated this script in order to make it incremental.

+ +

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:

+ +
+mv folder folder2
+
+ +

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.

+ +
+
+#!/usr/bin/env zsh
+
+function samelineprint {
+    print -n -P -- "\r$*"
+}
+
+# avec 1 essai par seconde: 300 = 5 minutes
+maxessais=300
+
+# try to create a directory until success
+function trymkdir {
+    target="$1"
+    print -- mkdir -p $target
+    local essai=1
+    while ! mkdir -p $target; do
+        samelineprint "Echec: essai n°$essai"
+        ((essai++))
+        ((essai>maxessais)) && exit 5
+    done
+    print
+}
+
+# try to copy until success
+function trycp {
+    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"
+        ((essai++))
+        ((essai>maxessais)) && exit 5
+    done
+    print
+}
+
+# try to remove until success
+function tryrm {
+    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"
+        ((essai++))
+        ((essai>maxessais)) && exit 5
+    done
+    essai=1
+    while [[ -e $element ]]; do
+        samelineprint "rm reussi mais fichier source non disparu n°$essai"
+        sleep 1
+        ((essai++))
+        ((essai>maxessais)) && exit 5
+    done
+    print
+}
+
+# try to rename until success
+function tryrename {
+    element="$1"
+    target="$2"
+    local essai=1
+    while [[ -e $target ]]; do
+        samelineprint "Echec n°$essai le fichier $target existe déjà"
+        ((essai++))
+        ((essai>maxessais)) && exit 5
+        sleep 1
+    done
+    print -- mv $element $target
+    while ! mv $element $target; do
+        samelineprint "Echec: essai n°$essai"
+        ((essai++))
+        ((essai>maxessais)) && exit 4
+    done
+    essai=1
+    while [[ -e $element ]]; do
+        samelineprint "mv reussi mais fichier source non disparu n°$essai"
+        sleep 1
+        ((essai++))
+        ((essai>maxessais)) && exit 5
+    done
+    print
+}
+
+# try to move until success
+function trymv {
+    element="$1"
+    target="$2"
+    local essai=1
+    print -- mv $element $target
+    while ! mv $element $target; do
+        samelineprint "Echec: essai n°$essai"
+        ((essai++))
+        ((essai>maxessais)) && exit 5
+    done
+    essai=1
+    while [[ -e $element ]]; do
+        samelineprint "mv reussi mais fichier source non disparu n°$essai"
+        sleep 1
+        ((essai++))
+        ((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.

+ +
+
+#!/usr/bin/env zsh
+
+# 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
+
+# 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"
+        rsyncPublish
+        swap
+    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
+            swap
+        fi
+    fi
+}
+
+# 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
+        ((essai++))
+    done
+}
+
+# swap
+function swap {
+    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 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 -P -- "  publication terminée"
+}
+
+print -- "Root = $webroot"
+print -- "Dest = $destRep"
+
+if [[ "$1" = "-s" ]]; then
+    swap
+else 
+    if [[ "$1" = "-d" ]]; then
+        suffix=""
+    else
+        suffix=".tmp"
+    fi
+    print -P -- "%BSync%b[${Root:t} => ${destRep:t}$suffix]"
+    incrementalPublish
+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.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Created: 10/28/2009 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2009-10-30-How-to-handle-evil-IE/code/ie.js b/output/n3blog/en/blog/2009-10-30-How-to-handle-evil-IE/code/ie.js new file mode 100644 index 000000000..661daa2f2 --- /dev/null +++ b/output/n3blog/en/blog/2009-10-30-How-to-handle-evil-IE/code/ie.js @@ -0,0 +1,18 @@ + +// 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; +}) ; + +// Append the CSS for IE only +$('head').append(''); + +// I also add a message on top of the page +$('body').prepend('

Avec Firefox et Safari cette page est bien plus jolie !This page is far nicer with Firefox and Safari!

.
'); + diff --git a/output/n3blog/en/blog/2009-10-30-How-to-handle-evil-IE/index.html b/output/n3blog/en/blog/2009-10-30-How-to-handle-evil-IE/index.html new file mode 100644 index 000000000..efbd52194 --- /dev/null +++ b/output/n3blog/en/blog/2009-10-30-How-to-handle-evil-IE/index.html @@ -0,0 +1,225 @@ + + + + + + + + + + + + + + + + + + + + + + + How to handle evil IE + + + + +
+ + +
+

+ How to handle evil IE +

+ +
+ +
+ + + + + +
+
+
+

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>');
+    }
+});
+
+ +
+
+// 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;
+}) ;
+
+// 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>');
+
+
+
+ +

That’s it.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Created: 10/30/2009 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2009-10-Focus-vs-Minimalism/index.html b/output/n3blog/en/blog/2009-10-Focus-vs-Minimalism/index.html new file mode 100644 index 000000000..97f3aab9b --- /dev/null +++ b/output/n3blog/en/blog/2009-10-Focus-vs-Minimalism/index.html @@ -0,0 +1,262 @@ + + + + + + + + + + + + + + + + + + + + + + + Focus > Minimalism + + + + +
+ + +
+

+ Focus > Minimalism +

+ +
+ +
+ + + + + +
+
+
+

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.

+ + +
+ +
+ + +

technical details

+ +

For those who want the technical details behind the show/hide menu, here is the simple jQuery code.

+ +

The HTML:

+ +
+
+<div id="menuButton"></div>
+<div id="entete">#content of the menu</div>
+
+
+ +

The CSS:

+ +
+#menuButton {
+  font-size: 2em;
+  height: 2em;
+  line-height: 1.8em;
+  width: 2em;
+  position: fixed;
+  left: 0;
+  top: 0; 
+  z-index: 9001 }
+
+#menuButton:hover {
+  cursor: pointer; }
+
+#entete {
+  top: 5em;
+  left: 0;
+  position: fixed;
+  width: 10em;
+  z-index: 9000; }
+
+
+ +

The javascript code (using jQuery)

+ +
+
+function hideMenu() {
+    $('#entete').animate({left:"-10em"}, 500 );
+    $('#menuButton').html('&rarr;');
+}
+function showMenu() {
+    $('#entete').animate({left:"0em"}, 500 );
+    $('#menuButton').html('&larr;');
+}
+function toggleMenu() {
+    if ( $('#entete').css('left')=='-10em' ) {
+        showMenu();
+    } else {
+        hideMenu();
+    }
+}
+
+
+ +

And the result is shown in the top left corner of this website.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ + + + +
+ +
+ Created: 10/22/2009 + Modified: 06/17/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2009-10-How-to-preload-your-site-with-style/index.html b/output/n3blog/en/blog/2009-10-How-to-preload-your-site-with-style/index.html new file mode 100644 index 000000000..4f9d8b767 --- /dev/null +++ b/output/n3blog/en/blog/2009-10-How-to-preload-your-site-with-style/index.html @@ -0,0 +1,272 @@ + + + + + + + + + + + + + + + + + + + + + + + How to preload your site with style + + + + +
+ + +
+

+ How to preload your site with style +

+ +
+ +
+ + + + + +
+
+
+

Example

+ +

Here is a live example of what appear while loading my pages.

+ +
+

Hello! I've finished loading!

+

Click me to see me disapear again.

+
+ Loading... + loading logo +
+ +
+ +

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.

+ +

In order to hide this small artefact, here is how I do that.

+ +

Code

+ +

In a first time, I added at the top of the body the div hiding all the content.

+ +
+
+...
+<body>
+<div id="blackpage">
+    content to display during the loading.
+</div>
+...
+
+
+ +

and here is the associated CSS to #blackpage:

+ +
+
+#blackpage
+  top: 0 
+  left: 0 
+  width: 100%
+  height: 100%
+  margin-left: 0
+  margin-right: 0
+  margin-top: 0
+  margin-bottom: 0
+  position: absolute
+  text-align: center
+  color: #666
+  padding-top: 10em
+  background-color: #eee
+  z-index: 9000
+
+
+ +

and the associated jQuery code:

+ +
+
+$(document).ready(function(){
+    $('#blackpage').fadeOut();
+});
+
+
+ +

Yes, it is as simple as that. And, putting the #blackpage div at the top of my page, I ensure to hide anything while loading.

+ +

I hope it had helped you!

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+ +
+ + +
+ +
+ Created: 10/03/2009 + Modified: 10/04/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2009-10-Wait-to-hide-a-menu-in-jQuery/index.html b/output/n3blog/en/blog/2009-10-Wait-to-hide-a-menu-in-jQuery/index.html new file mode 100644 index 000000000..d3b5a297f --- /dev/null +++ b/output/n3blog/en/blog/2009-10-Wait-to-hide-a-menu-in-jQuery/index.html @@ -0,0 +1,273 @@ + + + + + + + + + + + + + + + + + + + + + + + Menu waiting to hide himself + + + + +
+ + +
+

+ Menu waiting to hide himself +

+ +
+ +
+ + + + + +
+
+
+

I discussed earlier why I prefer to hide my navigation menu. I finally decided to hide it only after a short time. Just the time needed for a user to see it. But how make it disappear only when it is not used for some time?

+ +

Here is how to accomplish that easily.

+ +

HTML:

+ +
+
+    <div id="menuButton"></div>
+    <div id="entete">
+        <ul>
+            <li> menu item 1 </li>
+            ...
+            <li> menu item n </li>
+        </ul>
+    </div>
+
+
+ +

CSS:

+ +
+    #entete {
+      top: 1em;
+      left: 0;
+      position: fixed;
+      width: 10em;
+      z-index: 2000; }
+    
+    #entete {
+      top: 1em;
+      height: 22em;
+      left: 0;
+      position: fixed;
+      width: 10em; }
+
+ +

Javascript:

+ +
+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);
+
+    // 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
+
+// move to the left
+function hideMenu() { 
+    $('#entete').animate({left:"-10em"}, 500 ); 
+}
+
+// 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…

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Created: 10/26/2009 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2009-10-launch-daemon-from-command-line/index.html b/output/n3blog/en/blog/2009-10-launch-daemon-from-command-line/index.html new file mode 100644 index 000000000..5caaf5518 --- /dev/null +++ b/output/n3blog/en/blog/2009-10-launch-daemon-from-command-line/index.html @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + launch daemon from command line + + + + +
+ + +
+

+ launch daemon from command line +

+ +
+ +
+ + + + + +
+
+
+

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:

+ +
+nohup cmd &
+
+where cmd is your command. +
+ +

I let this command here for me and I wish it could also help someone.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ + + + +
+ +
+ Created: 10/23/2009 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2009-10-untaught-git-usage/index.html b/output/n3blog/en/blog/2009-10-untaught-git-usage/index.html new file mode 100644 index 000000000..d0573632b --- /dev/null +++ b/output/n3blog/en/blog/2009-10-untaught-git-usage/index.html @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + + + + + + + + + + Untaught Git usage + + + + +
+ + +
+

+ Untaught Git usage +

+ +
+ +
+ + + + + +
+
+
+

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.

+ + +
+ +
+ + +

My way to decentralisation

+ +

From SVN to Bazaar

+ +

I was a huge user of subversion (svn). Until the day I saw this video of Linus Torvald. Where he explain Git and all advantages of Decentralized Concurrent Versioning System(DCVS)

+ +

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

+ +

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.

+ +

From Bazaar to Git

+ +

It was really natural to learn when coming from subversion. The pull command corresponding to update, push command to commit. Commands like commit and update are still there if you want to use an SVN workflow.

+ +

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).

+ +

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…

+
+ +

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 speak about ClearCase©. I know there exists command line tools. But it was not the way my team used 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.

+ + +
+ +
+ + +

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.

+ +

From one site Parallel World and Patches from the other. There is many equivalent notions in the two point of vue, but also some differences.

+ +
    +
  • Bazaar seems base on the Parallel World vision which implies Patches
  • +
  • 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.

+ +

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.

+ +

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.

+ +

You just have to launch a Git command and the local directory reflect the state of the branch you selected.

+ +

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. +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.

+ +

Here how Git cheap branches should be used (for more details see Git for Designers):

+ +
    +
  • get or creation of a main repositoy The Great Repository
  • +
  • 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:

+ +
    +
  • Get or creation of a 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.

+ +

Real Life Usage

+ +

Now I have understood all that. I understand why Git has some many people claiming it is the best DCVS.

+ +

Cheap branching notion is essential in Git and is a really useful feature. Particularly for this website. But, there are not exactly, completely parallel line of development. Because they are designed to path the main branch. Of course, it is not an obligation, but there are slight messages which tell you this should be used like that.

+ +

If I want to separate in a better way some branches I just have to Clone them. +And I return exactly in branches Bazaar provided me.

+ +

Examples

+ +

For now, I prefer (from far) Bazaar terminology. They are cleaner and more understandable.

+ +
bzr revert
+
+ +

Is clearer than

+ +
git reset --hard HEAD
+
+ +

We can tell the same thing about

+ +
bzr revert -r -3
+
+ +

which seems preferable to

+ +
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.

+ +
OK
+ +

Now, if I want to revert time on on file. We should naturally imagine the command will be:

+ +
git reset --hard FILE
+
+ +
**OF COURSE NOT!**
+ +

The solution is:

+ +
git checkout FILE
+
+ +

What? checkout !? Well, ok. I accept. why not? +With Bazaar it is:

+ +
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
+
+ +

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
+
+ +

WTF? I believed checkout was the key to get a file in some state (not the entire tree).

+ +

Then checkout is the same keyword used to get back in time on a file (BUT NOT ON ALL THE TREE where you have to use reset --hard) and to change current branch!

+ +

It is totally unnatural. Even if it is theoretically totally justified like you can see in the really good article Git for Computer Scientist. From the user point of vue, it is difficult to do worse than that. It is like somebody made it on purpose to make it the hardest possible to learn and understand.

+ +
+
    +
  • — 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).

+ +

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 !”

+ + +
+ +
+ + +

Conclusion

+ +

DCVS vs. CVS ?

+ +

Was it a good idea to change to a decentralised versionning system? Clearly yes. Decentralisation give far much great possibilities. +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.

+ +

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.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ + + + +
+ +
+ Created: 10/13/2009 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2009-11-12-Git-for-n00b/Git-pour-quoi-faire/index.html b/output/n3blog/en/blog/2009-11-12-Git-for-n00b/Git-pour-quoi-faire/index.html new file mode 100644 index 000000000..6b6e26dd4 --- /dev/null +++ b/output/n3blog/en/blog/2009-11-12-Git-for-n00b/Git-pour-quoi-faire/index.html @@ -0,0 +1,408 @@ + + + + + + + + + + + + + + + + + + + + + + + Git for n00b + + + + +
+ + +
+

+ Git for n00b +

+ +

+ Git for what? +

+ +
+ +
+ + + + + +
+
+
+

Git for what?

+ + +
+ + +

If you just want to use Git immediately, just read dark part. You read this part later to understand correctly foundations of version systems and not doing strange things.

+ + +
+ + +

Git is a DCVS, which means a Decentralized Concurrent Versions System. Let’s analyze each part of this long term:

+ +

Versions System

+ +

Firstly, versions system manage files. +When somebody work with files without a versions system, the following happens frequently:

+ +

When you modify a somehow critical file you don’t want to loose. You copy naturally this file with another name. For example:

+ +
$ 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:

+ +
+
+fichier_important.c.bak
+fichier_important.c.old
+fichier_important.c.Bakcup
+fichier_important.c.BAK.2009-11-14
+fichier_important.c.2009.11.14
+fichier_important.c.12112009
+old.fichier_important.c
+
+
+ +

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.

+ +

You only have to signal you want a new version of a file and the versions system will do the job for you. It will record the backup where it could be easily recovered. Generally, systems version do it better than you, making the backup only of the modified lines and not the total file.

+ +

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”.

+ + +
+ + +

What gives versions system? (I didn’t mention everything at all)

+ +
    +
  • automatic backups: back in time,
  • +
  • gives the ability to see differences between each version,
  • +
  • put a tag on some version to be able to refer to them easily,
  • +
  • gives the ability to see an historic of all modifications. Generally the user must add a comment for each new version.
  • +
+ + +
+ + +

concurrent:

+ +

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:

+ +
+
+Cthulhu
+Shubniggurath
+Yogsototh
+
+ +

Say Alex is home and modify the file: +<div style="width: 10em; margin-left: auto; margin-right: auto"> +<pre class="twilight"> +Cthulhu +Shubniggurath +Soggoth +Yogsototh +</pre> +</div>

+ +

after that he send the file on the project server. Then on the server there is the Alex file:

+ +

A bit later, Beatrice who had not get the Alex file on the server make the modification:

+ +
+
+Cthulhu
+Dagon
+Shubniggurath
+Yogsototh
+
+
+ +

Beatrice send her file on the server

+ +

Alex modification is lost. One more time, versions system are here to help.

+ +

A version system would had merge the two files at the time Beatrice send the file on the server. And like by magic, on the server the file would be:

+ +
+
+Cthulhu
+Dagon
+Shubniggurath
+Soggoth
+Yogsototh
+
+
+ +

In real life, at the moment Beatrice want to send her modifications, the versions system alert her a modification had occurred on the server. Then she uses a command which pull the modification from the server to her local computer. And this command update her file. After that, Beatrice send again the new file on the server.

+ + +
+ + +

In what Concurrent Versions System help?

+ +
    +
  • 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,
  • +
  • help to know who done what and when.
  • +
+ + +
+ + +

decentralized

+ +

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.

+ +

All instances of a project can live independently.

+ +

To be more precise, DCVS are base on the branch notion.

+ +

Practically, it has great importance. It means, everybody work separately, and the system help to glue all their work.

+ +

It is even more than just that. It help to code independently each feature and bug fixes. Under other system it was far more difficult.

+ +

Typical example:

+ +
+

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.

+ +

In a not decentralized version system, doing such a thing is possible but not natural. Decentralization means it become natural to use a branch for each separable work.

+
+ + +
+ + +

**Advantages given by DCVS: **

+ +
    +
  • Ability to work offline,
  • +
  • Ability to create many atomic patches,
  • +
  • Help the maintenance of many different versions of the same application.
  • +
+ + +
+ + +

To resume

+ +

Let’s resume what we can easily do with DCVS:

+ +

Versions Systems

+ +
    +
  • back in time,
  • +
  • list differences between versions,
  • +
  • name some versions to refer to them easily
  • +
  • show history of modifications
  • +
+ +

Concurrent

+ +
    +
  • get others modifications,
  • +
  • send its modifications to others,
  • +
  • know who done what and when,
  • +
  • conflicts management.
  • +
+ +

Decentralized

+ +
    +
  • Easily manipulate branches
  • +
+ +

Now let’s see how to obtain all these things easily with Git.

+ + +
+ + + +
+ + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+ +
+ + +
+ +
+ Created: 11/12/2009 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2009-11-12-Git-for-n00b/c-est-parti-pour-l-aventure/index.html b/output/n3blog/en/blog/2009-11-12-Git-for-n00b/c-est-parti-pour-l-aventure/index.html new file mode 100644 index 000000000..1a07568a4 --- /dev/null +++ b/output/n3blog/en/blog/2009-11-12-Git-for-n00b/c-est-parti-pour-l-aventure/index.html @@ -0,0 +1,304 @@ + + + + + + + + + + + + + + + + + + + + + + + Git for n00b + + + + +
+ + +
+

+ Git for n00b +

+ +

+ The Adventure Begins +

+ +
+ +
+ + + + + +
+
+
+

Here we go!

+ +

Here is one from many way to use Git. This method is sufficient to work on a project. Not there is many other workflows.

+ +

Basic usage

+ +

Work with Git immediately:

+ +
    +
  • Get modification done by others git pull,
  • +
  • See details of these modifications git log,
  • +
  • Many times: +
      +
    • Make an atomic modification
    • +
    • Verify details of this modification: git status and git diff,
    • +
    • Add some file to be versionned if necessary:
      git add [file],
    • +
    • Save you modifications
      git commit -a -m "message",
    • +
    • Send your modifications to others: git push (redo a git pull if push return an error).
    • +
    +
  • +
+ +

With these few commands you can use Git. Even if it is sufficient, you need to know one more thing before really begin ; How to manage conflicts.

+ +

Conflicts management

+ +

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.

+ +

example

+ +

You start from the following file

+ +
+
+Zoot 
+
+
+ +

and you modify one line

+ +
+
+Zoot the pure
+
+
+ +

except during this time, another user had also modified the same line and had done a push.

+ +
+
+Zoot, just Zoot
+
+
+ +

Now when you do a:

+ +
+
+$ git pull
+remote: Counting objects: 5, done.
+remote: Total 3 (delta 0), reused 0 (delta 0)
+Unpacking objects: 100% (3/3), done.
+From /home/e640846/tmp/conflictTest
+   d3ea395..2dc7ffb  master     -> origin/master
+Auto-merging foo
+CONFLICT (content): Merge conflict in foo
+Automatic merge failed; fix conflicts and then commit the result.
+
+
+ +

Our file foo now contains:

+ +
+
+<<<<<<< HEAD:foo
+Zoot the pure
+=======
+Zoot, just Zoot
+>>>>>>> 2dc7ffb0f186a407a1814d1a62684342cd54e7d6:foo
+
+
+ +

Conflict resolution

+ +

To resolve the conflict you only have to edit the file for example, writing:

+ +
+
+Zoot the not so pure
+
+
+ +

and to commit

+ +
+
+git commit -a -m "conflict resolved"
+
+
+ +

Now you’re ready to use Git. +Git provide many other functionnalities. Now we’ll see some Git usages older CVS couldn’t handle.

+ + +
+ + + +
+ + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+ +
+ + +
+ +
+ Created: 11/12/2009 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2009-11-12-Git-for-n00b/commandes-avancees/index.html b/output/n3blog/en/blog/2009-11-12-Git-for-n00b/commandes-avancees/index.html new file mode 100644 index 000000000..e99758be7 --- /dev/null +++ b/output/n3blog/en/blog/2009-11-12-Git-for-n00b/commandes-avancees/index.html @@ -0,0 +1,330 @@ + + + + + + + + + + + + + + + + + + + + + + + Git for n00b + + + + +
+ + +
+

+ Git for n00b +

+ +

+ Command List +

+ +
+ +
+ + + + + +
+
+
+

Command List

+ +

Command for each functionality

+ +

In the first part, we saw the list of resolved problem by Git. To resume Git should do:

+ +
    +
  • get others modifications,
  • +
  • send modifications to others,
  • +
  • get back in time,
  • +
  • list differences between each version,
  • +
  • name some versions in order to refer easily to them,
  • +
  • write an historic of modifications,
  • +
  • know who did what and when,
  • +
  • manage conflicts,
  • +
  • easily manage branches.
  • +
+ +

get others modifications

+ +
+$ git pull
+
+ +

send modifications to others

+ +
+$ git push
+
+ +

or more generally

+ +
+$ git pull
+$ git push
+
+ +

get back in time

+ +

For all tree

+ +
+$ git checkout
+
+ +
+$ git revert
+
+ +

revert three version before (see my .gitconfig file).

+ +
+$ git uncommit 3
+
+ +

Undo the las merge (if something goes wrong)

+ +
+$ git revertbeforemerge
+
+ +

For one file

+ +
+$ git checkout file
+$ git checkout VersionHash file
+$ git checkout HEAD~3 file
+
+ +

list differences between each version

+ +

list files being modified

+ +
+$ git status
+
+ +

differences between last version files and local files

+ +
+$ git diff
+
+ +

differences between some version and local files

+ +
+$ git diff VersionHash fichier
+
+ +

name some version to refer to them in the future

+ +
+$ git tag 'toto'
+
+ +

show historic of modifications

+ +
+$ git log
+$ git lg
+$ git logfull
+
+ +

know who did what and when

+ +
+$ git blame fichier
+
+ +

handle conflicts

+ +
+$ git conflict
+
+ +

manage branches

+ +

To create a branch:

+ +
+$ git branch branch_name
+
+ +

To change the current branch:

+ +
+$ git checkout branch_name
+
+ + +
+ + + +
+ + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+ +
+ + +
+ +
+ Created: 11/12/2009 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2009-11-12-Git-for-n00b/comprendre/index.html b/output/n3blog/en/blog/2009-11-12-Git-for-n00b/comprendre/index.html new file mode 100644 index 000000000..0f45abeb0 --- /dev/null +++ b/output/n3blog/en/blog/2009-11-12-Git-for-n00b/comprendre/index.html @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + Git for n00b + + + + +
+ + +
+

+ Git for n00b +

+ +

+ Understanding +

+ +
+ +
+ + + + + +
+
+
+

Why Git is cool?

+ +

Because with Git you can work on many part of some project totally independently. This is the true efficiency of decentralisation.

+ +

Each branch use the same directory. Then you can easily change your branch. You can also change branch when some files are modified. You can then dispatch your work on many different branches and merge them on one master branch at will.

+ +

Using the git rebase you can decide which modifications should be forget or merged into only one modification.

+ +

What does it mean for real usage? You can focus on coding. For example, you can code, a fix for bug b01 and for bug b02 and code a feature f03. Once finished you can create a branch by bug and by feature. And finally you can merge these modifications on a main branch.

+ +

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.

+ +

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.

+ + +
+ + + +
+ + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+ +
+ + +
+ +
+ Created: 11/12/2009 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2009-11-12-Git-for-n00b/conf-et-install/code/gitconfig b/output/n3blog/en/blog/2009-11-12-Git-for-n00b/conf-et-install/code/gitconfig new file mode 100644 index 000000000..25bcf85ce --- /dev/null +++ b/output/n3blog/en/blog/2009-11-12-Git-for-n00b/conf-et-install/code/gitconfig @@ -0,0 +1,20 @@ + +[color] + branch = auto + diff = auto + status = auto +[alias] + st = status + co = checkout + br = branch + 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\""' + 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 +[branch] + autosetupmerge = true diff --git a/output/n3blog/en/blog/2009-11-12-Git-for-n00b/conf-et-install/index.html b/output/n3blog/en/blog/2009-11-12-Git-for-n00b/conf-et-install/index.html new file mode 100644 index 000000000..bcd9bb616 --- /dev/null +++ b/output/n3blog/en/blog/2009-11-12-Git-for-n00b/conf-et-install/index.html @@ -0,0 +1,335 @@ + + + + + + + + + + + + + + + + + + + + + + + Git for n00b + + + + +
+ + +
+

+ Git for n00b +

+ +

+ Configure before Use +

+ +
+ +
+ + + + + +
+
+
+

Before usage, configuration

+ +

install

+ +

Under Linux Ubuntu or Debian:

+ +
$ sudo apt-get install git
+
+ +

Under Mac OS X:

+ + + +
+$ sudo port selfupdate
+
+$ sudo port install git-core
+
+ +

Global configuration

+ +

Save the following file as your ~/.gitconfig.

+ +
+
+[color]
+    branch = auto
+    diff   = auto
+    status = auto
+[alias]
+    st        = status
+    co        = checkout
+    br        = branch
+    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\""'
+    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
+[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.email john.doe@email.com
+
+ +

Here it is. Base configuration is over. The file containing alias will help to type shorter commands.

+ +

Get a project

+ +

If a project is already versionned with Git you should have an URL of the sources. Then use the following command:

+ +
+$ 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
+
+ +

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.

+ +

The easiest way if you have ssh-copy-id:

+
+me@locahost$ ssh-copy-id ~/.ssh/id_rsa.pub me@main.server
+
+ +

or manually

+ +
+me@locahost$ scp ~/.ssh/id_rsa.pub me@main.server:
+me@locahost$ ssh me@main.server
+password:
+me@main.server$ cat id_rsa.pub >> ~/.ssh/authorized_keys
+me@main.server$ rm id_rsa.pub
+me@main.server$ logout
+
+ +

Now you don’t need to write your password to access the main.server.

+ +

Creating a new project

+ +

Suppose you already have a project with files. Then it is really easy to version it.

+ +
+$ cd /path/to/project
+$ git init
+$ git add .
+$ git commit -m "Initial commit"
+
+ +

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
+$ git clone --bare . ssh://server/path/to/project
+
+ +

Others will be able to get your modifications.

+ +
+git clone ssh://server/path/to/project
+
+ +

Abstract of the second step

+ +

You now have a local directory on your computer. It is versionned and you can say it is, because there is a .git directory at the root (and the root only) of your project. This directory contain all necessary informations for Git to version your project.

+ +

Now you only need to know how to use it.

+ + +
+ + + +
+ + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+ +
+ + +
+ +
+ Created: 11/12/2009 + Modified: 09/20/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2009-11-12-Git-for-n00b/index.html b/output/n3blog/en/blog/2009-11-12-Git-for-n00b/index.html new file mode 100644 index 000000000..c69ea4aef --- /dev/null +++ b/output/n3blog/en/blog/2009-11-12-Git-for-n00b/index.html @@ -0,0 +1,255 @@ + + + + + + + + + + + + + + + + + + + + + + + Git for n00b + + + + +
+ + +
+

+ Git for n00b +

+ +

+ introduction +

+ +
+ +
+ + + + + +
+
+
+ +
+ + +

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.

+ + +
+ + + +
+ +
+ + +

Begin with conclusion

+ +

Here is the list of sufficient and necessary command to use Git. There is very few. It is normal not to understand immediately but it is to gives you an idea. Even if this article is long, 95% of Git usage is in these 7 commands:

+ +

Get a project from the web:

+ +
+git clone ssh://server/path/to/project
+
+ +

Everyday Git usage:

+ +
+# get modifications from other
+git pull
+# read what was done
+git log
+
+# Make local changes to files 
+hack, hack, hack...
+# list the modified files
+git status
+# show what I've done
+git diff
+
+# 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"
+
+# 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.

+ + +
+ + + +
+ + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+ +
+ + +
+ +
+ Created: 11/12/2009 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2009-12-06-iphone-call-filter/index.html b/output/n3blog/en/blog/2009-12-06-iphone-call-filter/index.html new file mode 100644 index 000000000..6f74795a4 --- /dev/null +++ b/output/n3blog/en/blog/2009-12-06-iphone-call-filter/index.html @@ -0,0 +1,194 @@ + + + + + + + + + + + + + + + + + + + + + + + iphone call filter + + + + +
+ + +
+

+ iphone call filter +

+ +
+ +
+ + + + + +
+
+
+

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

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ + + + +
+ +
+ Created: 12/06/2009 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2009-12-14-Git-vs--Bzr/code/gitconfig b/output/n3blog/en/blog/2009-12-14-Git-vs--Bzr/code/gitconfig new file mode 100644 index 000000000..85a89236f --- /dev/null +++ b/output/n3blog/en/blog/2009-12-14-Git-vs--Bzr/code/gitconfig @@ -0,0 +1,3 @@ + +[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\""' diff --git a/output/n3blog/en/blog/2009-12-14-Git-vs--Bzr/index.html b/output/n3blog/en/blog/2009-12-14-Git-vs--Bzr/index.html new file mode 100644 index 000000000..70c26540d --- /dev/null +++ b/output/n3blog/en/blog/2009-12-14-Git-vs--Bzr/index.html @@ -0,0 +1,332 @@ + + + + + + + + + + + + + + + + + + + + + + + Git vs. Bzr + + + + +
+ + +
+

+ Git vs. Bzr +

+ +

+ Why I switched from bazaar to git +

+ +
+ +
+ + + + + +
+
+
+ +
+ + +

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.

+ + +
+ + +

The DCVS discovery

+ +

Before beginning this article, you should know I come from subversion. I find subversion to be a really good CVS. But I was converted to the decentralized ones.

+ +

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.

+ +

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.

+ +

And it was so fastidious! The git terminology was horrible! And it is nothing to say it.

+ +

Where Bazaar is better than git

+ +

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
+
+ +

undo the current modification of the file 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…

+ +

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:

+ +
+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
+
+ +

The git equivalent is far more cryptic:

+ +
+bzr checkout HEAD~3 pipo
+
+ +

One more time, Bazaar is far more readable.

+ +

Back in time for all the project:

+ +

with Bazaar:

+ +
+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
+
+ +

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:

+ +
+git checkout HEAD~3 -- . && git commit -m 'back in time'
+
+ +

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…).

+ +
+
+[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.

+ +

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.

+ +
+> vim file1
+> vim file2
+> git br fix1
+> git add file1 
+> git commit -m 'fix1'
+> git br fix2
+> git add file2
+> git commit -m 'fix2'
+> git commit master
+> git merge fix1
+> git merge fix2
+
+ +

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.

+ +

And I use this possibilities a lot. Working with bazaar, I often made the error to begin a change in the bad branch. then I have to copy my modifications, then revert. In short it was tiedous.

+ +

This is why I prefer using git on an every day usage. If Bazaar implement the same way of cheap branching than git. I should switch again.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+ +
+ + +
+ +
+ Created: 12/14/2009 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-01-04-Change-default-shell-on-Mac-OS-X/index.html b/output/n3blog/en/blog/2010-01-04-Change-default-shell-on-Mac-OS-X/index.html new file mode 100644 index 000000000..795bccddc --- /dev/null +++ b/output/n3blog/en/blog/2010-01-04-Change-default-shell-on-Mac-OS-X/index.html @@ -0,0 +1,196 @@ + + + + + + + + + + + + + + + + + + + + + + + Change default shell on Mac OS X + + + + +
+ + +
+

+ Change default shell on Mac OS X +

+ +
+ +
+ + + + + +
+
+
+

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:

+ +
+> chsh
+
+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+ +
+ + +
+ +
+ Created: 01/04/2010 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/code/local.conf b/output/n3blog/en/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/code/local.conf new file mode 100644 index 000000000..cbbcb2c5e --- /dev/null +++ b/output/n3blog/en/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/code/local.conf @@ -0,0 +1,55 @@ + + + + + + + + +misc.conf + + + +alias.conf + + + +msfonts-rules.conf + + + + Tahoma + + + Verdana + + + + + + + Lucida Grande + + + + + + + + Georgia + + + Georgia + + + + + + + Century Schoolbook L + + + + + + diff --git a/output/n3blog/en/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/index.html b/output/n3blog/en/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/index.html new file mode 100644 index 000000000..bef6495c3 --- /dev/null +++ b/output/n3blog/en/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/index.html @@ -0,0 +1,257 @@ + + + + + + + + + + + + + + + + + + + + + + + antialias font in Firefox under Ubuntu + + + + +
+ + +
+

+ antialias font in Firefox under Ubuntu +

+ +
+ +
+ + + + + +
+
+
+

How to stop using bad Microsoft© font under Ubuntu Linux in order to user nice anti aliased font under Firefox.

+ +

Just modify the /etc/fonts/local.conf with the following code:

+ +
+
+
+
+<?xml version="1.0"?>
+<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
+<fontconfig>
+
+<!-- Miscellaneous settings -→
+
+<include ignore_missing="yes">misc.conf</include>
+
+<!-- Define alias -→
+
+<include ignore_missing="yes">alias.conf</include>
+
+<!-- Rules for Microsoft fonts -→
+
+<include ignore_missing="yes">msfonts-rules.conf</include>
+
+  <match target="pattern" name="family" >
+      <test name="family" qual="any" >
+          <string>Tahoma</string>
+      </test>
+      <edit mode="assign" name="family" >
+          <string>Verdana</string>
+      </edit>
+  </match>
+  <selectfont>
+      <acceptfont>
+          <pattern>
+              <patelt name="family"> 
+                <string>Lucida Grande</string> 
+              </patelt>
+          </pattern>
+      </acceptfont>
+  </selectfont>
+
+  <match target="pattern" name="family" >
+      <test name="family" qual="any" >
+          <string>Georgia</string>
+      </test>
+      <edit mode="assign" name="family" >
+          <string>Georgia</string>
+      </edit>
+  </match>
+  <selectfont>
+      <acceptfont>
+          <pattern>
+              <patelt name="family"> 
+                <string>Century Schoolbook L</string> 
+              </patelt>
+          </pattern>
+      </acceptfont>
+  </selectfont>
+
+</fontconfig>
+
+
+
+ +

Hope it helped someone who like me had his eyes crying in face of such ugly fonts.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+ +
+ + +
+ +
+ Created: 01/12/2010 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-02-15-All-but-something-regexp/index.html b/output/n3blog/en/blog/2010-02-15-All-but-something-regexp/index.html new file mode 100644 index 000000000..93bef38b2 --- /dev/null +++ b/output/n3blog/en/blog/2010-02-15-All-but-something-regexp/index.html @@ -0,0 +1,260 @@ + + + + + + + + + + + + + + + + + + + + + + + Pragmatic Regular Expression Exclude + + + + +
+ + +
+

+ Pragmatic Regular Expression Exclude +

+ +
+ +
+ + + + + +
+
+
+

Sometimes you cannot simply write:

+ +
+if str.match(regexp) and 
+    not str.match(other_regexp)
+        do_something
+
+ +

and you have to make this behaviour with only one regular expression. The problem is the complementary of regular languages is not regular. Then, for some expression it is absolutely not impossible.

+ +

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]|$)/
+
+# 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? +Because, without it the word bull would be no more matched. This expression means:

+ +
+

The string finish by bull
+or,
+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$/)
+    do_something
+end
+
+ +

A nice solution is:

+ +
+/abc|           # length 3
+a.bc|           # length 4
+ab.c|
+a[^x]b[^x]c|    # length 5
+a...*b.*c|      # length >5
+a.*b...*c/
+
+ +

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.

+ +
+

+It can be proved that any regular set minus a finite set is also regular. +

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ + + + +
+ +
+ Created: 02/15/2010 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-02-16-All-but-something-regexp--2-/index.html b/output/n3blog/en/blog/2010-02-16-All-but-something-regexp--2-/index.html new file mode 100644 index 000000000..710246795 --- /dev/null +++ b/output/n3blog/en/blog/2010-02-16-All-but-something-regexp--2-/index.html @@ -0,0 +1,281 @@ + + + + + + + + + + + + + + + + + + + + + + + Pragmatic Regular Expression Exclude (2) + + + + +
+ + +
+

+ Pragmatic Regular Expression Exclude (2) +

+ +
+ +
+ + + + + +
+
+
+

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:

+ +
+a.....a......b..b..a....a....b...
+
+ +

Here are two common errors and a solution:

+ +
+/a.*b/
+a.....a......b..b..a....a....b...
+
+ +

The first error is to use the evil .*. Because you will match from the first to the last.

+ +
+/a.*?b/
+a.....a......b..b..a....a....b...
+
+ +

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.

+ +
+/a[^ab]*b/
+a.....a......b..b..a....a....b...
+
+ +

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>
+
+ +

This is a bit difficult. You need to match

+
+<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>
+
+ +

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:

+
+<li>([^<]|<[^l]|<l[^i]|<li[^>])*(|<|<l|<li)</li>
+
+ +

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
+
+# use the first method
+s/X([^X]*)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::.

+ + +
+ + + + + +
+
+

comments

+ + + + + + +
+ + + + +
+ +
+ Created: 02/16/2010 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-02-18-split-a-file-by-keyword/index.html b/output/n3blog/en/blog/2010-02-18-split-a-file-by-keyword/index.html new file mode 100644 index 000000000..fb23d8197 --- /dev/null +++ b/output/n3blog/en/blog/2010-02-18-split-a-file-by-keyword/index.html @@ -0,0 +1,225 @@ + + + + + + + + + + + + + + + + + + + + + + + split a file by keyword + + + + +
+ + +
+

+ split a file by keyword +

+ +
+ +
+ + + + + +
+
+
+

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.

+ +
+#!/usr/bin/env awk
+BEGIN{i=0;}
+/UTC/ { 
+    i+=1;
+    FIC=sprintf("fic.%03d",i); 
+} 
+{print $0>>FIC}
+
+ +

In my real world example, I wanted one file per day, each line containing UTC being in the following format:

+ +
+Mon Dec  7 10:32:30 UTC 2009
+
+ +

I then finished with the following code:

+ +
+#!/usr/bin/env awk
+BEGIN{i=0;}
+/UTC/ {
+    date=$1$2$3; 
+    if ( date != olddate ) {
+        olddate=date;
+        i+=1;
+        FIC=sprintf("fic.%03d",i); 
+    }
+} 
+{print $0>>FIC}
+
+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ + + + +
+ +
+ Created: 02/18/2010 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-02-23-When-regexp-is-not-the-best-solution/code/regex_benchmark_ext.rb b/output/n3blog/en/blog/2010-02-23-When-regexp-is-not-the-best-solution/code/regex_benchmark_ext.rb new file mode 100644 index 000000000..33e9e5580 --- /dev/null +++ b/output/n3blog/en/blog/2010-02-23-When-regexp-is-not-the-best-solution/code/regex_benchmark_ext.rb @@ -0,0 +1,25 @@ + +#!/usr/bin/env ruby +require 'benchmark' +n=80000 +tab=[ '/accounts/user.json', + '/accounts/user.xml', + '/user/titi/blog/toto.json', + '/user/titi/blog/toto.xml' ] + +puts "Get extname" +Benchmark.bm do |x| + x.report("regexp:") { n.times do + str=tab[rand(4)]; + str.match(/[^.]*$/); + ext=$&; + end } + x.report(" split:") { n.times do + str=tab[rand(4)]; + ext=str.split('.')[-1] ; + end } + x.report(" File:") { n.times do + str=tab[rand(4)]; + ext=File.extname(str); + end } +end diff --git a/output/n3blog/en/blog/2010-02-23-When-regexp-is-not-the-best-solution/code/regex_benchmark_strip.rb b/output/n3blog/en/blog/2010-02-23-When-regexp-is-not-the-best-solution/code/regex_benchmark_strip.rb new file mode 100644 index 000000000..f99b07a97 --- /dev/null +++ b/output/n3blog/en/blog/2010-02-23-When-regexp-is-not-the-best-solution/code/regex_benchmark_strip.rb @@ -0,0 +1,21 @@ + +#!/usr/bin/env ruby +require 'benchmark' +n=80000 +tab=[ '/accounts/user.json', + '/accounts/user.xml', + '/user/titi/blog/toto.json', + '/user/titi/blog/toto.xml' ] + +puts "remove extension" +Benchmark.bm do |x| + x.report(" File:") { n.times do + str=tab[rand(4)]; + path=File.expand_path(str,File.basename(str,File.extname(str))); + end } + x.report("chomp:") { n.times do + str=tab[rand(4)]; + ext=File.extname(str); + path=str.chomp(ext); + end } +end diff --git a/output/n3blog/en/blog/2010-02-23-When-regexp-is-not-the-best-solution/index.html b/output/n3blog/en/blog/2010-02-23-When-regexp-is-not-the-best-solution/index.html new file mode 100644 index 000000000..ca25ddc16 --- /dev/null +++ b/output/n3blog/en/blog/2010-02-23-When-regexp-is-not-the-best-solution/index.html @@ -0,0 +1,290 @@ + + + + + + + + + + + + + + + + + + + + + + + When regexp is not the best solution + + + + +
+ + +
+

+ When regexp is not the best solution +

+ +
+ +
+ + + + + +
+
+
+

Regular expression are really useful. Unfortunately, they are not always the best way of doing things. +Particularly when transformations you want to make are easy.

+ +

I wanted to know how to get file extension from filename the fastest way possible. There is 3 natural way of doing this:

+ +
+# regexp
+str.match(/[^.]*$/); 
+ext=$&
+
+# split
+ext=str.split('.')[-1]
+
+# File module
+ext=File.extname(str)
+
+ +

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.

+ +

Here is the Benchmark ruby code:

+ +
+
+#!/usr/bin/env ruby
+require 'benchmark'
+n=80000
+tab=[ '/accounts/user.json',
+      '/accounts/user.xml',
+      '/user/titi/blog/toto.json',
+      '/user/titi/blog/toto.xml' ]
+
+puts "Get extname"
+Benchmark.bm do |x|
+    x.report("regexp:") { n.times do 
+        str=tab[rand(4)]; 
+        str.match(/[^.]*$/); 
+        ext=$&; 
+    end  }
+    x.report(" split:") { n.times do 
+        str=tab[rand(4)]; 
+        ext=str.split('.')[-1] ; 
+    end }
+    x.report("  File:") { n.times do 
+        str=tab[rand(4)]; 
+        ext=File.extname(str); 
+    end  }
+end
+
+
+ +

And here is the result

+ +
+Get extname
+            user     system      total        real
+regexp:  2.550000   0.020000   2.570000 (  2.693407)
+ split:  1.080000   0.050000   1.130000 (  1.190408)
+  File:  0.640000   0.030000   0.670000 (  0.717748)
+
+ +

Conclusion of this benchmark, dedicated function are better than your way of doing stuff (most of time).

+ +

file path without the extension.

+ +
+
+#!/usr/bin/env ruby
+require 'benchmark'
+n=80000
+tab=[ '/accounts/user.json',
+      '/accounts/user.xml',
+      '/user/titi/blog/toto.json',
+      '/user/titi/blog/toto.xml' ]
+
+puts "remove extension"
+Benchmark.bm do |x|
+    x.report(" File:") { n.times do 
+        str=tab[rand(4)]; 
+        path=File.expand_path(str,File.basename(str,File.extname(str))); 
+    end }
+    x.report("chomp:") { n.times do 
+        str=tab[rand(4)]; 
+        ext=File.extname(str); 
+        path=str.chomp(ext); 
+    end }
+end
+
+
+ +

and here is the result:

+ +
+remove extension
+          user     system      total        real
+ File:  0.970000   0.060000   1.030000 (  1.081398)
+chomp:  0.820000   0.040000   0.860000 (  0.947432)
+
+ +

Conclusion of the second benchmark. One simple function is better than three dedicated functions. No surprise, but it is good to know.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Created: 02/23/2010 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-03-22-Git-Tips/index.html b/output/n3blog/en/blog/2010-03-22-Git-Tips/index.html new file mode 100644 index 000000000..f916b8859 --- /dev/null +++ b/output/n3blog/en/blog/2010-03-22-Git-Tips/index.html @@ -0,0 +1,249 @@ + + + + + + + + + + + + + + + + + + + + + + + Git Tips + + + + +
+ + +
+

+ Git Tips +

+ +
+ +
+ + + + + +
+
+
+

clone from github behind an evil firewall

+ +

Standard:

+ +
+git clone git@github.com:yogsototh/project.git
+
+ +

Using HTTPS port:

+ +
+git clone git+ssh://git@github.com:443/yogsototh/project.git
+
+ +

clone all branches

+ +

git clone can only fetch the master branch.

+ +

If you don’t have much branches, you can simply use clone your project and then use the following command:

+ +
+git branch --track local_branch remote_branch
+
+ +

for example:

+
+$ git clone git@github:yogsototh/example.git
+$ git branch
+master *
+$ git branch -a
+master *
+remotes/origin/HEAD -> origin/master
+remotes/origin/experimental
+$ git branch --track experimental remotes/origin/experimental
+$ git branch
+master *
+experimental
+
+ +

If you have many branches it can be useful to use the following script/long command line.

+ +
+# first clone your project
+$ git clone git@github.com:yogsototh/project.git
+
+# copy all branches
+$ zsh
+$ cd project
+$ for br in $( git br -a ); do
+    case $br in
+    remotes/*) print $br ; 
+        case ${br:t} in
+            master|HEAD) continue ;;
+            *) git branch --track ${br:t} $br ;;
+        esac ;;
+    esac
+done
+
+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+ +
+ + +
+ +
+ Created: 03/22/2010 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-03-23-Encapsulate-git/code/eng b/output/n3blog/en/blog/2010-03-23-Encapsulate-git/code/eng new file mode 100644 index 000000000..e46a24787 --- /dev/null +++ b/output/n3blog/en/blog/2010-03-23-Encapsulate-git/code/eng @@ -0,0 +1,103 @@ + +#!/usr/bin/env ruby +# encoding: utf-8 + +# 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 ] } + +def get_current_branch() + (`git branch --no-color | awk '$1 == "*" {print $2}'`).chop.intern +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 + +require 'set' +$known_branches=Set.new +$architecture.each do |k,v| + $known_branches.add(k) + v.each { |b| $known_branches.add(b) } +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 + +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 diff --git a/output/n3blog/en/blog/2010-03-23-Encapsulate-git/index.html b/output/n3blog/en/blog/2010-03-23-Encapsulate-git/index.html new file mode 100644 index 000000000..fe30bc7db --- /dev/null +++ b/output/n3blog/en/blog/2010-03-23-Encapsulate-git/index.html @@ -0,0 +1,353 @@ + + + + + + + + + + + + + + + + + + + + + + + Encapsulate git + + + + +
+ + +
+

+ Encapsulate git +

+ +
+ +
+ + + + + +
+
+
+
+Here is a solution to maintain divergent branches in git. Because it is easy to merge by mistake. I give a script that encapsulate git in order to forbid some merge and warn you some merge should be dangerous. +
+ +

how to protect against your own dumb

+ +

I work on a project in which some of my git branches should remain divergent. And divergences should grow.

+ +

I also use some branch to contain what is common between projects.

+ +

Say I have some branches:

+ +

master: common to all branches +dev: branch devoted to unstable development +client: branch with features for all client but not general enough for master +clientA: project adapted for client A +clientB: project adapted for client B

+ +

Here how I want to work:

+ +

Dynamic branching

+ +

And more precisely the branch hierarchy:

+ +

Branch hierarchy

+ +

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, :client ],
+    :dev => [ :master ],
+    :client => [ :clientA, :clientB ] }
+
+ +

Having a :master => [ :dev, :client ] means you can merge master branch into dev and client.

+ +

If by mistake I make a git checkout master && git merge clientA, I made a mistake. This is why I made a script which encapsulate the git behaviour to dodge this kind of mistake.

+ +

But this script do far more than that. It also merge from top to down. The action allmerges will do:

+ +
+git co dev && git merge master
+git co client && git merge master
+git co clientA && git merge client
+git co clientB && git merge client
+
+ +

That means, I can update all branches. The algorithm will not make loop even if there is a cycle in the branch hierarchy.

+ +

Here it is:

+ +
+
+#!/usr/bin/env ruby
+# encoding: utf-8
+
+# 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 ] }
+
+def get_current_branch()
+    (`git branch --no-color | awk '$1 == "*" {print $2}'`).chop.intern
+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
+
+require 'set'
+$known_branches=Set.new
+$architecture.each do |k,v| 
+    $known_branches.add(k)
+    v.each { |b| $known_branches.add(b) }
+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
+
+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.

+ +

Of course try to use as few as possible cherry-pick and rebase. This script was intended to work with workflow using pull and merge.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Created: 03/23/2010 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-05-17-at-least-this-blog-revive/index.html b/output/n3blog/en/blog/2010-05-17-at-least-this-blog-revive/index.html new file mode 100644 index 000000000..75ff4b751 --- /dev/null +++ b/output/n3blog/en/blog/2010-05-17-at-least-this-blog-revive/index.html @@ -0,0 +1,227 @@ + + + + + + + + + + + + + + + + + + + + + + + I live again! + + + + +
+ + +
+

+ I live again! +

+ +
+ +
+ + + + + +
+
+
+

Hi all!

+ +
+

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. +> Stop write TODO in your code and make it now!
+> 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.

+ +

What did I do?

+ +

I finished some web services/application for gridpocket©.

+ +

I also finished to update my blog engine to nanoc3. The difficult part was to handle nicely multiple languages. But I should detail why in a future post.

+ +

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.

+ +

Then what I plan to do from now:

+ +
    +
  • finish to make a public web service (I believe it can be popular)
  • +
  • finish to write the associated iPhone application for it
  • +
  • finish to publish our private framework to make web services
  • +
  • publish some articles about this blog (at least 3)
  • +
  • provide the sources of this website on github
  • +
+ +

There is some random in some of these achivement mostly because they don’t depend totally on me.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Created: 05/17/2010 + Modified: 05/19/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-05-19-How-to-cut-HTML-and-repair-it/code/repair_xml.rb b/output/n3blog/en/blog/2010-05-19-How-to-cut-HTML-and-repair-it/code/repair_xml.rb new file mode 100644 index 000000000..1121d4ef1 --- /dev/null +++ b/output/n3blog/en/blog/2010-05-19-How-to-cut-HTML-and-repair-it/code/repair_xml.rb @@ -0,0 +1,25 @@ + +# repair cutted XML code by closing the tags +# work even if the XML is cut into a tag. +# example: +# transform '
toto

hello ]*$/m,'') + depth-=1 + depth.downto(0).each { |x| res<<= %{} } + res +end diff --git a/output/n3blog/en/blog/2010-05-19-How-to-cut-HTML-and-repair-it/index.html b/output/n3blog/en/blog/2010-05-19-How-to-cut-HTML-and-repair-it/index.html new file mode 100644 index 000000000..caf1866ad --- /dev/null +++ b/output/n3blog/en/blog/2010-05-19-How-to-cut-HTML-and-repair-it/index.html @@ -0,0 +1,297 @@ + + + + + + + + + + + + + + + + + + + + + + + How to repair a cutted XML? + + + + +

+ + +
+

+ How to repair a cutted XML? +

+ +

+ and how to do it without any parsor? +

+ +
+ +
+ + + + + +
+
+
+

For my main page, you can see, a list of my latest blog entry. And you have the first part of each article. To accomplish that, I needed to include the begining of the entry and to cut it somewhere. But now, I had to repair this cutted HTML.

+ +

Here is an example:

+ +
+<div class="corps">
+    <div class="intro">
+        <p>Introduction</p>
+    </div>
+    <p>The first paragraph</p>
+    <img src="/img/img.png" alt="an image"/>
+    <p>Another long paragraph</p>
+</div>
+
+ +

After the cut, I obtain:

+ +
+<div class="corps">
+    <div class="intro">
+        <p>Introduction</p>
+    </div>
+    <p>The first paragraph</p>
+    <img src="/img/im
+
+ +

Argh! In the middle of an <img> tag.

+ +

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:

+ +
+[]           
+[div]           <div class="corps">
+[div, div]          <div class="intro">
+[div, div, p]           <p>
+                            Introduction
+[div, div]              </p>
+[div]               </div>
+[div, p]            <p>
+                        The first paragraph
+[div]               </p>
+[div]               <img src="/img/img.png" alt="an image"/>
+[div, p]            <p>
+                        Another long paragraph
+[div]               </p>
+[]              </div>
+
+ +

The algorihm, is then really simple: +<pre class="twilight"> +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.

+ +

remove any malformed/cutted tag in the end of res +for each tag in the stack, pop it, and write: + res = res + closed tag

+ +

return res +</pre>

+ +

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>'
+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.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Created: 05/19/2010 + Modified: 10/04/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-05-24-Trees--Pragmatism-and-Formalism/index.html b/output/n3blog/en/blog/2010-05-24-Trees--Pragmatism-and-Formalism/index.html new file mode 100644 index 000000000..3fe79ba97 --- /dev/null +++ b/output/n3blog/en/blog/2010-05-24-Trees--Pragmatism-and-Formalism/index.html @@ -0,0 +1,482 @@ + + + + + + + + + + + + + + + + + + + + + + + Trees; Pragmatism and Formalism + + + + +
+ + +
+

+ Trees; Pragmatism and Formalism +

+ +

+ When theory is more efficient than practice +

+ +
+ +
+ + + + + +
+
+
+ +
+ + +

tl;dr:

+ +
    +
  • I tried to program a simple filter
  • +
  • Was blocked 2 days
  • +
  • Then stopped working like an engineer monkey
  • +
  • Used a pen and a sheet of paper
  • +
  • Made some math.
  • +
  • Crushed the problem in 10 minutes
  • +
  • Conclusion: The pragmatism shouldn’t mean “never use theory”.
  • +
+ + +
+ + +

Abstract (longer than tl;dr)

+ +

For my job, I needed to resolve a problem. It first seems not too hard. +Then I started working directly on my program. +I entered in the infernal: try & repair loop. +Each step was like:

+ +
+

– Just this thing to repair and that should be done.
+ – OK, now that should just work.
+ – Yeah!!!
+ – Oops! I forgotten that…
+ repeat until death

+
+ +

After two days of this Sisyphus work, I finally just stopped to rethink the problem. +I took a pen, a sheet of paper. I simplified the problem, reminded what I learned during my Ph.D. about trees. +Finally, the problem was crushed in less than 20 minutes.

+ +

I believe the important lesson is to remember that the most efficient methodology to resolve this pragmatic problem was the theoretical one. +And therefore, argues opposing science, theory to pragmatism and efficiency are fallacies.

+ + +
+ +
+ + +

First: my experience

+ +

Apparently 90% of programmer are unable to program a binary search without bug. +The algorithm is well known and easy to understand. +However it is difficult to program it without any flaw. +I participated to this contest. +And you can see the results here1. +I had to face a problem of the same kind at my job. The problem was simple to the start. Simply transform an xml from one format to another.

+ +

The source xml was in the following general format:

+ +
+<rubrique>
+    <contenu>
+        <tag1>value1</tag1>
+        <tag2>value2</tag2>
+        ...
+    </contenu>
+    <enfant>
+        <rubrique>
+            ...
+        </rubrique>
+        ...
+        <rubrique>
+            ...
+        </rubrique>
+    </enfant>
+</menu>
+
+ +

and the destination format was in the following general format:

+ +
+<item name="Menu0">
+    <value>
+        <item name="menu">
+            <value>
+                <item name="tag1">
+                    <value>value1</value>
+                </item>
+                <item name="tag2">
+                    <value>value2</value>
+                </item>
+                ...
+                <item name="menu">
+                    <value>
+                        ...
+                    </value>
+                    <value>
+                        ...
+                    </value>
+                </item>
+            </value>
+        </item>
+    </value>
+</item>
+
+ +

At first sight I believed it will be easy. I was so certain it will be easy that I fixed to myself the following rules:

+ +
    +
  1. do not use xslt
  2. +
  3. avoid the use of an xml parser
  4. +
  5. resolve the problem using a simple perl script[^2]
  6. +
+ +

You can try if you want. If you attack the problem directly opening an editor, I assure you, it will certainly be not so simple. +I can tell that, because it’s what I’ve done. And I must say I lost almost a complete day at work trying to resolve this. There was also, many small problems around that make me lose more than two days for this problem.

+ +

Why after two days did I was unable to resolve this problem which seems so simple?

+ +

What was my behaviour (workflow)?

+ +
    +
  1. Think
  2. +
  3. Write the program
  4. +
  5. Try the program
  6. +
  7. Verify the result
  8. +
  9. Found a bug
  10. +
  11. Resolve the bug
  12. +
  13. Go to step 3.
  14. +
+ +

This was a standard workflow for computer engineer. The flaw came from the first step. +I thought about how to resolve the problem but with the eyes of a pragmatic engineer. I was saying:

+ +
+

That should be a simple perl search and replace program.
+Let’s begin to write code

+
+ +

This is the second sentence that was plainly wrong. I started in the wrong direction. And the workflow did not work from this entry point.

+ +

Think

+ +

After some times, I just stopped to work. Tell myself “it is enough, now, I must finish it!”. +I took a sheet of paper, a pen and began to draw some trees.

+ +

I began by make by removing most of the verbosity. +I first renamed <item name="Menu"> by simpler name M for example. +I obtained something like:

+ +

The source tree

+ +

and

+ +

The destination tree

+ +

Then I made myself the following reflexion:

+ +

Considering Tree Edit Distance, each unitary transformation of tree correspond to a simple search and replace on my xml source2. +We consider three atomic transformations on trees:

+ +
    +
  • substitution: renaming a node
  • +
  • insertion: adding a node
  • +
  • deletion: remove a node
  • +
+ +

One of the particularity of atomic transformations on trees, is ; if you remove a node, all children of this node, became children of its father.

+ +

An example:

+ +
+r - x - a
+  \   \
+   \    b
+    y - c   
+
+ +

If you delete the x node, you obtain

+ +
+    a
+  /
+r - b
+  \
+    y - c   
+
+ +

And look at what it implies when you write it in xml:

+ +
+<r>
+  <x>
+    <a>value for a</a>
+    <b>value for b</b>
+  </x>
+  <y>
+    <c>value for c</c>
+  </y>
+</r>
+
+ +

Then deleting all x nodes is equivalent to pass the xml via the following search and replace script:

+ +
+s/<\/?x>//g
+
+ +

Therefore, if there exists a one state deterministic transducer which transform my trees ; +I can transform the xml from one format to another with just a simple list of search and replace directives.

+ +

Solution

+ +

Transform this tree:

+ +
+R - C - tag1
+  \   \
+   \    tag2
+    E -- R - C - tag1
+      \   \    \
+       \   \     tag2
+        \    E ...
+         R - C - tag1 
+           \    \
+            \     tag2
+             E ...
+
+ +

to this tree:

+ +
+                tag1
+              /
+M - V - M - V - tag2      tag1
+              \         / 
+                M --- V - tag2
+                  \     \ 
+                   \      M
+                    \     tag1
+                     \  / 
+                      V - tag2
+                        \ 
+                          M
+
+ +

can be done using the following one state deterministic tree transducer:

+ +
+

C → ε
+ E → M
+ R → V

+
+ +

Wich can be traduced by the following simple search and replace directives:

+ +
+s/C//g
+s/E/M/g
+s/R/V/g
+
+ +

Once adapted to xml it becomes:

+ +
+s%</?contenu>%%g
+s%<enfant>%<item name="menu">%g
+s%</enfant>%</item>%g
+s%<rubrique>%<value>%g
+s%</rubrique>%</value>%g
+
+ +

That is all.

+ +

Conclusion

+ +

It should seems a bit paradoxal, but sometimes the most efficient approach to a pragmatic problem is to use the theoretical methodology.

+
+
    +
  1. +

    Hopefully I am in the 10% who had given a bug free implementation.

    +
  2. +
  3. +

    I did a program which generate automatically the weight in a matrix of each edit distance from data.

    +
  4. +
+
+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Created: 05/24/2010 + Modified: 09/21/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-06-14-multi-language-choices/index.html b/output/n3blog/en/blog/2010-06-14-multi-language-choices/index.html new file mode 100644 index 000000000..14be484c2 --- /dev/null +++ b/output/n3blog/en/blog/2010-06-14-multi-language-choices/index.html @@ -0,0 +1,230 @@ + + + + + + + + + + + + + + + + + + + + + + + multi language choices + + + + +
+ + +
+

+ multi language choices +

+ +
+ +
+ + + + + +
+
+
+

I translate most of my blog entries in French and English. +Most people advice me to have one file per language. Generally it ends with:

+ +
+Bonjour, 
+
+voici un exemple de texte en français.
+[image](url)
+
+ +
+Hello, 
+
+here is an example of english text.
+[image](url)
+
+ +

This way of handling translations force you to write completely an article in one language, copy it, and translate it.

+ +

However, most of time, there are common parts like images, source code, etc… +When I want to correct some mistake on these parts, I have to make twice the work. With sometimes adding another mistake in only one language.

+ +

This is why I preferred to handle it differently. +I use tags on a single file. +Finally my files looks like:

+ +
+ fr:   Bonjour, 
+ en:   Hello, 
+
+ en:   here is an example of english text.
+ fr:   voici un exemple de texte en français.
+[image](url)
+
+ +

As I edit my files with vim, it is really easy to add fr: or en: at some line’s beginning using the useful C-v. +However nanoc was conceived to be used for one language only. Or to be used with the first method. I tried to adapt nanoc to my usage. But after a while, I found it easier to pre-filter the nanoc work by a simple script. My script transform my file into two new files. And all work like a charm.

+ +

You can get my blog code source (without most of articles) at github.com/yogsototh/nanoc3_blog. I’ll make a new blog entry about how to use it. I added many scripts and libraries to help making nice website.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+ +
+ + +
+ +
+ Created: 06/14/2010 + Modified: 06/15/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-06-15-Get-my-blog-engine/index.html b/output/n3blog/en/blog/2010-06-15-Get-my-blog-engine/index.html new file mode 100644 index 000000000..336ae872d --- /dev/null +++ b/output/n3blog/en/blog/2010-06-15-Get-my-blog-engine/index.html @@ -0,0 +1,320 @@ + + + + + + + + + + + + + + + + + + + + + + + Get my blog engine + + + + +
+ + +
+

+ Get my blog engine +

+ +
+ +
+ + + + + +
+
+
+

I published a light version of my blog engine based on nanoc yesterday night. By light, I mean a lighter, more portable CSS (without round border). +You can get it on github.com.

+ +

What this system provide?

+ +
    +
  • All nanoc advantages,
  • +
  • Easy multi-language handling,
  • +
  • Syntax Coloration for most languages,
  • +
  • intenseDebate comments integration (asynchronous) ;
  • +
  • Portable with and without javascript, XHTML Strict 1.0 / CSS3,
  • +
  • Write in markdown format (no HTML editing needed),
  • +
  • Typographic ameliorations (no ‘:’ starting a line in French for example),
  • +
  • Graphviz graph generation integration.
  • +
+ + +
+ +
+ + +

Main Documentation Page

+ +

Use It NOW!

+ +

Once installed (follow the README.md instructions).

+ +
+$ cd /root/of/nanoc3_blog
+$ ./task/new_blog_entry Title of the blog
+$ vi latest.md
+$ ./task/recompile
+
+ +

Now your website reside into the output directory.

+ + +
+ +
+ + +

Documentation

+ +

Useful things to know

+ +

Multi-language

+ +

All files in multi are processed and copied in the content directory. +For each file in multi, each line starting by ‘fr: ’ are copied (without the fr: into the content/html/fr/ tree, but not into the content/html/en tree. File not starting by fr: or en: are copied in each destinations.

+ +

If you want to add another language, you’ll have to modify tasks/config, and config.yaml, create a content/html/xx where xx is the language code.

+ +

Edition & Rendering

+ +

additional keywords

+ +

You can separate multi content div using the: newcorps directive (see examples).

+ +

You can create div using begindiv(classname), enddiv. (See some existing blog entries for example). Use the class intro for the abstract part.

+ +

You can create nice description table using <desc> (See source code for example).

+ +

Typography

+ +

In French all ‘:’, ‘;’, ‘!’ and ‘?’ are preceded automatically by &nbsp. This enable not to have a line starting by a single special character.

+ +

You can use small caps using <sc> tags.

+ +
    +
  • (c) is replaced by ©.
  • +
  • (r) is replaced by ®.
  • +
  • <- is replaced by ←.
  • +
  • -> is replaced by →.
  • +
+ +

source code

+ +

To write source code you should use the following format:

+ +
+<code class="ruby" file="filename.rb">
+The code
+</cOde>
+
+ +

The file attribute is not required.

+ +

blog

+ +

If you want to make really long blog post, you can separate them into many files. To accomplish that, you simply have to make your files like:

+ +
+multi/blog/2010-06-01-the-title.md
+multi/blog/2010-06-01-the-title/second_part.md
+multi/blog/2010-06-01-the-title/third_part.md
+
+ +

mobileme

+ +

All files are intended to be generated into the output/n3blog directory. +This was made like that to work nicely with iWeb organisation of websites.

+ + + +

The order of post is done using the menupriority meta-data in the header of the files.

+ +

You can hide some file from the menu by setting: isHidden: true in the header.

+ +

Details

+ +

To know more about this blog engine, you should look at +nanoc project.

+ +

Then look at the files inside your project:

+
+
+README.md readme for the project (used by github)
+latest.md symbolic link to the last blog entry
+multi/ Directory containing multi-language articles
+tasks/ scripts for website live
+config.yaml global configuration file
+Rules generation rules
+content/ content files processed by nanoc
+layouts/ erb templates
+lib/ ruby libraries used to process files
+output/ website
+Rakefile not mandatory for this blog
+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ + + + +
+ +
+ Created: 06/15/2010 + Modified: 06/24/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-06-17-hide-yourself-to-analytics/code/become_hidden.html b/output/n3blog/en/blog/2010-06-17-hide-yourself-to-analytics/code/become_hidden.html new file mode 100644 index 000000000..e3f00f255 --- /dev/null +++ b/output/n3blog/en/blog/2010-06-17-hide-yourself-to-analytics/code/become_hidden.html @@ -0,0 +1,21 @@ + + + + + + + + + + Hide to analytics + + +
+ + diff --git a/output/n3blog/en/blog/2010-06-17-hide-yourself-to-analytics/code/become_visible.html b/output/n3blog/en/blog/2010-06-17-hide-yourself-to-analytics/code/become_visible.html new file mode 100644 index 000000000..3593c9bfc --- /dev/null +++ b/output/n3blog/en/blog/2010-06-17-hide-yourself-to-analytics/code/become_visible.html @@ -0,0 +1,21 @@ + + + + + + + + + + Hide to analytics + + +
+ + diff --git a/output/n3blog/en/blog/2010-06-17-hide-yourself-to-analytics/index.html b/output/n3blog/en/blog/2010-06-17-hide-yourself-to-analytics/index.html new file mode 100644 index 000000000..b55a33c54 --- /dev/null +++ b/output/n3blog/en/blog/2010-06-17-hide-yourself-to-analytics/index.html @@ -0,0 +1,262 @@ + + + + + + + + + + + + + + + + + + + + + + + Hide Yourself to your Analytics + + + + +
+ + +
+

+ Hide Yourself to your Analytics +

+ +
+ +
+ + + + + +
+
+
+

This is a way not to count your own visits to your blog. +First you should look on how I handle analytics. All analytics are handled in one javascript file, this make things really convenient.

+ +

Then you need to know my method use the jquery-cookie.

+ +

I check if the key admin is not set in the cookie before adding the visit.

+ +
+    var admin = $.cookie('admin');
+    if (! admin) {
+        // put your analytics code here
+    } else {
+        console.log("[WARNING] you're HIDDEN to analytics");
+    }
+
+ +

then create two html files. One to hide:

+ +
+
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="fr" xml:lang="fr">
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+        <script type="text/javascript" src="jquery.js"></script>
+        <script type="text/javascript" src="jquery.cookie.js"></script>
+        <script>
+            $(document).ready(function(){
+                $.cookie('admin',1);
+                $('#info').html('Analytics can no more see you.')
+            });
+        </script>
+        <title>Hide to analytics</title>
+    </head>
+    <body>
+        <div id="info"></div> 
+    </body>
+</html>
+
+
+ +

the other to be visible again (it can be useful):

+ +
+
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="fr" xml:lang="fr">
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+        <script type="text/javascript" src="jquery.js"></script>
+        <script type="text/javascript" src="jquery.cookie.js"></script>
+        <script>
+            $(document).ready(function(){
+                $.cookie('admin',null);
+                $('#info').html('Analytics can see you.')
+            });
+        </script>
+        <title>Hide to analytics</title>
+    </head>
+    <body>
+        <div id="info"></div> 
+    </body>
+</html>
+
+
+ +

Now accessing these files with you browser you can hide or appear in your statistics. You just have to think to access these file from all you browser.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+ +
+ + +
+ +
+ Created: 06/17/2010 + Modified: 06/18/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-06-17-track-events-with-google-analytics/code/yga.js b/output/n3blog/en/blog/2010-06-17-track-events-with-google-analytics/code/yga.js new file mode 100644 index 000000000..31369ad5c --- /dev/null +++ b/output/n3blog/en/blog/2010-06-17-track-events-with-google-analytics/code/yga.js @@ -0,0 +1,46 @@ + +$(document).ready( function() { + // add an event to all link for google analytics + $('a').click(function () { + // tell analytics to save event + try { + var identifier=$(this).attr('id') ; + var href=$(this).attr('href') + var label=""; + if ( typeof( identifier ) != 'undefined' ) { + label=label+'[id]:'+identifier + category='JSLink' + } + if ( typeof( href ) != 'undefined' ) { + label=label+' [href]:'+href + if ( href[0] == '#' ) { + category='Anchor'; + } else { + category='Link'; + } + } + _gaq.push(['_trackEvent', category, 'clicked', label]); + // console.log('[tracked]: ' + category + ' ; clicked ; ' + label ); + } + catch (err) { + console.log(err); + } + + // pause to allow google script to run + var date = new Date(); + var curDate = null; + do { + curDate = new Date(); + } while(curDate-date < 300); + }); +}); + +var _gaq = _gaq || []; +_gaq.push(['_setAccount', 'UA-XXXXXXXX-1']); +_gaq.push(['_trackPageview']); + +(function() { + var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; + ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; + var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); + })(); diff --git a/output/n3blog/en/blog/2010-06-17-track-events-with-google-analytics/index.html b/output/n3blog/en/blog/2010-06-17-track-events-with-google-analytics/index.html new file mode 100644 index 000000000..d97d30244 --- /dev/null +++ b/output/n3blog/en/blog/2010-06-17-track-events-with-google-analytics/index.html @@ -0,0 +1,263 @@ + + + + + + + + + + + + + + + + + + + + + + + Track Events with Google Analytics + + + + +
+ + +
+

+ Track Events with Google Analytics +

+ +

+ Asynchronous Complete Google Analytics with jQuery +

+ +
+ +
+ + + + + +
+
+
+

Here is how to track all clicks on your website using google analytics asynchronously.

+ +

First in your html you need to use jQuery and a javscript file I named yga.js:

+ +
+    <script type="text/javascript" src="jquery.js"></script>
+    <script type="text/javascript" src="yga.js"></script>
+
+ +

And here is the yga.js file:

+ +
+
+$(document).ready( function() {
+    // add an event to all link for google analytics
+    $('a').click(function () {
+        // tell analytics to save event
+        try {
+            var identifier=$(this).attr('id') ;
+            var href=$(this).attr('href')
+            var label="";
+            if ( typeof( identifier ) != 'undefined' ) {
+                label=label+'[id]:'+identifier
+                category='JSLink'
+            }
+            if ( typeof( href ) != 'undefined' ) {
+                label=label+' [href]:'+href
+                if ( href[0] == '#' ) {
+                    category='Anchor';
+                } else {
+                    category='Link';
+                }
+            }
+            _gaq.push(['_trackEvent', category, 'clicked', label]);
+            // console.log('[tracked]: ' + category + ' ; clicked ; ' + label );
+        }
+        catch (err) {
+            console.log(err);
+        }
+
+        // pause to allow google script to run
+        var date = new Date();
+        var curDate = null;
+        do {
+            curDate = new Date();
+        } while(curDate-date < 300);
+    });
+});
+
+var _gaq = _gaq || [];
+_gaq.push(['_setAccount', 'UA-XXXXXXXX-1']);
+_gaq.push(['_trackPageview']);
+
+(function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+
+
+ +

Replace the: UA-XXXXXXXX-1 by your google analytics code and you’re done.

+ +

To see what occurs, simply go in Content and Event Tracking as shown in the following screenshot:

+ +

Where to find events tracking in google analytics interface

+ +

Happy tracking!

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Created: 06/17/2010 + Modified: 06/17/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-06-19-jQuery-popup-the-easy-way/code/essai.js b/output/n3blog/en/blog/2010-06-19-jQuery-popup-the-easy-way/code/essai.js new file mode 100644 index 000000000..751a56c5c --- /dev/null +++ b/output/n3blog/en/blog/2010-06-19-jQuery-popup-the-easy-way/code/essai.js @@ -0,0 +1,23 @@ + +// --- code popup --- +function openPopup() { + $(this).clone(false).appendTo($("#_code")); + $("#_code").show(); +} + +function closePopup() { + $("#_code").html(""); + $("#_code").hide(); +} + +function initCode() { + $(".code").click(openPopup); + $(".code").css({cursor: "pointer"}); + $('body').append('
'); + $('#_code').css( { 'text-align': "justify", position: "fixed", + left:0, top:0, width: "100%", height: "100%", + "background-color": "rgba(0, 0, 0, 0.8)", 'z-index':2000, 'padding':'3px'} ); + $('#_code').hide(); + $('#_code').click(closePopup); +} +// --- end of code popup section --- diff --git a/output/n3blog/en/blog/2010-06-19-jQuery-popup-the-easy-way/index.html b/output/n3blog/en/blog/2010-06-19-jQuery-popup-the-easy-way/index.html new file mode 100644 index 000000000..2d68aebad --- /dev/null +++ b/output/n3blog/en/blog/2010-06-19-jQuery-popup-the-easy-way/index.html @@ -0,0 +1,234 @@ + + + + + + + + + + + + + + + + + + + + + + + jQuery popup the easy way + + + + +
+ + +
+

+ jQuery popup the easy way +

+ +
+ +
+ + + + + +
+
+
+

Some source code on this blog can be downloaded. +Most of time, the code is larger than the div bloc. +This is why I use a method to show this code in a large jQuery popup.

+ +

You can try clicking the following code ; remark that the content is cutted a bit after z-index:

+ +
+
+// --- code popup ---
+function openPopup() {
+    $(this).clone(false).appendTo($("#_code"));
+    $("#_code").show();
+}
+
+function closePopup() {
+    $("#_code").html("");
+    $("#_code").hide();
+}
+
+function initCode() {
+    $(".code").click(openPopup);
+    $(".code").css({cursor: "pointer"});
+    $('body').append('<div id="_code"></div>');
+    $('#_code').css( { 'text-align': "justify", position: "fixed", 
+                        left:0, top:0, width: "100%", height: "100%", 
+                        "background-color": "rgba(0, 0, 0, 0.8)", 'z-index':2000, 'padding':'3px'} );
+    $('#_code').hide();
+    $('#_code').click(closePopup);
+}
+// --- end of code popup section ---
+
+
+ +

This code is the one I use to obtain this result.

+ +

What does it do?

+ +

At the loading of the page, I create a div as wide as the window. +This div is a bit transparent. Then I hide it. I also take care to its z-index value to be sure it is behind all elements.

+ +

Then when we click on a div of class code, I copy the content into this new wide div, and I show it. +Really simple but really efficient. +No need to use a jQuery plugin.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ + + + +
+ +
+ Created: 06/19/2010 + Modified: 06/19/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-07-05-Cappuccino-and-Web-applications/index.html b/output/n3blog/en/blog/2010-07-05-Cappuccino-and-Web-applications/index.html new file mode 100644 index 000000000..941ba373b --- /dev/null +++ b/output/n3blog/en/blog/2010-07-05-Cappuccino-and-Web-applications/index.html @@ -0,0 +1,356 @@ + + + + + + + + + + + + + + + + + + + + + + + Cappuccino vs jQuery + + + + +
+ + +
+

+ Cappuccino vs jQuery +

+ +
+ +
+ + + + + +
+
+
+ +
+ + +

tl;dr:

+ +
    +
  • Tried to make YPassword in jQuery and with Cappuccino.
  • +
  • Cappuccino nice in desktop browser but 1.4MB, not compatible with iPhone.
  • +
  • jQuery not as nice as the Cappuccino version but 106KB. iPhone compatible.
  • +
  • I’ll give a try to Dashcode 3.
  • +
+ + +
+ + +
+ +
+ + +

Before start, I must say I know Cappuccino and jQuery are no more comparable than Cocoa and the C++ standard library. One is oriented for user interface while the other is and helper for low level programming. +Nonetheless I used these two to make the same web application. This is why I compare the experience I had with each of them for this specific task.

+ + +
+ + +

I made a web version of my dashboard widget YPassword. +It is a simple widget to manage your online password with a strong security and with a totally portable way. It is not intended to replace a keychain. +It is more a password generator.

+ +

The first was made from the code of my dashboard widget and with some jQuery. +You can try it here. +I then made a second version with the Cappuccino. You can try it here.

+ +

What this widget do?

+ + +
+ + +

If you don’t mind about what does my widget and just want to know how the two frameworkcompare, you should go +directly to the next part.

+ + +
+ + +

I manage my password on many site with a simple method. +I remember a strong master password. And my password is mainly +<pre class="twilight">hash(masterPassword+domainName) +</pre>

+ +

In reality I need a bit more informations to create a password:

+ +
    +
  • A master password,
  • +
  • an URL,
  • +
  • a maximal password length,
  • +
  • the kind of output base64 or hexadecimal,
  • +
  • how many times my password could have leaked.
  • +
+ +

The result password is this:

+ +
+domainName=domaine_Name_Of_URL(url)
+hash=sha1( masterPassword + leakedTimes + domainName )
+if ( kind == 'base64' )
+    hash=base64(hash)
+end
+return hash[0..maxlength]
+
+ +

In fact depending of websites, some give some strange constraint to your password:

+ +
    +
  • minimal length,
  • +
  • maximal length,
  • +
  • must not contain a special character,
  • +
  • must contain a special character,
  • +
  • etc…
  • +
+ +

And if you want to change your password the leak number is here for that. +All informations such as user name, maximal length can be stored in a public file. The only real secret is the master password.

+ +

If you want to know even more details you can always look at some of my old blog entries:

+ + + +

Cappuccino

+ +

First, I’d like to say Cappuccino applications look simply awesome. +It is like having a Cocoa application in your web browser. +And this is great.

+ +

I also must admit I enjoyed making my application with Cappuccino. +It is like programming for an iPhone application. +If you are a bit familiar with Cocoa, you feel at home. +If you don’t know anything about Cocoa, I suggest you to look at it. +This is a really great framework to make User Interface. +I am not a specialist, but I have done some MFC, java Swing1 and WXWindows User Interfaces (some years ago). +And I must say, Cocoa is far better than those.

+ +

Cappuccino is a great web application oriented development. +But there was also some drawbacks

+ +

Things I liked:

+ +
    +
  • It looks great
  • +
  • It was fun to program
  • +
  • It was like programming a Mac application
  • +
  • I could have done the User Interface using Interface Builder.
  • +
+ +

Some things I didn’t like:

+ +
    +
  • I made some time to understand how to handle the onChange on the text fields.
  • +
  • Documentation lacked a bit of organisation.
  • +
  • It doesn’t work on iPhone.
  • +
  • It weighted 11MB to deploy.
  • +
  • It weight 1.3MB to load.
  • +
+ +

I didn’t use bindings because I believe they are not ready by now.

+ +

jQuery

+ +

The jQuery version of YPassword is not as finished as the Cappuccino one. Because, there is no slider directly with jQuery. I’d have to use jQueryUI. And I believe, using it will make the application weight far more than the today 106KB.

+ +

To make this version I simply copied my widget source code and adapted it. It was straightforward. But jQuery is not an application oriented framework. It is more a “dark side javascript animation framework”2.

+ +

I don’t have too much to say about the jQuery version. But this was way more low level programming than Cappuccino.

+ +

My conclusion

+ +

If you want to make an iPhone compatible web application just don’t use Cappuccino yet. +If you want to make simple application like mine, I also believe, Cappuccino is a bit too much.

+ +

If you want to make a complex web oriented application, Cappuccino is a great choice. +But you may have some difficulties to begin programming with it.

+ +

Finally, to terminate my web version of my widget, I’ll give a try to Dashcode 3. +It seems to be a good alternative to create web widgets. +I don’t know if Dashcode 3 is portable on non webkit browser. +But if it is, it could be the end of projects like Cappuccino and Sproutcore.

+
+
    +
  1. +

    If you are interested you can take a look at SEDiL. I am proud of the tree drawing view made from scratch.

    +
  2. +
  3. +

    I don’t want to feel like a troll I use jQuery to make some dark side animation on this blog. But the javascript on my blog is not needed except for commenting.

    +
  4. +
+
+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ + + + +
+ +
+ Created: 07/05/2010 + Modified: 08/01/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-07-07-CSS-rendering-problems-by-navigator/index.html b/output/n3blog/en/blog/2010-07-07-CSS-rendering-problems-by-navigator/index.html new file mode 100644 index 000000000..e11290f76 --- /dev/null +++ b/output/n3blog/en/blog/2010-07-07-CSS-rendering-problems-by-navigator/index.html @@ -0,0 +1,220 @@ + + + + + + + + + + + + + + + + + + + + + + + Do not use CSS gradient with Chrome + + + + +
+ + +
+

+ Do not use CSS gradient with Chrome +

+ +
+ +
+ + + + + +
+
+
+

Some Reddit users reported my website was really long to load and to scroll. +They thinks it was because of the ‘1px shadow’ I apply on all the text. +I was a bit surprised, because I make some test into a really slow virtual machine. And all have always worked fine. In fact, what slow down so much are by order of importance:

+ +
    +
  1. Radial gradient on Chrome (not in Safari on Mac)
  2. +
  3. Box shadows on Firefox and Chrome
  4. +
+ +

Gradient

+ +

On Safari on Mac there is absolutely no rendering time problem. But when I use Chrome under Linux it is almost unusable.

+ +

Safari and Chrome use webkit, when you access my website with javascript enabled, an additionnal browser specific CSS is loaded. Until now I switched only between: IE, Mozilla and Webkit. Now I added one more special case for Chrome. Now I continue to use gradient for Safari but no more on Chrome.

+ +

I didn’t tried to verify the efficiency of all new CSS 3 features. But I advise you not to use -webkit-gradient on Chrome. At least when the host is a Linux.

+ +

Box Shadows

+ +

I also detected that -moz-box-shadow elements slow down the rendering on Firefox under Linux. But there was very few time rendering issue with Safari on Mac.

+ +

Text Shadows

+ +

Many tell me to use text-shadows sparingly. But I believe it was not the real reason of the slow down. This is why I’ll get them back.

+ +

Conclusion

+ +

Do not use -webkit-gradient on Chrome browser yet. +Try to use -moz-box-shadow sparingly.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Created: 07/07/2010 + Modified: 10/07/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-07-09-Indecidabilities/index.html b/output/n3blog/en/blog/2010-07-09-Indecidabilities/index.html new file mode 100644 index 000000000..86c9c101f --- /dev/null +++ b/output/n3blog/en/blog/2010-07-09-Indecidabilities/index.html @@ -0,0 +1,412 @@ + + + + + + + + + + + + + + + + + + + + + + + Undecidabilities (part 1) + + + + +
+ + +
+

+ Undecidabilities (part 1) +

+ +
+ +
+ + + + + +
+
+
+ +
+ + +

tl;dr: I pretend to create a world to give examples of different meanings behind the word undecidability:

+ +
    +
  • Undecidability due to measure errors,
  • +
  • Big errors resulting from small initial measure error,
  • +
  • Fractal undecidability ;
  • +
  • Logic Undecidability.
  • +
+ + +
+ + + +
+ +
+ + +

The Undecidabilities

+ + +
+ + +

If a demiurge made our world, he certainly had a great sense of humor. +After this read, you should be convinced. +I’ll pretend to be him. +I’ll create a simplified world. +A world that obey to simple mathematical rules. +And I’ll tell you about one of the curse on this world: the undecidability. +The inability to know if we had find the truth. +The inability to predict many things that should be natural. +Here begin the story.

+ + +
+ + +

no name

+ +

In the beginning there was only void. +Then a blog post beginning to be written. +I breath profoundly to feel the weight of the act I will accomplish. +A last tense moment and… I create the Universe. +An incredible Universe which will exists only the time of this read. +I’m the demiurge of this universe and you are its observer.

+ +

I construct this world using only simples rules. +I decide that real rules of this world will be the one we believe are true for our world. +Note the difference. +For their world, everything we believe today is true for them. +Their world is then probably simpler than our. +Particularly, we can describe this world with axioms and mathematic rules. +It is not so sure for our Universe. +But we’ll talk about that later.

+ +

Lets the work begin. +I create an Earth. +I populate it with intelligent people, the Ys. +Of course they are curious. +In particular they try to understand their world. +They believe that if they know the rules of their world they will be able to predict the consequences of most of their acts. +They are so naive. +If only they knew. +But I’m here to help them.

+ +

I am a God who likes jokes. +The first joke I make to Ys is to make their sense imperfect. +Furthermore it is not possible to make perfect precise measure in my world. +I let Ys ameliorate their technology but there is a theoretical limit to the best precision they can reach.

+ +

I’d like to precise that these people believe their world is flat. +Some believe it is possible to find the rules of their Universe. +Now, let the game begins.

+ +

Lets start easily, errors can cause undecidability.

+ +

Undecidability due to measure errors

+ +

Here is what one of them think:

+ +
+

All triangle I observe seems to share the same property. +Each time I sum up their angles I obtain π radiants (180°). +It is certainly a rule of my Universe. +But how to be certain all triangle in my Universe share this property?

+
+ +

no name

+ +

Some began to formalize the problem. +They end by writing a mathematical proof. +Marvelous! +The proof seems correct, but, a problem remains. +The proof is based on rules and axioms. +How to be certain these rules and axioms are right in their world? +They will try to measure again and again the sum of the angles of triangles. +The measure will never fail. +But they’ll never be certain the rules and axioms are right. +Because then only way to verify all axioms depends of observation. +And as a facetious god, I forbid perfect measure in observation.

+ +

Of course, they prey, they call me to help. +And as any respectful god, I don’t answer. +Ah ah ah! I’ve always loved to make these kind of thing. +Let’s act as if I don’t exists. +What a good joke!

+ +

They feel sad. But they have some hope:

+ +

Hope

+ +
+

If we make small measure error, we will make small predictive error.

+
+ +

Growing errors Undecidability

+ +

no name

+ +

Unfortunately, the three bodies problem will crush this hope. +Using Newton’s Universal Law of gravitation with two bodies, we can predict with precision what will be their position and speed in the future. +Until there all seems OK. +But now, add another body. +All errors will grow. +Errors will grow at a point that any prediction will be unusable.

+ +

Even with this bad news there is the hope to control the error. +> May we should know the maximal measure error we can handle to predict something. +> And we should at least determine what we can predict and what we cannot.

+ +

Once again, this should not terminate has they hope.

+ +

Fractal Undecidability

+ +

Consider the following question:

+ +

no name

+ +

Consider some GPS coordinates on a point around the cost of the “Bretagne” in France. +The coordinates are 3 feet precise. +Is the point in the water or on Earth?

+ +

For some coordinates it is not possible to know. +Even if we are authorize to move a bit to dodge the borders. +Because there are some zone in which all point could be a “border” for any size of the zone.

+ +

We can even imagine some mathematical structure where all points are at the border[^2]. +[^2]: The set R\Q has this property.

+ +

Logical Undecidability

+ +

no name

+ +

Until there all problem were undecidable because of measure errors. +May be in a controlled world without any error we should be able to predict anything.
+I’m sorry to say no. +Even in a self-contained mathematical world it can be possible to create object with an unpredictable behaviour.

+ +

It is the halting problem.

+ +

Theorem: It is undecidable given a description of a program, whether the program finishes running or will run forever. +The idea of the proof is simple enough to be part of this article. +And this is with pleasure I give you one here.

+ +
+

Suppose a program able to decide if any program halt exists. +More precisely:

+ +

Hypothesis: there exists a program P such that:

+ +
    +
  • P(x,y) return “stop” in a finite amount of time if x(y)1 will stop running.
  • +
  • P(x,y) return “loop” in a finite amount of time if x(y) will never stop running.
  • +
+ +

Remark: Any program can be represented as a string. Therefore, a program can be used as the input of another program. +It is authorized to write P(x,x).

+ +

Let Q be the following program using the return value of P. +<pre class="twilight"> +Q(x) : + if P(x,x)=”stop” then I enter in an infinite loop + if P(x,x)=”loop” then I stop +</pre>

+ +

Now, what is the value of P(Q,Q)?

+ +
    +
  • if P(Q,Q) returns “stop” that imply by construction of Q that P(Q,Q) returns “loop”.
  • +
  • if P(Q,Q) returns “loop” that means by construction of Q that P(Q,Q) return “stop”.
  • +
+ +

Therefore there is a contradiction the only way to handle is by the non existence of the program P.

+
+ +

I am the demiurge of this imaginary world. +And I cannot know the future of this world. +Therefore, creative power isn’t equivalent to omnipotence.

+ + +
+ +
+ + +

After all this, it becomes difficult to know what we can believe. +But it would be another error to throw away all our knowledge. +In a future next part, I’ll explain what we can hope and what attitude we should have once we’ve realized most of truth are unaccessible.

+
+
    +
  1. +

    Meaning x taking y as input.

    +
  2. +
+
+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ + + + +
+ +
+ Created: 08/11/2010 + Modified: 08/17/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-07-31-New-style-after-holidays/index.html b/output/n3blog/en/blog/2010-07-31-New-style-after-holidays/index.html new file mode 100644 index 000000000..db59349d7 --- /dev/null +++ b/output/n3blog/en/blog/2010-07-31-New-style-after-holidays/index.html @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + New style after holidays + + + + +
+ + +
+

+ New style after holidays +

+ +
+ +
+ + + + + +
+
+
+

Before my holidays many visitors tell me my website was too long to scroll. +This is why I completely changed my website design. +Now all should scroll smoothly on all platforms. +I was inspired by Readability and iBooks© (the iPhone© application).

+ +

Tell me what you think of this new design.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ + + + +
+ +
+ Created: 07/31/2010 + Modified: 08/01/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-08-23-Now-heberged-on-heroku/code/.gems b/output/n3blog/en/blog/2010-08-23-Now-heberged-on-heroku/code/.gems new file mode 100644 index 000000000..7c156f5cb --- /dev/null +++ b/output/n3blog/en/blog/2010-08-23-Now-heberged-on-heroku/code/.gems @@ -0,0 +1,4 @@ + +rack +rack-rewrite +rack-contrib diff --git a/output/n3blog/en/blog/2010-08-23-Now-heberged-on-heroku/code/config.ru b/output/n3blog/en/blog/2010-08-23-Now-heberged-on-heroku/code/config.ru new file mode 100644 index 000000000..78678fb46 --- /dev/null +++ b/output/n3blog/en/blog/2010-08-23-Now-heberged-on-heroku/code/config.ru @@ -0,0 +1,43 @@ + +require 'rubygems' +require 'rack' +require 'rack/contrib' +require 'rack-rewrite' +require 'mime/types' + +use Rack::ETag +module ::Rack + class TryStatic < Static + + def initialize(app, options) + super + @try = ([''] + Array(options.delete(:try)) + ['']) + end + + def call(env) + @next = 0 + while @next < @try.size && 404 == (resp = super(try_next(env)))[0] + @next += 1 + end + 404 == resp[0] ? @app.call : resp + end + + private + def try_next(env) + env.merge('PATH_INFO' => env['PATH_INFO'] + @try[@next]) + end + + end +end + +use Rack::TryStatic, + :root => "output", # static files root dir + :urls => %w[/], # match all requests + :try => ['.html', 'index.html', '/index.html'] # try these postfixes sequentially + +errorFile='output/n3blog/en/error/404-not_found/index.html' +run lambda { [404, { + "Last-Modified" => File.mtime(errorFile).httpdate, + "Content-Type" => "text/html", + "Content-Length" => File.size(errorFile).to_s + }, File.read(errorFile)] } diff --git a/output/n3blog/en/blog/2010-08-23-Now-heberged-on-heroku/index.html b/output/n3blog/en/blog/2010-08-23-Now-heberged-on-heroku/index.html new file mode 100644 index 000000000..1ebeafccb --- /dev/null +++ b/output/n3blog/en/blog/2010-08-23-Now-heberged-on-heroku/index.html @@ -0,0 +1,281 @@ + + + + + + + + + + + + + + + + + + + + + + + Now hosted by heroku + + + + +
+ + +
+

+ Now hosted by heroku +

+ +

+ Host static website on Heroku +

+ +
+ +
+ + + + + +
+
+
+

Now on Heroku

+ +

I now changed my hosting to Heroku. +I believe it will be far more reliable.

+ +

But as you should know my website is completely static. +I use nanoc to generate it. +But here is the conf to make it work on heroku.

+ +

The root of my files is /output. You only need to create a config.ru1 file:

+ +
+
+require 'rubygems'
+require 'rack'
+require 'rack/contrib'
+require 'rack-rewrite'
+require 'mime/types'
+
+use Rack::ETag
+module ::Rack
+    class TryStatic < Static
+
+        def initialize(app, options)
+            super
+            @try = ([''] + Array(options.delete(:try)) + [''])
+        end
+
+        def call(env)
+            @next = 0
+            while @next < @try.size && 404 == (resp = super(try_next(env)))[0] 
+                @next += 1
+            end
+            404 == resp[0] ? @app.call : resp
+        end
+
+        private
+        def try_next(env)
+            env.merge('PATH_INFO' => env['PATH_INFO'] + @try[@next])
+        end
+
+    end
+end
+
+use Rack::TryStatic, 
+    :root => "output",                              # static files root dir
+    :urls => %w[/],                                 # match all requests 
+    :try => ['.html', 'index.html', '/index.html']  # try these postfixes sequentially
+
+errorFile='output/n3blog/en/error/404-not_found/index.html'
+run lambda { [404, {
+                "Last-Modified"  => File.mtime(errorFile).httpdate,
+                "Content-Type"   => "text/html",
+                "Content-Length" => File.size(errorFile).to_s
+            }, File.read(errorFile)] }
+
+
+ +

and the .gems file needed to install rack middlewares.

+ +
+
+rack
+rack-rewrite
+rack-contrib
+
+
+ +

Now, just follow the heroku tutorial to create an application :

+ +
+git init
+git add .
+heroku create
+git push heroku master
+
+ +

Now I’ll should be able to redirect properly to my own 404 page for example. +I hope it is helpful.

+
+
    +
  1. +

    I was inspired by this article.

    +
  2. +
+
+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ + + + +
+ +
+ Created: 08/23/2010 + Modified: 09/16/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-08-31-send-mail-from-command-line-with-attached-file/index.html b/output/n3blog/en/blog/2010-08-31-send-mail-from-command-line-with-attached-file/index.html new file mode 100644 index 000000000..8159ef538 --- /dev/null +++ b/output/n3blog/en/blog/2010-08-31-send-mail-from-command-line-with-attached-file/index.html @@ -0,0 +1,264 @@ + + + + + + + + + + + + + + + + + + + + + + + send mail from command line with attached file + + + + +
+ + +
+

+ send mail from command line with attached file +

+ +
+ +
+ + + + + +
+
+
+

I had to send a mail using only command line. +I was surprised it isn’t straightforward at all. +I didn’t had pine nor mutt or anything like that. +Just mail and mailx.

+ +

What Internet say (via google) is

+ +
+uuencode fic.jpg fic.jpg | mail -s 'Subject'
+
+ +

I tried it. +And it works almost each times. +But for my file, it didn’t worked. +I compressed it to .gz, .bz2 and .zip. +Using .bz2 format it worked nicely, but not with other formats. +Instead of having an attached file I saw this in my email.

+ +
+begin 664 fic.jpg
+M(R$O=7-R+V)I;B]E;G8@>G-H"GAL<STD,0H*9F]R(&QI;F4@:6X@)"@\("1X
+M;',@*0H@("`@9&-R/20H96-H;R`D;&EN92!\(&%W:R`M1EP[("=[<')I;G0@
+...
+M93U<(FUO='-<(CX\=F%L=64^/&ET96T@;F%M93U<(F-T>%]M8UPB/BD\=F%L
+M=64O/B@\+VET96T^*2-<)#$\=F%L=64^)&ME>7=O<F1S/"]V86QU93Y<)#(C
+end
+
+ +

Not really readable. +After some research I found the solution. +Use MIME instead of uuencode.

+ +

Finally I made it manually using sendmail. +I didn’t dare to use telnet. +The command to use is:

+ +
+sendmail -t -oi < mailcontent.txt
+
+ +

Of course you need to create the mailcontent.txt file. +It should contains:

+ +
+From: from@mail.com
+To: to@mail.com
+Subject: View the attached file
+Mime-Version: 1.0
+Content-Type: multipart/mixed; boundary="-"
+
+This is a MIME encoded message. Decode it with "Decoder"
+or any other MIME reading software. Decoder is available
+at <http://www.etresoft.com>.
+---
+Content-Type: image/jpeg; name="fic.jpg"
+Content-Transfer-Encoding: base64
+Content-Disposition: inline; filename="fic.jpg"
+
+H4sICB6Ke0wAA2Rjcl93aXRob3V0X2tleXdvcmQuY3N2ANSdW5ubOJPH7/e7
+7Brw+dmrTk8yk7yTSTaZeWd2b/TIIGy6MRAE7ng+/VaJgwF3g522SsxN2+3T
+/4eOJamqmARP+yibvI8ykUYim+x5EE2euBfIyd3byZ+fvvzr7svbu8ndTx/f
+...
+
+ +

And to obtain the “encoded” file in base64 I used:

+ +

+uuencode -m fic.jpg fic.jpg +

+ +

That is all. +Sometimes technology is so easy to use. +If I need it another time I should consider to make a shell script to automatize this.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+ +
+ + +
+ +
+ Created: 08/31/2010 + Modified: 08/31/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes/code/gitmtime.rb b/output/n3blog/en/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes/code/gitmtime.rb new file mode 100644 index 000000000..f95ac83f9 --- /dev/null +++ b/output/n3blog/en/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes/code/gitmtime.rb @@ -0,0 +1,15 @@ + +def gitmtime + filepath=@item.path.sub('/n3blog/','content/html/').sub(/\/$/,'') + ext=%{.#{@item[:extension]}} + filepath<<=ext + if not FileTest.exists?(filepath) + filepath.sub!(ext,%{/index#{ext}}) + end + str=`git log -1 --format='%ci' -- #{filepath}` + if str.nil? or str.empty? + return Time.now + else + return DateTime.parse( str ) + end +end diff --git a/output/n3blog/en/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes/index.html b/output/n3blog/en/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes/index.html new file mode 100644 index 000000000..39d8e7498 --- /dev/null +++ b/output/n3blog/en/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes/index.html @@ -0,0 +1,224 @@ + + + + + + + + + + + + + + + + + + + + + + + Use git to calculate trusted mtimes + + + + +
+ + +
+

+ Use git to calculate trusted mtimes +

+ +
+ +
+ + + + + +
+
+
+

You can remark at the bottom of each page I provide a last modification date. +This label was first calculated using the mtime of the file on the file system. +But many times I modify this date just to force some recompilation. +Therefore the date wasn’t a date of real modification.

+ +

I use git to version my website. +And fortunately I can know the last date of real change of a file. +This is how I do this with nanoc:

+ +
+
+def gitmtime
+    filepath=@item.path.sub('/n3blog/','content/html/').sub(/\/$/,'')
+    ext=%{.#{@item[:extension]}}
+    filepath<<=ext
+    if not FileTest.exists?(filepath)
+        filepath.sub!(ext,%{/index#{ext}})
+    end
+    str=`git log -1 --format='%ci' -- #{filepath}`
+    if str.nil? or str.empty?
+        return Time.now
+    else
+        return DateTime.parse( str )
+    end
+end
+
+
+ +

Of course I know it is really slow and absolutely not optimized. +But it works as expected. +Now the date you see at the bottom is exactly the date I modified the content of the page.

+ +

Thanks to Eric Sunshine to provide me some hints at cleaning my code.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ + + + +
+ +
+ Created: 09/02/2010 + Modified: 09/03/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-09-02-base64-and-sha1-on-iPhone/code/iphone_base64_sha1.c b/output/n3blog/en/blog/2010-09-02-base64-and-sha1-on-iPhone/code/iphone_base64_sha1.c new file mode 100644 index 000000000..26c5a31f0 --- /dev/null +++ b/output/n3blog/en/blog/2010-09-02-base64-and-sha1-on-iPhone/code/iphone_base64_sha1.c @@ -0,0 +1,43 @@ + + +- (unsigned char *)sha1:(NSString *)baseString result:(unsigned char *)result { + char *c_baseString=(char *)[baseString UTF8String]; + CC_SHA1(c_baseString, strlen(c_baseString), result); + return result; +} + +- (NSString *)base64:(unsigned char *)result { + NSString *password=[[NSString alloc] init]; + static const unsigned char cb64[65]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + for (int i=0; i>2], + cb64[((result[i] & 0x03) << 4) + | ((result[i + 1] & 0xF0) >> 4)], + cb64[((result[i + 1] & 0x0F) << 2) + | ((result[i + 2] & 0xC0) >> 6)], + cb64[result[i+2]&0x3F] + ]; + } + return password; +} + +- (NSString *)hexadecimalRepresentation:(unsigned char *)result { + NSString *password=[[NSString alloc] init]; + for (int i=0; i + + + + + + + + + + + + + + + + + + + + + + base64 and sha1 on iPhone + + + + +
+ + +
+

+ base64 and sha1 on iPhone +

+ +
+ +
+ + + + + +
+
+
+

Lets be straight: +here are two functions to add to your code to have base64 and hexadecimal version of the sha1 hash of an NSString.

+ +

To use it, simply copy the code in your class and use as this:

+ +
+#import <CommonCrypto/CommonDigest.h>
+...
+NSString *b64_hash = [self b64_sha1:@"some NSString to be sha1'ed"];
+...
+NSString *hex_hash = [self hex_sha1:@"some NSString to be sha1'ed"];
+
+ +

The base64 algorithm must be programmed by hand on iPhone!

+ +
+
+
+- (unsigned char *)sha1:(NSString *)baseString result:(unsigned char *)result {
+    char *c_baseString=(char *)[baseString UTF8String];
+    CC_SHA1(c_baseString, strlen(c_baseString), result);
+    return result;
+}
+
+- (NSString *)base64:(unsigned char *)result {
+    NSString *password=[[NSString alloc] init];
+    static const unsigned char cb64[65]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+    for (int i=0; i<CC_SHA1_DIGEST_LENGTH; i+=3) {
+        password=[password stringByAppendingFormat:@"%c%c%c%c",
+            cb64[(result[i] &0xFC)>>2],
+            cb64[((result[i] & 0x03) << 4)
+                | ((result[i + 1] & 0xF0) >> 4)],
+            cb64[((result[i + 1] & 0x0F) << 2)
+                | ((result[i + 2] & 0xC0) >> 6)],
+            cb64[result[i+2]&0x3F]
+                ];            
+    }
+    return password;
+}
+
+- (NSString *)hexadecimalRepresentation:(unsigned char *)result {
+    NSString *password=[[NSString alloc] init];
+    for (int i=0; i<CC_SHA1_DIGEST_LENGTH; i++) {
+        password=[password stringByAppendingFormat:@"%02x", result[i]];
+    }
+    return password;
+}
+
+- (NSString *)b64_sha1:(NSString *)inputString {
+    unsigned char result[CC_SHA1_DIGEST_LENGTH+1];
+    [self sha1:inputString result:result];
+    return [self base64:result];
+}
+
+- (NSString *)hex_sha1:(NSString *)inputString {
+    unsigned char result[CC_SHA1_DIGEST_LENGTH+1];
+    [self sha1:inputString result:result];
+    return [self hexadecimalRepresentation:result];
+}
+
+
+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ + + + +
+ +
+ Created: 09/02/2010 + Modified: 09/04/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-10-06-New-Blog-Design-Constraints/index.html b/output/n3blog/en/blog/2010-10-06-New-Blog-Design-Constraints/index.html new file mode 100644 index 000000000..13feaa745 --- /dev/null +++ b/output/n3blog/en/blog/2010-10-06-New-Blog-Design-Constraints/index.html @@ -0,0 +1,207 @@ + + + + + + + + + + + + + + + + + + + + + + + New Blog Design Constraints + + + + +
+ + +
+

+ New Blog Design Constraints +

+ +
+ +
+ + + + + +
+
+
+

I changed the design of my blog. +Now it should be far cleaner. +I believe I use no CSS3 feature and far less javascript. +Of course before my website was perfectly browsable without javascript. +Unfortunately some CSS3 feature are not mature enough on some browser. +For more details you can read my older blog entry. +But the major problem came from, font-shadow and gradients. +Then my new design obey to the following rules:

+ +
    +
  • no CSS element begining by ‘-moz’ or ‘-webkit’, etc…,
  • +
  • no text shadow,
  • +
  • clean (I mean delete) most javascript.
  • +
+ +

I hope the new design please you.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ + + + +
+ +
+ Created: 10/06/2010 + Modified: 10/07/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/index.html b/output/n3blog/en/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/index.html new file mode 100644 index 000000000..33cbca2aa --- /dev/null +++ b/output/n3blog/en/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/index.html @@ -0,0 +1,235 @@ + + + + + + + + + + + + + + + + + + + + + + + Secure eMail on Mac in few steps + + + + +
+ + +
+

+ Secure eMail on Mac in few steps +

+ +
+ +
+ + + + + +
+
+
+

Title image

+ + +
+ + +

tl;dr: on Mac

+ +
    +
  • Get a certificate signed by a CA: click here for a free one,
  • +
  • open the file,
  • +
  • delete securely the file,
  • +
  • use Mail instead of online gmail.
  • +
  • ???
  • +
  • Profit
  • +
+ + +
+ + +

I’ve (re)discovered how to become S/MIME compliant. +I am now suprised how easy it was. +Some years ago it was far more difficult. +Now I’m able to sign and encrypt my emails.

+ +

Why is it important?

+ +

Signing: it tell the other with an aboslute certitude the writer of the mail is you or at least used your computer.

+ +

Encrypt: because sometimes you need to be 100% sure a conversation remains private.

+ +

How to proceed?

+ +
    +
  • Get a certificate signed by a CA: click here to get a free one,
  • +
  • open the file,
  • +
  • empty your trash, put the file in the trash, secure empty trash,
  • +
  • use Mail instead of online gmail. +Now you should see these icons: +no name
  • +
+ +

n.b.: if you use gmail, you and work not alway with a Mac, you should consider to try the gmail S/MIME firefox addon.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Created: 10/10/2010 + Modified: 10/10/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-10-14-Fun-with-wav/code/wavsum.c b/output/n3blog/en/blog/2010-10-14-Fun-with-wav/code/wavsum.c new file mode 100644 index 000000000..214ab6ee5 --- /dev/null +++ b/output/n3blog/en/blog/2010-10-14-Fun-with-wav/code/wavsum.c @@ -0,0 +1,59 @@ + +#include +#include +#include + +struct wavfile +{ + char id[4]; // should always contain "RIFF" + int totallength; // total file length minus 8 + char wavefmt[8]; // should be "WAVEfmt " + int format; // 16 for PCM format + short pcm; // 1 for PCM format + short channels; // channels + int frequency; // sampling frequency + int bytes_per_second; + short bytes_by_capture; + short bits_per_sample; + char data[4]; // should always contain "data" + int bytes_in_data; +}; + +int main(int argc, char *argv[]) { + char *filename=argv[1]; + FILE *wav = fopen(filename,"rb"); + struct wavfile header; + + if ( wav == NULL ) { + fprintf(stderr,"Can't open input file %s", filename); + exit(1); + } + + + // read header + if ( fread(&header,sizeof(header),1,wav) < 1 ) + { + fprintf(stderr,"Can't read file header\n"); + exit(1); + } + if ( header.id[0] != 'R' + || header.id[1] != 'I' + || header.id[2] != 'F' + || header.id[3] != 'F' ) { + fprintf(stderr,"ERROR: Not wav format\n"); + exit(1); + } + + fprintf(stderr,"wav format\n"); + + // read data + long sum=0; + short value=0; + while( fread(&value,sizeof(value),1,wav) ) { + // fprintf(stderr,"%d\n", value); + if (value<0) { value=-value; } + sum += value; + } + printf("%ld\n",sum); + exit(0); +} diff --git a/output/n3blog/en/blog/2010-10-14-Fun-with-wav/code/wavsum.py b/output/n3blog/en/blog/2010-10-14-Fun-with-wav/code/wavsum.py new file mode 100644 index 000000000..ddeedd473 --- /dev/null +++ b/output/n3blog/en/blog/2010-10-14-Fun-with-wav/code/wavsum.py @@ -0,0 +1,28 @@ + +#!/usr/bin/env python +from struct import calcsize, unpack +from sys import argv, exit + +def word_iter(f): + while True: + _bytes = f.read(2) + + if len(_bytes) != 2: + raise StopIteration + + yield unpack("=h", _bytes)[0] + +try: + with open(argv[1], "rb") as f: + wav = "=4ci8cihhiihh4ci" + wav_size = calcsize(wav) + metadata = unpack(wav, f.read(wav_size)) + + if "".join(metadata[:4]) != "RIFF": + print "error: not wav file." + exit(1) + + print sum(abs(word) for word in word_iter(f)) +except IOError: + print "error: can't open input file '%s'." % argv[1] + exit(1) diff --git a/output/n3blog/en/blog/2010-10-14-Fun-with-wav/code/wavsum.rb b/output/n3blog/en/blog/2010-10-14-Fun-with-wav/code/wavsum.rb new file mode 100644 index 000000000..fc63899b5 --- /dev/null +++ b/output/n3blog/en/blog/2010-10-14-Fun-with-wav/code/wavsum.rb @@ -0,0 +1,12 @@ + +data = ARGF.read + keys = %w[id totallength wavefmt format + pcm channels frequency bytes_per_second + bytes_by_capture bits_per_sample + data bytes_in_data sum + ] + values = data.unpack 'Z4 i Z8 i s s i i s s Z4 i s*' + sum = values.drop(12).map(&:abs).inject(:+) + keys.zip(values.take(12) << sum) {|k, v| + puts "#{k.ljust 17}: #{v}" + } diff --git a/output/n3blog/en/blog/2010-10-14-Fun-with-wav/code/wavsum2.c b/output/n3blog/en/blog/2010-10-14-Fun-with-wav/code/wavsum2.c new file mode 100644 index 000000000..0f9850943 --- /dev/null +++ b/output/n3blog/en/blog/2010-10-14-Fun-with-wav/code/wavsum2.c @@ -0,0 +1,107 @@ + +#include +#include +#include // for memcmp +#include // for int16_t and int32_t + +struct wavfile +{ + char id[4]; // should always contain "RIFF" + int32_t totallength; // total file length minus 8 + char wavefmt[8]; // should be "WAVEfmt " + int32_t format; // 16 for PCM format + int16_t pcm; // 1 for PCM format + int16_t channels; // channels + int32_t frequency; // sampling frequency + int32_t bytes_per_second; + int16_t bytes_by_capture; + int16_t bits_per_sample; + char data[4]; // should always contain "data" + int32_t bytes_in_data; +} __attribute__((__packed__)); + +int is_big_endian(void) { + union { + uint32_t i; + char c[4]; + } bint = {0x01000000}; + return bint.c[0]==1; +} + +int main(int argc, char *argv[]) { + char *filename=argv[1]; + FILE *wav = fopen(filename,"rb"); + struct wavfile header; + + if ( wav == NULL ) { + fprintf(stderr,"Can't open input file %s\n", filename); + exit(1); + } + + + // read header + if ( fread(&header,sizeof(header),1,wav) < 1 ) { + fprintf(stderr,"Can't read input file header %s\n", filename); + exit(1); + } + + // if wav file isn't the same endianness than the current environment + // we quit + if ( is_big_endian() ) { + if ( memcmp( header.id,"RIFX", 4) != 0 ) { + fprintf(stderr,"ERROR: %s is not a big endian wav file\n", filename); + exit(1); + } + } else { + if ( memcmp( header.id,"RIFF", 4) != 0 ) { + fprintf(stderr,"ERROR: %s is not a little endian wav file\n", filename); + exit(1); + } + } + + if ( memcmp( header.wavefmt, "WAVEfmt ", 8) != 0 + || memcmp( header.data, "data", 4) != 0 + ) { + fprintf(stderr,"ERROR: Not wav format\n"); + exit(1); + } + if (header.format != 16) { + fprintf(stderr,"\nERROR: not 16 bit wav format."); + exit(1); + } + fprintf(stderr,"format: %d bits", header.format); + if (header.format == 16) { + fprintf(stderr,", PCM"); + } else { + fprintf(stderr,", not PCM (%d)", header.format); + } + if (header.pcm == 1) { + fprintf(stderr, " uncompressed" ); + } else { + fprintf(stderr, " compressed" ); + } + fprintf(stderr,", channel %d", header.pcm); + fprintf(stderr,", freq %d", header.frequency ); + fprintf(stderr,", %d bytes per sec", header.bytes_per_second ); + fprintf(stderr,", %d bytes by capture", header.bytes_by_capture ); + fprintf(stderr,", %d bits per sample", header.bytes_by_capture ); + fprintf(stderr,"\n" ); + + if ( memcmp( header.data, "data", 4) != 0 ) { + fprintf(stderr,"ERROR: Prrroblem?\n"); + exit(1); + } + fprintf(stderr,"wav format\n"); + + // read data + long long sum=0; + int16_t value; + int i=0; + fprintf(stderr,"---\n", value); + while( fread(&value,sizeof(value),1,wav) ) { + if (value<0) { value=-value; } + sum += value; + } + printf("%lld\n",sum); + exit(0); +} diff --git a/output/n3blog/en/blog/2010-10-14-Fun-with-wav/index.html b/output/n3blog/en/blog/2010-10-14-Fun-with-wav/index.html new file mode 100644 index 000000000..018ca3c1b --- /dev/null +++ b/output/n3blog/en/blog/2010-10-14-Fun-with-wav/index.html @@ -0,0 +1,521 @@ + + + + + + + + + + + + + + + + + + + + + Fun with wav + + + + +
+ + +
+

+ Fun with wav +

+ +
+ +
+ + + + + +
+
+
+ +
+ + +

tl;dr: Played to process a wav file. C was easier and cleaner than Ruby.

+ +

edit: I wanted this program to work only on one specific machine (a x86 on a 32 bit Ubuntu). Therefore I didn’t had any portability consideration. This is only a hack.

+ + +
+ + +

I had to compute the sum of the absolute values of data of a .wav file. +For efficiency (and fun) reasons, I had chosen C language.

+ +

I didn’t programmed in C for a long time. +From my memory it was a pain to read and write to files. +But in the end I was really impressed by the code I get. +It was really clean. +This is even more impressive knowing I used mostly low level functions.

+ +

A wav file has an header containing many metadata. +This header was optimized to take as few space as possible. +The header is then a block of packed bytes.

+ +
    +
  • The 4th first bytes must contains RIFF in ASCII,
  • +
  • the following 4th Bytes is an 32 bits integer giving the size of the file minus 8, etc…
  • +
+ +

Surprisingly, I believe that reading this kind of file is easier in C than in most higher level language. +Proof: I only have to search on the web the complete header format and write it in a struct.

+ +
+struct wavfile
+{
+    char        id[4];          // should always contain "RIFF"
+    int     totallength;    // total file length minus 8
+    char        wavefmt[8];     // should be "WAVEfmt "
+    int     format;         // 16 for PCM format
+    short     pcm;            // 1 for PCM format
+    short     channels;       // channels
+    int     frequency;      // sampling frequency
+    int     bytes_per_second;
+    short     bytes_by_capture;
+    short     bits_per_sample;
+    char        data[4];        // should always contain "data"
+    int     bytes_in_data;
+};
+
+ +

To read this kind of data in Ruby, I certainly had to write a block of code for each element in the struct. +But in C I simply written:

+ +
+fread(&header,sizeof(header),1,wav)
+
+ +

Only one step to fill my data structure. Magic!

+ +

Then, get an int value coded on two Bytes is also not a natural operation for high level language. +In C, to read a sequence of 2 Bytes numbers I only had to write:

+ +
+short value=0;
+while( fread(&value,sizeof(value),1,wav) ) {
+    // do something with value
+}
+
+ +

Finally I ended with the following code. Remark I know the wav format (16 bit / 48000Hz):

+ +
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+struct wavfile
+{
+    char        id[4];          // should always contain "RIFF"
+    int     totallength;    // total file length minus 8
+    char        wavefmt[8];     // should be "WAVEfmt "
+    int     format;         // 16 for PCM format
+    short     pcm;            // 1 for PCM format
+    short     channels;       // channels
+    int     frequency;      // sampling frequency
+    int     bytes_per_second;
+    short     bytes_by_capture;
+    short     bits_per_sample;
+    char        data[4];        // should always contain "data"
+    int     bytes_in_data;
+};
+
+int main(int argc, char *argv[]) {
+    char *filename=argv[1];
+    FILE *wav = fopen(filename,"rb");
+    struct wavfile header;
+
+    if ( wav == NULL ) {
+        fprintf(stderr,"Can't open input file %s", filename);
+        exit(1);
+    }
+
+
+    // read header
+    if ( fread(&header,sizeof(header),1,wav) < 1 )
+    {
+        fprintf(stderr,"Can't read file header\n");
+        exit(1);
+    }
+    if (    header.id[0] != 'R'
+         || header.id[1] != 'I' 
+         || header.id[2] != 'F' 
+         || header.id[3] != 'F' ) { 
+        fprintf(stderr,"ERROR: Not wav format\n"); 
+        exit(1); 
+    }
+
+    fprintf(stderr,"wav format\n");
+
+    // read data
+    long sum=0;
+    short value=0;
+    while( fread(&value,sizeof(value),1,wav) ) {
+        // fprintf(stderr,"%d\n", value);
+        if (value<0) { value=-value; }
+        sum += value;
+    }
+    printf("%ld\n",sum);
+    exit(0);
+}
+
+
+ +

Of course it is only a hack. +But we can see how easy and clean it should be to improve. +As I say often: the right tool for your need instead of the same tool for all your needs. +Because here C is clearly far superior than Ruby to handle this simple tasks.

+ +

I am curious to know if somebody know a nice way to do this with Ruby or Python.

+ +

edit: for compatibility reasons (64bit machines) used int16_t instead of short and int instead of int.

+ + +
+ + +

Edit (2): after most consideration about portability I made an hopefully more portable version. +But I must confess this task was a bit tedious. +The code remain as readable as before. +But I had to use some compiler specific declaration to force the structure to be packed:

+ +
+__attribute__((__packed__))
+
+ +

Therefore this implementation should for big and little endian architecture. +However, it must be compiled with gcc. +The new code make more tests but still don’t use mmap. +Here it is:

+ + +
+ + +
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> // for memcmp
+#include <stdint.h> // for int16_t and int32_t
+
+struct wavfile
+{
+    char    id[4];          // should always contain "RIFF"
+    int32_t totallength;    // total file length minus 8
+    char    wavefmt[8];     // should be "WAVEfmt "
+    int32_t format;         // 16 for PCM format
+    int16_t pcm;            // 1 for PCM format
+    int16_t channels;       // channels
+    int32_t frequency;      // sampling frequency
+    int32_t bytes_per_second;
+    int16_t bytes_by_capture;
+    int16_t bits_per_sample;
+    char    data[4];        // should always contain "data"
+    int32_t bytes_in_data;
+} __attribute__((__packed__));
+
+int is_big_endian(void) {
+    union {
+        uint32_t i;
+        char c[4];
+    } bint = {0x01000000};
+    return bint.c[0]==1;
+}
+
+int main(int argc, char *argv[]) {
+    char *filename=argv[1];
+    FILE *wav = fopen(filename,"rb");
+    struct wavfile header;
+
+    if ( wav == NULL ) {
+        fprintf(stderr,"Can't open input file %s\n", filename);
+        exit(1);
+    }
+
+
+    // read header
+    if ( fread(&header,sizeof(header),1,wav) < 1 ) {
+        fprintf(stderr,"Can't read input file header %s\n", filename);
+        exit(1);
+    }
+
+    // if wav file isn't the same endianness than the current environment
+    // we quit
+    if ( is_big_endian() ) {
+        if (   memcmp( header.id,"RIFX", 4) != 0 ) {
+            fprintf(stderr,"ERROR: %s is not a big endian wav file\n", filename); 
+            exit(1);
+        }
+    } else {
+        if (   memcmp( header.id,"RIFF", 4) != 0 ) {
+            fprintf(stderr,"ERROR: %s is not a little endian wav file\n", filename); 
+            exit(1);
+        }
+    }
+
+    if (   memcmp( header.wavefmt, "WAVEfmt ", 8) != 0 
+        || memcmp( header.data, "data", 4) != 0 
+            ) {
+        fprintf(stderr,"ERROR: Not wav format\n"); 
+        exit(1); 
+    }
+    if (header.format != 16) {
+        fprintf(stderr,"\nERROR: not 16 bit wav format.");
+        exit(1);
+    }
+    fprintf(stderr,"format: %d bits", header.format);
+    if (header.format == 16) {
+        fprintf(stderr,", PCM");
+    } else {
+        fprintf(stderr,", not PCM (%d)", header.format);
+    }
+    if (header.pcm == 1) {
+        fprintf(stderr, " uncompressed" );
+    } else {
+        fprintf(stderr, " compressed" );
+    }
+    fprintf(stderr,", channel %d", header.pcm);
+    fprintf(stderr,", freq %d", header.frequency );
+    fprintf(stderr,", %d bytes per sec", header.bytes_per_second );
+    fprintf(stderr,", %d bytes by capture", header.bytes_by_capture );
+    fprintf(stderr,", %d bits per sample", header.bytes_by_capture );
+    fprintf(stderr,"\n" );
+
+    if ( memcmp( header.data, "data", 4) != 0 ) { 
+        fprintf(stderr,"ERROR: Prrroblem?\n"); 
+        exit(1); 
+    }
+    fprintf(stderr,"wav format\n");
+
+    // read data
+    long long sum=0;
+    int16_t value;
+    int i=0;
+    fprintf(stderr,"---\n", value);
+    while( fread(&value,sizeof(value),1,wav) ) {
+        if (value<0) { value=-value; }
+        sum += value;
+    }
+    printf("%lld\n",sum);
+    exit(0);
+}
+
+
+ +

Edit(3): +On reddit +Bogdanp +proposed a Python version:

+ +
+
+#!/usr/bin/env python
+from struct import calcsize, unpack
+from sys import argv, exit
+
+def word_iter(f):
+    while True:
+        _bytes = f.read(2)
+
+    if len(_bytes) != 2:
+        raise StopIteration
+
+    yield unpack("=h", _bytes)[0]
+
+try:
+    with open(argv[1], "rb") as f:
+        wav = "=4ci8cihhiihh4ci"
+        wav_size = calcsize(wav)
+        metadata = unpack(wav, f.read(wav_size))
+
+        if "".join(metadata[:4]) != "RIFF":
+            print "error: not wav file."
+            exit(1)
+
+        print sum(abs(word) for word in word_iter(f))
+except IOError:
+    print "error: can't open input file '%s'." % argv[1]
+    exit(1)
+
+
+ +

and luikore +proposed an impressive Ruby version:

+ +
+
+data = ARGF.read
+ keys = %w[id totallength wavefmt format
+       pcm channels frequency bytes_per_second
+         bytes_by_capture bits_per_sample
+           data bytes_in_data sum
+ ]
+ values = data.unpack 'Z4 i Z8 i s s i i s s Z4 i s*'
+ sum = values.drop(12).map(&:abs).inject(:+)
+ keys.zip(values.take(12) << sum) {|k, v|
+       puts "#{k.ljust 17}: #{v}"
+ }
+
+
+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ + + + +
+ +
+ Created: 10/14/2010 + Modified: 10/26/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2010-10-26-LaTeX-like-macro-and-markdown/code/macros.rb b/output/n3blog/en/blog/2010-10-26-LaTeX-like-macro-and-markdown/code/macros.rb new file mode 100644 index 000000000..ad7816cdd --- /dev/null +++ b/output/n3blog/en/blog/2010-10-26-LaTeX-like-macro-and-markdown/code/macros.rb @@ -0,0 +1,44 @@ + +# usage: +# --- +# ... +# macros: +# test: "passed test" +# --- +# ... +# Here is a %test. +# +class Macros < Nanoc3::Filter + identifier :falacy + attr_accessor :macro + def initialize(arg) + super + @macro={} + @macro[:tlal] = %{tlàl : } + @macro[:tldr] = %{tl;dr: } + if @item.nil? + if not arg.nil? + @macro.merge!( arg ) + end + else + if not @item[:macros].nil? + @macro.merge!( @item[:macros] ) + end + end + end + def macro_value_for(macro_name) + if macro_name.nil? or macro_name=="" or @macro[macro_name.intern].nil? + return %{%#{macro_name}} + end + return @macro[macro_name.intern] + end + def run(content, params={}) + content.gsub(/%(\w*)/) do |m| + if m != '%' + macro_value_for($1) + else + m + end + end + end +end diff --git a/output/n3blog/en/blog/2010-10-26-LaTeX-like-macro-and-markdown/index.html b/output/n3blog/en/blog/2010-10-26-LaTeX-like-macro-and-markdown/index.html new file mode 100644 index 000000000..52dece6ad --- /dev/null +++ b/output/n3blog/en/blog/2010-10-26-LaTeX-like-macro-and-markdown/index.html @@ -0,0 +1,265 @@ + + + + + + + + + + + + + + + + + + + + + LaTeX like macro for markdown + + + + +
+ + +
+

+ LaTeX like macro for markdown +

+ +
+ +
+ + + + + +
+
+
+ +
+ + +

tl;dr: I made a simple macro system for my blog. Now I juste have to write %latex and it show as LaTeX.

+ + +
+ + +

I added a macro system for my blog system. +When we are used to LaTeX this lack can be hard to handle. +Particularly when using mathematical notations. +In the header of my files I simply write:

+ +
+macros:
+  test: "This is a macro test"
+  latex: '<span style="text-transform: uppercase">L<sup style="vertical-align: 0.15em; margin-left: -0.36em; margin-right: -0.15em; font-size: .85em">a</sup>T<sub style="vertical-align: -0.5ex; margin-left: -0.1667em; margin-right: -0.125em; font-size: 1em">e</sub>X</span>'
+
+ +

In the body it will replace every occurrence of:

+ +
    +
  • %test by This is a macro test,
  • +
  • and %latex by LaTeX.
  • +
+ +

The source code is really simple. +For nanoc user, simply put this file in your lib directory.

+ +
+
+# usage:
+# ---
+# ...
+# macros:
+#   test: "passed test"
+# ---
+# ...
+# Here is a This is a macro test.
+#
+class Macros < Nanoc3::Filter
+    identifier :falacy
+    attr_accessor :macro
+    def initialize(arg)
+        super
+        @macro={}
+        @macro[:tlal] = %{<span class="sc"><abbr title="Trop long à lire">tlàl</abbr> : </span>}
+        @macro[:tldr] = %{<span class="sc"><abbr title="Too long; don't read">tl;dr</abbr>: </span>}
+        if @item.nil?
+            if not arg.nil?
+                @macro.merge!( arg )
+            end
+        else
+            if not @item[:macros].nil?
+                @macro.merge!( @item[:macros] )
+            end
+        end
+    end
+    def macro_value_for(macro_name)
+        if macro_name.nil? or macro_name=="" or @macro[macro_name.intern].nil?
+            return %{%#{macro_name}} 
+        end
+        return @macro[macro_name.intern]
+    end
+    def run(content, params={})
+        content.gsub(/%(\w*)/) do |m| 
+            if m != '%'
+                macro_value_for($1)
+            else
+                m
+            end
+        end
+    end
+end
+
+
+ +

Macros could be very useful, read this article for example.

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Created: 10/26/2010 + Modified: 04/07/2011 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2011-01-03-Happy-New-Year/index.html b/output/n3blog/en/blog/2011-01-03-Happy-New-Year/index.html new file mode 100644 index 000000000..f58aa6863 --- /dev/null +++ b/output/n3blog/en/blog/2011-01-03-Happy-New-Year/index.html @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + + Happy New Year + + + + +
+ + +
+

+ Happy New Year +

+ +
+ +
+ + + + + +
+
+
+

Happy New Year!

+ +

I was busy during the last months. +But I will revive a bit this blog.

+ +

I made a project to write book in markdown syntax and generating HTML and high quality PDF. I am not finished with this.

+ +

I had written an efficient & simplistic MVC javascript framework.

+ +

Best wishes for 2011!

+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Created: 01/01/2011 + Modified: 01/06/2011 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/2011-01-03-Why-I-sadly-won-t-use-coffeescript/index.html b/output/n3blog/en/blog/2011-01-03-Why-I-sadly-won-t-use-coffeescript/index.html new file mode 100644 index 000000000..31ba8f9c5 --- /dev/null +++ b/output/n3blog/en/blog/2011-01-03-Why-I-sadly-won-t-use-coffeescript/index.html @@ -0,0 +1,303 @@ + + + + + + + + + + + + + + + + + + + + + Why I won't use CoffeeScript (sadly) + + + + +
+ + +
+

+ Why I won't use CoffeeScript (sadly) +

+ +
+ +
+ + + + + +
+
+
+

Title image

+ + +
+ + +

tl;dr: I would have loved to program client side using a Ruby-like syntax. But in the end, CoffeScript raised more disavantages than advantages.

+ + +
+ + +

Recently I read this entry on HackerNews. +The most upvoted comment praised (within other) CoffeeScript. +Recently I used a lot of javascript. After trying +Sproutcore, +Cappuccino, looking at +backbone.js & +javascriptMVC, +I’ve finally decided to make my own minimal javascript MVC framework.1

+ +

I had to fight the horrible syntax of javascript. It was like experiencing a back-in-time travel:

+ +
    +
  • Verbose Java-like syntax,
  • +
  • Strange and insanely Verbose Object Oriented Programming,
  • +
  • No easy way to refer to current instance of a class (this doesn’t work really well),
  • +
  • etc…
  • +
+ +

It was so annoying at a point, I had thinked about creating my own CoffeeScript.

+ +

I’d finished a first draft of my MVC javascript framework. +Just after I learned about the existence of CoffeeScript, I immediately created a new git branch to try it.

+ +

Here is my experience:

+ +
    +
  1. I had to install node.js and use npm just to use CoffeeScript. It wasn’t a big deal but it wasn’t as straightfoward as I expected either.
  2. +
  3. Existing javascript file are not coffee compatible. + I had to translate them by hand. + There were no script to help me in this process. + Thanks to vim, it wasn’t too hard to translate 90% of the javascript using some regexp. + The --watch option of coffee was also really helpful to help in the translation. + But I had to write my own shell script in order to follow an entire directory tree.
  4. +
  5. An unexpected event. I made some meta-programming in javascript using eval. But in order to work, the string in the eval must be written in pure javascript not in coffee. It was like writing in two different languages. Really not so good.
  6. +
+ +

Conclusion

+ +

Advantages:

+ +
    +
  • Readability: clearly it resolved most of javascript syntax problems
  • +
  • Verbosity: I gained 14% line, 22% words, 14% characters
  • +
+ +

Disadvantages:

+ +
    +
  • Added another compilation step to see how my code behave on the website.
  • +
  • I had to launch some script to generate on change every of my javascript file
  • +
  • I have to learn another Ruby-like language,
  • +
  • meta-programming become a poor experience,
  • +
  • I must convince people working with me to: +
      +
    • install node.js, npm and CoffeeScript,
    • +
    • remember to launch a script at each code session,
    • +
    • learn and use another ruby-like language
    • +
    +
  • +
+ +

The last two point were definitively really problematic for me.

+ +

But even if I’ll have to work alone, I certainly won’t use CoffeeScript either. +CoffeeScript is a third party and any of their update can break my code. +I experienced this kind of situation many times, and it is very annoying. +Far more than coding with a bad syntax.

+ +

Digression

+ +

I am sad. +I wanted so much to program on Web Client with a Ruby-like syntax. +But in the end I think it is not for me. +I have to use the horrible javascript syntax for now. +At least I would have preferred a complete ruby2js script for example2. +But I believe it would be a really hard task just to simulate the access of current class for example.

+ +

Typically @x translate into this.x. But the following code will not do what I should expect. Call the foo function of the current class.

+ +
+-> 
+class MyClass
+  foo: ->
+    alert('ok')
+
+  bar: ->
+    $('#content').load( '/content.html', ( -> @foo(x) ) )
+    # That won't call MyClass.foo
+
+ +

The only way to handle this is to make the following code:

+ +
+-> 
+class MyClass
+  foo: ->
+    alert('ok')
+
+  bar: ->
+    self=this
+    $('#content').load( '/content.html', ( -> self.foo(x) ) )
+
+ +

Knowing this, @ notation lose most of its interrest for me.

+
+
    +
  1. +

    I know it may not be the best nor productive decision, but I’d like to start from scratch and understand how things works under the hood.

    +
  2. +
  3. +

    I know there is rb2js, but it doesn’t handle the problem I talk about.

    +
  4. +
+
+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Created: 01/03/2011 + Modified: 03/14/2011 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/feed/feed.xml b/output/n3blog/en/blog/feed/feed.xml new file mode 100644 index 000000000..ba331f01a --- /dev/null +++ b/output/n3blog/en/blog/feed/feed.xml @@ -0,0 +1,1084 @@ + + + http://yannesposito.com/ + Yogsototh's last blogs entries + 2011-01-03T08:37:26Z + + + + Yann Esposito + http://yannesposito.com + + + tag:yannesposito.com,2011-01-03:/n3blog/en/blog/2011-01-03-Why-I-sadly-won-t-use-coffeescript/ + Why I won't use CoffeeScript (sadly) + 2011-01-03T08:37:26Z + 2011-01-03T08:37:26Z + + Yann Esposito + yannesposito.com + + + <p><img alt="Title image" src="/n3blog/img/blog/2011-01-03-Why-I-sadly-won-t-use-coffeescript/main.png" /></p> + + +<div class="intro"> + + +<p><span class="sc"><abbr title="Too long; don't read">tl;dr</abbr>: </span> I would have loved to program client side using a Ruby-like syntax. But in the end, CoffeScript raised more disavantages than advantages.</p> + + +</div> + + +<p>Recently I read <a href="http://news.ycombinator.com/item?id=2053956">this entry</a> on HackerNews. +The most upvoted comment praised (within other) <a href="http://coffeescript.org">CoffeeScript</a>. +Recently I used <em>a lot</em> of javascript. After trying +<a href="http://sproutcore.com">Sproutcore</a>, +<a href="http://cappuccino.org">Cappuccino</a>, looking at +<a href="documentcloud.github.com/backbone/">backbone.js</a> </p></p> + + + tag:yannesposito.com,2011-01-01:/n3blog/en/blog/2011-01-03-Happy-New-Year/ + Happy New Year + 2011-01-01T06:55:54Z + 2011-01-01T06:55:54Z + + Yann Esposito + yannesposito.com + + + <p>Happy New Year!</p> + +<p>I was busy during the last months. +But I will revive a bit this blog.</p> + +<p>I made a project to write book in markdown syntax and generating HTML and high quality PDF. I am not finished with this.</p> + +<p>I had written an efficient <em>&amp;</em> simplistic MVC javascript framework.</p> + +<p>Best wishes for <em>2011</em>!</p> +</p> + + + tag:yannesposito.com,2010-10-26:/n3blog/en/blog/2010-10-26-LaTeX-like-macro-and-markdown/ + LaTeX like macro for markdown + 2010-10-26T12:30:58Z + 2010-10-26T12:30:58Z + + Yann Esposito + yannesposito.com + + + +<div class="intro"> + + +<p><span class="sc"><abbr title="Too long; don't read">tl;dr</abbr>: </span> I made a simple macro system for my blog. Now I juste have to write %<span />latex and it show as <span style="text-transform: uppercase">L<sup style="vertical-align: 0.15em; margin-left: -0.36em; margin-right: -0.15em; font-size: .85em">a</sup>T<sub style="vertical-align: -0.5ex; margin-left: -0.1667em; margin-right: -0.125em; font-size: 1em">e</sub>X</span>.</p> + + +</div> + + +<p>I added a macro system for my blog system. +When we are used to <span style="text-transform: uppercase">L<sup style="vertical-align: 0.15em; margin-left: -0.36em; margin-right: -0.15em; font-size: .85em">a</sup>T<sub style="vertical-align: -0.5ex; margin-left: -0.1667em; margin-right: -0.125em; font-size: 1em">e</sub></span></p></div> + + + tag:yannesposito.com,2010-10-14:/n3blog/en/blog/2010-10-14-Fun-with-wav/ + Fun with wav + 2010-10-14T09:04:58Z + 2010-10-14T09:04:58Z + + Yann Esposito + yannesposito.com + + + +<div class="intro"> + + +<p><span class="sc"><abbr title="Too long; don't read">tl;dr</abbr>: </span> Played to process a <code>wav</code> file. <code>C</code> was easier and cleaner than Ruby.</p> + +<p>edit: I wanted this program to work only on one specific machine (a x86 on a 32 bit Ubuntu). Therefore I didn&rsquo;t had any portability consideration. This is only a <em>hack</em>.</p> + + +</div> + + +<p>I had to compute the sum of the absolute values of data of a <code>.wav</code> file. +For efficiency (and fun) reasons, I had chosen <code>C</code> language.</p> + +<p>I didn&rsquo;t programmed in <code>C</code> for a long time. +From my memory it was a pain to read and write to files. +But in the end I was really impressed by the code I get. +It was really clean. +This is even more impressive knowi...</p> + + + tag:yannesposito.com,2010-10-10:/n3blog/en/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/ + Secure eMail on Mac in few steps + 2010-10-10T16:39:00Z + 2010-10-10T16:39:00Z + + Yann Esposito + yannesposito.com + + + <p><img alt="Title image" src="/n3blog/img/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/main.png" class="clean" /></p> + + +<div class="intro"> + + +<p><span class="sc"><abbr title="Too long; don't read">tl;dr</abbr>: </span> <em>on Mac</em></p> + +<ul> + <li>Get a certificate signed by a CA: <a href="http://www.instantssl.com/ssl-certificate-products/free-email-certificate.html">click here for a free one</a>,</li> + <li>open the file,</li> + <li>delete securely the file,</li> + <li>use Mail instead of online gmail.</li> + <li>???</li> + <li>Profit</li> +</ul> + + +</div> + + +<p>I&rsquo;ve (re)discovered how to become S/MIME compliant. +I am now suprised how easy it was. +Some years ago it was far more difficult. +Now I&rsquo;m able to sign and encrypt my emails.</p> + +<h2 id="why-is-it-important">...</h2></p> + + + tag:yannesposito.com,2010-10-06:/n3blog/en/blog/2010-10-06-New-Blog-Design-Constraints/ + New Blog Design Constraints + 2010-10-06T09:33:03Z + 2010-10-06T09:33:03Z + + Yann Esposito + yannesposito.com + + + <p>I changed the design of my blog. +Now it should be far cleaner. +I believe I use no CSS3 feature and far less javascript. +Of course before my website was perfectly browsable without javascript. +Unfortunately some CSS3 feature are not mature enough on some browser. +For more details you can read my older <a href="/n3blog/en/blog/2010-07-07-CSS-rendering-problems-by-navigator">blog entry</a>. +But the major problem came from, <code>font-shadow</code> and gradients. +Then my new design obey to the following rules:</p> + +<ul> + <li>no CSS element begining by &lsquo;-moz&rsquo; or &lsquo;-webkit&rsquo;, etc&hellip;,</li> + <li>no text shadow,</li> + <li>clean (I mean delete) most javascript.</li> +</ul> + +<p>I hope the new design please you.</p> +</p> + + + tag:yannesposito.com,2010-09-02:/n3blog/en/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes/ + Use git to calculate trusted mtimes + 2010-09-02T13:54:10Z + 2010-09-02T13:54:10Z + + Yann Esposito + yannesposito.com + + + <p>You can remark at the bottom of each page I provide a last modification date. +This label was first calculated using the <code>mtime</code> of the file on the file system. +But many times I modify this date just to force some recompilation. +Therefore the date wasn&rsquo;t a date of <em>real</em> modification.</p> + +<p>I use <a href="http://git-scm.org">git</a> to version my website. +And fortunately I can know the last date of <em>real</em> change of a file. +This is how I do this with <a href="http://nanoc.stoneship.org">nanoc</a>:</p> + +<div class="code"><div class="file"><a href="/n3blog/en/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes/code/gitmtime.rb"> &#x27A5; gitmtime.rb </a></div><div class="withfile"> +<pre class="twilight"> +<span class="Keyword">def</span> </pre></div></div> + + + tag:yannesposito.com,2010-09-01:/n3blog/en/blog/2010-09-02-base64-and-sha1-on-iPhone/ + base64 and sha1 on iPhone + 2010-09-01T22:02:17Z + 2010-09-01T22:02:17Z + + Yann Esposito + yannesposito.com + + + <p>Lets be straight: +here are two functions to add to your code to have <code>base64</code> and <code>hexadecimal</code> version of the <code>sha1</code> hash of an NSString.</p> + +<p>To use it, simply copy the code in your class and use as this:</p> + +<pre class="twilight"> +<span class="CCCPreprocessorLine">#<span class="CCCPreprocessorDirective">import</span> <span class="String"><span class="String">&lt;</span>CommonCrypto/CommonDigest.h<span class="String">&gt;</span></span></span> +... +<span class="Support">NSString</span> *b64_hash = [<span class="Variable">self</span> <span class="SupportFunction">b64_sha1<span class="SupportFunction">:</span></span><span class="String"><span class="String">@&quot;</span>some NSString to be sha1'ed<span class="String">&quot;</span></span>]; +... +</pre> + + + tag:yannesposito.com,2010-08-31:/n3blog/en/blog/2010-08-31-send-mail-from-command-line-with-attached-file/ + send mail from command line with attached file + 2010-08-31T08:16:04Z + 2010-08-31T08:16:04Z + + Yann Esposito + yannesposito.com + + + <p>I had to send a mail using only command line. +I was surprised it isn&rsquo;t straightforward at all. +I didn&rsquo;t had <code>pine</code> nor <code>mutt</code> or anything like that. +Just <code>mail</code> and <code>mailx</code>.</p> + +<p>What Internet say (via google) is</p> + +<pre class="twilight"> +uuencode fic.jpg fic.jpg <span class="Keyword">|</span> mail -s <span class="String"><span class="String">'</span>Subject<span class="String">'</span></span> +</pre> + +<p>I tried it. +And it works almost each times. +But for my file, it didn&rsquo;t worked. +I compressed it to <code>.gz</code>, <code>.bz2</code> and <code>.zip</code>. +Using <code>.bz2</code> format it worked nicely, but not with other formats. +Instead of having an attached file I saw this in my email.</p> + +<pre> +begin 664 fic....</pre> + + + tag:yannesposito.com,2010-08-23:/n3blog/en/blog/2010-08-23-Now-heberged-on-heroku/ + Now hosted by heroku + 2010-08-23T13:05:13Z + 2010-08-23T13:05:13Z + + Yann Esposito + yannesposito.com + + + <h1 class="first" id="now-on-herokuhttpherokucom">Now on <a href="http://heroku.com">Heroku</a></h1> + +<p>I now changed my hosting to <a href="http://heroku.com">Heroku</a>. +I believe it will be far more reliable.</p> + +<p>But as you should know my website is completely static. +I use <a href="http://nanoc.stoneship.org/">nanoc</a> to generate it. +But here is the conf to make it work on heroku.</p> + +<p>The root of my files is <code>/output</code>. You only need to create a <code>config.ru</code><sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup> file:</p> + +<div class="code"><div class="file"><a href="/n3blog/en/blog/2010-08-23-Now-heberged-on-heroku/code/config.ru"> &#x27A5; config.ru </a></div><div class="withfile"> +<pre class="twilight"> +<span class="Keyword">require</span> </pre></div></div> + + + tag:yannesposito.com,2010-08-11:/n3blog/en/blog/2010-07-09-Indecidabilities/ + Undecidabilities (part 1) + 2010-08-11T08:04:31Z + 2010-08-11T08:04:31Z + + Yann Esposito + yannesposito.com + + + +<div class="intro"> + + +<p><span class="sc"><abbr title="Too long; don't read">tl;dr</abbr>: </span> I pretend to create a world to give examples of different meanings behind the word <em>undecidability</em>:</p> + +<ul> + <li>Undecidability due to measure errors, </li> + <li>Big errors resulting from small initial measure error,</li> + <li>Fractal undecidability&nbsp;;</li> + <li>Logic Undecidability.</li> +</ul> + + +</div> + + + +</div> + +<div class="corps"> + + +<h1 class="first" id="the-undecidabilities">The Undecidabilities</h1> + + +<div class="intro"> + + +<p>If a demiurge made our world, he certainly had a great sense of humor. +After this read, you should be convinced. +I&rsquo;ll pretend to be him. +I&rsquo;ll create a simplified world. +A world that obey to simple mathematical rules. +And I&rsquo;ll ...</p></div> + + + tag:yannesposito.com,2010-07-31:/n3blog/en/blog/2010-07-31-New-style-after-holidays/ + New style after holidays + 2010-07-31T21:59:10Z + 2010-07-31T21:59:10Z + + Yann Esposito + yannesposito.com + + + <p>Before my holidays many visitors tell me my website was too long to scroll. +This is why I completely changed my website design. +Now all should scroll smoothly on all platforms. +I was inspired by Readability and iBooks<small>&copy;</small> (the iPhone<small>&copy;</small> application).</p> + +<p>Tell me what you think of this new design.</p> +</p> + + + tag:yannesposito.com,2010-07-07:/n3blog/en/blog/2010-07-07-CSS-rendering-problems-by-navigator/ + Do not use CSS gradient with Chrome + 2010-07-07T13:43:43Z + 2010-07-07T13:43:43Z + + Yann Esposito + yannesposito.com + + + <p>Some <a href="http://reddit.com">Reddit</a> users reported my website was really long to load and to scroll. +They thinks it was because of the &lsquo;1px shadow&rsquo; I apply on all the text. +I was a bit surprised, because I make some test into a really <em>slow</em> virtual machine. And all have always worked fine. In fact, what slow down so much are by order of importance:</p> + +<ol> + <li>Radial gradient on Chrome (not in Safari on Mac)</li> + <li>Box shadows on Firefox and Chrome</li> +</ol> + +<h2 id="gradient">Gradient</h2> + +<p>On Safari on Mac there is absolutely no rendering time problem. But when I use Chrome under Linux it is almost unusable.</p> + +<p>Safari and Chrome use webkit, when you access my website with javascript enabled, an additionnal browser specific CSS is loaded....</p> + + + tag:yannesposito.com,2010-07-05:/n3blog/en/blog/2010-07-05-Cappuccino-and-Web-applications/ + Cappuccino vs jQuery + 2010-07-05T11:49:04Z + 2010-07-05T11:49:04Z + + Yann Esposito + yannesposito.com + + + +<div class="intro"> + + +<p><abbr class="sc" title="Too long; don't read">tl;dr</abbr>:</p> + +<ul> + <li>Tried to make <a href="http://yannesposito.com/Softwares/YPassword.html">YPassword</a> in jQuery and with Cappuccino.</li> + <li>Cappuccino nice in desktop browser but 1.4MB, not compatible with iPhone.</li> + <li>jQuery not as nice as the Cappuccino version but 106KB. iPhone compatible.</li> + <li>I&rsquo;ll give a try to Dashcode 3.</li> +</ul> + + +</div> + + +<hr /> + +<div class="intro"> + + +<p>Before start, I must say I know Cappuccino and jQuery are no more comparable than Cocoa and the C++ standard library. One is oriented for user interface while the other is and helper for low level programming. +Nonetheless I used these two to make the same web application. This is why I compare the expe...</p></div></hr> + + + tag:yannesposito.com,2010-06-19:/n3blog/en/blog/2010-06-19-jQuery-popup-the-easy-way/ + jQuery popup the easy way + 2010-06-18T22:44:50Z + 2010-06-18T22:44:50Z + + Yann Esposito + yannesposito.com + + + <p>Some source code on this blog can be downloaded. +Most of time, the code is larger than the <code>div</code> bloc. +This is why I use a method to show this code in a large jQuery popup. </p> + +<p>You can try clicking the following code&nbsp;; remark that the content is cutted a bit after <code>z-index</code>:</p> + +<div class="code"><div class="file"><a href="/n3blog/en/blog/2010-06-19-jQuery-popup-the-easy-way/code/essai.js"> &#x27A5; essai.js </a></div><div class="withfile"> +<pre class="twilight"> +<span class="Comment"><span class="Comment">//</span> --- code popup ---</span> +<span class="Storage">function</span> <span class="Entity">openPopup</span>() { + <span class="Keyword">$</span>(<span class="Variable">this</span>).clone(<span class="Constant">false</span>).appendTo(</pre></div></div> + + + tag:yannesposito.com,2010-06-17:/n3blog/en/blog/2010-06-17-hide-yourself-to-analytics/ + Hide Yourself to your Analytics + 2010-06-17T14:37:22Z + 2010-06-17T14:37:22Z + + Yann Esposito + yannesposito.com + + + <p>This is a way not to count your own visits to your blog. +First you should look on how <a href="/n3blog/en/blog/2010-06-17-track-events-with-google-analytics">I handle analytics</a>. All analytics are handled in one javascript file, this make things really convenient.</p> + +<p>Then you need to know my method use the <code>jquery-cookie</code>.</p> + +<p>I check if the key <code>admin</code> is not set in the cookie before adding the visit.</p> + +<pre class="twilight"> + <span class="Storage">var</span> admin <span class="Keyword">=</span> <span class="Keyword">$</span>.<span class="SupportConstant">cookie</span>(<span class="String"><span class="String">'</span>admin<span class="String">'</span></span>); + <span class="Keyword">if</span> (<span class="Keyword">!</span> admin) { + ...</pre> + + + tag:yannesposito.com,2010-06-17:/n3blog/en/blog/2010-06-17-track-events-with-google-analytics/ + Track Events with Google Analytics + 2010-06-17T12:41:36Z + 2010-06-17T12:41:36Z + + Yann Esposito + yannesposito.com + + + <p>Here is how to track all clicks on your website using google analytics asynchronously.</p> + +<p>First in your <span class="sc">html</span> you need to use <a href="http://jquery.com">jQuery</a> and a javscript file I named <code>yga.js</code>:</p> + +<pre class="twilight"> +<span class="EmbeddedSource"> <span class="EmbeddedSource">&lt;</span><span class="MetaTagInline">script</span> <span class="MetaTagInline">type</span>=<span class="String"><span class="String">&quot;</span>text/javascript<span class="String">&quot;</span></span> <span class="MetaTagInline">src</span>=<span class="String"><span class="String">&quot;</span>jquery.js<span class="String">&quot;</span></span><span class="EmbeddedSource">&gt;</span><span class="EmbeddedSource">&lt;/</span><span class="MetaTagInline">scr...</span></span></pre> + + + tag:yannesposito.com,2010-06-15:/n3blog/en/blog/2010-06-15-Get-my-blog-engine/ + Get my blog engine + 2010-06-15T08:56:32Z + 2010-06-15T08:56:32Z + + Yann Esposito + yannesposito.com + + + <p>I published a <em>light</em> version of my blog engine based on <a href="http://nanoc.stoneship.org">nanoc</a> yesterday night. By <em>light</em>, I mean a lighter, more portable CSS (without round border). +You can get it on <a href="http://github.com/yogsototh/nanoc3_blog">github.com</a>.</p> + +<p>What this system provide?</p> + +<ul> + <li>All <a href="http://nanoc.stoneship.org">nanoc</a> advantages,</li> + <li>Easy multi-language handling,</li> + <li>Syntax Coloration for most languages,</li> + <li><a href="http://intensedebate.org">intenseDebate</a> comments integration (asynchronous)&nbsp;;</li> + <li>Portable with and without javascript, XHTML Strict 1.0 / CSS3,</li> + <li>Write in markdown format (no HTML editing needed),</li> + <li>Typographic ameliorations (no &lsquo;:&rsquo; ...</li></ul> + + + tag:yannesposito.com,2010-06-14:/n3blog/en/blog/2010-06-14-multi-language-choices/ + multi language choices + 2010-06-14T14:14:57Z + 2010-06-14T14:14:57Z + + Yann Esposito + yannesposito.com + + + <p>I translate most of my blog entries in French and English. +Most people advice me to have one file per language. Generally it ends with:</p> + +<pre class="twilight"> +Bonjour, + +voici un exemple de texte en français. +[image](url) +</pre> + +<pre class="twilight"> +Hello, + +here is an example of english text. +[image](url) +</pre> + +<p>This way of handling translations force you to write completely an article in one language, copy it, and translate it.</p> + +<p>However, most of time, there are common parts like images, source code, etc&hellip; +When I want to correct some mistake on these parts, I have to make twice the work. With sometimes adding another mistake in only one language.</p> + +<p>This is why I preferred to handle it differently. +I use <em>tags</em> on a single file. +Finally my files...</p> + + + tag:yannesposito.com,2010-05-24:/n3blog/en/blog/2010-05-24-Trees--Pragmatism-and-Formalism/ + Trees; Pragmatism and Formalism + 2010-05-24T18:05:14Z + 2010-05-24T18:05:14Z + + Yann Esposito + yannesposito.com + + + +<div class="intro"> + + +<p><abbr title="Too Long; Don't Read"><span class="sc">tl;dr</span></abbr>: </p> + +<ul> + <li>I tried to program a simple filter</li> + <li>Was blocked 2 days</li> + <li>Then stopped working like an engineer monkey</li> + <li>Used a pen and a sheet of paper</li> + <li>Made some math.</li> + <li>Crushed the problem in 10 minutes</li> + <li>Conclusion: The pragmatism shouldn&rsquo;t mean &ldquo;never use theory&rdquo;.</li> +</ul> + + +</div> + + +<h2 id="abstract-longer-than-abbr-titletoo-long-dont-readsctldrscabbr">Abstract (longer than <abbr title="Too Long; Don't Read"><span class="sc">tl;dr</span></abbr>)</h2> + +<p>For my job, I needed to resolve a problem. It first seems not too hard. +Then I started working directly on my program. +I entered in the <em>infernal</em>: ...</p> + + + tag:yannesposito.com,2010-05-19:/n3blog/en/blog/2010-05-19-How-to-cut-HTML-and-repair-it/ + How to repair a cutted XML? + 2010-05-19T20:20:34Z + 2010-05-19T20:20:34Z + + Yann Esposito + yannesposito.com + + + <p>For my main page, you can see, a list of my latest blog entry. And you have the first part of each article. To accomplish that, I needed to include the begining of the entry and to cut it somewhere. But now, I had to repair this cutted HTML.</p> + +<p>Here is an example:</p> + +<pre class="twilight"> +<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">div</span> <span class="MetaTagAll">class</span>=<span class="String"><span class="String">&quot;</span>corps<span class="String">&quot;</span></span><span class="MetaTagAll">&gt;</span></span> + <span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">div</span> <span class="MetaTagAll">class</span>=<span class="String"><span class="String">&quot;</span>intro</span></span></pre> + + + tag:yannesposito.com,2010-05-17:/n3blog/en/blog/2010-05-17-at-least-this-blog-revive/ + I live again! + 2010-05-17T11:25:51Z + 2010-05-17T11:25:51Z + + Yann Esposito + yannesposito.com + + + <p>Hi all!</p> + +<blockquote cite="http://www.madore.org/~david/weblog/2010-05.html#d.2010-05-12.1752"> + <p>The more you wait to do something, the more difficult it is to start doing it.</p> +</blockquote> + +<p>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&rsquo;ve always said (until now), I&rsquo;ll do this later. What changed my mind is the haunt of this simple remark about how to be productive in programming. +&gt; Stop write <code>TODO</code> in your code and make it now!<br /> +&gt; You&rsquo;ll be surprised by the results.</p> + +<p>In short: +&gt; <strong>Just do it!</strong> ou <strong>Juste fait le</strong> comme auraient dit les nuls.</p> + +<p>Finally I&rsquo;ll certainly write blog post more often for a ...</p></p> + + + tag:yannesposito.com,2010-03-23:/n3blog/en/blog/2010-03-23-Encapsulate-git/ + Encapsulate git + 2010-03-23T20:37:36Z + 2010-03-23T20:37:36Z + + Yann Esposito + yannesposito.com + + + <div class="intro"> +Here is a solution to maintain divergent branches in git. Because it is easy to merge by mistake. I give a script that encapsulate git in order to forbid some merge and warn you some merge should be dangerous. +</div> + +<h2 id="how-to-protect-against-your-own-dumb">how to protect against your own dumb</h2> + +<p>I work on a project in which some of my git branches should remain divergent. And divergences should grow.</p> + +<p>I also use some branch to contain what is common between projects.</p> + +<p>Say I have some branches:</p> + +<p>master: common to all branches +dev: branch devoted to unstable development +client: branch with features for all client but not general enough for master +clientA: project adapted for client A +clientB: project adapted for client B</p> + +<p>Her...</p> + + + tag:yannesposito.com,2010-03-22:/n3blog/en/blog/2010-03-22-Git-Tips/ + Git Tips + 2010-03-22T08:42:27Z + 2010-03-22T08:42:27Z + + Yann Esposito + yannesposito.com + + + <h2 class="first" id="clone-from-github-behind-an-evil-firewall">clone from github behind an evil firewall</h2> + +<p>Standard:</p> + +<div><pre class="twilight"> +git clone git@github.com:yogsototh/project.git +</pre></div> + +<p>Using HTTPS port:</p> + +<div><pre class="twilight"> +git clone git+ssh://git@github.com:443/yogsototh/project.git +</pre></div> + +<h2 id="clone-all-branches">clone all branches</h2> + +<p><code>git clone</code> can only fetch the master branch.</p> + +<p>If you don&rsquo;t have much branches, you can simply use clone your project and then use the following command:</p> + +<div><pre class="twilight"> +git branch --track local_branch remote_branch +</pre></div> + +<p>for example:</p> +<div><pre class="twilight"> +$ git clone git@github:yogsototh/example.git +$ git branch +master * +$ git ...</pre></div> + + + tag:yannesposito.com,2010-02-23:/n3blog/en/blog/2010-02-23-When-regexp-is-not-the-best-solution/ + When regexp is not the best solution + 2010-02-23T08:09:52Z + 2010-02-23T08:09:52Z + + Yann Esposito + yannesposito.com + + + <p>Regular expression are really useful. Unfortunately, they are not always the best way of doing things. +Particularly when transformations you want to make are easy.</p> + +<p>I wanted to know how to get file extension from filename the fastest way possible. There is 3 natural way of doing this:</p> + +<div><pre class="twilight"> +<span class="Comment"><span class="Comment">#</span> regexp</span> +str.<span class="Entity">match</span>(<span class="StringRegexp"><span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="StringRegexp">[</span>^.<span class="StringRegexp">]</span></span>*$</span><span class="StringRegexp"><span class="StringRegexp">/</span></span>); +ext<span class="Keyword">=</span><span class="Variable"><span class="Variable">...</span></span></pre></div> + + + tag:yannesposito.com,2010-02-18:/n3blog/en/blog/2010-02-18-split-a-file-by-keyword/ + split a file by keyword + 2010-02-18T13:29:14Z + 2010-02-18T13:29:14Z + + Yann Esposito + yannesposito.com + + + <p>Strangely enough, I didn&rsquo;t find any built-in tool to split a file by keyword. I made one myself in <code>awk</code>. 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 <code>UTC</code>.</p> + +<div><pre class="twilight"> +<span class="Comment"><span class="Comment">#</span>!/usr/bin/env awk</span> +<span class="Entity">BEGIN</span>{i=0;} +<span class="StringRegexp"><span class="StringRegexp">/</span>UTC<span class="StringRegexp">/</span></span> { + i+=1; + FIC=<span class="SupportFunction">sprintf</span>(<span class="String"><span class="String">&quot;</span>fic.%03d<span class="String">&quot;</span></span>,i); +} +{<span class="SupportFunction">print</span> <span class="Variable"></span></pre></div> + + + tag:yannesposito.com,2010-02-16:/n3blog/en/blog/2010-02-16-All-but-something-regexp--2-/ + Pragmatic Regular Expression Exclude (2) + 2010-02-16T08:33:21Z + 2010-02-16T08:33:21Z + + Yann Esposito + yannesposito.com + + + <p>In my <a href="previouspost">previous post</a> 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 &lsquo;a&rsquo; and &lsquo;b&rsquo;, for example, you want to match:</p> + +<pre class="twilight"> +a.....<span class="Constant"><strong>a......b</strong></span>..b..a....<span class="Constant"><strong>a....b</strong></span>... +</pre> + +<p>Here are two common errors and a solution:</p> + +<pre class="twilight"> +/a.*b/ +<span class="Constant"><strong>a.....a......b..b..a....a....b</strong></span>... +</pre> + +<p>The first error is to use the <em>evil</em> <code>.*</code>. Because you will match from the first to the last.</p> + +<pre class="twilight"> +/a.*?b/ +<span class="Constant"><strong>...</strong></span></pre> + + + tag:yannesposito.com,2010-02-15:/n3blog/en/blog/2010-02-15-All-but-something-regexp/ + Pragmatic Regular Expression Exclude + 2010-02-15T09:16:12Z + 2010-02-15T09:16:12Z + + Yann Esposito + yannesposito.com + + + <p>Sometimes you cannot simply write:</p> + +<div><pre class="twilight"> +<span class="Keyword">if</span> str.<span class="Entity">match</span>(regexp) <span class="Keyword">and</span> + <span class="Keyword">not</span> str.<span class="Entity">match</span>(other_regexp) + do_something +</pre></div> + +<p>and you have to make this behaviour with only one regular expression. The problem is the complementary of regular languages is not regular. Then, for some expression it is absolutely not impossible.</p> + +<p>But sometimes with some simple regular expression it should be possible<sup><a href="#note1">&dagger;</a></sup>. Say you want to match everything containing the some word say <code>bull</code> but don&rsquo;t want to match <code>bullshit</code>. Here is a nice way to do that:</p>...</p> + + + tag:yannesposito.com,2010-01-12:/n3blog/en/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/ + antialias font in Firefox under Ubuntu + 2010-01-12T14:36:40Z + 2010-01-12T14:36:40Z + + Yann Esposito + yannesposito.com + + + <p>How to stop using bad Microsoft© font under Ubuntu Linux in order to user nice anti aliased font under Firefox.</p> + +<p>Just modify the <code>/etc/fonts/local.conf</code> with the following code: </p> + +<div> +<div class="code"><div class="file"><a href="/n3blog/en/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/code/local.conf"> &#x27A5; local.conf </a></div><div class="withfile"> +<pre class="twilight"> + +<span class="DoctypeXmlProcessing"><span class="DoctypeXmlProcessing">&lt;?</span><span class="DoctypeXmlProcessing">xml</span><span class="DoctypeXmlProcessing"> version</span>=<span class="DoctypeXmlProcessing"><span class="DoctypeXmlProcessing">&quot;</span>1.0<span class="DoctypeXmlProcessing">&quot;</span></span><span class="DoctypeXmlProcessing">?&gt;</span></span> +</pre></div></div></div> + + + tag:yannesposito.com,2010-01-04:/n3blog/en/blog/2010-01-04-Change-default-shell-on-Mac-OS-X/ + Change default shell on Mac OS X + 2010-01-04T10:31:47Z + 2010-01-04T10:31:47Z + + Yann Esposito + yannesposito.com + + + <p>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: </p> + +<div><pre class="twilight"> +<span class="Keyword">&gt;</span> chsh +</pre></div> +</div> + + + tag:yannesposito.com,2009-12-14:/n3blog/en/blog/2009-12-14-Git-vs--Bzr/ + Git vs. Bzr + 2009-12-14T08:46:36Z + 2009-12-14T08:46:36Z + + Yann Esposito + yannesposito.com + + + +<div class="intro"> + + +<p>Why even if I believe <code>git</code> has many bad point I believe it is the best DCVS around to work with. This is why I first tell why I prefer <a href="http://bazaar-vcs.org">Bazaar</a> over <a href="http://git-scm.org">Git</a>. Secondly I&rsquo;ll talk about the only advantage of git against Bazaar which lead me to prefer it.</p> + + +</div> + + +<h2 id="the-dcvs-discovery">The DCVS discovery</h2> + +<p>Before beginning this article, you should know I come from <em>subversion</em>. I find subversion to be a really good CVS. But I was converted to the decentralized ones.</p> + +<p>There is two way of perceive version control system. Either you think in term of branches (see the really good article on </p> + + + tag:yannesposito.com,2009-12-06:/n3blog/en/blog/2009-12-06-iphone-call-filter/ + iphone call filter + 2009-12-06T09:35:34Z + 2009-12-06T09:35:34Z + + Yann Esposito + yannesposito.com + + + <p>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.</p> + +<p>I&rsquo;m a λ iPhone&rsquo;s user. The only way to filter your call and to manage blacklist is to <em>jailbreak</em> your iPhone. And I don&rsquo;t want to do that. Then, if like me you find it unacceptable, just write a line to Apple: <a href="http://www.apple.com/feedback/iphone.html">http://www.apple.com/feedback/iphone.html</a></p> +</p> + + + tag:yannesposito.com,2009-11-12:/n3blog/en/blog/2009-11-12-Git-for-n00b/Git-pour-quoi-faire/ + Git for n00b + 2009-11-12T09:39:54Z + 2009-11-12T09:39:54Z + + Yann Esposito + yannesposito.com + + + <h1 class="first" id="gitgit-for-what"><a href="http://git-scm.org" title="Git">Git</a> for what?</h1> + + +<div class="intro"> + + +<p>If you just want to use <a href="http://git-scm.org" title="Git">Git</a> <strong>immediately</strong>, just read dark part. You read this part later to understand correctly foundations of version systems and not doing strange things.</p> + + +</div> + + +<p><a href="http://git-scm.org" title="Git">Git</a> is a <abbr title="Decentralized Concurent Versions System">DCVS</abbr>, which means a Decentralized Concurrent Versions System. Let&rsquo;s analyze each part of this long term:</p> + +<h3 id="versions-system">Versions System</h3> + +<p>Firstly, versions system manage files. +When somebody work with files without a versions system, the following happens frequently:</p> +...</p> + + + tag:yannesposito.com,2009-11-12:/n3blog/en/blog/2009-11-12-Git-for-n00b/conf-et-install/ + Git for n00b + 2009-11-12T09:39:54Z + 2009-11-12T09:39:54Z + + Yann Esposito + yannesposito.com + + + <h1 class="first" id="before-usage-configuration">Before usage, configuration</h1> + +<h2 id="install">install</h2> + +<p>Under Linux Ubuntu or Debian:</p> + +<div><pre class="twilight">$ sudo apt-get install git +</pre></div> + +<p>Under Mac OS X:</p> + +<ul> + <li>install <a href="http://macports.org/install.php">MacPorts</a></li> + <li>install <a href="http://git-scm.org" title="Git">Git</a></li> +</ul> + +<div><pre class="twilight"> +$ sudo port selfupdate + +$ sudo port install git-core +</pre></div> + +<h2 id="global-configuration">Global configuration</h2> + +<p>Save the following file as your <code>~/.gitconfig</code>.</p> + +<div><div class="code"><div class="file"><a href="/n3blog/en/blog/2009-11-12-Git-for-n00b/conf-et-install/code/gitconfig"> &#x27A5; gitconfig </a></div><div class="withfile"> +</div></div></div> + + + tag:yannesposito.com,2009-11-12:/n3blog/en/blog/2009-11-12-Git-for-n00b/ + Git for n00b + 2009-11-12T09:39:54Z + 2009-11-12T09:39:54Z + + Yann Esposito + yannesposito.com + + + +<div class="intro"> + + +<p>A detailed tutorial of <a href="http://git-scm.org">Git</a> for people knowing very few about versions systems. You&rsquo;ll understand utility of such program and how we use modern version control system. I try to stay as pragmatic as possible.</p> + + +</div> + + + +</div> + +<div class="corps"> + + +<h1 class="first" id="begin-with-conclusion">Begin with conclusion</h1> + +<p>Here is the list of sufficient and necessary command to use <a href="http://git-scm.org" title="Git">Git</a>. There is very few. It is normal not to understand immediately but it is to gives you an idea. Even if this article is long, 95% of <a href="http://git-scm.org" title="Git">Git</a> usage is in these 7 commands:</p> + +<p>Get a project from the web: </p> + +<div><pre class="twilight"> +git clone ssh...</pre></div> + + + tag:yannesposito.com,2009-11-12:/n3blog/en/blog/2009-11-12-Git-for-n00b/c-est-parti-pour-l-aventure/ + Git for n00b + 2009-11-12T09:39:54Z + 2009-11-12T09:39:54Z + + Yann Esposito + yannesposito.com + + + <h1 class="first" id="here-we-go">Here we go!</h1> + +<p>Here is one from many way to use <a href="http://git-scm.org" title="Git">Git</a>. This method is sufficient to work on a project. Not there is many other <em>workflows</em>.</p> + +<h2 id="basic-usage">Basic usage</h2> + +<p>Work with <a href="http://git-scm.org" title="Git">Git</a> immediately:</p> + +<ul> + <li>Get modification done by others <span class="black"><code>git pull</code></span>,</li> + <li>See details of these modifications <span class="black"><code>git log</code></span>,</li> + <li>Many times: + <ul> + <li><em>Make an atomic modification</em></li> + <li>Verify details of this modification: <span class="black"><code>git status</code></span> and <span class="black"><code>git diff</code></span>,</li> + <li>Add ...</li></ul></li></ul> + + + tag:yannesposito.com,2009-11-12:/n3blog/en/blog/2009-11-12-Git-for-n00b/commandes-avancees/ + Git for n00b + 2009-11-12T09:39:54Z + 2009-11-12T09:39:54Z + + Yann Esposito + yannesposito.com + + + <h1 class="first" id="command-list">Command List</h1> + +<h2 id="command-for-each-functionality">Command for each functionality</h2> + +<p>In the first part, we saw the list of resolved problem by <a href="http://git-scm.org" title="Git">Git</a>. To resume <a href="http://git-scm.org" title="Git">Git</a> should do:</p> + +<ul> + <li>get others modifications,</li> + <li>send modifications to others,</li> + <li>get back in time,</li> + <li>list differences between each version,</li> + <li>name some versions in order to refer easily to them,</li> + <li>write an historic of modifications,</li> + <li>know who did what and when,</li> + <li>manage conflicts,</li> + <li>easily manage branches.</li> +</ul> + +<h3 id="get-others-modifications">get others modifications</h3> + +<div><pre class="twilight"> +$ g...</pre></div> + + + tag:yannesposito.com,2009-11-12:/n3blog/en/blog/2009-11-12-Git-for-n00b/comprendre/ + Git for n00b + 2009-11-12T09:39:54Z + 2009-11-12T09:39:54Z + + Yann Esposito + yannesposito.com + + + <h1 class="first" id="why-git-is-cool">Why Git is cool?</h1> + +<p>Because with <a href="http://git-scm.org" title="Git">Git</a> you can work on many part of some project totally independently. This is the true efficiency of decentralisation.</p> + +<p>Each branch use the same directory. Then you can easily change your branch. You can also change branch when some files are modified. You can then dispatch your work on many different branches and merge them on one master branch at will.</p> + +<p>Using the <code>git rebase</code> you can decide which modifications should be forget or merged into only one modification.</p> + +<p>What does it mean for real usage? You can focus on coding. For example, you can code, a fix for bug b01 and for bug b02 and code a feature f03. Once finished you can creat...</p> + + + tag:yannesposito.com,2009-10-30:/n3blog/en/blog/2009-10-30-How-to-handle-evil-IE/ + How to handle evil IE + 2009-10-30T20:34:46Z + 2009-10-30T20:34:46Z + + Yann Esposito + yannesposito.com + + + <p>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.</p> + +<div><pre class="twilight"> +<span class="Keyword">$</span>(<span class="Support">document</span>).ready( <span class="Storage">function</span>() { + <span class="Keyword">if</span> (<span class="Keyword">$</span>.browser[<span class="String"><span class="String">&quot;</span>msie<span class="String">&quot;</span></span>]) { + <span class="Comment"><span class="Comment">//</span> include the ie.js file</span> + <span class="Keyword">$</span>(<span class="String"><span class="String">'</span>head<span class="String">'</span></span>).append(<span class="String"><span class="String">'</span>&lt;script type=&quot;text/javascr...</span></pre></div> + + + tag:yannesposito.com,2009-10-28:/n3blog/en/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/ + custom website synchronisation with mobileme (2) + 2009-10-28T09:03:30Z + 2009-10-28T09:03:30Z + + Yann Esposito + yannesposito.com + + + <p>I already talked about how <a href="/n3blog/en/blog/10_Synchronize_Custom_WebSite_with_mobileMe">I synchronized my website with mobileme</a>. I ameliorated this script in order to make it incremental.</p> + +<p>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.</p> + +<p>Even with this script I also have some problem. Mostly due to &lsquo;webdav&rsquo; issues. For example, renaming a folder work really badly (on Linux at least). I use webdavfs. For example:</p> + +<div><pre class="twilight"> +mv folder folder2 +</pre></div> + +<p>It returns OK and I&rsquo;ve got: </p> + +<div><pre class="twilight"> +$ ls +folder folder2 +</pre></div> + +<p>Booh&hellip;.</p> + +<p>In ord...</p> + + diff --git a/output/n3blog/en/blog/index.html b/output/n3blog/en/blog/index.html new file mode 100644 index 000000000..8b922d5a4 --- /dev/null +++ b/output/n3blog/en/blog/index.html @@ -0,0 +1,2151 @@ + + + + + + + + + + + + + + + + Blog + + + + +
+ +
+
+ + +
+ +
+
+
+ + Presentation drawing +
+

+ Blog +

+ +
+ +
+ + + + + +
+ +
+ + + +

+ + 3 + Jan + 2011 + + Why I won't use CoffeeScript (sadly) » +

+ +
+ + +

Title image

+ + +
+ + +

tl;dr: I would have loved to program client side using a Ruby-like syntax. But in the end, CoffeScript raised more disavantages than advantages.

+ + +
+ + +

Recently I read this entry on HackerNews. +The most upvoted comment praised (within other) CoffeeScript. +Recently I used a lot of javascript. After trying +Sproutcore, +Cappuccino, looking at +backbone.js

+ +
+
+

+ Read more » +

+
+ +
+ +

+ + 1 + Jan + 2011 + + Happy New Year » +

+ +
+ + +

Happy New Year!

+ +

I was busy during the last months. +But I will revive a bit this blog.

+ +

I made a project to write book in markdown syntax and generating HTML and high quality PDF. I am not finished with this.

+ +

I had written an efficient & simplistic MVC javascript framework.

+ +

Best wishes for 2011!

+

+ +
+
+

+ Read more » +

+
+ +
+ +

+ + 26 + Oct + 2010 + + LaTeX like macro for markdown » +

+ +
+ + + +
+ + +

tl;dr: I made a simple macro system for my blog. Now I juste have to write %latex and it show as LaTeX.

+ + +
+ + +

I added a macro system for my blog system. +When we are used to LaTe

+ +
+
+

+ Read more » +

+
+ +
+ +

+ + 14 + Oct + 2010 + + Fun with wav » +

+ +
+ + + +
+ + +

tl;dr: Played to process a wav file. C was easier and cleaner than Ruby.

+ +

edit: I wanted this program to work only on one specific machine (a x86 on a 32 bit Ubuntu). Therefore I didn’t had any portability consideration. This is only a hack.

+ + +
+ + +

I had to compute the sum of the absolute values of data of a .wav file. +For efficiency (and fun) reasons, I had chosen C language.

+ +

I didn’t programmed in C for a long time. +From my memory it was a pain to read and write to files. +But in the end I was really impressed by the code I get. +It was really clean. +This is even more impressive knowi...

+ +
+
+

+ Read more » +

+
+ +
+ +

+ + 10 + Oct + 2010 + + Secure eMail on Mac in few steps » +

+ +
+ + +

Title image

+ + +
+ + +

tl;dr: on Mac

+ +
    +
  • Get a certificate signed by a CA: click here for a free one,
  • +
  • open the file,
  • +
  • delete securely the file,
  • +
  • use Mail instead of online gmail.
  • +
  • ???
  • +
  • Profit
  • +
+ + +
+ + +

I’ve (re)discovered how to become S/MIME compliant. +I am now suprised how easy it was. +Some years ago it was far more difficult. +Now I’m able to sign and encrypt my emails.

+ +

...

+ +
+
+

+ Read more » +

+
+ +
+ + +
+
+

alternate reality

analyser

analytics

Apple

Asynchronous

awk

Bazaar

blacklist

blog

branch

branches

bzr

Cappuccino

Chrome

Cocoa

comments

CSS

David Lynch

DCVS

dcvs

design

disqus

diverged

drm

email

extension

file

filter

Firefox

Fonts

git

Google

hide

HTML

indecidability

intense debate

iPhone

iTunes

javascript

jQuery

Linux

local

Lost Highway

mac

Mac

mathematics

mobileme

movie

multi-language

nanoc

Objective-C

OS X

philosophy

programming

Programming

protection

regexp

regular expression

remote

ruby

S/MIME

Safari

science

screensaver

script

security

shell

ssh

statistics

svn

synchronisation

theory

tip

tree

Ubuntu

User

web

WebDav

webdesign

workflow

zsh

+
+
+ +

Archives

+ +

[2011]

[2010]

[2009]

[2008]

+ +

+Two words about the content +

+ + +
+ +

+Here you'll can find mostly technical articles. +Some are just reminder of technical tips. +But some are long and technically detailled articles. +

+
+

+ I do my best to traduce each page in french and in english. +It not always easy. English is not my natural language. +I make many errors, orthographic, grammatical, typographical… +

+

+ Thanks not to judge me based on these errors! And don't forget content is more important than presentation! +

+The first impression I'll let you if we meet in real life should be different from the one I let you based on my website. +

+I wish you to find something useful or interesting on this website. +

+ + + +
+
+ +
+ Modified: 04/07/2011 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/blog/mvc/index.html b/output/n3blog/en/blog/mvc/index.html new file mode 100644 index 000000000..5263ca7e3 --- /dev/null +++ b/output/n3blog/en/blog/mvc/index.html @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + MVC explained + + + + +
+ + +
+

+ MVC explained +

+ +
+ +
+ + + + + +
+
+
+

Why This article and for whom?

+ +

Many website explaining how MVC works. But I can’t found one who explain why.

+ +

I have difficulties to obey some principle don’t know why I should use it. And something better than the:

+ +
+

“Smarter people than you decided you have to do so”

+
+ +

This article is for people who like me want to understand the real motivation of using an MVC architecture and which advantage it gives you.

+ +

Let’s start making a project from scratch pretending we don’t know anything about the MVC architecture. Then let see how we’ll naturally derive to an MVC architecture.

+ +
+

→ Next

+
+ +
+ + + + + +
+
+

comments

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Created: 07/06/2009 + Modified: 05/09/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/error/401-authorization_required/index.html b/output/n3blog/en/error/401-authorization_required/index.html new file mode 100644 index 000000000..892e96719 --- /dev/null +++ b/output/n3blog/en/error/401-authorization_required/index.html @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + Page not found + + + + +
+ + + + Presentation drawing +
+

+ Page not found +

+ +
+ +
+ + + + + +
+ +
+
+

If you don’t have the password or believe it is an error you can mail me at .

+ + +
+ +
+ + +

Vous pouvez me contacter par mail: .

+ + + + +
+
+ +
+ Modified: 09/02/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/error/403-forbidden/index.html b/output/n3blog/en/error/403-forbidden/index.html new file mode 100644 index 000000000..d356f0bc5 --- /dev/null +++ b/output/n3blog/en/error/403-forbidden/index.html @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + Page not found + + + + +
+ + + + Presentation drawing +
+

+ Page not found +

+ +
+ +
+ + + + + +
+ +
+
+

Contact:

+ + + + +
+
+ +
+ Modified: 09/02/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/error/404-not_found/index.html b/output/n3blog/en/error/404-not_found/index.html new file mode 100644 index 000000000..85d8a82eb --- /dev/null +++ b/output/n3blog/en/error/404-not_found/index.html @@ -0,0 +1,83 @@ + + + + + + + + + + + + + Page not found + + +
+ + Presentation drawing + +

+ Page not found +

+ + +
+ +
+
+

The page you’re looking at doesn’t exists on the server. +If you have followed an internal link, you can tell me by mail and I’ll fix it as soon as possible.

+ + +
+ +
+ + +

La page que vous recherchez n’est pas présente sur le site. +Si vous avez suivi un lien vous pouvez me prévenir par mail et je réparerai ça dès que possible.

+ +
+
+ +
+ Modified: 10/05/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/error/408-request_timed_out/index.html b/output/n3blog/en/error/408-request_timed_out/index.html new file mode 100644 index 000000000..9735659a4 --- /dev/null +++ b/output/n3blog/en/error/408-request_timed_out/index.html @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + Page not found + + + + +
+ + + + Presentation drawing +
+

+ Page not found +

+ +
+ +
+ + + + + +
+ +
+
+

Contact:

+ + + + +
+
+ +
+ Modified: 09/02/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/error/500-internal_server_error/index.html b/output/n3blog/en/error/500-internal_server_error/index.html new file mode 100644 index 000000000..63e3cf22a --- /dev/null +++ b/output/n3blog/en/error/500-internal_server_error/index.html @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + Page not found + + + + +
+ + + + Presentation drawing +
+

+ Page not found +

+ +
+ +
+ + + + + +
+ +
+
+

Contact:

+ + + + +
+
+ +
+ Modified: 09/02/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/error/503-service_unavailable/index.html b/output/n3blog/en/error/503-service_unavailable/index.html new file mode 100644 index 000000000..b468f6322 --- /dev/null +++ b/output/n3blog/en/error/503-service_unavailable/index.html @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + Page not found + + + + +
+ + + + Presentation drawing +
+

+ Page not found +

+ +
+ +
+ + + + + +
+ +
+
+

Contact:

+ + + + +
+
+ +
+ Modified: 09/02/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/index.html b/output/n3blog/en/index.html new file mode 100644 index 000000000..5eb5f080b --- /dev/null +++ b/output/n3blog/en/index.html @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + Home + + + + +
+ + Presentation drawing +
+

+ + + Yann + Esposito + + +

+ +

+ + Yogsototh + +

+ +
+ +
+ + + + + +
+ +
+
+ + + +
+
+

+ + Blog + » + +

+

+ Computer, Philosophy & Life. +

+
+
+

+ + Softwares + » + +

+

+ Password Manager, + Screensavers & + Scientific Applications. +

+
+
+

+ Contact + » + +

+

+ Don't be shy, I'll be happy to talk to you. +

+

+
+ +
+ +
+
+ +
+ Modified: 01/05/2011 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+

+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/rss/index.html b/output/n3blog/en/rss/index.html new file mode 100644 index 000000000..bf08be4d9 --- /dev/null +++ b/output/n3blog/en/rss/index.html @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + What is this RSS thing? + + + + +
+ + + + Presentation drawing +
+

+ What is this RSS thing? +

+ +
+ +
+ + + + + +
+ +
+
+

When you click on this logo:

+ +

rss

+ +

You have the capability to subscribe to my RSS flux. But what it is all about?

+ +

You can visit what is rss or even better look this cool video: RSS explained.

+ + +
+ +
+ + +

My explanation

+ +

It is an easy way to aggregate all the update made on websites you like in a single place. You’ll never have to surf many website to see if there is news on a website.

+ +

choose an aggregator

+ +

To begin, you must choose an RSS client called aggregator. There is many online clients: website which will present the news in a fancy way.

+ +

Personally I use Netvibes. I tried a bunch, and it is by far the best - In My Humble Opinion.

+ +

Of course Google has a client named Google Reader. +It is great for content you never want to forgot some article. It is not really useful when you have to handle flux generating many news per day.

+ +

Subscribe to some website news

+ +

Once you have chosen your aggregator, you only have to subscribe to websites you like. Do do this, you only have to click on the RSS icon in the top bar of your navigator. Or generally a nice icon is shown into the page you’re reading.

+ +

Get the news

+ +

Now, you’ll only have to use your RSS client. And you’ll see all news on all subscribed websites. There is no more need to surf many websites. All news which interest you are in the same place.

+ + + + +
+
+ +
+ Modified: 05/28/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/softwares/index.html b/output/n3blog/en/softwares/index.html new file mode 100644 index 000000000..fca69a906 --- /dev/null +++ b/output/n3blog/en/softwares/index.html @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + Softwares + + + + +
+ +
+
+ + +
+ +
+
+
+ + Presentation drawing +
+

+ Softwares +

+ +
+ +
+ + + + + +
+ +
+
+
+

+ YPassword + » + +

+

+ YPassword is a password manager that make your web life more secure +

+
+ +
+

+ YAquaBubbles + » + +

+

+ Nice underwater floating bubbles +

+
+ +
+

+ YClock + » + +

+

+ Biohazard logo inspired clock +

+
+ +
+ + + + +
+
+ +
+ Modified: 10/05/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/softwares/yaquabubbles/index.html b/output/n3blog/en/softwares/yaquabubbles/index.html new file mode 100644 index 000000000..ff04b2074 --- /dev/null +++ b/output/n3blog/en/softwares/yaquabubbles/index.html @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + YAquaBubbles + + + + +
+ + + + Presentation drawing +
+

+ YAquaBubbles +

+ +

+ bubble in the ocean +

+ +
+ +
+ + + + + +
+ +
+
+

Screenshot

+ +

YAquaBubbles is a QuartzComposer Screensaver. +It was one of my first try but the result was nice.

+ +

YAquaBubbles.dmg

+ + + + + +
+
+ +
+ Modified: 10/06/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/softwares/yclock/index.html b/output/n3blog/en/softwares/yclock/index.html new file mode 100644 index 000000000..2756e91ac --- /dev/null +++ b/output/n3blog/en/softwares/yclock/index.html @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + YClock + + + + +
+ + + + Presentation drawing +
+

+ YClock +

+ +
+ +
+ + + + + +
+ +
+
+

Screenshot

+ +

YClock is a nice clock screensaver. +It has three themes: white, black and red. +It is based on a QuartzComposition and with some little Objective-C code to handle gently the frame per second.

+ +

YClock.dmg

+ + + + + +
+
+ +
+ Modified: 10/05/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/softwares/ypassword/index.html b/output/n3blog/en/softwares/ypassword/index.html new file mode 100644 index 000000000..6f6593b23 --- /dev/null +++ b/output/n3blog/en/softwares/ypassword/index.html @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + YPassword + + + + +
+ + + + Presentation drawing +
+

+ YPassword +

+ +
+ +
+ + + + + +
+ +
+
+

Easy, Secure and Portable way to manage your web passwords.

+ +

Remember only one strong password. And the rest follow. +See my blog entry for the details.

+ +

Here you can find:

+ + + +

I’ll soon release an iPhone application.

+ + + + +
+
+ +
+ Modified: 10/01/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/softwares/ypassword/iphoneweb/index.html b/output/n3blog/en/softwares/ypassword/iphoneweb/index.html new file mode 100644 index 000000000..7db5c011b --- /dev/null +++ b/output/n3blog/en/softwares/ypassword/iphoneweb/index.html @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + YPassword + + + + +
+ + + + Presentation drawing +
+

+ YPassword +

+ +

+ Web Interface for iPhone +

+ +
+ +
+ + + + + +
+ +
+
+
+ +
+ + + + +
+
+ +
+ Modified: 10/01/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/softwares/ypassword/web/index.html b/output/n3blog/en/softwares/ypassword/web/index.html new file mode 100644 index 000000000..17725b8dd --- /dev/null +++ b/output/n3blog/en/softwares/ypassword/web/index.html @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + YPassword + + + + +
+ + + + Presentation drawing +
+

+ YPassword +

+ +

+ Cappuccino Web Application +

+ +
+ +
+ + + + + +
+ +
+
+
+ +
+ + + + +
+
+ +
+ Modified: 10/01/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/en/validation/index.html b/output/n3blog/en/validation/index.html new file mode 100644 index 000000000..a9ca4b7b5 --- /dev/null +++ b/output/n3blog/en/validation/index.html @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + Validation + + + + +
+ + + + Presentation drawing +
+

+ Validation +

+ +
+ +
+ + + + + +
+ +
+
+

One word to explain why there is some validation errors.

+ +

I wanted to use box-shadows and border-radius.

+ +

Then here I prefered pragmatism against dogmatism.

+ +

Using these properties broke my validation +but work really well in the two most recent and main browsers +(Safari 4 and Firefox 3.5 at the time I’m writing these lines). +If you don’t use these browser the page is +correctly displayed but not with all the ‘eyecandy’ effects.

+ +

I believed in the benefits of CSS +validation, this is why there is alway the +CSS validation link on my pages. +And all CSS validate except +for properities beginning by -moz and -webkit.

+ + + + +
+
+ +
+ Modified: 04/29/2010 +
+
+ Entirely done with + Vim + and + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/feed/feed.xml b/output/n3blog/feed/feed.xml new file mode 100644 index 000000000..871359538 --- /dev/null +++ b/output/n3blog/feed/feed.xml @@ -0,0 +1,366 @@ + + + http://yannesposito.com/ + Yogsototh's last blogs entries + 2010-02-18T13:29:14Z + + + + Yann Esposito + http://yannesposito.com + + + tag:yannesposito.com,2010-02-18:/Scratch/en/blog/2010-02-18-split-a-file-by-keyword/ + split a file by keyword + 2010-02-18T13:29:14Z + 2010-02-18T13:29:14Z + + <p>Strangely enough, I didn&rsquo;t find any built-in tool to split a file by keyword. I made one myself in <code>awk</code>. 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 <code>UTC</code>.</p> + +<pre class="twilight"> +<span class="Comment"><span class="Comment">#</span>!/usr/bin/env awk</span> +<span class="Entity">BEGIN</span>{i=0;} +<span class="StringRegexp"><span class="StringRegexp">/</span>UTC<span class="StringRegexp">/</span></span> { + i+=1; + FIC=<span class="SupportFunction">sprintf</span>(<span class="String"><span class="String">&quot;</span>fic.%03d<span class="String">&quot;</span></span>,i); +} +{<span class="SupportFunction">print</span> <span class="Variable"><span class="Variable">$</span>0</span>&gt;&gt;FIC} +</pre> + +<p>In my real world example, I wanted one file per day, each line containing UTC being in the following format:</p> + +<pre class="twilight"> +Mon Dec 7 10:32:30 UTC 2009 +</pre> + +<p>I then finished with the following code:</p> + +<pre class="twilight"> +<span class="Comment"><span class="Comment">#</span>!/usr/bin/env awk</span> +<span class="Entity">BEGIN</span>{i=0;} +<span class="StringRegexp"><span class="StringRegexp">/</span>UTC<span class="StringRegexp">/</span></span> { + date=<span class="Variable"><span class="Variable">$</span>1</span><span class="Variable"><span class="Variable">$</span>2</span><span class="Variable"><span class="Variable">$</span>3</span>; + <span class="Keyword">if</span> ( date&nbsp;!= olddate ) { + olddate=date; + i+=1; + FIC=<span class="SupportFunction">sprintf</span>(<span class="String"><span class="String">&quot;</span>fic.%03d<span class="String">&quot;</span></span>,i); + } +} +{<span class="SupportFunction">print</span> <span class="Variable"><span class="Variable">$</span>0</span>&gt;&gt;FIC} +</pre> + + + + tag:yannesposito.com,2010-02-18:/Scratch/fr/blog/2010-02-18-split-a-file-by-keyword/ + split a file by keyword + 2010-02-18T13:29:14Z + 2010-02-18T13:29:14Z + + <p>Strangely enough, I didn&rsquo;t find any built-in tool to split a file by keyword. I made one myself in <code>awk</code>. 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 <code>UTC</code>.</p> + +<pre class="twilight"> +<span class="Comment"><span class="Comment">#</span>!/usr/bin/env awk</span> +<span class="Entity">BEGIN</span>{i=0;} +<span class="StringRegexp"><span class="StringRegexp">/</span>UTC<span class="StringRegexp">/</span></span> { + i+=1; + FIC=<span class="SupportFunction">sprintf</span>(<span class="String"><span class="String">&quot;</span>fic.%03d<span class="String">&quot;</span></span>,i); +} +{<span class="SupportFunction">print</span> <span class="Variable"><span class="Variable">$</span>0</span>&gt;&gt;FIC} +</pre> + +<p>In my real world example, I wanted one file per day, each line containing UTC being in the following format:</p> + +<pre class="twilight"> +Mon Dec 7 10:32:30 UTC 2009 +</pre> + +<p>I then finished with the following code:</p> + +<pre class="twilight"> +<span class="Comment"><span class="Comment">#</span>!/usr/bin/env awk</span> +<span class="Entity">BEGIN</span>{i=0;} +<span class="StringRegexp"><span class="StringRegexp">/</span>UTC<span class="StringRegexp">/</span></span> { + date=<span class="Variable"><span class="Variable">$</span>1</span><span class="Variable"><span class="Variable">$</span>2</span><span class="Variable"><span class="Variable">$</span>3</span>; + <span class="Keyword">if</span> ( date&nbsp;!= olddate ) { + olddate=date; + i+=1; + FIC=<span class="SupportFunction">sprintf</span>(<span class="String"><span class="String">&quot;</span>fic.%03d<span class="String">&quot;</span></span>,i); + } +} +{<span class="SupportFunction">print</span> <span class="Variable"><span class="Variable">$</span>0</span>&gt;&gt;FIC} +</pre> + + + + tag:yannesposito.com,2010-02-16:/Scratch/en/blog/2010-02-16-All-but-something-regexp--2-/ + All but something regexp (2) + 2010-02-16T08:33:21Z + 2010-02-16T08:33:21Z + + <p>In my <a href="previouspost">previous post</a> 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 &lsquo;a&rsquo; and &lsquo;b&rsquo;, for example, you want to match:</p> + +<pre class="twilight"> +a.....<span class="Constant"><strong>a......b</strong></span>..b..a....<span class="Constant"><strong>a....b</strong></span>... +</pre> + +<p>Here are two common errors and a solution:</p> + +<pre class="twilight"> +/a.*b/ +<span class="Constant"><strong>a.....a......b..b..a....a....b</strong></span>... +</pre> + +<pre class="twilight"> +/a.*?b/ +<span class="Constant"><strong>a.....a......b</strong></span>..b..<span class="Constant"><strong>a....a....b</strong></span>... +</pre> + +<pre class="twilight"> +/a[^ab]*b/ +a.....<span class="Constant"><strong>a......b</strong></span>..b..a....<span class="Constant"><strong>a....b</strong></span>... +</pre> + +<p>The first error is to use the <em>evil</em> <code>.*</code>. Because you will match from the first to the last. The next natural way, is to change the <em>greediness</em>. But it is not enough as you will match from the first <code>a</code> to the first <code>b</code>. Then a simple constatation is that our matching string shouldn&rsquo;t contain any <code>a</code> nor <code>b</code>. Which lead to the last elegant solution.</p> + +<p>Until now, that was, easy. Now, how do you manage when instead of <code>a</code> you have a string?</p> + +<p>Say you want to match: </p> +<pre class="twilight"> +&lt;li&gt;...&lt;li&gt; +</pre> + +<p>This is a bit difficult. You need to match </p> +<pre class="twilight"> +&lt;li&gt;[anything not containing &lt;li&gt;]&lt;/li&gt; +</pre> + +<p>The first method would be to use the same reasoning as in my <a href="previouspost">previous post</a>. Here is a first try:</p> + +<pre class="twilight"> +&lt;li&gt;([^&lt;]|&lt;[^l]|&lt;l[^i]|&lt;li[^&gt;])*&lt;/li&gt; +</pre> + +<p>But what about the following string: </p> +<pre class="twilight"> +&lt;li&gt;...&lt;li&lt;/li&gt; +</pre> + +<p>That string should not match. This is why if we really want to match it correctly<sup><a href="#note1">&dagger;</a></sup> we need to add:</p> +<pre class="twilight"> +&lt;li&gt;([^&lt;]|&lt;[^l]|&lt;l[^i]|&lt;li[^&gt;])*(|&lt;|&lt;l|&lt;li)&lt;/li&gt; +</pre> + +<p>Yes a bit complicated. But what if the string I wanted to match was even longer?</p> + +<p>Here is the algorithm way to handle this easily. You reduce the problem to the first one letter matching:</p> + +<pre class="twilight"> +<span class="Comment"><span class="Comment">#</span> transform a simple randomly choosen character</span> +<span class="Comment"><span class="Comment">#</span> to an unique ID </span> +<span class="Comment"><span class="Comment">#</span> (you should verify the identifier is REALLY unique)</span> +<span class="Comment"><span class="Comment">#</span> beware the unique ID must not contain the </span> +<span class="Comment"><span class="Comment">#</span> choosen character</span> +<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>X</span><span class="StringRegexp"><span class="StringRegexp">/</span>_was_x_<span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span> +<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>Y</span><span class="StringRegexp"><span class="StringRegexp">/</span>_was_y_<span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span> + +<span class="Comment"><span class="Comment">#</span> transform the long string in this simple character</span> +<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>&lt;li&gt;</span><span class="StringRegexp"><span class="StringRegexp">/</span>X<span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span> +<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>&lt;<span class="StringRegexpSpecial">\/</span>li&gt;</span><span class="StringRegexp"><span class="StringRegexp">/</span>Y<span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span> + +<span class="Comment"><span class="Comment">#</span> use the first method</span> +<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>X([^X]*)Y</span><span class="StringRegexp"><span class="StringRegexp">/</span><span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span> + +<span class="Comment"><span class="Comment">#</span> retransform choosen letter by string</span> +<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>X</span><span class="StringRegexp"><span class="StringRegexp">/</span>&lt;li&gt;<span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span> +<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>Y</span><span class="StringRegexp"><span class="StringRegexp">/</span>&lt;<span class="StringRegexpSpecial">\/</span>li&gt;<span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span> + +<span class="Comment"><span class="Comment">#</span> retransform the choosen character back</span> +<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>_was_x_</span><span class="StringRegexp"><span class="StringRegexp">/</span>X<span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span> +<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>_was_y_</span><span class="StringRegexp"><span class="StringRegexp">/</span>Y<span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span> +</pre> + +<p>And it works in only 9 lines for any beginning and ending string. This solution should look less <em>I AM THE GREAT REGEXP M45T3R, URAN00B</em>, 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.</p> + +<hr /> + +<p><small><a name="note1"><sup>&dagger;</sup></a> I know I used an HTML syntax example, but in my real life usage, I needed to match between <code>and</code>. And sometimes the string could finish with <code>e::</code>.</small></p> + + + + + tag:yannesposito.com,2010-02-16:/Scratch/fr/blog/2010-02-16-All-but-something-regexp--2-/ + All but something regexp (2) + 2010-02-16T08:33:21Z + 2010-02-16T08:33:21Z + + <p>In my <a href="previouspost">previous post</a> 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 &lsquo;a&rsquo; and &lsquo;b&rsquo;, for example, you want to match:</p> + +<pre class="twilight"> +a.....<span class="Constant"><strong>a......b</strong></span>..b..a....<span class="Constant"><strong>a....b</strong></span>... +</pre> + +<p>Here are two common errors and a solution:</p> + +<pre class="twilight"> +/a.*b/ +<span class="Constant"><strong>a.....a......b..b..a....a....b</strong></span>... +</pre> + +<pre class="twilight"> +/a.*?b/ +<span class="Constant"><strong>a.....a......b</strong></span>..b..<span class="Constant"><strong>a....a....b</strong></span>... +</pre> + +<pre class="twilight"> +/a[^ab]*b/ +a.....<span class="Constant"><strong>a......b</strong></span>..b..a....<span class="Constant"><strong>a....b</strong></span>... +</pre> + +<p>The first error is to use the <em>evil</em> <code>.*</code>. Because you will match from the first to the last. The next natural way, is to change the <em>greediness</em>. But it is not enough as you will match from the first <code>a</code> to the first <code>b</code>. Then a simple constatation is that our matching string shouldn&rsquo;t contain any <code>a</code> nor <code>b</code>. Which lead to the last elegant solution.</p> + +<p>Until now, that was, easy. Now, how do you manage when instead of <code>a</code> you have a string?</p> + +<p>Say you want to match: </p> +<pre class="twilight"> +&lt;li&gt;...&lt;li&gt; +</pre> + +<p>This is a bit difficult. You need to match </p> +<pre class="twilight"> +&lt;li&gt;[anything not containing &lt;li&gt;]&lt;/li&gt; +</pre> + +<p>The first method would be to use the same reasoning as in my <a href="previouspost">previous post</a>. Here is a first try:</p> + +<pre class="twilight"> +&lt;li&gt;([^&lt;]|&lt;[^l]|&lt;l[^i]|&lt;li[^&gt;])*&lt;/li&gt; +</pre> + +<p>But what about the following string: </p> +<pre class="twilight"> +&lt;li&gt;...&lt;li&lt;/li&gt; +</pre> + +<p>That string should not match. This is why if we really want to match it correctly<sup><a href="#note1">&dagger;</a></sup> we need to add:</p> +<pre class="twilight"> +&lt;li&gt;([^&lt;]|&lt;[^l]|&lt;l[^i]|&lt;li[^&gt;])*(|&lt;|&lt;l|&lt;li)&lt;/li&gt; +</pre> + +<p>Yes a bit complicated. But what if the string I wanted to match was even longer?</p> + +<p>Here is the algorithm way to handle this easily. You reduce the problem to the first one letter matching:</p> + +<pre class="twilight"> +<span class="Comment"><span class="Comment">#</span> transform a simple randomly choosen character</span> +<span class="Comment"><span class="Comment">#</span> to an unique ID </span> +<span class="Comment"><span class="Comment">#</span> (you should verify the identifier is REALLY unique)</span> +<span class="Comment"><span class="Comment">#</span> beware the unique ID must not contain the </span> +<span class="Comment"><span class="Comment">#</span> choosen character</span> +<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>X</span><span class="StringRegexp"><span class="StringRegexp">/</span>_was_x_<span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span> +<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>Y</span><span class="StringRegexp"><span class="StringRegexp">/</span>_was_y_<span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span> + +<span class="Comment"><span class="Comment">#</span> transform the long string in this simple character</span> +<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>&lt;li&gt;</span><span class="StringRegexp"><span class="StringRegexp">/</span>X<span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span> +<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>&lt;<span class="StringRegexpSpecial">\/</span>li&gt;</span><span class="StringRegexp"><span class="StringRegexp">/</span>Y<span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span> + +<span class="Comment"><span class="Comment">#</span> use the first method</span> +<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>X([^X]*)Y</span><span class="StringRegexp"><span class="StringRegexp">/</span><span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span> + +<span class="Comment"><span class="Comment">#</span> retransform choosen letter by string</span> +<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>X</span><span class="StringRegexp"><span class="StringRegexp">/</span>&lt;li&gt;<span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span> +<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>Y</span><span class="StringRegexp"><span class="StringRegexp">/</span>&lt;<span class="StringRegexpSpecial">\/</span>li&gt;<span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span> + +<span class="Comment"><span class="Comment">#</span> retransform the choosen character back</span> +<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>_was_x_</span><span class="StringRegexp"><span class="StringRegexp">/</span>X<span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span> +<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>_was_y_</span><span class="StringRegexp"><span class="StringRegexp">/</span>Y<span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span> +</pre> + +<p>And it works in only 9 lines for any beginning and ending string. This solution should look less <em>I AM THE GREAT REGEXP M45T3R, URAN00B</em>, 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.</p> + +<hr /> + +<p><small><a name="note1"><sup>&dagger;</sup></a> I know I used an HTML syntax example, but in my real life usage, I needed to match between ``. And sometimes the string could finish with <code>e::</code>.</small></p> + + + + + tag:yannesposito.com,2010-02-15:/Scratch/en/blog/2010-02-15-All-but-something-regexp/ + All but something regexp + 2010-02-15T09:16:12Z + 2010-02-15T09:16:12Z + + <p>Sometimes you cannot simply write:</p> + +<pre class="twilight"> +<span class="Keyword">if</span> str.<span class="Entity">match</span>(regexp) <span class="Keyword">and</span> + <span class="Keyword">not</span> str.<span class="Entity">match</span>(other_regexp) + do_something +</pre> + +<p>and you have to make this behaviour with only one regular expression. The problem is the complementary of regular languages is not regular. Then, for some expression it is absolutely not impossible.</p> + +<p>But sometimes with some simple regular expression it should be possible<sup><a href="#note1">&dagger;</a></sup>. Say you want to match everything containing the some word say <code>bull</code> but don&rsquo;t want to match <code>bullshit</code>. Here is a nice way to do that:</p> + +<pre class="twilight"> +<span class="Comment"><span class="Comment">#</span> match all string containing 'bull' (bullshit comprised)</span> +<span class="StringRegexp"><span class="StringRegexp">/</span></span><span class="StringRegexp">bull</span><span class="StringRegexp"><span class="StringRegexp">/</span></span> + +<span class="Comment"><span class="Comment">#</span> match all string containing 'bull' except 'bullshit'</span> +<span class="StringRegexp"><span class="StringRegexp">/</span></span><span class="StringRegexp">bull<span class="StringRegexp"><span class="StringRegexp">(</span><span class="StringRegexp"><span class="StringRegexp">[</span>^s<span class="StringRegexp">]</span></span>|$<span class="StringRegexp">)</span></span>|</span> +<span class="StringRegexp">bulls<span class="StringRegexp"><span class="StringRegexp">(</span><span class="StringRegexp"><span class="StringRegexp">[</span>^h<span class="StringRegexp">]</span></span>|$<span class="StringRegexp">)</span></span>|</span> +<span class="StringRegexp">bullsh<span class="StringRegexp"><span class="StringRegexp">(</span><span class="StringRegexp"><span class="StringRegexp">[</span>^i<span class="StringRegexp">]</span></span>|$<span class="StringRegexp">)</span></span>|</span> +<span class="StringRegexp">bullshi<span class="StringRegexp"><span class="StringRegexp">(</span><span class="StringRegexp"><span class="StringRegexp">[</span>^t<span class="StringRegexp">]</span></span>|$<span class="StringRegexp">)</span></span></span><span class="StringRegexp"><span class="StringRegexp">/</span></span> + +<span class="Comment"><span class="Comment">#</span> another way to write it would be</span> +<span class="StringRegexp"><span class="StringRegexp">/</span></span><span class="StringRegexp">bull<span class="StringRegexp"><span class="StringRegexp">(</span><span class="StringRegexp"><span class="StringRegexp">[</span>^s<span class="StringRegexp">]</span></span>|$|s<span class="StringRegexp"><span class="StringRegexp">(</span><span class="StringRegexp"><span class="StringRegexp">[</span>^h<span class="StringRegexp">]</span></span>|$<span class="StringRegexp">)</span></span>|sh<span class="StringRegexp"><span class="StringRegexp">(</span><span class="StringRegexp"><span class="StringRegexp">[</span>^i<span class="StringRegexp">]</span></span>|$<span class="StringRegexp">)</span></span>|shi<span class="StringRegexp"><span class="StringRegexp">(</span><span class="StringRegexp"><span class="StringRegexp">[</span>^t<span class="StringRegexp">]</span></span>|$<span class="StringRegexp">)</span></span><span class="StringRegexp">)</span></span></span><span class="StringRegexp"><span class="StringRegexp">/</span></span> +</pre> + +<p>Let look closer. In the first line the expression is: +<code>bull([^s]|$)</code>, why does the <code>$</code> is needed? +Because, without it the word <code>bull</code> would be no more matched. This expression means:</p> + +<blockquote> + <p>The string finish by <code>bull</code> <br /> +or, <br /> +contains <code>bull</code> followed by a letter different from <code>s</code>. </p> +</blockquote> + +<p>And this is it. I hope it could help you.</p> + +<p>Notice this method is not always the best. For example try to write a regular expression equivalent to the following conditional expression:</p> +<pre class="twilight"> +<span class="Comment"><span class="Comment">#</span> Begin with 'a': ^a</span> +<span class="Comment"><span class="Comment">#</span> End with 'a': c$</span> +<span class="Comment"><span class="Comment">#</span> Contain 'b': .*b.*</span> +<span class="Comment"><span class="Comment">#</span> But isn't 'axbxc'</span> +<span class="Keyword">if</span> str.<span class="Entity">match</span>(<span class="StringRegexp"><span class="StringRegexp">/</span></span><span class="StringRegexp">^a.*b.*c$</span><span class="StringRegexp"><span class="StringRegexp">/</span></span>) <span class="Keyword">and</span> + <span class="Keyword">not</span> str.<span class="Entity">match</span>(<span class="StringRegexp"><span class="StringRegexp">/</span></span><span class="StringRegexp">^axbxc$</span><span class="StringRegexp"><span class="StringRegexp">/</span></span>) + do_something +<span class="Keyword">end</span> +</pre> + +<p>A nice solution is:</p> + +<pre class="twilight"> +<span class="StringRegexp"><span class="StringRegexp">/</span></span><span class="StringRegexp">abc| <span class="Comment"><span class="Comment">#</span> length 3</span></span> +<span class="StringRegexp">a.bc| <span class="Comment"><span class="Comment">#</span> length 4</span></span> +<span class="StringRegexp">ab.c|</span> +<span class="StringRegexp">a<span class="StringRegexp"><span class="StringRegexp">[</span>^x<span class="StringRegexp">]</span></span>b<span class="StringRegexp"><span class="StringRegexp">[</span>^x<span class="StringRegexp">]</span></span>c| <span class="Comment"><span class="Comment">#</span> length 5</span></span> +<span class="StringRegexp">a...*b.*c| # length &gt;5</span> +<span class="StringRegexp">a.*b...*c</span><span class="StringRegexp"><span class="StringRegexp">/</span></span> +</pre> + +<p>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.</p> + +<hr /> + +<p><small><a name="note1">&dagger;</a> +It can be proved that any regular set minus a finite set is also regular. +</small></p> + + + diff --git a/output/n3blog/files/YAquaBubbles.dmg b/output/n3blog/files/YAquaBubbles.dmg new file mode 100644 index 000000000..67ba05b4e Binary files /dev/null and b/output/n3blog/files/YAquaBubbles.dmg differ diff --git a/output/n3blog/files/YClock.dmg b/output/n3blog/files/YClock.dmg new file mode 100644 index 000000000..3ca0ac498 Binary files /dev/null and b/output/n3blog/files/YClock.dmg differ diff --git a/output/n3blog/files/YPassword-1.6.zip b/output/n3blog/files/YPassword-1.6.zip new file mode 100644 index 000000000..769002d60 Binary files /dev/null and b/output/n3blog/files/YPassword-1.6.zip differ diff --git a/output/n3blog/files/cv.pdf b/output/n3blog/files/cv.pdf new file mode 100644 index 000000000..1a3bdeb8c Binary files /dev/null and b/output/n3blog/files/cv.pdf differ diff --git a/output/n3blog/files/cv_en.pdf b/output/n3blog/files/cv_en.pdf new file mode 100644 index 000000000..0ad00a4f4 Binary files /dev/null and b/output/n3blog/files/cv_en.pdf differ diff --git a/output/n3blog/files/forcePaste.app.zip b/output/n3blog/files/forcePaste.app.zip new file mode 100644 index 000000000..8cd3cc3e9 Binary files /dev/null and b/output/n3blog/files/forcePaste.app.zip differ diff --git a/output/n3blog/fr/about/contact/index.html b/output/n3blog/fr/about/contact/index.html new file mode 100644 index 000000000..51784d51c --- /dev/null +++ b/output/n3blog/fr/about/contact/index.html @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + Contact + + + + +
+ + + + Presentation drawing +
+

+ Contact +

+ +
+ +
+ + + + + +
+ +
+
+

Comment me contacter

+ +

Avatar

+ +

yann.esposito@gmail.com
+ Suivez moi sur twitter
+ Mes “bookmarks” diigo
+ Open Source github
+stackoverflow

+ + + + +
+
+ +
+ modifié le : 06/01/2011 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/about/cv/index.html b/output/n3blog/fr/about/cv/index.html new file mode 100644 index 000000000..fb2a5e40f --- /dev/null +++ b/output/n3blog/fr/about/cv/index.html @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + Curriculum Vitæ + + + + +
+ + + + Presentation drawing +
+

+ Curriculum Vitæ +

+ +
+ +
+ + + + + +
+ +
+
+

La dernière version de mon curriculum vitæ sur iWork.

+
+

+Si vous souhaitez pouvoir télécharger ce document en format PDF, iWorks ou Word, merci de me communiquer votre email. Je pourrais vous ajouter à la liste des invités. Il me semble qu'il s'agit d'un bug de la part d'Apple sur ce service encore en β. +

+ + + +
+
+ +
+ modifié le : 28/09/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/about/index.html b/output/n3blog/fr/about/index.html new file mode 100644 index 000000000..400f086fd --- /dev/null +++ b/output/n3blog/fr/about/index.html @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + À propos + + + + +
+ +
+
+ + +
+ +
+
+
+ + Presentation drawing +
+

+ À propos +

+ +
+ +
+ + + + + +
+ +
+
+

Pour faire connaissance

+ +

Une photo de moi

+ +
+
+
+ Nom Yann Esposito
+ Diplôme Doctorat d'Informatique
+ École Université de Provence
+ Emplois Informaticien à Sophia Antipolis
+
+ +

Livres que j’aime :

+ +
    +
  • Goëdel, Escher & Bach [Hofstadter]
  • +
  • On Numbers And Games [Conway]
  • +
  • Baudolino [Eco]
  • +
+ +

Films que j’aime :

+ +
    +
  • Eraserhead [Lynch]
  • +
  • Mullholland Drive [Lynch]
  • +
  • Le festin nu [Cronenberg]
  • +
  • eXistenZ [Cronenberg]
  • +
+ +

Mes sites préférés

+ + +
+ +
+ + +

En deux mots

+ +

Je suis un passioné. Passioné par :

+ + + +

Mais avant tout j’adore apprendre. Par exemple, j’ai appris de nombreux langages de programmation: +C, C++, Objective-C, Python, Java, Perl, awk, bash, zsh, LaTeX, Metapost, CamL… Et j’ai la même passion pour la recherche scientifique, la sécurité informatique, la philosophie et encore pas mal d’autres choses.

+ + +
+ +
+ + +

Ma petite histoire

+ +

J’ai eu mon doctorat en Informatique en décembre 2004 au LIF (Marseille). Pendant les trois années de ma formation j’ai non seulement fait de la recherche en informatique mais j’ai aussi enseigné à des étudiants de l’Université. J’ai aussi développé un programme informatique dont le but était de vérifier expérimentalement mes résultats théoriques.

+ +

J’ai ensuite fait un Post Doctorat au Laboratoire Hubert Curient de Saint-Etienne. Ma mission consistait à développer une application scientifique (SEDiL). Cette application visait comme public des biologistes et devait avoir une interface utilisateur agréable à utiliser.

+ +

Ajourd’hui je travaille pour AirFrance© via Astek. Ce travail est très diversifié. Il demande la connaissance des technologies Web, CMS mais aussi de la programmation en Perl, JSP, meta-programmation…

+ + + + +
+
+ +
+ modifié le : 29/04/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/about/old/index.html b/output/n3blog/fr/about/old/index.html new file mode 100644 index 000000000..10f1a7984 --- /dev/null +++ b/output/n3blog/fr/about/old/index.html @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + Autres sites + + + + +
+ + + + Presentation drawing +
+

+ Autres sites +

+ +
+ +
+ + + + + +
+ +
+
+
+

+ Recherche + » + +

+

+ Mes activités de recherches. +

+
+ +
+

+ Site étudiant + » + +

+

+ Mon site personnel lorsque j'étais étudiant. ✞ 2007 +

+
+ +
+

+ Famille & Photos + » + +

+

+ Le login est "invite", si vous l'avez oublié, demandez-moi le mot de passe. +

+
+ +
+ + + + +
+
+ +
+ modifié le : 04/10/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/about/technical_details/index.html b/output/n3blog/fr/about/technical_details/index.html new file mode 100644 index 000000000..bd85567c8 --- /dev/null +++ b/output/n3blog/fr/about/technical_details/index.html @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + Détails techniques + + + + +
+ + + + Presentation drawing +
+

+ Détails techniques +

+ +

+ Comment vie ce site +

+ +
+ +
+ + + + + +
+ +
+
+

Ce site a été réalisé à partir de rien ou presque. Quasiment toutes les +pages ont été codées avec Vim et engendrées +avec nanoc.

+ +

+ +Les images ont été faites avec +Inkscape et +Gimp. +J'utilise Git +comme +DCVS. + +

+ +

Les commentaires de blog sont gérés par +disqus intense debate. Ainsi je n’ai besoin pour héberger mons site que +d’un serveur de pages statiques. Ce qui a de nombreux avantages. +Principalement concernant la charge et la sécurité du serveur.

+ +

+ +Si vous n'avez pas tout compris, rappelez-vous simplement que je n'utilise +que des outils Opensource +et que j'ai conçu ce site quasiment ex nihilo. + +

+ +

Si au contraire vous voulez connaitre tous les détails je vous suggère +d’aller lire mon article concernant nanoc.

+ + + + +
+
+ +
+ modifié le : 02/08/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/01_nanoc/index.html b/output/n3blog/fr/blog/01_nanoc/index.html new file mode 100644 index 000000000..6c06a88d4 --- /dev/null +++ b/output/n3blog/fr/blog/01_nanoc/index.html @@ -0,0 +1,190 @@ + + + + + + + + + + + + + + + + + + + + + nanoc + + + + +
+ + +
+

+ nanoc +

+ +
+ +
+ + + + + +
+
+
+

Qu’est-ce que nanoc ?

+ +

Il ne s’agit pas exactement d’un +CMS, +mais plutôt d’un système de gestion de pages statiques.

+ +

Il faut programmer sois-même les pages web, +le code pour engendrer les menus…

+ +

J’ai programmé des filtres pour rendre ce site multilangue par exemple

+ +

Vous pourrez trouver beaucoup d’informations sur +le site officiel de nanoc.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Écrit le : 10/10/2008 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/02_ackgrep/code/ack b/output/n3blog/fr/blog/02_ackgrep/code/ack new file mode 100644 index 000000000..38a093374 --- /dev/null +++ b/output/n3blog/fr/blog/02_ackgrep/code/ack @@ -0,0 +1,14 @@ + +#!/usr/bin/env zsh +(($#<1)) && { print 'usage: ack "regexp"' >&2; exit 1 } + +listeFic=( **/*(.) ) +autoload zargs +zargs -- $listeFic -- grep $1 | perl -ne 'use Term::ANSIColor; +if (m/([^:]*)(:.*)('$1')(.*)/) { + print color("green").$1; + print color("reset").$2; + print color("black","on_yellow").$3; + print color("reset").$4."\n"; +} ' + \ No newline at end of file diff --git a/output/n3blog/fr/blog/02_ackgrep/index.html b/output/n3blog/fr/blog/02_ackgrep/index.html new file mode 100644 index 000000000..a5469a510 --- /dev/null +++ b/output/n3blog/fr/blog/02_ackgrep/index.html @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + + Mieux que grep + + + + +
+ + +
+

+ Mieux que grep +

+ +
+ +
+ + + + + +
+
+
+

Mise à jour

+ +

Comme Andy Lester me l’a fait remarqué. ack est un simple fichier perl qu’il suffit de copier dans son répertoire personnel ~/bin. Maintenant j’ai ack sur mon serveur professionnel.

+ +

Il suffit d’aller sur http://betterthangrep.com pour le télécharger.

+ +

Sincèrement, je ne comprend pas qu’ack ne soit pas une commande implémentée par défaut sur les systèmes UNIX. Je ne peux vraiment plus m’en passer, il m’est devenu aussi essentiel qu’un which ou un find.

+ + +
+ +
+ + +

Mieux que grep

+ +

Un des mes usages principaux de grep est

+ +
+
+grep 'pattern' **/*(.)
+
+
+ +

La plupart du temps c’est suffisant, mais ajouter de la coloration +améliore beaucoup l’utilité de cette commande. Il existe déjà un outil +pour ça : il s’appelle ack-grep sous Ubuntu. +Comme je ne peux pas l’installer sur le serveur de mon entreprise, +j’en ai créé un moi-même en quelques lignes :

+ +
+
+
+#!/usr/bin/env zsh
+(($#<1)) && { print 'usage: ack "regexp"' >&2; exit 1 }
+
+listeFic=( **/*(.) )
+autoload zargs
+zargs -- $listeFic -- grep $1 | perl -ne 'use Term::ANSIColor;
+if (m/([^:]*)(:.*)('$1')(.*)/) {
+    print color("green").$1;
+    print color("reset").$2;
+    print color("black","on_yellow").$3;
+    print color("reset").$4."\n";
+} '
+    
+
+
+
+ +

Pour mon utilisation personnelle et celle de mon équipe +c’est suffisant. J’espère que ça pourra vous aider.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Écrit le : 22/07/2009 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/03_losthighway/03_losthighway_1/index.html b/output/n3blog/fr/blog/03_losthighway/03_losthighway_1/index.html new file mode 100644 index 000000000..da04a1af5 --- /dev/null +++ b/output/n3blog/fr/blog/03_losthighway/03_losthighway_1/index.html @@ -0,0 +1,241 @@ + + + + + + + + + + + + + + + + + + + + + + + Lost Highway démystifié (un peu) + + + + +
+ + +
+

+ Lost Highway démystifié (un peu) +

+ +

+ Les clefs du film +

+ +
+ +
+ + + + + +
+
+
+

Les clefs du films

+ +
+ + Tout se passe dans la mémoire de Fred + +
+ +

Tout d’abord, il est clair que comprendre le film comme simplement un film fantastique ne fonctionne pas. En suivant ce point d’entrée on en fini pas de se heurter à des détails incompréhensibles.

+ +

Mon hypothèse de départ c’est que le film dépeint la représentation de la réalité que s’en fait Fred. +Chaque fois qu’il essaye d’échapper à la réalité, celle-ci finira par le rattraper.

+ +

Fred a commis un acte horrible, un meurtre, et essaye de réparer sa mémoire pour accepter son acte. Il va alors s’inventer des réalitées alternatives.

+ +
    +
  • Dans un premier temps il tue sa femme (Renée) parce qu’elle le trompe.
  • +
  • Dans la deuxième partie, il est plus faible. La version blonde de Renée va le manipuler pour tuer Dick Laurent.
  • +
  • Dans la troisième partie il tue Dick Laurent
  • +
+ +

Quelle est la validité de ce choix ?

+ +

Cet interprétation me semble valide à cause du dialogue au début du film avec les policier qui demande au protagoniste s’il a une caméra :

+ +
+

“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.”

+
+ +

Ce que l’on peut traduire approximativement par :

+ +
+

– Avez-vous une caméra ?
+– Non, Fred les détestes.
+– J’aime me rappeler les choses à ma façon.
+– Qu’entendez-vous par là ?
+– Je me rapelle des choses pas nécessairement comme elles se sont passées.

+
+ +

Ainsi, ce que l’on voit n’est pas la réalité, mais la réalité telle que le conçoit Fred. Il est donc le Dieu de cette réalité. Ainsi les interprétations mystiques faisant intervenir le Diable ont une certaine validité.

+ +
+ + + +
+ + + + +
+
+

commentaires

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Écrit le : 04/08/2009 + modifié le : 09/07/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/03_losthighway/03_losthighway_2/index.html b/output/n3blog/fr/blog/03_losthighway/03_losthighway_2/index.html new file mode 100644 index 000000000..b6442f302 --- /dev/null +++ b/output/n3blog/fr/blog/03_losthighway/03_losthighway_2/index.html @@ -0,0 +1,216 @@ + + + + + + + + + + + + + + + + + + + + + + + Lost Highway démystifié (un peu) + + + + +
+ + +
+

+ Lost Highway démystifié (un peu) +

+ +

+ Qui est l'homme mystérieux ? +

+ +
+ +
+ + + + + +
+
+
+

Qui est l’homme mystérieux ?

+ +

l'homme mystérieux

+ +

Qui est donc ce personnage étrange et inquiétant ? +Un être capable d’ubiquité qui dit être invité par Fred dans sa maison ? +Sans sourcils, le visage blême, les yeux écarquillés fixant sans relâche les faits et gestes de Fred.

+ +

C’est certainement une des clés du film. +À mon avis, il représente la partie mauvaise de Fred. +Certainement la jalousie. Si j’étais Catholique je dirai Satan, le tentateur. +Il n’agit jamais, mais ne fait qu’observer et filmer. +Par contre c’est lui qui donne les armes à Fred pour tuer Dick Laurent. +Fred l’a laissé entrer chez lui et il ne peut plus s’en débarrasser. +Un peu comme le Iago de Shakespeare est enfermé dans sa jalousie. +Le personnage mystérieux prend toute l’importance, il le ronge de l’intérieur. +Il aide Fred à accomplir les actes de violences et aussi l’oblige à se souvenir de la réalité.

+ +

Quand il fait l’amour à Renée il voit le visage de l’homme mystérieux à la place du visage de sa femme. En réalité, il s’agit de la même personne d’après Fred. Ce serait donc elle qui est la source de son mal intérieur.

+ +
+ + + +
+ + + + +
+
+

commentaires

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Écrit le : 04/08/2009 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/03_losthighway/03_losthighway_3/index.html b/output/n3blog/fr/blog/03_losthighway/03_losthighway_3/index.html new file mode 100644 index 000000000..baa375784 --- /dev/null +++ b/output/n3blog/fr/blog/03_losthighway/03_losthighway_3/index.html @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + Lost Highway démystifié (un peu) + + + + +
+ + +
+

+ Lost Highway démystifié (un peu) +

+ +

+ Qui filme et dépose les cassettes ? +

+ +
+ +
+ + + + + +
+
+
+

Qui filme et dépose les cassettes ?

+ +

C’est certainement l’homme mystérieux (ou Fred lui-même) qui est à l’origine de ces cassettes. +Le rôle des cassettes est double :

+ +
    +
  • Rappeler à Fred la réalité. D’après Fred les cassettes video correspondent à la réalité. Il a beau essayer de se cacher la réalité, les cassettes finissent par aller jusqu’au bout et il se voit en train de tuer Renée.
  • +
  • La cassette peut aussi faire référence aux cassettes de films pornographique dans laquelle Renée a peut-être tournée dans la réalité ?
  • +
+ +
+ + + +
+ + + + +
+
+

commentaires

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Écrit le : 04/08/2009 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/03_losthighway/03_losthighway_4/index.html b/output/n3blog/fr/blog/03_losthighway/03_losthighway_4/index.html new file mode 100644 index 000000000..742cabb88 --- /dev/null +++ b/output/n3blog/fr/blog/03_losthighway/03_losthighway_4/index.html @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + Lost Highway démystifié (un peu) + + + + +
+ + +
+

+ Lost Highway démystifié (un peu) +

+ +

+ Que s'est-il vraiment passé ? +

+ +
+ +
+ + + + + +
+
+
+

Que s’est-il vraiment passé ?

+ +

Ici, tout n’est pas donné, on garde une assez grande liberté. Mais on a des indices.

+ +

Hypothese n°1

+ +

Je dirais que le protagoniste est un garagiste qui est tombé amoureux d’une actrice porno. Il l’a certainement vu la première fois accompagnant le fameux Dick Laurent. Voyant qu’il ne peut pas l’avoir pour lui, fou de jalousie il tue Dick Laurent dans un motel où celui-ci à couché avec Renée.

+ +

On a la liberté de décider s’il a vraiment tué la femme ou pas. +Dans ma première vision du film, j’avais envie de dire qu’il ne la tue pas. Mais qu’une fois le meurtre commis, il va chez elle, sonne pour lui annoncer la mort de Dick Laurent. Il a alors juste le temps de s’enfuir, la police à ses trousses.

+ +

Hypothese n°2

+ +

La première partie resemble à la réalité. Il a vraiment tué sa femme. Il se fait arrété et condamné (certainement à mort). Par contre on ne sait pas s’il est aussi allé tuer Andy.

+ +

alors c’est laquelle ?

+ +

La seconde hypothèse me semble plus vraisemblable, car il y a plus de recoupements possibles. +La première me semble aussi cohérente. C’est cette première hypothèse que j’avais émise lors de mon premier visionnage du film.

+ +

Ce qui montre la force de ce film c’est de se dire qu’il y a de nombreuses autres hypothèses qui pourraient aussi bien fonctionner. C’est le fameux effet Rashomon. Plusieurs personnes peuvent décrire de façon cohérentes ce qu’elles ont vu, mais toutes les descriptions sont incohérentes entres-elles.

+ + +
+ +
+ + +

Conclusion

+ +

Il y aurait encore beaucoup à dire sur l’analyse de ce film. Mais il me semble que j’ai rassemblé l’essentiel des clés pour sa compréhension.

+ +

Il me semble qu’avoir à l’esprit l’effet “test de Rorschach” est essentiel lors de la visualisation de ce film.

+ +

J’aimerai avoir votre opinion ; mon interprétation tient-elle la route ?

+ +
+ + + +
+ + + + +
+
+

commentaires

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Écrit le : 04/08/2009 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/03_losthighway/index.html b/output/n3blog/fr/blog/03_losthighway/index.html new file mode 100644 index 000000000..5762a0797 --- /dev/null +++ b/output/n3blog/fr/blog/03_losthighway/index.html @@ -0,0 +1,248 @@ + + + + + + + + + + + + + + + + + + + + + + + Lost Highway démystifié (un peu) + + + + +
+ + +
+

+ Lost Highway démystifié (un peu) +

+ +

+ introduction +

+ +
+ +
+ + + + + +
+
+
+

Lost Highway

+ +
+Lost Highway ne laisse pas indiférent. Le revoir ne lasse pas même s'il parrait complètement obscur. +C'est une des forces de David Lynch. +Il faut garder à l'esprit qu'il n'existe pas une seule interprétation possible et cohérente du film. +Seul David Lynch pourrait donner une explication complète du film. +Je donne cependant quelques clés que j'ai découverte qui aident à suivre le film sans être complètement perdu. +Ces clés devraient vous aider à vous faire votre propre idée du film... +
+ +

La première fois que j’ai vu Lost Highway je me suis senti un peu perdu. +J’en ai alors cherché le sens. Voilà ce que j’ai pu trouver sur Internet :

+ +
    +
  • Fred passe un pacte avec le diable incarné par l’homme en noir ;
  • +
  • l’homme mystérieux est une (la) caméra ;
  • +
  • seule la première histoire est vrai, la suite étant l’imagination de Fred ;
  • +
+ +

sans compter les multiples avis trouvés sur les forums. Tout cela ne me paraissait pas convaincant. +J’ai alors réussi à trouver deux articles (en anglais) qui proposent de bien meilleures interprétations. Mais aucun des deux ne m’a complètement convaincu :

+ +
    +
  • le permier est sur mediacircus,
  • +
  • le second qui développe presque la même interprétation que la première est vraiment très détaillé sur jasonweb.
  • +
+ +

Il faut garder à l’esprit qu’il n’existe pas une seule interprétation possible et cohérente du film. Seul David Lynch pourrait donner l’explication complète du film.

+ +

Je donne quelques clés aidant à suivre le film sans être complètement perdu. +Ces clés devraient vous aider à vous faire votre propre idée du film.

+ +

Le test de Rorschach

+ +

test de Rorschach +À l’instar du protagoniste chacun voit dans ce film ce qu’il a envie d’y voir. Nous pouvons nous y perdre simplement parce que nous pouvons nous perdre dans notre propre esprit. C’est une invitation à la réflexion. Regarder ce film c’est un peu comme passer un test de Rorschach. Qu’y voit-on ? Chacun y met un peu de sa propre personnalité dans l’explication du film.

+ +
    +
  • Si vous êtes un mystique, vous verrez dans l’homme mystérieux un démon
  • +
  • si vous êtes plus psychanalytique vous y verrez une partie inconsciente du protagoniste…
  • +
+ +

En général en essayant d’expliquer ce film, on se perd un peu dans notre pensée. Et souvent on échoue à tout expliquer. Il y a toujours un point qui rend la construction incohérente avec le film. C’est pourquoi rechercher une explication unique est un entreprise vaine.

+ +

Interprétation ≠ Explication

+ +

Je donne une interprétation et non pas une explication. Ma vision des choses, me semble cohérente. Cependant il est très probable que mon adhésion au film soit très différente de la votre. +Il y a certainement beaucoup d’autres explications qui restent cohérentes.

+ +

J’écris cet article, parce que j’ai l’impression d’en avoir trouver une qui marche pour plus de 97% du film (peut-être 100%, mais j’en doute, il faudrait que je le revois encore une fois).

+ +
+ + + +
+ + + + +
+
+

commentaires

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Écrit le : 04/08/2009 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/04_drm/index.html b/output/n3blog/fr/blog/04_drm/index.html new file mode 100644 index 000000000..948e41074 --- /dev/null +++ b/output/n3blog/fr/blog/04_drm/index.html @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + Les protections anti-copies sont LE MAL + + + + +
+ + +
+

+ Les protections anti-copies sont LE MAL +

+ +

+ Protections anti-copie = Belle connerie (+1) ! +

+ +
+ +
+ + + + + +
+
+
+

Protections anti-copie = Belle connerie (+1)!

+ +

Ma femme a acheté pour environ 500€ (au moins) de séries télé sur iTunes. Mais elles s’est trompé pour la première saison de Battlestar Galactica. Qu’elle a téléchargé en anglais. Hors comme les séries sont protégées, on ne peut simplement pas voir la série avec des sous-titres !

+ +
+

WTF?

+
+ +

Résultat des courses, ma femme n’achetera plus de séries sur iTunes tant qu’elles resteront protégées par DRM, qu’elle ne pourront pas être gravées sur DVD (pour être regardées sur la télé). Et comme elle est bien moins prompte à acheter des DVD que simplement cliquer sur un bouton.

+ +
+ +Ca fera nettement moins d'argent pour vous les ayant-droits !!! + +
+ +

Et ma femme ne pourra pas voir ces épisodes.
+C’est ce qu’on appelle une cooperation ‘LOSE-LOSE’.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Écrit le : 15/08/2009 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/05_git_create_remote_branch/code/git-create-new-branch.sh b/output/n3blog/fr/blog/05_git_create_remote_branch/code/git-create-new-branch.sh new file mode 100644 index 000000000..b72b97815 --- /dev/null +++ b/output/n3blog/fr/blog/05_git_create_remote_branch/code/git-create-new-branch.sh @@ -0,0 +1,14 @@ + +#!/usr/bin/env zsh + +if (($#<1)); then + print -- "usage: $0:t branch_name" >&2 + exit 1 +fi + +branch=$1 +git br ${branch} +git co ${branch} +git config branch.${branch}.remote origin +git config branch.${branch}.merge refs/heads/${branch} + \ No newline at end of file diff --git a/output/n3blog/fr/blog/05_git_create_remote_branch/index.html b/output/n3blog/fr/blog/05_git_create_remote_branch/index.html new file mode 100644 index 000000000..aab4ba61b --- /dev/null +++ b/output/n3blog/fr/blog/05_git_create_remote_branch/index.html @@ -0,0 +1,219 @@ + + + + + + + + + + + + + + + + + + + + + + + Création de branches externe avec Git + + + + +
+ + +
+

+ Création de branches externe avec Git +

+ +
+ +
+ + + + + +
+
+
+

Créer une branche Git externe facilement

+ +

J’utilise Git pour synchroniser des projets personnels. +C’est pourquoi quand je crée une branche locale je souhaite quasiment toujours qu’elle soit aussi créée en externe (remote).

+ +

Voici le script que j’utilise pour accomplir cette tâche :

+ +
+
+
+#!/usr/bin/env zsh
+
+if (($#<1)); then
+    print -- "usage: $0:t branch_name" >&2
+    exit 1
+fi
+
+branch=$1
+git br ${branch}
+git co ${branch}
+git config branch.${branch}.remote origin
+git config branch.${branch}.merge refs/heads/${branch}
+    
+
+
+
+ +

Bien sûr, je suppose qu’origin est déjà configurée.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 17/08/2009 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/06_How_I_use_git/code/git-create-new-branch b/output/n3blog/fr/blog/06_How_I_use_git/code/git-create-new-branch new file mode 100644 index 000000000..add959c52 --- /dev/null +++ b/output/n3blog/fr/blog/06_How_I_use_git/code/git-create-new-branch @@ -0,0 +1,13 @@ + +#!/usr/bin/env zsh + +if (($#<1)); then + print -- "usage: $0:t branch_name" >&2 + exit 1 +fi + +branch=$1 +git br ${branch} +git co ${branch} +git config branch.${branch}.remote origin +git config branch.${branch}.merge refs/heads/${branch} diff --git a/output/n3blog/fr/blog/06_How_I_use_git/code/git-get-remote-branches b/output/n3blog/fr/blog/06_How_I_use_git/code/git-get-remote-branches new file mode 100644 index 000000000..ca1ef8c3b --- /dev/null +++ b/output/n3blog/fr/blog/06_How_I_use_git/code/git-get-remote-branches @@ -0,0 +1,14 @@ + +#!/usr/bin/env zsh + +# recup branches not on local +localbranches=( $(git br | sed 's/\*/ /') ) +remoteMissingBranches=( $(git br -r | \ + egrep -v "origin/HEAD|(${(j:|:)localbranches})" ) ) +for br in $remoteMissingBranches; do + branch=${br#origin/} + print "get remote branch $branch" + git br ${branch} + git config branch.${branch}.remote origin + git config branch.${branch}.merge refs/heads/${branch} +done diff --git a/output/n3blog/fr/blog/06_How_I_use_git/index.html b/output/n3blog/fr/blog/06_How_I_use_git/index.html new file mode 100644 index 000000000..186d6c92f --- /dev/null +++ b/output/n3blog/fr/blog/06_How_I_use_git/index.html @@ -0,0 +1,382 @@ + + + + + + + + + + + + + + + + + + + + + + + Git en solo + + + + +
+ + +
+

+ Git en solo +

+ +
+ +
+ + + + + +
+
+
+

central architecture

+ + +
+ + +

Màj : Actuellement j’utilise github avec des repository privés. Je paye une somme très raisonnable pour ce service. Si vous voulez être complètement autonome, je vous conseille d’utiliser gitolite sur votre propre serveur accessible sur le web.

+ + +
+ + +

J’utilise Git pour gérer mes projets personnels. +J’ai un repository centralisé et tous mes ordinateurs se synchronisent avec lui. +Cependant, dans la documentation officielle, je n’ai pas trouvé clairement ce que je souhaitais.

+ +

En d’autres termes, si vous souhaitez utiliser le type de workflow que SVN proposait avec Git (et ses avantages), voici comment procéder.

+ + +
+ +
+ + +

Initialisation

+ +

Disons que j’ai déjà un projet et que je veuille en créer un nouveau.

+ +
+
+cd to/project/directory/
+git init
+git add
+git commit
+
+
+ +

Maintenant tous les fichiers du répertoire to/project/directory/ sont versionnés. Si vous voulez ignorer certains fichiers il suffit de modifier le fichier .gitignore.

+ +

Par exemple voici le mien :

+
+
+*.swp
+.DS_Store
+ikog.py.bak
+output/n3blog/assets
+output/n3blog/en
+output/n3blog/fr
+output/n3blog/multi
+
+
+ +

Ensuite, il faut placer ce projet dans un répertoire accessible via Internet.

+ +
+
+git clone --bare . /path/to/repository
+
+
+ +
+Màj: La meilleure solution est d'installer gitolite pour installer un serveur git sur sa machine. Gitolite permet de gérer la gestion des droits d'utilisateurs, ceux-ci n'ayant pas accès à un shell sur la machine. + +
+ +

Maintenant à partir de n’importe quel ordinateur, voici ce que vous pouvez faire :

+ +
+
+git clone protocol://path/to/repository local_directory
+
+
+ +

et local_directory contiendra un projet à jour.

+ +
+ +Je vous conseille de faire la même opération sur l'ordinateur qui à servi à créer le projet de façon à vérifier que tout fonctionne correctement. + +
+ + +
+ +
+ + +

L’utilisation courante

+ +

Pour résumer vous avez maintenant un repository sur Internet et un ou plusieurs ordinateurs lui sont associés. Maintenant il faut que tout soit toujours synchronisé.

+ +

Avant de commencer à travailler, la première chose à faire est de récupérer les modification à partir d’Internet vers votre poste local :

+ +
+
+git pull
+
+
+ +

Ensuit vous pouvez travailler en faisant (plusieurs fois) :

+ +
+
+hack, hack, hack...
+git add some files
+git commit
+
+
+ +

Quang vous voulez envoyez les modifications locales sur Internet, il suffit de faire :

+ +
+
+git push
+
+
+ +

Tout devrait être bon.

+ +

Si vous avez des problèmes avec le push et le pull ; vérifiez votre fichier .git/config. Il devrait contenir les lignes suivantes :

+ +
+
+...
+[remote "origin"]
+	url = protocol://url/of/the/repository
+	fetch = +refs/heads/*:refs/remotes/origin/*
+[branch "master"]
+	remote = origin
+	merge = refs/heads/master
+...
+
+
+ +

Synchronisation des branches

+ +

Bien, maintenant que tout semble bon, il faut encore s’occuper de quelques petites choses (sinon, SVN suffirait). +Git est complètement orienté sur la décentralisation et la création de nouvelles branches sur le même poste. Synchroniser des branches sur plusieurs serveurs différent n’est pas une opération naturelle.

+ +

C’est pourquoi j’ai créé deux simples scripts pour automatiser cette opération. Un script pour créer un branche localement et en ligne. Un autre script pour récupérer les branches en lignes qui ne sont pas présente localement.

+ +

Ainsi, lorsque je veux créer une nouvelle branche (localement et ligne) ; je lance le script :

+ +
git-create-new-branch branch_name
+
+ +

et quand je suis sur un autre ordinateur et que je veux récupérer les branches crées sur un autre poste, j’exécute :

+ +
git-get-remote-branches
+
+ +

Voici le code des deux script (en zsh) :

+ +
+
+
+#!/usr/bin/env zsh
+
+if (($#<1)); then
+    print -- "usage: $0:t branch_name" >&2
+    exit 1
+fi
+
+branch=$1
+git br ${branch}
+git co ${branch}
+git config branch.${branch}.remote origin
+git config branch.${branch}.merge refs/heads/${branch}
+
+
+
+ +
+
+
+#!/usr/bin/env zsh
+
+# recup branches not on local
+localbranches=( $(git br | sed 's/\*/ /') )
+remoteMissingBranches=( $(git br -r | \
+    egrep -v "origin/HEAD|(${(j:|:)localbranches})" ) )
+for br in $remoteMissingBranches; do
+  branch=${br#origin/}
+  print "get remote branch $branch"
+  git br ${branch}
+  git config branch.${branch}.remote origin
+  git config branch.${branch}.merge refs/heads/${branch}
+done
+
+
+
+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 18/08/2009 + modifié le : 17/11/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/07_Screensaver_compilation_option_for_Snow_Leopard/index.html b/output/n3blog/fr/blog/07_Screensaver_compilation_option_for_Snow_Leopard/index.html new file mode 100644 index 000000000..9479e9eea --- /dev/null +++ b/output/n3blog/fr/blog/07_Screensaver_compilation_option_for_Snow_Leopard/index.html @@ -0,0 +1,203 @@ + + + + + + + + + + + + + + + + + + + + + + + Compilation d'économiseur d'écran sous Snow Leopard<small>©</small> + + + + +
+ + +
+

+ Compilation d'économiseur d'écran sous Snow Leopard© +

+ +
+ +
+ + + + + +
+
+
+

Comment recompiler un économiseur d’écran sous Snow Leopard©

+ +

Mon économiseur d’écran ne fonctionnait plus sous Mac OS X 10.6 Snow Leopard©. Après un peu de recherche sous google, le problème semblait pouvoir être réglé avec une recompilation. +Cependant, même en recomilant en 64 bits ça ne fonctionnait toujours pas. +Après un peu plus de recherches (merci à ElectricSheep ), +j’ai découvert les bons paramètres.

+ +

XCode configuration

+ +

Pour l’instant je ne l’ai pas compilé pour être compatible Tiger et Leopard. Je ne connais pas assez bien XCode pour savoir comment désactiver le garbage collector sur la version 32 bits et l’activer sur la version 64 bits.

+ +

Il a été assez difficile de découvrir toutes ces informations. J’espère que cet article aura pu aider quelqu’un.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 06/09/2009 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/08_Configure_ssh_to_listen_the_port_443_on_Snow_Leopard/code/ssh-443.plist b/output/n3blog/fr/blog/08_Configure_ssh_to_listen_the_port_443_on_Snow_Leopard/code/ssh-443.plist new file mode 100644 index 000000000..9cccfce9d --- /dev/null +++ b/output/n3blog/fr/blog/08_Configure_ssh_to_listen_the_port_443_on_Snow_Leopard/code/ssh-443.plist @@ -0,0 +1,35 @@ + + + + + + Disabled + + Label + local.sshd + Program + /usr/libexec/sshd-keygen-wrapper + ProgramArguments + + /usr/sbin/sshd + -i + + Sockets + + Listeners + + SockServiceName + https + + + inetdCompatibility + + Wait + + + StandardErrorPath + /dev/null + SHAuthorizationRight + system.preferences + + diff --git a/output/n3blog/fr/blog/08_Configure_ssh_to_listen_the_port_443_on_Snow_Leopard/index.html b/output/n3blog/fr/blog/08_Configure_ssh_to_listen_the_port_443_on_Snow_Leopard/index.html new file mode 100644 index 000000000..65a6f3086 --- /dev/null +++ b/output/n3blog/fr/blog/08_Configure_ssh_to_listen_the_port_443_on_Snow_Leopard/index.html @@ -0,0 +1,267 @@ + + + + + + + + + + + + + + + + + + + + + + + ssh sur le port 443 avec Snow Leopard + + + + +
+ + +
+

+ ssh sur le port 443 avec Snow Leopard +

+ +
+ +
+ + + + + +
+
+
+

Surfez partout comme si vous étiez chez vous

+ +

Que ce soit pour surfer en toute sécurité depuis un accès wifi non sécurisé ou pour contourner les parefeux diaboliques des entreprises. J’ai configuré un serveur ssh écoutant sur le port 443 chez moi.

+ +

Ensuite de mon portable ou de mon ordinateur local, je dois simplement lancé la merveilleuse commande :

+ +
+
+ssh -p 443 -D 9050 username@host
+
+
+ +

et un proxy socks écoute sur le port 9050. Ce proxy socks transférera toutes les requêtes locales via le tunnel ssh. Ainsi je peux surfer en local comme si je naviguais depuis mon ordinateur à la maison. Je peux écrire mon numéro de carte bleu sans avoir peur que le wifi local soit sniffé. Je dois simplement configurer mon navigateur web pour utiliser le proxy socks sur localhost écoutant le port 9050.

+ +

J’ai eu cette information à partir de cet article.

+ +

Ssh et Snow Leopard©

+ +

J’ai un Mac avec Snow Leopard© à la maison. +Il ne suffit pas de modifier le fichier /etc/sshd.config pour changer le port d’écoute d’sshd. +Le système utilise launchd pour lancer les démons.

+ +

J’ai posé cette question sur Apple Discussions dans ce fil de discussion. +Merci à tous ceux qui m’ont aidé. Et la solution est :

+ +

Créer un fichier /Library/LaunchDaemons/ssh-443.plist contenant :

+ +
+
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>Disabled</key>
+	<false/>
+	<key>Label</key>
+	<string>local.sshd</string>
+	<key>Program</key>
+	<string>/usr/libexec/sshd-keygen-wrapper</string>
+	<key>ProgramArguments</key>
+	<array>
+		<string>/usr/sbin/sshd</string>
+		<string>-i</string>
+	</array>
+	<key>Sockets</key>
+	<dict>
+		<key>Listeners</key>
+		<dict>
+			<key>SockServiceName</key>
+			<string>https</string>
+		</dict>
+	</dict>
+	<key>inetdCompatibility</key>
+	<dict>
+		<key>Wait</key>
+		<false/>
+	</dict>
+	<key>StandardErrorPath</key>
+	<string>/dev/null</string>
+        <key>SHAuthorizationRight</key>
+        <string>system.preferences</string>
+</dict>
+</plist>
+
+
+
+ +

C’est une copie de /System/Library/LaunchDaemons/ssh.plist avec quelques modifications :

+ +
    +
  • le SockServiceName est devenu https au lieu de ssh
  • +
  • le Label est passé de com.openssh.sshd à quelque chose qui n’existait pas comme local.sshd
  • +
+ +

Encore une fois j’espère que ça a pu être utile.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 07/09/2009 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/09_Why_I_didn-t_keep_whosamung-us/index.html b/output/n3blog/fr/blog/09_Why_I_didn-t_keep_whosamung-us/index.html new file mode 100644 index 000000000..ed61fa5ee --- /dev/null +++ b/output/n3blog/fr/blog/09_Why_I_didn-t_keep_whosamung-us/index.html @@ -0,0 +1,204 @@ + + + + + + + + + + + + + + + + + + + + + + + Pourquoi je n'ai pas conservé whos.amung.us + + + + +
+ + +
+

+ Pourquoi je n'ai pas conservé whos.amung.us +

+ +
+ +
+ + + + + +
+
+
+

J’ai arrété d’utiliser whos.amung.us en faveur de Google Analytics.

+ +

La plupart du temps je préfère ne pas utiliser le même produit que tout le monde. J’aime bien essayer des choses un peu nouvelles. Mais whosamung.us avait trop de publicités. Je devais affichier une de leur image sur mon site qui n’écrivait que le nombre de personne actuellement présentes. Pas les nombres de visites.

+ +

C’est pourquoi j’utilise maintenant google analytics. Le problème reste entier pour les navigateurs sans javascript.

+ +

Donc pour l’instant +<div class="encadre"> +Théoreme :

+
+Google Analytics > Who's Amung Us +
+
+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 11/09/2009 + modifié le : 02/09/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/10_Synchronize_Custom_WebSite_with_mobileMe/code/publish b/output/n3blog/fr/blog/10_Synchronize_Custom_WebSite_with_mobileMe/code/publish new file mode 100644 index 000000000..466320d4f --- /dev/null +++ b/output/n3blog/fr/blog/10_Synchronize_Custom_WebSite_with_mobileMe/code/publish @@ -0,0 +1,102 @@ + +#!/usr/bin/env zsh + +# Author: Yann Esposito +# Mail: yann.esposito@gmail.com +# Synchronize with "mobileMe" iDisk account. + +mobileMeUser="firstname.lastname" +siteName="siteName" + +# 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 does not exist ; please verify the configuration ($0)" >&2; + exit 1 +} + +[[ ! -d $destRep ]] && { + print -- "$destRep does not exist, please mount the filesystem" >&2; + exit 1 +} + +if [[ $1 == '-h' ]]; then + print -- "usage: $0:h [-h|-a|-s]" + print -- " -a sychronize primary index" + print -- " -h show this help" + print -- " -s only swap directories" +fi + +if [[ $1 == '-a' ]]; then + print -- "Index synchronisation (${destRep:h})" + rsync -av $root/index.html ${destRep:h}/index.html +fi + +print -- "Root = $root" +print -- "Dest = $destRep" + +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/n3blog/ $destRep.tmp + result=$? + if (( $result > 0 )); then + print -P -- "%Brsync failed%b (try n°$essai)" >&2 + fi + ((essai++)) + done +fi + +# SWAP +print -P -- "%B[Directory Swap (tmp <=> target)]%b" +essai=1 +while [[ -e $destRep.old ]]; do + print -n -- "remove $destRep.old" + if ((essai>1)); then + print " (try n°$essai)" + else + print + fi + ((essai++)) + \rm -rf $destRep.old +done + +print -- " renommage du repertoire sandard vers le .old" +essai=1 +while [[ -e $destRep ]]; do + mv $destRep $destRep.old + (($?)) && print -- "Failed to rename (try n°$essai)" >&2 + ((essai++)) +done + +print -- " renaming folder tmp (new) to the standard one" +print -P -- " %BThe WebSite isn't working%b $(date)" +essai=1 +while [[ ! -e $destRep ]]; do + mv $destRep.tmp $destRep + (($?)) && print -P -- "%B[WebSite not working]%b(try n°$essai) Failed to rename (mv $destRep.tmp $destRep)" >&2 + ((essai++)) +done + +print -P -- "\t===\t%BWEBSITE SHOULD WORK NOW%b\t===" + +print -- " rename old folder to tmp folder" +essai=1 +while [[ ! -e $destRep ]]; do + mv $destRep.old $destRep.tmp + (($?)) && print -P -- "Failed to rename n°$essai" >&2 + ((essai++)) +done + +print -P -- " Publish terminated" diff --git a/output/n3blog/fr/blog/10_Synchronize_Custom_WebSite_with_mobileMe/index.html b/output/n3blog/fr/blog/10_Synchronize_Custom_WebSite_with_mobileMe/index.html new file mode 100644 index 000000000..ee5b01c64 --- /dev/null +++ b/output/n3blog/fr/blog/10_Synchronize_Custom_WebSite_with_mobileMe/index.html @@ -0,0 +1,444 @@ + + + + + + + + + + + + + + + + + + + + + + + Héberger son site personnel sur le site mobileMe + + + + +
+ + +
+

+ Héberger son site personnel sur le site mobileMe +

+ +
+ +
+ + + + + +
+
+
+

mise à jour du 28/10/2009

+ +

J’ai mis à jour mon script avec une version incrémentale bien plus pratique. +En plus depuis l’écriture de cet article Apple© semble avoir nettement amélioré la vitesse de ses serveurs en Europe.

+ + +
+ +
+ + +

WebDav terror

+ +

En France l’iDisk d’Apple© est très lent. La vitesse d’upload me rapelle l’époque des modem 56k, c’est dire. La plupart du temps les opérations telles que lister le contenu d’un répertoire prennent au moins 30 secondes (pour 15 éléments). Renommer un répertoire échoue presque systématiquement.

+ +

Apple© utilise des serveurs WebDav pour héberger les fichiers. Le protocole fonctionne sur le port 80 (comme http). Je me suis rendu compte qu’utiliser WebDav via https fontionne bien mieux (2 à 3 fois plus rapide avec moins d’erreurs). Mais, ça reste quand même très lent et insuffisant.

+ +

J’uploade mes fichiers à partir de mon Mac et de temps en temps à partir d’un PC sous Ubuntu (iDisk monté avec webdavfs).

+ +

Synchroniser de façon sûre

+ +

Voici le script que j’utilise pour synchroniser mon site web (non créé avec iWeb©) avec le maximum de sécurité. Chaque opération est répétée jusqu’à ce qu’elle fonctionne.

+ +

Les idées sont :

+ +
    +
  • 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).
  • +
+ +

Jusqu’ici j’utilise rsync qui n’est en fait pas plus efficace qu’une simple copie cp avec WebDav. Je devrais utiliser une méthode pour mémoriser les changements entre chaque publication.

+ +

En réalité quand je suis sur mon Mac j’utilise Transmit qui est vraiment très bien et surtout beaucoup plus efficace que le finder pour synchroniser des fichiers. Ensuite, je ne fait que le “swap” des répertoires.

+ +

Mon script prend un paramètre -s pour ne faire que le “swap”. Il prend aussi une option -a pour envoyer le fichier index.html qui va rediriger vers ma nouvelle page principale (iWeb© à la fâcheuse habitude de le remplacer).

+ +

Pour utiliser le script vous devriez remplacer la valeur de la variable mobileMeUser par votre nom d’utilisateur mobileMe©.

+ +
+
+
+#!/usr/bin/env zsh
+
+# 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"
+
+# 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; 
+    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 == '-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"
+
+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/n3blog/ $destRep.tmp
+        result=$?
+        if (( $result > 0 )); then
+            print -P -- "%BEchec du rsync%b (essai n°$essai)" >&2
+        fi
+        ((essai++))
+    done
+fi
+
+# 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
+        print
+    fi
+    ((essai++))
+    \rm -rf $destRep.old
+done
+
+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
+    ((essai++))
+done
+
+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
+    ((essai++))
+done
+
+print -P -- "\t===\t%BSITE DISPONIBLE%b\t==="
+
+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
+    ((essai++))
+done
+
+print -P -- "  publication terminée"
+
+
+
+ +
+
+
+#!/usr/bin/env zsh
+
+# Author: Yann Esposito
+#   Mail: yann.esposito@gmail.com
+# Synchronize with "mobileMe" iDisk account.
+
+mobileMeUser="firstname.lastname"
+siteName="siteName"
+
+# 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 does not exist ; please verify the configuration ($0)" >&2; 
+    exit 1 
+}
+
+[[ ! -d $destRep ]] && { 
+    print -- "$destRep does not exist, please mount the filesystem" >&2; 
+    exit 1 
+}
+
+if [[ $1 == '-h' ]]; then
+    print -- "usage: $0:h [-h|-a|-s]"
+    print -- "  -a sychronize primary index"
+    print -- "  -h show this help"
+    print -- "  -s only swap directories"
+fi
+
+if [[ $1 == '-a' ]]; then
+    print -- "Index synchronisation (${destRep:h})"
+    rsync -av $root/index.html ${destRep:h}/index.html
+fi
+
+print -- "Root = $root"
+print -- "Dest = $destRep"
+
+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/n3blog/ $destRep.tmp
+        result=$?
+        if (( $result > 0 )); then
+            print -P -- "%Brsync failed%b (try n°$essai)" >&2
+        fi
+        ((essai++))
+    done
+fi
+
+# SWAP
+print -P -- "%B[Directory Swap (tmp <=> target)]%b"
+essai=1
+while [[ -e $destRep.old ]]; do
+    print -n -- "remove $destRep.old"
+    if ((essai>1)); then 
+        print " (try n°$essai)"
+    else
+        print
+    fi
+    ((essai++))
+    \rm -rf $destRep.old
+done
+
+print -- "  renommage du repertoire sandard vers le .old"
+essai=1
+while [[ -e $destRep ]]; do
+    mv $destRep $destRep.old 
+    (($?)) && print -- "Failed to rename (try n°$essai)" >&2
+    ((essai++))
+done
+
+print -- "  renaming folder tmp (new) to the standard one"
+print -P -- "  %BThe WebSite isn't working%b $(date)"
+essai=1
+while [[ ! -e $destRep ]]; do
+    mv $destRep.tmp $destRep
+    (($?)) && print -P -- "%B[WebSite not working]%b(try n°$essai) Failed to rename (mv $destRep.tmp $destRep)" >&2
+    ((essai++))
+done
+
+print -P -- "\t===\t%BWEBSITE SHOULD WORK NOW%b\t==="
+
+print -- "  rename old folder to tmp folder"
+essai=1
+while [[ ! -e $destRep ]]; do
+    mv $destRep.old $destRep.tmp
+    (($?)) && print -P -- "Failed to rename n°$essai" >&2
+    ((essai++))
+done
+
+print -P -- "  Publish terminated"
+
+
+
+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 11/09/2009 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/11_Load_Disqus_Asynchronously/index.html b/output/n3blog/fr/blog/11_Load_Disqus_Asynchronously/index.html new file mode 100644 index 000000000..406664ed7 --- /dev/null +++ b/output/n3blog/fr/blog/11_Load_Disqus_Asynchronously/index.html @@ -0,0 +1,265 @@ + + + + + + + + + + + + + + + + + + + + + + + Load Disqus Asynchronously [en] + + + + +
+ + +
+

+ Load Disqus Asynchronously [en] +

+ +
+ +
+ + + + + +
+
+
+

Update

+ +

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 :-).

+ + +
+ +
+ + +

Before begining, I must state that I love Disqus.

+ +

I know there is a similar blog entry at Trephine.org. Here I just add a straight and easy way to load disqus asynchronously using jQuery.

+ +

I also know there is a jQuery plugin to make just that. Unfortunately I had some issue with CSS.

+ +

Now let’s begin.

+ + +
+ +
+ + +

Why?

+ +

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.
  • +
  • More independance: when disqus is down, my page is blocked!
  • +
+ + +
+ +
+ + +

How?

+ +

I give a solution with jQuery, but I’m certain it will work with many other js library.

+ +

Javascript

+ +

replace:

+ +
+
+<script type="text/javascript" src="http://disqus.com/forums/YOUR_DISQUS_ID/embed.js"></script>
+
+
+ +

by

+ +
+
+window.disqus_no_style=true;
+$(document).ready(function(){
+    $.getScript("http://disqus.com/forums/YOUR_DISQUS_ID/embed.js");
+});
+
+
+ +

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.

+ +

CSS

+ +

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.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 17/09/2009 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2009-09-Disqus-versus-Intense-Debate--Why-I-switched-/index.html b/output/n3blog/fr/blog/2009-09-Disqus-versus-Intense-Debate--Why-I-switched-/index.html new file mode 100644 index 000000000..c7e42899f --- /dev/null +++ b/output/n3blog/fr/blog/2009-09-Disqus-versus-Intense-Debate--Why-I-switched-/index.html @@ -0,0 +1,230 @@ + + + + + + + + + + + + + + + + + + + + + + + Disqus contre Intense Debate (pourquois j'ai changé) + + + + +
+ + +
+

+ Disqus contre Intense Debate (pourquois j'ai changé) +

+ +
+ +
+ + + + + +
+
+
+

Disqus vs. Intense Debate

+ +

J’ai écrit un article sur la façon dont j’ai essayé d’intégrer Disqus. Mon problème majeur avec Disqus c’était que ma page ne s’affichait pas correctement tant que les commentaire n’avait pas fini de s’afficher. Ça m’est arrivé plusieurs fois d’avoir ma page complètement bloquée parce que les serveurs de Disqus ne répondait pas. +C’est pourquoi j’ai essayer de l’inclure de manière asynchrone. Cependant j’ai eu des difficultés pour le faire fonctionner correctement.

+ +

De plus il n’a pas été trivial de faire en sorte que les commentaires soient commun à plusieurs pages différentes (chaque page à trois représentations différentes, une par language plus une version multi-langue).

+ +

Je dois reconnaître que je suis un peu triste de quitter Disqus parce que pour chacun de mes problèmes giannii m’a aidé du mieux qu’il a pu. Cependant les problèmes que j’ai eu étaient inhérents à des choix de conceptions plus que de simples petits problèmes techniques.

+ +

Lorsque j’ai commencé à intégrer Disqus je n’ai jamais essayé Intense Debate. Maintenant que j’ai essayé je doit dire que je suis conquis. Il correspond exactement à ce que j’espérais de ce type de service.

+ +

Pour le rendre complètement asynchrone il suffit de récupérer leur js commun et de remplacer la ligne suivante :

+ +
+
+document.getElementsByTagName("head")[0].appendChild(commentScript);
+
+
+ +

par (si vous utilisez jQuery) :

+ +
+
+$(document).ready( function() {
+    document.getElementsByTagName("head")[0].appendChild(commentScript);
+});
+
+
+ +

And the Winner is: Intense Debate

+ +

Pour conclure les avantages majeurs (pour moi) d’Intense Debate par rapport à Disqus:

+ +
    +
  • Se charge de façon asynchrone ; ne bloque pas mon site web
  • +
  • Permet d’ajouter sans rien de plus des boutons comme “share to any” et les charge eux aussi de façon asynchrone.
  • +
+ +

Voilà.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Écrit le : 28/09/2009 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2009-09-jQuery-Tag-Cloud/index.html b/output/n3blog/fr/blog/2009-09-jQuery-Tag-Cloud/index.html new file mode 100644 index 000000000..ef69652e1 --- /dev/null +++ b/output/n3blog/fr/blog/2009-09-jQuery-Tag-Cloud/index.html @@ -0,0 +1,2027 @@ + + + + + + + + + + + + + + + + + + + + + + + jQuery Tag Cloud [en] + + + + +
+ + +
+

+ jQuery Tag Cloud [en] +

+ +
+ +
+ + + + + +
+
+
+

Here is how I done the tag cloud of my blog. It is done mostly in jQuery. +All my site is static and pages are generated with nanoc. +It is (in my humble opinion) the modern geek way to make a website.

+ +

This is why I’ll give only a Ruby Generator, not a full javascript generator. +But you can easily translate from Ruby to Javascript.

+ +

Here is what you should obtain:

+ + +
+ +
+ + +
+

analyser

analytics

Apple

arbre

asynchrone

awk

Bazaar

blacklist

blog

branch

branches

bzr

cacher

Cappuccino

Chrome

Cocoa

commentaires

courriel

CSS

David Lynch

DCVS

dcvs

design

disqus

drm

email

expressions régulières

extension

fichier

film

filter

Firefox

Fonts

git

Google

HTML

indecidability

intense debate

iPhone

iTunes

javascript

jQuery

langues

Linux

local

Lost Highway

Mac

mac

mathématiques

mobileme

nanoc

Objective-C

OS X

philosophy

programmation

Programmation

programming

protection

regexp

regular expression

remote

ruby

Réalité alternée

S/MIME

Safari

science

screensaver

script

securité

shell

ssh

statistiques

svn

synchronisation

théorie

tip

Ubuntu

utilisateur

web

WebDav

webdesign

workflow

zsh

+
+ + +
+ +
+ + +

jQuery

+ +

Here is the simple jQuery code:

+ +
+
+    $(document).ready( function(){$('.list').hide();} );
+    function tagSelected(id) {
+        $('.list').hide();
+        $('#'+id).fadeIn();
+        $('.tag.selected').removeClass('selected');
+        $('#tag_'+id).addClass('selected');
+    }
+
+
+ +

This code will hide all the div containing links to articles containing the tag. And create a function do show the div containing the tag.

+ +

For each tag I create a span element:

+ +
+
+    <span   style="font-size: 1.0em;" 
+            class="tag" 
+            onClick="tagSelected('[TAG]')" 
+            id="tag_[TAG]">
+        [TAG]
+    </span> 
+
+
+ +

and a div containing links associtated to this tag:

+ +
+
+    <div id="[TAG]">
+        <h4>[TAG]</h4>
+        <ul>
+            <li> LINK 1 </li>
+            <li> LINK 2 </li>
+        </ul>
+    </div> 
+
+
+ + +
+ +
+ + +

nanoc

+ +

Here is how I generate this using nanoc 2.

+ +

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.

+ +
+
+def tags
+    return @page.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
+def tagNumber
+    tags={}
+    @pages.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 ... ]
+def tagRefs
+    tagLinks={}
+    @pages.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 +of the maximal size.

+ +
+
+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
+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 '&nbsp;'
+        protected=t.gsub(/&/,'&amp;').gsub(/ /,'&nbsp;').gsub(/</,'&lt;').gsub(/>/,'&gt;')
+        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
+
+
+ +

You can download the complete file to put in your ‘lib’ directory. Beware, it is a nanoc 2 version, you’ll have to make some small changes like replace @pages by @items to be nanoc3 compatible.

+ +

Of course to be nice you need the associated CSS

+ +
+
+
+// Change the color when mouse over
+.tag:hover {
+  color: #cc0000; }
+
+// Change the color when tag selected
+.tag.selected {
+  color: #6c0000; }
+
+// a bit of space and pointer cursor
+.tag {
+  cursor: pointer;
+  margin-left: .5em;
+  margin-right: .5em; }
+
+
+ +

That’s all folks.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 23/09/2009 + modifié le : 17/06/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2009-09-replace-all-except-some-part/index.html b/output/n3blog/fr/blog/2009-09-replace-all-except-some-part/index.html new file mode 100644 index 000000000..863528a47 --- /dev/null +++ b/output/n3blog/fr/blog/2009-09-replace-all-except-some-part/index.html @@ -0,0 +1,271 @@ + + + + + + + + + + + + + + + + + + + + + + + Remplacer tout sauf une partie + + + + +
+ + +
+

+ Remplacer tout sauf une partie +

+ +
+ +
+ + + + + +
+
+
+

My problem is simple:

+ +

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
+...
+text
+...
+END not to filter
+...
+text
+...
+
+
+ +

I searched a better way to do that, but the best I can do is using split and scan.

+ +
+
+def allExceptCode( f, content )
+    regexp=/<code[^>]*>.*?<\/code>/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
+
+
+ +

An usage is:

+ +
+
+def filter(content)
+    content.gsub(/e/,'X')
+end
+...
+allExceptCode(:filter, content)
+...
+
+
+ +

A better syntax would be:

+ +
+
+# !!!!!!!!!! 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
+
+
+ +

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.

+ +

If someone know a nicer way to do that I will be happy to know how.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 22/09/2009 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/code/publish b/output/n3blog/fr/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/code/publish new file mode 100644 index 000000000..b68d650fc --- /dev/null +++ b/output/n3blog/fr/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/code/publish @@ -0,0 +1,122 @@ + +#!/usr/bin/env zsh + +# 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 + +# 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" + rsyncPublish + swap + 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 + swap + fi + fi +} + +# 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 + ((essai++)) + done +} + +# swap +function swap { + 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 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 -P -- " publication terminée" +} + +print -- "Root = $webroot" +print -- "Dest = $destRep" + +if [[ "$1" = "-s" ]]; then + swap +else + print -P "Copie de l'init" + \cp -f $webroot/n3blog/multi/index.html $webroot/index.html + + if [[ "$1" = "-d" ]]; then + suffix="" + else + suffix=".tmp" + fi + print -P -- "%BSync%b[${Root:t} => ${destRep:t}$suffix]" + incrementalPublish +fi diff --git a/output/n3blog/fr/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/code/webdav-framework b/output/n3blog/fr/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/code/webdav-framework new file mode 100644 index 000000000..f83af7601 --- /dev/null +++ b/output/n3blog/fr/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/code/webdav-framework @@ -0,0 +1,109 @@ + +#!/usr/bin/env zsh + +function samelineprint { + print -n -P -- "\r$*" +} + +# avec 1 essai par seconde: 300 = 5 minutes +maxessais=300 + +# try to create a directory until success +function trymkdir { + target="$1" + print -- mkdir -p $target + local essai=1 + while ! mkdir -p $target; do + samelineprint "Echec: essai n°$essai" + ((essai++)) + ((essai>maxessais)) && exit 5 + done + print +} + +# try to copy until success +function trycp { + 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" + ((essai++)) + ((essai>maxessais)) && exit 5 + done + print +} + +# try to remove until success +function tryrm { + 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" + ((essai++)) + ((essai>maxessais)) && exit 5 + done + essai=1 + while [[ -e $element ]]; do + samelineprint "rm reussi mais fichier source non disparu n°$essai" + sleep 1 + ((essai++)) + ((essai>maxessais)) && exit 5 + done + print +} + +# try to rename until success +function tryrename { + element="$1" + target="$2" + local essai=1 + while [[ -e $target ]]; do + samelineprint "Echec n°$essai le fichier $target existe déjà" + ((essai++)) + ((essai>maxessais)) && exit 5 + sleep 1 + done + print -- mv $element $target + while ! mv $element $target; do + samelineprint "Echec: essai n°$essai" + ((essai++)) + ((essai>maxessais)) && exit 4 + done + essai=1 + while [[ -e $element ]]; do + samelineprint "mv reussi mais fichier source non disparu n°$essai" + sleep 1 + ((essai++)) + ((essai>maxessais)) && exit 5 + done + print +} + +# try to move until success +function trymv { + element="$1" + target="$2" + local essai=1 + print -- mv $element $target + while ! mv $element $target; do + samelineprint "Echec: essai n°$essai" + ((essai++)) + ((essai>maxessais)) && exit 5 + done + essai=1 + while [[ -e $element ]]; do + samelineprint "mv reussi mais fichier source non disparu n°$essai" + sleep 1 + ((essai++)) + ((essai>maxessais)) && exit 5 + done + print +} diff --git a/output/n3blog/fr/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/index.html b/output/n3blog/fr/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/index.html new file mode 100644 index 000000000..33438e4a7 --- /dev/null +++ b/output/n3blog/fr/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/index.html @@ -0,0 +1,454 @@ + + + + + + + + + + + + + + + + + + + + + + + Synchronisation avec mobileme (2) + + + + +
+ + +
+

+ Synchronisation avec mobileme (2) +

+ +
+ +
+ + + + + +
+
+
+

J’ai déjà discuté de la façon dont je synchronise mon site web sur mobileme. J’ai amélioré mon script pour le rendre incrémental.

+ +

Voici mon script, il créé tout d’abord un fichier qui contient la liste des fichiers avec leur hash. Afin de les comparer avec ceux qui sont en ligne sans avoir à les parcourir. Ensuite pour chaque fichier qui semble différent, je met à jour le contenu.

+ +

Cependant même avec ce script j’ai encore des problèmes. Dû à webdav. En particulier le renommage de répertoire. Par exemple :

+ +
+mv folder folder2
+
+ +

Retourne OK et pourtant :

+ +
+$ ls 
+folder folder2
+
+ +

Bouuhh…

+ +

Pour résoudre ce type de problèmes j’utilise un framework en zsh. Il résout presque tous les problèmes liés à webdav à l’exception du renommage de répertoire.

+ +
+
+#!/usr/bin/env zsh
+
+function samelineprint {
+    print -n -P -- "\r$*"
+}
+
+# avec 1 essai par seconde: 300 = 5 minutes
+maxessais=300
+
+# try to create a directory until success
+function trymkdir {
+    target="$1"
+    print -- mkdir -p $target
+    local essai=1
+    while ! mkdir -p $target; do
+        samelineprint "Echec: essai n°$essai"
+        ((essai++))
+        ((essai>maxessais)) && exit 5
+    done
+    print
+}
+
+# try to copy until success
+function trycp {
+    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"
+        ((essai++))
+        ((essai>maxessais)) && exit 5
+    done
+    print
+}
+
+# try to remove until success
+function tryrm {
+    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"
+        ((essai++))
+        ((essai>maxessais)) && exit 5
+    done
+    essai=1
+    while [[ -e $element ]]; do
+        samelineprint "rm reussi mais fichier source non disparu n°$essai"
+        sleep 1
+        ((essai++))
+        ((essai>maxessais)) && exit 5
+    done
+    print
+}
+
+# try to rename until success
+function tryrename {
+    element="$1"
+    target="$2"
+    local essai=1
+    while [[ -e $target ]]; do
+        samelineprint "Echec n°$essai le fichier $target existe déjà"
+        ((essai++))
+        ((essai>maxessais)) && exit 5
+        sleep 1
+    done
+    print -- mv $element $target
+    while ! mv $element $target; do
+        samelineprint "Echec: essai n°$essai"
+        ((essai++))
+        ((essai>maxessais)) && exit 4
+    done
+    essai=1
+    while [[ -e $element ]]; do
+        samelineprint "mv reussi mais fichier source non disparu n°$essai"
+        sleep 1
+        ((essai++))
+        ((essai>maxessais)) && exit 5
+    done
+    print
+}
+
+# try to move until success
+function trymv {
+    element="$1"
+    target="$2"
+    local essai=1
+    print -- mv $element $target
+    while ! mv $element $target; do
+        samelineprint "Echec: essai n°$essai"
+        ((essai++))
+        ((essai>maxessais)) && exit 5
+    done
+    essai=1
+    while [[ -e $element ]]; do
+        samelineprint "mv reussi mais fichier source non disparu n°$essai"
+        sleep 1
+        ((essai++))
+        ((essai>maxessais)) && exit 5
+    done
+    print
+}
+
+
+ +

Et voici le code qui me permet de synchroniser mon site web. Il y a une partie un peu incompréhensible. C’est pour enlever les mail réencodés par le filtre bluecloth qui est une implémentation de markdown. Mes mails, sont encodés à chaque fois de façon différente à chaque réengendrement de page html. C’est pourquoi je les enlève pour ne pas les uploadés inutilement à chaque fois.

+ +
+
+#!/usr/bin/env zsh
+
+# 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
+
+# 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"
+        rsyncPublish
+        swap
+    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
+            swap
+        fi
+    fi
+}
+
+# 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
+        ((essai++))
+    done
+}
+
+# swap
+function swap {
+    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 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 -P -- "  publication terminée"
+}
+
+print -- "Root = $webroot"
+print -- "Dest = $destRep"
+
+if [[ "$1" = "-s" ]]; then
+    swap
+else 
+    print -P "Copie de l'init"
+    \cp -f $webroot/n3blog/multi/index.html $webroot/index.html
+
+    if [[ "$1" = "-d" ]]; then
+        suffix=""
+    else
+        suffix=".tmp"
+    fi
+    print -P -- "%BSync%b[${Root:t} => ${destRep:t}$suffix]"
+    incrementalPublish
+fi
+
+
+ +

C’est ma façon de remplacer rsync avec des filesystem qui ne permettent pas de l’utiliser. J’espère que ça pourra vous être utile. Je serai heureux de savoir si quelqu’un à une idée sur comment gérer le problème de renommage de répertoire avec webdav.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Écrit le : 28/10/2009 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2009-10-30-How-to-handle-evil-IE/code/ie.js b/output/n3blog/fr/blog/2009-10-30-How-to-handle-evil-IE/code/ie.js new file mode 100644 index 000000000..661daa2f2 --- /dev/null +++ b/output/n3blog/fr/blog/2009-10-30-How-to-handle-evil-IE/code/ie.js @@ -0,0 +1,18 @@ + +// 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; +}) ; + +// Append the CSS for IE only +$('head').append(''); + +// I also add a message on top of the page +$('body').prepend('

Avec Firefox et Safari cette page est bien plus jolie !This page is far nicer with Firefox and Safari!

.
'); + diff --git a/output/n3blog/fr/blog/2009-10-30-How-to-handle-evil-IE/index.html b/output/n3blog/fr/blog/2009-10-30-How-to-handle-evil-IE/index.html new file mode 100644 index 000000000..845c08c55 --- /dev/null +++ b/output/n3blog/fr/blog/2009-10-30-How-to-handle-evil-IE/index.html @@ -0,0 +1,225 @@ + + + + + + + + + + + + + + + + + + + + + + + Une CSS pour IE seulement + + + + +
+ + +
+

+ Une CSS pour IE seulement +

+ +
+ +
+ + + + + +
+
+
+

Pour les développeur de site web Internet Explorer est un cauchemar. C’est pourquoi j’utilise un style complètement différent pour ce navigateur. Avec la librairie jQuery.

+ +
+$(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;
+}) ;
+
+// 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>');
+
+
+
+ +

Voilà.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 30/10/2009 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2009-10-Focus-vs-Minimalism/index.html b/output/n3blog/fr/blog/2009-10-Focus-vs-Minimalism/index.html new file mode 100644 index 000000000..bc8add383 --- /dev/null +++ b/output/n3blog/fr/blog/2009-10-Focus-vs-Minimalism/index.html @@ -0,0 +1,267 @@ + + + + + + + + + + + + + + + + + + + + + + + <em>Focus</em> > Minimalisme + + + + +
+ + +
+

+ Focus > Minimalisme +

+ +

+ Cacher la navigation pour une meilleure concentration +

+ +
+ +
+ + + + + +
+
+
+

Je crois que le but du minimalisme est de facilité le Focus c’est-à-dire la concentration sur le contenu. Je crois que le minimalisme doit être un moyen et pas une fin. Le Focus devrait être le but, et je pense que le minimalisme n’est pas obligatoire pour l’atteindre.

+ +

C’est pourquoi mon design n’est pas minimaliste. Mais j’ai décidé d’enlever la majorité des objets servant à la navigation pour améliorer l’attention sur l’article. Peut-être que plus tard, je préfèrerai laisser le menu dans les pages normales du site pour ne le cacher que dans les articles de blog. +Pour l’instant je le cache partout.

+ + +
+ +
+ + +

Détails techniques

+ +

Pour ceux qui souhaitent connaître les détails techniques derrière le menu apparaissant/disparaissant, voici le code utilisant jQuery.

+ +

L’HTML :

+ +
+
+<div id="menuButton"></div>
+<div id="entete">#content of the menu</div>
+
+
+ +

La CSS :

+ +
+#menuButton {
+  font-size: 2em;
+  height: 2em;
+  line-height: 1.8em;
+  width: 2em;
+  position: fixed;
+  left: 0;
+  top: 0; 
+  z-index: 9001 }
+
+#menuButton:hover {
+  cursor: pointer; }
+
+#entete {
+  top: 5em;
+  left: 0;
+  position: fixed;
+  width: 10em;
+  z-index: 9000; }
+
+
+ +

Le code javascript (utilisant jQuery)

+ +
+
+function hideMenu() {
+    $('#entete').animate({left:"-10em"}, 500 );
+    $('#menuButton').html('&rarr;');
+}
+function showMenu() {
+    $('#entete').animate({left:"0em"}, 500 );
+    $('#menuButton').html('&larr;');
+}
+function toggleMenu() {
+    if ( $('#entete').css('left')=='-10em' ) {
+        showMenu();
+    } else {
+        hideMenu();
+    }
+}
+
+
+ +

Le résultat est visible dans le coin en haut à droite de cet article.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 22/10/2009 + modifié le : 17/06/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2009-10-How-to-preload-your-site-with-style/index.html b/output/n3blog/fr/blog/2009-10-How-to-preload-your-site-with-style/index.html new file mode 100644 index 000000000..5dc7c2b20 --- /dev/null +++ b/output/n3blog/fr/blog/2009-10-How-to-preload-your-site-with-style/index.html @@ -0,0 +1,272 @@ + + + + + + + + + + + + + + + + + + + + + + + Charger une page web avec style + + + + +
+ + +
+

+ Charger une page web avec style +

+ +
+ +
+ + + + + +
+
+
+

Exemple

+ +

Voici comment apparaissent mes pages pendant leur chargement.

+ +
+

Voilà ! Je suis chargée !

+

Cliquez-moi dessus pour recommencer.

+
+ Loading... + loading logo +
+ +
+ +

J’ai d’abord essayé d’intégrer queryLoader, mais il ne comblait pas mes besoins.

+ +

Ce plugin ajoutait un ‘div’ noir pour cacher le contenu du site. Cependant, comme le script doit être lancé à la fin du code source. Pendant un petit moment, on peut voir mon site en train de se mettre à jour.

+ +

Pour cacher ce petit ‘artefact’, voici comment je m’y suis pris.

+ +

Code

+ +

D’abort il faut ajouter tout en haut du body cette fois un div qui va être le voile noir qui va tout cacher.

+ +
+
+...
+<body>
+<div id="blackpage">
+    content to display during the loading.
+</div>
+...
+
+
+ +

et le CSS correspondant au div #blackpage :

+ +
+
+#blackpage
+  top: 0 
+  left: 0 
+  width: 100%
+  height: 100%
+  margin-left: 0
+  margin-right: 0
+  margin-top: 0
+  margin-bottom: 0
+  position: absolute
+  text-align: center
+  color: #666
+  padding-top: 10em
+  background-color: #eee
+  z-index: 9000
+
+
+ +

ainsi que le code jQuery associé :

+ +
+
+$(document).ready(function(){
+    $('#blackpage').fadeOut();
+});
+
+
+ +

Oui, c’est aussi simple que ça. Maintenant ajouter le #blackpage tout en haut de ma page me permet d’être certain de tout cacher pendant le chargement de la page.

+ +

J’espère que ça a pu vous être utile !

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 03/10/2009 + modifié le : 04/10/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2009-10-Wait-to-hide-a-menu-in-jQuery/index.html b/output/n3blog/fr/blog/2009-10-Wait-to-hide-a-menu-in-jQuery/index.html new file mode 100644 index 000000000..ee45adf94 --- /dev/null +++ b/output/n3blog/fr/blog/2009-10-Wait-to-hide-a-menu-in-jQuery/index.html @@ -0,0 +1,273 @@ + + + + + + + + + + + + + + + + + + + + + + + Un menu qui attends avant de se cacher + + + + +
+ + +
+

+ Un menu qui attends avant de se cacher +

+ +
+ +
+ + + + + +
+
+
+

J’ai déjà dit pourquoi je préférais que mon menu de navigation soit caché. J’ai finalement décidé d’attendre un peu avant de cacher le menu. Juste le temps que l’utilisateur le voit. Mais voilà. Comment faire pour qu’il ne disparaisse que lorsque l’on ne s’en sert pas pendant un petit moment ?

+ +

Voici la solution que j’utilise avec jQuery

+ +

HTML :

+ +
+
+    <div id="menuButton"></div>
+    <div id="entete">
+        <ul>
+            <li> menu item 1 </li>
+            ...
+            <li> menu item n </li>
+        </ul>
+    </div>
+
+
+ +

CSS :

+ +
+    #entete {
+      top: 1em;
+      left: 0;
+      position: fixed;
+      width: 10em;
+      z-index: 2000; }
+    
+    #entete {
+      top: 1em;
+      height: 22em;
+      left: 0;
+      position: fixed;
+      width: 10em; }
+
+ +

Javascript :

+ +
+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);
+
+    // 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
+
+// move to the left
+function hideMenu() { 
+    $('#entete').animate({left:"-10em"}, 500 ); 
+}
+
+// move to right and will try to hide in 5 sec.
+function showMenu() { 
+    $('#entete').animate({left:"0em"}, 500 );
+    last+=1;
+    autoHideMenu(last);
+}
+
+
+ +

Simple et peu gourmand en ressources. Pas de timer (ou presque), pas de fuite de mémoire, pas d’utilisation de date…

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Écrit le : 26/10/2009 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2009-10-launch-daemon-from-command-line/index.html b/output/n3blog/fr/blog/2009-10-launch-daemon-from-command-line/index.html new file mode 100644 index 000000000..d39c14baf --- /dev/null +++ b/output/n3blog/fr/blog/2009-10-launch-daemon-from-command-line/index.html @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + lancer un démon en ligne de commande + + + + +
+ + +
+

+ lancer un démon en ligne de commande +

+ +
+ +
+ + + + + +
+
+
+

Une petite astuce dont je ne me souvient jamais (je ne sais pas pourquoi).

+ +

Lorsque que vous souhaitez lancer une commande qui ne soit pas tuée après la fermeture du terminal voici comment s’y prendre :

+ +
+nohup cmd &
+
+cmd est la commande que vous souhaitez lancer. +
+ +

Je laisse cette astuce ici pour moi et dans l’espoir que ça pourra aussi être utile à quelqu’un d’autre.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 23/10/2009 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2009-10-untaught-git-usage/index.html b/output/n3blog/fr/blog/2009-10-untaught-git-usage/index.html new file mode 100644 index 000000000..50385ee5b --- /dev/null +++ b/output/n3blog/fr/blog/2009-10-untaught-git-usage/index.html @@ -0,0 +1,399 @@ + + + + + + + + + + + + + + + + + + + + + + + Usages non dits de Git + + + + +
+ + +
+

+ Usages non dits de Git +

+ +
+ +
+ + + + + +
+
+
+

Je décris pourquoi j’ai eu tant de mal à me faire à Git. Il y a en effet une partie “non dite” qui m’a bloqué pendant un bon moment. Jusqu’à ce que je découvre le bon document.

+ +

Le fait est que les branches légères ne sont pas destinée à être des branches isolées. Ainsi, il y a un “workflow standard” qui s’il n’est pas suivi rend l’utilisation de Git inappropriée.

+ + +
+ +
+ + +

La décentralisation en action

+ +

De SVN à Bazaar

+ +

J’étais un fervent utilisateur de subversion (svn). Lorsqu’un jour, comme beaucoup de gens je découvris ce qu’en pensais Linus Torvald sur une vidéo. Ventant les mérites d’un système de versions concurrentes décentralisé.

+ +

En effet une fois qu’on s’y intéresse un peu, on voit tous les avantages pratiques qu’apporteraient en théorie un tel système.

+ +

J’ai alors eu besoin d’un système de version dans mon équipe. +Ils n’étaient pas familier avec les systèmes de versions. À par ceux possédant une GUI, qui sont lourds et administrés par un responsable.

+ +

Après quelques recherches trois choix se dessinent :

+ + + +

En me renseignant un peu sur les forums et en essayant les trois, je me suis vite rendu compte que celui possédant l’interface utilisateur la plus simple était Bazaar*. Mon choix était fait.

+ +

De bazaar à Git

+ +

Je me suis alors familiarisé avec Bazaar. Et je dois dire que c’était vraiment naturel en venant de subversion. La commande pull correspond au update, la commande push correspond au commit. Puis les commandes commit et update existent toujours si on en a besoin et qu’on veut utiliser un workflow identique à celui de subversion.

+ +

Mais plus le temps passe et plus de partout sur les blog, c’est surtout Git qui a le vent en poupe.

+ +

Je décide alors d’utiliser Git en particulier pour versionner le site que vous êtes en train de lire. Sauf que je le trouve vraiment difficile d’utilisation et surtout complètement contre intuitif (j’y reviendrai plus tard).

+ +

Alors que j’essaye de trouver de l’aide et que je dis qu’il est plus difficile à utiliser que Bazaar, beaucoup me répliquent que c’est :

+ +
+

Super-tellement-trop-simple que même ma fille de 12 ans qui n’y comprend rien en informatique l’utilise pour versionner ses documents. Elle s’en sert très facilement en créant des branches et tout et tout…

+
+ +

Bon alors si une gamine 12 ans trouve ça très naturel et que moi (avec mon Doctorat en informatique) j’ai du mal à faire ce que je veux, c’est un peu frustrant et humiliant. Mais qu’est-ce qui fait que Git est naturel aux uns (comme pour CocoaSamurai ) et très confus pour moi ?

+ +

C’est en lisant un article j’ai enfin compris ce qu’il me manquait. C’est la partie non dite de la conception. Celle que tous les développeurs et les concepteurs trouvaient comme aller de soi. Sauf que pour moi, ce n’était pas du tout le cas.

+ +

- Je parle de ClearCase©. Et oui, je sais qu’il existe des commandes en lignes pour ClearCase©, mais ce n’est pas comme ça qu’ils étaient habitués à travailler avec des systèmes de “versionning”.

+ +

* - Je n’ai pas vraiment donné sa chance à Mercurial, la terminologie qu’ils utilisaient était trop éloignée de celle de svn à laquelle je m’étais habituée.

+ + +
+ +
+ + +

Lorsqu’on voit les présentations autour de la notion de branche et de dcvs, on s’imagine dans un monde où chaque branche est totalement isolée des autres sauf au moment de “merger” les différences les unes des autres. +Tout est magique. C’est la façon de voir “Mondes Parallèles”. Cette façon de voir est expliquée dans le très bon article sur les branches sur betterexplained.

+ +

Sauf que les concepteurs de Git (conçu pour le noyau Linux) ont plutôt imaginé un système basé non pas autour des mondes parallèles, mais sur la notion de Patch.

+ +

D’un côté Mondes Parallèles, de l’autre Patchs. Il y a beaucoup de notions équivalentes dans les deux cas, mais aussi quelques différences.

+ +
    +
  • Bazaar est complètement basé sur la notion de Mondes Parallèles qui va impliquer un phénomène de Patch.
  • +
  • Alors que Git est basé sur la notion de Patch qui va impliquer la création de Mondes Parallèles.
  • +
+ +

Je ne vais pas argumenté pour savoir si une façon de voir est meilleure que l’autre. Disons simplement que ma façon d’entrer dans l’explication des DCVS était par le biais des Mondes Parallèles alors que Git est conçut selon l’autre notion.

+ +

De la théorie à la pratique

+ +

Bien que je pense avoir bien compris les mécanismes conceptuels de Git, la mise en pratique posait problème. Et le point noir, celui qui m’empêchait de comprendre Git comme je le souhaitais était dû à la notion de branche légère.

+ +

Une branche légère qu’est-ce que c’est me demanderez-vous ? Si comme moi on vient de Bazaar, c’est une notion complètement nouvelle. Il s’agit simplement de la capacité de créer une nouvelle branche en réutilisant le répertoire dans lequel on se trouve.

+ +

En pratique pour changer de branche, il faut lancer une commande. Tous les fichiers locaux non modifiés depuis le dernier commit seront alors modifiés pour correspondre à la version de la branche.

+ +

En théorie, les branches légères sont des branches tout comme avec bazaar. D’ailleurs le mot utilisé n’est pas branche légère mais branche tout court.

+ +

Sauf que contrairement à une branche standard résidant dans son propre répertoire, une branche légère est destinée à n’être qu’un patch de la branche principale du répertoire dans lequel elle réside.

+ +

Bien entendu on pourra m’objecter que l’on peut tout à fait utiliser ces branches légères comme des branches normales. Mais elles n’ont pas été conçues pour ça. Et donc, en pratique, c’est gênant de les utiliser de la sorte.

+ +

Voici comment Git est censé être utilisé (pour plus de détails vous pouvez lire Git for Designers en anglais) :

+ +
    +
  • récupération ou création d’un “repository” central Le Grand Repository
  • +
  • Création d’un branche légère locale qui contient les différences qui vont devoir être “patché” dans LE GRAND REPOSITORY.
  • +
+ +

Voici comment n’est pas censé être utilisé Git :

+ +
    +
  • Récupération ou création d’un “repository” quelconque
  • +
  • Création d’un branche légère locale qui n’a pas pour vocation de mettre à jour le “repository” d’origine, mais de vivre sa vie de façon autonome et de récupérer les mises à jour des autres du “repository” d’origine.
  • +
+ +

En effet cette petite notion m’a empêché de fonctionner correctement.

+ +

En pratique

+ +

Maintenant que j’ai compris ça, je peux enfin comprendre pourquoi Git a tant de défenseurs qui continue de trouver que Git est meilleur que les autres.

+ +

La notion de branche légère est essentielle à Git et vraiment utile en pratique. Notamment pour la gestion de ce site. Par contre, elle m’empêche d’utiliser les branches comme je le souhaiterai.

+ +

Mais dans ce cas-là, je n’ai qu’à utiliser des clônes et pas des branches légères.

+ +

Des exemples

+ +

Je trouve toujours que les terminologies de bazaar sont plus claires et plus concises.

+ +
bzr revert
+
+ +

est quand même plus clair que

+ +
git reset --hard HEAD
+
+ +

De la même façon

+ +
bzr revert -r -3
+
+ +

je trouve ça mieux que

+ +
git reset --hard HEAD~3
+
+ +

Là ça va commencer à se compliquer. Si on veut revenir dans le temps sur toute l’arborescence, avec Git on utilise reset.

+ +
OK
+ +

Maintenant si je veux revenir dans le temps sur un seul fichier. Naturellement on se dit :

+ +
git reset --hard FILE
+
+ +
**ET BIEN NON !**
+ +

La solution c’est :

+ +
git checkout FILE
+
+ +

Quoi ? checkout !? Bon, d’accord, j’accepte, pourquoi pas après tout ? +En plus quand on est habitué à Bazaar c’est :

+ +
git revert FILE
+
+ +

Ce que je trouve quand même bien plus naturel.

+ +

Mais là où ça devient vraiment difficile de s’y faire c’est pour changer de branche.
+Avec Bazaar ça donne :

+ +
cd ../branch
+
+ +

Bon ok, il faut changer de répertoire, un répertoire par branche. Ça consomme de l’espace disque mais au moins on voit où on est. Avec Git voilà comment on change de branche (branche légère) :

+ +
git checkout branch
+
+ +

Alors là, on se dit “WTF?” ; en français : mais qu’est-ce que c’est que ça ? Je croyais que checkout c’était pour récupérer l’état d’un fichier ?

+ +

En fait le mot checkout sert à la fois à revenir en arrière sur un fichier (MAIS PAS TOUTE UNE ARBORESCENCE où là ça sera reset --hard) et à changer de branche !

+ +

Je trouve ça carrément contre nature. Même si c’est totalement justifié du point de vue théorique voir le très bon article (en anglais) Git for Computer Scientist. Du point de vue interface utilisateur, on peut difficilement faire pire. On dirait que les mots clés sont utilisés pour piéger l’utilisateur.

+ +
+
    +
  • — Alors, essaye de deviner ce qu’il va falloir écrire pour faire cette opération ?
  • +
  • — Perdu. Essaye encore, cherche sur Internet (blaireau).
  • +
  • — Non, c’est toujours pas bon, recommence (sale nul).
  • +
+
+ +

Bon alors, voilà, les défauts de Git. Mais, il a par contre beaucoup d’avantages. Une fois qu’on a compris le principe des branches légères. Tout devient plus clair. Même si en pratique, l’édition du fichier .git/config peut s’avérer un peu fastidieuse et surtout contre intuitive.

+ +

- Il faut aussi préciser qu’ayant travaillé sur les logiques multi-modales et en particulier sur les logiques temporelles (linéaires ou non), j’étais plus enclin à adhérer à cette vision des choses. “Ah mes premiers amours dans la recherche scientifique !”

+ + +
+ +
+ + +

Conclusion

+ +

DCVS vs. CVS ?

+ +

Est-ce que ça valait la peine d’utiliser un système de “versionning” décentralisé ? Indéniablement la réponse est oui. On peut très bien vivre avec des systèmes de versions centralisés, mais la souplesse apportée par la facilité de “merger” différentes branches. De travailler de façon autonomes sur différentes parties d’un projets sont vraiment des plus appréciables. J’aurai vraiment du mal à revenir en arrière.

+ +

Est-ce que Git est meilleurs que Bazaar ?

+ +

En terme de fonctionnalités je dirai que Git est meilleurs. +Par contre, je dois avouer qu’il s’agit d’un CVS qui s’est mis dans mes pattes. Or c’est exactement ce que je ne souhaitait pas lors de mon premier choix.

+ +

Je n’aurai pas dû avoir du mal à comprendre cette notion de branche légère qui doit être un patch sinon tu reçois des messages t’expliquant que tu es en retard. En réalité, Git différencie la notion d’arbre de la notion de branche. Ce qui n’est pas le cas dans Bazaar. Conceptuellement, c’est beaucoup plus simple de comprendre avec Bazaar.

+ +

Finalement ?

+ +

Pour conclure, j’utilise plus souvent Git que Bazaar et je dois dire que je préfère utiliser Git. Cependant, les commandes comme revert manquent cruellement avec Git. Pour l’instant je n’ai pas encore fait d’alias pour renommer les commandes Git comme je le souhaite.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 13/10/2009 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2009-11-12-Git-for-n00b/Git-pour-quoi-faire/index.html b/output/n3blog/fr/blog/2009-11-12-Git-for-n00b/Git-pour-quoi-faire/index.html new file mode 100644 index 000000000..366bc4b55 --- /dev/null +++ b/output/n3blog/fr/blog/2009-11-12-Git-for-n00b/Git-pour-quoi-faire/index.html @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + + + + + + + + Git pour les nuls + + + + +
+ + +
+

+ Git pour les nuls +

+ +

+ Git pour quoi faire ? +

+ +
+ +
+ + + + + +
+
+
+

Git pour quoi faire ?

+ + +
+ + +

Si tout ce qui vous intéresse c’est d’utiliser Git tout de suite. Lisez simplement les parties sur fond noir. Je vous conseille aussi de revenir relire tout ça un peu plus tard, pour mieux comprendre les fondements des systèmes de versions et ne pas faire de bêtises quand vous les utilisez.

+ + +
+ + +

Git est un DCVS, c’est-à-dire un système de versions concurrentes décentralisé. Analysons chaque partie de cette appellation compliquée.

+ +

Système de versions

+ +

Tout d’abord, les systèmes de versions gèrent des fichiers. +Quand on travaille avec des fichiers sans système de version voilà ce qui arrive souvent :

+ +

Lorsqu’on modifie un fichier un peu critique et qu’on a pas envie de perdre, on se retrouve souvent à le recopier sous un autre nom. Par exemple

+ +
$ cp fichier_important.c fichier_important.c.bak
+
+ +

Du coups, ce nouveau fichier joue le rôle de backup. Si on casse tout, on peut toujours écraser les modifications que nous avons faites. Évidemment le problème avec cette façon de faire c’est que ce n’est pas très professionnel. Et puis c’est un peu limité. Si on veut faire trois ou quatre modifications on se retrouve avec plein de fichiers. Parfois avec des nom bizarres comme :

+ +
+
+fichier_important.c.bak
+fichier_important.c.old
+fichier_important.c.Bakcup
+fichier_important.c.BAK.2009-11-14
+fichier_important.c.2009.11.14
+fichier_important.c.12112009
+old.fichier_important.c
+
+
+ +

Bon alors si on veut que ça marche il faut se fixer des conventions de nommage. Les fichiers prennent beaucoup de place alors que souvent il n’y a que quelques lignes différentes entre le fichier et son backup…

+ +

Heureusement les systèmes de version viennent à la rescousse.

+ +

Il suffit de signaler que l’on va faire une nouvelle version d’un fichier et le système de version se débrouille pour l’enregistrer quelque part où on pourra facilement le retrouver. Et en général, le système de version fait les choses bien. C’est-à-dire qu’il n’utilise que très peu d’espace disque pour faire ces backups.

+ +

Il fut un temps où les versions étaient gérées fichier par fichier. Je pense à CVS. Puis on s’est vite aperçu qu’un projet c’est un ensemble de fichiers cohérents. Et donc il ne suffit pas de pouvoir revenir en arrière par fichier, mais plutôt dans le temps. Les numéros de versions sont donc passé d’un numéro par fichier à un numéro par projet tout entier.

+ +

Ainsi on peut dire, «je veux revenir trois jours en arrière», et tous les fichiers se remettent à jour.

+ + +
+ + +

Qu’apportent les systèmes de versions ? (je n’ai pas tout mentionné)

+ +
    +
  • backup automatique de tous les fichiers: Revenir dans le temps. ;
  • +
  • donne la possibilité de voir les différences entre chaque version et les différences entre la version en cours et les modifications locales ;
  • +
  • permet de poser un tag sur certaines versions et ainsi pouvoir s’y référer facilement ;
  • +
  • permet d’avoir un historique des modifications. Car en général il est demandé aux utilisateurs d’ajouter un petit commentaire à chaque nouvelle version.
  • +
+ + +
+ + +

concurrentes

+ +

Les systèmes de versions sont déjà intéressants pour gérer ses projets personnels. Car ils permettent de mieux organiser celui-ci. De ne (presque) plus se poser de questions à propos des backups. Je dis presque parce qu’il faut quand même penser à protéger par backup son repository. Mais là où les systèmes de versions deviennent vraiment intéressants, c’est pour la gestion de projets à plusieurs.

+ +

Commençons par un exemple avec un projet fait par deux personnes ; Alex et Béatrice. +Sur un fichier contenant une liste de dieux Lovecraftiens :

+ +
+
+Cthulhu
+Shubniggurath
+Yogsototh
+
+ +

Disons que Alex est chez lui, il modifie le fichier :

+ +
+
+Cthulhu
+Shubniggurath
+Soggoth
+Yogsototh
+
+
+ +

puis il envoi ce fichier sur le serveur du projet. Ainsi sur le serveur, il y a le fichier d’Alex.

+ +

Ensuite c’est Béatrice qui n’a pas récupéré le fichier d’Alex sur le serveur qui fait une modification.

+ +
+
+Cthulhu
+Dagon
+Shubniggurath
+Yogsototh
+
+
+ +

Puis Béatrice envoi son fichier sur le serveur.

+ +

La modification d’Alex est perdue. Encore une fois les systèmes de versions sont là pour résoudre ce type de soucis.

+ +

Un système de version aurait mergé les deux fichiers au moment où Béatrice voulait envoyer la modification sur le serveur. Et comme par magie, sur le serveur le fichier deviendra :

+ +
+
+Cthulhu
+Dagon
+Shubniggurath
+Soggoth
+Yogsototh
+
+
+ +

En pratique, au moment où Béatrice veut envoyer ses modifications, le système de version la préviens qu’une modification a eu lieu sur le serveur. Elle utilise la commande qui rapatrie les modifications localement et qui va mettre à jour le fichier. Ensuite Béatrice renvoie le nouveau fichier sur le serveur.

+ + +
+ + +

Qu’apportent les Systèmes de Versions Concurrentes ?

+ +
    +
  • récupérer sans problème les modifications des autres ;
  • +
  • envoyer sans problème ses modifications aux autres ;
  • +
  • permet de gérer les conflits. Je n’en ai pas parlé, mais quand un conflit arrive (ça peut arriver si deux personnes modifient la même ligne avec deux contenus différents), les SVC proposent leur aide pour les résoudre. J’en dirai un mot plus loin.
  • +
  • permet de savoir qui a fait quoi et quand
  • +
+ + +
+ + +

décentralisé

+ +

Ce mot n’est devenu populaire que très récemment dans le milieu des systèmes de version. Et bien ça veut dire principalement deux choses.

+ +

Tout d’abord, jusqu’à très récemment (SVN) il fallait être connecté sur un serveur distant pour avoir des informations sur un projet. Comme avoir l’historique. Les nouveaux systèmes décentralisés permettent de travailler avec un REPOSITORY (le répertoire contenant tous les backups, et les différentes info nécessaires au fonctionnement du système de versions) local au projet. Ainsi on peut avoir l’historique du projet sans avoir à se connecter au serveur.

+ +

Toutes les instances de projets peuvent vivre de façon indépendantes.

+ +

Pour préciser, les systèmes de versions concurrentes décentralisés sont basés sur la notion de branche.

+ +

Et la signification pratique est très importante. Ça veut dire que tout les utilisateurs travaillent de façon complètement indépendante les uns des autres. Et c’est l’outil de version qui se charge de mettre tout ça ensemble.

+ +

Ça va même encore plus loin. Ça permet de développer plusieurs features de manière complètement indépendantes. Sous les autres systèmes c’était plus difficile.

+ +

L’exemple type :

+ +
+

Je développe mon projet. Je suis en train de l’améliorer. Lorsqu’un bug urgent est reporté.

+ +

Je peux très facilement avec un système décentralisé, revenir sur la version qui pose problème. Résoudre le bug. Renvoyer les modifications. Puis revenir à ma version avec les améliorations en cours. Et même récupérer la correction de bug dans ma nouvelle version avec les améliorations.

+ +

Dans un système non décentralisé, cela est possible, mais fastidieux. Les systèmes décentralisés rendent ce type de comportement très naturels. Ainsi, il devient naturel de tirer des branches pour toutes les features, les bug…

+
+ + +
+ + +

**Avantages donnés par la décentralisation des systèmes de versions concurrentes : **

+ +
    +
  • Possibilité de travailler sans être connecté au serveur de version ;
  • +
  • Possibilité de créer beaucoup de patches atomiques ;
  • +
  • Grande facilité de maintenance de plusieurs versions différentes de la même application.
  • +
+ + +
+ + +

Pour résumer

+ +

Résumons l’ensemble des choses que l’on peut faire facilement avec un DCVS :

+ +

Systèmes de versions

+ +
    +
  • revenir dans le temps ;
  • +
  • lister les différences entre chaque version ;
  • +
  • nommer certaines versions pour s’y référer facilement ;
  • +
  • afficher l’historique des modifications.
  • +
+ +

Concurrentes

+ +
    +
  • récupérer les modifications des autres ;
  • +
  • envoyer ses modifications aux autres ;
  • +
  • permet de savoir qui a fait quoi et quand ;
  • +
  • gestion des conflits.
  • +
+ +

Décentralisé

+ +
    +
  • manipuler facilement des branches
  • +
+ +

Maintenant voyons comment obtenir toutes ces choses facilement avec Git.

+ + +
+ + + +
+ + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 12/11/2009 + modifié le : 21/12/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2009-11-12-Git-for-n00b/c-est-parti-pour-l-aventure/index.html b/output/n3blog/fr/blog/2009-11-12-Git-for-n00b/c-est-parti-pour-l-aventure/index.html new file mode 100644 index 000000000..ac3bd4522 --- /dev/null +++ b/output/n3blog/fr/blog/2009-11-12-Git-for-n00b/c-est-parti-pour-l-aventure/index.html @@ -0,0 +1,302 @@ + + + + + + + + + + + + + + + + + + + + + Git pour les nuls + + + + +
+ + +
+

+ Git pour les nuls +

+ +

+ Utiliser git avec quelques commandes simples +

+ +
+ +
+ + + + + +
+
+
+

Et c’est parti !

+ +

Voici une parmi de nombreuses autres façon d’utiliser Git. Cette méthode est nécessaire et suffisante pour travailler seul ou en collaboration sur un projet commun. Cependant, on peut faire beaucoup mieux avec Git que ce workflow (en langage anglo-saxon).

+ +

Utilisation basique

+ +

La façon immédiate de travailler avec Git :

+ +
    +
  • récupérer les modifications des autres git pull
  • +
  • voir les détails de ces modifications git log
  • +
  • Plusieurs fois: +
      +
    • Faire une modification atomique
    • +
    • verifier le details de ses modifications git status et git diff
    • +
    • indiquer si nécessaire que de nouveaux fichiers doivent être versionnés git add [file]
    • +
    • enregistrer ses modifications
      git commit -a -m "message"
    • +
    • envoyer ses modifications aux autres git push (refaire un git pull si le push renvoie une erreur).
    • +
    +
  • +
+ +

Voilà, avec ces quelques commandes vous pouvez utiliser Git sur un projet avec d’autres personnes. Même si c’est suffisant, il faut quand même connaître une chose avant de se lancer ; la gestion des conflits.

+ +

Gestion des conflits

+ +

Les conflits peuvent survenir lorsque vous modifiez les même lignes de codes sur le même fichier d’une autre branche que vous mergez. Ça peut sembler un peu intimidant, mais avec Git ce genre de chose est très facile a régler.

+ +

exemple

+ +

Vous partez du fichier suivant :

+ +
+
+Zoot 
+
+
+ +

et vous modifiez une ligne

+ +
+
+Zoot the pure
+
+
+ +

sauf que pendant ce temps, un autre utilisateur a aussi modifié cette ligne et a fait un push de sa modification.

+ +
+
+Zoot, just Zoot
+
+
+ +

Maintenant quand vous lancez la commande

+ +
+
+$ git pull
+remote: Counting objects: 5, done.
+remote: Total 3 (delta 0), reused 0 (delta 0)
+Unpacking objects: 100% (3/3), done.
+From /home/e640846/tmp/conflictTest
+   d3ea395..2dc7ffb  master     -> origin/master
+Auto-merging foo
+CONFLICT (content): Merge conflict in foo
+Automatic merge failed; fix conflicts and then commit the result.
+
+
+ +

Notre fichier foo contient alors :

+ +
+
+<<<<<<< HEAD:foo
+Zoot the pure
+=======
+Zoot, just Zoot
+>>>>>>> 2dc7ffb0f186a407a1814d1a62684342cd54e7d6:foo
+
+
+ +

Résolution du conflit

+ +

Régler le conflit, il suffit d’éditer le fichier, par exemple en écrivant :

+ +
+
+Zoot the not so pure
+
+
+ +

et de ‘commiter’ tout simplement :

+ +
+
+git commit -a -m "conflict resolved"
+
+
+ +

Maintenant vous êtes fin prêt pour utiliser Git. +Sauf que Git, c’est un outil qui permet de faire beaucoup plus que juste ça. Nous allons maintenant voir comment utiliser les fonctionnalités de Git qui n’étaient pas disponibles avec CVS et consorts.

+ + +
+ + + +
+ + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 12/11/2009 + modifié le : 21/12/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2009-11-12-Git-for-n00b/commandes-avancees/index.html b/output/n3blog/fr/blog/2009-11-12-Git-for-n00b/commandes-avancees/index.html new file mode 100644 index 000000000..1fbb1299b --- /dev/null +++ b/output/n3blog/fr/blog/2009-11-12-Git-for-n00b/commandes-avancees/index.html @@ -0,0 +1,330 @@ + + + + + + + + + + + + + + + + + + + + + + + Git pour les nuls + + + + +
+ + +
+

+ Git pour les nuls +

+ +

+ Liste de commandes +

+ +
+ +
+ + + + + +
+
+
+

Liste de commandes

+ +

Les commandes pour chaque choses

+ +

Dans la première partie, nous avons vu la liste des problèmes résolus par Git. En résumé Git doit pouvoir :

+ +
    +
  • récupérer les modifications des autres ;
  • +
  • envoyer ses modifications aux autres ;
  • +
  • revenir dans le temps ;
  • +
  • lister les différences entre chaque version ;
  • +
  • nommer certaines versions pour s’y référer facilement ;
  • +
  • afficher l’historique des modifications ;
  • +
  • savoir qui a fait quoi et quand ;
  • +
  • gérer des conflits ;
  • +
  • manipuler facilement des branches.
  • +
+ +

récupérer les modifications des autres

+ +
+$ git pull
+
+ +

envoyer ses modifications aux autres

+ +
+$ git push
+
+ +

ou plus généralement

+ +
+$ git pull
+$ git push
+
+ +

revenir dans le temps

+ +

Pour toute l’arborescence

+ +
+$ git checkout
+
+ +
+$ git revert
+
+ +

revenir trois versions en arrière

+ +
+$ git uncommit 3
+
+ +

Revenir avant le dernier merge (s’il s’est mal passé).

+ +
+$ git revertbeforemerge
+
+ +

Pour un seul fichier

+ +
+$ git checkout file
+$ git checkout VersionHash file
+$ git checkout HEAD~3 file
+
+ +

lister les différences entre chaque version

+ +

liste les fichiers en cours de modifications

+ +
+$ git status
+
+ +

différences entre les fichiers de la dernière version et les fichiers locaux.

+ +
+$ git diff
+
+ +

liste les différences entre les fichier d’une certaine version et les fichiers locaux.

+ +
+$ git diff VersionHash fichier
+
+ +

nommer certaines versions pour s’y référer facilement

+ +
+$ git tag 'toto'
+
+ +

afficher l’historique des modifications

+ +
+$ git log
+$ git lg
+$ git logfull
+
+ +

savoir qui a fait quoi et quand

+ +
+$ git blame fichier
+
+ +

gérer des conflits

+ +
+$ git conflict
+
+ +

manipuler facilement des branches

+ +

Pour créer une branche :

+ +
+$ git branch branch_name
+
+ +

Pour changer de branche courante :

+ +
+$ git checkout branch_name
+
+ + +
+ + + +
+ + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 12/11/2009 + modifié le : 21/12/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2009-11-12-Git-for-n00b/comprendre/index.html b/output/n3blog/fr/blog/2009-11-12-Git-for-n00b/comprendre/index.html new file mode 100644 index 000000000..367f921c4 --- /dev/null +++ b/output/n3blog/fr/blog/2009-11-12-Git-for-n00b/comprendre/index.html @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + Git pour les nuls + + + + +
+ + +
+

+ Git pour les nuls +

+ +

+ Comprendre +

+ +
+ +
+ + + + + +
+
+
+

Pourquoi Git est cool ?

+ +

Parce que grace à Git vous pouvez travailler sur plusieurs partie du projet de façon complètement isolée les unes des autres. Ça c’est la partie décentralisée de Git.

+ +

Toutes les branches locales utilisent le même répertoire. Ainsi on peu changer de branche très aisément et rapidement. On peut aussi changer de branche alors que certains fichier sont en cours de modifications. On peut même pousser le vice jusqu’à modifier un fichier, changer de branche, commiter une partie seulement des modifications de ce fichier dans la branche courante. Revenir dans l’ancienne branche et commiter à nouveau les modifications restantes. Et merger dans une troisième branche les deux modifications.

+ +

Avec la command git rebase on peut après coup, décider que certaines modifications devaient aller dans certaines branches, que d’autres ne servaient à rien. C’est une commande vraiment très puissante pour organiser l’historique.

+ +

En pratique, qu’est-ce que ça signifie ? Mieux qu’avec tous les autres systèmes de versions, vous pouvez utiliser Git pour vous concentrer sur votre code. En effet, on peut envoyer les commits après avoir coder. Par exemple, vous pouvez coder sur la résolution du bug b01, du bug b02 et de la feature f03. Puis ensuite, vous pouvez créer une branche par bug et par feature. Puis commiter les modifications pour chaque branche et chaque feature. Puis finalement merger tous les modifications dans la branche principale.

+ +

Tout a été pensé pour vous permettre de coder d’abord, puis de vous occuper du système de version plus tard. Bien entendu, faire des commit atomique au fur et à mesure du code permet de gagner du temps et de ne pas trop s’embêter pour organiser les branches. Mais rien ne vous y oblige. Par contre faire la même chose dans d’autres systèmes de versions n’est absolument pas naturel.

+ +

Avec Git vous pouvez aussi dépendre de plusieurs sources. Ainsi, plutôt que d’avoir un serveur centralisé, vous pouvez avoir plusieurs sources. Vous pouvez définir ce genre de chose très finement.

+ +

Ce qui change le plus avec Git c’est la vision d’un projet centralisé sur un serveur avec plusieurs personnes qui travaillent dessus. Avec Git plusieurs personnes peuvent travailler sur le même projet, mais sans nécessairement avoir un repository de référence. On peut très facilement résoudre un bug et envoyer le patch à plein d’autres versions du projet.

+ + +
+ + + +
+ + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 12/11/2009 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2009-11-12-Git-for-n00b/conf-et-install/code/gitconfig b/output/n3blog/fr/blog/2009-11-12-Git-for-n00b/conf-et-install/code/gitconfig new file mode 100644 index 000000000..25bcf85ce --- /dev/null +++ b/output/n3blog/fr/blog/2009-11-12-Git-for-n00b/conf-et-install/code/gitconfig @@ -0,0 +1,20 @@ + +[color] + branch = auto + diff = auto + status = auto +[alias] + st = status + co = checkout + br = branch + 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\""' + 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 +[branch] + autosetupmerge = true diff --git a/output/n3blog/fr/blog/2009-11-12-Git-for-n00b/conf-et-install/index.html b/output/n3blog/fr/blog/2009-11-12-Git-for-n00b/conf-et-install/index.html new file mode 100644 index 000000000..724a52ffa --- /dev/null +++ b/output/n3blog/fr/blog/2009-11-12-Git-for-n00b/conf-et-install/index.html @@ -0,0 +1,335 @@ + + + + + + + + + + + + + + + + + + + + + Git pour les nuls + + + + +
+ + +
+

+ Git pour les nuls +

+ +

+ Avant l'utilisation, la configuration +

+ +
+ +
+ + + + + +
+
+
+

Avant l’utilisation, la configuration

+ +

installation

+ +

Sous Linux Ubuntu ou Debian :

+ +
$ sudo apt-get install git
+
+ +

Sous Mac OS X :

+ + + +
+$ sudo port selfupdate
+
+$ sudo port install git-core
+
+ +

Configuration globale

+ +

Enregistrez le fichier suivant comme le fichier ~/.gitconfig.

+ +
+
+[color]
+    branch = auto
+    diff   = auto
+    status = auto
+[alias]
+    st        = status
+    co        = checkout
+    br        = branch
+    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\""'
+    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
+[branch]
+	autosetupmerge = true
+
+
+ +

Vous pouvez obtenir le même résultat en utilisant pour chaque entrée la commande git config --global. +Configurez ensuite votre nom et votre email. Par exemple si vous vous appelez John Doe et que votre email est john.doe@email.com. Lancez les commandes suivantes :

+ +
+$ git config --global user.name John Doe
+
+$ git config --global user.email john.doe@email.com
+
+ +

Voilà, la configuration de base est terminée. J’ai créé dans le fichier de configuration global des alias qui vont permettre de taper des commandes un peu plus courtes.

+ +

Récupération d’un projet déjà versionné

+ +

Si un projet est déjà versionné avec Git vous devez avoir une URL pointant vers les sources du projet. La commande a exécuter est alors très simple.

+ +
+$ cd ~/Projets
+$ git clone git://main.server/path/to/file
+
+ +

S’il n’y a pas de serveur git sur le serveur distant, mais que vous avez un accès ssh, il suffit de remplacer le git de l’url par ssh. Pour ne pas avoir à entrer votre mot de passe à chaque fois le plus simple est de procéder comme suit :

+ +
+$ ssh-keygen -t rsa
+
+ +

Répondez aux question et n’entrez surtout PAS de mot de passe. Ensuite copiez les clés sur le serveur distant. Ce n’est pas la façon la plus sûre de procéder. L’idéal étant d’écrire quand même un mot de passe et d’utiliser ssh-agent.

+ +

Ensuite le plus simple, si vous possédez ssh-copy-id (sous Ubuntu par exemple) :

+ +
+me@locahost$ ssh-copy-id -i ~/.ssh/id_rsa.pub me@main.server
+
+ +

ou manuellement :

+ +
+me@locahost$ scp ~/.ssh/id_rsa.pub me@main.server:
+me@locahost$ ssh me@main.server
+password:
+me@main.server$ cat id_rsa.pub >> ~/.ssh/authorized_keys
+me@main.server$ rm id_rsa.pub
+me@main.server$ logout
+
+ +

Maintenant vous n’avez plus besoin de taper votre mot de passe pour accéder à main.server. Et donc aussi pour les commandes git.

+ +

Créer un nouveau projet

+ +

Supposons que vous avez déjà un projet avec des fichiers. Alors il est très facile de le versionner.

+ +
+$ cd /path/to/project
+$ git init
+$ git add .
+$ git commit -m "Initial commit"
+
+ +

Une petite précision. Si vous ne souhaitez pas versionner tous les fichiers. Par exemple, les fichiers de compilations intermédiaires. Alors il faut les exclure. Pour cela, avant de lancer la commande git add .. Il faut créer un fichier .gitignore qui va contenir les pattern que git doit ignorer. Par exemple :

+ +
+*.o
+*.bak
+*.swp
+*~
+
+ +

Maintenant si vous voulez créer un repository sur un serveur distant, il faut absolument qu’il soit en mode bare. C’est-à-dire que le repository ne contiendra que la partie contenant les informations utile à la gestion de git, mais pas les fichiers du projet. Sans rentrer dans les détails, il suffit de lancer :

+ +
+$ cd /path/to/local/project
+$ git clone --bare . ssh://server/path/to/project
+
+ +

Les autres pourront alors récupérer les modifications via la commande vue précédemment :

+ +
+git clone ssh://server/path/to/project
+
+ +

Résumé de la seconde étape

+ +

Vous avez maintenant un répertoire sur votre ordinateur local. Il est versionné. Vous pouvez vous en rendre compte parcequ’à la racine (et à la racine seulement), il y a un répertoire .git. Ce répertoire contient tous les fichiers nécessaires au bon fonctionnement de Git.

+ +

Il ne reste plus qu’à savoir comment s’en servir maintenant pour obtenir toutes les jolies promesses faites dans la première partie.

+ + +
+ + + +
+ + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 12/11/2009 + modifié le : 21/12/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2009-11-12-Git-for-n00b/index.html b/output/n3blog/fr/blog/2009-11-12-Git-for-n00b/index.html new file mode 100644 index 000000000..835c7e0b8 --- /dev/null +++ b/output/n3blog/fr/blog/2009-11-12-Git-for-n00b/index.html @@ -0,0 +1,255 @@ + + + + + + + + + + + + + + + + + + + + + + + Git pour les nuls + + + + +
+ + +
+

+ Git pour les nuls +

+ +

+ la conlusion pour commencer +

+ +
+ +
+ + + + + +
+
+
+ +
+ + +

Voici un tutoriel Git détaillé pour ceux qui en connaissent très peu sur les systèmes de versions. Vous comprendrez l’utilité de tels systèmes et surtout comment on se sert des systèmes de versions modernes, le tout en restant le plus pragmatique possible.

+ + +
+ + + +
+ +
+ + +

Pour commencer, la conclusion

+ +

Voici la liste des commandes nécessaires et suffisantes pour utiliser Git. Il y en a très peu. Il est normal de ne pas les comprendre tout de suite mais c’est pour vous donner une idée. Malgré la longueur de l’article, 95% de l’utilisation de Git tiens dans les 7 commandes décrites ci-après.

+ +

Récupérer un projet :

+ +
+git clone ssh://server/path/to/project
+
+ +

Utiliser Git tous les jours :

+ +
+# get modifications from other
+git pull
+# read what was done
+git log
+
+# Make local changes to files 
+hack, hack, hack...
+# list the modified files
+git status
+# show what I've done
+git diff
+
+# 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"
+
+# send local modifications to other
+git push
+
+ +

Cet article est écrit pour ceux qui en savent très peu sur les systèmes de version. Il est aussi écrit pour ceux qui n’ont pas suivi les progrès accomplis depuis CVS ou subversion (SVN). C’est pourquoi, dans un premier temps, j’explique rapidement quels sont les buts poursuivis par les systèmes de versions. J’explique ensuite comment installer et configurer Git. Puis, pour chaque action que doivent accomplir les DCVS je donne les commandes Git qui y correspondent.

+ + +
+ + + +
+ + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 12/11/2009 + modifié le : 21/12/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2009-12-06-iphone-call-filter/index.html b/output/n3blog/fr/blog/2009-12-06-iphone-call-filter/index.html new file mode 100644 index 000000000..594144adc --- /dev/null +++ b/output/n3blog/fr/blog/2009-12-06-iphone-call-filter/index.html @@ -0,0 +1,194 @@ + + + + + + + + + + + + + + + + + + + + + + + Filtrage d'appel avec l'iPhone + + + + +
+ + +
+

+ Filtrage d'appel avec l'iPhone +

+ +
+ +
+ + + + + +
+
+
+

Il est vraiment incroyable que le filtrage d’appel soit impossible avec un iPhone ! Le seul intérêt que j’y vois, c’est une négociation avec les opérateurs pour interdire aux utilisateurs de passer à travers la publicité. C’est tout simplement inacceptable.

+ +

Je suis un utilisateur λ de l’iPhone. Le seul moyen de filtrer ses appels, de faire des blacklists ou autre c’est de jailbreaker son iPhone. Et je n’en ai aucune envie. Alors si comme moi, vous trouvez ça inacceptable, envoyez un mot à Apple : http://www.apple.com/feedback/iphone.html

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ +
+ +
+
+ +
+ + +
+ +
+ Écrit le : 06/12/2009 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2009-12-14-Git-vs--Bzr/code/gitconfig b/output/n3blog/fr/blog/2009-12-14-Git-vs--Bzr/code/gitconfig new file mode 100644 index 000000000..85a89236f --- /dev/null +++ b/output/n3blog/fr/blog/2009-12-14-Git-vs--Bzr/code/gitconfig @@ -0,0 +1,3 @@ + +[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\""' diff --git a/output/n3blog/fr/blog/2009-12-14-Git-vs--Bzr/index.html b/output/n3blog/fr/blog/2009-12-14-Git-vs--Bzr/index.html new file mode 100644 index 000000000..2a6767ddf --- /dev/null +++ b/output/n3blog/fr/blog/2009-12-14-Git-vs--Bzr/index.html @@ -0,0 +1,333 @@ + + + + + + + + + + + + + + + + + + + + + + + Git ou Bazaar ? + + + + +
+ + +
+

+ Git ou Bazaar ? +

+ +

+ Pourquoi je suis passé de Bazaar à Git +

+ +
+ +
+ + + + + +
+
+
+ +
+ + +

Même si je considère que git a beaucoup de points noirs, je pense qu’il reste le meilleur DCVS à ce jour avec lequel travailler. C’est pourquoi je commencerai par parler des qualité de bazaar qui manquent à git. Ensuite seulement je donnerai le seul avantage de git qui suffit à le rendre préférable à Bazaar.

+ + +
+ + +

La découverte des DCVS

+ +

À savoir avant de débuter l’article. Je suis, comme beaucoup, un ancien utilisateur de subversion. Je trouve subversion très bien, mais j’ai été conquis par les capacités supplémentaires apportées par les systèmes de versions concurrentes décentralisés.

+ +

Il y a deux façon de percevoir les systèmes de versions. Soit on voit un système de branches (voir le très bon article sur betterexplained). Soit on peut voir les systèmes de versions comme des moyens d’appliquer des patches. C’est-à-dire que l’on peut soit se concentrer sur les nœuds soit sur les transitions du graphe induit par les différentes versions d’un projet.

+ +

Pour git, c’est plutôt ce deuxième point de vue qui a été adopté. C’est un peu normal, étant donné que c’est Linus Torvald qui l’a inventé pour combler les problèmes inhérent aux problèmes de création de code dans le noyau Linux. Et comme historiquement, la communauté Linux se base beaucoup sur les patches, il semblait logique que ce soit ce second point de vue qui soit adopté.

+ +

J’ai d’abord été convaincu par Bazaar. Pourquoi ? Les arguments en faveur de bazaar étaient : facilité d’utilisation en particulier, facilité d’adaptation pour tous ceux qui étaient habitués à subversion. Comme c’était mon cas, et que lorsque j’avais essayé de suivre la doc Git à l’époque c’était un peu épique. +Puis avec le temps, je me suis dit que je n’allais quand même pas mourir idiot et que j’allais me mettre sérieusement à git histoire de voir si ses défenseurs avaient vraiment raison.

+ +

Mon dieu, que ce fut fastidieux. La terminologie est affreuse ! Et ce n’est rien de le dire.

+ +

Là où Bazaar est meilleur que git

+ +

Par exemple, checkout qui sert certainement à la même chose du point de vue technique, est dans l’usage un terme employé pour faire des actions qui semblent très différentes à un utilisateur λ. Exemple :

+ +
+git checkout pipo
+
+ +

annule une modification courante du fichier pipo

+ +
+git checkout pipo
+
+ +

change de la branche courante vers la branche pipo

+ +

Et là, comme moi, vous remarquez que la même commande à deux sens complètement différents. Comment ça se passe alors, quand il y a une branche pipo et un fichier pipo alors ? Et bien par défaut, ça change de branche. Pour lever l’ambigüité il faut utiliser la syntaxe

+ +
+git checkout ./pipo
+
+ +

Oui, bon… Voilà, voilà, voilà….

+ +

Ça marche, mais ce n’est pas très convivial. D’autant plus que le mot clé checkout signifiait sous CVS et SVN l’opération pour récupérer un projet distant.

+ +

Là où la différence se creuse c’est avec la terminologie Bazaar qui est bien plus naturelle. Car il n’y a pas de commande pour changer de branche, puisqu’il y a une branche par répertoire. Ainsi, pour changer de branche, il suffit de faire cd path/to/branch. Et pour revenir en arrière :

+ +
+bzr revert pipo
+
+ +

De plus, la plupart des commandes bazaar prennent en paramètre un numéro de révision, par exemple pour revenir 3 versions précédentes il suffit d’écrire :

+ +
+bzr revert -r -3 pipo
+
+ +

L’équivalent sous git est beaucoup plus cryptique :

+ +
+bzr checkout HEAD~3 pipo
+
+ +

Encore un fois, Bazaar est bien plus lisible.

+ +

Revenir dans le temps pour tout le projet :

+ +

avec Bazaar :

+ +
+bzr revert -r -3 pipo
+
+ +

et avec git ? git checkout ? Bien sûr que non voyons ! Ce serait bien trop simple. Ce que l’on trouve dans les forums c’est :

+ +
+git reset --hard HEAD~3
+
+ +

Sauf que cette syntaxe est horrible. Elle oublie ‘réellement’ les révisions. Il faut donc l’utiliser avec prudence. Mais en effet, je conseillerai plutôt :

+ +
+git checkout HEAD~3 -- . && git commit -m 'back in time'
+
+ +

Histoire d’avoir la branche backup sous la main, car sinon, on risque de perdre définitivement la version courante de HEAD. Qui ramène la branche locale à ce point. Mais il reste des erreur s’il y a eu des ajouts de fichier entre temps. Le seul et l’unique vraiment propre de revenir en arrière dans git c’est de lancer la commande suivante :

+ +
+for i in $(seq 0 2); do 
+    git revert -n --no-edit head~$i; 
+done
+git commit -m "reverted 3 versions back"
+
+ +

ce qui signifie sur un système UNIX en zsh (ou bash) faire git revert de toutes les dernières versions. Même si quelqu’un d’autre à fait un pull de vos modification intermédiaire il ne sera pas embêté et il sera au courant de ce qu’il s’est passé.

+ +

La règle est simple : Ne JAMAIS utiliser la commande git reset avec une version que d’autres personnes auraient pu avoir fetcher.

+ +

Voilà, c’est dit. Découvrir ça m’a pris pas mal de temps, avec plein d’essai de tous les cotés. Le plus sûr reste toujours la méthode vue plus haut. Si vous souhaitez automatiser cela, le plus simple est d’ajouter l’alias suivant à votre fichier ~/.gitconfig. Bien sûr l’alias ne fonctionnera que sur les environnement possédant zsh, ce qui est le cas de la plupart des environnements 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\""'
+
+
+ +

Ce qui fait que git est le meilleur DCVS jusqu’à aujourd’hui

+ +

Après avoir énoncé les cotés négatifs (et je les trouve nombreux) de git. Voici les cotés positifs qui a eux seul valent la peine de se coltiner tous les problèmes inhérent à git.

+ +

Cheap branching

+ +

Vous travaillez toujours dans le même répertoire principal. Par exemple, vous pouvez travailler sur deux corrections de bug. Disons fix1 et fix2 nécessitant la modification respective de file1 et file2. Vous pouvez travailler dans n’importe quel ordre sur vos deux fichiers dans la branche master. Puis, une fois votre travail fini. Aller dans la branche fix1 pour commiter file1. Puis aller dans la branche fix2 pour commiter file2. Et enfin, merger les deux branches dans master.

+ +
+> vim file1
+> vim file2
+> git br fix1
+> git add file1 
+> git commit -m 'fix1'
+> git br fix2
+> git add file2
+> git commit -m 'fix2'
+> git commit master
+> git merge fix1
+> git merge fix2
+
+ +

Et il est vraiment très agréable de ne pas se soucier d’être dans la bonne branche. Vous n’avez à vous occuper que de votre code et seulement ensuite vous occuper du système de version.

+ +

Sous Bazaar, il m’est souvent arriver de coder dans la mauvaise branche. Pour récupérer le coup, on doit copier les modifications du fichier dans la bonne branche et faire un revert sur le fichier en question, puis aller dans la bonne branche pour commiter les modifications. Enfin, la plupart du temps, je me trompe de branche et puis tant pis, je merge les deux tout en sachant que c’est sale.

+ +

C’est pourquoi je préfère utiliser git. Si Bazaar venait à implémenter ce système de cheap branching, je le replacerai certainement en tête.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 14/12/2009 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-01-04-Change-default-shell-on-Mac-OS-X/index.html b/output/n3blog/fr/blog/2010-01-04-Change-default-shell-on-Mac-OS-X/index.html new file mode 100644 index 000000000..b60b5ff7a --- /dev/null +++ b/output/n3blog/fr/blog/2010-01-04-Change-default-shell-on-Mac-OS-X/index.html @@ -0,0 +1,196 @@ + + + + + + + + + + + + + + + + + + + + + + + Changer le shell par défaut sous Mac OS X + + + + +
+ + +
+

+ Changer le shell par défaut sous Mac OS X +

+ +
+ +
+ + + + + +
+
+
+

Je viens de trouver le moyen de changer son shell par défaut sous Mac OS X. Cette note est plus pour moi. Mais elle peut aussi servir à quelqu’un d’autre. Il suffit de lancer la commande :

+ +
+> chsh
+
+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 04/01/2010 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/code/local.conf b/output/n3blog/fr/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/code/local.conf new file mode 100644 index 000000000..cbbcb2c5e --- /dev/null +++ b/output/n3blog/fr/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/code/local.conf @@ -0,0 +1,55 @@ + + + + + + + + +misc.conf + + + +alias.conf + + + +msfonts-rules.conf + + + + Tahoma + + + Verdana + + + + + + + Lucida Grande + + + + + + + + Georgia + + + Georgia + + + + + + + Century Schoolbook L + + + + + + diff --git a/output/n3blog/fr/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/index.html b/output/n3blog/fr/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/index.html new file mode 100644 index 000000000..b14af9884 --- /dev/null +++ b/output/n3blog/fr/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/index.html @@ -0,0 +1,257 @@ + + + + + + + + + + + + + + + + + + + + + + + Fontes adoucies sous Ubuntu Firefox + + + + +
+ + +
+

+ Fontes adoucies sous Ubuntu Firefox +

+ +
+ +
+ + + + + +
+
+
+

Voici comment faire pour ne plus utiliser les fontes Microsoft© sous Linux Ubuntu pour avoir de belles fontes adoucies (anti aliased) qui ne font pas mal aux yeux sous Firefox.

+ +

modifiez le fichier /etc/fonts/local.conf en y incluant le contenu suivant :

+ +
+
+
+
+<?xml version="1.0"?>
+<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
+<fontconfig>
+
+<!-- Miscellaneous settings -→
+
+<include ignore_missing="yes">misc.conf</include>
+
+<!-- Define alias -→
+
+<include ignore_missing="yes">alias.conf</include>
+
+<!-- Rules for Microsoft fonts -→
+
+<include ignore_missing="yes">msfonts-rules.conf</include>
+
+  <match target="pattern" name="family" >
+      <test name="family" qual="any" >
+          <string>Tahoma</string>
+      </test>
+      <edit mode="assign" name="family" >
+          <string>Verdana</string>
+      </edit>
+  </match>
+  <selectfont>
+      <acceptfont>
+          <pattern>
+              <patelt name="family"> 
+                <string>Lucida Grande</string> 
+              </patelt>
+          </pattern>
+      </acceptfont>
+  </selectfont>
+
+  <match target="pattern" name="family" >
+      <test name="family" qual="any" >
+          <string>Georgia</string>
+      </test>
+      <edit mode="assign" name="family" >
+          <string>Georgia</string>
+      </edit>
+  </match>
+  <selectfont>
+      <acceptfont>
+          <pattern>
+              <patelt name="family"> 
+                <string>Century Schoolbook L</string> 
+              </patelt>
+          </pattern>
+      </acceptfont>
+  </selectfont>
+
+</fontconfig>
+
+
+
+ +

J’espère que ça a pu aider quelqu’un qui comme moi pleurait en regardant des fontes aussi laides.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 12/01/2010 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-02-15-All-but-something-regexp/index.html b/output/n3blog/fr/blog/2010-02-15-All-but-something-regexp/index.html new file mode 100644 index 000000000..b8e7e99e8 --- /dev/null +++ b/output/n3blog/fr/blog/2010-02-15-All-but-something-regexp/index.html @@ -0,0 +1,260 @@ + + + + + + + + + + + + + + + + + + + + + + + Expression régulière pour tout sauf quelquechose + + + + +
+ + +
+

+ Expression régulière pour tout sauf quelquechose +

+ +
+ +
+ + + + + +
+
+
+

Parfois vous ne pouvez simplement pas écrire :

+ +
+if str.match(regexp) and 
+    not str.match(other_regexp)
+        do_something
+
+ +

et vous devez obtenir le même comportement avec seulement une expression régulière. Le problème c’est que le complémentaire des régulier n’est pas régulier. Celà peut s’avérer impossible.

+ +

Cependant, pour certaines expressions ce peut être possible. Disons que vous souhaitez matcher toutes les lignes contenant le mot bull, mais que vous ne souhaitez pas matcher bullshit. Voici une façon sympa d’y arriver :

+ +
+# matcher toute les chaines qui 
+# matchent 'bull' (bullshit compris)
+/bull/
+
+# matcher toutes les chaines qui 
+# contiennent 'bull' sauf 'bullshit'
+/bull([^s]|$)|
+bulls([^h]|$)|
+bullsh([^i]|$)|
+bullshi([^t]|$)/
+
+# une autre façon de l'écrire serait
+/bull([^s]|$|s([^h]|$)|sh([^i]|$)|shi([^t]|$))/
+
+ +

Regardons de plus près. Dans la première ligne, l’expression est : +bull([^s]|$), pourquoi avons nous besoin du $ ? +Parce que sans lui, le mot bull ne serait pas matché. Cette expression signifie :

+ +
+

La chaine finie par bull
+ou,
+contient bull suivi d’une lettre différente de s.

+
+ +

Et voilà. J’espère que ça a pu vous aider.

+ +

Notez que cette méthode n’est pas toujours la meilleure. Par exemple essayons d’écrire une expression régulière équivalente à l’expression conditionnelle suivante :

+
+# Commence avec 'a': ^a
+# Se finit par 'a': c$
+# Contient 'b': .*b.*
+# Mais n'est pas 'axbxc'
+if str.match(/^a.*b.*c$/) and 
+        not str.match(/^axbxc$/)
+    do_something
+end
+
+ +

Une solution est :

+ +
+/abc|           # longueur 3
+a.bc|           # longueur 4
+ab.c|
+a[^x]b[^x]c|    # longueur 5
+a...*b.*c|      # longueur >5
+a.*b...*c/
+
+ +

Cette solution utilise la longueur maximale de la chaine qui ne doit pas être matchée. Il existe certainement d’autres méthodes. Mais la leçon importante c’est qu’il n’est pas naturel d’exclure des solutions d’un expression régulière.

+ +
+

+Il peut être démontré que tout ensemble régulier privé d’un ensemble fini est aussi régulier. +

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 15/02/2010 + modifié le : 11/06/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-02-16-All-but-something-regexp--2-/index.html b/output/n3blog/fr/blog/2010-02-16-All-but-something-regexp--2-/index.html new file mode 100644 index 000000000..8744ae08f --- /dev/null +++ b/output/n3blog/fr/blog/2010-02-16-All-but-something-regexp--2-/index.html @@ -0,0 +1,284 @@ + + + + + + + + + + + + + + + + + + + + + + + Tout sauf quelquechose en expression régulière. + + + + +
+ + +
+

+ Tout sauf quelquechose en expression régulière. +

+ +
+ +
+ + + + + +
+
+
+

Dans mon précédent article j’ai donné certaines astuces pour matcher ‘tout sauf quelque chose’. De la même manière, un truc pour matcher la chaine de caractère la plus petite possible. +Disons que vous voulez matcher la chaine de caractère entre ‘a’ et ‘b’. Par exemple, vous voulez matcher :

+ +
+a.....a......b..b..a....a....b...
+
+ +

Voici les deux erreurs communes et une solution :

+ +
+/a.*b/
+a.....a......b..b..a....a....b...
+
+ +

La première erreur vient de l’utilisation du terrible .*. Parce que vous allez matcher la chaîne de caractère la plus longue possible.

+ +
+/a.*?b/
+a.....a......b..b..a....a....b...
+
+ +

L’autre manière naturelle de répondre à ce problème est de changer la greediness. Mais ce n’est pas assez parce que vous allez matcher du premier a au premier b après celui-ci. On peut alors constater que votre chaine de caractère ne devrait comprendre ni la lettre a ni la lettre b. Ce qui emène à la dernière solution élégante.

+ +
+/a[^ab]*b/
+a.....a......b..b..a....a....b...
+
+ +

Jusqu’ici, c’était facile. Maintenant comment fait vous quand au lieu de a vous avez une chaine de caractère ?

+ +

Par exemple, vous voulez matcher:

+
+<li>...<li>
+
+ +

C’est un peu difficile. Vous devez matcher

+
+<li>[anything not containing <li>]</li>
+
+ +

La première méthode serait d’utiliser le même rainsonnement que dans mon article précédent. Ici un premier essai :

+ +
+<li>([^<]|<[^l]|<l[^i]|<li[^>])*</li>
+
+ +

Mais il y a encore une erreur. Pensez à la chaine de caractère suivante :

+
+<li>...<li</li>
+
+ +

Cette chaine ne matchera pas. C’est pourquoi si on veut vraiment la matcher correctement nous devons ajouter :

+
+<li>([^<]|<[^l]|<l[^i]|<li[^>])*(|<|<l|<li)</li>
+
+ +

Oui, c’est un peu compliqué. Mais que se passe t’il lorsque la chaine de caractère que vous voulez matcher est encore plus longue que <li> ?

+ +

Voici un algorithme qui permet de résoudre ce problème aisément. Vous devez réduire ce problème au premier. C’est-à-dire celui avec une seule lettre :

+ +
+# transforme un simple caractère choisi aléatoirement
+# en un identifiant unique
+# (vous devez vérifier que l'identifier est VRAIMENT unique)
+# attention l'identifiant unique ne doit pas 
+# contenir le caractère choisi.
+s/X/_was_x_/g
+s/Y/_was_y_/g
+
+# transforme la longue chaine de caractère
+# en un seul caractère
+s/<li>/X/g
+s/<\/li>/Y/g
+
+# Utilisation de la première méthode
+s/X([^X]*)Y//g
+
+# Retransformation des lettres en chaines
+# de caractères
+s/X/<li>/g
+s/Y/<\/li>/g
+
+# retour des anciens caractères.
+s/_was_x_/X/g
+s/_was_y_/Y/g
+
+ +

Et ça fonctionne en seulement 9 lignes pour toute chaine de début et de fin. +Cette solution fait un peu moins I AM THE GREAT REGEXP M45T3R, URAN00B, mais elle est mieux adaptée à mon avis. De plus, utiliser cette dernière solution prouve que vous maitrisez les expressions régulières. Simplement parce que vous savez qu’il est difficile de résoudre des problèmes de cette forme en utilisant seulement des expressions régulières.

+ +
+

Je sais que j’ai utilisé une syntaxe HTML dans mon exemple. Mais dans l’utilisation réelle que j’en ai faite, je devais matcher entre en: et ::, sachant que parfois les chaines pouvaient se terminer par e::.

+ + +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 16/02/2010 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-02-18-split-a-file-by-keyword/index.html b/output/n3blog/fr/blog/2010-02-18-split-a-file-by-keyword/index.html new file mode 100644 index 000000000..bd1245537 --- /dev/null +++ b/output/n3blog/fr/blog/2010-02-18-split-a-file-by-keyword/index.html @@ -0,0 +1,226 @@ + + + + + + + + + + + + + + + + + + + + + + + découper un fichier par mots clés + + + + +
+ + +
+

+ découper un fichier par mots clés +

+ +
+ +
+ + + + + +
+
+
+

Assez bizarrement, je n’ai trouvé aucun outil UNIX pour découper un fichier par mot clé. +Alors j’en ai fait un en awk. Je le met ici principalement pour moi, mais ça peut toujours servir à quelqu’un d’autre. +Le code suivant découpe un fichier pour chacune de ses ligne contenant le mot UTC.

+ +
+#!/usr/bin/env awk
+BEGIN{i=0;}
+/UTC/ { 
+    i+=1;
+    FIC=sprintf("fic.%03d",i); 
+} 
+{print $0>>FIC}
+
+ +

En réalité, j’avais besoin de cet outils pour avoir un fichier par jour. Chaque ligne contenant UTC ayant le format suivant :

+ +
+Mon Dec  7 10:32:30 UTC 2009
+
+ +

J’en suis finallement arrivé au code suivant :

+ +
+#!/usr/bin/env awk
+BEGIN{i=0;}
+/UTC/ {
+    date=$1$2$3; 
+    if ( date != olddate ) {
+        olddate=date;
+        i+=1;
+        FIC=sprintf("fic.%03d",i); 
+    }
+} 
+{print $0>>FIC}
+
+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 18/02/2010 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-02-23-When-regexp-is-not-the-best-solution/code/regex_benchmark_ext.rb b/output/n3blog/fr/blog/2010-02-23-When-regexp-is-not-the-best-solution/code/regex_benchmark_ext.rb new file mode 100644 index 000000000..33e9e5580 --- /dev/null +++ b/output/n3blog/fr/blog/2010-02-23-When-regexp-is-not-the-best-solution/code/regex_benchmark_ext.rb @@ -0,0 +1,25 @@ + +#!/usr/bin/env ruby +require 'benchmark' +n=80000 +tab=[ '/accounts/user.json', + '/accounts/user.xml', + '/user/titi/blog/toto.json', + '/user/titi/blog/toto.xml' ] + +puts "Get extname" +Benchmark.bm do |x| + x.report("regexp:") { n.times do + str=tab[rand(4)]; + str.match(/[^.]*$/); + ext=$&; + end } + x.report(" split:") { n.times do + str=tab[rand(4)]; + ext=str.split('.')[-1] ; + end } + x.report(" File:") { n.times do + str=tab[rand(4)]; + ext=File.extname(str); + end } +end diff --git a/output/n3blog/fr/blog/2010-02-23-When-regexp-is-not-the-best-solution/code/regex_benchmark_strip.rb b/output/n3blog/fr/blog/2010-02-23-When-regexp-is-not-the-best-solution/code/regex_benchmark_strip.rb new file mode 100644 index 000000000..f99b07a97 --- /dev/null +++ b/output/n3blog/fr/blog/2010-02-23-When-regexp-is-not-the-best-solution/code/regex_benchmark_strip.rb @@ -0,0 +1,21 @@ + +#!/usr/bin/env ruby +require 'benchmark' +n=80000 +tab=[ '/accounts/user.json', + '/accounts/user.xml', + '/user/titi/blog/toto.json', + '/user/titi/blog/toto.xml' ] + +puts "remove extension" +Benchmark.bm do |x| + x.report(" File:") { n.times do + str=tab[rand(4)]; + path=File.expand_path(str,File.basename(str,File.extname(str))); + end } + x.report("chomp:") { n.times do + str=tab[rand(4)]; + ext=File.extname(str); + path=str.chomp(ext); + end } +end diff --git a/output/n3blog/fr/blog/2010-02-23-When-regexp-is-not-the-best-solution/index.html b/output/n3blog/fr/blog/2010-02-23-When-regexp-is-not-the-best-solution/index.html new file mode 100644 index 000000000..24a81de57 --- /dev/null +++ b/output/n3blog/fr/blog/2010-02-23-When-regexp-is-not-the-best-solution/index.html @@ -0,0 +1,290 @@ + + + + + + + + + + + + + + + + + + + + + + + Quand se passer des expressions régulières ? + + + + +
+ + +
+

+ Quand se passer des expressions régulières ? +

+ +
+ +
+ + + + + +
+
+
+

Les expressions régulières sont très utiles. Cependant, elles ne sont pas toujours la meilleure manière d’aborder certain problème autour des chaines de caractères. +Et surtout quand les transformations que vous voulez accomplir sont simples.

+ +

Je voulais savoir comment récupérer le plus vite possible l’extension d’un nom de fichier. Il y a trois manière naturelle d’accomplir celà :

+ +
+# regexp
+str.match(/[^.]*$/); 
+ext=$&
+
+# split
+ext=str.split('.')[-1]
+
+# File module
+ext=File.extname(str)
+
+ +

A première vue, je pensais que l’expression régulière serait plus rapide que le split parce qu’il pouvait y avoir plusieurs de . dans un nom de fichier. Mais la majorité du temps il n’y a qu’un seul point par nom de fichier. C’est pourquoi j’ai réalisé que le split serait plus rapide. Mais pas le plus rapide possible. Il y a une fonction qui est dédiée à faire ce travail dans un module standard de ruby ; le module File.

+ +

Voici le code pour faire un benchmark :

+ +
+
+#!/usr/bin/env ruby
+require 'benchmark'
+n=80000
+tab=[ '/accounts/user.json',
+      '/accounts/user.xml',
+      '/user/titi/blog/toto.json',
+      '/user/titi/blog/toto.xml' ]
+
+puts "Get extname"
+Benchmark.bm do |x|
+    x.report("regexp:") { n.times do 
+        str=tab[rand(4)]; 
+        str.match(/[^.]*$/); 
+        ext=$&; 
+    end  }
+    x.report(" split:") { n.times do 
+        str=tab[rand(4)]; 
+        ext=str.split('.')[-1] ; 
+    end }
+    x.report("  File:") { n.times do 
+        str=tab[rand(4)]; 
+        ext=File.extname(str); 
+    end  }
+end
+
+
+ +

Et voici les résultats :

+ +
+Get extname
+            user     system      total        real
+regexp:  2.550000   0.020000   2.570000 (  2.693407)
+ split:  1.080000   0.050000   1.130000 (  1.190408)
+  File:  0.640000   0.030000   0.670000 (  0.717748)
+
+ +

En conclusion, les fonction dédiées sont meilleures que votre façon de faire (la plupart du temps).

+ +

Chemin complet d’un fichier sans l’extension

+ +
+
+#!/usr/bin/env ruby
+require 'benchmark'
+n=80000
+tab=[ '/accounts/user.json',
+      '/accounts/user.xml',
+      '/user/titi/blog/toto.json',
+      '/user/titi/blog/toto.xml' ]
+
+puts "remove extension"
+Benchmark.bm do |x|
+    x.report(" File:") { n.times do 
+        str=tab[rand(4)]; 
+        path=File.expand_path(str,File.basename(str,File.extname(str))); 
+    end }
+    x.report("chomp:") { n.times do 
+        str=tab[rand(4)]; 
+        ext=File.extname(str); 
+        path=str.chomp(ext); 
+    end }
+end
+
+
+ +

et voici les résultats :

+ +
+remove extension
+          user     system      total        real
+ File:  0.970000   0.060000   1.030000 (  1.081398)
+chomp:  0.820000   0.040000   0.860000 (  0.947432)
+
+ +

En conclusion du ce second benchmark. Un fonction simple est meilleure que trois fonctions dédiées. Pas de surprise, mais c’est toujours bien de savoir.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 23/02/2010 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-03-22-Git-Tips/index.html b/output/n3blog/fr/blog/2010-03-22-Git-Tips/index.html new file mode 100644 index 000000000..e9501dc4d --- /dev/null +++ b/output/n3blog/fr/blog/2010-03-22-Git-Tips/index.html @@ -0,0 +1,251 @@ + + + + + + + + + + + + + + + + + + + + + + + Astuces Git + + + + +
+ + +
+

+ Astuces Git +

+ +
+ +
+ + + + + +
+
+
+

Cloner de github à travers un pare-feu

+ +

La façon standard:

+ +
+git clone git@github.com:yogsototh/project.git
+
+ +

En utilisant le port HTTPS :

+ +
+git clone git+ssh://git@github.com:443/yogsototh/project.git
+
+ +

Cloner toutes les branches

+ +

git clone peut seulement récuper la branche master.

+ +

Si vous n’avez pas beaucoup de branches, vous pouvez simplement les clone le project et ensuite pour chacune d’entre elle lancer la commande suivante :

+ +
+git branch --track local_branch remote_branch
+
+ +

par exemple :

+
+$ git clone git@github:yogsototh/example.git
+$ git branch
+master *
+$ git branch -a
+master *
+remotes/origin/HEAD -> origin/master
+remotes/origin/experimental
+$ git branch --track experimental remotes/origin/experimental
+$ git branch
+master *
+experimental
+
+ +

Si vous avez beaucoup de branches il peut être utile d’utiliser le script/la longue ligne de commande suivant(e) :

+ +
+# first clone your project
+$ git clone git@github.com:yogsototh/project.git
+
+# copy all branches
+$ zsh
+$ cd project
+$ for br in $( git br -a ); do
+    case $br in
+    remotes/*) print $br ; 
+        case ${br:t} in
+            master|HEAD) continue ;;
+            *) git branch --track ${br:t} $br ;;
+        esac ;;
+    esac
+done
+
+ +

Et toutes les branches seront récupérées en local.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 22/03/2010 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-03-23-Encapsulate-git/code/eng b/output/n3blog/fr/blog/2010-03-23-Encapsulate-git/code/eng new file mode 100644 index 000000000..3cb5eded6 --- /dev/null +++ b/output/n3blog/fr/blog/2010-03-23-Encapsulate-git/code/eng @@ -0,0 +1,103 @@ + +#!/usr/bin/env ruby +# encoding: utf-8 + +# 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 ] } + +def get_current_branch() + (`git branch --no-color | awk '$1 == "*" {print $2}'`).chop.intern +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 + +require 'set' +$known_branches=Set.new +$architecture.each do |k,v| + $known_branches.add(k) + v.each { |b| $known_branches.add(b) } +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 + +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 + f 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 diff --git a/output/n3blog/fr/blog/2010-03-23-Encapsulate-git/index.html b/output/n3blog/fr/blog/2010-03-23-Encapsulate-git/index.html new file mode 100644 index 000000000..ca1735828 --- /dev/null +++ b/output/n3blog/fr/blog/2010-03-23-Encapsulate-git/index.html @@ -0,0 +1,354 @@ + + + + + + + + + + + + + + + + + + + + + + + Encapsuler git + + + + +
+ + +
+

+ Encapsuler git +

+ +
+ +
+ + + + + +
+
+
+

+Voici une solution pour conserver des branches divergentes avec git. +Parce qu’il est facile de merger par erreur, je propose un script qui encapsule le comportement de git pour interdire certains merges dangereux. Mais qui permet aussi de faire des merges en cascades de la racines vers les autres branches. +

+ +

Se prémunir contre les erreurs

+ +

Je travaille sur un projet dans lequel certaines de mes branches git doivent rester divergentes. Et les divergences devraient aller en s’accentuant.

+ +

J’utilise aussi certaines branches qui contiennent la partie commune de ces projets.

+ +

Disons que j’ai les branches :

+ +

master: commune à toutes les branches +dev: branche instable pour le développement +client: Branche commune à plusieurs clients +clientA: le projet spécialisé pour le client A +clientB: le projet spécialisé pour le client B

+ +

Voilà comment je souhaiterai que ça fonctionne

+ +

Dynamic branching

+ +

Et plus précisément la hiérarchie des branches :

+ +

Branch hierarchy

+ +

Une flèche de A vers B signifie que l’on peut merger A dans B. S’il n’y a pas de flèche de A vers B cela signifie qu’il est interdit de merger A dans B. Voici le code ruby correspondant :

+ +
+$architecture={ 
+    :master => [ :dev, :client ],
+    :dev => [ :master ],
+    :client => [ :clientA, :clientB ] }
+
+ +

:master => [ :dev, :client ] signifie que l’on peut merger la branche master dans la branche dev et la branche client.

+ +

Je fait une erreur si je tape git checkout master && git merge clientA. +C’est pour éviter ça que j’ai fait un script pour encapsuler le comportement de git.

+ +

Mais ce script fait bien plus que ça. Il fait des merges en cascade de la racine vers les feuilles avec l’acion allmerges.

+ +
+git co dev && git merge master
+git co client && git merge master
+git co clientA && git merge client
+git co clientB && git merge client
+
+ +

Je peux ainsi mettre à jour toutes les branches. L’algorithme ne boucle pas même s’il y a des cycles dans la structure des branches.
+Le voici :

+ +
+
+#!/usr/bin/env ruby
+# encoding: utf-8
+
+# 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 ] }
+
+def get_current_branch()
+    (`git branch --no-color | awk '$1 == "*" {print $2}'`).chop.intern
+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
+
+require 'set'
+$known_branches=Set.new
+$architecture.each do |k,v| 
+    $known_branches.add(k)
+    v.each { |b| $known_branches.add(b) }
+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
+
+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
+            f 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
+
+
+ +

Pour que ça fonctionne il vous suffit de copier eng dans un répertoire présent dans votre PATH.

+ +

Bien entendu, il faut essayer de faire aussi peu que possible des cherry-pick et des rebase. Ce script a pour but de s’intégrer avec les workflow basé sur les pull et merge.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 23/03/2010 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-05-17-at-least-this-blog-revive/index.html b/output/n3blog/fr/blog/2010-05-17-at-least-this-blog-revive/index.html new file mode 100644 index 000000000..6af9bcd82 --- /dev/null +++ b/output/n3blog/fr/blog/2010-05-17-at-least-this-blog-revive/index.html @@ -0,0 +1,227 @@ + + + + + + + + + + + + + + + + + + + + + + + Je reviens à la vie ! + + + + +
+ + +
+

+ Je reviens à la vie ! +

+ +
+ +
+ + + + + +
+
+
+

Bonjour à tous !

+ +
+

…plus on retarde quelque chose, plus il devient difficile de s’y mettre…

+
+ +

Je devais écrire d’autres articles pour ce blog. J’ai noté plein d’idées dans mes todolist. Mais j’avais pas mal d’autres choses à faire. Et jusqu’ici, j’ai toujours dit «je le ferai plus tard». Ce qui m’a fait agir, c’est la petite réflexion que j’avais lu une fois. +> Arrétez d’écrire des TODO dans votre code est faites le maintenant !
+> Vous serez surpris de l’efficacité de cette mesure.

+ +

En résumé : +> Just do it! ou Juste fait le comme auraient dit les nuls.

+ +

Finallement j’écrirais plus souvent ces derniers temps.

+ +

Qu’ai-je fait ?

+ +

J’ai fini une application web pour gridpocket©.

+ +

J’ai aussi fini d’adapter mon site à la dernière version de nanoc. La partie difficile étant d’avoir un système qui permet de gérer plusieurs langues. Je pense que j’écrirai les détails dans un article.

+ +

J’ai aussi une vrai vie. J’ai passé quelques moments agréables avec ma famille et des amis.

+ +

J’ai travaillé avec luc sur un framework REST/JSON orienté API écrit en ruby. Il fonctionne assez bien, avec très peu de bug jusqu’ici. Nous espérons pouvoir écrire un tutoriel de todolist. Peut-être en deux ou trois posts. Ce framework n’est pas encore public. Il le deviendra certainement lorsque nous aurons fini d’écrire une application web et que nous aurons fait un joli site pour lui.

+ +

Finallement voilà un partie des choses que je dois faire :

+ +
    +
  • finir de faire un service web public (je pense que ça peut être populaire) ;
  • +
  • finir d’écrire l’application iPhone associée ;
  • +
  • finir de publier notre framework pour créer des services web ;
  • +
  • publier des articles sur ce blog ;
  • +
  • publier le code source de ce blog sur github.
  • +
+ +

Certaines choses ne seront peut-être jamais finie. Mais simplement parce qu’elles ne dépendent pas complètement de moi.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 17/05/2010 + modifié le : 19/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-05-19-How-to-cut-HTML-and-repair-it/code/repair_xml.rb b/output/n3blog/fr/blog/2010-05-19-How-to-cut-HTML-and-repair-it/code/repair_xml.rb new file mode 100644 index 000000000..1121d4ef1 --- /dev/null +++ b/output/n3blog/fr/blog/2010-05-19-How-to-cut-HTML-and-repair-it/code/repair_xml.rb @@ -0,0 +1,25 @@ + +# repair cutted XML code by closing the tags +# work even if the XML is cut into a tag. +# example: +# transform '
toto

hello ]*$/m,'') + depth-=1 + depth.downto(0).each { |x| res<<= %{} } + res +end diff --git a/output/n3blog/fr/blog/2010-05-19-How-to-cut-HTML-and-repair-it/index.html b/output/n3blog/fr/blog/2010-05-19-How-to-cut-HTML-and-repair-it/index.html new file mode 100644 index 000000000..6598c804f --- /dev/null +++ b/output/n3blog/fr/blog/2010-05-19-How-to-cut-HTML-and-repair-it/index.html @@ -0,0 +1,297 @@ + + + + + + + + + + + + + + + + + + + + + + + Comment réparer un XML coupé ? + + + + +

+ + +
+

+ Comment réparer un XML coupé ? +

+ +

+ et comment s'en sortir sans parseur ? +

+ +
+ +
+ + + + + +
+
+
+

Sur ma page d’accueil vous pouvez voir la liste des mes derniers articles avec le début de ceux-ci. Pour arriver à faire ça, j’ai besoin de couper le code XHTML de mes pages en plein milieu. Il m’a donc fallu trouver un moyen de les réparer.

+ +

Prenons un exemple :

+ +
+<div class="corps">
+    <div class="intro">
+        <p>Introduction</p>
+    </div>
+    <p>The first paragraph</p>
+    <img src="/img/img.png" alt="an image"/>
+    <p>Another long paragraph</p>
+</div>
+
+ +

Après avoir coupé, j’obtiens :

+ +
+<div class="corps">
+    <div class="intro">
+        <p>Introduction</p>
+    </div>
+    <p>The first paragraph</p>
+    <img src="/img/im
+
+ +

En plein milieu d’un tag <img> !

+ +

En réalité, ce n’est pas si difficile que celà peut paraître au premier abord. Le secret réside dans le fait de comprendre que l’on n’a pas besoin de conserver la structure complète de l’arbre pour le réparer, mais seulement la liste des parents non fermés.

+ +

Pour notre exemple, juste après le paragraphe first paragraph nous n’avons qu’à fermer un div pour la classe corps et le XML est réparé. Bien entendu, quand on est dans le cas où un tag est coupé au milieu, on a qu’à remonté juste avant le début de ce tag corrompu.

+ +

Donc, tout ce que nous avons à faire, c’est d’enregistrer la liste des parents dans une pile. Supposons que nous traitions le premier exemple complètement. La pile passera par les états suivants :

+ +
+[]           
+[div]           <div class="corps">
+[div, div]          <div class="intro">
+[div, div, p]           <p>
+                            Introduction
+[div, div]              </p>
+[div]               </div>
+[div, p]            <p>
+                        The first paragraph
+[div]               </p>
+[div]               <img src="/img/img.png" alt="an image"/>
+[div, p]            <p>
+                        Another long paragraph
+[div]               </p>
+[]              </div>
+
+ +

L’algorithme est alors très simple : +<pre class="twilight"> +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.

+ +

remove any malformed/cutted tag in the end of res +for each tag in the stack, pop it, and write: + res = res + closed tag

+ +

return res +</pre>

+ +

Et res contiend le XML réparé.

+ +

Finallement, voici le code en ruby que j’utilise. La variable xml contient le XML coupé.

+ +
+
+# 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
+
+
+ +

Je ne sais pas si ce code pourra vous être utile. Par contre le raisonnement pour y parvenir mérite d’être connu.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Écrit le : 19/05/2010 + modifié le : 04/10/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-05-24-Trees--Pragmatism-and-Formalism/index.html b/output/n3blog/fr/blog/2010-05-24-Trees--Pragmatism-and-Formalism/index.html new file mode 100644 index 000000000..b62391e2b --- /dev/null +++ b/output/n3blog/fr/blog/2010-05-24-Trees--Pragmatism-and-Formalism/index.html @@ -0,0 +1,487 @@ + + + + + + + + + + + + + + + + + + + + + + + Arbres ; Pragmatisme et Formalisme + + + + +
+ + +
+

+ Arbres ; Pragmatisme et Formalisme +

+ +

+ Quand la théorie est plus pratique que la pratique +

+ +
+ +
+ + + + + +
+
+
+ +
+ + +

tlàl :

+ +
    +
  • J’ai essayé de programmer un simple filtre ;
  • +
  • J’ai été bloqué pendant deux jours ;
  • +
  • J’ai arrêté de penser comme un robot ;
  • +
  • J’ai utilisé un papier et un stylo ;
  • +
  • J’ai fait un peu de maths ;
  • +
  • J’ai résolu le problème en 10 minutes ;
  • +
  • Conclusion: Pragmatisme n’est pas : «n’utilisez jamais la théorie». + +
+ + + +

Résumé (plus long que le tlàl)

+ +

Je devais résoudre un problème à mon travail. Au début cela +semblait assez facile. J’ai donc commencé à programmer +tout de suite. Je suis alors entré dans un cercle infernal d’essais +et de réparations. Voilà à quoi ressemblait cet étrange état +de boucle infini :

+ +
+

– Plus que ça a réparer et ça devrait être bon.
+ – Très bien, maintenant ça doit marcher.
+ – Oui !!
+ – Ah mince! J’ai oublié ce détail…
+ répéter jusqu'à la mort

+
+ +

Après deux jours à me prendre pour Sisyphe, je me suis arrêté pour repenser le problème. +J’ai pris un stylo et une feuille de papier. Je me suis souvenu de de ce que j’avais appris sur les arbres pendant mon doctorat. +Finalement, le problème fut résolu en moins de 20 minutes.

+ +

Je pense que la leçon à retenir de cette expérience est de se souvenir que la méthodologie la plus efficace pour résoudre ce problème pragamtique était la méthode théorique. +Ça ne signifie pas que la méthode théorique est toujours la meilleure, mais en tout cas, il ne faut pas l’écarter.

+ + +
+ +
+ + +

L’anecdote

+ +

Apparemment 90% des programmeurs sont incapable de programmer une recherche binaire sans faire de bug. +L’algorithme est pourtant connu et facile à comprendre. +Cependant, il est difficile à programmer sans bug. +J’ai participé à ce concours. +Vous pouvez voir les résultats ici1. +J’ai dû faire face à un problème similaire à mon travail. +Il paraissait simple au départ. +Transformer un xml d’un format à un autre.

+ +

Voici le format général du xml source :

+ +
+<rubrique>
+    <contenu>
+        <tag1>value1</tag1>
+        <tag2>value2</tag2>
+        ...
+    </contenu>
+    <enfant>
+        <rubrique>
+            ...
+        </rubrique>
+        ...
+        <rubrique>
+            ...
+        </rubrique>
+    </enfant>
+</menu>
+
+ +

et le format d’arrivé est celui-ci :

+ +
+<item name="Menu0">
+    <value>
+        <item name="menu">
+            <value>
+                <item name="tag1">
+                    <value>value1</value>
+                </item>
+                <item name="tag2">
+                    <value>value2</value>
+                </item>
+                ...
+                <item name="menu">
+                    <value>
+                        ...
+                    </value>
+                    <value>
+                        ...
+                    </value>
+                </item>
+            </value>
+        </item>
+    </value>
+</item>
+
+ +

À première vue, cela m’a paru simple. J’étais certain de pouvoir y arriver en me fixant les règles suivantes :

+ +
    +
  1. ne pas utiliser xslt ;
  2. +
  3. ne pas utiliser de parseur xml ;
  4. +
  5. résoudre le problème en utilisant un simple script perl
  6. +
+ +

Vous pouvez essayer si vous le souhaitez. Si vous attaquez ce problème directement en écrivant le programme, ce ne sera certainement pas si simple. +Je peux le dire, parce que c’est ce que j’ai fait. +Et je dois dire que j’ai perdu une journée de travail complète en m’y prenant de la sorte. +En réalité, il y avait pas mal de petits détails dont je ne parle pas qui m’ont induis en erreur et qui m’ont fait perdre encore plus de temps.

+ +

Pourquoi étais-je incapable de résoudre ce problème si simple en aparence ?

+ +

Voici comment je m’y suis pris :

+ +
    +
  1. Réfléchir
  2. +
  3. Écrire le programme
  4. +
  5. Essayer le programme
  6. +
  7. Vérifier les résultats
  8. +
  9. Trouver un bug
  10. +
  11. Résoudre le bug
  12. +
  13. Reprendre à l’étape 3
  14. +
+ +

Il s’agissait d’une méthode de travail standard pour un ingénieur en informatique. L’erreur venait de la première étape. +J’ai d’abord pensé à comment résoudre le problème mais avec des yeux d’ingéinieur pragmatique. Je me suis simplement dit :

+ +
+

Ça à l’air de pouvoir se résouvre avec un petit script de search&replace en perl +Commençons à écrire le code maintenant.

+
+ +

C’est la deuxième phrase qui est complètement fausse. Parce que j’avais mal commencé et que cette méthodologie de travail ne fonctionne pas lorsque l’on part vraiment mal.

+ +

Réfléchir

+ +

Après un certain temps, j’ai arrêté de programmer et je me suis dit : «Maintenant, ça suffit !». +J’ai pris une feuille et un stylo et j’ai commencé à dessiner des arbres.

+ +

J’ai commencer par simplifier un peu en enlevant le maximum de verbiage. +Tout d’abord en renommant <item name="Menu"> par un simple M par exemple. +J’ai obtenu quelque chose comme :

+ +

The source tree

+ +

et

+ +

The destination tree

+ +

Puis, je me suis fait la réflexion suivante :

+ +

Dans les distances d’éditions sur les arbres, chaque opération atomique correspond à un simple search and replace sur mon fichier xml source2. +On considère trois opérations atomiques sur les arbres :

+ +
    +
  • substitution: renommer un nœud
  • +
  • insertion: ajouter un nœud
  • +
  • délétion: supprimer un nœud
  • +
+ +

Une des particularité avec les transformations sur les arbres est celle-ci : +supprimer un nœud et tous ses enfants deviendront les enfants du père de ce nœud.

+ +

Un exemple:

+ +
+r - x - a
+  \   \
+   \    b
+    y - c   
+
+ +

Si vous supprimez le nœud x, vous obtenez

+ +
+    a
+  /
+r - b
+  \
+    y - c   
+
+ +

Et regardez ce que ça implique quand on l’écrit en xml :

+ +
+<r>
+  <x>
+    <a>value for a</a>
+    <b>value for b</b>
+  </x>
+  <y>
+    <c>value for c</c>
+  </y>
+</r>
+
+ +

Alors supprimer tous les nœuds x revient à faire passer le xml à travers le filtre suivant :

+ +
+s/<\/?x>//g
+
+ +

Par conséquent, s’il existe un transducteur déterministe à un état qui permet de transformer mes arbres ; +je suis capable de transformer le xml d’un format à l’autre en utilisant une simple liste de search and replace.

+ +

Solution

+ +

Transformer cet arbre :

+ +
+R - C - tag1
+  \   \
+   \    tag2
+    E -- R - C - tag1
+      \   \    \
+       \   \     tag2
+        \    E ...
+         R - C - tag1 
+           \    \
+            \     tag2
+             E ...
+
+ +

en celui-ci :

+ +
+                tag1
+              /
+M - V - M - V - tag2      tag1
+              \         / 
+                M --- V - tag2
+                  \     \ 
+                   \      M
+                    \     tag1
+                     \  / 
+                      V - tag2
+                        \ 
+                          M
+
+ +

peut-être fait en utilisant le transducteur déterministe à un état suivant:

+ +
+

C → ε
+ E → M
+ R → V

+
+ +

Ce qui peut-être traduit par les simples directives Perl suivantes :

+ +
+s/C//g
+s/E/M/g
+s/R/V/g
+
+ +

Une fois adapté au xml cela devient :

+ +
+s%</?contenu>%%g
+s%<enfant>%<item name="menu">%g
+s%</enfant>%</item>%g
+s%<rubrique>%<value>%g
+s%</rubrique>%</value>%g
+
+ +

Et c’est tout.

+ +

Conclusion

+ +

Même si cela peut sembler paradoxal, parfois la solution la plus efficace à un problème pragmatique est d’utiliser une méthodologie théorique.

+
+
    +
  1. +

    Normalement, je fais parti des 10% qui ont fourni une implémentation sans bug.

    +
  2. +
  3. +

    J’ai programmé un outil qui calcule automatiquement le poids de chaque élément des matrices d’édition à partir de données.

    +
  4. +
+
+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 24/05/2010 + modifié le : 21/09/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-06-14-multi-language-choices/index.html b/output/n3blog/fr/blog/2010-06-14-multi-language-choices/index.html new file mode 100644 index 000000000..0607bbeb0 --- /dev/null +++ b/output/n3blog/fr/blog/2010-06-14-multi-language-choices/index.html @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + + + + choix liés à l'écriture dans plusieurs langues + + + + +
+ + +
+

+ choix liés à l'écriture dans plusieurs langues +

+ +
+ +
+ + + + + +
+
+
+

Je traduis la plupart de mes articles pour qu’ils soient disponibles en français et en anglais. +La façon que l’on m’a conseillé était d’avoir un fichier par langue. En général ça donne ça.

+ +
+Bonjour, 
+
+voici un exemple de texte en français.
+[image](url)
+
+ +
+Hello, 
+
+here is an example of english text.
+[image](url)
+
+ +

Cette façon de traduire vous impose une certaine façon de traduire. +D’abord écrire entièrement le texte dans une langue, +puis copier le fichier et enfin retraduire dans une nouvelle langue.

+ +

Le problème, c’est que très souvent, les articles ont des parties communes non négligeables. Par exemple, les images, les codes sources, etc… +Lorsque je m’aperçoit que j’ai fait une erreur dans ces parties communes +ça m’oblige à refaire deux fois la même manipulation. Sauf que comme il m’arrive d’être distrait, il peut y avoir pas mal d’aller-retours.

+ +

C’est pourquoi, j’ai plutôt opté pour une autre solution. +J’utilise des tags sur un seul fichier. +En fin de compte, mes fichiers ressemblent à :

+ +
+ fr:   Bonjour, 
+ en:   Hello, 
+
+ en:   here is an example of english text.
+ fr:   voici un exemple de texte en français.
+[image](url)
+
+ +

Comme j’édite mes fichier avec vim, il m’est très facile d’ajouter ces fr: ou en: en début de ligne à l’aide du très utile C-v. +Par contre nanoc a été conçu pour être utilisé par une seule langue. Précédemment, j’avais utilisé les capacité de nanoc pour séparer les langues. Mais finalement, il s’avère bien plus simple de faire un pré-traitement qui nettoie mes fichiers et en fait deux copie qui seront ensuite gérées par nanoc.

+ +

Vous pouvez récupérer les sources de mon blog (sans tous les articles) à l’adresse suivante github.com/yogsototh/nanoc3_blog. J’écrirais un article pour savoir comment l’utiliser facilement. J’ai en effet ajouté beaucoup de scripts et de librairies.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 14/06/2010 + modifié le : 15/06/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-06-15-Get-my-blog-engine/index.html b/output/n3blog/fr/blog/2010-06-15-Get-my-blog-engine/index.html new file mode 100644 index 000000000..a269fa871 --- /dev/null +++ b/output/n3blog/fr/blog/2010-06-15-Get-my-blog-engine/index.html @@ -0,0 +1,324 @@ + + + + + + + + + + + + + + + + + + + + + + + Récupérez mon système de blog + + + + +
+ + +
+

+ Récupérez mon système de blog +

+ +
+ +
+ + + + + +
+
+
+

J’ai publié une version light de mon système de blog hier soir. Par light il faut comprendre avec un CSS plus épuré et plus portable (sans les bords ronds). +Vous pouvez le récupérer sur github.com.

+ +

Que pouvez-vous attendre de ce système de blog ?

+ +
    +
  • Tous les avantages liés à nanoc ;
  • +
  • Facilité de la gestion de plusieurs langues ;
  • +
  • coloration syntaxique des codes sources pour la plupart des languages ;
  • +
  • commentaires gérés avec intenseDebate de façon asynchrone ;
  • +
  • très portable avec ou sans javascript, XHTML Strict 1.0 / CSS3 ;
  • +
  • écrivez vos entrées au format Markdown (pas de HTML) ;
  • +
  • des améliorations typographiques (pas de ‘:’ en début de ligne en Français par exemple),
  • +
  • entrez directement le code de graphes qui se génèreront automatiquement en image à l’aide de Graphviz.
  • +
+ +

Pour vous donner une idée plus précise, voici la documentation que j’ai faite (en anglais) pour accompagner le code.

+ + +
+ +
+ + +

Main Documentation Page

+ +

Cette page est seulement en anglais désolé.

+ +

Use It NOW!

+ +

Once installed (follow the README.md instructions).

+ +
+$ cd /root/of/nanoc3_blog
+$ ./task/new_blog_entry Title of the blog
+$ vi latest.md
+$ ./task/recompile
+
+ +

Now your website reside into the output directory.

+ + +
+ +
+ + +

Documentation

+ +

Useful things to know

+ +

Multi-language

+ +

All files in multi are processed and copied in the content directory. +For each file in multi, each line starting by ‘fr: ’ are copied (without the fr: into the content/html/fr/ tree, but not into the content/html/en tree. File not starting by fr: or en: are copied in each destinations.

+ +

If you want to add another language, you’ll have to modify tasks/config, and config.yaml, create a content/html/xx where xx is the language code.

+ +

Edition & Rendering

+ +

additional keywords

+ +

You can separate multi content div using the: newcorps directive (see examples).

+ +

You can create div using begindiv(classname), enddiv. (See some existing blog entries for example). Use the class intro for the abstract part.

+ +

You can create nice description table using <desc> (See source code for example).

+ +

Typography

+ +

In French all ‘:’, ‘;’, ‘!’ and ‘?’ are preceded automatically by &nbsp. This enable not to have a line starting by a single special character.

+ +

You can use small caps using <sc> tags.

+ +
    +
  • (c) is replaced by ©.
  • +
  • (r) is replaced by ®.
  • +
  • <- is replaced by ←.
  • +
  • -> is replaced by →.
  • +
+ +

source code

+ +

To write source code you should use the following format:

+ +
+<code class="ruby" file="filename.rb">
+The code
+</cOde>
+
+ +

The file attribute is not required.

+ +

blog

+ +

If you want to make really long blog post, you can separate them into many files. To accomplish that, you simply have to make your files like:

+ +
+multi/blog/2010-06-01-the-title.md
+multi/blog/2010-06-01-the-title/second_part.md
+multi/blog/2010-06-01-the-title/third_part.md
+
+ +

mobileme

+ +

All files are intended to be generated into the output/n3blog directory. +This was made like that to work nicely with iWeb organisation of websites.

+ + + +

The order of post is done using the menupriority meta-data in the header of the files.

+ +

You can hide some file from the menu by setting: isHidden: true in the header.

+ +

Details

+ +

To know more about this blog engine, you should look at +nanoc project.

+ +

Then look at the files inside your project:

+
+
+README.md readme for the project (used by github)
+latest.md symbolic link to the last blog entry
+multi/ Directory containing multi-language articles
+tasks/ scripts for website live
+config.yaml global configuration file
+Rules generation rules
+content/ content files processed by nanoc
+layouts/ erb templates
+lib/ ruby libraries used to process files
+output/ website
+Rakefile not mandatory for this blog
+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 15/06/2010 + modifié le : 24/06/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-06-17-hide-yourself-to-analytics/code/become_hidden.html b/output/n3blog/fr/blog/2010-06-17-hide-yourself-to-analytics/code/become_hidden.html new file mode 100644 index 000000000..e3f00f255 --- /dev/null +++ b/output/n3blog/fr/blog/2010-06-17-hide-yourself-to-analytics/code/become_hidden.html @@ -0,0 +1,21 @@ + + + + + + + + + + Hide to analytics + + +
+ + diff --git a/output/n3blog/fr/blog/2010-06-17-hide-yourself-to-analytics/code/become_visible.html b/output/n3blog/fr/blog/2010-06-17-hide-yourself-to-analytics/code/become_visible.html new file mode 100644 index 000000000..3593c9bfc --- /dev/null +++ b/output/n3blog/fr/blog/2010-06-17-hide-yourself-to-analytics/code/become_visible.html @@ -0,0 +1,21 @@ + + + + + + + + + + Hide to analytics + + +
+ + diff --git a/output/n3blog/fr/blog/2010-06-17-hide-yourself-to-analytics/index.html b/output/n3blog/fr/blog/2010-06-17-hide-yourself-to-analytics/index.html new file mode 100644 index 000000000..3321db55f --- /dev/null +++ b/output/n3blog/fr/blog/2010-06-17-hide-yourself-to-analytics/index.html @@ -0,0 +1,264 @@ + + + + + + + + + + + + + + + + + + + + + + + Se cacher de ses statistiques web + + + + +
+ + +
+

+ Se cacher de ses statistiques web +

+ +
+ +
+ + + + + +
+
+
+

Voici un moyen très simple de ne plus être comptabilisé dans les visites de son propre site. +Tout d’abord, vous devriez jeter un coup d’œil sur comment je gère les systèmes de récupération de statistiques. +Je centralise tout dans un seul fichier javascript ce qui facilite le travail.

+ +

Cette méthode nécessite l’utilisation de jquery-cookie.

+ +

Avant de comptabiliser les visites, je vérifie que la clé admin n’est pas utilisée dans mes cookies.

+ +
+    var admin = $.cookie('admin');
+    if (! admin) {
+        // put your analytics code here
+    } else {
+        console.log("[WARNING] you're HIDDEN to analytics");
+    }
+
+ +

et il suffit de créer deux fichier html. Un pour se cacher :

+ +
+
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="fr" xml:lang="fr">
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+        <script type="text/javascript" src="jquery.js"></script>
+        <script type="text/javascript" src="jquery.cookie.js"></script>
+        <script>
+            $(document).ready(function(){
+                $.cookie('admin',1);
+                $('#info').html('Analytics can no more see you.')
+            });
+        </script>
+        <title>Hide to analytics</title>
+    </head>
+    <body>
+        <div id="info"></div> 
+    </body>
+</html>
+
+
+ +

et un autre pour redevenir visible (ça peut être utile) :

+ +
+
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="fr" xml:lang="fr">
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+        <script type="text/javascript" src="jquery.js"></script>
+        <script type="text/javascript" src="jquery.cookie.js"></script>
+        <script>
+            $(document).ready(function(){
+                $.cookie('admin',null);
+                $('#info').html('Analytics can see you.')
+            });
+        </script>
+        <title>Hide to analytics</title>
+    </head>
+    <body>
+        <div id="info"></div> 
+    </body>
+</html>
+
+
+ +

Maintenant en accédant à ces fichiers depuis votre navigateur vous pouvez disparaître des systèmes d’analyses ou bien être considéré comme tous les autres individus. +Pensez à accéder à ces fichiers depuis tous les navigateurs que vous utilisez et vos visites ne seront plus comptabilisées.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 17/06/2010 + modifié le : 18/06/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-06-17-track-events-with-google-analytics/code/yga.js b/output/n3blog/fr/blog/2010-06-17-track-events-with-google-analytics/code/yga.js new file mode 100644 index 000000000..31369ad5c --- /dev/null +++ b/output/n3blog/fr/blog/2010-06-17-track-events-with-google-analytics/code/yga.js @@ -0,0 +1,46 @@ + +$(document).ready( function() { + // add an event to all link for google analytics + $('a').click(function () { + // tell analytics to save event + try { + var identifier=$(this).attr('id') ; + var href=$(this).attr('href') + var label=""; + if ( typeof( identifier ) != 'undefined' ) { + label=label+'[id]:'+identifier + category='JSLink' + } + if ( typeof( href ) != 'undefined' ) { + label=label+' [href]:'+href + if ( href[0] == '#' ) { + category='Anchor'; + } else { + category='Link'; + } + } + _gaq.push(['_trackEvent', category, 'clicked', label]); + // console.log('[tracked]: ' + category + ' ; clicked ; ' + label ); + } + catch (err) { + console.log(err); + } + + // pause to allow google script to run + var date = new Date(); + var curDate = null; + do { + curDate = new Date(); + } while(curDate-date < 300); + }); +}); + +var _gaq = _gaq || []; +_gaq.push(['_setAccount', 'UA-XXXXXXXX-1']); +_gaq.push(['_trackPageview']); + +(function() { + var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; + ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; + var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); + })(); diff --git a/output/n3blog/fr/blog/2010-06-17-track-events-with-google-analytics/index.html b/output/n3blog/fr/blog/2010-06-17-track-events-with-google-analytics/index.html new file mode 100644 index 000000000..fc7ce08e3 --- /dev/null +++ b/output/n3blog/fr/blog/2010-06-17-track-events-with-google-analytics/index.html @@ -0,0 +1,263 @@ + + + + + + + + + + + + + + + + + + + + + + + Analyser les clicks sur votre Site + + + + +
+ + +
+

+ Analyser les clicks sur votre Site +

+ +

+ Utiliser Google Analytics comme un Pro +

+ +
+ +
+ + + + + +
+
+
+

Voici comment analyser tous les clics que font vos utilisateurs sur votre blog en incluant google analytics de façon asynchrone.

+ +

Dans le html, il faut utiliser jQuery et un fichier que j’ai appelé yga.js :

+ +
+    <script type="text/javascript" src="jquery.js"></script>
+    <script type="text/javascript" src="yga.js"></script>
+
+ +

Voici le contenu du fichier yga.js :

+ +
+
+$(document).ready( function() {
+    // add an event to all link for google analytics
+    $('a').click(function () {
+        // tell analytics to save event
+        try {
+            var identifier=$(this).attr('id') ;
+            var href=$(this).attr('href')
+            var label="";
+            if ( typeof( identifier ) != 'undefined' ) {
+                label=label+'[id]:'+identifier
+                category='JSLink'
+            }
+            if ( typeof( href ) != 'undefined' ) {
+                label=label+' [href]:'+href
+                if ( href[0] == '#' ) {
+                    category='Anchor';
+                } else {
+                    category='Link';
+                }
+            }
+            _gaq.push(['_trackEvent', category, 'clicked', label]);
+            // console.log('[tracked]: ' + category + ' ; clicked ; ' + label );
+        }
+        catch (err) {
+            console.log(err);
+        }
+
+        // pause to allow google script to run
+        var date = new Date();
+        var curDate = null;
+        do {
+            curDate = new Date();
+        } while(curDate-date < 300);
+    });
+});
+
+var _gaq = _gaq || [];
+_gaq.push(['_setAccount', 'UA-XXXXXXXX-1']);
+_gaq.push(['_trackPageview']);
+
+(function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+
+
+ +

Remplacez le : UA-XXXXXXXX-1 par votre code google analytics. Maintenant l’installation est finie.

+ +

Pour l’utiliser il suffit de se rendre dans google analytics rubrique Content puis Event Tracking comme sur la capture d’écran suivante :

+ +

Where to find events tracking in google analytics interface

+ +

Joyeuse inspection du comportement de vos utilisateurs.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 17/06/2010 + modifié le : 17/06/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-06-19-jQuery-popup-the-easy-way/code/essai.js b/output/n3blog/fr/blog/2010-06-19-jQuery-popup-the-easy-way/code/essai.js new file mode 100644 index 000000000..751a56c5c --- /dev/null +++ b/output/n3blog/fr/blog/2010-06-19-jQuery-popup-the-easy-way/code/essai.js @@ -0,0 +1,23 @@ + +// --- code popup --- +function openPopup() { + $(this).clone(false).appendTo($("#_code")); + $("#_code").show(); +} + +function closePopup() { + $("#_code").html(""); + $("#_code").hide(); +} + +function initCode() { + $(".code").click(openPopup); + $(".code").css({cursor: "pointer"}); + $('body').append('
'); + $('#_code').css( { 'text-align': "justify", position: "fixed", + left:0, top:0, width: "100%", height: "100%", + "background-color": "rgba(0, 0, 0, 0.8)", 'z-index':2000, 'padding':'3px'} ); + $('#_code').hide(); + $('#_code').click(closePopup); +} +// --- end of code popup section --- diff --git a/output/n3blog/fr/blog/2010-06-19-jQuery-popup-the-easy-way/index.html b/output/n3blog/fr/blog/2010-06-19-jQuery-popup-the-easy-way/index.html new file mode 100644 index 000000000..162b8f68f --- /dev/null +++ b/output/n3blog/fr/blog/2010-06-19-jQuery-popup-the-easy-way/index.html @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + Comment faire des popups en jQuery rapidement + + + + +
+ + +
+

+ Comment faire des popups en jQuery rapidement +

+ +
+ +
+ + + + + +
+
+
+

Sur ce blog, je donne parfois la possibilité de télécharger certaines sources de code. +Dans ce cas, le code est souvent plus large que le div qui le contient. +Le texte est alors coupé. +C’est pourquoi, j’utilise une méthode qui permet d’afficher ces sources dans de grandes popups en jQuery.

+ +

Vous pouvez faire un essai en cliquant le code suivant ; remarquez qu’un bout du code n’est pas visible (après z-index normallement) :

+ +
+
+// --- code popup ---
+function openPopup() {
+    $(this).clone(false).appendTo($("#_code"));
+    $("#_code").show();
+}
+
+function closePopup() {
+    $("#_code").html("");
+    $("#_code").hide();
+}
+
+function initCode() {
+    $(".code").click(openPopup);
+    $(".code").css({cursor: "pointer"});
+    $('body').append('<div id="_code"></div>');
+    $('#_code').css( { 'text-align': "justify", position: "fixed", 
+                        left:0, top:0, width: "100%", height: "100%", 
+                        "background-color": "rgba(0, 0, 0, 0.8)", 'z-index':2000, 'padding':'3px'} );
+    $('#_code').hide();
+    $('#_code').click(closePopup);
+}
+// --- end of code popup section ---
+
+
+ +

Ce code est celui qui permet d’obtenir cet effet.

+ +

Que fait-il ?

+ +

Au chargement de la page je crée un div grand comme toute la page avec un fond légèrement transparent que je cache. +Je fais bien attention à son z-index pour qu’il soit devant tout le reste.

+ +

Puis lorsque l’on clique sur un div de class code, +je recopie le contenu de celui-ci dans le grand div que je rend visible. +Très simple mais très efficace. +Pas besoin d’utiliser un plugin jQuery.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 19/06/2010 + modifié le : 19/06/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-07-05-Cappuccino-and-Web-applications/index.html b/output/n3blog/fr/blog/2010-07-05-Cappuccino-and-Web-applications/index.html new file mode 100644 index 000000000..4bead7153 --- /dev/null +++ b/output/n3blog/fr/blog/2010-07-05-Cappuccino-and-Web-applications/index.html @@ -0,0 +1,351 @@ + + + + + + + + + + + + + + + + + + + + + + + Cappuccino ou jQuery ? + + + + +
+ + +
+

+ Cappuccino ou jQuery ? +

+ +
+ +
+ + + + + +
+
+
+ +
+ + +

tlàl:

+ +
    +
  • J’ai essayé de faire une version de YPassword en jQuery et avec Cappuccino.
  • +
  • Cappuccino est très bien sur les navigateurs non mobile mais l’application pèse 1.4Mo et n’est pas compatible avec l’iPhone.
  • +
  • la version jQuery n’est pas aussi jolie que la version réalisée avec Cappuccino mais elle pèse seulement 106Ko et est compatible avec l’iPhone.
  • +
  • J’essayerai Dashcode 3
  • +
+ + +
+ + +
+ +
+ + +

Avant de commencer, je dois dire que je sais que Cappuccino et jQuery ne sont pas plus comparable que Cocoa et la standard library en C++. L’un est fait pour créer des interfaces utilisateurs tandis que l’autre est plus une librairie qui aide aux tâches de bas niveaux. +Par contre je les ai utilisé tous les deux pour faire la même application. C’est pourquoi je compare l’expérience que j’ai retenu de chacun pour cette tâche.

+ + +
+ + +

J’ai fait une version web de mon widget YPassword. +C’est un simple widget qui permet d’organiser ses mots de passes simplement avec une grande sécurité et de façon portable. +Ce n’est pas un widget créé pour remplacer le trousseau d’accès, mais +plus un générateur de mots de passe.

+ +

Le premier a été élaboré à partir du code de mon widget Mac. +Vous pouvez l’essayer ici. +J’ai ensuite fait une version avec Cappuccino, que vous pouvez essayer ici.

+ +

Que fait ce widget ?

+ + +
+ + +

Si vous vous moquez de savoir ce que fait mon widget, vous pouvez allez directement à la section suivante.

+ + +
+ + +

J’organise mes mots de passe avec une méthode simple. +Je mémorise un mot de passe maître. Et mon mot de passe est alors (principalement) : +<pre class="twilight">hash(motDePasseMaitre+NomDeDomaine) +</pre>

+ +

En réalité j’ai besoin d’un plus d’informations pour créer mon mot de passe :

+ +
    +
  • Un mot de passe maître ;
  • +
  • une URL ;
  • +
  • une longeur maximale de mot de passe ;
  • +
  • le type de sortie (hexadécimale ou base64) ;
  • +
  • Combien de fois mon mot de passe a dû être changé.
  • +
+ +

Le mot de passe résultant est calculé comme suit :

+ +
+domainName=domaine_Name_Of_URL(url)
+hash=sha1( masterPassword + leakedTimes + domainName )
+if ( kind == 'base64' )
+    hash=base64(hash)
+end
+return hash[0..maxlength]
+
+ +

En fait, selon le site web, on peut avoir des contraintes très différentes :

+ +
    +
  • longueur minimale ;
  • +
  • longueur maximale ;
  • +
  • ne doit pas contenir de caractères spéciaux ;
  • +
  • doit contenir des caractères spéciaux ;
  • +
  • etc…
  • +
+ +

Et si vous souhaitez changer votre mot de passe, le nombre de changement sert à ça. +Toutes les informations peuvent rester publiques sans trop de danger à l’exception du mot de passe principal.

+ +

Si vous souhaitez avoir encore plus de détails vous pouvez toujours lire certaines de mes anciens articles de blog (en anglais) :

+ + + +

Cappuccino

+ +

Tout d’abord je voudrais dire que les applications réalisées avec Cappuccino sont tout simplement incroyables. +C’est comme avoir une application Mac dans son navigateur.

+ +

Je dois aussi admettre que j’ai pris du plaisir a écrire mon application avec Cappuccino. +C’est comme programmer une application Mac ou iPhone. +Si vous connaissez bien Cocoa, vous vous sentirez comme à la maison. +Si vous ne connaissez pas Cocoa, je vous conseille de vous y intéresser. +Il s’agit vraiment d’un framework excellent pour faire des interfaces utilisateur. +Je ne suis pas un spécialiste de tous les frameworks. +Mais j’ai réalisé des Interfaces Utilisateurs avec les MFC, Java Swing1 et WXWindows il y a quelques années. +Et je dois dire que Cocoa est bien meilleurs que tous ces framework.

+ +

Cappuccino est un framework spécialisé dans le développement d’application web vraiment exceptionnel. Mais il a aussi quelques défauts qui ont surgit lors de l’écriture de mon widget.

+ +

Les choses qui m’ont plu :

+ +
    +
  • Le résultat est vraiment très beau
  • +
  • C’était très agréable de programmer
  • +
  • Comme programmer une application Mac
  • +
  • J’aurai pu utiliser Interface Builder pour créer l’interface.
  • +
+ +

Les choses qui ne m’ont pas plu :

+ +
    +
  • J’ai mis un bon moment avant de comprendre comment récupérer le onChange des champs textuels.
  • +
  • La documentation manquait d’organisation.
  • +
  • Ça ne marche pas sous iPhone.
  • +
  • Il a fallu déployer 11Mo.
  • +
  • Il faut télécharger 1,3Mo pour que l’application se charge dans le navigateur.
  • +
+ +

Je n’ai pas utilisé les bindings parce qu’il me semble qu’ils ne sont pas prêts.

+ +

jQuery

+ +

La version jQuery de YPassword n’est pas aussi bien finie que celle de Cappuccino. Simplement parce qu’il n’y a pas de slider directement avec jQuery. Il faudrait que j’utilise jQueryUI. Et je pense que l’application deviendrait beaucoup plus lourde pour le coups. En tout cas largement au dessus des 106Ko actuels.

+ +

J’ai utilisé le code de mon widget mac en l’adaptant un peu pour faire cette version. C’était relativement facile. Mais jQuery n’est pas un framework orienté application. Il s’agit plus d’un framework pour faire des animations qui la pète.

+ +

Je n’ai pas beaucoup plus à dire sur la version jQuery, sinon que programmer avec jQuery était de la programmation de niveau beaucoup plus bas qu’avec Cappuccino.

+ +

En conclusion

+ +

Si vous voulez faire une application compatible iPhone n’utilisez pas Cappuccino. Du moins pas encore. +Si vous souhaitez faire un application très simple (comme la mienne), je pense que Cappuccino est un peu trop lourd pour ça.

+ +

Si vous souhaitez faire des applications web complexes qui ressemblent à des applications de bureau alors clairement Cappuccino est un très bon choix. +Notez cependant qu’il peut être un peu difficile de débuter.

+ +

Finallement, pour terminer la version web de mon widget, j’essayerai Dashcode 3. +Il semblerai que ce soit une bonne alternative pour créer des widget sur le web compatible iPhone. +Je ne sais pas si les applications réalisées avec Dashcode 3 sont compatibles pour les browser n’utilisant pas webkit. Mais si c’est le cas, alors ça pourrait sonner le glas des projets comme Cappuccino et Sproutcore.

+
+
    +
  1. +

    Si ça vous intéresse vous pouvez jeter un coup d’œil à SEDiL. Je suis assez fier de la vue automatique des arbres que j’ai programmé sans librairie de départ.

    +
  2. +
+
+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 05/07/2010 + modifié le : 17/07/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-07-07-CSS-rendering-problems-by-navigator/index.html b/output/n3blog/fr/blog/2010-07-07-CSS-rendering-problems-by-navigator/index.html new file mode 100644 index 000000000..a26dbfd94 --- /dev/null +++ b/output/n3blog/fr/blog/2010-07-07-CSS-rendering-problems-by-navigator/index.html @@ -0,0 +1,222 @@ + + + + + + + + + + + + + + + + + + + + + + + N'utilisez pas de gradients avec Chrome + + + + +
+ + +
+

+ N'utilisez pas de gradients avec Chrome +

+ +
+ +
+ + + + + +
+
+
+

Beaucoup d’utilisateurs de Reddit m’ont rapporté que mon site était très long à charger et à scroller. +Ils pensaient qu’il s’agissait d’un problème dû aux ombres que j’applique sur le texte. +J’étais un peu surpris puisque je fais mes tests sur une machine vraiment très lente et je n’avais jamais détecté ces problèmes. +En réalité, ce qui ralenti le rendu de ce site est par ordre d’importance :

+ +
    +
  1. Les dégradés sur Chrome (pas dans Safari sur Mac)
  2. +
  3. les box shadows sur Firefox
  4. +
+ +

les dégradés

+ +

Sur Safari il n’y a absolument aucun problème avec les dégradés. Par contre sur Chrome sous Linux le site devient quasiment inutilisable.

+ +

Safari et Chrome utilisent webkit tous les deux. Lorsque vous accéder à ce blog avec javascript activé, un CSS spécifique à votre navigateur est ajouté. Jusqu’à maintenant je faisais un tri entre : IE, Mozilla et Webkit. Maintenant j’ai rajouté un cas particulier pour Chrome. +Maintenant j’ai supprimé les gradients lorsque vous naviguer sur ce site en utilisant Chrome.

+ +

Je n’ai pas vérifier la vitesse de rendu de toutes les propriétés de CSS 3. Mais je vous conseille de ne pas utiliser -webkit-gradient avec Chrome. Au moins sous Linux.

+ +

Les ombres (box-shadow)

+ +

J’ai aussi remarqué que -moz-box-shadow ralenti le rendu sous Firefox (et sous Linux). Alors que l’équivalent webkit ne pose aucun problème à Safari sous Mac.

+ +

Ombres de texte

+ +

Beaucoup d’utilisateurs mon dit d’utiliser text-shadows avec parcimonie. Mais je pense qu’il ne s’agissait pas là du problème du ralentissement du site. C’est pourquoi je vais les remettre.

+ +

en conclusion

+ +

N’utilisez pas -webkit-gradient avec google Chrome pour l’instant. +Utilisez -moz-box-shadow avec parcimonie.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 07/07/2010 + modifié le : 07/10/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-07-09-Indecidabilities/index.html b/output/n3blog/fr/blog/2010-07-09-Indecidabilities/index.html new file mode 100644 index 000000000..aba74e48a --- /dev/null +++ b/output/n3blog/fr/blog/2010-07-09-Indecidabilities/index.html @@ -0,0 +1,425 @@ + + + + + + + + + + + + + + + + + + + + + + + Indécidabilités (partie 1) + + + + +
+ + +
+

+ Indécidabilités (partie 1) +

+ +
+ +
+ + + + + +
+
+
+ +
+ + +

tlàl : Je crée un mode mathématique simple pour parler de différents types d’indécidabilités :

+ +
    +
  • indécidabilité due aux erreurs d’observation ;
  • +
  • grandes erreurs résultant de petites erreurs de mesure ;
  • +
  • indécidabilité fractales ;
  • +
  • indécidabilité logique.
  • +
+ + +
+ + + +
+ +
+ + +

Les indécidabilités

+ + +
+ + +

Si le monde a été fabriqué par un démiurge, on peut dire que celui-ci devait avoir le sens de l’humour. +Et le récit que je vais faire va vous en fournir la preuve. +Je vais me mettre à sa place. +Je vais créer un monde simplifié. +Un monde régi exactement par nos règles mathématiques. +Puis je vais vous parler du mal qui touche cet Univers semblable au notre ; l’indécidabilité. +L’incapacité de savoir si nous avons trouvé la vérité, ou seulement une approximation de celle-ci. +L’incapacité de prédire certaines choses qui semblent pourtant aller de soi. +Voilà comment tout aurait pu commencer.

+ + +
+ + +

no name

+ +

Au début, il n’y avait rien. +Puis un article de blog commença à prendre forme. +J’inspire profondément pour sentir la pesanteur de ce que je vais accomplir. +Attention, une dernier moment de tension et je crée l’Univers. +Un Univers qui n’existera que le temps de la lecture de cet article. +Me voici le démiurge de cet Univers et te voilà son observateur privilégié.

+ +

Comme j’aime bien tout contrôler, je fabrique ce monde avec quelques règles simples. +Je décide que les vrais règles de ce monde sont celles que nous pensons qui régissent notre monde. +Notez qu’il y a une grande différence. +Pour leur monde, ce que l’on croit vrai aujourd’hui, est vraiment vrai pour eux. +Leur monde est donc plus simple à priori que le notre. +En particulier, on peut le décrire avec des axiomes et des règles mathématiques. +Alors qu’il est possible que ce ne soit pas le cas de notre Univers. +Mais nous reviendront là-dessus plus tard.

+ +

Bon au travail maintenant, je crée une Terre. +J’y ajoute des habitants intelligents, les Ys. +Bien entendu ils se posent des questions. +En particulier, ils se demandent quelles sont les lois qui régissent leur monde. +Ils pensent que connaître toutes ces règles leur permettrait de connaître l’avenir. +Leur naïveté est touchante. +Ah, si seulement ils savaient. +Mais je suis là pour les aider à apprendre.

+ +

Comme je suis un Dieu un peu facétieux, je vais leur jouer quelques tours. +Sinon on s’ennuierai à mourir. +Le premier est de leur donner des sens imparfaits. +De plus il leur est impossible d’avoir des mesures parfaites. +Je leur laisse cependant toutes libertés pour améliorer leur technologie et diminuer ces erreurs de mesures.

+ +

Les habitants de ce monde pensent que celui-ci est plat. +Certains d’entre eux pensent qu’il est possible de découvrir les règles du monde que j’ai créé. +Et bien que le jeu commence.

+ +

Commençons par leur première leçon, les erreurs causent de l’indécidabilité.

+ +

Indécidabilité dues aux erreurs de mesures

+ +

Voici ce que pense l’un de ces individus.

+ +
+

Tous les triangles que j’observe semble avoir une propriété commune. +La somme de leurs angles est toujours π radiants (180°). +Il s’agit certainement d’une loi de mon Univers. +Mais comment être certain que tous les triangles de mon Univers possèdent cette propriété ?

+
+ +

no name

+ +

Certain d’entre eux commencent à formaliser un petit peu le problème +et ils finissent faire une preuve mathématique. +Magnifique ! +La preuve est correcte, mais il reste un petit problème. +La preuve s’appuie sur des axiomes et des règles. +Comment être certain que ces règles et ces axiomes sont vrai dans leur monde? +Ils auront beau faire des mesures de plus en plus précises qui conforteront cette formule, +ils n’auront que l’espoir et jamais la certitude que la formule est vrai. +Simplement parce que le seul moyen de vérifier la véracité des axiomes est par l’observation. +Hors en tant que dieu facétieux, j’ai interdit les observation avec des mesures parfaites.

+ +

Bien entendu, ils prient, ils m’appellent à l’aide. +Et comme tout Dieu qui se respecte, je ne réponds pas. +Ah ah ah ! J’ai toujours aimé faire ce genre de chose. +Ensuite je ferai comme si je n’existe pas. +Encore un bonne blague !

+ +

Si certains se sentent accablés, il leur reste un espoir :

+ +
+

Espoir

+ +

Si nous faisons de faibles erreurs de mesure, nous aurons de faibles erreurs dans nos prédictions.

+
+ +

Indécidabilité avec erreurs croissantes

+ +

no name

+ +

Malheureusement pour eux, il y a le problème des 3 corps. +Prenons les formules de la gravitation Universelle et appliquons la à deux corps célestes. +Si on connait la position de ces corps avec un grande précision, on pourra aussi connaître la position future de ces corps avec une grande précision. +L’hypothèse selon laquelle de petite erreurs de mesures impliquent de petites erreurs prédictive est confortée. +Cependant, il y a un problème. +Reprenons le même problème mais avec trois corps. Par exemple, avec le Soleil, la Terre et la Lune. +Dans ce cas, les erreurs de mesures initiales vont s’amplifier. +S’amplifier au point de rendre toute prédiction inutilisable.

+ +

Là encore une voix d’espoir s’élève : +> Peut-être pouvons nous calculer l’erreur maximale acceptable pour prédire quelque chose. +> Et nous pourrions au moins savoir ce que nous pouvons prédire ou pas.

+ +

Une fois encore, ça ne va pas très bien se passer.

+ +

Indécidabilité fractale

+ +

Considérons la question suivante :

+ +

no name

+ +

Soit des coordonnées GPS précises à 1m près. +Les coordonnées sont proches des côtes de la Bretagne. +Ce point va-t-il tomber dans la mer ou sur la terre ferme ?

+ +

Et bien, pour certaines coordonnées, c’est impossible de le savoir. +Même si je réduis l’erreur à une valeur infinitésimale. +Simplement parce que certains voisinages autour d’un point contiennent toujours à la fois de l’eau et de la terre. +Et ce quelque soit la taille du voisinage.

+ +

On peut même imaginer une structure ou tous les points sont au bord de celle-ci, on ne peut donc pas se permettre d’erreur[^2]. +[^2]: Pensez aux deux ensembles R\Q et Q.

+ +

Mais que vois-je ? +Un petit malin essaye de trouver la vérité en s’extrayant de mon Monde et en faisant un article sur un blog ? +Ça ne va pas se passer comme ça ! Croyez moi ! +> Faire des prédictions précises à partir des données observées semble être une quête vouée à l’échec. +> Mais je suis persuadé que l’on peut aller au delà. +> Au diable ce Dieu qui nous empêche d’avoir des mesures précises ! +> Inventons notre propre Univers mathématique. +> Un monde qui se suffit à lui-même. +> Un monde dans lequel il n’y aura plus d’erreur de mesure. +> Un monde entièrement contrôlé par des règles que nous aurons choisi. +> Un monde similaire au notre mais où tout pourra être prédit.

+ +

Indécidabilité logique

+ +

no name

+ +

Jusqu’ici, tous les problèmes d’indécidabilités étaient dûs aux erreurs. +Maintenant peut-être que privé d’erreur de mesure, on pourrait enfin résoudre tous les problèmes.
+Et bien non. +Même dans un monde mathématique complètement contrôlé. +On peut créer un objet pour lequel on ne pourra pas décider à l’avance ce qu’il fait.

+ +

Il s’agit du problème de l’arrêt.

+ +

Le Théorème stipule qu’il n’existe pas de programme permettant de décider si un autre programme s’arrête. +La preuve est suffisamment simple pour rentrer dans ce post, donc je me fais un petit plaisir en la donnant.

+ +
+

Supposons qu’il existe un programme qui puisse dire si un autre programme s’arrête. Plus précisément :

+ +

Hypothèse: Il existe un programme P tel que:

+ +
    +
  • P(x,y) réponde “s’arrête” en un temps fini si et seulement si x(y)1 s’arrête effectivement en temps fini et
  • +
  • P(x,y) réponde “ne s’arrête pas” en un temps fini dans le cas contraire.
  • +
+ +

Remarque: Tout code de programme est une chaîne de caractère qui peut être utilisée aussi comme entrée d’un autre programme. +Ainsi écrire P(x,x) est autorisé.

+ +

Soit le programme Q que j’écris comme suit : +<pre class="twilight"> +Q(x) : + si P(x,x)=”s’arrête” alors je fais une boucle infinie. + si P(x,x)=”ne s’arrête pas” alors je m’arrête. +</pre>

+ +

Maintenant que répond P(Q,Q)?

+ +
    +
  • si P(Q,Q) répond “s’arrête” ça implique que P(Q,Q)=”ne s’arrête pas”
  • +
  • si P(Q,Q) répond “ne s’arrête pas” ça implique que P(Q,Q)=”s’arrête”
  • +
+ +

Il y a donc une contradiction que le seul moyen de régler est par la non existence du programme P.

+
+ +

C’est simple, je suis le démiurge de ce monde imaginaire. +Et même moi, je dois me soumettre à cette règle. +Comme quoi, avoir la possibilité de créer le monde et la toute puissance sont deux choses différentes.

+ + +
+ +
+ + +

Après tout ceci, il peut sembler difficile de savoir en quoi nous pouvons croire. +Mais ce serait une erreur de jeter le bébé avec l’eau du bain. +Dans une seconde partie, j’expliquerai ce que nous pouvons espérer et qu’elle attitude nous devons adopter une fois que l’on a réalisé que beaucoup de vérité nous sont inaccessibles.

+
+
    +
  1. +

    C’est-à-dire le programme x prenant l’entrée y.

    +
  2. +
+
+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 11/08/2010 + modifié le : 17/08/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-07-31-New-style-after-holidays/index.html b/output/n3blog/fr/blog/2010-07-31-New-style-after-holidays/index.html new file mode 100644 index 000000000..8d748cfd4 --- /dev/null +++ b/output/n3blog/fr/blog/2010-07-31-New-style-after-holidays/index.html @@ -0,0 +1,198 @@ + + + + + + + + + + + + + + + + + + + + + + + Nouveau style après les vacances + + + + +
+ + +
+

+ Nouveau style après les vacances +

+ +
+ +
+ + + + + +
+
+
+

Avant les vacances beaucoup d’utilisateurs se sont plaints de la lenteur de rendu de mon site. +Il s’agit notamment de problèmes avec Chrome en particulier. +Mais pour éviter tout problème. +J’ai complètement modifié le style de mon site web. +Il est inspiré du style de l’application iBooks© sur iPhone©.

+ +

Dites moi ce que vous pensez de ce nouveau design.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 31/07/2010 + modifié le : 01/08/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-08-23-Now-heberged-on-heroku/code/.gems b/output/n3blog/fr/blog/2010-08-23-Now-heberged-on-heroku/code/.gems new file mode 100644 index 000000000..7c156f5cb --- /dev/null +++ b/output/n3blog/fr/blog/2010-08-23-Now-heberged-on-heroku/code/.gems @@ -0,0 +1,4 @@ + +rack +rack-rewrite +rack-contrib diff --git a/output/n3blog/fr/blog/2010-08-23-Now-heberged-on-heroku/code/config.ru b/output/n3blog/fr/blog/2010-08-23-Now-heberged-on-heroku/code/config.ru new file mode 100644 index 000000000..78678fb46 --- /dev/null +++ b/output/n3blog/fr/blog/2010-08-23-Now-heberged-on-heroku/code/config.ru @@ -0,0 +1,43 @@ + +require 'rubygems' +require 'rack' +require 'rack/contrib' +require 'rack-rewrite' +require 'mime/types' + +use Rack::ETag +module ::Rack + class TryStatic < Static + + def initialize(app, options) + super + @try = ([''] + Array(options.delete(:try)) + ['']) + end + + def call(env) + @next = 0 + while @next < @try.size && 404 == (resp = super(try_next(env)))[0] + @next += 1 + end + 404 == resp[0] ? @app.call : resp + end + + private + def try_next(env) + env.merge('PATH_INFO' => env['PATH_INFO'] + @try[@next]) + end + + end +end + +use Rack::TryStatic, + :root => "output", # static files root dir + :urls => %w[/], # match all requests + :try => ['.html', 'index.html', '/index.html'] # try these postfixes sequentially + +errorFile='output/n3blog/en/error/404-not_found/index.html' +run lambda { [404, { + "Last-Modified" => File.mtime(errorFile).httpdate, + "Content-Type" => "text/html", + "Content-Length" => File.size(errorFile).to_s + }, File.read(errorFile)] } diff --git a/output/n3blog/fr/blog/2010-08-23-Now-heberged-on-heroku/index.html b/output/n3blog/fr/blog/2010-08-23-Now-heberged-on-heroku/index.html new file mode 100644 index 000000000..f2efd7289 --- /dev/null +++ b/output/n3blog/fr/blog/2010-08-23-Now-heberged-on-heroku/index.html @@ -0,0 +1,281 @@ + + + + + + + + + + + + + + + + + + + + + + + Maintenant sur Heroku + + + + +
+ + +
+

+ Maintenant sur Heroku +

+ +

+ Héberger un site web statique sur heroku +

+ +
+ +
+ + + + + +
+
+
+

Maintenant sur Heroku

+ +

J’ai changé mon hébergeur. Mobileme n’est absolument pas adapté à la diffusion de mon blog. C’est pourquoi je suis passé à Heroku.

+ +

Mais comme vous devez le savoir mon blog est un site complètement statique. +J’utilise nanoc pour l’engendrer. +Avoir un site statique amène beaucoup d’avantages par rapport à un site dynamique. Surtout en terme de sécurité. +Voici comment configurer un site statique sur heroku.

+ +

La racine de mes fichiers est ‘/output’. Vous devez simplement créer deux fichiers. Un fichier config.ru1 :

+ +
+
+require 'rubygems'
+require 'rack'
+require 'rack/contrib'
+require 'rack-rewrite'
+require 'mime/types'
+
+use Rack::ETag
+module ::Rack
+    class TryStatic < Static
+
+        def initialize(app, options)
+            super
+            @try = ([''] + Array(options.delete(:try)) + [''])
+        end
+
+        def call(env)
+            @next = 0
+            while @next < @try.size && 404 == (resp = super(try_next(env)))[0] 
+                @next += 1
+            end
+            404 == resp[0] ? @app.call : resp
+        end
+
+        private
+        def try_next(env)
+            env.merge('PATH_INFO' => env['PATH_INFO'] + @try[@next])
+        end
+
+    end
+end
+
+use Rack::TryStatic, 
+    :root => "output",                              # static files root dir
+    :urls => %w[/],                                 # match all requests 
+    :try => ['.html', 'index.html', '/index.html']  # try these postfixes sequentially
+
+errorFile='output/n3blog/en/error/404-not_found/index.html'
+run lambda { [404, {
+                "Last-Modified"  => File.mtime(errorFile).httpdate,
+                "Content-Type"   => "text/html",
+                "Content-Length" => File.size(errorFile).to_s
+            }, File.read(errorFile)] }
+
+
+ +

et un fichier .gems qui liste les gems nécessaires.

+ +
+
+rack
+rack-rewrite
+rack-contrib
+
+
+ +

Maintenant il suffit de suivre l’introduction rapide d’heroku pour créer une nouvelle application :

+ +
+git init
+git add .
+heroku create
+git push heroku master
+
+ +

Maintenant je peux rediriger correctement mes erreurs 404. +J’espère que ça a pu vous être utile.

+
+
    +
  1. +

    Je me suis complètement inspiré de cet article.

    +
  2. +
+
+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 23/08/2010 + modifié le : 16/09/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-08-31-send-mail-from-command-line-with-attached-file/index.html b/output/n3blog/fr/blog/2010-08-31-send-mail-from-command-line-with-attached-file/index.html new file mode 100644 index 000000000..d0154067e --- /dev/null +++ b/output/n3blog/fr/blog/2010-08-31-send-mail-from-command-line-with-attached-file/index.html @@ -0,0 +1,264 @@ + + + + + + + + + + + + + + + + + + + + + + + Envoyer un mail en ligne de commande avec un fichier attaché + + + + +
+ + +
+

+ Envoyer un mail en ligne de commande avec un fichier attaché +

+ +
+ +
+ + + + + +
+
+
+

J’ai dû envoyer un mail en ligne de commande récemment. +Quelle ne fût pas ma surprise lorsque je constatais que ce n’était vraiment pas évident. +Je n’avais ni pine ni mutt. Seulement mail et mailx.

+ +

Ce qu’on trouve sur internet pour envoyer un mail avec fichier attaché c’est ça :

+ +
+uuencode fic.jpg fic.jpg | mail -s 'Subject'
+
+ +

Bon, alors, bête et discipliné j’ai essayé. +Et bien, ça marche presque tout le temps. +Pour mon fichier ça n’a pas marché du tout. +Je l’ai compressé au format .gz, .bz2 et .zip. +Avec le format .bz2 le mail reçu avait bien un fichier attaché. +Mais avec les formats .gz et .zip, ça ne fonctionnait pas. +Au lieu d’avoir un fichier attaché j’avais un message qui contenait quelque chose comme :

+ +
+begin 664 fic.jpg
+M(R$O=7-R+V)I;B]E;G8@>G-H"GAL<STD,0H*9F]R(&QI;F4@:6X@)"@\("1X
+M;',@*0H@("`@9&-R/20H96-H;R`D;&EN92!\(&%W:R`M1EP[("=[<')I;G0@
+...
+M93U<(FUO='-<(CX\=F%L=64^/&ET96T@;F%M93U<(F-T>%]M8UPB/BD\=F%L
+M=64O/B@\+VET96T^*2-<)#$\=F%L=64^)&ME>7=O<F1S/"]V86QU93Y<)#(C
+end
+
+ +

Pas très lisible. +Après pas mal de recherche j’ai trouvé la solution. +Le problème c’est uuencode qui est une méthode qui devrait devenir obsolète pour envoyer les fichiers. +Il vaut mieux utiliser le format MIME pour envoyer des fichiers attachés.

+ +

Donc finalement le mieux est de faire ça “à la main” avec sendmail. +Je n’ai quand même pas utilisé telnet. +La commande à lancer est :

+ +
+sendmail -t -oi < mailcontent.txt
+
+ +

Bien entendu il faut créer le fichier mailcontent.txt qui contient :

+ +
+From: from@mail.com
+To: to@mail.com
+Subject: View the attached file
+Mime-Version: 1.0
+Content-Type: multipart/mixed; boundary="-"
+
+This is a MIME encoded message. Decode it with "Decoder"
+or any other MIME reading software. Decoder is available
+at <http://www.etresoft.com>.
+---
+Content-Type: image/jpeg; name="fic.jpg"
+Content-Transfer-Encoding: base64
+Content-Disposition: inline; filename="fic.jpg"
+
+H4sICB6Ke0wAA2Rjcl93aXRob3V0X2tleXdvcmQuY3N2ANSdW5ubOJPH7/e7
+7Brw+dmrTk8yk7yTSTaZeWd2b/TIIGy6MRAE7ng+/VaJgwF3g522SsxN2+3T
+/4eOJamqmARP+yibvI8ykUYim+x5EE2euBfIyd3byZ+fvvzr7svbu8ndTx/f
+...
+
+ +

Et pour avoir le code il suffit de lancer la commande :

+ +

+uuencode -m fic.jpg fic.jpg +

+ +

Et voilà. +Parfois la technique c’est tellement simple. +Si j’en ai besoin encore quelques fois, je pense que j’écrirai un émetteur de mail en shell.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 31/08/2010 + modifié le : 31/08/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes/code/gitmtime.rb b/output/n3blog/fr/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes/code/gitmtime.rb new file mode 100644 index 000000000..f95ac83f9 --- /dev/null +++ b/output/n3blog/fr/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes/code/gitmtime.rb @@ -0,0 +1,15 @@ + +def gitmtime + filepath=@item.path.sub('/n3blog/','content/html/').sub(/\/$/,'') + ext=%{.#{@item[:extension]}} + filepath<<=ext + if not FileTest.exists?(filepath) + filepath.sub!(ext,%{/index#{ext}}) + end + str=`git log -1 --format='%ci' -- #{filepath}` + if str.nil? or str.empty? + return Time.now + else + return DateTime.parse( str ) + end +end diff --git a/output/n3blog/fr/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes/index.html b/output/n3blog/fr/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes/index.html new file mode 100644 index 000000000..a573ed5d9 --- /dev/null +++ b/output/n3blog/fr/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes/index.html @@ -0,0 +1,224 @@ + + + + + + + + + + + + + + + + + + + + + + + Utilisation de git pour calculer les mtimes + + + + +
+ + +
+

+ Utilisation de git pour calculer les mtimes +

+ +
+ +
+ + + + + +
+
+
+

Vous pouvez remarquer qu’à la fin de chaque page je donne une date de dernière modification. +Précédemment cette date était calculée en utilisant la date du fichier. +Mais il arrive fréquemment que je fasse un touch d’un fichier pour engendrer tout le site de nouveau. +Donc la date n’est pas nécessairement la vraie de modification du contenue.

+ +

J’utilise git pour versionner mon site web. +Et cet outil me permet de récupérer la dernière date de vraie modification d’un fichier. +Voici comment je m’y prend avec nanoc :

+ +
+
+def gitmtime
+    filepath=@item.path.sub('/n3blog/','content/html/').sub(/\/$/,'')
+    ext=%{.#{@item[:extension]}}
+    filepath<<=ext
+    if not FileTest.exists?(filepath)
+        filepath.sub!(ext,%{/index#{ext}})
+    end
+    str=`git log -1 --format='%ci' -- #{filepath}`
+    if str.nil? or str.empty?
+        return Time.now
+    else
+        return DateTime.parse( str )
+    end
+end
+
+
+ +

Bien entendu je sais que c’est très lent et absolument pas optimisé. +Mais ça fonctionne comme prévu. +Maintenant la date que vous voyez en bas de la page correspond exactement à la dernière date de modification de son contenu.

+ +

Je tiens à remercier Eric Sunshine pour ses conseils sur ce problème.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 02/09/2010 + modifié le : 03/09/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-09-02-base64-and-sha1-on-iPhone/code/iphone_base64_sha1.c b/output/n3blog/fr/blog/2010-09-02-base64-and-sha1-on-iPhone/code/iphone_base64_sha1.c new file mode 100644 index 000000000..26c5a31f0 --- /dev/null +++ b/output/n3blog/fr/blog/2010-09-02-base64-and-sha1-on-iPhone/code/iphone_base64_sha1.c @@ -0,0 +1,43 @@ + + +- (unsigned char *)sha1:(NSString *)baseString result:(unsigned char *)result { + char *c_baseString=(char *)[baseString UTF8String]; + CC_SHA1(c_baseString, strlen(c_baseString), result); + return result; +} + +- (NSString *)base64:(unsigned char *)result { + NSString *password=[[NSString alloc] init]; + static const unsigned char cb64[65]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + for (int i=0; i>2], + cb64[((result[i] & 0x03) << 4) + | ((result[i + 1] & 0xF0) >> 4)], + cb64[((result[i + 1] & 0x0F) << 2) + | ((result[i + 2] & 0xC0) >> 6)], + cb64[result[i+2]&0x3F] + ]; + } + return password; +} + +- (NSString *)hexadecimalRepresentation:(unsigned char *)result { + NSString *password=[[NSString alloc] init]; + for (int i=0; i + + + + + + + + + + + + + + + + + + + + + + base64 et sha1 sur iPhone + + + + +
+ + +
+

+ base64 et sha1 sur iPhone +

+ +
+ +
+ + + + + +
+
+
+

Allons directement à l’essentiel : +voici deux fonctions à intégrer à votre application iPhone pour afficher l’encodage en base64 ou en hexadecimal du hash sha1 d’un string en Objective-C pour iPhone.

+ +

Pour l’usage c’est très simple, copiez le code dans la classe de votre choix. +Puis :

+ +
+#import <CommonCrypto/CommonDigest.h>
+...
+NSString *b64_hash = [self b64_sha1:@"some NSString to be sha1'ed"];
+...
+NSString *hex_hash = [self hex_sha1:@"some NSString to be sha1'ed"];
+
+ +

L’algorithme pour l’encodage en base64 doit être programmé sur iPhone. +Il n’y a pas de librairie officielle qui s’occupe de ça.

+ +
+
+
+- (unsigned char *)sha1:(NSString *)baseString result:(unsigned char *)result {
+    char *c_baseString=(char *)[baseString UTF8String];
+    CC_SHA1(c_baseString, strlen(c_baseString), result);
+    return result;
+}
+
+- (NSString *)base64:(unsigned char *)result {
+    NSString *password=[[NSString alloc] init];
+    static const unsigned char cb64[65]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+    for (int i=0; i<CC_SHA1_DIGEST_LENGTH; i+=3) {
+        password=[password stringByAppendingFormat:@"%c%c%c%c",
+            cb64[(result[i] &0xFC)>>2],
+            cb64[((result[i] & 0x03) << 4)
+                | ((result[i + 1] & 0xF0) >> 4)],
+            cb64[((result[i + 1] & 0x0F) << 2)
+                | ((result[i + 2] & 0xC0) >> 6)],
+            cb64[result[i+2]&0x3F]
+                ];            
+    }
+    return password;
+}
+
+- (NSString *)hexadecimalRepresentation:(unsigned char *)result {
+    NSString *password=[[NSString alloc] init];
+    for (int i=0; i<CC_SHA1_DIGEST_LENGTH; i++) {
+        password=[password stringByAppendingFormat:@"%02x", result[i]];
+    }
+    return password;
+}
+
+- (NSString *)b64_sha1:(NSString *)inputString {
+    unsigned char result[CC_SHA1_DIGEST_LENGTH+1];
+    [self sha1:inputString result:result];
+    return [self base64:result];
+}
+
+- (NSString *)hex_sha1:(NSString *)inputString {
+    unsigned char result[CC_SHA1_DIGEST_LENGTH+1];
+    [self sha1:inputString result:result];
+    return [self hexadecimalRepresentation:result];
+}
+
+
+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 02/09/2010 + modifié le : 04/09/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-10-06-New-Blog-Design-Constraints/index.html b/output/n3blog/fr/blog/2010-10-06-New-Blog-Design-Constraints/index.html new file mode 100644 index 000000000..d007efa91 --- /dev/null +++ b/output/n3blog/fr/blog/2010-10-06-New-Blog-Design-Constraints/index.html @@ -0,0 +1,209 @@ + + + + + + + + + + + + + + + + + + + + + + + Contraintes du design de ce blog + + + + +
+ + +
+

+ Contraintes du design de ce blog +

+ +
+ +
+ + + + + +
+
+
+

Vous avez pu constater que j’ai modifié le design de mon blog. +Maintenant il doit être beaucoup plus léger qu’avant. +Je n’utilise plus de CSS3 et beaucoup moins de javascript. +Bien entendu, même avant, mes pages étaient parfaitement lisibles sans javascript. +Mais, je me suis aperçu que les systèmes de CSS3 sont loin d’être au point. +J’utilisait des gradient en CSS3, ainsi que des ombres sous le texte. Ça avait un rendu très sympa. Sauf… +Ce n’était pas compatible ie6, sous Chrome le rendu était d’une lenteur incroyable. +J’ai donc décidé de faire un site à minima. +Je voulais qu’il soit joli et le plus simple possible pour assurer sa compatibilité. +Les règles que je me suis fixées sont donc:

+ +
    +
  • pas d’élément CSS qui commence par -moz ou -webkit, etc… ;
  • +
  • pas d’ombre sous le texte pour donner une impression de profondeur ;
  • +
  • nettoyer pas mal le code et enlever tout ce que je peux ;
  • +
+ +

J’espère que ce nouveau design vous plaît.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 06/10/2010 + modifié le : 07/10/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/index.html b/output/n3blog/fr/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/index.html new file mode 100644 index 000000000..2b74e7e70 --- /dev/null +++ b/output/n3blog/fr/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/index.html @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + + + + Sécurisez vos emails + + + + +
+ + +
+

+ Sécurisez vos emails +

+ +
+ +
+ + + + + +
+
+
+

Title image

+ + +
+ + +

tlàl : avec un Mac

+ +
    +
  • Récupérez un certificat signé par une AC: cliquez ici pour un certificat gratuit ;
  • +
  • ouvrez le fichier ;
  • +
  • supprimer le fichier en mode sécurisé ;
  • +
  • utilisez Mail plutôt que l’interface web de gmail.
  • +
+ + +
+ + +

J’ai (re)découvert comment adoptez la norme S/MIME. +J’ai été surpris de voir à quel point ce fut aisé. +Il y a seulement quelques années c’était bien plus difficile à accomplir. +Maintenant je peux signer et chiffrer mes mails.

+ +

Pourquoi est-ce important ?

+ +

Signer : cela permet de certifier avec une absolue certitude que la personne qui a écrit le mail est vous ou au moins qu’elle a utilisé votre ordinateur.

+ +

Chiffrer : parce que parfois il est nécessaire d’être certain qu’une conversation reste privée.

+ +

Comment procéder ?

+ +
    +
  • Récupérez un certificat signé par une authorité de certification : cliquez ici pour récupérer un certificat gratuit ;
  • +
  • ouvrez le fichier ;
  • +
  • supprimer le fichier en mode sécurisé ;
  • +
  • utilisez Mail plutôt que l’interface web de gmail. +Maintenant vous devriez voir ces icônes : +no name
  • +
+ +

n.b. : si vous utilisez gmail et que vous ne travaillez pas toujours avec un Mac, vous devriez considérer d’utiliser le module gmail S/MIME de firefox.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 10/10/2010 + modifié le : 10/10/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-10-14-Fun-with-wav/code/wavsum.c b/output/n3blog/fr/blog/2010-10-14-Fun-with-wav/code/wavsum.c new file mode 100644 index 000000000..214ab6ee5 --- /dev/null +++ b/output/n3blog/fr/blog/2010-10-14-Fun-with-wav/code/wavsum.c @@ -0,0 +1,59 @@ + +#include +#include +#include + +struct wavfile +{ + char id[4]; // should always contain "RIFF" + int totallength; // total file length minus 8 + char wavefmt[8]; // should be "WAVEfmt " + int format; // 16 for PCM format + short pcm; // 1 for PCM format + short channels; // channels + int frequency; // sampling frequency + int bytes_per_second; + short bytes_by_capture; + short bits_per_sample; + char data[4]; // should always contain "data" + int bytes_in_data; +}; + +int main(int argc, char *argv[]) { + char *filename=argv[1]; + FILE *wav = fopen(filename,"rb"); + struct wavfile header; + + if ( wav == NULL ) { + fprintf(stderr,"Can't open input file %s", filename); + exit(1); + } + + + // read header + if ( fread(&header,sizeof(header),1,wav) < 1 ) + { + fprintf(stderr,"Can't read file header\n"); + exit(1); + } + if ( header.id[0] != 'R' + || header.id[1] != 'I' + || header.id[2] != 'F' + || header.id[3] != 'F' ) { + fprintf(stderr,"ERROR: Not wav format\n"); + exit(1); + } + + fprintf(stderr,"wav format\n"); + + // read data + long sum=0; + short value=0; + while( fread(&value,sizeof(value),1,wav) ) { + // fprintf(stderr,"%d\n", value); + if (value<0) { value=-value; } + sum += value; + } + printf("%ld\n",sum); + exit(0); +} diff --git a/output/n3blog/fr/blog/2010-10-14-Fun-with-wav/code/wavsum.py b/output/n3blog/fr/blog/2010-10-14-Fun-with-wav/code/wavsum.py new file mode 100644 index 000000000..ddeedd473 --- /dev/null +++ b/output/n3blog/fr/blog/2010-10-14-Fun-with-wav/code/wavsum.py @@ -0,0 +1,28 @@ + +#!/usr/bin/env python +from struct import calcsize, unpack +from sys import argv, exit + +def word_iter(f): + while True: + _bytes = f.read(2) + + if len(_bytes) != 2: + raise StopIteration + + yield unpack("=h", _bytes)[0] + +try: + with open(argv[1], "rb") as f: + wav = "=4ci8cihhiihh4ci" + wav_size = calcsize(wav) + metadata = unpack(wav, f.read(wav_size)) + + if "".join(metadata[:4]) != "RIFF": + print "error: not wav file." + exit(1) + + print sum(abs(word) for word in word_iter(f)) +except IOError: + print "error: can't open input file '%s'." % argv[1] + exit(1) diff --git a/output/n3blog/fr/blog/2010-10-14-Fun-with-wav/code/wavsum.rb b/output/n3blog/fr/blog/2010-10-14-Fun-with-wav/code/wavsum.rb new file mode 100644 index 000000000..fc63899b5 --- /dev/null +++ b/output/n3blog/fr/blog/2010-10-14-Fun-with-wav/code/wavsum.rb @@ -0,0 +1,12 @@ + +data = ARGF.read + keys = %w[id totallength wavefmt format + pcm channels frequency bytes_per_second + bytes_by_capture bits_per_sample + data bytes_in_data sum + ] + values = data.unpack 'Z4 i Z8 i s s i i s s Z4 i s*' + sum = values.drop(12).map(&:abs).inject(:+) + keys.zip(values.take(12) << sum) {|k, v| + puts "#{k.ljust 17}: #{v}" + } diff --git a/output/n3blog/fr/blog/2010-10-14-Fun-with-wav/code/wavsum2.c b/output/n3blog/fr/blog/2010-10-14-Fun-with-wav/code/wavsum2.c new file mode 100644 index 000000000..0f9850943 --- /dev/null +++ b/output/n3blog/fr/blog/2010-10-14-Fun-with-wav/code/wavsum2.c @@ -0,0 +1,107 @@ + +#include +#include +#include // for memcmp +#include // for int16_t and int32_t + +struct wavfile +{ + char id[4]; // should always contain "RIFF" + int32_t totallength; // total file length minus 8 + char wavefmt[8]; // should be "WAVEfmt " + int32_t format; // 16 for PCM format + int16_t pcm; // 1 for PCM format + int16_t channels; // channels + int32_t frequency; // sampling frequency + int32_t bytes_per_second; + int16_t bytes_by_capture; + int16_t bits_per_sample; + char data[4]; // should always contain "data" + int32_t bytes_in_data; +} __attribute__((__packed__)); + +int is_big_endian(void) { + union { + uint32_t i; + char c[4]; + } bint = {0x01000000}; + return bint.c[0]==1; +} + +int main(int argc, char *argv[]) { + char *filename=argv[1]; + FILE *wav = fopen(filename,"rb"); + struct wavfile header; + + if ( wav == NULL ) { + fprintf(stderr,"Can't open input file %s\n", filename); + exit(1); + } + + + // read header + if ( fread(&header,sizeof(header),1,wav) < 1 ) { + fprintf(stderr,"Can't read input file header %s\n", filename); + exit(1); + } + + // if wav file isn't the same endianness than the current environment + // we quit + if ( is_big_endian() ) { + if ( memcmp( header.id,"RIFX", 4) != 0 ) { + fprintf(stderr,"ERROR: %s is not a big endian wav file\n", filename); + exit(1); + } + } else { + if ( memcmp( header.id,"RIFF", 4) != 0 ) { + fprintf(stderr,"ERROR: %s is not a little endian wav file\n", filename); + exit(1); + } + } + + if ( memcmp( header.wavefmt, "WAVEfmt ", 8) != 0 + || memcmp( header.data, "data", 4) != 0 + ) { + fprintf(stderr,"ERROR: Not wav format\n"); + exit(1); + } + if (header.format != 16) { + fprintf(stderr,"\nERROR: not 16 bit wav format."); + exit(1); + } + fprintf(stderr,"format: %d bits", header.format); + if (header.format == 16) { + fprintf(stderr,", PCM"); + } else { + fprintf(stderr,", not PCM (%d)", header.format); + } + if (header.pcm == 1) { + fprintf(stderr, " uncompressed" ); + } else { + fprintf(stderr, " compressed" ); + } + fprintf(stderr,", channel %d", header.pcm); + fprintf(stderr,", freq %d", header.frequency ); + fprintf(stderr,", %d bytes per sec", header.bytes_per_second ); + fprintf(stderr,", %d bytes by capture", header.bytes_by_capture ); + fprintf(stderr,", %d bits per sample", header.bytes_by_capture ); + fprintf(stderr,"\n" ); + + if ( memcmp( header.data, "data", 4) != 0 ) { + fprintf(stderr,"ERROR: Prrroblem?\n"); + exit(1); + } + fprintf(stderr,"wav format\n"); + + // read data + long long sum=0; + int16_t value; + int i=0; + fprintf(stderr,"---\n", value); + while( fread(&value,sizeof(value),1,wav) ) { + if (value<0) { value=-value; } + sum += value; + } + printf("%lld\n",sum); + exit(0); +} diff --git a/output/n3blog/fr/blog/2010-10-14-Fun-with-wav/index.html b/output/n3blog/fr/blog/2010-10-14-Fun-with-wav/index.html new file mode 100644 index 000000000..10e0c8d9f --- /dev/null +++ b/output/n3blog/fr/blog/2010-10-14-Fun-with-wav/index.html @@ -0,0 +1,517 @@ + + + + + + + + + + + + + + + + + + + + + S'amuser avec un .wav + + + + +
+ + +
+

+ S'amuser avec un .wav +

+ +
+ +
+ + + + + +
+
+
+ +
+ + +

tlàl : Je me suis amusé à lire un fichier wav. Le C fut le langage le mieux adapté à ce traitement. Bien meilleur que Ruby par exemple.

+ +

edit: Je voulais que ce programme fonctionne sur une machine spécifique. En aucun cas je ne pensais publier ce code pour une utilisation autre que celle-ci.

+ + +
+ + +

J’ai eu besoin de calculer la somme des valeurs absolue des données d’un fichier wav. +Pour des raison d’efficacité (et aussi de fun), j’ai fait le programme en C.

+ +

Celà faisait longtemps que je n’avais pas programmé en C. +De mémoire il était peu aisé de manipuler des fichiers. +Mais je dois concéder que j’ai été étonné de la clarté du code que j’ai obtenu.

+ +

Tout d’abord, un fichier wav se compose d’un entête qui contient pas mal de meta données. +Cet entête a été optimisé pour prendre peu de place. +Donc on discute de l’entête avec des nombres d’octets :

+ +
    +
  • Les 4 premiers octets doivent contenir RIFF en ASCII ;
  • +
  • les 4 octects suivant correspondent à un entier codé sur 32 bits qui donne la taille du fichier moins 8 octets. etc..
  • +
+ +

Etonnamment je pense que lire ce type de fichier avec un langage de haut niveau aurait été plus pénible qu’en C. +La preuve, il m’a suffit de chercher sur le net le format complet de l’entête et de l’écrire dans un struct.

+ +
+struct wavfile
+{
+    char        id[4];          // should always contain "RIFF"
+    int     totallength;    // total file length minus 8
+    char        wavefmt[8];     // should be "WAVEfmt "
+    int     format;         // 16 for PCM format
+    short     pcm;            // 1 for PCM format
+    short     channels;       // channels
+    int     frequency;      // sampling frequency
+    int     bytes_per_second;
+    short     bytes_by_capture;
+    short     bits_per_sample;
+    char        data[4];        // should always contain "data"
+    int     bytes_in_data;
+};
+
+ +

Si j’avais eu à faire ça en Ruby, je pense qu’il m’aurait fallu pour chaque bloc de l’entête écrire un bout de code de lecture du bon nombre d’octets. +Alors qu’en C il m’a suffit d’écrire:

+ +
+fread(&header,sizeof(header),1,wav)
+
+ +

Et en une seule étape ma structure de donnée a été remplie avec les valeurs souhaitées. Magique !

+ +

Ensuite, récupérer un entier à partir de deux octets n’est pas non plus une opération naturelle dans les nouveaux langages de programmation. +Alors qu’en C. Pour récupérer un entier codé sur 16 bits il suffit d’écrire :

+ +
+short value=0;
+while( fread(&value,sizeof(value),1,wav) ) {
+    // do something with value
+}
+
+ +

Finallement je suis arrivé au code suivant, sachant que le format de wav était connu, avec notamment échantillonage sur 16 bits en 48000Hz :

+ +
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+struct wavfile
+{
+    char        id[4];          // should always contain "RIFF"
+    int     totallength;    // total file length minus 8
+    char        wavefmt[8];     // should be "WAVEfmt "
+    int     format;         // 16 for PCM format
+    short     pcm;            // 1 for PCM format
+    short     channels;       // channels
+    int     frequency;      // sampling frequency
+    int     bytes_per_second;
+    short     bytes_by_capture;
+    short     bits_per_sample;
+    char        data[4];        // should always contain "data"
+    int     bytes_in_data;
+};
+
+int main(int argc, char *argv[]) {
+    char *filename=argv[1];
+    FILE *wav = fopen(filename,"rb");
+    struct wavfile header;
+
+    if ( wav == NULL ) {
+        fprintf(stderr,"Can't open input file %s", filename);
+        exit(1);
+    }
+
+
+    // read header
+    if ( fread(&header,sizeof(header),1,wav) < 1 )
+    {
+        fprintf(stderr,"Can't read file header\n");
+        exit(1);
+    }
+    if (    header.id[0] != 'R'
+         || header.id[1] != 'I' 
+         || header.id[2] != 'F' 
+         || header.id[3] != 'F' ) { 
+        fprintf(stderr,"ERROR: Not wav format\n"); 
+        exit(1); 
+    }
+
+    fprintf(stderr,"wav format\n");
+
+    // read data
+    long sum=0;
+    short value=0;
+    while( fread(&value,sizeof(value),1,wav) ) {
+        // fprintf(stderr,"%d\n", value);
+        if (value<0) { value=-value; }
+        sum += value;
+    }
+    printf("%ld\n",sum);
+    exit(0);
+}
+
+
+ +

Bien entendu ce code n’est qu’un hack. +Mais on voit bien comment on peut facilement améliorer ce code, ajouter des cas possibles par exemple. +Comme je dis souvent : le bon outil pour la bonne tâche. +On voit en effet que pour cette tâche C est bien supérieur à Ruby par exemple.

+ +

_màj : pour des raisons de compatibilité (machines 64 bits) j’ai utilisé int16_t au lieu de short et int au lieu de int.

+ +

Je serai curieux de savoir s’il existe un manière plus propre en Ruby que je ne connais pas. +Certainement qu’en Python ça doit être la cas.

+ + +
+ + +

Màj (2) : après toutes les remarques concernant la portabilité. +J’ai fait une nouvelle version qui devrait être plus portable. +Elle fait aussi plus de test pour vérifier le fichier. +Cependant j’utilise une assertion spécifique à gcc pour être certain que la structure de donnée n’ai pas de “trou” :

+ +
+__attribute__((__packed__))
+
+ +

Le nouveau code n’utilise pas mmap et devrait être plus compatible.
+Voici le dernier résultat :

+ + +
+ + +
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> // for memcmp
+#include <stdint.h> // for int16_t and int32_t
+
+struct wavfile
+{
+    char    id[4];          // should always contain "RIFF"
+    int32_t totallength;    // total file length minus 8
+    char    wavefmt[8];     // should be "WAVEfmt "
+    int32_t format;         // 16 for PCM format
+    int16_t pcm;            // 1 for PCM format
+    int16_t channels;       // channels
+    int32_t frequency;      // sampling frequency
+    int32_t bytes_per_second;
+    int16_t bytes_by_capture;
+    int16_t bits_per_sample;
+    char    data[4];        // should always contain "data"
+    int32_t bytes_in_data;
+} __attribute__((__packed__));
+
+int is_big_endian(void) {
+    union {
+        uint32_t i;
+        char c[4];
+    } bint = {0x01000000};
+    return bint.c[0]==1;
+}
+
+int main(int argc, char *argv[]) {
+    char *filename=argv[1];
+    FILE *wav = fopen(filename,"rb");
+    struct wavfile header;
+
+    if ( wav == NULL ) {
+        fprintf(stderr,"Can't open input file %s\n", filename);
+        exit(1);
+    }
+
+
+    // read header
+    if ( fread(&header,sizeof(header),1,wav) < 1 ) {
+        fprintf(stderr,"Can't read input file header %s\n", filename);
+        exit(1);
+    }
+
+    // if wav file isn't the same endianness than the current environment
+    // we quit
+    if ( is_big_endian() ) {
+        if (   memcmp( header.id,"RIFX", 4) != 0 ) {
+            fprintf(stderr,"ERROR: %s is not a big endian wav file\n", filename); 
+            exit(1);
+        }
+    } else {
+        if (   memcmp( header.id,"RIFF", 4) != 0 ) {
+            fprintf(stderr,"ERROR: %s is not a little endian wav file\n", filename); 
+            exit(1);
+        }
+    }
+
+    if (   memcmp( header.wavefmt, "WAVEfmt ", 8) != 0 
+        || memcmp( header.data, "data", 4) != 0 
+            ) {
+        fprintf(stderr,"ERROR: Not wav format\n"); 
+        exit(1); 
+    }
+    if (header.format != 16) {
+        fprintf(stderr,"\nERROR: not 16 bit wav format.");
+        exit(1);
+    }
+    fprintf(stderr,"format: %d bits", header.format);
+    if (header.format == 16) {
+        fprintf(stderr,", PCM");
+    } else {
+        fprintf(stderr,", not PCM (%d)", header.format);
+    }
+    if (header.pcm == 1) {
+        fprintf(stderr, " uncompressed" );
+    } else {
+        fprintf(stderr, " compressed" );
+    }
+    fprintf(stderr,", channel %d", header.pcm);
+    fprintf(stderr,", freq %d", header.frequency );
+    fprintf(stderr,", %d bytes per sec", header.bytes_per_second );
+    fprintf(stderr,", %d bytes by capture", header.bytes_by_capture );
+    fprintf(stderr,", %d bits per sample", header.bytes_by_capture );
+    fprintf(stderr,"\n" );
+
+    if ( memcmp( header.data, "data", 4) != 0 ) { 
+        fprintf(stderr,"ERROR: Prrroblem?\n"); 
+        exit(1); 
+    }
+    fprintf(stderr,"wav format\n");
+
+    // read data
+    long long sum=0;
+    int16_t value;
+    int i=0;
+    fprintf(stderr,"---\n", value);
+    while( fread(&value,sizeof(value),1,wav) ) {
+        if (value<0) { value=-value; }
+        sum += value;
+    }
+    printf("%lld\n",sum);
+    exit(0);
+}
+
+
+ +

Màj(3) : +Sur reddit +Bogdanp +a proposé une version en Python :

+ +
+
+#!/usr/bin/env python
+from struct import calcsize, unpack
+from sys import argv, exit
+
+def word_iter(f):
+    while True:
+        _bytes = f.read(2)
+
+    if len(_bytes) != 2:
+        raise StopIteration
+
+    yield unpack("=h", _bytes)[0]
+
+try:
+    with open(argv[1], "rb") as f:
+        wav = "=4ci8cihhiihh4ci"
+        wav_size = calcsize(wav)
+        metadata = unpack(wav, f.read(wav_size))
+
+        if "".join(metadata[:4]) != "RIFF":
+            print "error: not wav file."
+            exit(1)
+
+        print sum(abs(word) for word in word_iter(f))
+except IOError:
+    print "error: can't open input file '%s'." % argv[1]
+    exit(1)
+
+
+ +

et luikore a proposé une version Ruby assez impressionnante :

+ +
+
+data = ARGF.read
+ keys = %w[id totallength wavefmt format
+       pcm channels frequency bytes_per_second
+         bytes_by_capture bits_per_sample
+           data bytes_in_data sum
+ ]
+ values = data.unpack 'Z4 i Z8 i s s i i s s Z4 i s*'
+ sum = values.drop(12).map(&:abs).inject(:+)
+ keys.zip(values.take(12) << sum) {|k, v|
+       puts "#{k.ljust 17}: #{v}"
+ }
+
+
+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ + + + +
+ +
+ Écrit le : 14/10/2010 + modifié le : 26/10/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2010-10-26-LaTeX-like-macro-and-markdown/code/macros.rb b/output/n3blog/fr/blog/2010-10-26-LaTeX-like-macro-and-markdown/code/macros.rb new file mode 100644 index 000000000..ad7816cdd --- /dev/null +++ b/output/n3blog/fr/blog/2010-10-26-LaTeX-like-macro-and-markdown/code/macros.rb @@ -0,0 +1,44 @@ + +# usage: +# --- +# ... +# macros: +# test: "passed test" +# --- +# ... +# Here is a %test. +# +class Macros < Nanoc3::Filter + identifier :falacy + attr_accessor :macro + def initialize(arg) + super + @macro={} + @macro[:tlal] = %{tlàl : } + @macro[:tldr] = %{tl;dr: } + if @item.nil? + if not arg.nil? + @macro.merge!( arg ) + end + else + if not @item[:macros].nil? + @macro.merge!( @item[:macros] ) + end + end + end + def macro_value_for(macro_name) + if macro_name.nil? or macro_name=="" or @macro[macro_name.intern].nil? + return %{%#{macro_name}} + end + return @macro[macro_name.intern] + end + def run(content, params={}) + content.gsub(/%(\w*)/) do |m| + if m != '%' + macro_value_for($1) + else + m + end + end + end +end diff --git a/output/n3blog/fr/blog/2010-10-26-LaTeX-like-macro-and-markdown/index.html b/output/n3blog/fr/blog/2010-10-26-LaTeX-like-macro-and-markdown/index.html new file mode 100644 index 000000000..a36bd69c3 --- /dev/null +++ b/output/n3blog/fr/blog/2010-10-26-LaTeX-like-macro-and-markdown/index.html @@ -0,0 +1,267 @@ + + + + + + + + + + + + + + + + + + + + + Des macros LaTeX pour markdown + + + + +
+ + +
+

+ Des macros LaTeX pour markdown +

+ +
+ +
+ + + + + +
+
+
+ +
+ + +

tlàl : J’ai fait un système simple de macros pour mon blog. Par exemple, il me suffit d’écrire %latex et ça affiche LaTeX.

+ + +
+ + +

J’ai ajouter un système de macro pour mon système de blog. +Lorsqu’on est habitué à LaTeX et que l’on commence à écrire des articles +un peu conséquent avec des notations mathématiques, +les macros deviennent vite quelque chose d’indispensable.

+ +

Dans l’entête de mes fichiers j’écris simplement:

+ +
+macros:
+  test: "This is a macro test"
+  latex: '<span style="text-transform: uppercase">L<sup style="vertical-align: 0.15em; margin-left: -0.36em; margin-right: -0.15em; font-size: .85em">a</sup>T<sub style="vertical-align: -0.5ex; margin-left: -0.1667em; margin-right: -0.125em; font-size: 1em">e</sub>X</span>'
+
+ +

Puis dans le corps ça va remplacer :

+ +
    +
  • %test par This is a macro test ;
  • +
  • et %latex par LaTeX
  • +
+ +

Le code est assez simple. +Pour les utilisateurs de nanoc il suffit de copier le fichier suivant dans le répertoire lib.

+ +
+
+# usage:
+# ---
+# ...
+# macros:
+#   test: "passed test"
+# ---
+# ...
+# Here is a This is a macro test.
+#
+class Macros < Nanoc3::Filter
+    identifier :falacy
+    attr_accessor :macro
+    def initialize(arg)
+        super
+        @macro={}
+        @macro[:tlal] = %{<span class="sc"><abbr title="Trop long à lire">tlàl</abbr> : </span>}
+        @macro[:tldr] = %{<span class="sc"><abbr title="Too long; don't read">tl;dr</abbr>: </span>}
+        if @item.nil?
+            if not arg.nil?
+                @macro.merge!( arg )
+            end
+        else
+            if not @item[:macros].nil?
+                @macro.merge!( @item[:macros] )
+            end
+        end
+    end
+    def macro_value_for(macro_name)
+        if macro_name.nil? or macro_name=="" or @macro[macro_name.intern].nil?
+            return %{%#{macro_name}} 
+        end
+        return @macro[macro_name.intern]
+    end
+    def run(content, params={})
+        content.gsub(/%(\w*)/) do |m| 
+            if m != '%'
+                macro_value_for($1)
+            else
+                m
+            end
+        end
+    end
+end
+
+
+ +

Les macros peuvent être vraiment utiles. Lisez cet article par exemple.

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Écrit le : 26/10/2010 + modifié le : 07/04/2011 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2011-01-03-Happy-New-Year/index.html b/output/n3blog/fr/blog/2011-01-03-Happy-New-Year/index.html new file mode 100644 index 000000000..77a5299fb --- /dev/null +++ b/output/n3blog/fr/blog/2011-01-03-Happy-New-Year/index.html @@ -0,0 +1,194 @@ + + + + + + + + + + + + + + + + + + + + + Bonne et heureuse année + + + + +
+ + +
+

+ Bonne et heureuse année +

+ +
+ +
+ + + + + +
+
+
+

Bonne et heureuse année !

+ +

J’étais très occupé ces derniers mois. +Maintenant il me semble que je vais pouvoir faire revivre ce blog.

+ +

J’ai fait un outil qui permet d’écrire des livre en utilisant une syntaxe proche de markdown. +C’est un markdown avec des macros (essentiel pour les textes longs). +De plus le système gère la génération de pages HTML ainsi que du PDF engendré avec du XeLaTeX. +Je n’en ai pas encore terminé avec ça. Mais si je tarde trop, je communiquerai lorsque j’aurai fini le minimum.

+ +

J’ai écrit un framework MVC pour application javascript simple mais néanmoins très rapide.

+ +

Meilleurs vœux à tous !

+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Écrit le : 01/01/2011 + modifié le : 06/01/2011 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/2011-01-03-Why-I-sadly-won-t-use-coffeescript/index.html b/output/n3blog/fr/blog/2011-01-03-Why-I-sadly-won-t-use-coffeescript/index.html new file mode 100644 index 000000000..8cf720576 --- /dev/null +++ b/output/n3blog/fr/blog/2011-01-03-Why-I-sadly-won-t-use-coffeescript/index.html @@ -0,0 +1,301 @@ + + + + + + + + + + + + + + + + + + + + + Pourquoi je n'utiliserai pas CoffeeScript (malheureusement) + + + + +
+ + +
+

+ Pourquoi je n'utiliserai pas CoffeeScript (malheureusement) +

+ +
+ +
+ + + + + +
+
+
+

Title image

+ + +
+ + +

tlàl : Qu’est-ce qui n’allait pas avec Coffeescript? La meta-programmation, il faut le “vendre” aux autres, une nouvelle étape de compilation intermédiaire sans fournir les avantages de Cappuccino, la sensation que c’est un peu instable.

+ + +
+ + +

Le commentaire le mieux classé de la question suivante posée sur HackerNews mentionnait CoffeeScript. +Récemment j’ai beaucoup programmé en javascript. +Après avoir essayé +Sroutcore, +Cappuccino, +backbone.js & +javascriptMVC, +Je me suis décidé à créer mon propre framework MVC minimal pour client javascript.1

+ +

Je me suis battu avec l’horrible syntaxe de javascript. C’était comme revenir des années dans le passé :

+ +
    +
  • une syntaxe à la Java très verbeuse ;
  • +
  • une syntaxe follement verbeuse et étrange pour la programmation orientée objet ;
  • +
  • pas de manière naturelle de se référer à l’instance d’une classe ;
  • +
  • etc…
  • +
+ +

J’étais tellement ennuyé par tous ces point qu’il était arrivé un moment où je commençais à vouloir faire mon propre CoffeeScript.

+ +

J’ai fini une première version de mon framework MVC en javascript et j’ai appris l’existence de CoffeeScript. Merci à git, j’ai immédiatement créé une nouvelle branche dans le seul but d’essayer CoffeeScript.

+ +

Voici mon expérience :

+ +
    +
  1. J’ai dû installer node.js et utiliser npm simplement pour utiliser CoffeeScript. Ce n’était pas très difficile, mais pas aussi facile que ce que j’aurai aimé.
  2. +
  3. Les fichier javascript existants ne sont pas compatible avec coffee.
  4. +
  5. Il n’y a pas script pour aider à transformer les anciens fichiers javascripts en fichier coffee. Du coups j’ai dû faire ça manuellement. + Merci à vim, il ne fut pas très difficile de transformer 90% des fichiers avec des expressions régulières. + L’option --watch de coffee était très utile pour debugger cette transformation. + Cependant, il m’a fallu écrire mon propre script pour que tous mes fichiers soient watchés dans tous les sous-répertoires.
  6. +
  7. Quelque chose à laquelle je n’avais pas pensé. J’ai fait un peu de meta-programmation en javascript en utilisant eval. Mais pour que celà fonctionne correctement, il faut que la chaîne de caractère que je passe à eval soit codée en javascript et pas en coffee. C’est un peu comme écrire dans deux langages différents au même endroit. Ça ne me parraissait vraiment pas agréable.
  8. +
+ +

Conclusion

+ +

Avantages :

+ +
    +
  • Code plus lisible : CoffeeScript résoud la majorité des problèmes de syntaxes de javascript
  • +
  • Concision : j’ai gagné 14% de lignes, 22% de mots et 14% de caractères.
  • +
+ +

Inconvénients :

+ +
    +
  • Ajout d’une nouvelle étape de compilation avant de pouvoir vérifier le comportement de mon site
  • +
  • Facilité d’utilisation : il m’a fallu créer un script pour gérer la génératio automatique des fichiers
  • +
  • Il faut apprendre un autre langage proche de ruby
  • +
  • La meta-programmation devient une expérience désagréable
  • +
  • Je dois convaincre les personnes travaillant avec moi : +
      +
    • d’installer node.js, npm et CoffeeScript ;
    • +
    • de se souvenir de lancer un script à chaque session de codage ;
    • +
    • d’apprendre un autre language proche de ruby.
    • +
    +
  • +
+ +

Les deux derniers points étant de mon point de vue les plus problématiques.

+ +

Mais même si j’avais à travailler seul, je n’utiliserai certainement pas CoffeeScript. +Il s’agit d’un tier dont la moindre mise à jour pourrait rendre mon code inutilisable. +Cette situation m’est déjà arrivée plusieurs fois et c’est très désagrable. +Beaucoup plus que coder avec une mauvaise syntaxe.

+ +

Digression

+ +

Je suis attristé. +J’espérais tant pouvoir programmer Javascript avec une touche de Ruby. +En fin de compte, cette solution n’est pas pour moi. +Je vais devoir utiliser l’horrible syntaxe javascript pour l’instant. +À la limite j’aurai préféré un script Ruby2Js par exemple2. +Mais il me semble que ça serait un travail très difficile rien que pour simuler l’accès à la classe courante.

+ +

Typiquement @x est transformé en this.x. Mais le code suivant ne fait pas ce que j’attendrai de lui.

+ +
+-> 
+class MyClass
+  foo: ->
+    alert('ok')
+
+  bar: ->
+    $('#content').load( '/content.html', ( -> @foo(x) ) )
+    # Ça n'appellera pas MyClass.foo
+
+ +

La seule façon de résoudre ce problème est avec le code suivant :

+ +
+-> 
+class MyClass
+  foo: ->
+    alert('ok')
+
+  bar: ->
+    self=this
+    $('#content').load( '/content.html', ( -> self.foo(x) ) )
+
+ +

Sachant celà, la notation @ perd tout son intérêt pour moi.

+
+
    +
  1. +

    Je sais que ce n’est certainement ni la meilleure ni la plus productive des décisions. Mais j’aime bien fabriquer les choses pour savoir comment tout fonctionne dans le détail.

    +
  2. +
  3. +

    Je sais qu’il existe un projet rb2js, mais il ne résoud pas le problème dont je parle.

    +
  4. +
+
+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Écrit le : 03/01/2011 + modifié le : 14/03/2011 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/feed/feed.xml b/output/n3blog/fr/blog/feed/feed.xml new file mode 100644 index 000000000..39f8804b1 --- /dev/null +++ b/output/n3blog/fr/blog/feed/feed.xml @@ -0,0 +1,999 @@ + + + http://yannesposito.com/ + Yogsototh's last blogs entries + 2011-01-03T08:37:26Z + + + + Yann Esposito + http://yannesposito.com + + + tag:yannesposito.com,2011-01-03:/n3blog/fr/blog/2011-01-03-Why-I-sadly-won-t-use-coffeescript/ + Pourquoi je n'utiliserai pas CoffeeScript (malheureusement) + 2011-01-03T08:37:26Z + 2011-01-03T08:37:26Z + + Yann Esposito + yannesposito.com + + + <p><img alt="Title image" src="/n3blog/img/blog/2011-01-03-Why-I-sadly-won-t-use-coffeescript/main.png" /></p> + + +<div class="intro"> + + +<p><span class="sc"><abbr title="Trop long à lire">tlàl</abbr>&nbsp;: </span> Qu&rsquo;est-ce qui n&rsquo;allait pas avec Coffeescript? La meta-programmation, il faut le &ldquo;vendre&rdquo; aux autres, une nouvelle étape de compilation intermédiaire sans fournir les avantages de Cappuccino, la sensation que c&rsquo;est un peu instable.</p> + + +</div> + + +<p>Le commentaire le mieux classé de <a href="http://news.ycombinator.com/item?id=2053956">la question suivante</a> posée sur HackerNews mentionnait <a href="http://coffeescript.org">CoffeeScript</a>. +Récemment j&rsquo;ai beaucoup programmé en javascript. +Après avoir essayé +</p></p> + + + tag:yannesposito.com,2011-01-01:/n3blog/fr/blog/2011-01-03-Happy-New-Year/ + Bonne et heureuse année + 2011-01-01T06:55:54Z + 2011-01-01T06:55:54Z + + Yann Esposito + yannesposito.com + + + <p>Bonne et heureuse année&nbsp;!</p> + +<p>J&rsquo;étais très occupé ces derniers mois. +Maintenant il me semble que je vais pouvoir faire revivre ce blog.</p> + +<p>J&rsquo;ai fait un outil qui permet d&rsquo;écrire des livre en utilisant une syntaxe proche de markdown. +C&rsquo;est un markdown avec des macros (essentiel pour les textes longs). +De plus le système gère la génération de pages HTML ainsi que du PDF engendré avec du XeLaTeX. +Je n&rsquo;en ai pas encore terminé avec ça. Mais si je tarde trop, je communiquerai lorsque j&rsquo;aurai fini le minimum.</p> + +<p>J&rsquo;ai écrit un framework MVC pour application javascript simple mais néanmoins très rapide.</p> + +<p>Meilleurs vœux à tous&nbsp;!</p> +</p> + + + tag:yannesposito.com,2010-10-26:/n3blog/fr/blog/2010-10-26-LaTeX-like-macro-and-markdown/ + Des macros LaTeX pour markdown + 2010-10-26T12:30:58Z + 2010-10-26T12:30:58Z + + Yann Esposito + yannesposito.com + + + +<div class="intro"> + + +<p><span class="sc"><abbr title="Trop long à lire">tlàl</abbr>&nbsp;: </span> J&rsquo;ai fait un système simple de macros pour mon blog. Par exemple, il me suffit d&rsquo;écrire %<span />latex et ça affiche <span style="text-transform: uppercase">L<sup style="vertical-align: 0.15em; margin-left: -0.36em; margin-right: -0.15em; font-size: .85em">a</sup>T<sub style="vertical-align: -0.5ex; margin-left: -0.1667em; margin-right: -0.125em; font-size: 1em">e</sub>X</span>.</p> + + +</div> + + +<p>J&rsquo;ai ajouter un système de macro pour mon système de blog. +Lorsqu&rsquo;on est habitué à <span style="text-transform: uppercase">L<sup style="vertical-align: 0.15em; margin-left: -0.36em; margin-right: -0.15em; font-size: .85em">a</sup>T</span></p></div> + + + tag:yannesposito.com,2010-10-14:/n3blog/fr/blog/2010-10-14-Fun-with-wav/ + S'amuser avec un .wav + 2010-10-14T09:04:58Z + 2010-10-14T09:04:58Z + + Yann Esposito + yannesposito.com + + + +<div class="intro"> + + +<p><span class="sc"><abbr title="Trop long à lire">tlàl</abbr>&nbsp;: </span> Je me suis amusé à lire un fichier <code>wav</code>. Le <code>C</code> fut le langage le mieux adapté à ce traitement. Bien meilleur que Ruby par exemple.</p> + +<p>edit: Je voulais que ce programme fonctionne sur une machine spécifique. En aucun cas je ne pensais publier ce code pour une utilisation autre que celle-ci.</p> + + +</div> + + +<p>J&rsquo;ai eu besoin de calculer la somme des valeurs absolue des données d&rsquo;un fichier <code>wav</code>. +Pour des raison d&rsquo;efficacité (et aussi de fun), j&rsquo;ai fait le programme en <code>C</code>.</p> + +<p>Celà faisait longtemps que je n&rsquo;avais pas programmé en <code>C</code>. +De mémoire il était peu aisé de manipuler des ...</p> + + + tag:yannesposito.com,2010-10-10:/n3blog/fr/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/ + Sécurisez vos emails + 2010-10-10T16:39:00Z + 2010-10-10T16:39:00Z + + Yann Esposito + yannesposito.com + + + <p><img alt="Title image" src="/n3blog/img/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/main.png" class="clean" /></p> + + +<div class="intro"> + + +<p><span class="sc"><abbr title="Trop long à lire">tlàl</abbr>&nbsp;: </span> <em>avec un Mac</em> </p> + +<ul> + <li>Récupérez un certificat signé par une AC: <a href="http://www.instantssl.com/ssl-certificate-products/free-email-certificate.html">cliquez ici pour un certificat gratuit</a>&nbsp;;</li> + <li>ouvrez le fichier&nbsp;;</li> + <li>supprimer le fichier en mode sécurisé&nbsp;;</li> + <li>utilisez Mail plutôt que l&rsquo;interface web de gmail.</li> +</ul> + + +</div> + + +<p>J&rsquo;ai (re)découvert comment adoptez la norme S/MIME. +J&rsquo;ai été surpris de voir à quel point ce fut aisé. +Il y a seulement quelques années c&rsq...</p></p> + + + tag:yannesposito.com,2010-10-06:/n3blog/fr/blog/2010-10-06-New-Blog-Design-Constraints/ + Contraintes du design de ce blog + 2010-10-06T09:33:03Z + 2010-10-06T09:33:03Z + + Yann Esposito + yannesposito.com + + + <p>Vous avez pu constater que j&rsquo;ai modifié le design de mon blog. +Maintenant il doit être beaucoup plus léger qu&rsquo;avant. +Je n&rsquo;utilise plus de CSS3 et beaucoup moins de javascript. +Bien entendu, même avant, mes pages étaient parfaitement lisibles sans javascript. +Mais, je me suis aperçu que les systèmes de CSS3 sont loin d&rsquo;être au point. +J&rsquo;utilisait des gradient en CSS3, ainsi que des ombres sous le texte. Ça avait un rendu très sympa. Sauf&hellip; +Ce n&rsquo;était pas compatible ie6, sous Chrome le rendu était d&rsquo;une lenteur incroyable. +J&rsquo;ai donc décidé de faire un site à minima. +Je voulais qu&rsquo;il soit joli <em>et</em> le plus simple possible pour assurer sa compatibilité. +Les règles que je me suis fixées sont donc:</p> + +</p> + + + tag:yannesposito.com,2010-09-02:/n3blog/fr/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes/ + Utilisation de git pour calculer les mtimes + 2010-09-02T13:54:10Z + 2010-09-02T13:54:10Z + + Yann Esposito + yannesposito.com + + + <p>Vous pouvez remarquer qu&rsquo;à la fin de chaque page je donne une date de dernière modification. +Précédemment cette date était calculée en utilisant la date du fichier. +Mais il arrive fréquemment que je fasse un <code>touch</code> d&rsquo;un fichier pour engendrer tout le site de nouveau. +Donc la date n&rsquo;est pas nécessairement la <em>vraie</em> de modification du contenue.</p> + +<p>J&rsquo;utilise <a href="http://git-scm.org">git</a> pour <em>versionner</em> mon site web. +Et cet outil me permet de récupérer la dernière date de <em>vraie</em> modification d&rsquo;un fichier. +Voici comment je m&rsquo;y prend avec <a href="http://nanoc.stoneship.org">nanoc</a>&nbsp;:</p> + +<div class="code"><div class="file"></div></div> + + + tag:yannesposito.com,2010-09-01:/n3blog/fr/blog/2010-09-02-base64-and-sha1-on-iPhone/ + base64 et sha1 sur iPhone + 2010-09-01T22:02:17Z + 2010-09-01T22:02:17Z + + Yann Esposito + yannesposito.com + + + <p>Allons directement à l&rsquo;essentiel&nbsp;: +voici deux fonctions à intégrer à votre application iPhone pour afficher l&rsquo;encodage en base64 ou en hexadecimal du hash sha1 d&rsquo;un string en Objective-C pour iPhone.</p> + +<p>Pour l&rsquo;usage c&rsquo;est très simple, copiez le code dans la classe de votre choix. +Puis&nbsp;:</p> + +<pre class="twilight"> +<span class="CCCPreprocessorLine">#<span class="CCCPreprocessorDirective">import</span> <span class="String"><span class="String">&lt;</span>CommonCrypto/CommonDigest.h<span class="String">&gt;</span></span></span> +... +<span class="Support">NSString</span> *b64_hash = [<span class="Variable">self</span> <span class="SupportFunction">b64_sha1<span class="SupportFunction">:</span></span><span class="String"></span></pre> + + + tag:yannesposito.com,2010-08-31:/n3blog/fr/blog/2010-08-31-send-mail-from-command-line-with-attached-file/ + Envoyer un mail en ligne de commande avec un fichier attaché + 2010-08-31T08:16:04Z + 2010-08-31T08:16:04Z + + Yann Esposito + yannesposito.com + + + <p>J&rsquo;ai dû envoyer un mail en ligne de commande récemment. +Quelle ne fût pas ma surprise lorsque je constatais que ce n&rsquo;était vraiment pas évident. +Je n&rsquo;avais ni <code>pine</code> ni <code>mutt</code>. Seulement <code>mail</code> et <code>mailx</code>.</p> + +<p>Ce qu&rsquo;on trouve sur internet pour envoyer un mail avec fichier attaché c&rsquo;est ça&nbsp;:</p> + +<pre class="twilight"> +uuencode fic.jpg fic.jpg <span class="Keyword">|</span> mail -s <span class="String"><span class="String">'</span>Subject<span class="String">'</span></span> +</pre> + +<p>Bon, alors, bête et discipliné j&rsquo;ai essayé. +Et bien, ça marche <em>presque</em> tout le temps. +Pour mon fichier ça n&rsquo;a pas marché du tout. +Je l&rsquo;ai compressé au format <code>.gz</code>, </p> + + + tag:yannesposito.com,2010-08-23:/n3blog/fr/blog/2010-08-23-Now-heberged-on-heroku/ + Maintenant sur Heroku + 2010-08-23T13:05:13Z + 2010-08-23T13:05:13Z + + Yann Esposito + yannesposito.com + + + <h1 class="first" id="maintenant-sur-herokuhttpherokucom">Maintenant sur <a href="http://heroku.com">Heroku</a></h1> + +<p>J&rsquo;ai changé mon hébergeur. Mobileme n&rsquo;est absolument pas adapté à la diffusion de mon blog. C&rsquo;est pourquoi je suis passé à <a href="http://heroku.com">Heroku</a>.</p> + +<p>Mais comme vous devez le savoir mon blog est un site complètement statique. +J&rsquo;utilise <a href="http://nanoc.stoneship.org/">nanoc</a> pour l&rsquo;engendrer. +Avoir un site statique amène beaucoup d&rsquo;avantages par rapport à un site dynamique. Surtout en terme de sécurité. +Voici comment configurer un site statique sur heroku.</p> + +<p>La racine de mes fichiers est &lsquo;/output&rsquo;. Vous devez simplement créer deux fichiers. Un fichier <code>config.ru</code></p> + + + tag:yannesposito.com,2010-08-11:/n3blog/fr/blog/2010-07-09-Indecidabilities/ + Indécidabilités (partie 1) + 2010-08-11T08:04:31Z + 2010-08-11T08:04:31Z + + Yann Esposito + yannesposito.com + + + +<div class="intro"> + + +<p><span class="sc"><abbr title="Trop long à lire">tlàl</abbr>&nbsp;: </span> Je crée un mode mathématique simple pour parler de différents types d&rsquo;<em>indécidabilités</em>&nbsp;:</p> + +<ul> + <li>indécidabilité due aux erreurs d&rsquo;observation&nbsp;;</li> + <li>grandes erreurs résultant de petites erreurs de mesure&nbsp;;</li> + <li>indécidabilité fractales&nbsp;;</li> + <li>indécidabilité logique.</li> +</ul> + + +</div> + + + +</div> + +<div class="corps"> + + +<h1 class="first" id="les-indcidabilits">Les indécidabilités</h1> + + +<div class="intro"> + + +<p>Si le monde a été fabriqué par un démiurge, on peut dire que celui-ci devait avoir le sens de l&rsquo;humour. +Et le récit que je vais faire va vous en fournir la preuve. +Je vais me mettre à sa p...</p></div> + + + tag:yannesposito.com,2010-07-31:/n3blog/fr/blog/2010-07-31-New-style-after-holidays/ + Nouveau style après les vacances + 2010-07-31T21:59:10Z + 2010-07-31T21:59:10Z + + Yann Esposito + yannesposito.com + + + <p>Avant les vacances beaucoup d&rsquo;utilisateurs se sont plaints de la lenteur de rendu de mon site. +Il s&rsquo;agit notamment de problèmes avec Chrome en particulier. +Mais pour éviter tout problème. +J&rsquo;ai complètement modifié le style de mon site web. +Il est inspiré du style de l&rsquo;application iBooks<small>&copy;</small> sur iPhone<small>&copy;</small>.</p> + +<p>Dites moi ce que vous pensez de ce nouveau design.</p> +</p> + + + tag:yannesposito.com,2010-07-07:/n3blog/fr/blog/2010-07-07-CSS-rendering-problems-by-navigator/ + N'utilisez pas de gradients avec Chrome + 2010-07-07T13:43:43Z + 2010-07-07T13:43:43Z + + Yann Esposito + yannesposito.com + + + <p>Beaucoup d&rsquo;utilisateurs de <a href="http://reddit.com">Reddit</a> m&rsquo;ont rapporté que mon site était très long à charger et à <em>scroller</em>. +Ils pensaient qu&rsquo;il s&rsquo;agissait d&rsquo;un problème dû aux ombres que j&rsquo;applique sur le texte. +J&rsquo;étais un peu surpris puisque je fais mes tests sur une machine vraiment très lente et je n&rsquo;avais jamais détecté ces problèmes. +En réalité, ce qui ralenti le rendu de ce site est par ordre d&rsquo;importance&nbsp;:</p> + +<ol> + <li>Les dégradés sur Chrome (pas dans Safari sur Mac)</li> + <li>les <em>box shadows</em> sur Firefox</li> +</ol> + +<h2 id="les-dgrads">les dégradés</h2> + +<p>Sur Safari il n&rsquo;y a absolument aucun problème avec les dégradés. Par contre sur Chrome sous Linux le si...</p> + + + tag:yannesposito.com,2010-07-05:/n3blog/fr/blog/2010-07-05-Cappuccino-and-Web-applications/ + Cappuccino ou jQuery ? + 2010-07-05T11:49:04Z + 2010-07-05T11:49:04Z + + Yann Esposito + yannesposito.com + + + +<div class="intro"> + + +<p><abbr title="Trop long à lire">tlàl</abbr>:</p> + +<ul> + <li>J&rsquo;ai essayé de faire une version de <a href="http://yannesposito.com/Softwares/YPassword.html">YPassword</a> en jQuery et avec Cappuccino.</li> + <li>Cappuccino est très bien sur les navigateurs non mobile mais l&rsquo;application pèse 1.4Mo et n&rsquo;est pas compatible avec l&rsquo;iPhone.</li> + <li>la version jQuery n&rsquo;est pas aussi jolie que la version réalisée avec Cappuccino mais elle pèse seulement 106Ko et est compatible avec l&rsquo;iPhone.</li> + <li>J&rsquo;essayerai Dashcode 3</li> +</ul> + + +</div> + + +<hr /> + +<div class="intro"> + + +<p>Avant de commencer, je dois dire que je sais que Cappuccino et jQuery ne sont pas plus comparable que Cocoa et la <em>standard library</em> en...</p></div></hr> + + + tag:yannesposito.com,2010-06-18:/n3blog/fr/blog/2010-06-19-jQuery-popup-the-easy-way/ + Comment faire des popups en jQuery rapidement + 2010-06-18T22:44:50Z + 2010-06-18T22:44:50Z + + Yann Esposito + yannesposito.com + + + <p>Sur ce blog, je donne parfois la possibilité de télécharger certaines sources de code. +Dans ce cas, le code est souvent plus large que le <code>div</code> qui le contient. +Le texte est alors coupé. +C&rsquo;est pourquoi, j&rsquo;utilise une méthode qui permet d&rsquo;afficher ces sources dans de grandes <em>popups</em> en jQuery.</p> + +<p>Vous pouvez faire un essai en cliquant le code suivant&nbsp;; remarquez qu&rsquo;un bout du code n&rsquo;est pas visible (après <code>z-index</code> normallement)&nbsp;:</p> + +<div class="code"><div class="file"><a href="/n3blog/fr/blog/2010-06-19-jQuery-popup-the-easy-way/code/essai.js"> &#x27A5; essai.js </a></div><div class="withfile"> +<pre class="twilight"> +<span class="Comment"><span class="Comment">//</span> --- code popup ---</span> +</pre></div></div> + + + tag:yannesposito.com,2010-06-17:/n3blog/fr/blog/2010-06-17-hide-yourself-to-analytics/ + Se cacher de ses statistiques web + 2010-06-17T14:37:22Z + 2010-06-17T14:37:22Z + + Yann Esposito + yannesposito.com + + + <p>Voici un moyen très simple de ne plus être comptabilisé dans les visites de son propre site. +Tout d&rsquo;abord, vous devriez jeter un coup d&rsquo;œil sur comment <a href="/n3blog/fr/blog/2010-06-17-track-events-with-google-analytics">je gère les systèmes de récupération de statistiques</a>. +Je centralise tout dans un seul fichier javascript ce qui facilite le travail.</p> + +<p>Cette méthode nécessite l&rsquo;utilisation de <code>jquery-cookie</code>.</p> + +<p>Avant de comptabiliser les visites, je vérifie que la clé <code>admin</code> n&rsquo;est pas utilisée dans mes cookies.</p> + +<pre class="twilight"> + <span class="Storage">var</span> admin <span class="Keyword">=</span> <span class="Keyword">$</span>.<span class="SupportConstant">cookie</span>(</pre> + + + tag:yannesposito.com,2010-06-17:/n3blog/fr/blog/2010-06-17-track-events-with-google-analytics/ + Analyser les clicks sur votre Site + 2010-06-17T12:41:36Z + 2010-06-17T12:41:36Z + + Yann Esposito + yannesposito.com + + + <p>Voici comment analyser tous les clics que font vos utilisateurs sur votre blog en incluant google analytics de façon asynchrone.</p> + +<p>Dans le html, il faut utiliser <a href="http://jquery.com">jQuery</a> et un fichier que j&rsquo;ai appelé <code>yga.js</code>&nbsp;:</p> + +<pre class="twilight"> +<span class="EmbeddedSource"> <span class="EmbeddedSource">&lt;</span><span class="MetaTagInline">script</span> <span class="MetaTagInline">type</span>=<span class="String"><span class="String">&quot;</span>text/javascript<span class="String">&quot;</span></span> <span class="MetaTagInline">src</span>=<span class="String"><span class="String">&quot;</span>jquery.js<span class="String">&quot;</span></span><span class="EmbeddedSource">&gt;</span><span class="EmbeddedSource">&lt;/</span></span></pre> + + + tag:yannesposito.com,2010-06-15:/n3blog/fr/blog/2010-06-15-Get-my-blog-engine/ + Récupérez mon système de blog + 2010-06-15T08:56:32Z + 2010-06-15T08:56:32Z + + Yann Esposito + yannesposito.com + + + <p>J&rsquo;ai publié une version <em>light</em> de mon système de blog hier soir. Par <em>light</em> il faut comprendre avec un CSS plus épuré et plus portable (sans les bords ronds). +Vous pouvez le récupérer sur <a href="http://github.com/yogsototh/nanoc3_blog">github.com</a>.</p> + +<p>Que pouvez-vous attendre de ce système de blog&nbsp;?</p> + +<ul> + <li>Tous les avantages liés à <a href="http://nanoc.stoneship.org">nanoc</a>&nbsp;;</li> + <li>Facilité de la gestion de plusieurs langues&nbsp;;</li> + <li>coloration syntaxique des codes sources pour la plupart des languages&nbsp;;</li> + <li>commentaires gérés avec <a href="http://intensedebate.org">intenseDebate</a> de façon asynchrone&nbsp;;</li> + <li>très portable avec ou sans javascript, XHTML Strict 1.0 / CSS3&nbsp;;</li></ul> + + + tag:yannesposito.com,2010-06-14:/n3blog/fr/blog/2010-06-14-multi-language-choices/ + choix liés à l'écriture dans plusieurs langues + 2010-06-14T14:14:57Z + 2010-06-14T14:14:57Z + + Yann Esposito + yannesposito.com + + + <p>Je traduis la plupart de mes articles pour qu&rsquo;ils soient disponibles en français et en anglais. +La façon que l&rsquo;on m&rsquo;a conseillé était d&rsquo;avoir un fichier par langue. En général ça donne ça.</p> + +<pre class="twilight"> +Bonjour, + +voici un exemple de texte en français. +[image](url) +</pre> + +<pre class="twilight"> +Hello, + +here is an example of english text. +[image](url) +</pre> + +<p>Cette façon de traduire vous impose une certaine façon de traduire. +D&rsquo;abord écrire entièrement le texte dans une langue, +puis copier le fichier et enfin retraduire dans une nouvelle langue.</p> + +<p>Le problème, c&rsquo;est que très souvent, les articles ont des parties communes non négligeables. Par exemple, les images, les codes sources, etc&hellip; +Lorsque je m&...</p> + + + tag:yannesposito.com,2010-05-24:/n3blog/fr/blog/2010-05-24-Trees--Pragmatism-and-Formalism/ + Arbres ; Pragmatisme et Formalisme + 2010-05-24T18:05:14Z + 2010-05-24T18:05:14Z + + Yann Esposito + yannesposito.com + + + +<div class="intro"> + + +<p><abbr title="Trop Long À Lire"><span class="sc">tlàl</span></abbr>&nbsp;:</p> + +<ul> + <li>J&rsquo;ai essayé de programmer un simple filtre&nbsp;;</li> + <li>J&rsquo;ai été bloqué pendant deux jours&nbsp;;</li> + <li>J&rsquo;ai arrêté de penser comme un robot&nbsp;;</li> + <li>J&rsquo;ai utilisé un papier et un stylo&nbsp;;</li> + <li>J&rsquo;ai fait un peu de maths&nbsp;;</li> + <li>J&rsquo;ai résolu le problème en 10 minutes&nbsp;;</li> + <li>Conclusion: Pragmatisme n&rsquo;est pas&nbsp;: &laquo;n&rsquo;utilisez jamais la théorie&raquo;. + +</div> + +</ul> + +<h2 id="rsum-plus-long-que-le--abbr-titletrop-long--liresctllscabbr">Résumé (plus long que le <abbr title="Trop Long À Lire"><span class="sc">tlàl</span></abbr>)</h2> + +<p>Je devais résoudre un...</p></div> + + + tag:yannesposito.com,2010-05-19:/n3blog/fr/blog/2010-05-19-How-to-cut-HTML-and-repair-it/ + Comment réparer un XML coupé ? + 2010-05-19T20:20:34Z + 2010-05-19T20:20:34Z + + Yann Esposito + yannesposito.com + + + <p>Sur ma page d&rsquo;accueil vous pouvez voir la liste des mes derniers articles avec le début de ceux-ci. Pour arriver à faire ça, j&rsquo;ai besoin de couper le code XHTML de mes pages en plein milieu. Il m&rsquo;a donc fallu trouver un moyen de les réparer.</p> + +<p>Prenons un exemple&nbsp;:</p> + +<pre class="twilight"> +<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">div</span> <span class="MetaTagAll">class</span>=<span class="String"><span class="String">&quot;</span>corps<span class="String">&quot;</span></span><span class="MetaTagAll">&gt;</span></span> + <span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">div</span> <span class="MetaTagAll">class</span>=<span class="String"><span class="String">&quot;</span></span></span></pre> + + + tag:yannesposito.com,2010-05-17:/n3blog/fr/blog/2010-05-17-at-least-this-blog-revive/ + Je reviens à la vie ! + 2010-05-17T11:25:51Z + 2010-05-17T11:25:51Z + + Yann Esposito + yannesposito.com + + + <p>Bonjour à tous&nbsp;!</p> + +<blockquote cite="http://www.madore.org/~david/weblog/2010-05.html#d.2010-05-12.1752"> + <p>&hellip;plus on retarde quelque chose, plus il devient difficile de s&rsquo;y mettre&hellip;</p> +</blockquote> + +<p>Je devais écrire d&rsquo;autres articles pour ce blog. J&rsquo;ai noté plein d&rsquo;idées dans mes <em>todolist</em>. Mais j&rsquo;avais pas mal d&rsquo;autres choses à faire. Et jusqu&rsquo;ici, j&rsquo;ai toujours dit &laquo;je le ferai plus tard&raquo;. Ce qui m&rsquo;a fait agir, c&rsquo;est la petite réflexion que j&rsquo;avais lu une fois. +&gt; Arrétez d&rsquo;écrire des <code>TODO</code> dans votre code est faites le maintenant&nbsp;!<br /> +&gt; Vous serez surpris de l&rsquo;efficacité de cette mesure.</p> + +<p>En résumé&nbsp;: +&gt; </p></p> + + + tag:yannesposito.com,2010-03-23:/n3blog/fr/blog/2010-03-23-Encapsulate-git/ + Encapsuler git + 2010-03-23T20:37:36Z + 2010-03-23T20:37:36Z + + Yann Esposito + yannesposito.com + + + <p><span class="intro"> +Voici une solution pour conserver des branches divergentes avec <code>git</code>. +Parce qu&rsquo;il est facile de <em>merger</em> par erreur, je propose un script qui encapsule le comportement de <code>git</code> pour interdire certains <em>merges</em> dangereux. Mais qui permet aussi de faire des merges en cascades de la racines vers les autres branches. +</span></p> + +<h2 id="se-prmunir-contre-les-erreurs">Se prémunir contre les erreurs</h2> + +<p>Je travaille sur un projet dans lequel certaines de mes branches <code>git</code> doivent rester divergentes. Et les divergences devraient aller en s&rsquo;accentuant.</p> + +<p>J&rsquo;utilise aussi certaines branches qui contiennent la partie commune de ces projets.</p> + +<p>Disons que j&rsquo;ai les branches&nbsp;:</p> + +...</p> + + + tag:yannesposito.com,2010-03-22:/n3blog/fr/blog/2010-03-22-Git-Tips/ + Astuces Git + 2010-03-22T08:42:27Z + 2010-03-22T08:42:27Z + + Yann Esposito + yannesposito.com + + + <h2 class="first" id="cloner-de-github--travers-un-pare-feu">Cloner de github à travers un pare-feu</h2> + +<p>La façon standard:</p> + +<div><pre class="twilight"> +git clone git@github.com:yogsototh/project.git +</pre></div> + +<p>En utilisant le port HTTPS&nbsp;:</p> + +<div><pre class="twilight"> +git clone git+ssh://git@github.com:443/yogsototh/project.git +</pre></div> + +<h2 id="cloner-toutes-les-branches">Cloner toutes les branches</h2> + +<p><code>git clone</code> peut seulement récuper la branche <code>master</code>.</p> + +<p>Si vous n&rsquo;avez pas beaucoup de branches, vous pouvez simplement les clone le project et ensuite pour chacune d&rsquo;entre elle lancer la commande suivante&nbsp;:</p> + +<div><pre class="twilight"> +git branch --track local_branch remote_branch +</pre></div> + +<p>par ...</p> + + + tag:yannesposito.com,2010-02-23:/n3blog/fr/blog/2010-02-23-When-regexp-is-not-the-best-solution/ + Quand se passer des expressions régulières ? + 2010-02-23T08:09:52Z + 2010-02-23T08:09:52Z + + Yann Esposito + yannesposito.com + + + <p>Les expressions régulières sont très utiles. Cependant, elles ne sont pas toujours la meilleure manière d&rsquo;aborder certain problème autour des chaines de caractères. +Et surtout quand les transformations que vous voulez accomplir sont simples.</p> + +<p>Je voulais savoir comment récupérer le plus vite possible l&rsquo;extension d&rsquo;un nom de fichier. Il y a trois manière naturelle d&rsquo;accomplir celà&nbsp;:</p> + +<div><pre class="twilight"> +<span class="Comment"><span class="Comment">#</span> regexp</span> +str.<span class="Entity">match</span>(<span class="StringRegexp"><span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="StringRegexp">[</span>^.<span class="StringRegexp">]</span></span>*$</span></pre></div> + + + tag:yannesposito.com,2010-02-18:/n3blog/fr/blog/2010-02-18-split-a-file-by-keyword/ + découper un fichier par mots clés + 2010-02-18T13:29:14Z + 2010-02-18T13:29:14Z + + Yann Esposito + yannesposito.com + + + <p>Assez bizarrement, je n&rsquo;ai trouvé aucun outil UNIX pour découper un fichier par mot clé. +Alors j&rsquo;en ai fait un en <code>awk</code>. Je le met ici principalement pour moi, mais ça peut toujours servir à quelqu&rsquo;un d&rsquo;autre. +Le code suivant découpe un fichier pour chacune de ses ligne contenant le mot <code>UTC</code>.</p> + +<div><pre class="twilight"> +<span class="Comment"><span class="Comment">#</span>!/usr/bin/env awk</span> +<span class="Entity">BEGIN</span>{i=0;} +<span class="StringRegexp"><span class="StringRegexp">/</span>UTC<span class="StringRegexp">/</span></span> { + i+=1; + FIC=<span class="SupportFunction">sprintf</span>(<span class="String"><span class="String">&quot;</span>fic.%03d<span class="String">&quot;</span></span>,i); +} +{</pre></div> + + + tag:yannesposito.com,2010-02-16:/n3blog/fr/blog/2010-02-16-All-but-something-regexp--2-/ + Tout sauf quelquechose en expression régulière. + 2010-02-16T08:33:21Z + 2010-02-16T08:33:21Z + + Yann Esposito + yannesposito.com + + + <p>Dans mon <a href="previouspost">précédent article</a> j&rsquo;ai donné certaines astuces pour matcher &lsquo;tout sauf quelque chose&rsquo;. De la même manière, un truc pour matcher la chaine de caractère la plus petite possible. +Disons que vous voulez matcher la chaine de caractère entre &lsquo;a&rsquo; et &lsquo;b&rsquo;. Par exemple, vous voulez matcher&nbsp;:</p> + +<pre class="twilight"> +a.....<span class="Constant"><strong>a......b</strong></span>..b..a....<span class="Constant"><strong>a....b</strong></span>... +</pre> + +<p>Voici les deux erreurs communes et une solution&nbsp;:</p> + +<pre class="twilight"> +/a.*b/ +<span class="Constant"><strong>a.....a......b..b..a....a....b</strong></span>... +</pre> + +<p>La première erreur vient de l&rsquo;utilisation du <em>terrible</em> </p> + + + tag:yannesposito.com,2010-02-15:/n3blog/fr/blog/2010-02-15-All-but-something-regexp/ + Expression régulière pour tout sauf quelquechose + 2010-02-15T09:16:12Z + 2010-02-15T09:16:12Z + + Yann Esposito + yannesposito.com + + + <p>Parfois vous ne pouvez simplement pas écrire&nbsp;:</p> + +<div><pre class="twilight"> +<span class="Keyword">if</span> str.<span class="Entity">match</span>(regexp) <span class="Keyword">and</span> + <span class="Keyword">not</span> str.<span class="Entity">match</span>(other_regexp) + do_something +</pre></div> + +<p>et vous devez obtenir le même comportement avec seulement une expression régulière. Le problème c&rsquo;est que le complémentaire des régulier n&rsquo;est pas régulier. Celà peut s&rsquo;avérer impossible.</p> + +<p>Cependant, pour certaines expressions ce peut être possible<sup><a href="#note1">&dagger;</a></sup>. Disons que vous souhaitez <em>matcher</em> toutes les lignes contenant le mot <code>bull</code>, mais que vous ne souhaitez pas matcher <code>bu...</code></p> + + + tag:yannesposito.com,2010-01-12:/n3blog/fr/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/ + Fontes adoucies sous Ubuntu Firefox + 2010-01-12T14:36:40Z + 2010-01-12T14:36:40Z + + Yann Esposito + yannesposito.com + + + <p>Voici comment faire pour ne plus utiliser les fontes Microsoft© sous Linux Ubuntu pour avoir de belles fontes adoucies (anti aliased) qui ne font pas mal aux yeux sous Firefox.</p> + +<p>modifiez le fichier <code>/etc/fonts/local.conf</code> en y incluant le contenu suivant&nbsp;: </p> + +<div> +<div class="code"><div class="file"><a href="/n3blog/fr/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/code/local.conf"> &#x27A5; local.conf </a></div><div class="withfile"> +<pre class="twilight"> + +<span class="DoctypeXmlProcessing"><span class="DoctypeXmlProcessing">&lt;?</span><span class="DoctypeXmlProcessing">xml</span><span class="DoctypeXmlProcessing"> version</span>=<span class="DoctypeXmlProcessing"><span class="DoctypeXmlProcessing">&quot;</span>1.0</span></span></pre></div></div></div> + + + tag:yannesposito.com,2010-01-04:/n3blog/fr/blog/2010-01-04-Change-default-shell-on-Mac-OS-X/ + Changer le shell par défaut sous Mac OS X + 2010-01-04T10:31:47Z + 2010-01-04T10:31:47Z + + Yann Esposito + yannesposito.com + + + <p>Je viens de trouver le moyen de changer son shell par défaut sous Mac OS X. Cette note est plus pour moi. Mais elle peut aussi servir à quelqu&rsquo;un d&rsquo;autre. Il suffit de lancer la commande&nbsp;: </p> + +<div><pre class="twilight"> +<span class="Keyword">&gt;</span> chsh +</pre></div> +</div> + + + tag:yannesposito.com,2009-12-14:/n3blog/fr/blog/2009-12-14-Git-vs--Bzr/ + Git ou Bazaar ? + 2009-12-14T08:46:36Z + 2009-12-14T08:46:36Z + + Yann Esposito + yannesposito.com + + + +<div class="intro"> + + +<p>Même si je considère que <code>git</code> a beaucoup de points noirs, je pense qu&rsquo;il reste le meilleur DCVS à ce jour avec lequel travailler. C&rsquo;est pourquoi je commencerai par parler des qualité de bazaar qui manquent à git. Ensuite seulement je donnerai le seul avantage de git qui suffit à le rendre préférable à Bazaar.</p> + + +</div> + + +<h2 id="la-dcouverte-des-dcvs">La découverte des DCVS</h2> + +<p>À savoir avant de débuter l&rsquo;article. Je suis, comme beaucoup, un ancien utilisateur de <em>subversion</em>. Je trouve subversion très bien, mais j&rsquo;ai été conquis par les capacités supplémentaires apportées par les systèmes de versions concurrentes <em>décentralisés</em>.</p> + +<p>Il y a deux façon de percevoir les système...</p> + + + tag:yannesposito.com,2009-12-06:/n3blog/fr/blog/2009-12-06-iphone-call-filter/ + Filtrage d'appel avec l'iPhone + 2009-12-06T09:35:34Z + 2009-12-06T09:35:34Z + + Yann Esposito + yannesposito.com + + + <p>Il est vraiment incroyable que le filtrage d&rsquo;appel soit impossible avec un iPhone&nbsp;! Le <em>seul</em> intérêt que j&rsquo;y vois, c&rsquo;est une négociation avec les opérateurs pour interdire aux utilisateurs de passer à travers la publicité. C&rsquo;est tout simplement inacceptable.</p> + +<p>Je suis un utilisateur λ de l&rsquo;iPhone. Le seul moyen de filtrer ses appels, de faire des blacklists ou autre c&rsquo;est de <em>jailbreaker</em> son iPhone. Et je n&rsquo;en ai aucune envie. Alors si comme moi, vous trouvez ça inacceptable, envoyez un mot à Apple&nbsp;: <a href="http://www.apple.com/feedback/iphone.html">http://www.apple.com/feedback/iphone.html</a></p> +</p> + + + tag:yannesposito.com,2009-11-12:/n3blog/fr/blog/2009-11-12-Git-for-n00b/Git-pour-quoi-faire/ + Git pour les nuls + 2009-11-12T09:39:54Z + 2009-11-12T09:39:54Z + + Yann Esposito + yannesposito.com + + + <h1 class="first" id="gitgit-pour-quoi-faire-"><a href="http://git-scm.org" title="Git">Git</a> pour quoi faire&nbsp;?</h1> + + +<div class="intro"> + + +<p>Si tout ce qui vous intéresse c&rsquo;est d&rsquo;utiliser <a href="http://git-scm.org" title="Git">Git</a> <strong>tout de suite</strong>. Lisez simplement les parties sur fond noir. Je vous conseille aussi de revenir relire tout ça un peu plus tard, pour mieux comprendre les fondements des systèmes de versions et ne pas faire de bêtises quand vous les utilisez.</p> + + +</div> + + +<p><a href="http://git-scm.org" title="Git">Git</a> est un <abbr title="Decentralized Concurent Versions System">DCVS</abbr>, c&rsquo;est-à-dire un système de versions concurrentes décentralisé. Analysons chaque partie de cette appellation compliquée.</p> +...</p> + + + tag:yannesposito.com,2009-11-12:/n3blog/fr/blog/2009-11-12-Git-for-n00b/ + Git pour les nuls + 2009-11-12T09:39:54Z + 2009-11-12T09:39:54Z + + Yann Esposito + yannesposito.com + + + +<div class="intro"> + + +<p>Voici un tutoriel <a href="http://git-scm.org">Git</a> détaillé pour ceux qui en connaissent très peu sur les systèmes de versions. Vous comprendrez l&rsquo;utilité de tels systèmes et surtout comment on se sert des systèmes de versions modernes, le tout en restant le plus pragmatique possible.</p> + + +</div> + + + +</div> + +<div class="corps"> + + +<h1 class="first" id="pour-commencer-la-conclusion">Pour commencer, la conclusion</h1> + +<p>Voici la liste des commandes nécessaires et suffisantes pour utiliser <a href="http://git-scm.org" title="Git">Git</a>. Il y en a très peu. Il est normal de ne pas les comprendre tout de suite mais c&rsquo;est pour vous donner une idée. Malgré la longueur de l&rsquo;article, 95% de l&rsquo;utilisation de </p> + + + tag:yannesposito.com,2009-11-12:/n3blog/fr/blog/2009-11-12-Git-for-n00b/commandes-avancees/ + Git pour les nuls + 2009-11-12T09:39:54Z + 2009-11-12T09:39:54Z + + Yann Esposito + yannesposito.com + + + <h1 class="first" id="liste-de-commandes">Liste de commandes</h1> + +<h2 id="les-commandes-pour-chaque-choses">Les commandes pour chaque choses</h2> + +<p>Dans la première partie, nous avons vu la liste des problèmes résolus par <a href="http://git-scm.org" title="Git">Git</a>. En résumé Git doit pouvoir&nbsp;:</p> + +<ul> + <li>récupérer les modifications des autres&nbsp;;</li> + <li>envoyer ses modifications aux autres&nbsp;;</li> + <li>revenir dans le temps&nbsp;;</li> + <li>lister les différences entre chaque version&nbsp;;</li> + <li>nommer certaines versions pour s&rsquo;y référer facilement&nbsp;;</li> + <li>afficher l&rsquo;historique des modifications&nbsp;;</li> + <li>savoir qui a fait quoi et quand&nbsp;;</li> + <li>gérer des conflits&nbsp;;</li> + <li>manipuler facileme...</li></ul> + + + tag:yannesposito.com,2009-11-12:/n3blog/fr/blog/2009-11-12-Git-for-n00b/comprendre/ + Git pour les nuls + 2009-11-12T09:39:54Z + 2009-11-12T09:39:54Z + + Yann Esposito + yannesposito.com + + + <h1 class="first" id="pourquoi-git-est-cool-">Pourquoi Git est cool&nbsp;?</h1> + +<p>Parce que grace à <a href="http://git-scm.org" title="Git">Git</a> vous pouvez travailler sur plusieurs partie du projet de façon complètement isolée les unes des autres. Ça c&rsquo;est la partie décentralisée de <a href="http://git-scm.org" title="Git">Git</a>.</p> + +<p>Toutes les branches locales utilisent le même répertoire. Ainsi on peu changer de branche très aisément et rapidement. On peut aussi changer de branche alors que certains fichier sont en cours de modifications. On peut même pousser le vice jusqu&rsquo;à modifier un fichier, changer de branche, commiter une partie seulement des modifications de ce fichier dans la branche courante. Revenir dans l&rsquo;ancienne branche et commi...</p> + + + tag:yannesposito.com,2009-11-12:/n3blog/fr/blog/2009-11-12-Git-for-n00b/conf-et-install/ + Git pour les nuls + 2009-11-12T09:39:54Z + 2009-11-12T09:39:54Z + + Yann Esposito + yannesposito.com + + + <h1 class="first" id="avant-lutilisation-la-configuration">Avant l&rsquo;utilisation, la configuration</h1> + +<h2 id="installation">installation</h2> + +<p>Sous Linux Ubuntu ou Debian&nbsp;:</p> + +<div><pre class="twilight">$ sudo apt-get install git +</pre></div> + +<p>Sous Mac OS X&nbsp;:</p> + +<ul> + <li>installez <a href="http://macports.org/install.php">MacPorts</a></li> + <li>installez <a href="http://git-scm.org" title="Git">Git</a></li> +</ul> + +<div><pre class="twilight"> +$ sudo port selfupdate + +$ sudo port install git-core +</pre></div> + +<h2 id="configuration-globale">Configuration globale</h2> + +<p>Enregistrez le fichier suivant comme le fichier <code>~/.gitconfig</code>.</p> + +<div><div class="code"><div class="file"></div></div></div> + + + tag:yannesposito.com,2009-11-12:/n3blog/fr/blog/2009-11-12-Git-for-n00b/c-est-parti-pour-l-aventure/ + Git pour les nuls + 2009-11-12T09:39:54Z + 2009-11-12T09:39:54Z + + Yann Esposito + yannesposito.com + + + <h1 class="first" id="et-cest-parti-">Et c&rsquo;est parti&nbsp;!</h1> + +<p>Voici une parmi de nombreuses autres façon d&rsquo;utiliser <a href="http://git-scm.org" title="Git">Git</a>. Cette méthode est nécessaire et suffisante pour travailler seul ou en collaboration sur un projet commun. Cependant, on peut faire beaucoup mieux avec <a href="http://git-scm.org" title="Git">Git</a> que ce <em>workflow</em> (en langage anglo-saxon).</p> + +<h2 id="utilisation-basique">Utilisation basique</h2> + +<p>La façon immédiate de travailler avec <a href="http://git-scm.org" title="Git">Git</a>&nbsp;:</p> + +<ul> + <li>récupérer les modifications des autres <span class="black"><code>git pull</code></span></li> + <li>voir les détails de ces modifications <span class="black"><code>git log</code></span></li></ul> + + + tag:yannesposito.com,2009-10-30:/n3blog/fr/blog/2009-10-30-How-to-handle-evil-IE/ + Une CSS pour IE seulement + 2009-10-30T20:34:46Z + 2009-10-30T20:34:46Z + + Yann Esposito + yannesposito.com + + + <p>Pour les développeur de site web Internet Explorer est un cauchemar. C&rsquo;est pourquoi j&rsquo;utilise un style complètement différent pour ce navigateur. Avec la librairie jQuery.</p> + +<div><pre class="twilight"> +<span class="Keyword">$</span>(<span class="Support">document</span>).ready( <span class="Storage">function</span>() { + <span class="Keyword">if</span> (<span class="Keyword">$</span>.browser[<span class="String"><span class="String">&quot;</span>msie<span class="String">&quot;</span></span>]) { + <span class="Comment"><span class="Comment">//</span> include the ie.js file</span> + <span class="Keyword">$</span>(<span class="String"><span class="String">'</span>head<span class="String">'</span></span>).append(<span class="String"><span class="String">'</span></span></pre></div> + + + tag:yannesposito.com,2009-10-28:/n3blog/fr/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/ + Synchronisation avec mobileme (2) + 2009-10-28T09:03:30Z + 2009-10-28T09:03:30Z + + Yann Esposito + yannesposito.com + + + <p>J&rsquo;ai déjà discuté de la façon dont je <a href="/n3blog/fr/blog/10_Synchronize_Custom_WebSite_with_mobileMe">synchronise mon site web sur mobileme</a>. J&rsquo;ai amélioré mon script pour le rendre incrémental.</p> + +<p>Voici mon script, il créé tout d&rsquo;abord un fichier qui contient la liste des fichiers avec leur <em>hash</em>. Afin de les comparer avec ceux qui sont en ligne sans avoir à les parcourir. Ensuite pour chaque fichier qui semble différent, je met à jour le contenu.</p> + +<p>Cependant même avec ce script j&rsquo;ai encore des problèmes. Dû à webdav. En particulier le renommage de répertoire. Par exemple&nbsp;:</p> + +<div><pre class="twilight"> +mv folder folder2 +</pre></div> + +<p>Retourne OK et pourtant&nbsp;: </p> + +<div><pre class="twilight"> +$ ls ...</pre></div> + + diff --git a/output/n3blog/fr/blog/index.html b/output/n3blog/fr/blog/index.html new file mode 100644 index 000000000..12fbe5ff2 --- /dev/null +++ b/output/n3blog/fr/blog/index.html @@ -0,0 +1,2147 @@ + + + + + + + + + + + + + + + + Blog + + + + +
+ + + + Presentation drawing +
+

+ Blog +

+ +
+ +
+ + + + + +
+ +
+ + + +

+ + 3 + Jan + 2011 + + Pourquoi je n'utiliserai pas CoffeeScript (malheureusement) » +

+ +
+ + +

Title image

+ + +
+ + +

tlàl : Qu’est-ce qui n’allait pas avec Coffeescript? La meta-programmation, il faut le “vendre” aux autres, une nouvelle étape de compilation intermédiaire sans fournir les avantages de Cappuccino, la sensation que c’est un peu instable.

+ + +
+ + +

Le commentaire le mieux classé de la question suivante posée sur HackerNews mentionnait CoffeeScript. +Récemment j’ai beaucoup programmé en javascript. +Après avoir essayé +

+ +
+
+

+ en lire plus » +

+
+ +
+ +

+ + 1 + Jan + 2011 + + Bonne et heureuse année » +

+ +
+ + +

Bonne et heureuse année !

+ +

J’étais très occupé ces derniers mois. +Maintenant il me semble que je vais pouvoir faire revivre ce blog.

+ +

J’ai fait un outil qui permet d’écrire des livre en utilisant une syntaxe proche de markdown. +C’est un markdown avec des macros (essentiel pour les textes longs). +De plus le système gère la génération de pages HTML ainsi que du PDF engendré avec du XeLaTeX. +Je n’en ai pas encore terminé avec ça. Mais si je tarde trop, je communiquerai lorsque j’aurai fini le minimum.

+ +

J’ai écrit un framework MVC pour application javascript simple mais néanmoins très rapide.

+ +

Meilleurs vœux à tous !

+

+ +
+
+

+ en lire plus » +

+
+ +
+ +

+ + 26 + Oct + 2010 + + Des macros LaTeX pour markdown » +

+ +
+ + + +
+ + +

tlàl : J’ai fait un système simple de macros pour mon blog. Par exemple, il me suffit d’écrire %latex et ça affiche LaTeX.

+ + +
+ + +

J’ai ajouter un système de macro pour mon système de blog. +Lorsqu’on est habitué à LaT

+ +
+
+

+ en lire plus » +

+
+ +
+ +

+ + 14 + Oct + 2010 + + S'amuser avec un .wav » +

+ +
+ + + +
+ + +

tlàl : Je me suis amusé à lire un fichier wav. Le C fut le langage le mieux adapté à ce traitement. Bien meilleur que Ruby par exemple.

+ +

edit: Je voulais que ce programme fonctionne sur une machine spécifique. En aucun cas je ne pensais publier ce code pour une utilisation autre que celle-ci.

+ + +
+ + +

J’ai eu besoin de calculer la somme des valeurs absolue des données d’un fichier wav. +Pour des raison d’efficacité (et aussi de fun), j’ai fait le programme en C.

+ +

Celà faisait longtemps que je n’avais pas programmé en C. +De mémoire il était peu aisé de manipuler des ...

+ +
+
+

+ en lire plus » +

+
+ +
+ +

+ + 10 + Oct + 2010 + + Sécurisez vos emails » +

+ +
+ + +

Title image

+ + +
+ + +

tlàl : avec un Mac

+ +
    +
  • Récupérez un certificat signé par une AC: cliquez ici pour un certificat gratuit ;
  • +
  • ouvrez le fichier ;
  • +
  • supprimer le fichier en mode sécurisé ;
  • +
  • utilisez Mail plutôt que l’interface web de gmail.
  • +
+ + +
+ + +

J’ai (re)découvert comment adoptez la norme S/MIME. +J’ai été surpris de voir à quel point ce fut aisé. +Il y a seulement quelques années c&rsq...

+ +
+
+

+ en lire plus » +

+
+ +
+ + +
+
+

analyser

analytics

Apple

arbre

asynchrone

awk

Bazaar

blacklist

blog

branch

branches

bzr

cacher

Cappuccino

Chrome

Cocoa

commentaires

courriel

CSS

David Lynch

DCVS

dcvs

design

disqus

drm

email

expressions régulières

extension

fichier

film

filter

Firefox

Fonts

git

Google

HTML

indecidability

intense debate

iPhone

iTunes

javascript

jQuery

langues

Linux

local

Lost Highway

Mac

mac

mathématiques

mobileme

nanoc

Objective-C

OS X

philosophy

programmation

Programmation

programming

protection

regexp

regular expression

remote

ruby

Réalité alternée

S/MIME

Safari

science

screensaver

script

securité

shell

ssh

statistiques

svn

synchronisation

théorie

tip

Ubuntu

utilisateur

web

WebDav

webdesign

workflow

zsh

+
+
+ +

Archives

+ +

[2011]

[2010]

[2009]

[2008]

+ +

+Un petit mot sur le contenu +

+ + +
+ + +

+Vous trouverez ici des articles qui sont pour la plupart +écrits en anglais et qui sont techniques. +Certain sont justes là pour me souvenir de petits trucs, que +d'autres pourraient trouver utiles. Mais il y a aussi de +long articles techniques qui vont un peu plus dans les détails. +

+


+

+ Je fais de mon mieux pour traduire chaque page en anglais et en français. +Cependant, ce n'est pas toujours évident. +Il m'arrive de faire de nombreuses fautes d'orthographes, des erreurs typographiques et autres. +

+

+ Merci de ne pas me juger sur ces erreurs et de ne pas oublier que le fond est plus important que la forme. +

+L'impression que ce site laisse de moi n'est certainement pas l'impression que je vous laisserais si on se rencontrait. +

+Je vous souhaite de trouver ce que vous cherchez sur ce site. +

+ + + +
+
+ +
+ modifié le : 07/04/2011 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/blog/mvc/index.html b/output/n3blog/fr/blog/mvc/index.html new file mode 100644 index 000000000..5f6a48998 --- /dev/null +++ b/output/n3blog/fr/blog/mvc/index.html @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + Les raisons du MVC + + + + +
+ + +
+

+ Les raisons du MVC +

+ +
+ +
+ + + + + +
+
+
+

Why This article and for whom?

+ +

Many website explaining how MVC works. But I can’t found one who explain why.

+ +

I have difficulties to obey some principle don’t know why I should use it. And something better than the:

+ +
+

“Smarter people than you decided you have to do so”

+
+ +

This article is for people who like me want to understand the real motivation of using an MVC architecture and which advantage it gives you.

+ +

Let’s start making a project from scratch pretending we don’t know anything about the MVC architecture. Then let see how we’ll naturally derive to an MVC architecture.

+ +
+

→ Next

+
+ +
+ + + + + +
+
+

commentaires

+ + + + + + +
+ +
+ +
+
+
+ + +
+
+
+ + +
+ +
+ Écrit le : 06/07/2009 + modifié le : 09/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/index.html b/output/n3blog/fr/index.html new file mode 100644 index 000000000..7d7a5572b --- /dev/null +++ b/output/n3blog/fr/index.html @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + Bienvenue + + + + +
+ + Presentation drawing +
+

+ + + Yann + Esposito + + +

+ +

+ + Yogsototh + +

+ +
+ +
+ + + + + +
+ +
+
+ + + +
+ +
+

+ + Blog + » + +

+

+ Ordinateurs, philosophie & des choses de la vie. +

+
+
+

+ + Logiciels + » + +

+

+ Des économiseurs d'écran, + un gestionnaire de mots de passe & + des applications scientifiques. +

+
+
+

+ + Contact + » + +

+

+ Au diable la timidité, n'hésitez pas à me contacter, je serai ravi de vous parler. +

+
+
+
+

+ + Curriculum Vitæ + » + +

+

+ Doctorat → Post Doc → Consultant
+ Geek → G33K → G33|< + +

+ +
+
+

+ + Enseignement + » + +

+

+ Informatique:
+ TD, TD & solutions
+ BAC+1 à BAC+5
+ Projet réseau anonyme + » + +

+
+ +
+ +
+
+ +
+ modifié le : 05/01/2011 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/rss/index.html b/output/n3blog/fr/rss/index.html new file mode 100644 index 000000000..6f738f41c --- /dev/null +++ b/output/n3blog/fr/rss/index.html @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + Que sont les flux RSS ? + + + + +
+ + + + Presentation drawing +
+

+ Que sont les flux RSS ? +

+ +

+ Comment s'informer sans se fatiguer +

+ +
+ +
+ + + + + +
+ +
+
+

Lorsque vous cliquez sur ce logo :

+ +

rss

+ +

On vous propose de vous abonner au flux RSS. Mais de quoi s’agit il ?

+ +

Si vous n’êtes pas anglophobe je vous recommande la lecture de what is rss ou encore mieux, de regarder cette vidéo RSS explained.

+ + +
+ +
+ + +

Mon explication

+ +

Il s’agit d’un moyen facile d’agréger dans un seul endroit toutes les mises à jours de tous les sites qui vous intéressent.

+ +

choisir un client

+ +

Tout d’abord, il faut choisir un client de flux RSS. Aujourd’hui il existe de nombreux client en ligne. C’est-à-dire des sites web qui vont s’occuper du regroupement. Ces client s’appellent des “aggregator”.

+ +

Personnellement j’utilise Netvibes. J’en ai essayé vraiment beaucoup, et il reste de loin mon préféré.

+ +

Évidemment Google propose son client aussi : Google Reader. S’il reste adapté pour les contenus pour lesquels on ne veut rien perdre. Il est moins agréable d’utilisation lorsque l’on s’abonne à des flux qui proposent une vingtaine de nouveaux liens par jour.

+ +

S’abonner aux flux d’un site

+ +

Donc une fois que l’on a choisi son client, il suffit pour s’abonner de cliquer sur l’icône d’abonnement. Soit il est bien visible sur la page, soit tout en haut dans la barre des tâches.

+ +

Récupérer les “news”

+ +

Ensuite lorsque vous utilisez votre client RSS les nouvelles provenant du blog se mettront à jour. Ainsi, il n’y a plus besoin d’aller sur les sites intéressants pour voir s’il n’y a rien de neuf. Ce sont eux qui vous donne leur dernières nouvelles.

+ + + + +
+
+ +
+ modifié le : 28/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/softwares/index.html b/output/n3blog/fr/softwares/index.html new file mode 100644 index 000000000..5df1f5084 --- /dev/null +++ b/output/n3blog/fr/softwares/index.html @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + Softwares + + + + +
+ +
+
+ + +
+ +
+
+
+ + Presentation drawing +
+

+ Softwares +

+ +
+ +
+ + + + + +
+ +
+
+
+

+ YPassword + » + +

+

+ YPassword est un outil de gestion de mots de passe pour rendre votre vie en ligne plus sûre. +

+
+ +
+

+ YAquaBubbles + » + +

+

+ Des bulles se déplaçant sous l'eau +

+
+ +
+

+ YClock + » + +

+

+ Une horloge inspirée par le symbole "biohazard" +

+
+ +
+ + + + +
+
+ +
+ modifié le : 05/10/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/softwares/yaquabubbles/index.html b/output/n3blog/fr/softwares/yaquabubbles/index.html new file mode 100644 index 000000000..ba4983a5a --- /dev/null +++ b/output/n3blog/fr/softwares/yaquabubbles/index.html @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + YAquaBubbles + + + + +
+ + + + Presentation drawing +
+

+ YAquaBubbles +

+ +

+ Des bulles flottantes +

+ +
+ +
+ + + + + +
+ +
+
+

Screenshot

+ +

YAquaBubbles est un économiseur d’écran réalisé avec QuartzComposer. +Il s’agissait d’un simple essai mais le résultat était plaisant.

+ +

YAquaBubbles.dmg

+ + + + + +
+
+ +
+ modifié le : 06/10/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/softwares/yclock/index.html b/output/n3blog/fr/softwares/yclock/index.html new file mode 100644 index 000000000..ef10a5535 --- /dev/null +++ b/output/n3blog/fr/softwares/yclock/index.html @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + YClock + + + + +
+ + + + Presentation drawing +
+

+ YClock +

+ +
+ +
+ + + + + +
+ +
+
+

Screenshot

+ +

YClock est un économiseur d’écran qui vous donne l’heure.i +Il a trois thèmes clair, rouge et noir. +Il utilise une base de QuartzComposition + du code objective-C pour la gestion du nombre d’images par seconde.

+ +

YClock.dmg

+ + + + + +
+
+ +
+ modifié le : 05/10/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/softwares/ypassword/index.html b/output/n3blog/fr/softwares/ypassword/index.html new file mode 100644 index 000000000..106de6aa8 --- /dev/null +++ b/output/n3blog/fr/softwares/ypassword/index.html @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + YPassword + + + + +
+ + + + Presentation drawing +
+

+ YPassword +

+ +
+ +
+ + + + + +
+ +
+
+

Une gestion simple, sécurisée et portable de ses mots de passes web.

+ +

Souvenez vous d’un seul mot de passe de bonne qualité, le reste suis. +Lisez mon article pour les détails.

+ +

Ici vous trouverez :

+ + + +

Dans peu de temps je créerai une application iPhone pour YPassword.

+ + + + +
+
+ +
+ modifié le : 07/10/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/softwares/ypassword/iphoneweb/index.html b/output/n3blog/fr/softwares/ypassword/iphoneweb/index.html new file mode 100644 index 000000000..42ae9afec --- /dev/null +++ b/output/n3blog/fr/softwares/ypassword/iphoneweb/index.html @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + YPassword + + + + +
+ + + + Presentation drawing +
+

+ YPassword +

+ +

+ Web Interface for iPhone +

+ +
+ +
+ + + + + +
+ +
+
+
+ +
+ + + + +
+
+ +
+ modifié le : 01/10/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/softwares/ypassword/web/index.html b/output/n3blog/fr/softwares/ypassword/web/index.html new file mode 100644 index 000000000..5c076cead --- /dev/null +++ b/output/n3blog/fr/softwares/ypassword/web/index.html @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + YPassword + + + + +
+ + + + Presentation drawing +
+

+ YPassword +

+ +

+ Cappuccino Web Application +

+ +
+ +
+ + + + + +
+ +
+
+
+ +
+ + + + +
+
+ +
+ modifié le : 01/10/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/fr/validation/index.html b/output/n3blog/fr/validation/index.html new file mode 100644 index 000000000..0a0a42f40 --- /dev/null +++ b/output/n3blog/fr/validation/index.html @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + Validation + + + + +
+ + + + Presentation drawing +
+

+ Validation +

+ +
+ +
+ + + + + +
+ +
+
+

Une explication rapide du pourquoi il y a des erreurs de validation +de mes pages.

+ +

Je voulais utiliser box-shadows et border-radius

+ +

J’ai donc préféré avoir un approche pragamatique que dogmatique.

+ +

Utiliser ces propriétés me fait perdre la validation +CSS +mais fonctionne très bien avec les navigateurs récents (Safari 4 +et Firefox 3.5 au moment de l’écriture de ces lignes)

+ +

Si vous n’utilisez pas ces navigateur les pages s’affichent +correctement mais sans ces effets qui n’ont pour but que d’améliorer +l’aspect général de la page.

+ +

Par contre je suis plutôt un partisant de la validation et c’est +pourquoi il y a toujours les liens. Tout valide à l’exception +des propriétés commençant par -moz et -webkit.

+ + + + +
+
+ +
+ modifié le : 05/05/2010 +
+
+ Site entièrement réalisé avec + Vim + et + nanoc +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/output/n3blog/img/about/avatar.png b/output/n3blog/img/about/avatar.png new file mode 100644 index 000000000..3ce7c4e6f Binary files /dev/null and b/output/n3blog/img/about/avatar.png differ diff --git a/output/n3blog/img/about/cv/cv.png b/output/n3blog/img/about/cv/cv.png new file mode 100644 index 000000000..e202513dd Binary files /dev/null and b/output/n3blog/img/about/cv/cv.png differ diff --git a/output/n3blog/img/about/yann1.jpg b/output/n3blog/img/about/yann1.jpg new file mode 100644 index 000000000..62232c4ee Binary files /dev/null and b/output/n3blog/img/about/yann1.jpg differ diff --git a/output/n3blog/img/blog/03_losthighway/intro.jpg b/output/n3blog/img/blog/03_losthighway/intro.jpg new file mode 100644 index 000000000..1491f208a Binary files /dev/null and b/output/n3blog/img/blog/03_losthighway/intro.jpg differ diff --git a/output/n3blog/img/blog/03_losthighway/mysteryman.jpg b/output/n3blog/img/blog/03_losthighway/mysteryman.jpg new file mode 100644 index 000000000..1de2c35f7 Binary files /dev/null and b/output/n3blog/img/blog/03_losthighway/mysteryman.jpg differ diff --git a/output/n3blog/img/blog/03_losthighway/rorschach.gif b/output/n3blog/img/blog/03_losthighway/rorschach.gif new file mode 100644 index 000000000..331ad49d9 Binary files /dev/null and b/output/n3blog/img/blog/03_losthighway/rorschach.gif differ diff --git a/output/n3blog/img/blog/06_How_I_use_git/central_architecture.png b/output/n3blog/img/blog/06_How_I_use_git/central_architecture.png new file mode 100644 index 000000000..3def16e82 Binary files /dev/null and b/output/n3blog/img/blog/06_How_I_use_git/central_architecture.png differ diff --git a/output/n3blog/img/blog/07_Screensaver_compilation_option_for_Snow_Leopard/xcodeConfig.png b/output/n3blog/img/blog/07_Screensaver_compilation_option_for_Snow_Leopard/xcodeConfig.png new file mode 100644 index 000000000..12a1aab47 Binary files /dev/null and b/output/n3blog/img/blog/07_Screensaver_compilation_option_for_Snow_Leopard/xcodeConfig.png differ diff --git a/output/n3blog/img/blog/2010-03-23-Encapsulate-git/branch_hierarchy.png b/output/n3blog/img/blog/2010-03-23-Encapsulate-git/branch_hierarchy.png new file mode 100644 index 000000000..f018ae966 Binary files /dev/null and b/output/n3blog/img/blog/2010-03-23-Encapsulate-git/branch_hierarchy.png differ diff --git a/output/n3blog/img/blog/2010-03-23-Encapsulate-git/dynamic_branching.png b/output/n3blog/img/blog/2010-03-23-Encapsulate-git/dynamic_branching.png new file mode 100644 index 000000000..2ab981adc Binary files /dev/null and b/output/n3blog/img/blog/2010-03-23-Encapsulate-git/dynamic_branching.png differ diff --git a/output/n3blog/img/blog/2010-06-17-track-events-with-google-analytics/GA_events.png b/output/n3blog/img/blog/2010-06-17-track-events-with-google-analytics/GA_events.png new file mode 100644 index 000000000..552510330 Binary files /dev/null and b/output/n3blog/img/blog/2010-06-17-track-events-with-google-analytics/GA_events.png differ diff --git a/output/n3blog/img/blog/2010-07-09-Indecidabilities/3_corps.drawit/Data b/output/n3blog/img/blog/2010-07-09-Indecidabilities/3_corps.drawit/Data new file mode 100644 index 000000000..bfe316545 Binary files /dev/null and b/output/n3blog/img/blog/2010-07-09-Indecidabilities/3_corps.drawit/Data differ diff --git a/output/n3blog/img/blog/2010-07-09-Indecidabilities/3_corps.drawit/QuickLook/Preview.jpg b/output/n3blog/img/blog/2010-07-09-Indecidabilities/3_corps.drawit/QuickLook/Preview.jpg new file mode 100644 index 000000000..f30510f76 Binary files /dev/null and b/output/n3blog/img/blog/2010-07-09-Indecidabilities/3_corps.drawit/QuickLook/Preview.jpg differ diff --git a/output/n3blog/img/blog/2010-07-09-Indecidabilities/3_corps.drawit/QuickLook/Thumbnail.jpg b/output/n3blog/img/blog/2010-07-09-Indecidabilities/3_corps.drawit/QuickLook/Thumbnail.jpg new file mode 100644 index 000000000..f30510f76 Binary files /dev/null and b/output/n3blog/img/blog/2010-07-09-Indecidabilities/3_corps.drawit/QuickLook/Thumbnail.jpg differ diff --git a/output/n3blog/img/blog/2010-07-09-Indecidabilities/3_corps.png b/output/n3blog/img/blog/2010-07-09-Indecidabilities/3_corps.png new file mode 100644 index 000000000..423067fc8 Binary files /dev/null and b/output/n3blog/img/blog/2010-07-09-Indecidabilities/3_corps.png differ diff --git a/output/n3blog/img/blog/2010-07-09-Indecidabilities/controled_error.drawit/Data b/output/n3blog/img/blog/2010-07-09-Indecidabilities/controled_error.drawit/Data new file mode 100644 index 000000000..6f86addfa Binary files /dev/null and b/output/n3blog/img/blog/2010-07-09-Indecidabilities/controled_error.drawit/Data differ diff --git a/output/n3blog/img/blog/2010-07-09-Indecidabilities/controled_error.drawit/QuickLook/Preview.jpg b/output/n3blog/img/blog/2010-07-09-Indecidabilities/controled_error.drawit/QuickLook/Preview.jpg new file mode 100644 index 000000000..355c5315f Binary files /dev/null and b/output/n3blog/img/blog/2010-07-09-Indecidabilities/controled_error.drawit/QuickLook/Preview.jpg differ diff --git a/output/n3blog/img/blog/2010-07-09-Indecidabilities/controled_error.drawit/QuickLook/Thumbnail.jpg b/output/n3blog/img/blog/2010-07-09-Indecidabilities/controled_error.drawit/QuickLook/Thumbnail.jpg new file mode 100644 index 000000000..355c5315f Binary files /dev/null and b/output/n3blog/img/blog/2010-07-09-Indecidabilities/controled_error.drawit/QuickLook/Thumbnail.jpg differ diff --git a/output/n3blog/img/blog/2010-07-09-Indecidabilities/controled_error.png b/output/n3blog/img/blog/2010-07-09-Indecidabilities/controled_error.png new file mode 100644 index 000000000..e95f1619a Binary files /dev/null and b/output/n3blog/img/blog/2010-07-09-Indecidabilities/controled_error.png differ diff --git a/output/n3blog/img/blog/2010-07-09-Indecidabilities/genesis.drawit/Data b/output/n3blog/img/blog/2010-07-09-Indecidabilities/genesis.drawit/Data new file mode 100644 index 000000000..ce6cd9e11 Binary files /dev/null and b/output/n3blog/img/blog/2010-07-09-Indecidabilities/genesis.drawit/Data differ diff --git a/output/n3blog/img/blog/2010-07-09-Indecidabilities/genesis.drawit/QuickLook/Preview.jpg b/output/n3blog/img/blog/2010-07-09-Indecidabilities/genesis.drawit/QuickLook/Preview.jpg new file mode 100644 index 000000000..3d3355356 Binary files /dev/null and b/output/n3blog/img/blog/2010-07-09-Indecidabilities/genesis.drawit/QuickLook/Preview.jpg differ diff --git a/output/n3blog/img/blog/2010-07-09-Indecidabilities/genesis.drawit/QuickLook/Thumbnail.jpg b/output/n3blog/img/blog/2010-07-09-Indecidabilities/genesis.drawit/QuickLook/Thumbnail.jpg new file mode 100644 index 000000000..36ccbf3df Binary files /dev/null and b/output/n3blog/img/blog/2010-07-09-Indecidabilities/genesis.drawit/QuickLook/Thumbnail.jpg differ diff --git a/output/n3blog/img/blog/2010-07-09-Indecidabilities/genesis.png b/output/n3blog/img/blog/2010-07-09-Indecidabilities/genesis.png new file mode 100644 index 000000000..8c76b5ce5 Binary files /dev/null and b/output/n3blog/img/blog/2010-07-09-Indecidabilities/genesis.png differ diff --git a/output/n3blog/img/blog/2010-07-09-Indecidabilities/mandelbrot.drawit/Data b/output/n3blog/img/blog/2010-07-09-Indecidabilities/mandelbrot.drawit/Data new file mode 100644 index 000000000..ef5765d80 Binary files /dev/null and b/output/n3blog/img/blog/2010-07-09-Indecidabilities/mandelbrot.drawit/Data differ diff --git a/output/n3blog/img/blog/2010-07-09-Indecidabilities/mandelbrot.drawit/QuickLook/Preview.jpg b/output/n3blog/img/blog/2010-07-09-Indecidabilities/mandelbrot.drawit/QuickLook/Preview.jpg new file mode 100644 index 000000000..2e6392921 Binary files /dev/null and b/output/n3blog/img/blog/2010-07-09-Indecidabilities/mandelbrot.drawit/QuickLook/Preview.jpg differ diff --git a/output/n3blog/img/blog/2010-07-09-Indecidabilities/mandelbrot.drawit/QuickLook/Thumbnail.jpg b/output/n3blog/img/blog/2010-07-09-Indecidabilities/mandelbrot.drawit/QuickLook/Thumbnail.jpg new file mode 100644 index 000000000..0c295e0db Binary files /dev/null and b/output/n3blog/img/blog/2010-07-09-Indecidabilities/mandelbrot.drawit/QuickLook/Thumbnail.jpg differ diff --git a/output/n3blog/img/blog/2010-07-09-Indecidabilities/mandelbrot.png b/output/n3blog/img/blog/2010-07-09-Indecidabilities/mandelbrot.png new file mode 100644 index 000000000..a0f21c8e6 Binary files /dev/null and b/output/n3blog/img/blog/2010-07-09-Indecidabilities/mandelbrot.png differ diff --git a/output/n3blog/img/blog/2010-07-09-Indecidabilities/stackOverflow.drawit/Data b/output/n3blog/img/blog/2010-07-09-Indecidabilities/stackOverflow.drawit/Data new file mode 100644 index 000000000..1acf118a7 Binary files /dev/null and b/output/n3blog/img/blog/2010-07-09-Indecidabilities/stackOverflow.drawit/Data differ diff --git a/output/n3blog/img/blog/2010-07-09-Indecidabilities/stackOverflow.drawit/QuickLook/Preview.jpg b/output/n3blog/img/blog/2010-07-09-Indecidabilities/stackOverflow.drawit/QuickLook/Preview.jpg new file mode 100644 index 000000000..31bd451f0 Binary files /dev/null and b/output/n3blog/img/blog/2010-07-09-Indecidabilities/stackOverflow.drawit/QuickLook/Preview.jpg differ diff --git a/output/n3blog/img/blog/2010-07-09-Indecidabilities/stackOverflow.drawit/QuickLook/Thumbnail.jpg b/output/n3blog/img/blog/2010-07-09-Indecidabilities/stackOverflow.drawit/QuickLook/Thumbnail.jpg new file mode 100644 index 000000000..245857821 Binary files /dev/null and b/output/n3blog/img/blog/2010-07-09-Indecidabilities/stackOverflow.drawit/QuickLook/Thumbnail.jpg differ diff --git a/output/n3blog/img/blog/2010-07-09-Indecidabilities/stackOverflow.png b/output/n3blog/img/blog/2010-07-09-Indecidabilities/stackOverflow.png new file mode 100644 index 000000000..82e3180e4 Binary files /dev/null and b/output/n3blog/img/blog/2010-07-09-Indecidabilities/stackOverflow.png differ diff --git a/output/n3blog/img/blog/2010-07-09-Indecidabilities/triangle_3_angles.png b/output/n3blog/img/blog/2010-07-09-Indecidabilities/triangle_3_angles.png new file mode 100644 index 000000000..043c0eb1e Binary files /dev/null and b/output/n3blog/img/blog/2010-07-09-Indecidabilities/triangle_3_angles.png differ diff --git a/output/n3blog/img/blog/2010-07-09-Indecidabilities/triangle_on_sphere.drawit/Data b/output/n3blog/img/blog/2010-07-09-Indecidabilities/triangle_on_sphere.drawit/Data new file mode 100644 index 000000000..660193dcc Binary files /dev/null and b/output/n3blog/img/blog/2010-07-09-Indecidabilities/triangle_on_sphere.drawit/Data differ diff --git a/output/n3blog/img/blog/2010-07-09-Indecidabilities/triangle_on_sphere.drawit/QuickLook/Preview.jpg b/output/n3blog/img/blog/2010-07-09-Indecidabilities/triangle_on_sphere.drawit/QuickLook/Preview.jpg new file mode 100644 index 000000000..07b29cbb3 Binary files /dev/null and b/output/n3blog/img/blog/2010-07-09-Indecidabilities/triangle_on_sphere.drawit/QuickLook/Preview.jpg differ diff --git a/output/n3blog/img/blog/2010-07-09-Indecidabilities/triangle_on_sphere.drawit/QuickLook/Thumbnail.jpg b/output/n3blog/img/blog/2010-07-09-Indecidabilities/triangle_on_sphere.drawit/QuickLook/Thumbnail.jpg new file mode 100644 index 000000000..07b29cbb3 Binary files /dev/null and b/output/n3blog/img/blog/2010-07-09-Indecidabilities/triangle_on_sphere.drawit/QuickLook/Thumbnail.jpg differ diff --git a/output/n3blog/img/blog/2010-07-09-Indecidabilities/triangle_on_sphere.png b/output/n3blog/img/blog/2010-07-09-Indecidabilities/triangle_on_sphere.png new file mode 100644 index 000000000..3abbb7a3c Binary files /dev/null and b/output/n3blog/img/blog/2010-07-09-Indecidabilities/triangle_on_sphere.png differ diff --git a/output/n3blog/img/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/main.png b/output/n3blog/img/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/main.png new file mode 100644 index 000000000..d0833490c Binary files /dev/null and b/output/n3blog/img/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/main.png differ diff --git a/output/n3blog/img/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/sign_icon.png b/output/n3blog/img/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/sign_icon.png new file mode 100644 index 000000000..ac636c58f Binary files /dev/null and b/output/n3blog/img/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/sign_icon.png differ diff --git a/output/n3blog/img/blog/2011-01-03-Why-I-sadly-won-t-use-coffeescript/main.png b/output/n3blog/img/blog/2011-01-03-Why-I-sadly-won-t-use-coffeescript/main.png new file mode 100644 index 000000000..d11e42982 Binary files /dev/null and b/output/n3blog/img/blog/2011-01-03-Why-I-sadly-won-t-use-coffeescript/main.png differ diff --git a/output/n3blog/img/blog/mvc/Screenshot_v0.png b/output/n3blog/img/blog/mvc/Screenshot_v0.png new file mode 100644 index 000000000..c0fbab612 Binary files /dev/null and b/output/n3blog/img/blog/mvc/Screenshot_v0.png differ diff --git a/output/n3blog/img/bullet-feed.png b/output/n3blog/img/bullet-feed.png new file mode 100644 index 000000000..e6bac9a11 Binary files /dev/null and b/output/n3blog/img/bullet-feed.png differ diff --git a/output/n3blog/img/favicon.ico b/output/n3blog/img/favicon.ico new file mode 100644 index 000000000..933322aa4 Binary files /dev/null and b/output/n3blog/img/favicon.ico differ diff --git a/output/n3blog/img/loading.gif b/output/n3blog/img/loading.gif new file mode 100644 index 000000000..17ae831da Binary files /dev/null and b/output/n3blog/img/loading.gif differ diff --git a/output/n3blog/img/menu/rss-128.png b/output/n3blog/img/menu/rss-128.png new file mode 100644 index 000000000..c3f5af142 Binary files /dev/null and b/output/n3blog/img/menu/rss-128.png differ diff --git a/output/n3blog/img/menu/rss-32.png b/output/n3blog/img/menu/rss-32.png new file mode 100644 index 000000000..aba9519a6 Binary files /dev/null and b/output/n3blog/img/menu/rss-32.png differ diff --git a/output/n3blog/img/menu/rss-48.png b/output/n3blog/img/menu/rss-48.png new file mode 100644 index 000000000..855ccaa9d Binary files /dev/null and b/output/n3blog/img/menu/rss-48.png differ diff --git a/output/n3blog/img/menu/rss-64.png b/output/n3blog/img/menu/rss-64.png new file mode 100644 index 000000000..5fcebe7a0 Binary files /dev/null and b/output/n3blog/img/menu/rss-64.png differ diff --git a/output/n3blog/img/presentation.drawit/Data b/output/n3blog/img/presentation.drawit/Data new file mode 100644 index 000000000..117607d9b Binary files /dev/null and b/output/n3blog/img/presentation.drawit/Data differ diff --git a/output/n3blog/img/presentation.drawit/Info.plist b/output/n3blog/img/presentation.drawit/Info.plist new file mode 100644 index 000000000..6e899a643 --- /dev/null +++ b/output/n3blog/img/presentation.drawit/Info.plist @@ -0,0 +1,8 @@ + + + + + fileVersion + 2 + + diff --git a/output/n3blog/img/presentation.drawit/QuickLook/Preview.jpg b/output/n3blog/img/presentation.drawit/QuickLook/Preview.jpg new file mode 100644 index 000000000..15890c95d Binary files /dev/null and b/output/n3blog/img/presentation.drawit/QuickLook/Preview.jpg differ diff --git a/output/n3blog/img/presentation.drawit/QuickLook/Thumbnail.jpg b/output/n3blog/img/presentation.drawit/QuickLook/Thumbnail.jpg new file mode 100644 index 000000000..69869d1dc Binary files /dev/null and b/output/n3blog/img/presentation.drawit/QuickLook/Thumbnail.jpg differ diff --git a/output/n3blog/img/presentation.png b/output/n3blog/img/presentation.png new file mode 100644 index 000000000..fa0a8bbef Binary files /dev/null and b/output/n3blog/img/presentation.png differ diff --git a/output/n3blog/img/softwares/yaquabubbles/screenshot1.png b/output/n3blog/img/softwares/yaquabubbles/screenshot1.png new file mode 100644 index 000000000..bd587d9a7 Binary files /dev/null and b/output/n3blog/img/softwares/yaquabubbles/screenshot1.png differ diff --git a/output/n3blog/img/softwares/yclock/screenshot1.png b/output/n3blog/img/softwares/yclock/screenshot1.png new file mode 100644 index 000000000..908288db7 Binary files /dev/null and b/output/n3blog/img/softwares/yclock/screenshot1.png differ diff --git a/output/n3blog/js/become_hidden.html b/output/n3blog/js/become_hidden.html new file mode 100644 index 000000000..b619c6b3b --- /dev/null +++ b/output/n3blog/js/become_hidden.html @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + Hide to analytics + + +
+
+

+ Hide to Analytics +

+
+
+
+
+
+
+
+
+
+ + diff --git a/output/n3blog/js/become_visible.html b/output/n3blog/js/become_visible.html new file mode 100644 index 000000000..b21f53fb4 --- /dev/null +++ b/output/n3blog/js/become_visible.html @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + Be visible to analytics + + +
+
+

+ Be visible to Analytics +

+
+
+
+
+
+
+
+
+
+ + diff --git a/output/n3blog/js/genericCommentWrapperV2.js b/output/n3blog/js/genericCommentWrapperV2.js new file mode 100644 index 000000000..bfe5f870f --- /dev/null +++ b/output/n3blog/js/genericCommentWrapperV2.js @@ -0,0 +1,23 @@ +if(document.getElementById("IDCommentsPostTitle") && document.getElementById("IDCommentsPostTitle").innerHTML.length>0) + idcomments_post_title = document.getElementById("IDCommentsPostTitle").innerHTML; +else + idcomments_post_title = document.title; +if(idcomments_post_title.length==0) + idcomments_post_title = "Post"; + +idcomments_post_title = idcomments_post_title.replace(/#/, "%23"); + +if(null==idcomments_post_url || idcomments_post_url==='') + idcomments_post_url = window.location.href; +if(null==idcomments_post_id) + idcomments_post_id = window.location.href; +idcomments_post_id = encodeURIComponent(idcomments_post_id); +idcomments_post_url = encodeURIComponent(idcomments_post_url); +idcomments_post_title = encodeURIComponent(idcomments_post_title); +var commentScript = document.createElement("script"); +commentScript.type = "text/javascript"; +commentScript.src = "http://intensedebate.com/js/genericCommentWrapper2.php?acct="+idcomments_acct+"&postid="+idcomments_post_id+"&title="+idcomments_post_title+"&url="+idcomments_post_url; + +$(document).ready( function() { + document.getElementsByTagName("head")[0].appendChild(commentScript); +}); diff --git a/output/n3blog/js/index.js b/output/n3blog/js/index.js new file mode 100644 index 000000000..40c80a77e --- /dev/null +++ b/output/n3blog/js/index.js @@ -0,0 +1,105 @@ +// --- code popin handling --- +function openWide() { + $(this).clone(false).appendTo($("#_code")); + $('#_code a').css({"margin-right":"3em"}); + $("#_code").show(); +} + +function returnToNormal() { + $("#_code").html(""); + $("#_code").hide(); +} + +function initCode() { + if ( ! /ip(od|hone)/.test(userAgent) ) { + $(".code").click(openWide); + $(".code").css({cursor: "pointer"}); + $('body').append('
'); + $('#_code').css( { 'font-size':$('.corps:first').css('font-size'), 'text-align': "justify", position: "fixed", left:0, top:0, width: "100%", height: "100%", "background-color": "rgba(0, 0, 0, 0.8)", 'z-index':2000, 'padding':'3px'} ); + $('#_code').hide(); + $('#_code').click(returnToNormal); + } +} +// --- end of popin code --- + +// --- Google analytics --- +function analytics() { + var admin = $.cookie('admin'); + if (! admin) { + // console.log("you're logged by google analytics"); + // add an event to all link for google analytics + $('a').click(function () { + // tell analytics to save event + try { + var identifier=$(this).attr('id') ; + var href=$(this).attr('href') + var label=""; + if ( typeof( identifier ) != 'undefined' ) { + label=label+'[id]:'+identifier + category='JSLink' + } + if ( typeof( href ) != 'undefined' ) { + label=label+' [href]:'+href + if ( href[0] == '#' ) { + category='Anchor'; + } else { + category='Link'; + } + } + _gaq.push(['_trackEvent', category, 'clicked', label]); + // console.log('[tracked]: ' + category + ' ; clicked ; ' + label ); + } + catch (err) { + console.log(err); + } + + // pause to allow google script to run + var date = new Date(); + var curDate = null; + do { + curDate = new Date(); + } while(curDate-date < 300); + }); + } else { + console.log("[WARNING] you're HIDDEN to analytics"); + } +} + +var userAgent; + +function detectClient() { + userAgent = navigator.userAgent.toLowerCase(); + if (/msie/.test(userAgent) ) { + $('body').prepend('

Avec Firefox et Safari cette page est bien plus jolie !
This page is far nicer with Firefox and Safari!

'); + } else if (/ip(od|hone)/.test(userAgent)) { + $('head').append(''); + $('head').append(''); + } + return userAgent +} + +// Ce que l'on va lancer à l'init. +$(document).ready( function() { + var client=detectClient(); + if ( ! /msie/.test(client) ) { + initCode(); + } + $('#blackpage').fadeOut(); + analytics(); +}); + +// --- Google Analytics --- +if ( ! $.cookie('admin') ) { + var _gaq = _gaq || []; + _gaq.push(['_setAccount', 'UA-10612400-1']); + _gaq.push(['_trackPageview']); + + (function() { + var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; + ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; + var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); + })(); +} else { + console.log("[WARNING] you're HIDDEN to analytics"); +} + diff --git a/output/n3blog/js/jquery-1.3.1.min.js b/output/n3blog/js/jquery-1.3.1.min.js new file mode 100644 index 000000000..c327fae81 --- /dev/null +++ b/output/n3blog/js/jquery-1.3.1.min.js @@ -0,0 +1,19 @@ +/* + * jQuery JavaScript Library v1.3.1 + * http://jquery.com/ + * + * Copyright (c) 2009 John Resig + * Dual licensed under the MIT and GPL licenses. + * http://docs.jquery.com/License + * + * Date: 2009-01-21 20:42:16 -0500 (Wed, 21 Jan 2009) + * Revision: 6158 + */ +(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.makeArray(E))},selector:"",jquery:"1.3.1",size:function(){return this.length},get:function(E){return E===g?o.makeArray(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,find:function(E){if(this.length===1&&!/,/.test(E)){var G=this.pushStack([],"find",E);G.length=0;o.find(E,this[0],G);return G}else{var F=o.map(this,function(H){return o.find(E,H)});return this.pushStack(/[^+>] [^+>]/.test(E)?o.unique(F):F,"find",E)}},clone:function(F){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.cloneNode(true),H=document.createElement("div");H.appendChild(I);return o.clean([H.innerHTML])[0]}else{return this.cloneNode(true)}});var G=E.find("*").andSelf().each(function(){if(this[h]!==g){this[h]=null}});if(F===true){this.find("*").andSelf().each(function(I){if(this.nodeType==3){return}var H=o.data(this,"events");for(var K in H){for(var J in H[K]){o.event.add(G[I],K,H[K][J],H[K][J].data)}}})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var F=o.expr.match.POS.test(E)?o(E):null;return this.map(function(){var G=this;while(G&&G.ownerDocument){if(F?F.index(G)>-1:o(G).is(E)){return G}G=G.parentNode}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML:null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(K,N,M){if(this[0]){var J=(this[0].ownerDocument||this[0]).createDocumentFragment(),G=o.clean(K,(this[0].ownerDocument||this[0]),J),I=J.firstChild,E=this.length>1?J.cloneNode(true):J;if(I){for(var H=0,F=this.length;H0?E.cloneNode(true):J)}}if(G){o.each(G,z)}}return this;function L(O,P){return N&&o.nodeName(O,"table")&&o.nodeName(P,"tr")?(O.getElementsByTagName("tbody")[0]||O.appendChild(O.ownerDocument.createElement("tbody"))):O}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(G,E,I){if(E=="width"||E=="height"){var K,F={position:"absolute",visibility:"hidden",display:"block"},J=E=="width"?["Left","Right"]:["Top","Bottom"];function H(){K=E=="width"?G.offsetWidth:G.offsetHeight;var M=0,L=0;o.each(J,function(){M+=parseFloat(o.curCSS(G,"padding"+this,true))||0;L+=parseFloat(o.curCSS(G,"border"+this+"Width",true))||0});K-=Math.round(M+L)}if(o(G).is(":visible")){H()}else{o.swap(G,F,H)}return Math.max(0,K)}return o.curCSS(G,E,I)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,R){if(typeof R==="number"){R+=""}if(!R){return}if(typeof R==="string"){R=R.replace(/(<(\w+)[^>]*?)\/>/g,function(T,U,S){return S.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?T:U+">"});var O=o.trim(R).toLowerCase();var Q=!O.indexOf("",""]||!O.indexOf("",""]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
"]||!O.indexOf("",""]||(!O.indexOf("",""]||!O.indexOf("",""]||!o.support.htmlSerialize&&[1,"div
","
"]||[0,"",""];L.innerHTML=Q[1]+R+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var N=!O.indexOf(""&&O.indexOf("=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(R)){L.insertBefore(K.createTextNode(R.match(/^\s*/)[0]),L.firstChild)}R=o.makeArray(L.childNodes)}if(R.nodeType){G.push(R)}else{G=o.merge(G,R)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E*",this).remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}}); +/* + * Sizzle CSS Selector Engine - v0.9.3 + * Copyright 2009, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){var Q=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]+['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[]+)+|[>+~])(\s*,\s*)?/g,K=0,G=Object.prototype.toString;var F=function(X,T,aa,ab){aa=aa||[];T=T||document;if(T.nodeType!==1&&T.nodeType!==9){return[]}if(!X||typeof X!=="string"){return aa}var Y=[],V,ae,ah,S,ac,U,W=true;Q.lastIndex=0;while((V=Q.exec(X))!==null){Y.push(V[1]);if(V[2]){U=RegExp.rightContext;break}}if(Y.length>1&&L.exec(X)){if(Y.length===2&&H.relative[Y[0]]){ae=I(Y[0]+Y[1],T)}else{ae=H.relative[Y[0]]?[T]:F(Y.shift(),T);while(Y.length){X=Y.shift();if(H.relative[X]){X+=Y.shift()}ae=I(X,ae)}}}else{var ad=ab?{expr:Y.pop(),set:E(ab)}:F.find(Y.pop(),Y.length===1&&T.parentNode?T.parentNode:T,P(T));ae=F.filter(ad.expr,ad.set);if(Y.length>0){ah=E(ae)}else{W=false}while(Y.length){var ag=Y.pop(),af=ag;if(!H.relative[ag]){ag=""}else{af=Y.pop()}if(af==null){af=T}H.relative[ag](ah,af,P(T))}}if(!ah){ah=ae}if(!ah){throw"Syntax error, unrecognized expression: "+(ag||X)}if(G.call(ah)==="[object Array]"){if(!W){aa.push.apply(aa,ah)}else{if(T.nodeType===1){for(var Z=0;ah[Z]!=null;Z++){if(ah[Z]&&(ah[Z]===true||ah[Z].nodeType===1&&J(T,ah[Z]))){aa.push(ae[Z])}}}else{for(var Z=0;ah[Z]!=null;Z++){if(ah[Z]&&ah[Z].nodeType===1){aa.push(ae[Z])}}}}}else{E(ah,aa)}if(U){F(U,T,aa,ab)}return aa};F.matches=function(S,T){return F(S,null,null,T)};F.find=function(Z,S,aa){var Y,W;if(!Z){return[]}for(var V=0,U=H.order.length;V":function(X,T,Y){if(typeof T==="string"&&!/\W/.test(T)){T=Y?T:T.toUpperCase();for(var U=0,S=X.length;U=0){if(!U){S.push(X)}}else{if(U){T[W]=false}}}}return false},ID:function(S){return S[1].replace(/\\/g,"")},TAG:function(T,S){for(var U=0;S[U]===false;U++){}return S[U]&&P(S[U])?T[1]:T[1].toUpperCase()},CHILD:function(S){if(S[1]=="nth"){var T=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(S[2]=="even"&&"2n"||S[2]=="odd"&&"2n+1"||!/\D/.test(S[2])&&"0n+"+S[2]||S[2]);S[2]=(T[1]+(T[2]||1))-0;S[3]=T[3]-0}S[0]="done"+(K++);return S},ATTR:function(T){var S=T[1].replace(/\\/g,"");if(H.attrMap[S]){T[1]=H.attrMap[S]}if(T[2]==="~="){T[4]=" "+T[4]+" "}return T},PSEUDO:function(W,T,U,S,X){if(W[1]==="not"){if(W[3].match(Q).length>1){W[3]=F(W[3],null,null,T)}else{var V=F.filter(W[3],T,U,true^X);if(!U){S.push.apply(S,V)}return false}}else{if(H.match.POS.test(W[0])){return true}}return W},POS:function(S){S.unshift(true);return S}},filters:{enabled:function(S){return S.disabled===false&&S.type!=="hidden"},disabled:function(S){return S.disabled===true},checked:function(S){return S.checked===true},selected:function(S){S.parentNode.selectedIndex;return S.selected===true},parent:function(S){return !!S.firstChild},empty:function(S){return !S.firstChild},has:function(U,T,S){return !!F(S[3],U).length},header:function(S){return/h\d/i.test(S.nodeName)},text:function(S){return"text"===S.type},radio:function(S){return"radio"===S.type},checkbox:function(S){return"checkbox"===S.type},file:function(S){return"file"===S.type},password:function(S){return"password"===S.type},submit:function(S){return"submit"===S.type},image:function(S){return"image"===S.type},reset:function(S){return"reset"===S.type},button:function(S){return"button"===S.type||S.nodeName.toUpperCase()==="BUTTON"},input:function(S){return/input|select|textarea|button/i.test(S.nodeName)}},setFilters:{first:function(T,S){return S===0},last:function(U,T,S,V){return T===V.length-1},even:function(T,S){return S%2===0},odd:function(T,S){return S%2===1},lt:function(U,T,S){return TS[3]-0},nth:function(U,T,S){return S[3]-0==T},eq:function(U,T,S){return S[3]-0==T}},filter:{CHILD:function(S,V){var Y=V[1],Z=S.parentNode;var X=V[0];if(Z&&(!Z[X]||!S.nodeIndex)){var W=1;for(var T=Z.firstChild;T;T=T.nextSibling){if(T.nodeType==1){T.nodeIndex=W++}}Z[X]=W-1}if(Y=="first"){return S.nodeIndex==1}else{if(Y=="last"){return S.nodeIndex==Z[X]}else{if(Y=="only"){return Z[X]==1}else{if(Y=="nth"){var ab=false,U=V[2],aa=V[3];if(U==1&&aa==0){return true}if(U==0){if(S.nodeIndex==aa){ab=true}}else{if((S.nodeIndex-aa)%U==0&&(S.nodeIndex-aa)/U>=0){ab=true}}return ab}}}}},PSEUDO:function(Y,U,V,Z){var T=U[1],W=H.filters[T];if(W){return W(Y,V,U,Z)}else{if(T==="contains"){return(Y.textContent||Y.innerText||"").indexOf(U[3])>=0}else{if(T==="not"){var X=U[3];for(var V=0,S=X.length;V=0:V==="~="?(" "+X+" ").indexOf(T)>=0:!U[4]?S:V==="!="?X!=T:V==="^="?X.indexOf(T)===0:V==="$="?X.substr(X.length-T.length)===T:V==="|="?X===T||X.substr(0,T.length+1)===T+"-":false},POS:function(W,T,U,X){var S=T[2],V=H.setFilters[S];if(V){return V(W,U,T,X)}}}};var L=H.match.POS;for(var N in H.match){H.match[N]=RegExp(H.match[N].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(T,S){T=Array.prototype.slice.call(T);if(S){S.push.apply(S,T);return S}return T};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(M){E=function(W,V){var T=V||[];if(G.call(W)==="[object Array]"){Array.prototype.push.apply(T,W)}else{if(typeof W.length==="number"){for(var U=0,S=W.length;U";var S=document.documentElement;S.insertBefore(T,S.firstChild);if(!!document.getElementById(U)){H.find.ID=function(W,X,Y){if(typeof X.getElementById!=="undefined"&&!Y){var V=X.getElementById(W[1]);return V?V.id===W[1]||typeof V.getAttributeNode!=="undefined"&&V.getAttributeNode("id").nodeValue===W[1]?[V]:g:[]}};H.filter.ID=function(X,V){var W=typeof X.getAttributeNode!=="undefined"&&X.getAttributeNode("id");return X.nodeType===1&&W&&W.nodeValue===V}}S.removeChild(T)})();(function(){var S=document.createElement("div");S.appendChild(document.createComment(""));if(S.getElementsByTagName("*").length>0){H.find.TAG=function(T,X){var W=X.getElementsByTagName(T[1]);if(T[1]==="*"){var V=[];for(var U=0;W[U];U++){if(W[U].nodeType===1){V.push(W[U])}}W=V}return W}}S.innerHTML="";if(S.firstChild&&S.firstChild.getAttribute("href")!=="#"){H.attrHandle.href=function(T){return T.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var S=F,T=document.createElement("div");T.innerHTML="

";if(T.querySelectorAll&&T.querySelectorAll(".TEST").length===0){return}F=function(X,W,U,V){W=W||document;if(!V&&W.nodeType===9&&!P(W)){try{return E(W.querySelectorAll(X),U)}catch(Y){}}return S(X,W,U,V)};F.find=S.find;F.filter=S.filter;F.selectors=S.selectors;F.matches=S.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){H.order.splice(1,0,"CLASS");H.find.CLASS=function(S,T){return T.getElementsByClassName(S[1])}}function O(T,Z,Y,ac,aa,ab){for(var W=0,U=ac.length;W0){W=S;break}}}S=S[T]}ab[V]=W}}}var J=document.compareDocumentPosition?function(T,S){return T.compareDocumentPosition(S)&16}:function(T,S){return T!==S&&(T.contains?T.contains(S):true)};var P=function(S){return S.nodeType===9&&S.documentElement.nodeName!=="HTML"||!!S.ownerDocument&&P(S.ownerDocument)};var I=function(S,Z){var V=[],W="",X,U=Z.nodeType?[Z]:Z;while((X=H.match.PSEUDO.exec(S))){W+=X[0];S=S.replace(H.match.PSEUDO,"")}S=H.relative[S]?S+"*":S;for(var Y=0,T=U.length;Y=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("
").append(M.responseText.replace(//g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}this[H].style.display=o.data(this[H],"olddisplay",K)}}return this}},hide:function(H,I){if(H){return this.animate(t("hide",3),H,I)}else{for(var G=0,F=this.length;G=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)==1){n=setInterval(function(){var K=o.timers;for(var J=0;J=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='
';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(H,F){var E=H?"Left":"Top",G=H?"Right":"Bottom";o.fn["inner"+F]=function(){return this[F.toLowerCase()]()+j(this,"padding"+E)+j(this,"padding"+G)};o.fn["outer"+F]=function(J){return this["inner"+F]()+j(this,"border"+E+"Width")+j(this,"border"+G+"Width")+(J?j(this,"margin"+E)+j(this,"margin"+G):0)};var I=F.toLowerCase();o.fn[I]=function(J){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+F]||document.body["client"+F]:this[0]==document?Math.max(document.documentElement["client"+F],document.body["scroll"+F],document.documentElement["scroll"+F],document.body["offset"+F],document.documentElement["offset"+F]):J===g?(this.length?o.css(this[0],I):null):this.css(I,typeof J==="string"?J:J+"px")}})})(); \ No newline at end of file diff --git a/output/n3blog/js/jquery.cookie.js b/output/n3blog/js/jquery.cookie.js new file mode 100644 index 000000000..a80bfa29d --- /dev/null +++ b/output/n3blog/js/jquery.cookie.js @@ -0,0 +1,97 @@ +/** + * Cookie plugin + * + * Copyright (c) 2006 Klaus Hartl (stilbuero.de) + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + */ + +/** + * Create a cookie with the given name and value and other optional parameters. + * + * @example $.cookie('the_cookie', 'the_value'); + * @desc Set the value of a cookie. + * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true }); + * @desc Create a cookie with all available options. + * @example $.cookie('the_cookie', 'the_value'); + * @desc Create a session cookie. + * @example $.cookie('the_cookie', null); + * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain + * used when the cookie was set. + * + * @param String name The name of the cookie. + * @param String value The value of the cookie. + * @param Object options An object literal containing key/value pairs to provide optional cookie attributes. + * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object. + * If a negative value is specified (e.g. a date in the past), the cookie will be deleted. + * If set to null or omitted, the cookie will be a session cookie and will not be retained + * when the the browser exits. + * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie). + * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie). + * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will + * require a secure protocol (like HTTPS). + * @type undefined + * + * @name $.cookie + * @cat Plugins/Cookie + * @author Klaus Hartl/klaus.hartl@stilbuero.de + */ + +/** + * Get the value of a cookie with the given name. + * + * @example $.cookie('the_cookie'); + * @desc Get the value of a cookie. + * + * @param String name The name of the cookie. + * @return The value of the cookie. + * @type String + * + * @name $.cookie + * @cat Plugins/Cookie + * @author Klaus Hartl/klaus.hartl@stilbuero.de + */ +jQuery.cookie = function(name, value, options) { + if (typeof value != 'undefined') { // name and value given, set cookie + options = options || {}; + if (value === null) { + value = ''; + options = $.extend({}, options); // clone object since it's unexpected behavior if the expired property were changed + options.expires = -1; + } + var expires = ''; + if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) { + var date; + if (typeof options.expires == 'number') { + date = new Date(); + date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000)); + } else { + date = options.expires; + } + expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE + } + // NOTE Needed to parenthesize options.path and options.domain + // in the following expressions, otherwise they evaluate to undefined + // in the packed version for some reason... + var path = options.path ? '; path=' + (options.path) : ''; + var domain = options.domain ? '; domain=' + (options.domain) : ''; + var secure = options.secure ? '; secure' : ''; + document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join(''); + } else { // only name given, get cookie + var cookieValue = null; + if (document.cookie && document.cookie != '') { + var cookies = document.cookie.split(';'); + for (var i = 0; i < cookies.length; i++) { + var cookie = jQuery.trim(cookies[i]); + // Does this cookie string begin with the name we want? + if (cookie.substring(0, name.length + 1) == (name + '=')) { + cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); + break; + } + } + } + return cookieValue; + } +}; \ No newline at end of file diff --git a/output/n3blog/sitemap.xml b/output/n3blog/sitemap.xml new file mode 100644 index 000000000..f518e11ed --- /dev/null +++ b/output/n3blog/sitemap.xml @@ -0,0 +1,492 @@ + + + + http://yannesposito.com/ + + + http://yannesposito.com/n3blog/en/about/contact/ + + + http://yannesposito.com/n3blog/fr/blog/2010-06-17-track-events-with-google-analytics/ + + + http://yannesposito.com/n3blog/en/blog/2010-01-04-Change-default-shell-on-Mac-OS-X/ + + + http://yannesposito.com/n3blog/fr/blog/2010-06-19-jQuery-popup-the-easy-way/ + + + http://yannesposito.com/n3blog/en/softwares/ypassword/ + + + http://yannesposito.com/n3blog/fr/about/ + + + http://yannesposito.com/n3blog/fr/blog/2011-01-03-Why-I-sadly-won-t-use-coffeescript/ + + + http://yannesposito.com/n3blog/fr/blog/2009-09-jQuery-Tag-Cloud/ + + + http://yannesposito.com/n3blog/en/blog/2010-05-19-How-to-cut-HTML-and-repair-it/ + + + http://yannesposito.com/n3blog/en/blog/2010-05-24-Trees--Pragmatism-and-Formalism/ + + + http://yannesposito.com/n3blog/en/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/ + + + http://yannesposito.com/n3blog/fr/blog/2010-10-26-LaTeX-like-macro-and-markdown/ + + + http://yannesposito.com/n3blog/en/softwares/ypassword/iphoneweb/ + + + http://yannesposito.com/n3blog/fr/blog/2010-09-02-base64-and-sha1-on-iPhone/ + + + http://yannesposito.com/n3blog/fr/blog/2010-10-06-New-Blog-Design-Constraints/ + + + http://yannesposito.com/n3blog/en/blog/2010-02-18-split-a-file-by-keyword/ + + + http://yannesposito.com/n3blog/en/blog/2010-06-17-hide-yourself-to-analytics/ + + + http://yannesposito.com/n3blog/fr/blog/2009-11-12-Git-for-n00b/commandes-avancees/ + + + http://yannesposito.com/n3blog/en/blog/03_losthighway/03_losthighway_1/ + + + http://yannesposito.com/n3blog/en/blog/mvc/ + + + http://yannesposito.com/n3blog/fr/blog/2009-09-replace-all-except-some-part/ + + + http://yannesposito.com/n3blog/fr/blog/09_Why_I_didn-t_keep_whosamung-us/ + + + http://yannesposito.com/n3blog/fr/blog/2010-02-18-split-a-file-by-keyword/ + + + http://yannesposito.com/n3blog/en/blog/03_losthighway/03_losthighway_2/ + + + http://yannesposito.com/n3blog/en/softwares/yaquabubbles/ + + + http://yannesposito.com/n3blog/en/blog/2009-11-12-Git-for-n00b/commandes-avancees/ + + + http://yannesposito.com/n3blog/en/blog/2009-10-Focus-vs-Minimalism/ + + + http://yannesposito.com/n3blog/en/blog/03_losthighway/03_losthighway_3/ + + + http://yannesposito.com/n3blog/en/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/ + + + http://yannesposito.com/n3blog/en/blog/2010-03-22-Git-Tips/ + + + http://yannesposito.com/n3blog/en/blog/2010-06-19-jQuery-popup-the-easy-way/ + + + http://yannesposito.com/n3blog/fr/blog/2010-07-09-Indecidabilities/ + + + http://yannesposito.com/n3blog/en/blog/03_losthighway/03_losthighway_4/ + + + http://yannesposito.com/n3blog/en/blog/ + + + http://yannesposito.com/n3blog/fr/blog/01_nanoc/ + + + http://yannesposito.com/n3blog/fr/blog/2010-07-05-Cappuccino-and-Web-applications/ + + + http://yannesposito.com/n3blog/en/blog/2009-12-06-iphone-call-filter/ + + + http://yannesposito.com/n3blog/fr/blog/03_losthighway/03_losthighway_1/ + + + http://yannesposito.com/n3blog/fr/blog/11_Load_Disqus_Asynchronously/ + + + http://yannesposito.com/n3blog/en/blog/2010-02-15-All-but-something-regexp/ + + + http://yannesposito.com/n3blog/en/blog/2010-07-05-Cappuccino-and-Web-applications/ + + + http://yannesposito.com/n3blog/en/softwares/ypassword/web/ + + + http://yannesposito.com/n3blog/fr/blog/05_git_create_remote_branch/ + + + http://yannesposito.com/n3blog/en/blog/2009-10-untaught-git-usage/ + + + http://yannesposito.com/n3blog/en/blog/11_Load_Disqus_Asynchronously/ + + + http://yannesposito.com/n3blog/en/blog/2010-10-26-LaTeX-like-macro-and-markdown/ + + + http://yannesposito.com/n3blog/fr/about/cv/ + + + http://yannesposito.com/n3blog/fr/about/technical_details/ + + + http://yannesposito.com/n3blog/fr/blog/03_losthighway/03_losthighway_2/ + + + http://yannesposito.com/n3blog/fr/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes/ + + + http://yannesposito.com/n3blog/en/blog/2010-07-07-CSS-rendering-problems-by-navigator/ + + + http://yannesposito.com/n3blog/en/blog/2010-06-15-Get-my-blog-engine/ + + + http://yannesposito.com/n3blog/fr/blog/mvc/ + + + http://yannesposito.com/n3blog/fr/blog/03_losthighway/03_losthighway_3/ + + + http://yannesposito.com/n3blog/en/validation/ + + + http://yannesposito.com/n3blog/fr/blog/03_losthighway/03_losthighway_4/ + + + http://yannesposito.com/n3blog/fr/blog/2009-10-untaught-git-usage/ + + + http://yannesposito.com/n3blog/en/blog/08_Configure_ssh_to_listen_the_port_443_on_Snow_Leopard/ + + + http://yannesposito.com/n3blog/en/softwares/yclock/ + + + http://yannesposito.com/n3blog/en/blog/2009-10-How-to-preload-your-site-with-style/ + + + http://yannesposito.com/n3blog/en/blog/2011-01-03-Happy-New-Year/ + + + http://yannesposito.com/n3blog/fr/about/old/ + + + http://yannesposito.com/n3blog/fr/blog/2010-05-17-at-least-this-blog-revive/ + + + http://yannesposito.com/n3blog/fr/blog/02_ackgrep/ + + + http://yannesposito.com/n3blog/en/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes/ + + + http://yannesposito.com/n3blog/en/blog/03_losthighway/ + + + http://yannesposito.com/n3blog/en/blog/2010-08-31-send-mail-from-command-line-with-attached-file/ + + + http://yannesposito.com/n3blog/en/blog/2009-09-Disqus-versus-Intense-Debate--Why-I-switched-/ + + + http://yannesposito.com/n3blog/fr/about/contact/ + + + http://yannesposito.com/n3blog/fr/blog/2009-10-How-to-preload-your-site-with-style/ + + + http://yannesposito.com/n3blog/fr/blog/2009-10-Focus-vs-Minimalism/ + + + http://yannesposito.com/n3blog/fr/blog/2010-07-07-CSS-rendering-problems-by-navigator/ + + + http://yannesposito.com/n3blog/en/blog/07_Screensaver_compilation_option_for_Snow_Leopard/ + + + http://yannesposito.com/n3blog/en/blog/2010-07-31-New-style-after-holidays/ + + + http://yannesposito.com/n3blog/fr/blog/2009-12-06-iphone-call-filter/ + + + http://yannesposito.com/n3blog/fr/blog/2010-02-23-When-regexp-is-not-the-best-solution/ + + + http://yannesposito.com/n3blog/en/blog/2009-10-30-How-to-handle-evil-IE/ + + + http://yannesposito.com/n3blog/en/blog/2010-09-02-base64-and-sha1-on-iPhone/ + + + http://yannesposito.com/n3blog/fr/blog/2009-10-Wait-to-hide-a-menu-in-jQuery/ + + + http://yannesposito.com/n3blog/fr/blog/07_Screensaver_compilation_option_for_Snow_Leopard/ + + + http://yannesposito.com/n3blog/fr/softwares/ + + + http://yannesposito.com/n3blog/en/blog/02_ackgrep/ + + + http://yannesposito.com/n3blog/fr/blog/2010-10-14-Fun-with-wav/ + + + http://yannesposito.com/n3blog/fr/blog/08_Configure_ssh_to_listen_the_port_443_on_Snow_Leopard/ + + + http://yannesposito.com/n3blog/fr/blog/06_How_I_use_git/ + + + http://yannesposito.com/n3blog/en/blog/2009-09-replace-all-except-some-part/ + + + http://yannesposito.com/n3blog/fr/blog/10_Synchronize_Custom_WebSite_with_mobileMe/ + + + http://yannesposito.com/n3blog/fr/blog/2010-02-15-All-but-something-regexp/ + + + http://yannesposito.com/n3blog/en/about/old/ + + + http://yannesposito.com/n3blog/en/about/cv/ + + + http://yannesposito.com/n3blog/fr/softwares/ypassword/ + + + http://yannesposito.com/n3blog/en/blog/09_Why_I_didn-t_keep_whosamung-us/ + + + http://yannesposito.com/n3blog/fr/blog/feed/feed.xml + + + http://yannesposito.com/n3blog/fr/validation/ + + + http://yannesposito.com/n3blog/fr/blog/2010-08-23-Now-heberged-on-heroku/ + + + http://yannesposito.com/n3blog/en/blog/2010-10-14-Fun-with-wav/ + + + http://yannesposito.com/n3blog/fr/blog/2010-06-14-multi-language-choices/ + + + http://yannesposito.com/n3blog/fr/blog/2009-09-Disqus-versus-Intense-Debate--Why-I-switched-/ + + + http://yannesposito.com/n3blog/fr/blog/2009-11-12-Git-for-n00b/Git-pour-quoi-faire/ + + + http://yannesposito.com/n3blog/fr/blog/2011-01-03-Happy-New-Year/ + + + http://yannesposito.com/n3blog/fr/blog/2010-08-31-send-mail-from-command-line-with-attached-file/ + + + http://yannesposito.com/n3blog/en/blog/10_Synchronize_Custom_WebSite_with_mobileMe/ + + + http://yannesposito.com/n3blog/en/blog/2010-02-16-All-but-something-regexp--2-/ + + + http://yannesposito.com/n3blog/fr/blog/2010-07-31-New-style-after-holidays/ + + + http://yannesposito.com/n3blog/fr/softwares/yaquabubbles/ + + + http://yannesposito.com/n3blog/fr/blog/2009-12-14-Git-vs--Bzr/ + + + http://yannesposito.com/n3blog/en/blog/06_How_I_use_git/ + + + http://yannesposito.com/n3blog/fr/blog/03_losthighway/ + + + http://yannesposito.com/n3blog/en/blog/2009-11-12-Git-for-n00b/comprendre/ + + + http://yannesposito.com/n3blog/en/rss/ + + + http://yannesposito.com/n3blog/en/blog/2009-09-jQuery-Tag-Cloud/ + + + http://yannesposito.com/n3blog/en/blog/2009-11-12-Git-for-n00b/conf-et-install/ + + + http://yannesposito.com/n3blog/en/blog/2009-10-launch-daemon-from-command-line/ + + + http://yannesposito.com/n3blog/en/blog/2010-03-23-Encapsulate-git/ + + + http://yannesposito.com/n3blog/fr/blog/2010-06-15-Get-my-blog-engine/ + + + http://yannesposito.com/n3blog/fr/blog/2010-03-22-Git-Tips/ + + + http://yannesposito.com/n3blog/en/blog/2009-11-12-Git-for-n00b/Git-pour-quoi-faire/ + + + http://yannesposito.com/n3blog/fr/blog/2010-02-16-All-but-something-regexp--2-/ + + + http://yannesposito.com/n3blog/fr/blog/2010-05-24-Trees--Pragmatism-and-Formalism/ + + + http://yannesposito.com/n3blog/en/blog/2010-02-23-When-regexp-is-not-the-best-solution/ + + + http://yannesposito.com/n3blog/en/ + + + http://yannesposito.com/n3blog/en/blog/2010-10-06-New-Blog-Design-Constraints/ + + + http://yannesposito.com/n3blog/en/blog/2010-05-17-at-least-this-blog-revive/ + + + http://yannesposito.com/n3blog/en/blog/2010-08-23-Now-heberged-on-heroku/ + + + http://yannesposito.com/n3blog/fr/blog/2009-10-launch-daemon-from-command-line/ + + + http://yannesposito.com/n3blog/fr/blog/2009-11-12-Git-for-n00b/conf-et-install/ + + + http://yannesposito.com/n3blog/fr/blog/2010-03-23-Encapsulate-git/ + + + http://yannesposito.com/n3blog/fr/softwares/ypassword/web/ + + + http://yannesposito.com/n3blog/en/blog/2010-06-17-track-events-with-google-analytics/ + + + http://yannesposito.com/n3blog/assets/css/main.css + + + http://yannesposito.com/n3blog/fr/rss/ + + + http://yannesposito.com/n3blog/en/blog/2011-01-03-Why-I-sadly-won-t-use-coffeescript/ + + + http://yannesposito.com/n3blog/fr/blog/ + + + http://yannesposito.com/n3blog/fr/blog/2009-11-12-Git-for-n00b/ + + + http://yannesposito.com/n3blog/fr/blog/04_drm/ + + + http://yannesposito.com/n3blog/en/about/technical_details/ + + + http://yannesposito.com/n3blog/fr/blog/2010-06-17-hide-yourself-to-analytics/ + + + http://yannesposito.com/n3blog/en/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/ + + + http://yannesposito.com/n3blog/en/blog/2009-10-Wait-to-hide-a-menu-in-jQuery/ + + + http://yannesposito.com/n3blog/fr/blog/2009-10-30-How-to-handle-evil-IE/ + + + http://yannesposito.com/n3blog/fr/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/ + + + http://yannesposito.com/n3blog/en/blog/2010-07-09-Indecidabilities/ + + + http://yannesposito.com/n3blog/en/blog/01_nanoc/ + + + http://yannesposito.com/n3blog/en/about/ + + + http://yannesposito.com/n3blog/fr/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/ + + + http://yannesposito.com/n3blog/fr/ + + + http://yannesposito.com/n3blog/fr/blog/2010-01-04-Change-default-shell-on-Mac-OS-X/ + + + http://yannesposito.com/n3blog/fr/blog/2010-05-19-How-to-cut-HTML-and-repair-it/ + + + http://yannesposito.com/n3blog/fr/softwares/ypassword/iphoneweb/ + + + http://yannesposito.com/n3blog/en/softwares/ + + + http://yannesposito.com/n3blog/fr/blog/2009-11-12-Git-for-n00b/comprendre/ + + + http://yannesposito.com/n3blog/en/blog/2009-11-12-Git-for-n00b/c-est-parti-pour-l-aventure/ + + + http://yannesposito.com/n3blog/en/blog/2010-06-14-multi-language-choices/ + + + http://yannesposito.com/n3blog/en/blog/2009-11-12-Git-for-n00b/ + + + http://yannesposito.com/n3blog/en/blog/05_git_create_remote_branch/ + + + http://yannesposito.com/n3blog/fr/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/ + + + http://yannesposito.com/n3blog/en/blog/feed/feed.xml + + + http://yannesposito.com/n3blog/fr/blog/2009-11-12-Git-for-n00b/c-est-parti-pour-l-aventure/ + + + http://yannesposito.com/n3blog/sitemap.xml + + + http://yannesposito.com/n3blog/fr/softwares/yclock/ + + + http://yannesposito.com/n3blog/en/blog/04_drm/ + + + http://yannesposito.com/n3blog/en/blog/2009-12-14-Git-vs--Bzr/ + +