diff --git a/Scratch/css/darkmodern.css b/Scratch/css/darkmodern.css index 4c3b4aa..854f990 100644 --- a/Scratch/css/darkmodern.css +++ b/Scratch/css/darkmodern.css @@ -1 +1 @@ - html{padding:0}body{padding:0;margin:0;font-family:"Droid Sans", Helvetica, sans-serif !important;font-size:16px;line-height:24px;background:#073642;color:#93a1a1}a{text-decoration:none;color:#268bd2}a:visited{color:#268bd2}a:hover{color:#cb4b16;text-shadow:0 0 1px #dc322f}.corps a{color:#93a1a1}.corps a:after{content:"*";line-height:0;font-size:0.66em;vertical-align:super}.corps a:visited{color:#93a1a1}#navigation{text-align:center;padding:1em;letter-spacing:0.25em}#navigation .sep{opacity:0.3;font-style:italic}#blackpage, #nojsredirect{top:0;left:0;width:100%;min-height:100%;margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;position:fixed;text-align:center;background:#002b36}#content{background:#001823;color:#93a1a1;width:720px;margin:0 auto;padding:0}#content #titre h1{padding:0 64px;margin:64px auto;text-align:center;font-weight:200}#content h1, #content h2, #content h3, #content h4, #content h5, #content h6{padding:0 64px;margin:64px 0;color:#839496}#content table{margin:16px 0;padding:0 64px}#content table tr:nth-child(odd){background-color:#002b36}#content table tr th{border:solid medium #073642;padding:4px;margin:0}#content table tr td{border:solid 1px #073642;padding:4px;margin:0}#content figure, #content .figure{margin:0;padding:0}#content figure figcaption, #content figure .caption, #content .figure figcaption, #content .figure .caption{padding:0 64px;margin:16px 0}#content p{padding:0 64px;margin:16px 0}#content img{max-width:100%;display:block;border-top:medium solid;border-bottom:medium solid;margin:64px auto}#content pre{background:#002b36;font-family:monaco, monospace;font-size:16px;overflow:auto;padding:16px;line-height:17.92px;border-top:solid 1px #073642;border-bottom:solid 1px #073642}#content pre code{background:none;border:none}#content ul{list-style:none}#content ul li:before{content:"- "}#content ul{padding-left:0;margin:16px 64px;text-indent:-8px}#content ol{padding-left:0;margin:16px 64px}#content .toc a, #content #markdown-toc a{color:#93a1a1}#content .toc ol li, #content .toc ul li, #content #markdown-toc ol li, #content #markdown-toc ul li{margin:8px 0}#content ol li ul, #content ol li ol, #content ul li ol, #content ul li ul{margin:8px 24px;list-style:none}#content li p{display:inline;margin:0;padding:0}#entete > #choix > #choixrss{margin:0;padding:0}#entete > #choix > #choixlang{float:left}#choixlang{float:left}#switchcss{float:right}#choix{text-align:center}#choix > div{display:inline-block}#header{border-bottom:8px solid #073642}#choix{text-align:center;font-size:12px;padding:0 16px;font-weight:bold}#choix #switchcss{float:right}.cut{color:#93a1a1;font-size:10.66667px;opacity:0.5;display:block;text-align:right}.cut:after{content:" »"}.cut:hover{opacity:1}hr{color:#586e75;border-color:#073642;margin:0 64px}p code, li code{padding:1px 2px;background:#002b36;border:solid 1px #073642}#content blockquote{border:solid 1px #073642;background:#002b36}#content blockquote p{padding:0 16px}#content blockquote code{background:#002b36;border:solid 1px rgba(0, 0, 0, 0.1)}#content blockquote pre code{background:none;border:none}#social, #choixrss, #comment{margin:16px 64px}#social{text-align:center;opacity:0.3}#social:hover{opacity:1}#comment img{width:auto;max-width:100%}.intro{width:646px;margin:0 auto;font-size:14px;line-height:21px;color:#839496}.intro blockquote hr{display:none}.left{float:left}.right{float:right}#content img.right, #content img.left{max-width:30%;border:medium solid}#content img.left{margin:0 32px 0 64px}#content img.right{margin:0 64px 0 32px}.flush{clear:both}#bottom{padding:16px 0;text-align:center;font-size:14px;line-height:21px}#entete{padding:16px 0;text-align:center}#entete ul{text-indent:0}#entete ul li:before{content:""}#entete ul li{display:inline-block}#entete ul li span.active{color:#cb4b16}#entete ul li > *{padding:2px 16px;border:solid}#previous_articles{float:left;text-align:left}#next_articles{float:right;text-align:right}.corps{padding-bottom:32px}#tagcloud{margin:16px 64px;font-size:14px;line-height:21px}#sousliens.archive > ul{display:none}#sousliens.archive > h4:hover{cursor:pointer}#hiddenDivs > div{display:none}.list{margin:16px 64px}pre .list{margin:0 0}#content img#mainlogo{width:auto;margin:0 auto;display:block;max-width:100%}.date, .day, .month, .year{display:inline-block;padding-left:10px;text-align:right}.day{width:10px}.month{width:20px}.year{width:30px}.date{margin-right:10px}#content .popularblock{display:block;float:left;margin:1.5%;width:30%}#content .popularblock a:after{content:""}#content .popularblock figure, #content .popularblock .figure{width:100%;overflow:hidden}#content .popularblock figure img, #content .popularblock .figure img{height:120px}#content .popularblock figure figcaption, #content .popularblock figure .caption, #content .popularblock .figure figcaption, #content .popularblock .figure .caption{padding:0;text-align:center}.base03{color:#002b36}.base02{color:#073642}.base01{color:#586e75}.base00{color:#657b83}.base0{color:#839496}.base1{color:#93a1a1}.base2{color:#eee8d5}.base3{color:#fdf6e3}.yellow{color:#b58900}.orange{color:#cb4b16}.red{color:#dc322f}.magenta{color:#d33682}.violet{color:#6c71c4}.blue{color:#268bd2}.cyan{color:#2aa198}.green{color:#859900}#content section.slide{min-height:20em;border-top:1.6px solid #073642;border-bottom:1.6px solid #073642;margin:64px 0;background-color:#002b36;color:#93a1a1;padding:16px 0}#content section.slide > *{padding:0 16px}#content section.slide a{text-decoration:none;color:#839496}#content section.slide a:visited{color:#586e75}#content section.slide pre{padding:16px;margin:16px}#content section.slide pre, #content section.slide code{background-color:#002b36;border:1px solid #073642}#content section.slide pre code, #content section.slide code code{border:none;background:none}#content section.slide blockquote{background-color:#002b36;border-color:#073642}#content section.slide h1, #content section.slide h2, #content section.slide h3, #content section.slide h4, #content section.slide h5, #content section.slide h6{color:#839496}#content section.slide ul{margin:16px 0;padding:0}#content section.slide ul li{margin:8px 24px}#content section.slide img{display:block;max-width:80%;margin:16px auto;padding:8px;background-color:#002b36;border:solid 1px #073642}#content section.slide img.right, #content section.slide img.left, #content section.slide figure.right, #content section.slide figure.left, #content section.slide .figure.right, #content section.slide .figure.left{max-width:26%;margin:8px}#content section.slide img.right figcaption, #content section.slide img.left figcaption, #content section.slide figure.right figcaption, #content section.slide figure.left figcaption, #content section.slide .figure.right figcaption, #content section.slide .figure.left figcaption{padding:0;text-align:center}#content section.slide figure, #content section.slide .figure{max-width:80%;margin:0 auto}#content section.slide figure img, #content section.slide .figure img{max-width:80%}.codefile{font-size:11.2px;text-align:right;margin-bottom:-32px}.footnotes{font-size:12.8px}#next_before_articles{font-size:11.2px;padding:0 64px;margin:16px 0}#content .inlineblockimg{width:60px;margin:0 8px;text-align:center;vertical-align:middle;display:inline-block}#content img.inlineimage{display:inline-block;max-height:48px;max-width:48px;border:solid;box-shadow:none;margin:0 auto;vertical-align:middle;font-size:7px;font-family:Helvetica, sans-serif;overflow:hidden}a.rss{background-color:#f8f8f8;background-image:-moz-linear-gradient(center top, white, #dedede);border:1px solid #cccccc;border-radius:3px 3px 3px 3px;color:#cb4b16;cursor:pointer;display:inline-block;font-size:13px;font-weight:bold;height:20px;font-family:sans-serif;line-height:20px;overflow:hidden;padding:0 5px;position:relative;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);margin:0 20px}a.rss:hover{background-image:-moz-linear-gradient(center top, white, #f3f3f3)} \ No newline at end of file + @font-face{font-family:"social";src:url("fonts/social_font.ttf") format("truetype");font-weight:normal;font-style:normal}.social{font-family:social}#social{font-size:2em;text-align:center;opacity:0.3}#social .message{font-size:10px}#social:hover{opacity:1}html{padding:0}body{padding:0;margin:0;font-family:"Droid Sans", Helvetica, sans-serif !important;font-size:16px;line-height:24px;background:#073642;color:#93a1a1}a{text-decoration:none;color:#268bd2}a:visited{color:#268bd2}a:hover{color:#cb4b16;text-shadow:0 0 1px #dc322f}.corps a{color:#93a1a1}.corps a:after{content:"*";line-height:0;font-size:0.66em;vertical-align:super}.corps a:visited{color:#93a1a1}#navigation{text-align:center;padding:1em;letter-spacing:0.25em}#navigation .sep{opacity:0.3;font-style:italic}#blackpage, #nojsredirect{top:0;left:0;width:100%;min-height:100%;margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;position:fixed;text-align:center;background:#002b36}#content{background:#001823;color:#93a1a1;width:100%;max-width:720px;margin:0 auto;padding:0}#content #titre h1{padding:0 64px;margin:64px auto;text-align:center;font-weight:200}#content h1, #content h2, #content h3, #content h4, #content h5, #content h6{padding:0 64px;margin:64px 0;color:#839496}#content table{margin:16px 0;padding:0 64px}#content table tr:nth-child(odd){background-color:#002b36}#content table tr th{border:solid medium #073642;padding:4px;margin:0}#content table tr td{border:solid 1px #073642;padding:4px;margin:0}#content figure, #content .figure{margin:0;padding:0}#content figure figcaption, #content figure .caption, #content .figure figcaption, #content .figure .caption{padding:0 64px;margin:16px 0}#content p{padding:0 64px;margin:16px 0}#content img{max-width:100%;display:block;border-top:medium solid;border-bottom:medium solid;margin:64px auto}#content pre{background:#002b36;font-family:monaco, monospace;font-size:16px;overflow:auto;padding:16px;line-height:17.92px;border-top:solid 1px #073642;border-bottom:solid 1px #073642}#content pre code{background:none;border:none}#content ul{list-style:none}#content ul li:before{content:"- "}#content ul{padding-left:0;margin:16px 64px;text-indent:-8px}#content ol{padding-left:0;margin:16px 64px}#content .toc a, #content #markdown-toc a{color:#93a1a1}#content .toc ol li, #content .toc ul li, #content #markdown-toc ol li, #content #markdown-toc ul li{margin:8px 0}#content ol li ul, #content ol li ol, #content ul li ol, #content ul li ul{margin:8px 24px;list-style:none}#content li p{display:inline;margin:0;padding:0}@media only screen and (max-width:592px){#content{padding:0;width:100%}#content .corps{padding:0 1em}}#entete > #choix > #choixlang{float:left}#choixlang{float:left}#switchcss{float:right}#choix{text-align:center}#choix > div{display:inline-block}#header{border-bottom:8px solid #073642}#choix{text-align:center;font-size:12px;padding:0 16px;font-weight:bold}#choix #switchcss{float:right}.cut{color:#93a1a1;font-size:10.66667px;opacity:0.5;display:block;text-align:right}.cut:after{content:" »"}.cut:hover{opacity:1}hr{color:#586e75;border-color:#073642;margin:0 64px}p code, li code{padding:1px 2px;background:#002b36;border:solid 1px #073642}#content blockquote{border:solid 1px #073642;background:#002b36}#content blockquote p{padding:0 16px}#content blockquote code{background:#002b36;border:solid 1px rgba(0, 0, 0, 0.1)}#content blockquote pre code{background:none;border:none}#social, #comment{margin:16px 64px}#social{text-align:center;opacity:0.3}#social:hover{opacity:1}#comment img{width:auto;max-width:100%}.intro{width:100%;max-width:646px;margin:0 auto;font-size:14px;line-height:21px;color:#839496}.intro blockquote hr{display:none}.left{float:left}.right{float:right}#content img.right, #content img.left{max-width:30%;border:medium solid}#content img.left{margin:0 32px 0 64px}#content img.right{margin:0 64px 0 32px}.flush{clear:both}#bottom{padding:16px 0;text-align:center;font-size:14px;line-height:21px}#entete{padding:16px 0;text-align:center}#entete ul{text-indent:0}#entete ul li:before{content:""}#entete ul li{display:inline-block}#entete ul li span.active{color:#cb4b16}#entete ul li > *{padding:2px 16px;border:solid}#previous_articles{float:left;text-align:left}#next_articles{float:right;text-align:right}.corps{padding-bottom:32px}#tagcloud{margin:16px 64px;font-size:14px;line-height:21px}#sousliens.archive > ul{display:none}#sousliens.archive > h4:hover{cursor:pointer}#hiddenDivs > div{display:none}.list{margin:16px 64px}pre .list{margin:0 0}#content img#mainlogo{width:auto;margin:0 auto;display:block;max-width:100%}.date, .day, .month, .year{display:inline-block;padding-left:10px;text-align:right}.day{width:10px}.month{width:20px}.year{width:30px}.date{margin-right:10px}#content .popularblock{display:block;float:left;margin:1.5%;width:30%}#content .popularblock a:after{content:""}#content .popularblock figure, #content .popularblock .figure{width:100%;overflow:hidden}#content .popularblock figure img, #content .popularblock .figure img{height:120px}#content .popularblock figure figcaption, #content .popularblock figure .caption, #content .popularblock .figure figcaption, #content .popularblock .figure .caption{padding:0;text-align:center}.base03{color:#002b36}.base02{color:#073642}.base01{color:#586e75}.base00{color:#657b83}.base0{color:#839496}.base1{color:#93a1a1}.base2{color:#eee8d5}.base3{color:#fdf6e3}.yellow{color:#b58900}.orange{color:#cb4b16}.red{color:#dc322f}.magenta{color:#d33682}.violet{color:#6c71c4}.blue{color:#268bd2}.cyan{color:#2aa198}.green{color:#859900}#content section.slide{min-height:20em;border-top:1.6px solid #073642;border-bottom:1.6px solid #073642;margin:64px 0;background-color:#002b36;color:#93a1a1;padding:16px 0}#content section.slide > *{padding:0 16px}#content section.slide a{text-decoration:none;color:#839496}#content section.slide a:visited{color:#586e75}#content section.slide pre{padding:16px;margin:16px}#content section.slide pre, #content section.slide code{background-color:#002b36;border:1px solid #073642}#content section.slide pre code, #content section.slide code code{border:none;background:none}#content section.slide blockquote{background-color:#002b36;border-color:#073642}#content section.slide h1, #content section.slide h2, #content section.slide h3, #content section.slide h4, #content section.slide h5, #content section.slide h6{color:#839496}#content section.slide ul{margin:16px 0;padding:0}#content section.slide ul li{margin:8px 24px}#content section.slide img{display:block;max-width:80%;margin:16px auto;padding:8px;background-color:#002b36;border:solid 1px #073642}#content section.slide img.right, #content section.slide img.left, #content section.slide figure.right, #content section.slide figure.left, #content section.slide .figure.right, #content section.slide .figure.left{max-width:26%;margin:8px}#content section.slide img.right figcaption, #content section.slide img.left figcaption, #content section.slide figure.right figcaption, #content section.slide figure.left figcaption, #content section.slide .figure.right figcaption, #content section.slide .figure.left figcaption{padding:0;text-align:center}#content section.slide figure, #content section.slide .figure{max-width:80%;margin:0 auto}#content section.slide figure img, #content section.slide .figure img{max-width:80%}.codefile{font-size:11.2px;text-align:right;margin-bottom:-32px}.footnotes{font-size:12.8px}#next_before_articles{font-size:11.2px;padding:0 64px;margin:16px 0}#totop{text-align:center;margin:0 auto}#content .inlineblockimg{width:60px;margin:16px;text-align:center;vertical-align:middle;display:inline-block}#content img.inlineimage{display:inline-block;max-height:48px;max-width:48px;border:solid;box-shadow:none;margin:0 auto;vertical-align:middle;font-size:7px;font-family:Helvetica, sans-serif;overflow:hidden} \ No newline at end of file diff --git a/Scratch/css/fonts/social_font.ttf b/Scratch/css/fonts/social_font.ttf new file mode 100644 index 0000000..f0b16d3 Binary files /dev/null and b/Scratch/css/fonts/social_font.ttf differ diff --git a/Scratch/css/modern.css b/Scratch/css/modern.css index 0e722c0..64060d1 100644 --- a/Scratch/css/modern.css +++ b/Scratch/css/modern.css @@ -1 +1 @@ - html{padding:0}body{padding:0;margin:0;font-family:"Droid Sans", Helvetica, sans-serif !important;font-size:16px;line-height:24px;background:#93a1a1;color:#586e75}a{text-decoration:none;color:#268bd2}a:visited{color:#268bd2}a:hover{color:#cb4b16;text-shadow:0 0 1px #dc322f}.corps a{color:#586e75}.corps a:after{content:"*";line-height:0;font-size:0.66em;vertical-align:super}.corps a:visited{color:#586e75}#navigation{text-align:center;padding:1em;letter-spacing:0.25em}#navigation .sep{opacity:0.3;font-style:italic}#blackpage, #nojsredirect{top:0;left:0;width:100%;min-height:100%;margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;position:fixed;text-align:center;background:#fdf6e3}#content{background:#fffffb;color:#586e75;width:720px;margin:0 auto;padding:0}#content #titre h1{padding:0 64px;margin:64px auto;text-align:center;font-weight:200}#content h1, #content h2, #content h3, #content h4, #content h5, #content h6{padding:0 64px;margin:64px 0;color:#657b83}#content table{margin:16px 0;padding:0 64px}#content table tr:nth-child(odd){background-color:#fdf6e3}#content table tr th{border:solid medium #eee8d5;padding:4px;margin:0}#content table tr td{border:solid 1px #eee8d5;padding:4px;margin:0}#content figure, #content .figure{margin:0;padding:0}#content figure figcaption, #content figure .caption, #content .figure figcaption, #content .figure .caption{padding:0 64px;margin:16px 0}#content p{padding:0 64px;margin:16px 0}#content img{max-width:100%;display:block;border-top:medium solid;border-bottom:medium solid;margin:64px auto}#content pre{background:#fdf6e3;font-family:monaco, monospace;font-size:16px;overflow:auto;padding:16px;line-height:17.92px;border-top:solid 1px #eee8d5;border-bottom:solid 1px #eee8d5}#content pre code{background:none;border:none}#content ul{list-style:none}#content ul li:before{content:"- "}#content ul{padding-left:0;margin:16px 64px;text-indent:-8px}#content ol{padding-left:0;margin:16px 64px}#content .toc a, #content #markdown-toc a{color:#586e75}#content .toc ol li, #content .toc ul li, #content #markdown-toc ol li, #content #markdown-toc ul li{margin:8px 0}#content ol li ul, #content ol li ol, #content ul li ol, #content ul li ul{margin:8px 24px;list-style:none}#content li p{display:inline;margin:0;padding:0}#entete > #choix > #choixrss{margin:0;padding:0}#entete > #choix > #choixlang{float:left}#choixlang{float:left}#switchcss{float:right}#choix{text-align:center}#choix > div{display:inline-block}#header{border-bottom:8px solid #93a1a1}#choix{text-align:center;font-size:12px;padding:0 16px;font-weight:bold}#choix #switchcss{float:right}.cut{color:#586e75;font-size:10.66667px;opacity:0.5;display:block;text-align:right}.cut:after{content:" »"}.cut:hover{opacity:1}hr{color:#93a1a1;border-color:#eee8d5;margin:0 64px}p code, li code{padding:1px 2px;background:#fdf6e3;border:solid 1px #eee8d5}#content blockquote{border:solid 1px #eee8d5;background:#fdf6e3}#content blockquote p{padding:0 16px}#content blockquote code{background:#fdf6e3;border:solid 1px rgba(0, 0, 0, 0.1)}#content blockquote pre code{background:none;border:none}#social, #choixrss, #comment{margin:16px 64px}#social{text-align:center;opacity:0.3}#social:hover{opacity:1}#comment img{width:auto;max-width:100%}.intro{width:646px;margin:0 auto;font-size:14px;line-height:21px;color:#657b83}.intro blockquote hr{display:none}.left{float:left}.right{float:right}#content img.right, #content img.left{max-width:30%;border:medium solid}#content img.left{margin:0 32px 0 64px}#content img.right{margin:0 64px 0 32px}.flush{clear:both}#bottom{padding:16px 0;text-align:center;font-size:14px;line-height:21px}#entete{padding:16px 0;text-align:center}#entete ul{text-indent:0}#entete ul li:before{content:""}#entete ul li{display:inline-block}#entete ul li span.active{color:#cb4b16}#entete ul li > *{padding:2px 16px;border:solid}#previous_articles{float:left;text-align:left}#next_articles{float:right;text-align:right}.corps{padding-bottom:32px}#tagcloud{margin:16px 64px;font-size:14px;line-height:21px}#sousliens.archive > ul{display:none}#sousliens.archive > h4:hover{cursor:pointer}#hiddenDivs > div{display:none}.list{margin:16px 64px}pre .list{margin:0 0}#content img#mainlogo{width:auto;margin:0 auto;display:block;max-width:100%}.date, .day, .month, .year{display:inline-block;padding-left:10px;text-align:right}.day{width:10px}.month{width:20px}.year{width:30px}.date{margin-right:10px}#content .popularblock{display:block;float:left;margin:1.5%;width:30%}#content .popularblock a:after{content:""}#content .popularblock figure, #content .popularblock .figure{width:100%;overflow:hidden}#content .popularblock figure img, #content .popularblock .figure img{height:120px}#content .popularblock figure figcaption, #content .popularblock figure .caption, #content .popularblock .figure figcaption, #content .popularblock .figure .caption{padding:0;text-align:center}.base03{color:#002b36}.base02{color:#073642}.base01{color:#586e75}.base00{color:#657b83}.base0{color:#839496}.base1{color:#93a1a1}.base2{color:#eee8d5}.base3{color:#fdf6e3}.yellow{color:#b58900}.orange{color:#cb4b16}.red{color:#dc322f}.magenta{color:#d33682}.violet{color:#6c71c4}.blue{color:#268bd2}.cyan{color:#2aa198}.green{color:#859900}#content section.slide{min-height:20em;border-top:1.6px solid #073642;border-bottom:1.6px solid #073642;margin:64px 0;background-color:#fdf6e3;color:#586e75;padding:16px 0}#content section.slide > *{padding:0 16px}#content section.slide a{text-decoration:none;color:#657b83}#content section.slide a:visited{color:#93a1a1}#content section.slide pre{padding:16px;margin:16px}#content section.slide pre, #content section.slide code{background-color:#fdf6e3;border:1px solid #eee8d5}#content section.slide pre code, #content section.slide code code{border:none;background:none}#content section.slide blockquote{background-color:#fdf6e3;border-color:#eee8d5}#content section.slide h1, #content section.slide h2, #content section.slide h3, #content section.slide h4, #content section.slide h5, #content section.slide h6{color:#657b83}#content section.slide ul{margin:16px 0;padding:0}#content section.slide ul li{margin:8px 24px}#content section.slide img{display:block;max-width:80%;margin:16px auto;padding:8px;background-color:#fdf6e3;border:solid 1px #eee8d5}#content section.slide img.right, #content section.slide img.left, #content section.slide figure.right, #content section.slide figure.left, #content section.slide .figure.right, #content section.slide .figure.left{max-width:26%;margin:8px}#content section.slide img.right figcaption, #content section.slide img.left figcaption, #content section.slide figure.right figcaption, #content section.slide figure.left figcaption, #content section.slide .figure.right figcaption, #content section.slide .figure.left figcaption{padding:0;text-align:center}#content section.slide figure, #content section.slide .figure{max-width:80%;margin:0 auto}#content section.slide figure img, #content section.slide .figure img{max-width:80%}.codefile{font-size:11.2px;text-align:right;margin-bottom:-32px}.footnotes{font-size:12.8px}#next_before_articles{font-size:11.2px;padding:0 64px;margin:16px 0}#content .inlineblockimg{width:60px;margin:0 8px;text-align:center;vertical-align:middle;display:inline-block}#content img.inlineimage{display:inline-block;max-height:48px;max-width:48px;border:solid;box-shadow:none;margin:0 auto;vertical-align:middle;font-size:7px;font-family:Helvetica, sans-serif;overflow:hidden}a.rss{background-color:#f8f8f8;background-image:-moz-linear-gradient(center top, white, #dedede);border:1px solid #cccccc;border-radius:3px 3px 3px 3px;color:#cb4b16;cursor:pointer;display:inline-block;font-size:13px;font-weight:bold;height:20px;font-family:sans-serif;line-height:20px;overflow:hidden;padding:0 5px;position:relative;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);margin:0 20px}a.rss:hover{background-image:-moz-linear-gradient(center top, white, #f3f3f3)} \ No newline at end of file + @font-face{font-family:"social";src:url("fonts/social_font.ttf") format("truetype");font-weight:normal;font-style:normal}.social{font-family:social}#social{font-size:2em;text-align:center;opacity:0.3}#social .message{font-size:10px}#social:hover{opacity:1}html{padding:0}body{padding:0;margin:0;font-family:"Droid Sans", Helvetica, sans-serif !important;font-size:16px;line-height:24px;background:#93a1a1;color:#586e75}a{text-decoration:none;color:#268bd2}a:visited{color:#268bd2}a:hover{color:#cb4b16;text-shadow:0 0 1px #dc322f}.corps a{color:#586e75}.corps a:after{content:"*";line-height:0;font-size:0.66em;vertical-align:super}.corps a:visited{color:#586e75}#navigation{text-align:center;padding:1em;letter-spacing:0.25em}#navigation .sep{opacity:0.3;font-style:italic}#blackpage, #nojsredirect{top:0;left:0;width:100%;min-height:100%;margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;position:fixed;text-align:center;background:#fdf6e3}#content{background:#fffffb;color:#586e75;width:100%;max-width:720px;margin:0 auto;padding:0}#content #titre h1{padding:0 64px;margin:64px auto;text-align:center;font-weight:200}#content h1, #content h2, #content h3, #content h4, #content h5, #content h6{padding:0 64px;margin:64px 0;color:#657b83}#content table{margin:16px 0;padding:0 64px}#content table tr:nth-child(odd){background-color:#fdf6e3}#content table tr th{border:solid medium #eee8d5;padding:4px;margin:0}#content table tr td{border:solid 1px #eee8d5;padding:4px;margin:0}#content figure, #content .figure{margin:0;padding:0}#content figure figcaption, #content figure .caption, #content .figure figcaption, #content .figure .caption{padding:0 64px;margin:16px 0}#content p{padding:0 64px;margin:16px 0}#content img{max-width:100%;display:block;border-top:medium solid;border-bottom:medium solid;margin:64px auto}#content pre{background:#fdf6e3;font-family:monaco, monospace;font-size:16px;overflow:auto;padding:16px;line-height:17.92px;border-top:solid 1px #eee8d5;border-bottom:solid 1px #eee8d5}#content pre code{background:none;border:none}#content ul{list-style:none}#content ul li:before{content:"- "}#content ul{padding-left:0;margin:16px 64px;text-indent:-8px}#content ol{padding-left:0;margin:16px 64px}#content .toc a, #content #markdown-toc a{color:#586e75}#content .toc ol li, #content .toc ul li, #content #markdown-toc ol li, #content #markdown-toc ul li{margin:8px 0}#content ol li ul, #content ol li ol, #content ul li ol, #content ul li ul{margin:8px 24px;list-style:none}#content li p{display:inline;margin:0;padding:0}@media only screen and (max-width:592px){#content{padding:0;width:100%}#content .corps{padding:0 1em}}#entete > #choix > #choixlang{float:left}#choixlang{float:left}#switchcss{float:right}#choix{text-align:center}#choix > div{display:inline-block}#header{border-bottom:8px solid #93a1a1}#choix{text-align:center;font-size:12px;padding:0 16px;font-weight:bold}#choix #switchcss{float:right}.cut{color:#586e75;font-size:10.66667px;opacity:0.5;display:block;text-align:right}.cut:after{content:" »"}.cut:hover{opacity:1}hr{color:#93a1a1;border-color:#eee8d5;margin:0 64px}p code, li code{padding:1px 2px;background:#fdf6e3;border:solid 1px #eee8d5}#content blockquote{border:solid 1px #eee8d5;background:#fdf6e3}#content blockquote p{padding:0 16px}#content blockquote code{background:#fdf6e3;border:solid 1px rgba(0, 0, 0, 0.1)}#content blockquote pre code{background:none;border:none}#social, #comment{margin:16px 64px}#social{text-align:center;opacity:0.3}#social:hover{opacity:1}#comment img{width:auto;max-width:100%}.intro{width:100%;max-width:646px;margin:0 auto;font-size:14px;line-height:21px;color:#657b83}.intro blockquote hr{display:none}.left{float:left}.right{float:right}#content img.right, #content img.left{max-width:30%;border:medium solid}#content img.left{margin:0 32px 0 64px}#content img.right{margin:0 64px 0 32px}.flush{clear:both}#bottom{padding:16px 0;text-align:center;font-size:14px;line-height:21px}#entete{padding:16px 0;text-align:center}#entete ul{text-indent:0}#entete ul li:before{content:""}#entete ul li{display:inline-block}#entete ul li span.active{color:#cb4b16}#entete ul li > *{padding:2px 16px;border:solid}#previous_articles{float:left;text-align:left}#next_articles{float:right;text-align:right}.corps{padding-bottom:32px}#tagcloud{margin:16px 64px;font-size:14px;line-height:21px}#sousliens.archive > ul{display:none}#sousliens.archive > h4:hover{cursor:pointer}#hiddenDivs > div{display:none}.list{margin:16px 64px}pre .list{margin:0 0}#content img#mainlogo{width:auto;margin:0 auto;display:block;max-width:100%}.date, .day, .month, .year{display:inline-block;padding-left:10px;text-align:right}.day{width:10px}.month{width:20px}.year{width:30px}.date{margin-right:10px}#content .popularblock{display:block;float:left;margin:1.5%;width:30%}#content .popularblock a:after{content:""}#content .popularblock figure, #content .popularblock .figure{width:100%;overflow:hidden}#content .popularblock figure img, #content .popularblock .figure img{height:120px}#content .popularblock figure figcaption, #content .popularblock figure .caption, #content .popularblock .figure figcaption, #content .popularblock .figure .caption{padding:0;text-align:center}.base03{color:#002b36}.base02{color:#073642}.base01{color:#586e75}.base00{color:#657b83}.base0{color:#839496}.base1{color:#93a1a1}.base2{color:#eee8d5}.base3{color:#fdf6e3}.yellow{color:#b58900}.orange{color:#cb4b16}.red{color:#dc322f}.magenta{color:#d33682}.violet{color:#6c71c4}.blue{color:#268bd2}.cyan{color:#2aa198}.green{color:#859900}#content section.slide{min-height:20em;border-top:1.6px solid #073642;border-bottom:1.6px solid #073642;margin:64px 0;background-color:#fdf6e3;color:#586e75;padding:16px 0}#content section.slide > *{padding:0 16px}#content section.slide a{text-decoration:none;color:#657b83}#content section.slide a:visited{color:#93a1a1}#content section.slide pre{padding:16px;margin:16px}#content section.slide pre, #content section.slide code{background-color:#fdf6e3;border:1px solid #eee8d5}#content section.slide pre code, #content section.slide code code{border:none;background:none}#content section.slide blockquote{background-color:#fdf6e3;border-color:#eee8d5}#content section.slide h1, #content section.slide h2, #content section.slide h3, #content section.slide h4, #content section.slide h5, #content section.slide h6{color:#657b83}#content section.slide ul{margin:16px 0;padding:0}#content section.slide ul li{margin:8px 24px}#content section.slide img{display:block;max-width:80%;margin:16px auto;padding:8px;background-color:#fdf6e3;border:solid 1px #eee8d5}#content section.slide img.right, #content section.slide img.left, #content section.slide figure.right, #content section.slide figure.left, #content section.slide .figure.right, #content section.slide .figure.left{max-width:26%;margin:8px}#content section.slide img.right figcaption, #content section.slide img.left figcaption, #content section.slide figure.right figcaption, #content section.slide figure.left figcaption, #content section.slide .figure.right figcaption, #content section.slide .figure.left figcaption{padding:0;text-align:center}#content section.slide figure, #content section.slide .figure{max-width:80%;margin:0 auto}#content section.slide figure img, #content section.slide .figure img{max-width:80%}.codefile{font-size:11.2px;text-align:right;margin-bottom:-32px}.footnotes{font-size:12.8px}#next_before_articles{font-size:11.2px;padding:0 64px;margin:16px 0}#totop{text-align:center;margin:0 auto}#content .inlineblockimg{width:60px;margin:16px;text-align:center;vertical-align:middle;display:inline-block}#content img.inlineimage{display:inline-block;max-height:48px;max-width:48px;border:solid;box-shadow:none;margin:0 auto;vertical-align:middle;font-size:7px;font-family:Helvetica, sans-serif;overflow:hidden} \ No newline at end of file diff --git a/Scratch/css/scientific.css b/Scratch/css/scientific.css index 0e2e3ce..bfe0a76 100644 --- a/Scratch/css/scientific.css +++ b/Scratch/css/scientific.css @@ -1 +1 @@ - @font-face{font-family:"cmuntt";src:url("fonts/cmuntt.eot");src:local("☺"), url("fonts/cmuntt.svg") format("svg"), url("fonts/cmuntt.ttf") format("truetype");font-weight:normal;font-style:normal}@font-face{font-family:"ComputerModern";src:url("fonts/cmunrb.eot");src:local("☺"), url("fonts/cmunrb.svg") format("svg"), url("fonts/cmunrb.ttf") format("truetype");font-weight:bold}@font-face{font-family:"ComputerModern";src:url("fonts/cmunsl.eot");src:local("☺"), url("fonts/cmunsl.svg") format("svg"), url("fonts/cmunsl.ttf") format("truetype");font-style:italic, oblique}@font-face{font-family:"ComputerModern";src:url("fonts/cmunrm.eot");src:local("☺"), url("fonts/cmunrm.svg") format("svg"), url("fonts/cmunrm.ttf") format("truetype");font-weight:normal;font-style:normal}i, em{font-style:italic}b, strong, h1, h2, h3, h4, h5, h6{font-weight:bold}table.description tr td{border:1px solid #eeeef1}.assombris20{background-color:#eeeef1}body{color:#002b36;background-color:#fafafc}::selection{background:#002b36;color:#93a1a1}::-moz-selection{background:#002b36;color:#93a1a1}pre, code, a.cut{font-family:Incosolata, Monaco, monospace}pre::selection{background:#fdf6e3;color:#586e75}pre *::selection{background:#fdf6e3;color:#586e75}pre::-moz-selection{background:#fdf6e3;color:#586e75}pre *::-moz-selection{background:#fdf6e3;color:#586e75}a:hover{text-shadow:0 0 2px #ffaaaa}a, a:link, a:visited, a:active, a:hover{text-decoration:none;outline:none}a, a:link, a:visited, a:active{color:#002b36}a:hover{color:#cb4b16}hr{color:#eeeef1;border-top:1px solid #eeeef1;border-bottom:none;border-left:none;border-right:none}ul{list-style:none}.corps ul li:before{content:"- "}ul{padding-left:0;margin-left:1.5ex;text-indent:-1.5ex}ol{padding-left:0}.toc ol li, .toc ul li{margin:0.5em 0}ol li ul, ol li ol, ul li ol, ul li ul{margin:0.5em 1.5em;list-style:none}body, h1, h2, h3, h4, #entete, .tagname{text-rendering:optimizelegibility;line-height:1.5em}body{font-family:Georgia, Palatino, "Century Schoolbook L", "Times New Roman", Times, serif}#choix{font-style:italic}#navigation{letter-spacing:0.25em;margin:1em auto 2em;font-size:1.25em;text-align:center;font-weight:bold}#navigation .sep{opacity:0.3;font-style:italic}.article #afterheader{counter-reset:niv02}.article #afterheader h2{counter-increment:niv02;counter-reset:niv03;marker-offset:3em}.article #afterheader h2:before{content:counter(niv02) ". "}.article #afterheader h3{counter-increment:niv03;counter-reset:niv04}.article #afterheader h3:before{content:counter(niv02) "." counter(niv03) ". "}.article #afterheader h4{counter-increment:niv04}.article #afterheader h4:before{content:counter(niv02) "." counter(niv03) "." counter(niv04) ". "}pre{background-color:#002b36;color:#839496;box-shadow:0 0 5px #d0d0d2 inset;border-radius:3px;padding:1em;line-height:1.1em;font-size:0.9em}p{margin-bottom:1.2em}.corps blockquote{border:solid 1px #ccccd0;border-radius:2px;box-shadow:0 0 4px #f2f2f4 inset;background-color:#f8f8fa;font-style:italic;padding:0.5em 1em;color:#555566}.corps blockquote ul{margin-left:0}.corps blockquote a:hover{color:#cb4b16}.corps blockquote i, .corps blockquote em{font-weight:normal;font-style:normal;color:#002b36}.corps blockquote strong, .corps blockquote b{font-weight:bold;color:#002b36}.corps blockquote > ul{padding-left:1.5em}abbr, acronym{text-transform:uppercase;font-size:0.8em;text-decoration:none;border-bottom-width:0}#titre{letter-spacing:-0.06em;border-bottom:4px double #ccccd0;border-top:4px double #ccccd0}#liens .active, #sousliens{color:#002b36;border:#ccccd0 solid 1px;border-radius:5px;box-shadow:0 0 2px #ccccd0 inset;background-color:#eeeef1}#liens .active a, #sousliens a{color:#666677}#liens .active a:hover, #sousliens a:hover{color:#cb4b16}#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:#ffb17c}#liens .active hr, #sousliens hr{color:#666677;border-top:1px solid #666677}#liens .active strong, #liens .active b, #liens .active i, #liens .active em, #sousliens strong, #sousliens b, #sousliens i, #sousliens em{color:#002b36}#liens a{border:1px solid #eeeeee;background:rgba(0, 0, 0, 0.05);box-shadow:0 0 2px white, 0 0 3px #cccccc inset;border:1px solid rgba(0, 0, 0, 0.1);border-radius:3px}#liens a:hover{background:rgba(0, 0, 0, 0.1);box-shadow:0 0 6px #555555 inset}#liens .active{text-shadow:0 0 2px rgba(0, 0, 0, 0.5);background-color:#f7f7f9;border:1px solid #e9e9eb;box-shadow:0 0 3px #c7c7c9 inset;border-radius:3px;border-top:none}#lastmod{font-size:0.9em}.nojsbutton{font-size:2.5em}#clickcomment, #choixrss > a{display:block;width:20%;cursor:pointer;margin:1em 0;padding:1em;font-size:16px;line-height:1.4em;border:1px solid #fafafc;color:#ccccd0}#clickcomment:hover, #choixrss > a:hover{border:solid 1px #ccccd0;border-radius:2px;box-shadow:0 0 4px #f2f2f4 inset;background-color:#f8f8fa;color:#dc5c27;text-shadow:0 0 2px #ffaaaa}#clickcomment:hover ul, #choixrss > a:hover ul{margin-left:0}#clickcomment:active, #choixrss > a:active{border:solid 1px #ccccd0;border-radius:2px;box-shadow:0 0 4px #f2f2f4 inset;background-color:#f8f8fa;color:#dc5c27;text-shadow:0 0 2px #ffaaaa;background:#f4f4f6}#clickcomment:active ul, #choixrss > a:active ul{margin-left:0}.return > a, #choixrss > a{float:right}#choix .return > a, #choix #choixrss > a{margin-top:0}#choix #switchcss{float:right}#choix #choixlang{float:left}#choix #choixlang a, #choix #switchcss a{margin-top:0;width:100%}.small{font-size:0.8em}.sc{text-transform:uppercase;font-size:0.8em}.impact, .darkimpact{font-size:2em;margin:0 auto 1em auto;line-height:1.3em}h1 > .date{font-size:0.6em;color:#002b36}.date{font-size:0.8em;color:#fafafc;border:1px solid #002b36;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:#002b36;background-color:#fafafc;float:left;width:1.7em}.date .month{float:right;width:2.3em;background-color:#002b36;color:#fafafc}.date .year{line-height:3ex;clear:both;color:#002b36;border:#ccccd0 solid 1px;border-radius:5px;box-shadow:0 0 2px #ccccd0 inset;background-color:#eeeef1;border-radius:0}.date .year a{color:#666677}.date .year a:hover{color:#cb4b16}.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:#ffb17c}.date .year hr{color:#666677;border-top:1px solid #666677}.date .year strong, .date .year b, .date .year i, .date .year em{color:#002b36}body{text-align:center;font-size:16px}body > #entete{position:absolute;left:0;top:0.5em;width:100%;min-width:45em;z-index:8000;padding-bottom:1em;margin-bottom:3em}#titre h2{width:80%;margin-left:auto;margin-right:auto;text-align:center;color:#ccccd0}#titre{text-align:center;width:100%}#titre h1, #titre h2{padding-left:1em;padding-right:1em}#bottom{clear:right;margin-right:0px;padding:1.5em;line-height:1.5em;color:#224d58;margin-top:2em;text-align:center}#bottom a{color:#113c47}#bottom a:hover{color:#cb4b16}#sousliens{padding:1em 0;line-height:2em}#sousliens ul{list-style:none;margin-left:4em}ul.horizontal li{display:inline;font-size:0.9em}ul.horizontal{margin-top:0px;margin-bottom:0px}#entete{padding-top:0.1em;border-top:1px solid #ccccd0;border-bottom:1px solid #ccccd0}#liens{width:100%;padding:0;clear:both;margin-top:0.5em}#liens ul{width:100%;clear:both;padding:0;margin:0}#liens ul li{display:inline-block;height:4em;margin-left:0.2em;margin-right:0.2em;width:23%}#liens ul li a, #liens ul li span{width:100%;display:block;line-height:4em}.clear{clear:both}#content{line-height:2em;margin-left:auto;margin-right:auto;margin-top:0;position:relative;clear:both;width:100%;max-width:47em}@media only screen and (max-width:45em){#content{padding:0;width:100%}#content img{max-width:80%}#content .corps{padding:0 1em}}.encadre, .black, .intro, .resume, .shadow{padding:2em;margin-top:2em;margin-bottom:2em}.encadre, .black, .shadow{color:#002b36;border:#ccccd0 solid 1px;border-radius:5px;box-shadow:0 0 2px #ccccd0 inset;background-color:#eeeef1}.encadre a, .black a, .shadow a{color:#666677}.encadre a:hover, .black a:hover, .shadow a:hover{color:#cb4b16}.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, .shadow a:hover strong, .shadow a:hover b, .shadow a:hover i, .shadow a:hover em, .shadow a:hover .nicer{color:#ffb17c}.encadre hr, .black hr, .shadow hr{color:#666677;border-top:1px solid #666677}.encadre strong, .encadre b, .encadre i, .encadre em, .black strong, .black b, .black i, .black em, .shadow strong, .shadow b, .shadow i, .shadow em{color:#002b36}.intro, .resume{font-size:0.9em;font-style:italic;padding:0.5em 1em;color:#555566}.intro a:hover, .resume a:hover{color:#cb4b16}.intro i, .intro em, .resume i, .resume em{font-weight:normal;font-style:normal;color:#002b36}.intro strong, .intro b, .resume strong, .resume b{font-weight:bold;color:#002b36}#afterheader > h1{width:100%;padding-top:1.5em;text-align:left}#afterheader{padding-left:0em;padding-right:0em}#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-size:1.25em;line-height:1.5em;text-align:justify;padding:3em 3em;margin:0;clear:both}.corps p, .corps ol, .corps ul, .corps blockquote, .corps pre, .corps code{margin-top:1.5em;margin-bottom:1.5em}.corps pre code{margin:0}.corps p, .corps ol, .corps ul, .corps blockquote{line-height:1.5em}.corps ul li ul, .corps ol li ul, .corps ul li ol, .corps ol li ol{margin-top:0;margin-bottom:0}.corps img{max-width:80%;border:1px solid #ccccd0;background-color:#fafafc;padding:0.5em;box-shadow:0 10px 15px #cccccc;border-radius:3px}.corps a:hover img{background-color:#dc3a05}figure, .figure{margin:3em 0}figure img, .figure img{box-shadow:0 10px 15px #cccccc inset}figure figcaption, figure .caption, .figure figcaption, .figure .caption{text-align:center;margin:0.5em 0}figure.left, figure.right, .figure.right, .figure.left{max-width:30%}img.clean{border:none;background-color:none;box-shadow:none}#address{clear:both}.definitionCell{width:5em;vertical-align:top;text-align:center;font-weight:bold}.valueCell{text-align:right}.smallblock{float:left;width:50%;font-size:1em;font-weight:bold}.largeblock{float:right;width:70%;font-size:1em}#blackpage, #nojsredirect{top:0;left:0;width:100%;min-height:100%;margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;position:absolute;text-align:center}#blackpage{color:#002b36;background-color:#fafafc;font-family:Georgia, serif;font-style:italic;padding-top:8em;z-index:9000;cursor:wait}#blackpage .corps code, #blackpage .corps pre{font-family:monospace}#blackpage img{background:none;border:none;max-width:80%;margin:0 auto}#blackpage a{cursor:pointer}#blackpage .preh1{font-size:1.5em;font-weight:bold;margin-bottom:1em}#blackpage .preh2{font-size:1.2em;font-style:italic;margin-bottom:1em}#blackpage .preintro{text-align:left;width:47em;margin:0 auto}#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}.codefile{font-size:0.8em;text-align:right;padding-right:1em;margin-right:0.1;margin-bottom:-1em}.flush{clear:both}table.description{border-spacing:5px;border-collapse:separate;margin-right:auto;margin-left:auto}table.description tr td{padding-left:0.5em;padding-right:0.5em;padding-top:0.5ex;padding-bottom:0.5ex;vertical-align:middle;margin-right:5px}ul.long li{margin-bottom:1em}img{display:block;margin:1.2em auto;background:none;border:none}img.right{max-width:30%;margin-top:0.6em;margin-left:2em}img.left{float:left;max-width:30%;margin-top:0.6em;margin-right:2em}img.inside{display:inline;vertical-align:middle}pre{overflow-x:auto;overflow-y:hidden}.impact, .darkimpact{text-align:left;width:66%;padding-left:0.25em;padding-right:0.25em}table.impact{text-align:left}table.impact tr td{padding-left:0.25em;padding-right:0.25em}#liens{font-size:1.2em}#iemessage{font-size:1.2em;color:#cccccc;margin:-10px;padding:1px 0;background:#333333}#iemessage strong, #iemessage b, #iemessage i, #iemessage em{color:#cccccc}#iemessage a, #iemessage a:visited{color:#eeccaa}.tagname{display:inline;cursor:pointer;margin-left:0.5em;margin-right:0.5em}.list{margin-top:3em}#menuMessage{font-size:1.2em;line-height:1.5em;width:100%;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:#888899;font-size:0.8em;font-style:italic}#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}#rss{font-size:1.2em;text-align:center;display:block;width:100%;float:right;padding:1em 0.1em}.corps .return a{color:#eeeef1;padding:0.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:#eeeef1;padding:0.1em;line-height:1.5em;font-size:1.5em;height:1.5em;font-size:2em;width:1.5em;display:block}a.return:hover{color:#888899}.corps .return a:hover{color:#cb4b16}.footnotes{font-size:0.8em}.footnotes ol{color:#839496;font-weight:bold}.footnotes ol p{color:#002b36;font-weight:normal;font-style:normal}.fontnotes ol{margin-left:0}.typeset img{display:inline;border:none;margin:0;padding:0}strong, b, i, em{color:#888899}strong a, b a, i a, em a{color:#002b36}strong a:hover, b a:hover, i a:hover, em a:hover{color:#cb4b16}.corps p strong, .corps p b, .corps p i, .corps p em{color:#555566}a:hover strong, a:hover b, a:hover i, a:hover em{color:#dc5c27}a:hover .nicer{color:#ffb17c}.nicer{color:#ccccd0;font-family:"Lucida Grande", Tahoma}.block{border:solid 1px #ccccd0;border-radius:2px;box-shadow:0 0 4px #f2f2f4 inset;background-color:#f8f8fa;width:26.5%;padding:1em;border-radius:2px;text-align:left;line-height:1em;margin-left:1%;margin-right:1%;font-size:0.8em;height:9em}.block ul{margin-left:0}.block a{color:#002b36}.block a:hover{color:#cb4b16}.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:#555566}.corps p a:hover, .corps ul a:hover{color:#cb4b16}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}#tagcloud{font-size:0.8em;background:#f2f2f4;box-shadow:0 0 6px #ccccd0;border-radius:3px;line-height:2.5em;padding:2em;text-align:justify}.pala{font-family:Palatino}sup{vertical-align:top;font-size:0.7em}.article .corps a:after{content:"†";vertical-align:super;line-height:0;font-size:0.66em;color:#888899}.article .corps .footnotes a:after, .article .corps sup a:after{content:""}.article .corps sup a{font-weight:bold;padding:0 0.3em;margin-left:2px;border-radius:3px;-moz-border-radius:3px;-webkit-border-radius:3px}.article .corps sup a:hover{color:#cb4b16}ul#markdown-toc, .intro .toc ul{text-transform:uppercase;font-size:0.8em;list-style:none;padding-left:1.5em}ul#markdown-toc a:after, .intro .toc ul a:after{content:""}ul#markdown-toc ul ul, .intro .toc ul ul ul{font-variant:normal;line-height:1em;font-size:1em;margin-bottom:1em}table{border:1px solid #ccccd0}table tr td{padding:2px 0.5em}table tr:nth-child(odd){background-color:#f2f2f4}table tr:nth-child(even){background-color:#fafafc}p pre code, ul li pre code, ol li pre code{background:none;border:none;padding:0}p code, ul li code, ol li code{background:#f0f0f2;border:solid 1px #ccccd0;padding:2px}ul.sameline{list-style:none}ul.sameline li{float:left;margin-left:0.5em}.resumearticle{background-color:#f2f2f4;border-radius:7px;box-shadow:0 0 5px #c7c7b8 inset, 0 0 5px white;margin:1em 0;padding:1em}a.cut{font-size:12px;text-align:right;display:block;width:100%;opacity:0.5;border:1px solid #fafafc;border-radius:3px}a.cut:hover{opacity:1;background-color:#f2f2f4;border-color:#ccccd0;box-shadow:0 0 3px #ccccd0 inset}a.cut strong{font-weight:bold}.codehighlight pre{border-left:4px solid #ccccd0}#social{text-align:center;opacity:0.3}#social:hover{opacity:1}.popularblock{width:30.3333%;margin:0 1.5%;float:left}.popularblock figure{margin:0}.popularblock figure img{max-width:80%;max-height:6em}.inlineblockimg{width:48px;margin:0 8px;text-align:center;vertical-align:middle;display:inline-block;line-height:0.8em;overflow:hidden;border:solid 1px}img.inlineimage{padding:0;max-height:48px;max-width:48px;border:none;box-shadow:none;margin:0 auto;vertical-align:middle;font-size:7px;font-family:Helvetica, sans-serif;overflow:hidden}section.slide{border-color:#ccccd0;border:solid 1px;margin-bottom:1em;padding:0.5em;font-family:sans-serif;font-size:0.8em;min-height:25em}a.rss{background-color:#f8f8f8;background-image:-moz-linear-gradient(center top, white, #dedede);border:1px solid #cccccc;border-radius:3px 3px 3px 3px;color:#cb4b16;cursor:pointer;display:inline-block;font-size:13px;font-weight:bold;height:20px;font-family:sans-serif;line-height:20px;overflow:hidden;padding:0 5px;position:relative;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);margin:0 20px}a.rss:hover{background-image:-moz-linear-gradient(center top, white, #f3f3f3)}.base03{color:#002b36}.base02{color:#073642}.base01{color:#586e75}.base00{color:#657b83}.base0{color:#839496}.base1{color:#93a1a1}.base2{color:#eee8d5}.base3{color:#fdf6e3}.yellow{color:#b58900}.orange{color:#cb4b16}.red{color:#dc322f}.magenta{color:#d33682}.violet{color:#6c71c4}.blue{color:#268bd2}.cyan{color:#2aa198}.green{color:#859900}#header{opacity:0.25}#header:hover{opacity:1} \ No newline at end of file + @font-face{font-family:"cmuntt";src:url("fonts/cmuntt.eot");src:local("☺"), url("fonts/cmuntt.svg") format("svg"), url("fonts/cmuntt.ttf") format("truetype");font-weight:normal;font-style:normal}@font-face{font-family:"social";src:url("fonts/social_font.ttf") format("truetype");font-weight:normal;font-style:normal}.social{font-family:social}@font-face{font-family:"ComputerModern";src:url("fonts/cmunrb.eot");src:local("☺"), url("fonts/cmunrb.svg") format("svg"), url("fonts/cmunrb.ttf") format("truetype");font-weight:bold}@font-face{font-family:"ComputerModern";src:url("fonts/cmunsl.eot");src:local("☺"), url("fonts/cmunsl.svg") format("svg"), url("fonts/cmunsl.ttf") format("truetype");font-style:italic, oblique}@font-face{font-family:"ComputerModern";src:url("fonts/cmunrm.eot");src:local("☺"), url("fonts/cmunrm.svg") format("svg"), url("fonts/cmunrm.ttf") format("truetype");font-weight:normal;font-style:normal}i, em{font-style:italic}b, strong, h1, h2, h3, h4, h5, h6{font-weight:bold}table.description tr td{border:1px solid #eeeef1}.assombris20{background-color:#eeeef1}body{color:#002b36;background-color:#fafafc}::selection{background:#002b36;color:#93a1a1}::-moz-selection{background:#002b36;color:#93a1a1}pre, code, a.cut{font-family:Incosolata, Monaco, monospace}pre::selection{background:#fdf6e3;color:#586e75}pre *::selection{background:#fdf6e3;color:#586e75}pre::-moz-selection{background:#fdf6e3;color:#586e75}pre *::-moz-selection{background:#fdf6e3;color:#586e75}a:hover{text-shadow:0 0 2px #ffaaaa}a, a:link, a:visited, a:active, a:hover{text-decoration:none;outline:none}a, a:link, a:visited, a:active{color:#002b36}a:hover{color:#cb4b16}hr{color:#eeeef1;border-top:1px solid #eeeef1;border-bottom:none;border-left:none;border-right:none}ul{list-style:none}.corps ul li:before{content:"- "}ul{padding-left:0;margin-left:1.5ex;text-indent:-1.5ex}ol{padding-left:0}.toc ol li, .toc ul li{margin:0.5em 0}ol li ul, ol li ol, ul li ol, ul li ul{margin:0.5em 1.5em;list-style:none}body, h1, h2, h3, h4, #entete, .tagname{text-rendering:optimizelegibility;line-height:1.5em}body{font-family:Georgia, Palatino, "Century Schoolbook L", "Times New Roman", Times, serif}#navigation{letter-spacing:0.25em;margin:1em auto 2em;font-size:1.25em;text-align:center;font-weight:bold}#navigation .sep{opacity:0.3;font-style:italic}.article #afterheader{counter-reset:niv02}.article #afterheader h2{counter-increment:niv02;counter-reset:niv03;marker-offset:3em}.article #afterheader h2:before{content:counter(niv02) ". "}.article #afterheader h3{counter-increment:niv03;counter-reset:niv04}.article #afterheader h3:before{content:counter(niv02) "." counter(niv03) ". "}.article #afterheader h4{counter-increment:niv04}.article #afterheader h4:before{content:counter(niv02) "." counter(niv03) "." counter(niv04) ". "}pre{background-color:#002b36;color:#839496;box-shadow:0 0 5px #d0d0d2 inset;border-radius:3px;padding:1em;line-height:1.1em;font-size:0.9em}p{margin-bottom:1.2em}.corps blockquote{border:solid 1px #ccccd0;border-radius:2px;box-shadow:0 0 4px #f2f2f4 inset;background-color:#f8f8fa;font-style:italic;padding:0.5em 1em;color:#555566}.corps blockquote ul{margin-left:0}.corps blockquote a:hover{color:#cb4b16}.corps blockquote i, .corps blockquote em{font-weight:normal;font-style:normal;color:#002b36}.corps blockquote strong, .corps blockquote b{font-weight:bold;color:#002b36}.corps blockquote > ul{padding-left:1.5em}abbr, acronym{text-transform:uppercase;font-size:0.8em;text-decoration:none;border-bottom-width:0}#titre{letter-spacing:-0.06em;margin:2em 0;border-bottom:4px double #ccccd0;border-top:4px double #ccccd0}#liens .active, #sousliens{color:#002b36;border:#ccccd0 solid 1px;border-radius:5px;box-shadow:0 0 2px #ccccd0 inset;background-color:#eeeef1}#liens .active a, #sousliens a{color:#666677}#liens .active a:hover, #sousliens a:hover{color:#cb4b16}#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:#ffb17c}#liens .active hr, #sousliens hr{color:#666677;border-top:1px solid #666677}#liens .active strong, #liens .active b, #liens .active i, #liens .active em, #sousliens strong, #sousliens b, #sousliens i, #sousliens em{color:#002b36}#liens a{border:1px solid #eeeeee;background:rgba(0, 0, 0, 0.05);box-shadow:0 0 2px white, 0 0 3px #cccccc inset;border:1px solid rgba(0, 0, 0, 0.1);border-radius:3px}#liens a:hover{background:rgba(0, 0, 0, 0.1);box-shadow:0 0 6px #555555 inset}#liens .active{text-shadow:0 0 2px rgba(0, 0, 0, 0.5);background-color:#f7f7f9;border:1px solid #e9e9eb;box-shadow:0 0 3px #c7c7c9 inset;border-radius:3px;border-top:none}#lastmod{font-size:0.9em}.nojsbutton{font-size:2.5em}#clickcomment, #choixrss > a{display:block;width:20%;cursor:pointer;margin:1em 0;padding:1em;font-size:16px;line-height:1.4em;border:1px solid #fafafc;color:#ccccd0}#clickcomment:hover, #choixrss > a:hover{border:solid 1px #ccccd0;border-radius:2px;box-shadow:0 0 4px #f2f2f4 inset;background-color:#f8f8fa;color:#dc5c27;text-shadow:0 0 2px #ffaaaa}#clickcomment:hover ul, #choixrss > a:hover ul{margin-left:0}#clickcomment:active, #choixrss > a:active{border:solid 1px #ccccd0;border-radius:2px;box-shadow:0 0 4px #f2f2f4 inset;background-color:#f8f8fa;color:#dc5c27;text-shadow:0 0 2px #ffaaaa;background:#f4f4f6}#clickcomment:active ul, #choixrss > a:active ul{margin-left:0}.return > a, #choixrss > a{float:right}#choix .return > a, #choix #choixrss > a{margin-top:0}#choix #switchcss{float:right}#choix #choixlang{float:left}#choix #choixlang a, #choix #switchcss a{margin-top:0;width:100%}.small{font-size:0.8em}.tiny{font-size:0.6em}.sc{text-transform:uppercase;font-size:0.8em}.impact, .darkimpact{font-size:2em;margin:0 auto 1em auto;line-height:1.3em}h1 > .date{font-size:0.6em;color:#002b36}.date{font-size:0.8em;color:#fafafc;border:1px solid #002b36;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:#002b36;background-color:#fafafc;float:left;width:1.7em}.date .month{float:right;width:2.3em;background-color:#002b36;color:#fafafc}.date .year{line-height:3ex;clear:both;color:#002b36;border:#ccccd0 solid 1px;border-radius:5px;box-shadow:0 0 2px #ccccd0 inset;background-color:#eeeef1;border-radius:0}.date .year a{color:#666677}.date .year a:hover{color:#cb4b16}.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:#ffb17c}.date .year hr{color:#666677;border-top:1px solid #666677}.date .year strong, .date .year b, .date .year i, .date .year em{color:#002b36}body{text-align:center;font-size:16px}body > #entete{position:absolute;left:0;top:0.5em;width:100%;min-width:45em;z-index:8000;padding-bottom:1em;margin-bottom:3em}#titre h2{width:80%;margin-left:auto;margin-right:auto;text-align:center;color:#ccccd0}#titre{text-align:center;width:100%}#titre h1, #titre h2{padding-left:1em;padding-right:1em}#bottom{clear:right;margin-right:0px;padding:1.5em;line-height:1.5em;color:#224d58;margin-top:2em;text-align:center}#bottom a{color:#113c47}#bottom a:hover{color:#cb4b16}#sousliens{padding:1em 0;line-height:2em}#sousliens ul{list-style:none;margin-left:4em}ul.horizontal li{display:inline;font-size:0.9em}ul.horizontal{margin-top:0px;margin-bottom:0px}#entete{padding-top:0.1em;border-top:1px solid #ccccd0;border-bottom:1px solid #ccccd0}#liens{width:100%;padding:0;clear:both;margin-top:0.5em}#liens ul{width:100%;clear:both;padding:0;margin:0}#liens ul li{display:inline-block;height:4em;margin-left:0.2em;margin-right:0.2em;width:23%}#liens ul li a, #liens ul li span{width:100%;display:block;line-height:4em}.clear{clear:both}#content{line-height:2em;margin-left:auto;margin-right:auto;margin-top:0;position:relative;clear:both;width:100%;max-width:47em}@media only screen and (max-width:45em){#content{padding:0;width:100%}#content img{max-width:80%}#content .corps{padding:0 1em}}.encadre, .black, .intro, .resume, .shadow{padding:2em;margin-top:2em;margin-bottom:2em}.encadre, .black, .shadow{color:#002b36;border:#ccccd0 solid 1px;border-radius:5px;box-shadow:0 0 2px #ccccd0 inset;background-color:#eeeef1}.encadre a, .black a, .shadow a{color:#666677}.encadre a:hover, .black a:hover, .shadow a:hover{color:#cb4b16}.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, .shadow a:hover strong, .shadow a:hover b, .shadow a:hover i, .shadow a:hover em, .shadow a:hover .nicer{color:#ffb17c}.encadre hr, .black hr, .shadow hr{color:#666677;border-top:1px solid #666677}.encadre strong, .encadre b, .encadre i, .encadre em, .black strong, .black b, .black i, .black em, .shadow strong, .shadow b, .shadow i, .shadow em{color:#002b36}.intro, .resume{font-size:0.9em;font-style:italic;padding:0.5em 1em;color:#555566}.intro a:hover, .resume a:hover{color:#cb4b16}.intro i, .intro em, .resume i, .resume em{font-weight:normal;font-style:normal;color:#002b36}.intro strong, .intro b, .resume strong, .resume b{font-weight:bold;color:#002b36}#afterheader > h1{width:100%;padding-top:1.5em;text-align:left}#afterheader{padding-left:0em;padding-right:0em}#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-size:1.25em;line-height:1.5em;text-align:justify;padding:3em 3em;margin:0;clear:both}.corps p, .corps ol, .corps ul, .corps blockquote, .corps pre, .corps code{margin-top:1.5em;margin-bottom:1.5em}.corps pre code{margin:0}.corps p, .corps ol, .corps ul, .corps blockquote{line-height:1.5em}.corps ul li ul, .corps ol li ul, .corps ul li ol, .corps ol li ol{margin-top:0;margin-bottom:0}.corps img{max-width:80%;border:1px solid #ccccd0;background-color:#fafafc;padding:0.5em;box-shadow:0 10px 15px #cccccc;border-radius:3px}.corps a:hover img{background-color:#dc3a05}figure, .figure{margin:3em 0}figure img, .figure img{box-shadow:0 10px 15px #cccccc inset}figure figcaption, figure .caption, .figure figcaption, .figure .caption{text-align:center;margin:0.5em 0}figure.left, figure.right, .figure.right, .figure.left{max-width:30%}img.clean{border:none;background-color:none;box-shadow:none}#address{clear:both}.definitionCell{width:5em;vertical-align:top;text-align:center;font-weight:bold}.valueCell{text-align:right}.smallblock{float:left;width:50%;font-size:1em;font-weight:bold}.largeblock{float:right;width:70%;font-size:1em}#blackpage, #nojsredirect{top:0;left:0;width:100%;min-height:100%;margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;position:absolute;text-align:center}#blackpage{color:#002b36;background-color:#fafafc;font-family:Georgia, serif;font-style:italic;padding-top:8em;z-index:9000;cursor:wait}#blackpage .corps code, #blackpage .corps pre{font-family:monospace}#blackpage img{background:none;border:none;max-width:80%;margin:0 auto}#blackpage a{cursor:pointer}#blackpage .preh1{font-size:1.5em;font-weight:bold;margin-bottom:1em}#blackpage .preh2{font-size:1.2em;font-style:italic;margin-bottom:1em}#blackpage .preintro{text-align:left;width:47em;margin:0 auto}#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}.codefile{font-size:0.8em;text-align:right;padding-right:1em;margin-right:0.1;margin-bottom:-1em}.flush{clear:both}table.description{border-spacing:5px;border-collapse:separate;margin-right:auto;margin-left:auto}table.description tr td{padding-left:0.5em;padding-right:0.5em;padding-top:0.5ex;padding-bottom:0.5ex;vertical-align:middle;margin-right:5px}ul.long li{margin-bottom:1em}img{display:block;margin:1.2em auto;background:none;border:none}img.right{max-width:30%;margin-top:0.6em;margin-left:2em}img.left{float:left;max-width:30%;margin-top:0.6em;margin-right:2em}img.inside{display:inline;vertical-align:middle}pre{overflow-x:auto;overflow-y:hidden}.impact, .darkimpact{text-align:left;width:66%;padding-left:0.25em;padding-right:0.25em}table.impact{text-align:left}table.impact tr td{padding-left:0.25em;padding-right:0.25em}#liens{font-size:1.2em}#iemessage{font-size:1.2em;color:#cccccc;margin:-10px;padding:1px 0;background:#333333}#iemessage strong, #iemessage b, #iemessage i, #iemessage em{color:#cccccc}#iemessage a, #iemessage a:visited{color:#eeccaa}.tagname{display:inline;cursor:pointer;margin-left:0.5em;margin-right:0.5em}.list{margin-top:3em}#menuMessage{font-size:1.2em;line-height:1.5em;width:100%;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:#888899;font-size:0.8em;font-style:italic}#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}.corps .return a{color:#eeeef1;padding:0.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:#eeeef1;padding:0.1em;line-height:1.5em;font-size:1.5em;height:1.5em;font-size:2em;width:1.5em;display:block}a.return:hover{color:#888899}.corps .return a:hover{color:#cb4b16}.footnotes{font-size:0.8em}.footnotes ol{color:#839496;font-weight:bold}.footnotes ol p{color:#002b36;font-weight:normal;font-style:normal}.fontnotes ol{margin-left:0}.typeset img{display:inline;border:none;margin:0;padding:0}strong, b, i, em{color:#888899}strong a, b a, i a, em a{color:#002b36}strong a:hover, b a:hover, i a:hover, em a:hover{color:#cb4b16}.corps p strong, .corps p b, .corps p i, .corps p em{color:#555566}a:hover strong, a:hover b, a:hover i, a:hover em{color:#dc5c27}a:hover .nicer{color:#ffb17c}.nicer{color:#ccccd0;font-family:"Lucida Grande", Tahoma}.block{border:solid 1px #ccccd0;border-radius:2px;box-shadow:0 0 4px #f2f2f4 inset;background-color:#f8f8fa;width:26.5%;padding:1em;border-radius:2px;text-align:left;line-height:1em;margin-left:1%;margin-right:1%;font-size:0.8em;height:9em}.block ul{margin-left:0}.block a{color:#002b36}.block a:hover{color:#cb4b16}.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:#555566}.corps p a:hover, .corps ul a:hover{color:#cb4b16}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}#tagcloud{font-size:0.8em;background:#f2f2f4;box-shadow:0 0 6px #ccccd0;border-radius:3px;line-height:2.5em;padding:2em;text-align:justify}.pala{font-family:Palatino}sup{vertical-align:top;font-size:0.7em}.article .corps a:after{content:"†";vertical-align:super;line-height:0;font-size:0.66em;color:#888899}.article .corps .nostar a:after{content:""}.article .corps .footnotes a:after, .article .corps sup a:after{content:""}.article .corps sup a{font-weight:bold;padding:0 0.3em;margin-left:2px;border-radius:3px;-moz-border-radius:3px;-webkit-border-radius:3px}.article .corps sup a:hover{color:#cb4b16}ul#markdown-toc, .intro .toc ul{text-transform:uppercase;font-size:0.8em;list-style:none;padding-left:1.5em}ul#markdown-toc a:after, .intro .toc ul a:after{content:""}ul#markdown-toc ul ul, .intro .toc ul ul ul{font-variant:normal;line-height:1em;font-size:1em;margin-bottom:1em}table{border:1px solid #ccccd0}table tr td{padding:2px 0.5em}table tr:nth-child(odd){background-color:#f2f2f4}table tr:nth-child(even){background-color:#fafafc}p pre code, ul li pre code, ol li pre code{background:none;border:none;padding:0}p code, ul li code, ol li code{background:#f0f0f2;border:solid 1px #ccccd0;padding:2px}ul.sameline{list-style:none}ul.sameline li{float:left;margin-left:0.5em}.resumearticle{background-color:#f2f2f4;border-radius:7px;box-shadow:0 0 5px #c7c7b8 inset, 0 0 5px white;margin:1em 0;padding:1em}a.cut{font-size:12px;text-align:right;display:block;width:100%;opacity:0.5;border:1px solid #fafafc;border-radius:3px}a.cut:hover{opacity:1;background-color:#f2f2f4;border-color:#ccccd0;box-shadow:0 0 3px #ccccd0 inset}a.cut strong{font-weight:bold}.codehighlight pre{border-left:4px solid #ccccd0}#social{font-size:2em;text-align:center;opacity:0.3}#social .message{font-size:10px}#social:hover{opacity:1}.popularblock{width:30.3333%;margin:0 1.5%;float:left}.popularblock figure{margin:0}.popularblock figure img{max-width:80%;max-height:6em}.inlineblockimg{width:48px;margin:8px;text-align:center;vertical-align:middle;display:inline-block;line-height:0.8em;overflow:hidden;border:solid 1px}img.inlineimage{padding:0;max-height:48px;max-width:48px;border:none;box-shadow:none;margin:0 auto;vertical-align:middle;font-size:7px;font-family:Helvetica, sans-serif;overflow:hidden}section.slide{border-color:#ccccd0;border:solid 1px;margin-bottom:1em;padding:0.5em;font-family:sans-serif;font-size:0.8em;min-height:25em}a.rss{background-color:#f8f8f8;background-image:-moz-linear-gradient(center top, white, #dedede);border:1px solid #cccccc;border-radius:3px 3px 3px 3px;color:#cb4b16;cursor:pointer;display:inline-block;font-size:13px;font-weight:bold;height:20px;font-family:sans-serif;line-height:20px;overflow:hidden;padding:0 5px;position:relative;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5)}a.rss:hover{background-image:-moz-linear-gradient(center top, white, #f3f3f3)}.base03{color:#002b36}.base02{color:#073642}.base01{color:#586e75}.base00{color:#657b83}.base0{color:#839496}.base1{color:#93a1a1}.base2{color:#eee8d5}.base3{color:#fdf6e3}.yellow{color:#b58900}.orange{color:#cb4b16}.red{color:#dc322f}.magenta{color:#d33682}.violet{color:#6c71c4}.blue{color:#268bd2}.cyan{color:#2aa198}.green{color:#859900}#header{opacity:0.25}#header:hover{opacity:1} \ No newline at end of file diff --git a/Scratch/en/about/old/index.html b/Scratch/en/about/old/index.html index 3fe1855..1413b01 100644 --- a/Scratch/en/about/old/index.html +++ b/Scratch/en/about/old/index.html @@ -60,7 +60,7 @@ diff --git a/Scratch/en/blog/01_nanoc/index.html b/Scratch/en/blog/01_nanoc/index.html index ade86c7..a739b7f 100644 --- a/Scratch/en/blog/01_nanoc/index.html +++ b/Scratch/en/blog/01_nanoc/index.html @@ -32,16 +32,8 @@ document.write('
Change Theme
'); // +
↓ Menu ↓
- - @@ -49,7 +41,7 @@

Nanoc

-
+

What is nanoc?

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

@@ -59,25 +51,26 @@
- - RSS - - - - - - -
- -
-
+ + · + + · + + · + +
+ These social sharing links preserve your privacy
+ +

Comments

@@ -95,6 +88,7 @@ comments powered by Disqus
+
Published on 2008-10-10 diff --git a/Scratch/en/blog/02_ackgrep/index.html b/Scratch/en/blog/02_ackgrep/index.html index 78c287f..ec21d2f 100644 --- a/Scratch/en/blog/02_ackgrep/index.html +++ b/Scratch/en/blog/02_ackgrep/index.html @@ -32,16 +32,8 @@ document.write(''); // +
-
-
@@ -49,7 +41,7 @@

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.

@@ -74,25 +66,26 @@ listeFic=( /(.) ) autoload zargs zargs – $listeFic – grep $1 |
- - RSS - - - - - - -
- -
-
+ + · + + · + + · + +
+ These social sharing links preserve your privacy
+ +

Comments

@@ -110,6 +103,7 @@ listeFic=( /(.) ) autoload zargs zargs – $listeFic – grep $1 | comments powered by Disqus
+
Published on 2009-07-22 diff --git a/Scratch/en/blog/03_losthighway/index.html b/Scratch/en/blog/03_losthighway/index.html index 5c445d5..a485444 100644 --- a/Scratch/en/blog/03_losthighway/index.html +++ b/Scratch/en/blog/03_losthighway/index.html @@ -33,16 +33,8 @@ document.write(''); // +
-
-
@@ -50,7 +42,7 @@

A try to demystify 'Lost Highway'

-
+

Lost Highway

@@ -131,25 +123,26 @@
- - RSS - - - - - - -
- -
-
+ + · + + · + + · + +
+ These social sharing links preserve your privacy
+ +

Comments

@@ -167,6 +160,7 @@ comments powered by Disqus
+
Published on 2009-08-04 diff --git a/Scratch/en/blog/04_drm/index.html b/Scratch/en/blog/04_drm/index.html index b32a200..c5730e2 100644 --- a/Scratch/en/blog/04_drm/index.html +++ b/Scratch/en/blog/04_drm/index.html @@ -33,16 +33,8 @@ document.write(''); // +
-
-
@@ -50,7 +42,7 @@

DRM are EVIL

-
+

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.

@@ -70,25 +62,26 @@
- - RSS - - - - - - -
- -
-
+ + · + + · + + · + +
+ These social sharing links preserve your privacy
+ +

Comments

@@ -106,6 +99,7 @@ comments powered by Disqus
+
Published on 2009-08-15 diff --git a/Scratch/en/blog/05_git_create_remote_branch/index.html b/Scratch/en/blog/05_git_create_remote_branch/index.html index 9e8bf73..5c72e2d 100644 --- a/Scratch/en/blog/05_git_create_remote_branch/index.html +++ b/Scratch/en/blog/05_git_create_remote_branch/index.html @@ -33,16 +33,8 @@ document.write(''); // +
-
-
@@ -50,7 +42,7 @@

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.

@@ -66,25 +58,26 @@ branch=1gitbr
- - RSS - - - - - - -
- -
-
+ + · + + · + + · + +
+ These social sharing links preserve your privacy
+ +

Comments

@@ -102,6 +95,7 @@ branch=1gitbrPlease enable JavaScript to view the comments powered by Disqus. comments powered by Disqus
+
Published on 2009-08-17 diff --git a/Scratch/en/blog/06_How_I_use_git/index.html b/Scratch/en/blog/06_How_I_use_git/index.html index d7d591c..a6b0f7d 100644 --- a/Scratch/en/blog/06_How_I_use_git/index.html +++ b/Scratch/en/blog/06_How_I_use_git/index.html @@ -33,16 +33,8 @@ document.write(''); // +
-
-
@@ -50,7 +42,7 @@

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.

@@ -175,25 +167,26 @@ done
- - RSS - - - - - - -
- -
-
+ + · + + · + + · + +
+ These social sharing links preserve your privacy
+ +

Comments

@@ -211,6 +204,7 @@ done comments powered by Disqus
+
Published on 2009-08-18 diff --git a/Scratch/en/blog/07_Screensaver_compilation_option_for_Snow_Leopard/index.html b/Scratch/en/blog/07_Screensaver_compilation_option_for_Snow_Leopard/index.html index ecc6965..b51edbe 100644 --- a/Scratch/en/blog/07_Screensaver_compilation_option_for_Snow_Leopard/index.html +++ b/Scratch/en/blog/07_Screensaver_compilation_option_for_Snow_Leopard/index.html @@ -33,16 +33,8 @@ document.write(''); // +
-
-
@@ -50,7 +42,7 @@

Screensaver compilation option for Snow Leopard©

-
+

How to recompile your screensaver to be Snow Leopard(c) compatible

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

@@ -61,25 +53,26 @@
- - RSS - - - - - - -
- -
-
+ + · + + · + + · + +
+ These social sharing links preserve your privacy
+ +

Comments

@@ -97,6 +90,7 @@ comments powered by Disqus
+
Published on 2009-09-06 diff --git a/Scratch/en/blog/08_Configure_ssh_to_listen_the_port_443_on_Snow_Leopard/index.html b/Scratch/en/blog/08_Configure_ssh_to_listen_the_port_443_on_Snow_Leopard/index.html index 6bdbe4b..d8a3fb5 100644 --- a/Scratch/en/blog/08_Configure_ssh_to_listen_the_port_443_on_Snow_Leopard/index.html +++ b/Scratch/en/blog/08_Configure_ssh_to_listen_the_port_443_on_Snow_Leopard/index.html @@ -33,16 +33,8 @@ document.write(''); // +
-
-
@@ -50,7 +42,7 @@

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.

@@ -112,25 +104,26 @@
- - RSS - - - - - - -
- -
-
+ + · + + · + + · + +
+ These social sharing links preserve your privacy
+ +

Comments

@@ -148,6 +141,7 @@ comments powered by Disqus
+
Published on 2009-09-07 diff --git a/Scratch/en/blog/09_Why_I_didn-t_keep_whosamung-us/index.html b/Scratch/en/blog/09_Why_I_didn-t_keep_whosamung-us/index.html index 0b11b60..13c88f5 100644 --- a/Scratch/en/blog/09_Why_I_didn-t_keep_whosamung-us/index.html +++ b/Scratch/en/blog/09_Why_I_didn-t_keep_whosamung-us/index.html @@ -33,16 +33,8 @@ document.write(''); // +
-
-
@@ -50,7 +42,7 @@

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.

@@ -66,25 +58,26 @@ Google Analytics > Who’s Amung Us
- - RSS - - - - - - -
- -
-
+ + · + + · + + · + +
+ These social sharing links preserve your privacy
+ +

Comments

@@ -102,6 +95,7 @@ Google Analytics > Who’s Amung Us comments powered by Disqus
+
Published on 2009-09-11 diff --git a/Scratch/en/blog/10_Synchronize_Custom_WebSite_with_mobileMe/index.html b/Scratch/en/blog/10_Synchronize_Custom_WebSite_with_mobileMe/index.html index 0aa4525..ce98235 100644 --- a/Scratch/en/blog/10_Synchronize_Custom_WebSite_with_mobileMe/index.html +++ b/Scratch/en/blog/10_Synchronize_Custom_WebSite_with_mobileMe/index.html @@ -33,16 +33,8 @@ document.write(''); // +
-
-
@@ -50,7 +42,7 @@

Synchronize Custom WebSite with mobileMe

-
+

Update (2012/01/11)

iDisk should soon disapear. This entry is mainly obsolescent now.

@@ -284,25 +276,26 @@ print -P -- " Publish terminated"
- - RSS - - - - - - -
- -
-
+ + · + + · + + · + +
+ These social sharing links preserve your privacy
+ +

Comments

@@ -320,6 +313,7 @@ print -P -- " Publish terminated" comments powered by Disqus
+
Published on 2009-09-11 diff --git a/Scratch/en/blog/11_Load_Disqus_Asynchronously/index.html b/Scratch/en/blog/11_Load_Disqus_Asynchronously/index.html index a4d662c..e32b2da 100644 --- a/Scratch/en/blog/11_Load_Disqus_Asynchronously/index.html +++ b/Scratch/en/blog/11_Load_Disqus_Asynchronously/index.html @@ -33,16 +33,8 @@ document.write(''); // +
-
-
@@ -50,7 +42,7 @@

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.

@@ -73,14 +65,14 @@

Javascript

replace:

-
<script type="text/javascript" src="http://disqus.com/forums/YOUR_DISQUS_ID/embed.js"></script>
+
<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");
+
window.disqus_no_style=true;
+$(document).ready(function(){
+    $.getScript("http://disqus.com/forums/YOUR_DISQUS_ID/embed.js");
 });
@@ -92,25 +84,26 @@ $(document).ready( - - RSS - - - - - - -
- -
-
+ + · + + · + + · + +
+ These social sharing links preserve your privacy
+ +

Comments

@@ -128,6 +121,7 @@ $(document).ready(comments powered by Disqus. comments powered by Disqus
+
Published on 2009-09-17 diff --git a/Scratch/en/blog/2009-09-Disqus-versus-Intense-Debate--Why-I-switched-/index.html b/Scratch/en/blog/2009-09-Disqus-versus-Intense-Debate--Why-I-switched-/index.html index 0ce639c..ce06e18 100644 --- a/Scratch/en/blog/2009-09-Disqus-versus-Intense-Debate--Why-I-switched-/index.html +++ b/Scratch/en/blog/2009-09-Disqus-versus-Intense-Debate--Why-I-switched-/index.html @@ -33,16 +33,8 @@ document.write(''); // +
-
-
@@ -50,7 +42,7 @@

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.

@@ -59,13 +51,13 @@

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);
+
document.getElementsByTagName("head")[0].appendChild(commentScript);

by:

-
$(document).ready( function() {
-    document.getElementsByTagName("head")[0].appendChild(commentScript);
+
$(document).ready( function() {
+    document.getElementsByTagName("head")[0].appendChild(commentScript);
 });
@@ -79,25 +71,26 @@
- - RSS - - - - - - -
- -
-
+ + · + + · + + · + +
+ These social sharing links preserve your privacy
+ +

Comments

@@ -115,6 +108,7 @@ comments powered by Disqus
+
Published on 2009-09-28 diff --git a/Scratch/en/blog/2009-09-jQuery-Tag-Cloud/index.html b/Scratch/en/blog/2009-09-jQuery-Tag-Cloud/index.html index ef86806..a6b9bda 100644 --- a/Scratch/en/blog/2009-09-jQuery-Tag-Cloud/index.html +++ b/Scratch/en/blog/2009-09-jQuery-Tag-Cloud/index.html @@ -33,16 +33,8 @@ document.write(''); // +
-
-
@@ -50,7 +42,7 @@

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.

@@ -64,12 +56,12 @@

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');
+
    $(document).ready( function(){$('.list').hide();} );
+    function tagSelected(id) {
+        $('.list').hide();
+        $('#'+id).fadeIn();
+        $('.tag.selected').removeClass('selected');
+        $('#tag_'+id).addClass('selected');
     }
@@ -248,25 +240,26 @@
- - RSS - - - - - - -
- -
-
+ + · + + · + + · + +
+ These social sharing links preserve your privacy
+ +

Comments

@@ -284,6 +277,7 @@ comments powered by Disqus
+
Published on 2009-09-23 diff --git a/Scratch/en/blog/2009-09-replace-all-except-some-part/index.html b/Scratch/en/blog/2009-09-replace-all-except-some-part/index.html index 761cc29..c025853 100644 --- a/Scratch/en/blog/2009-09-replace-all-except-some-part/index.html +++ b/Scratch/en/blog/2009-09-replace-all-except-some-part/index.html @@ -33,16 +33,8 @@ document.write(''); // +
-
-
@@ -50,7 +42,7 @@

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

@@ -123,25 +115,26 @@ allExceptCode(:filter, content)
- - RSS - - - - - - -
- -
-
+ + · + + · + + · + +
+ These social sharing links preserve your privacy
+ +

Comments

@@ -159,6 +152,7 @@ allExceptCode(:filter, content) comments powered by Disqus
+
Published on 2009-09-22 diff --git a/Scratch/en/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/index.html b/Scratch/en/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/index.html index 272b301..e3c907c 100644 --- a/Scratch/en/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/index.html +++ b/Scratch/en/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/index.html @@ -33,16 +33,8 @@ document.write(''); // +
-
-
@@ -50,7 +42,7 @@

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.

@@ -128,25 +120,26 @@ if [[ “$1” = “-s” ]]; then swap else if [[ “$1” = “-d” ]]; then
- - RSS - - - - - - -
- -
-
+ + · + + · + + · + +
+ These social sharing links preserve your privacy
+ +

Comments

@@ -164,6 +157,7 @@ if [[ “$1” = “-s” ]]; then swap else if [[ “$1” = “-d” ]]; then comments powered by Disqus
+
Published on 2009-10-28 diff --git a/Scratch/en/blog/2009-10-30-How-to-handle-evil-IE/index.html b/Scratch/en/blog/2009-10-30-How-to-handle-evil-IE/index.html index 31af4d2..044cf5b 100644 --- a/Scratch/en/blog/2009-10-30-How-to-handle-evil-IE/index.html +++ b/Scratch/en/blog/2009-10-30-How-to-handle-evil-IE/index.html @@ -33,16 +33,8 @@ document.write(''); // +
-
-
@@ -50,7 +42,7 @@

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.

@@ -76,25 +68,26 @@
- - RSS - - - - - - -
- -
-
+ + · + + · + + · + +

+ These social sharing links preserve your privacy
+ +

Comments

@@ -112,6 +105,7 @@ comments powered by Disqus
+
Published on 2009-10-30 diff --git a/Scratch/en/blog/2009-10-Focus-vs-Minimalism/index.html b/Scratch/en/blog/2009-10-Focus-vs-Minimalism/index.html index 49baaf1..5d8924c 100644 --- a/Scratch/en/blog/2009-10-Focus-vs-Minimalism/index.html +++ b/Scratch/en/blog/2009-10-Focus-vs-Minimalism/index.html @@ -33,16 +33,8 @@ document.write(''); // +
-
-
@@ -50,7 +42,7 @@

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.

@@ -74,19 +66,19 @@ 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 hideMenu() {
+    $('#entete').animate({left:"-10em"}, 500 );
+    $('#menuButton').html('&rarr;');
 }
-function showMenu() {
-    $('#entete').animate({left:"0em"}, 500 );
-    $('#menuButton').html('&larr;');
+function showMenu() {
+    $('#entete').animate({left:"0em"}, 500 );
+    $('#menuButton').html('&larr;');
 }
-function toggleMenu() {
-    if ( $('#entete').css('left')=='-10em' ) {
-        showMenu();
+function toggleMenu() {
+    if ( $('#entete').css('left')=='-10em' ) {
+        showMenu();
     } else {
-        hideMenu();
+        hideMenu();
     }
 }
@@ -95,25 +87,26 @@ top: 5em; left: 0; position: fixed; width: 10em; z-index: 9000; } ~~~~~~
- - RSS - - - - - - -
- -
-
+ + · + + · + + · + +
+ These social sharing links preserve your privacy
+ +

Comments

@@ -131,6 +124,7 @@ top: 5em; left: 0; position: fixed; width: 10em; z-index: 9000; } ~~~~~~ comments powered by Disqus
+
Published on 2009-10-22 diff --git a/Scratch/en/blog/2009-10-How-to-preload-your-site-with-style/index.html b/Scratch/en/blog/2009-10-How-to-preload-your-site-with-style/index.html index 4ee41dd..34f133e 100644 --- a/Scratch/en/blog/2009-10-How-to-preload-your-site-with-style/index.html +++ b/Scratch/en/blog/2009-10-How-to-preload-your-site-with-style/index.html @@ -33,16 +33,8 @@ document.write(''); // +
-
-
@@ -50,7 +42,7 @@

How to preload your site with style

-
+

Example

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

@@ -114,8 +106,8 @@ Loading… and the associated jQuery code:

-
$(document).ready(function(){
-    $('#blackpage').fadeOut();
+
$(document).ready(function(){
+    $('#blackpage').fadeOut();
 });
@@ -124,25 +116,26 @@ Loading…
- - RSS - - - - - - -
- -
-
+ + · + + · + + · + +
+ These social sharing links preserve your privacy
+ +

Comments

@@ -160,6 +153,7 @@ Loading… Please enable JavaScript to view the comments powered by Disqus. comments powered by Disqus
+
Published on 2009-10-03 diff --git a/Scratch/en/blog/2009-10-Wait-to-hide-a-menu-in-jQuery/index.html b/Scratch/en/blog/2009-10-Wait-to-hide-a-menu-in-jQuery/index.html index 9942932..895f9c6 100644 --- a/Scratch/en/blog/2009-10-Wait-to-hide-a-menu-in-jQuery/index.html +++ b/Scratch/en/blog/2009-10-Wait-to-hide-a-menu-in-jQuery/index.html @@ -33,16 +33,8 @@ document.write(''); // +
-
-
@@ -50,7 +42,7 @@

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.

@@ -102,25 +94,26 @@ autoHideMenu(0);
- - RSS - - - - - - -
- -
-
+ + · + + · + + · + +
+ These social sharing links preserve your privacy
+ +

Comments

@@ -138,6 +131,7 @@ autoHideMenu(0);
comments powered by Disqus
+
Published on 2009-10-26 diff --git a/Scratch/en/blog/2009-10-launch-daemon-from-command-line/index.html b/Scratch/en/blog/2009-10-launch-daemon-from-command-line/index.html index 0c3f8c8..ca85343 100644 --- a/Scratch/en/blog/2009-10-launch-daemon-from-command-line/index.html +++ b/Scratch/en/blog/2009-10-launch-daemon-from-command-line/index.html @@ -33,16 +33,8 @@ document.write(''); // +
-
-
@@ -50,7 +42,7 @@

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:

@@ -62,25 +54,26 @@
- - RSS - - - - - - -
- -
-
+ + · + + · + + · + +
+ These social sharing links preserve your privacy
+ +

Comments

@@ -98,6 +91,7 @@ comments powered by Disqus
+
Published on 2009-10-23 diff --git a/Scratch/en/blog/2009-10-untaught-git-usage/index.html b/Scratch/en/blog/2009-10-untaught-git-usage/index.html index 778f709..d9b6149 100644 --- a/Scratch/en/blog/2009-10-untaught-git-usage/index.html +++ b/Scratch/en/blog/2009-10-untaught-git-usage/index.html @@ -33,16 +33,8 @@ document.write(''); // +
-
-
@@ -50,7 +42,7 @@

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.

@@ -190,25 +182,26 @@ OK
- - RSS - - - - - - -
- -
-
+ + · + + · + + · + +
+ These social sharing links preserve your privacy
+ +

Comments

@@ -226,6 +219,7 @@ OK comments powered by Disqus
+
Published on 2009-10-13 diff --git a/Scratch/en/blog/2009-11-12-Git-for-n00b/index.html b/Scratch/en/blog/2009-11-12-Git-for-n00b/index.html index bba079e..a0106e1 100644 --- a/Scratch/en/blog/2009-11-12-Git-for-n00b/index.html +++ b/Scratch/en/blog/2009-11-12-Git-for-n00b/index.html @@ -33,16 +33,8 @@ document.write(''); // +
-
-
@@ -50,7 +42,7 @@

Git for n00b

-
+
@@ -437,25 +429,26 @@ $ git logfull
- - RSS - - - - - - -
- -
-
+ + · + + · + + · + +
+ These social sharing links preserve your privacy
+ +

Comments

@@ -473,6 +466,7 @@ $ git logfull comments powered by Disqus
+
Published on 2009-11-12 diff --git a/Scratch/en/blog/2009-12-06-iphone-call-filter/index.html b/Scratch/en/blog/2009-12-06-iphone-call-filter/index.html index b8c6394..c310fa0 100644 --- a/Scratch/en/blog/2009-12-06-iphone-call-filter/index.html +++ b/Scratch/en/blog/2009-12-06-iphone-call-filter/index.html @@ -33,8 +33,32 @@ document.write(''); // +
+
+ +
+

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

+
+ +
+ + · + + · + + · + +
+ These social sharing links preserve your privacy +
-
- -
-

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

-
- -
- - RSS - - - - - - -
- -
-
-
+

Comments

@@ -93,6 +86,7 @@ comments powered by Disqus
+
Published on 2009-12-06 diff --git a/Scratch/en/blog/2009-12-14-Git-vs--Bzr/index.html b/Scratch/en/blog/2009-12-14-Git-vs--Bzr/index.html index 9caf384..a979793 100644 --- a/Scratch/en/blog/2009-12-14-Git-vs--Bzr/index.html +++ b/Scratch/en/blog/2009-12-14-Git-vs--Bzr/index.html @@ -33,16 +33,8 @@ document.write(''); // +
-
-
@@ -50,7 +42,7 @@

Git vs. Bzr

-
+
@@ -140,25 +132,26 @@
- - RSS - - - - - - -
- -
-
+ + · + + · + + · + +
+ These social sharing links preserve your privacy
+ +

Comments

@@ -176,6 +169,7 @@ comments powered by Disqus
+
Published on 2009-12-14 diff --git a/Scratch/en/blog/2010-01-04-Change-default-shell-on-Mac-OS-X/index.html b/Scratch/en/blog/2010-01-04-Change-default-shell-on-Mac-OS-X/index.html index 9f71d61..a3279c5 100644 --- a/Scratch/en/blog/2010-01-04-Change-default-shell-on-Mac-OS-X/index.html +++ b/Scratch/en/blog/2010-01-04-Change-default-shell-on-Mac-OS-X/index.html @@ -33,16 +33,8 @@ document.write(''); // +
-
-
@@ -50,7 +42,7 @@

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:

@@ -61,25 +53,26 @@
- - RSS - - - - - - -
- -
-
+ + · + + · + + · + +
+ These social sharing links preserve your privacy
+ +

Comments

@@ -97,6 +90,7 @@ comments powered by Disqus
+
Published on 2010-01-04 diff --git a/Scratch/en/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/index.html b/Scratch/en/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/index.html index eb8c71a..1ca17f1 100644 --- a/Scratch/en/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/index.html +++ b/Scratch/en/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/index.html @@ -33,16 +33,8 @@ document.write(''); // +
-
-
@@ -50,7 +42,7 @@

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:

@@ -115,25 +107,26 @@
- - RSS - - - - - - -
- -
-
+ + · + + · + + · + +
+ These social sharing links preserve your privacy
+ +

Comments

@@ -151,6 +144,7 @@ comments powered by Disqus
+
Published on 2010-01-12 diff --git a/Scratch/en/blog/2010-02-15-All-but-something-regexp/index.html b/Scratch/en/blog/2010-02-15-All-but-something-regexp/index.html index f29edd5..6a0fc58 100644 --- a/Scratch/en/blog/2010-02-15-All-but-something-regexp/index.html +++ b/Scratch/en/blog/2010-02-15-All-but-something-regexp/index.html @@ -33,16 +33,8 @@ document.write(''); // +
-
-
@@ -50,7 +42,7 @@

Pragmatic Regular Expression Exclude

-
+

Sometimes you cannot simply write:

@@ -88,25 +80,26 @@ Notice this method is not always the best. For example try to write a regular ex
- - RSS - - - - - - -
- -
-
+ + · + + · + + · + +
+ These social sharing links preserve your privacy
+ +

Comments

@@ -124,6 +117,7 @@ Notice this method is not always the best. For example try to write a regular ex comments powered by Disqus
+
Published on 2010-02-15 diff --git a/Scratch/en/blog/2010-02-16-All-but-something-regexp--2-/index.html b/Scratch/en/blog/2010-02-16-All-but-something-regexp--2-/index.html index b135273..64fe681 100644 --- a/Scratch/en/blog/2010-02-16-All-but-something-regexp--2-/index.html +++ b/Scratch/en/blog/2010-02-16-All-but-something-regexp--2-/index.html @@ -33,16 +33,8 @@ document.write(''); // +
-
-
@@ -50,7 +42,7 @@

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:

@@ -119,7 +111,7 @@ That string should not match. This is why if we really want to match it correctl
 

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 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/wasx_/g s/Y/wasy_/g

transform the long string in this simple character

s/
  • @@ -131,7 +123,7 @@ s/X/
  • /g s/Y/</li>/g

    retransform the choosen character back

    -s/was_x/X/g s/was_y/Y/g
    +s/wasx_/X/g s/wasy_/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.

    @@ -140,25 +132,26 @@ s/was_x/X/g s/was_y/Y/g
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -176,6 +169,7 @@ s/was_x/X/g s/was_y/Y/g comments powered by Disqus
    +
    Published on 2010-02-16 diff --git a/Scratch/en/blog/2010-02-18-split-a-file-by-keyword/index.html b/Scratch/en/blog/2010-02-18-split-a-file-by-keyword/index.html index 836fde6..460938f 100644 --- a/Scratch/en/blog/2010-02-18-split-a-file-by-keyword/index.html +++ b/Scratch/en/blog/2010-02-18-split-a-file-by-keyword/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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.

    @@ -71,25 +63,26 @@ Mon Dec 7 10:32:30 UTC 2009
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -107,6 +100,7 @@ Mon Dec 7 10:32:30 UTC 2009 comments powered by Disqus
    +
    Published on 2010-02-18 diff --git a/Scratch/en/blog/2010-02-23-When-regexp-is-not-the-best-solution/index.html b/Scratch/en/blog/2010-02-23-When-regexp-is-not-the-best-solution/index.html index 1c5b878..13b2d29 100644 --- a/Scratch/en/blog/2010-02-23-When-regexp-is-not-the-best-solution/index.html +++ b/Scratch/en/blog/2010-02-23-When-regexp-is-not-the-best-solution/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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:

    @@ -97,25 +89,26 @@ chomp: 0.820000 0.040000 0.860000 ( 0.947432)
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -133,6 +126,7 @@ chomp: 0.820000 0.040000 0.860000 ( 0.947432) comments powered by Disqus
    +
    Published on 2010-02-23 diff --git a/Scratch/en/blog/2010-03-22-Git-Tips/index.html b/Scratch/en/blog/2010-03-22-Git-Tips/index.html index 6c4c27c..0a8b5fc 100644 --- a/Scratch/en/blog/2010-03-22-Git-Tips/index.html +++ b/Scratch/en/blog/2010-03-22-Git-Tips/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Git Tips

    -
    +

    clone from github behind an evil firewall

    Standard:

    @@ -86,25 +78,26 @@ $ zsh $ cd project $ for br in (git
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -122,6 +115,7 @@ $ zsh $ cd project $ for br in (gitPlease enable JavaScript to view the comments powered by Disqus. comments powered by Disqus
    +
    Published on 2010-03-22 diff --git a/Scratch/en/blog/2010-03-23-Encapsulate-git/index.html b/Scratch/en/blog/2010-03-23-Encapsulate-git/index.html index 2fb5cb0..06a062a 100644 --- a/Scratch/en/blog/2010-03-23-Encapsulate-git/index.html +++ b/Scratch/en/blog/2010-03-23-Encapsulate-git/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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. @@ -108,25 +100,26 @@ case ARGV[0] when ‘allmerges’ then do_all_merges when ‘merge’ then do_me
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -144,6 +137,7 @@ case ARGV[0] when ‘allmerges’ then do_all_merges when ‘merge’ then do_me comments powered by Disqus
    +
    Published on 2010-03-23 diff --git a/Scratch/en/blog/2010-05-17-at-least-this-blog-revive/index.html b/Scratch/en/blog/2010-05-17-at-least-this-blog-revive/index.html index 6a55ba3..c1c44d1 100644 --- a/Scratch/en/blog/2010-05-17-at-least-this-blog-revive/index.html +++ b/Scratch/en/blog/2010-05-17-at-least-this-blog-revive/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    I live again!

    -
    +

    Hi all!

    @@ -76,25 +68,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -112,6 +105,7 @@ comments powered by Disqus
    +
    Published on 2010-05-17 diff --git a/Scratch/en/blog/2010-05-19-How-to-cut-HTML-and-repair-it/index.html b/Scratch/en/blog/2010-05-19-How-to-cut-HTML-and-repair-it/index.html index a5487c9..ee9e47d 100644 --- a/Scratch/en/blog/2010-05-19-How-to-cut-HTML-and-repair-it/index.html +++ b/Scratch/en/blog/2010-05-19-How-to-cut-HTML-and-repair-it/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    How to repair a cutted XML?

    -
    +

    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:

    @@ -121,25 +113,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -157,6 +150,7 @@ comments powered by Disqus
    +
    Published on 2010-05-19 diff --git a/Scratch/en/blog/2010-05-24-Trees--Pragmatism-and-Formalism/index.html b/Scratch/en/blog/2010-05-24-Trees--Pragmatism-and-Formalism/index.html index 30d1699..a827b93 100644 --- a/Scratch/en/blog/2010-05-24-Trees--Pragmatism-and-Formalism/index.html +++ b/Scratch/en/blog/2010-05-24-Trees--Pragmatism-and-Formalism/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Trees; Pragmatism and Formalism

    -
    +
    @@ -243,25 +235,26 @@ M - V - M - V - tag2 tag1
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -279,6 +272,7 @@ M - V - M - V - tag2 tag1 comments powered by Disqus
    +
    Published on 2010-05-24 diff --git a/Scratch/en/blog/2010-06-14-multi-language-choices/index.html b/Scratch/en/blog/2010-06-14-multi-language-choices/index.html index 4226037..165d585 100644 --- a/Scratch/en/blog/2010-06-14-multi-language-choices/index.html +++ b/Scratch/en/blog/2010-06-14-multi-language-choices/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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:

    @@ -84,25 +76,26 @@ here is an example of english text.
     				
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -120,6 +113,7 @@ here is an example of english text. comments powered by Disqus
    +
    Published on 2010-06-14 diff --git a/Scratch/en/blog/2010-06-15-Get-my-blog-engine/index.html b/Scratch/en/blog/2010-06-15-Get-my-blog-engine/index.html index 740cf51..182cb34 100644 --- a/Scratch/en/blog/2010-06-15-Get-my-blog-engine/index.html +++ b/Scratch/en/blog/2010-06-15-Get-my-blog-engine/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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?

    @@ -117,25 +109,26 @@ multi/blog/2010-06-01-the-title/third_part.md
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -153,6 +146,7 @@ multi/blog/2010-06-01-the-title/third_part.md comments powered by Disqus
    +
    Published on 2010-06-15 diff --git a/Scratch/en/blog/2010-06-17-hide-yourself-to-analytics/index.html b/Scratch/en/blog/2010-06-17-hide-yourself-to-analytics/index.html index b98ce55..d1dd21d 100644 --- a/Scratch/en/blog/2010-06-17-hide-yourself-to-analytics/index.html +++ b/Scratch/en/blog/2010-06-17-hide-yourself-to-analytics/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,16 +42,16 @@

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

    then create two html files. One to hide:

    <?xml version="1.0" encoding="utf-8"?>
    @@ -72,8 +64,8 @@
             <script type="text/javascript" src="jquery.cookie.js"></script>
             <script>
                 $(document).ready(function(){
    -                $.cookie('admin',1);
    -                $('#info').html('Analytics can no more see you.')
    +                $.cookie('admin',1);
    +                $('#info').html('Analytics can no more see you.')
                 });
             </script>
             <title>Hide to analytics</title>
    @@ -93,8 +85,8 @@
             <script type="text/javascript" src="jquery.cookie.js"></script>
             <script>
                 $(document).ready(function(){
    -                $.cookie('admin',null);
    -                $('#info').html('Analytics can see you.')
    +                $.cookie('admin',null);
    +                $('#info').html('Analytics can see you.')
                 });
             </script>
             <title>Hide to analytics</title>
    @@ -107,25 +99,26 @@
     				
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -143,6 +136,7 @@ comments powered by Disqus
    +
    Published on 2010-06-17 diff --git a/Scratch/en/blog/2010-06-17-track-events-with-google-analytics/index.html b/Scratch/en/blog/2010-06-17-track-events-with-google-analytics/index.html index c6a0882..fc73014 100644 --- a/Scratch/en/blog/2010-06-17-track-events-with-google-analytics/index.html +++ b/Scratch/en/blog/2010-06-17-track-events-with-google-analytics/index.html @@ -33,8 +33,84 @@ document.write(''); // +
    +
    + +
    +

    Track Events with Google Analytics

    +
    +
    +
    +
    +

    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:

    +

    +

    Happy tracking!

    +
    + +
    + + · + + · + + · + +
    + These social sharing links preserve your privacy +
    -
    - -
    -

    Track Events with Google Analytics

    -
    -
    -
    -
    -

    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:

    -

    -

    Happy tracking!

    -
    - -
    - - RSS - - - - - - -
    - -
    -
    -
    +

    Comments

    @@ -145,6 +138,7 @@ comments powered by Disqus
    +
    Published on 2010-06-17 diff --git a/Scratch/en/blog/2010-06-19-jQuery-popup-the-easy-way/index.html b/Scratch/en/blog/2010-06-19-jQuery-popup-the-easy-way/index.html index 073a354..2d62a0f 100644 --- a/Scratch/en/blog/2010-06-19-jQuery-popup-the-easy-way/index.html +++ b/Scratch/en/blog/2010-06-19-jQuery-popup-the-easy-way/index.html @@ -33,8 +33,56 @@ document.write(''); // +
    +
    + +
    +

    jQuery popup the easy way

    +
    +
    +
    +
    +

    Here is a fast and easy way to create jQuery popup.

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

    What does this code 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.

    +
    + +
    + + · + + · + + · + +
    + These social sharing links preserve your privacy +
    -
    - -
    -

    jQuery popup the easy way

    -
    -
    -
    -
    -

    Here is a fast and easy way to create jQuery popup.

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

    What does this code 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.

    -
    - -
    - - RSS - - - - - - -
    - -
    -
    -
    +

    Comments

    @@ -117,6 +110,7 @@ comments powered by Disqus
    +
    Published on 2010-06-19 diff --git a/Scratch/en/blog/2010-07-05-Cappuccino-and-Web-applications/index.html b/Scratch/en/blog/2010-07-05-Cappuccino-and-Web-applications/index.html index da69e68..841b5fc 100644 --- a/Scratch/en/blog/2010-07-05-Cappuccino-and-Web-applications/index.html +++ b/Scratch/en/blog/2010-07-05-Cappuccino-and-Web-applications/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Cappuccino vs jQuery

    -
    +
    @@ -146,25 +138,26 @@ hash=sha1( masterPassword + leakedTimes + domainName )
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -182,6 +175,7 @@ hash=sha1( masterPassword + leakedTimes + domainName ) comments powered by Disqus
    +
    Published on 2010-07-05 diff --git a/Scratch/en/blog/2010-07-07-CSS-rendering-problems-by-navigator/index.html b/Scratch/en/blog/2010-07-07-CSS-rendering-problems-by-navigator/index.html index d70af95..9a2de73 100644 --- a/Scratch/en/blog/2010-07-07-CSS-rendering-problems-by-navigator/index.html +++ b/Scratch/en/blog/2010-07-07-CSS-rendering-problems-by-navigator/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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:

      @@ -70,25 +62,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -106,6 +99,7 @@ comments powered by Disqus
    +
    Published on 2010-07-07 diff --git a/Scratch/en/blog/2010-07-09-Indecidabilities/index.html b/Scratch/en/blog/2010-07-09-Indecidabilities/index.html index 810b11f..649977d 100644 --- a/Scratch/en/blog/2010-07-09-Indecidabilities/index.html +++ b/Scratch/en/blog/2010-07-09-Indecidabilities/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Undecidabilities (part 1)

    -
    +

    <% # toremove_ %>

    @@ -145,25 +137,26 @@ Q(x) :
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -181,6 +174,7 @@ Q(x) : comments powered by Disqus
    +
    Published on 2010-08-11 diff --git a/Scratch/en/blog/2010-07-31-New-style-after-holidays/index.html b/Scratch/en/blog/2010-07-31-New-style-after-holidays/index.html index 6637ae8..2a19608 100644 --- a/Scratch/en/blog/2010-07-31-New-style-after-holidays/index.html +++ b/Scratch/en/blog/2010-07-31-New-style-after-holidays/index.html @@ -33,8 +33,32 @@ document.write(''); // +
    +
    + +
    +

    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(c) (the iPhone(c) application).

    +

    Tell me what you think of this new design.

    +
    + +
    + + · + + · + + · + +
    + These social sharing links preserve your privacy +
    -
    - -
    -

    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(c) (the iPhone(c) application).

    -

    Tell me what you think of this new design.

    -
    - -
    - - RSS - - - - - - -
    - -
    -
    -
    +

    Comments

    @@ -93,6 +86,7 @@ comments powered by Disqus
    +
    Published on 2010-07-31 diff --git a/Scratch/en/blog/2010-08-23-Now-heberged-on-heroku/index.html b/Scratch/en/blog/2010-08-23-Now-heberged-on-heroku/index.html index e3759ec..008520a 100644 --- a/Scratch/en/blog/2010-08-23-Now-heberged-on-heroku/index.html +++ b/Scratch/en/blog/2010-08-23-Now-heberged-on-heroku/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Now hosted by heroku

    -
    +

    Now on Heroku

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

    @@ -117,25 +109,26 @@ git push heroku master
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -153,6 +146,7 @@ git push heroku master
    comments powered by Disqus
    +
    Published on 2010-08-23 diff --git a/Scratch/en/blog/2010-08-31-send-mail-from-command-line-with-attached-file/index.html b/Scratch/en/blog/2010-08-31-send-mail-from-command-line-with-attached-file/index.html index b81e8ce..1fa0814 100644 --- a/Scratch/en/blog/2010-08-31-send-mail-from-command-line-with-attached-file/index.html +++ b/Scratch/en/blog/2010-08-31-send-mail-from-command-line-with-attached-file/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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

    @@ -94,38 +86,36 @@ H4sICB6Ke0wAA2Rjcl93aXRob3V0X2tleXdvcmQuY3N2ANSdW5ubOJPH7/e7 </div> <div id="social"> - <span> - <a class="rss" href="http://feeds.feedburner.com/yannespositocomen">RSS</a> - </span> - <span> - <a href="https://twitter.com/share" class="twitter-share-button" data-via="yogsototh">Tweet</a> - <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script> - </span> - <span> - <div class="g-plusone" data-size="medium" data-annotation="inline" data-width="106"></div> - <script type="text/javascript"> - (function() { - var po = document.createElement(" script'); po.type="text/javascript" ; po.async="true;" po.src="https://apis.google.com/js/plusone.js" ; var s="document.getElementsByTagName('script')[0];" s.parentNode.insertBefore(po, s); })(); < script> - -
    -
    -
    -

    Comments

    -
    - + var disqus_shortname = " yannesposito'; required: replace example with your forum shortname * * * DON'T EDIT BELOW THIS LINE * * * (function() { var dsq="document.createElement('script');" dsq.type="text/javascript" ; dsq.async="true;" dsq.src="http://" + disqus_shortname + '.disqus.com embed.js'; (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); })(); < script> comments powered by Disqus
    +
    Published on 2010-08-31 diff --git a/Scratch/en/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes/index.html b/Scratch/en/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes/index.html index f2fc6f9..fdfb22f 100644 --- a/Scratch/en/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes/index.html +++ b/Scratch/en/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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:

    @@ -73,25 +65,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -109,6 +102,7 @@ comments powered by Disqus
    +
    Published on 2010-09-02 diff --git a/Scratch/en/blog/2010-09-02-base64-and-sha1-on-iPhone/index.html b/Scratch/en/blog/2010-09-02-base64-and-sha1-on-iPhone/index.html index 853e30b..2dd616b 100644 --- a/Scratch/en/blog/2010-09-02-base64-and-sha1-on-iPhone/index.html +++ b/Scratch/en/blog/2010-09-02-base64-and-sha1-on-iPhone/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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:

    @@ -105,25 +97,26 @@ NSString *hex_hash = [self hex_sha1:@"some NSString to be sha1'ed"];
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -141,6 +134,7 @@ NSString *hex_hash = [self hex_sha1:@"some NSString to be sha1'ed"];Please enable JavaScript to view the comments powered by Disqus. comments powered by Disqus
    +
    Published on 2010-09-02 diff --git a/Scratch/en/blog/2010-10-06-New-Blog-Design-Constraints/index.html b/Scratch/en/blog/2010-10-06-New-Blog-Design-Constraints/index.html index 7ea85bd..df77dd4 100644 --- a/Scratch/en/blog/2010-10-06-New-Blog-Design-Constraints/index.html +++ b/Scratch/en/blog/2010-10-06-New-Blog-Design-Constraints/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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:

      @@ -62,25 +54,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -98,6 +91,7 @@ comments powered by Disqus
    +
    Published on 2010-10-06 diff --git a/Scratch/en/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/index.html b/Scratch/en/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/index.html index 953b0ef..a66deb4 100644 --- a/Scratch/en/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/index.html +++ b/Scratch/en/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Secure eMail on Mac in few steps

    -
    +

    Title image

    @@ -81,25 +73,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -117,6 +110,7 @@ comments powered by Disqus
    +
    Published on 2010-10-10 diff --git a/Scratch/en/blog/2010-10-14-Fun-with-wav/index.html b/Scratch/en/blog/2010-10-14-Fun-with-wav/index.html index afa0541..048d252 100644 --- a/Scratch/en/blog/2010-10-14-Fun-with-wav/index.html +++ b/Scratch/en/blog/2010-10-14-Fun-with-wav/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Fun with wav

    -
    +
    @@ -305,25 +297,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -341,6 +334,7 @@ comments powered by Disqus
    +
    Published on 2010-10-14 diff --git a/Scratch/en/blog/2010-10-26-LaTeX-like-macro-and-markdown/index.html b/Scratch/en/blog/2010-10-26-LaTeX-like-macro-and-markdown/index.html index 8c13ae8..b480103 100644 --- a/Scratch/en/blog/2010-10-26-LaTeX-like-macro-and-markdown/index.html +++ b/Scratch/en/blog/2010-10-26-LaTeX-like-macro-and-markdown/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    LaTeX like macro for markdown

    -
    +
    @@ -112,25 +104,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -148,6 +141,7 @@ comments powered by Disqus
    +
    Published on 2010-10-26 diff --git a/Scratch/en/blog/2011-01-03-Happy-New-Year/index.html b/Scratch/en/blog/2011-01-03-Happy-New-Year/index.html index 6fa3ce9..025d709 100644 --- a/Scratch/en/blog/2011-01-03-Happy-New-Year/index.html +++ b/Scratch/en/blog/2011-01-03-Happy-New-Year/index.html @@ -32,16 +32,8 @@ document.write(''); // +
    -
    -
    @@ -49,7 +41,7 @@

    Happy New Year

    -
    +

    Happy New Year!

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

    @@ -59,25 +51,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -95,6 +88,7 @@ comments powered by Disqus
    +
    Published on 2011-01-01 diff --git a/Scratch/en/blog/2011-01-03-Why-I-sadly-won-t-use-coffeescript/index.html b/Scratch/en/blog/2011-01-03-Why-I-sadly-won-t-use-coffeescript/index.html index 7aeb724..39676b6 100644 --- a/Scratch/en/blog/2011-01-03-Why-I-sadly-won-t-use-coffeescript/index.html +++ b/Scratch/en/blog/2011-01-03-Why-I-sadly-won-t-use-coffeescript/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Why I won't use CoffeeScript (sadly)

    -
    +

    Title image

    @@ -131,25 +123,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -167,6 +160,7 @@ comments powered by Disqus
    +
    Published on 2011-01-03 diff --git a/Scratch/en/blog/2011-04-20-Now-hosted-on-github/index.html b/Scratch/en/blog/2011-04-20-Now-hosted-on-github/index.html index e7f1b2c..e146ee0 100644 --- a/Scratch/en/blog/2011-04-20-Now-hosted-on-github/index.html +++ b/Scratch/en/blog/2011-04-20-Now-hosted-on-github/index.html @@ -32,8 +32,32 @@ document.write(''); // +
    +
    + +
    +

    Now hosted on github

    +
    +
    +
    +
    +

    Title image

    +

    I am now hosted on github.

    +
    + +
    + + · + + · + + · + +
    + These social sharing links preserve your privacy +
    -
    - -
    -

    Now hosted on github

    -
    -
    -
    -
    -

    Title image

    -

    I am now hosted on github.

    -
    - -
    - - RSS - - - - - - -
    - -
    -
    -
    +

    Comments

    @@ -92,6 +85,7 @@ comments powered by Disqus
    +
    Published on 2011-04-20 diff --git a/Scratch/en/blog/A-more-convenient-diff/index.html b/Scratch/en/blog/A-more-convenient-diff/index.html index 8ebf2d5..15b0bf3 100644 --- a/Scratch/en/blog/A-more-convenient-diff/index.html +++ b/Scratch/en/blog/A-more-convenient-diff/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    A more convenient diff

    -
    +

    Diff is a very useful tool. But it is not so easy to read for us, simple mortal.

    This is why, when you use git it will use a better formatting and colorize it.

    @@ -80,25 +72,26 @@ diff -u $* | colorize_diff
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -116,6 +109,7 @@ diff -u $* | colorize_diff comments powered by Disqus
    +
    Published on 2011-08-17 diff --git a/Scratch/en/blog/Category-Theory-Presentation/index.html b/Scratch/en/blog/Category-Theory-Presentation/index.html index 9de4a59..76bc946 100644 --- a/Scratch/en/blog/Category-Theory-Presentation/index.html +++ b/Scratch/en/blog/Category-Theory-Presentation/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Category Theory Presentation

    -
    +
    Cateogry of Hask's endofunctors @@ -1018,25 +1010,26 @@ depth = cata phi where
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -1054,6 +1047,7 @@ depth = cata phi where comments powered by Disqus
    +
    Published on 2012-12-12 diff --git a/Scratch/en/blog/Haskell-Mandelbrot/index.html b/Scratch/en/blog/Haskell-Mandelbrot/index.html index effe489..9ae2412 100644 --- a/Scratch/en/blog/Haskell-Mandelbrot/index.html +++ b/Scratch/en/blog/Haskell-Mandelbrot/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,14 +42,14 @@

    ASCII Haskell Mandelbrot

    -
    +

    Here is the obfuscated code:

    -
    a=27;b=79;c=C(-2.0,-1.0);d=C(1.0,1.0);e=C(-2.501,-1.003)
    +
    a=27;b=79;c=C(-2.0,-1.0);d=C(1.0,1.0);e=C(-2.501,-1.003)
     newtype C = C (Double,Double) deriving (Show,Eq)
    -instance Num C where C(x,y)*C(z,t)=C(z*x-y*t,y*z+x*t);C(x,y)+C(z,t)=C(x+z,y+t);abs(C(x,y))=C(sqrt(x*x+y*y),0.0)
    +instance Num C where C(x,y)*C(z,t)=C(z*x-y*t,y*z+x*t);C(x,y)+C(z,t)=C(x+z,y+t);abs(C(x,y))=C(sqrt(x*x+y*y),0.0)
     r(C(x,y))=x;i(C(x,y))=y
    -f c z 0=0;f c z n=if(r(abs(z))>2)then n else f c ((z*z)+c) (n-1)
    +f c z 0=0;f c z n=if(r(abs(z))>2)then n else f c ((z*z)+c) (n-1)
     h j k = map (\z->(f (C z) (C(0,0)) 32,(fst z>l - q/2))) [(x,y)|y<-[p,(p+((o-p)/a))..o],x<-[m,(m + q)..l]] where o=i k;p=i j;m=r j;l=r k;q=(l-m)/b
     u j k = concat $ map v $ h j k where v (i,p)=(" .,`'°\":;-+oO0123456789=!%*§&$@#"!!i):rst p;rst True="\n";rst False=""
     main = putStrLn $ im 0 where cl n (C (x,y))=let cs=(1.1**n-1) in C ((x+cs*(r e))/cs+1,(y+cs*(i e))/cs+1);bl n=cl n c;tr n=cl n d;im n=u (bl n) (tr n)++"\x1b[H\x1b[25A"++im (n+1)
    @@ -96,18 +88,18 @@ $$$$$$$$$$$$$$$$$$$$$$$$$$&&&&&&&&&&WWWW

    Here is the more readable version. I believe with this far more readable version, no more explanation is needed.

    nbvert = 30
     nbhor = 79
    -zoomfactor = 1.01
    -init_bottom_left = C (-2.0,-2.0)
    -init_top_right   = C (3.0,2.0)
    -interrest        = C (-1.713,-0.000)
    +zoomfactor = 1.01
    +init_bottom_left = C (-2.0,-2.0)
    +init_top_right   = C (3.0,2.0)
    +interrest        = C (-1.713,-0.000)
     
     newtype Complex = C (Float,Float) deriving (Show,Eq)
     instance Num Complex where
    -    fromInteger n     = C (fromIntegral n,0.0)
    +    fromInteger n     = C (fromIntegral n,0.0)
         C (x,y) * C (z,t) = C (z*x - y*t, y*z + x*t)
         C (x,y) + C (z,t) = C (x+z, y+t)
    -    abs (C (x,y))     = C (sqrt (x*x + y*y),0.0)
    -    signum (C (x,y))  = C (signum x , 0.0)
    +    abs (C (x,y))     = C (sqrt (x*x + y*y),0.0)
    +    signum (C (x,y))  = C (signum x , 0.0)
     
     real :: Complex -> Float
     real (C (x,y))    = x
    @@ -119,7 +111,7 @@ cabs = real.abs
     
     f :: Complex -> Complex -> Int -> Int
     f c z 0 = 0
    -f c z n = if (cabs z > 2) then n else f c ((z*z)+c) (n-1) 
    +f c z n = if (cabs z > 2) then n else f c ((z*z)+c) (n-1) 
     
     bmandel bottomleft topright = map (\z -> (f (C z) (C(0,0)) 32, (fst z > right - hstep/2 ))) [(x,y) | y <- [bottom,(bottom + vstep)..top], x<-[left,(left + hstep)..right]]
         where
    @@ -152,29 +144,30 @@ main = do
         putStrLn $ infinitemandel 0
         where
             window n = zoom init_bottom_left init_top_right interrest (zoomfactor**n) 
    -        infinitemandel n = mandel (window n) ++ "\x1b[H\x1b[25A" ++ infinitemandel (n+1)
    + infinitemandel n = mandel (window n) ++ "\x1b[H\x1b[25A" ++ infinitemandel (n+1)
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -192,6 +185,7 @@ main = do comments powered by Disqus
    +
    Published on 2011-07-10 diff --git a/Scratch/en/blog/Haskell-OpenGL-Mandelbrot/index.html b/Scratch/en/blog/Haskell-OpenGL-Mandelbrot/index.html index 956cac9..e87efe0 100644 --- a/Scratch/en/blog/Haskell-OpenGL-Mandelbrot/index.html +++ b/Scratch/en/blog/Haskell-OpenGL-Mandelbrot/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Haskell Progressive Example

    -
    +

    The B in Benoît B. Mandelbrot stand for Benoît B. Mandelbrot

    @@ -98,9 +90,9 @@ Another detail of the Mandelbulb

    We can consider two parts. The first being mostly some boilerplate2. And the second part more focused on OpenGL and content.

    Let’s play the song of our people

    -
    import Graphics.Rendering.OpenGL
    -import Graphics.UI.GLUT
    -import Data.IORef
    +
    import Graphics.Rendering.OpenGL
    +import Graphics.UI.GLUT
    +import Data.IORef

    For efficiency reason3, I will not use the default Haskell Complex data type.

    @@ -110,11 +102,11 @@ Another detail of the Mandelbulb
    instance Num Complex where
    -    fromInteger n = C (fromIntegral n,0.0)
    +    fromInteger n = C (fromIntegral n,0.0)
         C (x,y) * C (z,t) = C (z*x - y*t, y*z + x*t)
         C (x,y) + C (z,t) = C (x+z, y+t)
    -    abs (C (x,y))     = C (sqrt (x*x + y*y),0.0)
    -    signum (C (x,y))  = C (signum x , 0.0)
    + abs (C (x,y)) = C (sqrt (x*x + y*y),0.0) + signum (C (x,y)) = C (signum x , 0.0)

    We declare some useful functions for manipulating complex numbers:

    @@ -201,16 +193,16 @@ allPoints = [ (x/width,ycolorFromValue n = let t :: Int -> GLfloat - t i = 0.5 + 0.5*cos( fromIntegral i / 10 ) + t i = 0.5 + 0.5*cos( fromIntegral i / 10 ) in - Color3 (t n) (t (n+5)) (t (n+10)) + Color3 (t n) (t (n+5)) (t (n+10))

    And now the mandel function. Given two coordinates in pixels, it returns some integer value:

    mandel x y = 
    -  let r = 2.0 * x / width
    -      i = 2.0 * y / height
    +  let r = 2.0 * x / width
    +      i = 2.0 * y / height
       in
           f (complex r i) 0 64
    @@ -226,7 +218,7 @@ allPoints = [ (x/width,y0 = 0 f c z n = if (magnitude z > 2 ) then n - else f c ((z*z)+c) (n-1) + else f c ((z*z)+c) (n-1)

    Well, if you download this file (look at the bottom of this section), compile it and run it this is the result:

    @@ -242,20 +234,20 @@ f c z n = if (magnitude z
    -
    import Graphics.Rendering.OpenGL
    -import Graphics.UI.GLUT
    -import Data.IORef
    +
    import Graphics.Rendering.OpenGL
    +import Graphics.UI.GLUT
    +import Data.IORef
     -- Use UNPACK data because it is faster
     -- The ! is for strict instead of lazy
     data Complex = C  {-# UNPACK #-} !Float 
                       {-# UNPACK #-} !Float 
                    deriving (Show,Eq)
     instance Num Complex where
    -    fromInteger n = C (fromIntegral n) 0.0
    +    fromInteger n = C (fromIntegral n) 0.0
         (C x y) * (C z t) = C (z*x - y*t) (y*z + x*t)
         (C x y) + (C z t) = C (x+z) (y+t)
    -    abs (C x y)     = C (sqrt (x*x + y*y)) 0.0
    -    signum (C x y)  = C (signum x) 0.0
    +    abs (C x y)     = C (sqrt (x*x + y*y)) 0.0
    +    signum (C x y)  = C (signum x) 0.0
     complex :: Float -> Float -> Complex
     complex x y = C x y
     
    @@ -282,7 +274,7 @@ main = do
       mainLoop
     display = do
        -- set the background color (dark solarized theme)
    -  clearColor $= Color4 0 0.1686 0.2117 1
    +  clearColor $= Color4 0 0.1686 0.2117 1
       clear [ColorBuffer] -- make the window black
       loadIdentity -- reset any transformation
       preservingMatrix drawMandelbrot
    @@ -347,8 +339,8 @@ positivePoints = do
     maxZeroIndex func minval maxval 0 = (minval+maxval)/2
     maxZeroIndex func minval maxval n = 
       if (func medpoint) /= 0 
    -       then maxZeroIndex func minval medpoint (n-1)
    -       else maxZeroIndex func medpoint maxval (n-1)
    +       then maxZeroIndex func minval medpoint (n-1)
    +       else maxZeroIndex func medpoint maxval (n-1)
       where medpoint = (minval+maxval)/2
    @@ -360,15 +352,15 @@ maxZeroIndex func minval maxval n =
    colorFromValue n =
       let 
           t :: Int -> GLfloat
    -      t i = 0.5 + 0.5*cos( fromIntegral i / 10 )
    +      t i = 0.5 + 0.5*cos( fromIntegral i / 10 )
       in
    -    Color3 (t n) (t (n+5)) (t (n+10))
    + Color3 (t n) (t (n+5)) (t (n+10))
    mandel x y = 
    -  let r = 2.0 * x / width
    -      i = 2.0 * y / height
    +  let r = 2.0 * x / width
    +      i = 2.0 * y / height
       in
           f (complex r i) 0 64
    @@ -378,7 +370,7 @@ maxZeroIndex func minval maxval n = f c z 0 = 0 f c z n = if (magnitude z > 2 ) then n - else f c ((z*z)+c) (n-1) + else f c ((z*z)+c) (n-1)
    @@ -406,9 +398,9 @@ f c z n = if (magnitude z
    -
    import Graphics.Rendering.OpenGL
    -import Graphics.UI.GLUT
    -import Data.IORef
    +
    import Graphics.Rendering.OpenGL
    +import Graphics.UI.GLUT
    +import Data.IORef
     type ColoredPoint = (GLfloat,GLfloat,GLfloat,Color3 GLfloat)
    @@ -476,7 +468,7 @@ main = do -- Some state variables (I know it feels BAD) angle <- newIORef ((35,0)::(GLfloat,GLfloat)) zoom <- newIORef (2::GLfloat) - campos <- newIORef ((0.7,0)::(GLfloat,GLfloat)) + campos <- newIORef ((0.7,0)::(GLfloat,GLfloat)) -- Function to call each frame idleCallback $= Just idle -- Function to call when keyboard or mouse is used @@ -516,18 +508,18 @@ mapSnd f (x,y) = ( x,f y) z $= 1 -- zoom p $= (0,0) -- camera position -- use of hjkl to rotate - kact a _ _ (Char 'h') Down = modVar a (mapFst (+0.5)) - kact a _ _ (Char 'l') Down = modVar a (mapFst (+(-0.5))) - kact a _ _ (Char 'j') Down = modVar a (mapSnd (+0.5)) - kact a _ _ (Char 'k') Down = modVar a (mapSnd (+(-0.5))) + kact a _ _ (Char 'h') Down = modVar a (mapFst (+0.5)) + kact a _ _ (Char 'l') Down = modVar a (mapFst (+(-0.5))) + kact a _ _ (Char 'j') Down = modVar a (mapSnd (+0.5)) + kact a _ _ (Char 'k') Down = modVar a (mapSnd (+(-0.5))) -- use o and i to zoom - kact _ z _ (Char 'o') Down = modVar z (*1.1) - kact _ z _ (Char 'i') Down = modVar z (*0.9) + kact _ z _ (Char 'o') Down = modVar z (*1.1) + kact _ z _ (Char 'i') Down = modVar z (*0.9) -- use sdfe to move the camera - kact _ _ p (Char 's') Down = modVar p (mapFst (+0.1)) - kact _ _ p (Char 'f') Down = modVar p (mapFst (+(-0.1))) - kact _ _ p (Char 'd') Down = modVar p (mapSnd (+0.1)) - kact _ _ p (Char 'e') Down = modVar p (mapSnd (+(-0.1))) + kact _ _ p (Char 's') Down = modVar p (mapFst (+0.1)) + kact _ _ p (Char 'f') Down = modVar p (mapFst (+(-0.1))) + kact _ _ p (Char 'd') Down = modVar p (mapSnd (+0.1)) + kact _ _ p (Char 'e') Down = modVar p (mapSnd (+(-0.1))) -- any other keys does nothing kact _ _ _ _ _ = return ()
    @@ -536,7 +528,7 @@ mapSnd f (x,y) = ( x,f y)
    display angle zoom position = do
        -- set the background color (dark solarized theme)
    -  clearColor $= Color4 0 0.1686 0.2117 1
    +  clearColor $= Color4 0 0.1686 0.2117 1
       clear [ColorBuffer,DepthBuffer]
       -- Transformation to change the view
       loadIdentity -- reset any transformation
    @@ -548,8 +540,8 @@ mapSnd f (x,y) = (  x,f y)
    scale z z z -- rotate (xangle,yangle) <- get angle - rotate xangle $ Vector3 1.0 0.0 (0.0::GLfloat) - rotate yangle $ Vector3 0.0 1.0 (0.0::GLfloat) + rotate xangle $ Vector3 1.0 0.0 (0.0::GLfloat) + rotate yangle $ Vector3 0.0 1.0 (0.0::GLfloat) -- Now that all transformation were made -- We create the object(s) @@ -598,17 +590,17 @@ depthPoints = do depthOf x' y' = maxZeroIndex (mandel x' y') 0 deep logdeep logdeep = floor ((log deep) / log 2) z1 = depthOf x y - z2 = depthOf (x+1) y - z3 = depthOf (x+1) (y+1) - z4 = depthOf x (y+1) - c1 = mandel x y (z1+1) - c2 = mandel (x+1) y (z2+1) - c3 = mandel (x+1) (y+1) (z3+1) - c4 = mandel x (y+1) (z4+1) + z2 = depthOf (x+1) y + z3 = depthOf (x+1) (y+1) + z4 = depthOf x (y+1) + c1 = mandel x y (z1+1) + c2 = mandel (x+1) y (z2+1) + c3 = mandel (x+1) (y+1) (z3+1) + c4 = mandel x (y+1) (z4+1) p1 = ( x /width, y /height, z1/deep, colorFromValue c1) - p2 = ((x+1)/width, y /height, z2/deep, colorFromValue c2) - p3 = ((x+1)/width,(y+1)/height, z3/deep, colorFromValue c3) - p4 = ( x /width,(y+1)/height, z4/deep, colorFromValue c4) + p2 = ((x+1)/width, y /height, z2/deep, colorFromValue c2) + p3 = ((x+1)/width,(y+1)/height, z3/deep, colorFromValue c3) + p4 = ( x /width,(y+1)/height, z4/deep, colorFromValue c4) if (and $ map (>=57) [c1,c2,c3,c4]) then [] else [p1,p2,p3,p1,p3,p4] @@ -619,13 +611,13 @@ depthPoints = do x <- [-width..width] y <- [-height..height] let - neighbors = [(x,y),(x+1,y),(x+1,y+1),(x,y+1)] + neighbors = [(x,y),(x+1,y),(x+1,y+1),(x,y+1)] depthOf (u,v) = maxZeroIndex (mandel u v) 0 deep logdeep logdeep = floor ((log deep) / log 2) -- zs are 3D points with found depth zs = map (\(u,v) -> (u,v,depthOf (u,v))) neighbors -- ts are 3D pixels + mandel value - ts = map (\(u,v,w) -> (u,v,w,mandel u v (w+1))) zs + ts = map (\(u,v,w) -> (u,v,w,mandel u v (w+1))) zs -- ps are 3D opengl points + color value ps = map (\(u,v,w,c') -> (u/width,v/height,w/deep,colorFromValue c')) ts @@ -643,7 +635,7 @@ depthPoints = do allPoints = planPoints ++ map inverseDepth planPoints where planPoints = depthPoints - inverseDepth (x,y,z,c) = (x,y,-z+1/deep,c) + inverseDepth (x,y,z,c) = (x,y,-z+1/deep,c)

    The rest of the program is very close to the preceding one.

    @@ -663,8 +655,8 @@ allPoints = planPoints ++ 0 = (minval+maxval)/2 maxZeroIndex func minval maxval n = if (func medpoint) /= 0 - then maxZeroIndex func minval medpoint (n-1) - else maxZeroIndex func medpoint maxval (n-1) + then maxZeroIndex func minval medpoint (n-1) + else maxZeroIndex func medpoint maxval (n-1) where medpoint = (minval+maxval)/2
    @@ -673,9 +665,9 @@ maxZeroIndex func minval maxval n =
    colorFromValue n =
       let 
           t :: Int -> GLfloat
    -      t i = 0.7 + 0.3*cos( fromIntegral i / 10 )
    +      t i = 0.7 + 0.3*cos( fromIntegral i / 10 )
       in
    -    Color3 (t n) (t (n+5)) (t (n+10))
    + Color3 (t n) (t (n+5)) (t (n+10))

    We only changed from Complex to ExtComplex of the main f function.

    @@ -684,7 +676,7 @@ maxZeroIndex func minval maxval n = f c z 0 = 0 f c z n = if (magnitude z > 2 ) then n - else f c ((z*z)+c) (n-1) + else f c ((z*z)+c) (n-1)
    @@ -692,9 +684,9 @@ f c z n = if (magnitude z We simply add a new dimension to the mandel function and change the type signature of f from Complex to ExtComplex.

    mandel x y z = 
    -  let r = 2.0 * x / width
    -      i = 2.0 * y / height
    -      s = 2.0 * z / deep
    +  let r = 2.0 * x / width
    +      i = 2.0 * y / height
    +      s = 2.0 * z / deep
       in
           f (extcomplex r i s) 0 64
    @@ -712,8 +704,8 @@ f c z n = if (magnitude z ExtComplex, the extended complexes
    -
    import YBoiler -- Most the OpenGL Boilerplate
    -import Mandel -- The 3D Mandelbrot maths
    +
    import YBoiler -- Most the OpenGL Boilerplate
    +import Mandel -- The 3D Mandelbrot maths

    The yMainLoop takes two arguments: the title of the window and a function from time to triangles

    @@ -737,7 +729,7 @@ allPoints = planPoints ++ where planPoints = depthPoints ++ map inverseHeight depthPoints inverseHeight (x,y,z,c) = (x,-y,z,c) - inverseDepth (x,y,z,c) = (x,y,-z+1/deep,c) + inverseDepth (x,y,z,c) = (x,y,-z+1/deep,c)
    @@ -746,12 +738,12 @@ depthPoints = do x <- [-width..width] y <- [0..height] let - neighbors = [(x,y),(x+1,y),(x+1,y+1),(x,y+1)] + neighbors = [(x,y),(x+1,y),(x+1,y+1),(x,y+1)] depthOf (u,v) = maxZeroIndex (ymandel u v) 0 deep 7 -- zs are 3D points with found depth zs = map (\(u,v) -> (u,v,depthOf (u,v))) neighbors -- ts are 3D pixels + mandel value - ts = map (\(u,v,w) -> (u,v,w,ymandel u v (w+1))) zs + ts = map (\(u,v,w) -> (u,v,w,ymandel u v (w+1))) zs -- ps are 3D opengl points + color value ps = map (\(u,v,w,c') -> (u/width,v/height,w/deep,colorFromValue c')) ts @@ -772,16 +764,16 @@ depthPoints = do maxZeroIndex func minval maxval 0 = (minval+maxval)/2 maxZeroIndex func minval maxval n = if (func medpoint) /= 0 - then maxZeroIndex func minval medpoint (n-1) - else maxZeroIndex func medpoint maxval (n-1) + then maxZeroIndex func minval medpoint (n-1) + else maxZeroIndex func medpoint maxval (n-1) where medpoint = (minval+maxval)/2 colorFromValue n = let t :: Int -> GLfloat - t i = 0.7 + 0.3*cos( fromIntegral i / 10 ) + t i = 0.7 + 0.3*cos( fromIntegral i / 10 ) in - ((t n),(t (n+5)),(t (n+10))) + ((t n),(t (n+5)),(t (n+10))) ymandel x y z = mandel (2*x/width) (2*y/height) (2*z/deep) 64
    @@ -815,8 +807,8 @@ ymandel x y z = mandel (2

    Here is a real working code, I’ve hidden most display functions. The YGL, is a kind of framework to display 3D functions. But it can easily be extended to many kind of representation.

    -
    import YGL -- Most the OpenGL Boilerplate
    -import Mandel -- The 3D Mandelbrot maths
    +
    import YGL -- Most the OpenGL Boilerplate
    +import Mandel -- The 3D Mandelbrot maths

    We first set the mapping between user input and actions. The type of each couple should be of the form (user input, f) where (in a first time) f:World -> World. It means, the user input will transform the world state.

    @@ -830,16 +822,16 @@ inputActionMap = inputMapFromList [ ,(Press 'l' , rotate ydir (-5)) ,(Press 'o' , rotate zdir 5) ,(Press 'u' , rotate zdir (-5)) - ,(Press 'f' , translate xdir 0.1) - ,(Press 's' , translate xdir (-0.1)) - ,(Press 'e' , translate ydir 0.1) - ,(Press 'd' , translate ydir (-0.1)) - ,(Press 'z' , translate zdir 0.1) - ,(Press 'r' , translate zdir (-0.1)) - ,(Press '+' , zoom 1.1) - ,(Press '-' , zoom (1/1.1)) - ,(Press 'h' , resize 1.2) - ,(Press 'g' , resize (1/1.2)) + ,(Press 'f' , translate xdir 0.1) + ,(Press 's' , translate xdir (-0.1)) + ,(Press 'e' , translate ydir 0.1) + ,(Press 'd' , translate ydir (-0.1)) + ,(Press 'z' , translate zdir 0.1) + ,(Press 'r' , translate zdir (-0.1)) + ,(Press '+' , zoom 1.1) + ,(Press '-' , zoom (1/1.1)) + ,(Press 'h' , resize 1.2) + ,(Press 'g' , resize (1/1.2)) ]
    @@ -932,11 +924,11 @@ main = yMainLoop inputActionMap idleAction initialWorld< initialWorld = World { angle = makePoint3D (-30,-30,0) , position = makePoint3D (0,0,0) - , scale = 0.8 + , scale = 0.8 , shape = shapeFunc , box = Box3D { minPoint = makePoint3D (-2,-2,-2) , maxPoint = makePoint3D (2,2,2) - , resolution = 0.16 } + , resolution = 0.16 } , told = 0 }
    @@ -949,8 +941,8 @@ idleAction tnew world = world { , told = tnew } where - anglePerSec = 5.0 - delta = anglePerSec * elapsed / 1000.0 + anglePerSec = 5.0 + delta = anglePerSec * elapsed / 1000.0 elapsed = fromIntegral (tnew - (told world))
    @@ -962,7 +954,7 @@ shapeFunc res x y = let z = maxZeroIndex (ymandel x y) 0 1 20 in - if and [ maxZeroIndex (ymandel (x+xeps) (y+yeps)) 0 1 20 < 0.000001 | + if and [ maxZeroIndex (ymandel (x+xeps) (y+yeps)) 0 1 20 < 0.000001 | val <- [res], xeps <- [-val,val], yeps<-[-val,val]] then Nothing else Just (z,colorFromValue ((ymandel x y z) * 64)) @@ -974,9 +966,9 @@ shapeFunc res x y = colorFromValue n = let t :: Point -> Scalar - t i = 0.7 + 0.3*cos( i / 10 ) + t i = 0.7 + 0.3*cos( i / 10 ) in - makeColor (t n) (t (n+5)) (t (n+10)) + makeColor (t n) (t (n+5)) (t (n+10))

    The rest is similar to the preceding sections.

    @@ -994,8 +986,8 @@ colorFromValue n = maxZeroIndex _ minval maxval 0 = (minval+maxval)/2 maxZeroIndex func minval maxval n = if (func medpoint) /= 0 - then maxZeroIndex func minval medpoint (n-1) - else maxZeroIndex func medpoint maxval (n-1) + then maxZeroIndex func minval medpoint (n-1) + else maxZeroIndex func medpoint maxval (n-1) where medpoint = (minval+maxval)/2 ymandel :: Point -> Point -> Point -> Point @@ -1022,8 +1014,8 @@ ymandel x y z = fromIntegral (ma
    -
    import YGL -- Most the OpenGL Boilerplate
    -import Mandel -- The 3D Mandelbrot maths
    +
    import YGL -- Most the OpenGL Boilerplate
    +import Mandel -- The 3D Mandelbrot maths
     
     -- Centralize all user input interaction
     inputActionMap :: InputMap World
    @@ -1035,16 +1027,16 @@ inputActionMap = inputMapFromList [
         ,(Press 'l' , rotate ydir (-5))
         ,(Press 'o' , rotate zdir 5)
         ,(Press 'u' , rotate zdir (-5))
    -    ,(Press 'f' , translate xdir 0.1)
    -    ,(Press 's' , translate xdir (-0.1))
    -    ,(Press 'e' , translate ydir 0.1)
    -    ,(Press 'd' , translate ydir (-0.1))
    -    ,(Press 'z' , translate zdir 0.1)
    -    ,(Press 'r' , translate zdir (-0.1))
    -    ,(Press '+' , zoom 1.1)
    -    ,(Press '-' , zoom (1/1.1))
    -    ,(Press 'h' , resize 2.0)
    -    ,(Press 'g' , resize (1/2.0))
    +    ,(Press 'f' , translate xdir 0.1)
    +    ,(Press 's' , translate xdir (-0.1))
    +    ,(Press 'e' , translate ydir 0.1)
    +    ,(Press 'd' , translate ydir (-0.1))
    +    ,(Press 'z' , translate zdir 0.1)
    +    ,(Press 'r' , translate zdir (-0.1))
    +    ,(Press '+' , zoom 1.1)
    +    ,(Press '-' , zoom (1/1.1))
    +    ,(Press 'h' , resize 2.0)
    +    ,(Press 'g' , resize (1/2.0))
         ]
    @@ -1092,7 +1084,7 @@ rotate dir angleValue world = switchRotation :: World -> World switchRotation world = world { - anglePerSec = if anglePerSec world > 0 then 0 else 5.0 } + anglePerSec = if anglePerSec world > 0 then 0 else 5.0 } translate :: Point3D -> Scalar -> World -> World translate dir len world = @@ -1119,12 +1111,12 @@ main = yMainLoop inputActionMap idleAction initialWorld< initialWorld :: World initialWorld = World { angle = makePoint3D (30,30,0) - , anglePerSec = 5.0 + , anglePerSec = 5.0 , position = makePoint3D (0,0,0) - , scale = 1.0 + , scale = 1.0 , box = Box3D { minPoint = makePoint3D (0-eps, 0-eps, 0-eps) , maxPoint = makePoint3D (0+eps, 0+eps, 0+eps) - , resolution = 0.02 } + , resolution = 0.02 } , told = 0 -- We declare cache directly this time , cache = objectFunctionFromWorld initialWorld @@ -1168,7 +1160,7 @@ idleAction tnew world = , told = tnew } where - delta = anglePerSec world * elapsed / 1000.0 + delta = anglePerSec world * elapsed / 1000.0 elapsed = fromIntegral (tnew - (told world)) shapeFunc :: Scalar -> Function3D @@ -1176,7 +1168,7 @@ shapeFunc res x y = let z = maxZeroIndex (ymandel x y) 0 1 20 in - if and [ maxZeroIndex (ymandel (x+xeps) (y+yeps)) 0 1 20 < 0.000001 | + if and [ maxZeroIndex (ymandel (x+xeps) (y+yeps)) 0 1 20 < 0.000001 | val <- [res], xeps <- [-val,val], yeps<-[-val,val]] then Nothing else Just (z,colorFromValue 0) @@ -1185,9 +1177,9 @@ shapeFunc res x y = colorFromValue n = let t :: Point -> Scalar - t i = 0.0 + 0.5*cos( i /10 ) + t i = 0.0 + 0.5*cos( i /10 ) in - makeColor (t n) (t (n+5)) (t (n+10)) + makeColor (t n) (t (n+5)) (t (n+10)) -- given f min max nbtest, -- considering @@ -1202,8 +1194,8 @@ colorFromValue n = maxZeroIndex _ minval maxval 0 = (minval+maxval)/2 maxZeroIndex func minval maxval n = if func medpoint /= 0 - then maxZeroIndex func minval medpoint (n-1) - else maxZeroIndex func medpoint maxval (n-1) + then maxZeroIndex func minval medpoint (n-1) + else maxZeroIndex func medpoint maxval (n-1) where medpoint = (minval+maxval)/2 ymandel :: Point -> Point -> Point -> Point @@ -1237,25 +1229,26 @@ ymandel x y z = fromIntegral (ma
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -1273,6 +1266,7 @@ ymandel x y z = fromIntegral (ma comments powered by Disqus
    +
    Published on 2012-06-15 diff --git a/Scratch/en/blog/Haskell-the-Hard-Way/index.html b/Scratch/en/blog/Haskell-the-Hard-Way/index.html index 54d6a63..87f8a65 100644 --- a/Scratch/en/blog/Haskell-the-Hard-Way/index.html +++ b/Scratch/en/blog/Haskell-the-Hard-Way/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Learn Haskell Fast and Hard

    -
    +

    Magritte pleasure principle

    @@ -258,7 +250,7 @@ Function declaration return x*x + y*y; }

    In Javascript:

    -
    function f(x,y) {
    +
    function f(x,y) {
         return x*x + y*y;
     }

    in Python:

    @@ -298,7 +290,7 @@ main = print (f f :: Int -> Int -> Int f x y = x*x + y*y -main = print (f 2.3 4.2)
    +main = print (f 2.3 4.2)

    You get this error:

    21_very_basic.lhs:6:23:
    @@ -316,7 +308,7 @@ main = print (f 
     
    f x y = x*x + y*y
     
    -main = print (f 2.3 4.2)
    +main = print (f 2.3 4.2)

    It works! Great, we don’t have to declare a new function for every single type. For example, in C, you’ll have to declare a function for int, for float, for long, for double, etc…

    But, what type should we declare? To discover the type Haskell has found for us, just launch ghci:

    @@ -363,7 +355,7 @@ g y ⇔ 3*3 + y*y
    f :: Num a => a -> a -> a
     f x y = x*x + y*y
     
    -main = print (f 3 2.4)
    +main = print (f 3 2.4)

    It works, because, 3 is a valid representation both for Fractional numbers like Float and for Integer. As 2.4 is a Fractional number, 3 is then interpreted as being also a Fractional number.

    01_basic/10_Introduction/23_very_basic.lhs

    @@ -377,7 +369,7 @@ f x y = x*x +x :: Int x = 3 y :: Float -y = 2.4 +y = 2.4 main = print (f x y) -- won't work because type x ≠ type y

    The compiler complains. The two parameters must have the same type.

    @@ -566,9 +558,9 @@ Functional style

    example: [1,2,3,4,5] ⇒ 2 + 4 ⇒ 6

    To show differences between the functional and imperative approach, I’ll start by providing an imperative solution (in Javascript):

    -
    function evenSum(list) {
    +
    function evenSum(list) {
         var result = 0;
    -    for (var i=0; i< list.length ; i++) {
    +    for (var i=0; i< list.length ; i++) {
             if (list[i] % 2 ==0) {
                 result += list[i];
             }
    @@ -809,7 +801,7 @@ myfunc list = foldl bar initialVa
     
    -- Version 6
     -- foldl' isn't accessible by default
     -- we need to import it from the module Data.List
    -import Data.List
    +import Data.List
     evenSum l = foldl' mysum 0 (filter even l)
       where mysum acc value = acc + value

    Version we can simplify by using directly a lambda notation. This way we don’t have to create the temporary name mysum.

    @@ -817,7 +809,7 @@ evenSum l = foldl' mysum 0 (-- Version 7 -- Generally it is considered a good practice -- to import only the necessary function(s) -import Data.List (foldl') +import Data.List (foldl') evenSum l = foldl' (\x y -> x+y) 0 (filter even l)

    And of course, we note that

    @@ -834,7 +826,7 @@ evenSum l = foldl' (\x y -> x

    02_Hard_Part/16_Functions.lhs

    Finally

    -- Version 8
    -import Data.List (foldl')
    +import Data.List (foldl')
     evenSum :: Integral a => [a] -> a
     evenSum l = foldl' (+) 0 (filter even l)

    foldl' isn’t the easiest function to intuit. If you are not used to it, you should study it a bit.

    @@ -854,13 +846,13 @@ evenSum l = foldl' (+) (f . g . h) x ⇔ f ( g (h x))

    We can take advantage of this operator to η-reduce our function:

    -- Version 9
    -import Data.List (foldl')
    +import Data.List (foldl')
     evenSum :: Integral a => [a] -> a
     evenSum = (foldl' (+) 0) . (filter even)

    Also, we could rename some parts to make it clearer:

    -- Version 10 
    -import Data.List (foldl')
    +import Data.List (foldl')
     sum' :: (Num a) => [a] -> a
     sum' = foldl' (+) 0
     evenSum :: Integral a => [a] -> a
    @@ -1012,9 +1004,9 @@ main = putStrLn And many accessors are made for you. Furthermore you can use another order when setting values.

    Example:

    data Complex = Num a => Complex { real :: a, img :: a}
    -c = Complex 1.0 2.0
    +c = Complex 1.0 2.0
     z = Complex { real = 3, img = 4 }
    -real c  1.0
    +real c  1.0
     img z  4

    02_Hard_Part/22_Types.lhs


    @@ -1058,7 +1050,7 @@ Trees

    Magritte, l

    We’ll just give another standard example: binary trees.

    -
    import Data.List
    +
    import Data.List
     
     data BinTree a = Empty
                      | Node a (BinTree a) (BinTree a)
    @@ -1263,7 +1255,7 @@ numbers = 0:map
     
     take' n [] = []
     take' 0 l = []
    -take' n (x:xs) = x:take' (n-1) xs
    +take' n (x:xs) = x:take' (n-1) xs
     
     main = print $ take' 10 numbers
    @@ -1281,8 +1273,8 @@ main = print $<

    This code is mostly the same as the previous one.

    -
    import Debug.Trace (trace)
    -import Data.List
    +
    import Debug.Trace (trace)
    +import Data.List
     data BinTree a = Empty 
                      | Node a (BinTree a) (BinTree a) 
                       deriving (Eq,Ord)
    @@ -1339,8 +1331,8 @@ main = print $< treeTakeDepth _ Empty = Empty treeTakeDepth 0 _ = Empty treeTakeDepth n (Node x left right) = let - nl = treeTakeDepth (n-1) left - nr = treeTakeDepth (n-1) right + nl = treeTakeDepth (n-1) left + nr = treeTakeDepth (n-1) right in Node x nl nr
    @@ -1366,8 +1358,8 @@ treeTakeDepth n (Node x left right) =
    iTree = Node 0 (dec iTree) (inc iTree)
             where
    -           dec (Node x l r) = Node (x-1) (dec l) (dec r) 
    -           inc (Node x l r) = Node (x+1) (inc l) (inc r) 
    + dec (Node x l r) = Node (x-1) (dec l) (dec r) + inc (Node x l r) = Node (x+1) (inc l) (inc r)

    Another way to create this tree is to use a higher order function. This function should be similar to map, but should work on BinTree instead of list. Here is such a function:

    @@ -1382,8 +1374,8 @@ treeMap f (Node x left right) =

    Our definition is now:

    infTreeTwo :: BinTree Int
    -infTreeTwo = Node 0 (treeMap (\x -> x-1) infTreeTwo) 
    -                    (treeMap (\x -> x+1) infTreeTwo) 
    +infTreeTwo = Node 0 (treeMap (\x -> x-1) infTreeTwo) + (treeMap (\x -> x+1) infTreeTwo)

    Look at the result for

    main = print $ treeTakeDepth 4 infTreeTwo
    @@ -1500,7 +1492,7 @@ main = do

    Argh! An evil error message and a crash! The first evolution will be to answer with a more friendly message.

    In order to do this, we must detect that something went wrong. Here is one way to do this. Use the type Maybe. It is a very common type in Haskell.

    -
    import Data.Maybe
    +
    import Data.Maybe

    What is this thing? Maybe is a type which takes one parameter. Its definition is:

    data Maybe a = Nothing | Just a
    @@ -1543,7 +1535,7 @@ main = do

    Our next evolution will be to prompt the user again and again until she enters a valid answer.

    We keep the first part:

    -
    import Data.Maybe
    +
    import Data.Maybe
     
     maybeRead :: Read a => String -> Maybe a
     maybeRead s = case reads s of
    @@ -1806,7 +1798,7 @@ main = do
       print $ sum list

    Is translated into:

    -
    import Data.Maybe
    +
    import Data.Maybe
     
     maybeRead :: Read a => String -> Maybe a
     maybeRead s = case reads s of
    @@ -1979,7 +1971,7 @@ The list monad
     

    Golconde de Magritte

    The list monad helps us to simulate non deterministic computations. Here we go:

    -
    import Control.Monad (guard)
    +
    import Control.Monad (guard)
     
     allCases = [1..10]
     
    @@ -2035,7 +2027,7 @@ More on Infinite Tree
     
     

    This code is mostly the same as the one in the tree section.

    -
    import Data.List
    +
    import Data.List
     data BinTree a = Empty 
                      | Node a (BinTree a) (BinTree a) 
                       deriving (Eq,Ord)
    @@ -2096,8 +2088,8 @@ treeFromList (x:xs) = treeTakeDepth _ Empty = Empty
     treeTakeDepth 0 _     = Empty
     treeTakeDepth n (Node x left right) = let
    -          nl = treeTakeDepth (n-1) left
    -          nr = treeTakeDepth (n-1) right
    +          nl = treeTakeDepth (n-1) left
    +          nr = treeTakeDepth (n-1) right
               in
                   Node x nl nr
    @@ -2147,8 +2139,8 @@ treeTakeDepth 4 (treeFromList shuffle)

    This code is mostly the same as the preceding one.

    -
    import Debug.Trace (trace)
    -import Data.List
    +
    import Debug.Trace (trace)
    +import Data.List
     data BinTree a = Empty 
                      | Node a (BinTree a) (BinTree a) 
                       deriving (Eq,Ord)
    @@ -2195,8 +2187,8 @@ treeTakeDepth 4 (treeFromList shuffle) treeTakeDepth _ Empty = Empty treeTakeDepth 0 _ = Empty treeTakeDepth n (Node x left right) = let - nl = treeTakeDepth (n-1) left - nr = treeTakeDepth (n-1) right + nl = treeTakeDepth (n-1) left + nr = treeTakeDepth (n-1) right in Node x nl nr
    @@ -2240,7 +2232,7 @@ safefilter f l = safefilter' f l nbTry safefilter' f (x:xs) n = if f x then x : safefilter' f xs nbTry - else safefilter' f xs (n-1)
    + else safefilter' f xs (n-1)

    Now run the program and be happy:

    @@ -2291,25 +2283,26 @@ treeFromList' (x:xs) n =
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -2327,6 +2320,7 @@ treeFromList' (x:xs) n = Please enable JavaScript to view the comments powered by Disqus. comments powered by Disqus
    +
    Published on 2012-02-08 diff --git a/Scratch/en/blog/Higher-order-function-in-zsh/index.html b/Scratch/en/blog/Higher-order-function-in-zsh/index.html index d4253d1..179c625 100644 --- a/Scratch/en/blog/Higher-order-function-in-zsh/index.html +++ b/Scratch/en/blog/Higher-order-function-in-zsh/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Higher order function in zsh

    -
    +

    Title image

    @@ -107,11 +99,11 @@ done
  • The :t means tail; if toto=/path/to/file.ext then ${toto:t}=file.ext.
  • After ⇒

    -
    gif_to_png() { convert $1 ${1:r}.png && \rm -f $1 }
    +
    gif_to_png() { convert $1 ${1:r}.png && \rm -f $1 }
     
    -handle_resources() { map gif_to_png $1/resources/*.gif(.N) }
    +handle_resources() { map gif_to_png $1/resources/*.gif(.N) }
     
    -map handle_resources /path/to/projects/*(/N)
    +map handle_resources /path/to/projects/*(/N)

    No more bloc! It might be a little bit harder to read if you’re not used to functional programming notation. But it is more concise and robusts.

    Another example with some tests.

    Find all files in project not containing an s which their name contains their project name:

    @@ -205,25 +197,26 @@ function filter {
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -241,6 +234,7 @@ function filter { comments powered by Disqus
    +
    Published on 2011-09-28 diff --git a/Scratch/en/blog/Learn-Vim-Progressively/index.html b/Scratch/en/blog/Learn-Vim-Progressively/index.html index 442ed5a..a98d95b 100644 --- a/Scratch/en/blog/Learn-Vim-Progressively/index.html +++ b/Scratch/en/blog/Learn-Vim-Progressively/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Learn Vim Progressively

    -
    +

    Über leet use vim!

    @@ -311,25 +303,26 @@ $(document).ready(function() {
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -347,6 +340,7 @@ $(document).ready(function() { comments powered by Disqus
    +
    Published on 2011-08-25 diff --git a/Scratch/en/blog/Lost_Highway_Demistified/index.html b/Scratch/en/blog/Lost_Highway_Demistified/index.html index d78538d..2cf10f8 100644 --- a/Scratch/en/blog/Lost_Highway_Demistified/index.html +++ b/Scratch/en/blog/Lost_Highway_Demistified/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    A try to demystify 'Lost Highway'

    -
    +

    Lost Highway

    @@ -158,25 +150,26 @@ kind: article menupriority: 4 published: 2009-08-04 title: A try to demystify
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -194,6 +187,7 @@ kind: article menupriority: 4 published: 2009-08-04 title: A try to demystify comments powered by Disqus
    +
    Published on 2009-08-04 diff --git a/Scratch/en/blog/Password-Management/index.html b/Scratch/en/blog/Password-Management/index.html index f654cbb..12a3d8e 100644 --- a/Scratch/en/blog/Password-Management/index.html +++ b/Scratch/en/blog/Password-Management/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    40 character's passwords

    -
    +

    Title image

    @@ -114,25 +106,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -150,6 +143,7 @@ comments powered by Disqus
    +
    Published on 2011-05-18 diff --git a/Scratch/en/blog/SVG-and-m4-fractals/index.html b/Scratch/en/blog/SVG-and-m4-fractals/index.html index 179c47a..0449205 100644 --- a/Scratch/en/blog/SVG-and-m4-fractals/index.html +++ b/Scratch/en/blog/SVG-and-m4-fractals/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Increase the power of deficient languages.

    -
    +

    Yesod logo made in SVG and m4

    @@ -182,25 +174,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -218,6 +211,7 @@ comments powered by Disqus
    +
    Published on 2011-10-20 diff --git a/Scratch/en/blog/Social-link-the-right-way/index.html b/Scratch/en/blog/Social-link-the-right-way/index.html new file mode 100644 index 0000000..dad5837 --- /dev/null +++ b/Scratch/en/blog/Social-link-the-right-way/index.html @@ -0,0 +1,284 @@ + + + + + + YBlog - Social link the right way + + + + + + + + + + + + + +
    + + +
    +

    Social link the right way

    +
    +
    +
    +
    +

    Main image

    +
    + +

    tl;dr: Default share buttons track your user, aren’t uniform with your design, use computer ressources and slow down your web page loading.

    +

    Do it right. Use static links instead.

    +

    If you don’t want to read, just copy/paste this in your html:

    +
    <script>
    +var url=document.location;
    +document.write(
    +  '<'+'a href="https://twitter.com/home?status='+url+'" '
    +    +'target="_blank">Tweet this<'+'/a> - '
    +
    ++ '<'+'a href="http://www.facebook.com/sharer/sharer.php?u='+url+'" '
    +    +'target="_blank">Like this<'+'/a> - '
    +
    ++ '<'+'a href="https://plus.google.com/share?url='+url+'" '
    +    +'target="_blank">Share on G+<'+'/a>');
    +</script>
    +
    + +

    The problem

    +

    Ever been on a website and want to tweet about it? Fortunately, the website might have a button to help you. But do you really know what this button do?

    +

    The “Like”, “Tweet” and “+1” buttons will call a javascript. It will get access to your cookies. It helps the provider of the button to know who you are.

    +

    In plain English, the “+1” button will inform Google you are visiting the website, even if you don’t click on “+1”. The same is true for the “like” button for facebook and the “tweet this” button for twitter.

    +

    The problem is not only a privacy issue. In fact (sadly imho) this isn’t an issue for most people. These button consume computer ressources. Far more than a simple link. It thus slow down a bit the computer and consume energy. These button could also slow down the rendering of your web page.

    +

    Another aspect is their design. Their look and feel is mostly imposed by the provider.

    +

    The most problematic aspect in my opinion is to use a third party js on your website. What if tomorrow twitter update their tweet button? If the upgrade broke something for only a minority of people, they won’t fix it. This could occur anytime without any notification. They just have to add a document.write in their js you call asynchronously and BAM! Your website is just an empty blank page. And as you call many external ressources, it can be very difficult to find the origin of the problem.

    +

    Using social network buttons:

    +
      +
    • Pros: +
        +
      • help user share your website,
      • +
      • can provide a popularity indicator to your users.
      • +
    • +
    • Cons: +
        +
      • you help tracking your users,
      • +
      • generally doesn’t follow the design of your website,
      • +
      • use more computer ressources,
      • +
      • slow down your website,
      • +
      • executing third party js can break things silently.
      • +
    • +
    +

    Solutions

    +

    I will provide you two solutions with the following properties:

    +
      +
    • Pros: +
        +
      • help user share your website,
      • +
      • doesn’t follow your user,
      • +
      • use almost no computer ressource,
      • +
      • doesn’t slow down your website,
      • +
      • doesn’t execute any third party js on your website.
      • +
    • +
    • Cons: +
        +
      • doesn’t provide any popularity information.
      • +
    • +
    +

    Solution 1 (no js):

    +
    <a href="https://twitter.com/home?status=$url$"
    +    target="_blank">Tweet this</a>
    +
    +<a href="http://www.facebook.com/sharer/sharer.php?u=$url$"
    +    target="_blank">Like this</a>
    +
    +<a href="https://plus.google.com/share?url=$url$"
    +    target="_blank">Share on G+</a>
    +

    But you have to replace $url$ by the current url.

    +

    Solution 2 (Just copy/paste):

    +

    If you don’t want to write the url yourself, you could use some minimal js:

    +
    <script>
    +var url=document.location;
    +document.write(
    +  '<'+'a href="https://twitter.com/home?status='+url+'" '
    +    +'target="_blank">Tweet this<'+'/a> - '
    +
    ++ '<'+'a href="http://www.facebook.com/sharer/sharer.php?u='+url+'" '
    +    +'target="_blank">Like this<'+'/a> - '
    +
    ++ '<'+'a href="https://plus.google.com/share?url='+url+'" '
    +    +'target="_blank">Share on G+<'+'/a>');
    +</script>
    +

    Here is the result:

    +
    + +
    + +

    Good looking solutions

    +

    If you don’t want just text but nice icons. You have many choices:

    +
      +
    • Use images <img src="..."/> in the links.
    • +
    • Use icon fonts
    • +
    +

    As the first solution is pretty straightforward, I’ll explain the second one.

    +
      +
    1. Download the icon font here
    2. +
    3. put the font file(s) at some place (here ‘fonts/social_font.ttf’ relatively to your css file)
    4. +
    5. Add this to your css
    6. +
    +
    @font-face
    +  font-family: 'social'
    +  src: url('fonts/social_font.ttf') format('truetype')
    +  font-weight: normal
    +  font-style: normal
    +.social
    +  font-family: social
    +

    Now add this to your html:

    +

    Solution 1 (without js):

    +
    <a href="https://twitter.com/home?status=$url$"
    +    target="_blank"
    +    class="social">&#116;</a>
    +·
    +<a href="http://www.facebook.com/sharer/sharer.php?u=$url$"
    +   target="_blank"
    +   class="social">&#0096;</a>
    +·
    +<a href="https://plus.google.com/share?url=$url$"
    +    target="_blank"
    +    class="social">&#0103;</a>
    +

    Solution 2 (just copy/paste):

    +
    <script>
    +var url=document.location;
    +document.write(
    +    '<a href="https://twitter.com/home?status='+url+'"'
    +        + ' target="_blank"'
    +        + ' class="social">&#116;<'+'/a>'
    +    + ' · '
    +    + '<' + 'a href="http://www.facebook.com/sharer/sharer.php?u='+url+'"'
    +       + ' target="_blank"'
    +       + ' class="social">&#0096;<'+'/a>'
    +    + ' · '
    +    + '<a href="https://plus.google.com/share?url='+url+'"'
    +        + ' target="_blank"'
    +        + ' class="social">&#0103;<'+'/a>');
    +</script>
    +

    Here is the result:

    +
    + +
    + +

    Conclusion

    +
      +
    1. You get your design back,
    2. +
    3. You stop to help tracking people,
    4. +
    5. You use less computer ressources and more generally power ressources which is good for the planet,
    6. +
    7. Your web pages will load faster.
    8. +
    +

    ps: On my personal website I continue to use Google analytics. Therefore, Google (and only Google, not facebook nor twitter) can track you here. But I might change this in the future.

    +
    + +
    + + · + + · + + · + +
    + These social sharing links preserve your privacy +
    + + +
    +

    Comments

    +
    + + + comments powered by Disqus +
    + +
    +
    + Published on 2013-03-14 +
    + +
    + Yann Esposito© +
    +
    + Done with + Vim + & + Hakyll +
    +
    +
    + +
    + + + + + + + + diff --git a/Scratch/en/blog/Typography-and-the-Web/index.html b/Scratch/en/blog/Typography-and-the-Web/index.html index a7b456f..a226b6b 100644 --- a/Scratch/en/blog/Typography-and-the-Web/index.html +++ b/Scratch/en/blog/Typography-and-the-Web/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Typography and the Web

    -
    +

    @@ -107,25 +99,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -143,6 +136,7 @@ comments powered by Disqus
    +
    Published on 2012-02-02 diff --git a/Scratch/en/blog/Yesod-excellent-ideas/index.html b/Scratch/en/blog/Yesod-excellent-ideas/index.html index a892736..8ab0491 100644 --- a/Scratch/en/blog/Yesod-excellent-ideas/index.html +++ b/Scratch/en/blog/Yesod-excellent-ideas/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Yesod excellent ideas

    -
    +

    Title image

    @@ -65,7 +57,7 @@ SQL injection by a mom

    SQL injection by a mom

    When you create a web application, a lot of time is spent dealing with strings. Strings for URL, HTML, JavaScript, CSS, SQL, etc… To prevent malicious usage you have to protect each strings to be sure, no script will pass from one point to another. Suppose a user enter this user name:

    -
    Newton<script>alert("An apple fall")</script>
    +
    Newton<script>alert("An apple fall")</script>

    You must transform each < into &lt;. Without this transformation alert will appear each time you try to display this user name. Safe types associate with each string what kind of string it is. Is it a string for URL? For javascript? For HTML? And the right protection is made by default to prevent problems.

    Yesod does its best to handle cross scripting issues. Both between the client and the server and between the server and your DB. Here is an example:

    Go to the other page ~~~~~~

    @@ -127,25 +119,26 @@ toWidget hamletFile "buttonTemplate.hamlet"
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -163,6 +156,7 @@ toWidget hamletFile "buttonTemplate.hamlet"Please enable JavaScript to view the comments powered by Disqus. comments powered by Disqus
    +
    Published on 2011-10-04 diff --git a/Scratch/en/blog/Yesod-tutorial-for-newbies/index.html b/Scratch/en/blog/Yesod-tutorial-for-newbies/index.html index 8b5b17b..db178e0 100644 --- a/Scratch/en/blog/Yesod-tutorial-for-newbies/index.html +++ b/Scratch/en/blog/Yesod-tutorial-for-newbies/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Haskell web programming

    -
    +

    Neo Flying at warp speed

    @@ -143,7 +135,7 @@ static/tmp
  • config/models
  • Obviously:

    -

    config/routes | is where you’ll configure the map %url → Code. |
    Handler/ | contains the files that will contain the code called when a %url is accessed. |
    templates/ | contains html, js and css templates. |
    config/models | is where you’ll configure the persistent objects (database tables). |

    +

    config/routes | is where you’ll configure the map url → Code. |
    Handler/ | contains the files that will contain the code called when a url is accessed. |
    templates/ | contains html, js and css templates. |
    config/models | is where you’ll configure the persistent objects (database tables). |

    During this tutorial we’ll modify other files as well, but we won’t explore them in detail.

    Also note, shell commands are executed in the root directory of your project instead specified otherwise.

    We are now ready to start!

    @@ -153,7 +145,7 @@ static/tmp

    Goal:

    Make a server that when accessed /echo/[some text] should return a web page containing “some text” inside an h1 bloc.

    -

    In a first time, we must declare the %url of the form /echo/... are meaningful. Let’s take a look at the file config/routes:

    +

    In a first time, we must declare the url of the form /echo/... are meaningful. Let’s take a look at the file config/routes:

     /static StaticR Static getStatic
     /auth   AuthR   Auth   getAuth
    @@ -169,7 +161,7 @@ static/tmp
     /echo/#String EchoR GET
     
    -

    This line contains three elements: the %url pattern, a handler name, an %http method. I am not particularly fan of the big R notation but this is the standard convention.

    +

    This line contains three elements: the url pattern, a handler name, an %http method. I am not particularly fan of the big R notation but this is the standard convention.

    If you save config/routes, you should see your terminal in which you launched yesod devel activate and certainly displaying an error message.

     Application.hs:31:1: Not in scope: `getEchoR'
    @@ -186,12 +178,12 @@ getEchoR theText = do
     

    TADA! It works!

    Bulletproof?

    Neo stops a myriad of bullets

    -

    Even this extremely minimal web application has some impressive properties. For exemple, imagine an attacker entering this %url:

    +

    Even this extremely minimal web application has some impressive properties. For exemple, imagine an attacker entering this url:

    [http://localhost:3000/echo/<a>I'm <script>alert("Bad!");](http://localhost:3000/echo/I’m

    " %>

    The special characters are protected for us. A malicious user could not hide some bad script inside.

    -

    This behavior is a direct consequence of type safety. The %url string is put inside a %url type. Then the interesting part in the %url is put inside a String type. To pass from %url type to String type some transformation are made. For example, replace all “%20” by space characters. Then to show the String inside an html document, the string is put inside an html type. Some transformations occurs like replace “<” by “&lt;”. Thanks to yesod, this tedious job is done for us.

    +

    This behavior is a direct consequence of type safety. The url string is put inside a url type. Then the interesting part in the url is put inside a String type. To pass from url type to String type some transformation are made. For example, replace all “%20” by space characters. Then to show the String inside an html document, the string is put inside an html type. Some transformations occurs like replace “<” by “&lt;”. Thanks to yesod, this tedious job is done for us.

    "http://localhost:3000/echo/some%20text<a>" :: URL
                         ↓
                   "some text<a>"                 :: String
    @@ -236,7 +228,7 @@ a:visited { col
     

    Generally you don’t want to have all your code inside a unique file. This is why we will separate our handlers. In a first time create a new file Handler/Echo.hs containing:

    module Handler.Echo where
     
    -import Import
    +import Import
     
     getEchoR :: String -> Handler RepHtml
     getEchoR theText = do
    @@ -249,7 +241,7 @@ getEchoR theText = do
     

    We must also declare this new Handler module inside Application.hs. Just after the “import Handler.Home”, add:

    -
    import Handler.Echo
    +
    import Handler.Echo

    This is it.

    ps: I am sure not so far in the future we could simply write yesod add-handler Echo to declare it and create a new handler file.

    Data.Text

    @@ -264,7 +256,7 @@ getEchoR theText = do

    And do the same in Handler/Echo.hs:

    module Handler.Echo where
     
    -import Import
    +import Import
     
     getEchoR :: Text -> Handler RepHtml
     getEchoR theText = do
    @@ -290,8 +282,8 @@ getEchoR theText = do
     

    This time the path /mirror will accept GET and POST requests. Add the corresponding new Handler file:

    module Handler.Mirror where
     
    -import Import
    -import qualified Data.Text as T
    +import Import
    +import qualified Data.Text as T
     
     getMirrorR :: Handler RepHtml
     getMirrorR = do
    @@ -349,11 +341,11 @@ Article
         )
     where
     
    -import Import
    -import Data.Monoid
    +import Import
    +import Data.Monoid
     
     -- to use Html into forms
    -import Yesod.Form.Nic (YesodNic, nicHtmlField)
    +import Yesod.Form.Nic (YesodNic, nicHtmlField)
     instance YesodNic App

    Remark: it is a best practice to add the YesodNic instance inside Foundation.hs. I put this definition here to make things easier but you should see a warning about this orphan instance. To put the include inside Foundation.hs is left as an exercice to the reader.

    Hint: Do not forget to put YesodNic and nicHtmlField inside the exported objects of the module.

    @@ -428,7 +420,7 @@ getArticleR articleId = do
    <p>A last try to <em>cross script</em> 
        and <em>SQL injection</em></p>
     <p>Here is the first try: 
    -   <script>alert("You loose");</script></p>
    +   <script>alert("You loose");</script></p>
     <p> And Here is the last </p>
     "); DROP TABLE ARTICLE;;

    Conclusion

    @@ -458,25 +450,26 @@ getArticleR articleId = do
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -494,6 +487,7 @@ getArticleR articleId = do comments powered by Disqus
    +
    Published on 2012-01-15 diff --git a/Scratch/en/blog/feed/feed.xml b/Scratch/en/blog/feed/feed.xml index a28384f..9931a24 100644 --- a/Scratch/en/blog/feed/feed.xml +++ b/Scratch/en/blog/feed/feed.xml @@ -8,8 +8,188 @@ Yann Esposito yann.esposito@gmail.com - 2012-12-12T00:00:00Z + 2013-03-14T00:00:00Z + Social link the right way + + http://yannesposito.com/Scratch/en/blog/Social-link-the-right-way/index.html + 2013-03-14T00:00:00Z + 2013-03-14T00:00:00Z + Main image

    +
    + +

    tl;dr: Default share buttons track your user, aren’t uniform with your design, use computer ressources and slow down your web page loading.

    +

    Do it right. Use static links instead.

    +

    If you don’t want to read, just copy/paste this in your html:

    +
    <script>
    +var url=document.location;
    +document.write(
    +  '<'+'a href="https://twitter.com/home?status='+url+'" '
    +    +'target="_blank">Tweet this<'+'/a> - '
    +
    ++ '<'+'a href="http://www.facebook.com/sharer/sharer.php?u='+url+'" '
    +    +'target="_blank">Like this<'+'/a> - '
    +
    ++ '<'+'a href="https://plus.google.com/share?url='+url+'" '
    +    +'target="_blank">Share on G+<'+'/a>');
    +</script>
    +
    + +

    The problem

    +

    Ever been on a website and want to tweet about it? Fortunately, the website might have a button to help you. But do you really know what this button do?

    +

    The “Like”, “Tweet” and “+1” buttons will call a javascript. It will get access to your cookies. It helps the provider of the button to know who you are.

    +

    In plain English, the “+1” button will inform Google you are visiting the website, even if you don’t click on “+1”. The same is true for the “like” button for facebook and the “tweet this” button for twitter.

    +

    The problem is not only a privacy issue. In fact (sadly imho) this isn’t an issue for most people. These button consume computer ressources. Far more than a simple link. It thus slow down a bit the computer and consume energy. These button could also slow down the rendering of your web page.

    +

    Another aspect is their design. Their look and feel is mostly imposed by the provider.

    +

    The most problematic aspect in my opinion is to use a third party js on your website. What if tomorrow twitter update their tweet button? If the upgrade broke something for only a minority of people, they won’t fix it. This could occur anytime without any notification. They just have to add a document.write in their js you call asynchronously and BAM! Your website is just an empty blank page. And as you call many external ressources, it can be very difficult to find the origin of the problem.

    +

    Using social network buttons:

    +
      +
    • Pros: +
        +
      • help user share your website,
      • +
      • can provide a popularity indicator to your users.
      • +
    • +
    • Cons: +
        +
      • you help tracking your users,
      • +
      • generally doesn’t follow the design of your website,
      • +
      • use more computer ressources,
      • +
      • slow down your website,
      • +
      • executing third party js can break things silently.
      • +
    • +
    +

    Solutions

    +

    I will provide you two solutions with the following properties:

    +
      +
    • Pros: +
        +
      • help user share your website,
      • +
      • doesn’t follow your user,
      • +
      • use almost no computer ressource,
      • +
      • doesn’t slow down your website,
      • +
      • doesn’t execute any third party js on your website.
      • +
    • +
    • Cons: +
        +
      • doesn’t provide any popularity information.
      • +
    • +
    +

    Solution 1 (no js):

    +
    <a href="https://twitter.com/home?status=$url$"
    +    target="_blank">Tweet this</a>
    +
    +<a href="http://www.facebook.com/sharer/sharer.php?u=$url$"
    +    target="_blank">Like this</a>
    +
    +<a href="https://plus.google.com/share?url=$url$"
    +    target="_blank">Share on G+</a>
    +

    But you have to replace $url$ by the current url.

    +

    Solution 2 (Just copy/paste):

    +

    If you don’t want to write the url yourself, you could use some minimal js:

    +
    <script>
    +var url=document.location;
    +document.write(
    +  '<'+'a href="https://twitter.com/home?status='+url+'" '
    +    +'target="_blank">Tweet this<'+'/a> - '
    +
    ++ '<'+'a href="http://www.facebook.com/sharer/sharer.php?u='+url+'" '
    +    +'target="_blank">Like this<'+'/a> - '
    +
    ++ '<'+'a href="https://plus.google.com/share?url='+url+'" '
    +    +'target="_blank">Share on G+<'+'/a>');
    +</script>
    +

    Here is the result:

    +
    + +
    + +

    Good looking solutions

    +

    If you don’t want just text but nice icons. You have many choices:

    +
      +
    • Use images <img src="..."/> in the links.
    • +
    • Use icon fonts
    • +
    +

    As the first solution is pretty straightforward, I’ll explain the second one.

    +
      +
    1. Download the icon font here
    2. +
    3. put the font file(s) at some place (here ‘fonts/social_font.ttf’ relatively to your css file)
    4. +
    5. Add this to your css
    6. +
    +
    @font-face
    +  font-family: 'social'
    +  src: url('fonts/social_font.ttf') format('truetype')
    +  font-weight: normal
    +  font-style: normal
    +.social
    +  font-family: social
    +

    Now add this to your html:

    +

    Solution 1 (without js):

    +
    <a href="https://twitter.com/home?status=$url$"
    +    target="_blank"
    +    class="social">&#116;</a>
    +·
    +<a href="http://www.facebook.com/sharer/sharer.php?u=$url$"
    +   target="_blank"
    +   class="social">&#0096;</a>
    +·
    +<a href="https://plus.google.com/share?url=$url$"
    +    target="_blank"
    +    class="social">&#0103;</a>
    +

    Solution 2 (just copy/paste):

    +
    <script>
    +var url=document.location;
    +document.write(
    +    '<a href="https://twitter.com/home?status='+url+'"'
    +        + ' target="_blank"'
    +        + ' class="social">&#116;<'+'/a>'
    +    + ' · '
    +    + '<' + 'a href="http://www.facebook.com/sharer/sharer.php?u='+url+'"'
    +       + ' target="_blank"'
    +       + ' class="social">&#0096;<'+'/a>'
    +    + ' · '
    +    + '<a href="https://plus.google.com/share?url='+url+'"'
    +        + ' target="_blank"'
    +        + ' class="social">&#0103;<'+'/a>');
    +</script>
    +

    Here is the result:

    +
    + +
    + +

    Conclusion

    +
      +
    1. You get your design back,
    2. +
    3. You stop to help tracking people,
    4. +
    5. You use less computer ressources and more generally power ressources which is good for the planet,
    6. +
    7. Your web pages will load faster.
    8. +
    +

    ps: On my personal website I continue to use Google analytics. Therefore, Google (and only Google, not facebook nor twitter) can track you here. But I might change this in the future.

    ]]>
    +
    + Category Theory Presentation http://yannesposito.com/Scratch/en/blog/Category-Theory-Presentation/index.html @@ -1035,9 +1215,9 @@ Another detail of the Mandelbulb

    We can consider two parts. The first being mostly some boilerplate2. And the second part more focused on OpenGL and content.

    Let’s play the song of our people

    -
    import Graphics.Rendering.OpenGL
    -import Graphics.UI.GLUT
    -import Data.IORef
    +
    import Graphics.Rendering.OpenGL
    +import Graphics.UI.GLUT
    +import Data.IORef

    For efficiency reason3, I will not use the default Haskell Complex data type.

    @@ -1047,11 +1227,11 @@ Another detail of the Mandelbulb
    instance Num Complex where
    -    fromInteger n = C (fromIntegral n,0.0)
    +    fromInteger n = C (fromIntegral n,0.0)
         C (x,y) * C (z,t) = C (z*x - y*t, y*z + x*t)
         C (x,y) + C (z,t) = C (x+z, y+t)
    -    abs (C (x,y))     = C (sqrt (x*x + y*y),0.0)
    -    signum (C (x,y))  = C (signum x , 0.0)
    + abs (C (x,y)) = C (sqrt (x*x + y*y),0.0) + signum (C (x,y)) = C (signum x , 0.0)

    We declare some useful functions for manipulating complex numbers:

    @@ -1138,16 +1318,16 @@ allPoints = [ (x/width,ycolorFromValue n = let t :: Int -> GLfloat - t i = 0.5 + 0.5*cos( fromIntegral i / 10 ) + t i = 0.5 + 0.5*cos( fromIntegral i / 10 ) in - Color3 (t n) (t (n+5)) (t (n+10)) + Color3 (t n) (t (n+5)) (t (n+10))

    And now the mandel function. Given two coordinates in pixels, it returns some integer value:

    mandel x y = 
    -  let r = 2.0 * x / width
    -      i = 2.0 * y / height
    +  let r = 2.0 * x / width
    +      i = 2.0 * y / height
       in
           f (complex r i) 0 64
    @@ -1163,7 +1343,7 @@ allPoints = [ (x/width,y0 = 0 f c z n = if (magnitude z > 2 ) then n - else f c ((z*z)+c) (n-1)
    + else f c ((z*z)+c) (n-1)

    Well, if you download this file (look at the bottom of this section), compile it and run it this is the result:

    @@ -1179,20 +1359,20 @@ f c z n = if (magnitude z
    -
    import Graphics.Rendering.OpenGL
    -import Graphics.UI.GLUT
    -import Data.IORef
    +
    import Graphics.Rendering.OpenGL
    +import Graphics.UI.GLUT
    +import Data.IORef
     -- Use UNPACK data because it is faster
     -- The ! is for strict instead of lazy
     data Complex = C  {-# UNPACK #-} !Float 
                       {-# UNPACK #-} !Float 
                    deriving (Show,Eq)
     instance Num Complex where
    -    fromInteger n = C (fromIntegral n) 0.0
    +    fromInteger n = C (fromIntegral n) 0.0
         (C x y) * (C z t) = C (z*x - y*t) (y*z + x*t)
         (C x y) + (C z t) = C (x+z) (y+t)
    -    abs (C x y)     = C (sqrt (x*x + y*y)) 0.0
    -    signum (C x y)  = C (signum x) 0.0
    +    abs (C x y)     = C (sqrt (x*x + y*y)) 0.0
    +    signum (C x y)  = C (signum x) 0.0
     complex :: Float -> Float -> Complex
     complex x y = C x y
     
    @@ -1219,7 +1399,7 @@ main = do
       mainLoop
     display = do
        -- set the background color (dark solarized theme)
    -  clearColor $= Color4 0 0.1686 0.2117 1
    +  clearColor $= Color4 0 0.1686 0.2117 1
       clear [ColorBuffer] -- make the window black
       loadIdentity -- reset any transformation
       preservingMatrix drawMandelbrot
    @@ -1284,8 +1464,8 @@ positivePoints = do
     maxZeroIndex func minval maxval 0 = (minval+maxval)/2
     maxZeroIndex func minval maxval n = 
       if (func medpoint) /= 0 
    -       then maxZeroIndex func minval medpoint (n-1)
    -       else maxZeroIndex func medpoint maxval (n-1)
    +       then maxZeroIndex func minval medpoint (n-1)
    +       else maxZeroIndex func medpoint maxval (n-1)
       where medpoint = (minval+maxval)/2
    @@ -1297,15 +1477,15 @@ maxZeroIndex func minval maxval n =
    colorFromValue n =
       let 
           t :: Int -> GLfloat
    -      t i = 0.5 + 0.5*cos( fromIntegral i / 10 )
    +      t i = 0.5 + 0.5*cos( fromIntegral i / 10 )
       in
    -    Color3 (t n) (t (n+5)) (t (n+10))
    + Color3 (t n) (t (n+5)) (t (n+10))
    mandel x y = 
    -  let r = 2.0 * x / width
    -      i = 2.0 * y / height
    +  let r = 2.0 * x / width
    +      i = 2.0 * y / height
       in
           f (complex r i) 0 64
    @@ -1315,7 +1495,7 @@ maxZeroIndex func minval maxval n = f c z 0 = 0 f c z n = if (magnitude z > 2 ) then n - else f c ((z*z)+c) (n-1) + else f c ((z*z)+c) (n-1)
    @@ -1345,9 +1525,9 @@ f c z n = if (magnitude z
    -
    import Graphics.Rendering.OpenGL
    -import Graphics.UI.GLUT
    -import Data.IORef
    +
    import Graphics.Rendering.OpenGL
    +import Graphics.UI.GLUT
    +import Data.IORef
     type ColoredPoint = (GLfloat,GLfloat,GLfloat,Color3 GLfloat)
    @@ -1415,7 +1595,7 @@ main = do -- Some state variables (I know it feels BAD) angle <- newIORef ((35,0)::(GLfloat,GLfloat)) zoom <- newIORef (2::GLfloat) - campos <- newIORef ((0.7,0)::(GLfloat,GLfloat)) + campos <- newIORef ((0.7,0)::(GLfloat,GLfloat)) -- Function to call each frame idleCallback $= Just idle -- Function to call when keyboard or mouse is used @@ -1455,18 +1635,18 @@ mapSnd f (x,y) = ( x,f y) z $= 1 -- zoom p $= (0,0) -- camera position -- use of hjkl to rotate - kact a _ _ (Char 'h') Down = modVar a (mapFst (+0.5)) - kact a _ _ (Char 'l') Down = modVar a (mapFst (+(-0.5))) - kact a _ _ (Char 'j') Down = modVar a (mapSnd (+0.5)) - kact a _ _ (Char 'k') Down = modVar a (mapSnd (+(-0.5))) + kact a _ _ (Char 'h') Down = modVar a (mapFst (+0.5)) + kact a _ _ (Char 'l') Down = modVar a (mapFst (+(-0.5))) + kact a _ _ (Char 'j') Down = modVar a (mapSnd (+0.5)) + kact a _ _ (Char 'k') Down = modVar a (mapSnd (+(-0.5))) -- use o and i to zoom - kact _ z _ (Char 'o') Down = modVar z (*1.1) - kact _ z _ (Char 'i') Down = modVar z (*0.9) + kact _ z _ (Char 'o') Down = modVar z (*1.1) + kact _ z _ (Char 'i') Down = modVar z (*0.9) -- use sdfe to move the camera - kact _ _ p (Char 's') Down = modVar p (mapFst (+0.1)) - kact _ _ p (Char 'f') Down = modVar p (mapFst (+(-0.1))) - kact _ _ p (Char 'd') Down = modVar p (mapSnd (+0.1)) - kact _ _ p (Char 'e') Down = modVar p (mapSnd (+(-0.1))) + kact _ _ p (Char 's') Down = modVar p (mapFst (+0.1)) + kact _ _ p (Char 'f') Down = modVar p (mapFst (+(-0.1))) + kact _ _ p (Char 'd') Down = modVar p (mapSnd (+0.1)) + kact _ _ p (Char 'e') Down = modVar p (mapSnd (+(-0.1))) -- any other keys does nothing kact _ _ _ _ _ = return ()
    @@ -1475,7 +1655,7 @@ mapSnd f (x,y) = ( x,f y)
    display angle zoom position = do
        -- set the background color (dark solarized theme)
    -  clearColor $= Color4 0 0.1686 0.2117 1
    +  clearColor $= Color4 0 0.1686 0.2117 1
       clear [ColorBuffer,DepthBuffer]
       -- Transformation to change the view
       loadIdentity -- reset any transformation
    @@ -1487,8 +1667,8 @@ mapSnd f (x,y) = (  x,f y)
    scale z z z -- rotate (xangle,yangle) <- get angle - rotate xangle $ Vector3 1.0 0.0 (0.0::GLfloat) - rotate yangle $ Vector3 0.0 1.0 (0.0::GLfloat) + rotate xangle $ Vector3 1.0 0.0 (0.0::GLfloat) + rotate yangle $ Vector3 0.0 1.0 (0.0::GLfloat) -- Now that all transformation were made -- We create the object(s) @@ -1537,17 +1717,17 @@ depthPoints = do depthOf x' y' = maxZeroIndex (mandel x' y') 0 deep logdeep logdeep = floor ((log deep) / log 2) z1 = depthOf x y - z2 = depthOf (x+1) y - z3 = depthOf (x+1) (y+1) - z4 = depthOf x (y+1) - c1 = mandel x y (z1+1) - c2 = mandel (x+1) y (z2+1) - c3 = mandel (x+1) (y+1) (z3+1) - c4 = mandel x (y+1) (z4+1) + z2 = depthOf (x+1) y + z3 = depthOf (x+1) (y+1) + z4 = depthOf x (y+1) + c1 = mandel x y (z1+1) + c2 = mandel (x+1) y (z2+1) + c3 = mandel (x+1) (y+1) (z3+1) + c4 = mandel x (y+1) (z4+1) p1 = ( x /width, y /height, z1/deep, colorFromValue c1) - p2 = ((x+1)/width, y /height, z2/deep, colorFromValue c2) - p3 = ((x+1)/width,(y+1)/height, z3/deep, colorFromValue c3) - p4 = ( x /width,(y+1)/height, z4/deep, colorFromValue c4) + p2 = ((x+1)/width, y /height, z2/deep, colorFromValue c2) + p3 = ((x+1)/width,(y+1)/height, z3/deep, colorFromValue c3) + p4 = ( x /width,(y+1)/height, z4/deep, colorFromValue c4) if (and $ map (>=57) [c1,c2,c3,c4]) then [] else [p1,p2,p3,p1,p3,p4] @@ -1558,13 +1738,13 @@ depthPoints = do x <- [-width..width] y <- [-height..height] let - neighbors = [(x,y),(x+1,y),(x+1,y+1),(x,y+1)] + neighbors = [(x,y),(x+1,y),(x+1,y+1),(x,y+1)] depthOf (u,v) = maxZeroIndex (mandel u v) 0 deep logdeep logdeep = floor ((log deep) / log 2) -- zs are 3D points with found depth zs = map (\(u,v) -> (u,v,depthOf (u,v))) neighbors -- ts are 3D pixels + mandel value - ts = map (\(u,v,w) -> (u,v,w,mandel u v (w+1))) zs + ts = map (\(u,v,w) -> (u,v,w,mandel u v (w+1))) zs -- ps are 3D opengl points + color value ps = map (\(u,v,w,c') -> (u/width,v/height,w/deep,colorFromValue c')) ts @@ -1582,7 +1762,7 @@ depthPoints = do allPoints = planPoints ++ map inverseDepth planPoints where planPoints = depthPoints - inverseDepth (x,y,z,c) = (x,y,-z+1/deep,c) + inverseDepth (x,y,z,c) = (x,y,-z+1/deep,c)

    The rest of the program is very close to the preceding one.

    @@ -1602,8 +1782,8 @@ allPoints = planPoints ++ 0 = (minval+maxval)/2 maxZeroIndex func minval maxval n = if (func medpoint) /= 0 - then maxZeroIndex func minval medpoint (n-1) - else maxZeroIndex func medpoint maxval (n-1) + then maxZeroIndex func minval medpoint (n-1) + else maxZeroIndex func medpoint maxval (n-1) where medpoint = (minval+maxval)/2
    @@ -1612,9 +1792,9 @@ maxZeroIndex func minval maxval n =
    colorFromValue n =
       let 
           t :: Int -> GLfloat
    -      t i = 0.7 + 0.3*cos( fromIntegral i / 10 )
    +      t i = 0.7 + 0.3*cos( fromIntegral i / 10 )
       in
    -    Color3 (t n) (t (n+5)) (t (n+10))
    + Color3 (t n) (t (n+5)) (t (n+10))

    We only changed from Complex to ExtComplex of the main f function.

    @@ -1623,7 +1803,7 @@ maxZeroIndex func minval maxval n = f c z 0 = 0 f c z n = if (magnitude z > 2 ) then n - else f c ((z*z)+c) (n-1) + else f c ((z*z)+c) (n-1)
    @@ -1631,9 +1811,9 @@ f c z n = if (magnitude z We simply add a new dimension to the mandel function and change the type signature of f from Complex to ExtComplex.

    mandel x y z = 
    -  let r = 2.0 * x / width
    -      i = 2.0 * y / height
    -      s = 2.0 * z / deep
    +  let r = 2.0 * x / width
    +      i = 2.0 * y / height
    +      s = 2.0 * z / deep
       in
           f (extcomplex r i s) 0 64
    @@ -1651,8 +1831,8 @@ f c z n = if (magnitude z ExtComplex, the extended complexes
    -
    import YBoiler -- Most the OpenGL Boilerplate
    -import Mandel -- The 3D Mandelbrot maths
    +
    import YBoiler -- Most the OpenGL Boilerplate
    +import Mandel -- The 3D Mandelbrot maths

    The yMainLoop takes two arguments: the title of the window and a function from time to triangles

    @@ -1676,7 +1856,7 @@ allPoints = planPoints ++ where planPoints = depthPoints ++ map inverseHeight depthPoints inverseHeight (x,y,z,c) = (x,-y,z,c) - inverseDepth (x,y,z,c) = (x,y,-z+1/deep,c) + inverseDepth (x,y,z,c) = (x,y,-z+1/deep,c)
    @@ -1685,12 +1865,12 @@ depthPoints = do x <- [-width..width] y <- [0..height] let - neighbors = [(x,y),(x+1,y),(x+1,y+1),(x,y+1)] + neighbors = [(x,y),(x+1,y),(x+1,y+1),(x,y+1)] depthOf (u,v) = maxZeroIndex (ymandel u v) 0 deep 7 -- zs are 3D points with found depth zs = map (\(u,v) -> (u,v,depthOf (u,v))) neighbors -- ts are 3D pixels + mandel value - ts = map (\(u,v,w) -> (u,v,w,ymandel u v (w+1))) zs + ts = map (\(u,v,w) -> (u,v,w,ymandel u v (w+1))) zs -- ps are 3D opengl points + color value ps = map (\(u,v,w,c') -> (u/width,v/height,w/deep,colorFromValue c')) ts @@ -1711,16 +1891,16 @@ depthPoints = do maxZeroIndex func minval maxval 0 = (minval+maxval)/2 maxZeroIndex func minval maxval n = if (func medpoint) /= 0 - then maxZeroIndex func minval medpoint (n-1) - else maxZeroIndex func medpoint maxval (n-1) + then maxZeroIndex func minval medpoint (n-1) + else maxZeroIndex func medpoint maxval (n-1) where medpoint = (minval+maxval)/2 colorFromValue n = let t :: Int -> GLfloat - t i = 0.7 + 0.3*cos( fromIntegral i / 10 ) + t i = 0.7 + 0.3*cos( fromIntegral i / 10 ) in - ((t n),(t (n+5)),(t (n+10))) + ((t n),(t (n+5)),(t (n+10))) ymandel x y z = mandel (2*x/width) (2*y/height) (2*z/deep) 64
    @@ -1754,8 +1934,8 @@ ymandel x y z = mandel (2

    Here is a real working code, I’ve hidden most display functions. The YGL, is a kind of framework to display 3D functions. But it can easily be extended to many kind of representation.

    -
    import YGL -- Most the OpenGL Boilerplate
    -import Mandel -- The 3D Mandelbrot maths
    +
    import YGL -- Most the OpenGL Boilerplate
    +import Mandel -- The 3D Mandelbrot maths

    We first set the mapping between user input and actions. The type of each couple should be of the form (user input, f) where (in a first time) f:World -> World. It means, the user input will transform the world state.

    @@ -1769,16 +1949,16 @@ inputActionMap = inputMapFromList [ ,(Press 'l' , rotate ydir (-5)) ,(Press 'o' , rotate zdir 5) ,(Press 'u' , rotate zdir (-5)) - ,(Press 'f' , translate xdir 0.1) - ,(Press 's' , translate xdir (-0.1)) - ,(Press 'e' , translate ydir 0.1) - ,(Press 'd' , translate ydir (-0.1)) - ,(Press 'z' , translate zdir 0.1) - ,(Press 'r' , translate zdir (-0.1)) - ,(Press '+' , zoom 1.1) - ,(Press '-' , zoom (1/1.1)) - ,(Press 'h' , resize 1.2) - ,(Press 'g' , resize (1/1.2)) + ,(Press 'f' , translate xdir 0.1) + ,(Press 's' , translate xdir (-0.1)) + ,(Press 'e' , translate ydir 0.1) + ,(Press 'd' , translate ydir (-0.1)) + ,(Press 'z' , translate zdir 0.1) + ,(Press 'r' , translate zdir (-0.1)) + ,(Press '+' , zoom 1.1) + ,(Press '-' , zoom (1/1.1)) + ,(Press 'h' , resize 1.2) + ,(Press 'g' , resize (1/1.2)) ]
    @@ -1871,11 +2051,11 @@ main = yMainLoop inputActionMap idleAction initialWorld< initialWorld = World { angle = makePoint3D (-30,-30,0) , position = makePoint3D (0,0,0) - , scale = 0.8 + , scale = 0.8 , shape = shapeFunc , box = Box3D { minPoint = makePoint3D (-2,-2,-2) , maxPoint = makePoint3D (2,2,2) - , resolution = 0.16 } + , resolution = 0.16 } , told = 0 }
    @@ -1888,8 +2068,8 @@ idleAction tnew world = world { , told = tnew } where - anglePerSec = 5.0 - delta = anglePerSec * elapsed / 1000.0 + anglePerSec = 5.0 + delta = anglePerSec * elapsed / 1000.0 elapsed = fromIntegral (tnew - (told world))
    @@ -1901,7 +2081,7 @@ shapeFunc res x y = let z = maxZeroIndex (ymandel x y) 0 1 20 in - if and [ maxZeroIndex (ymandel (x+xeps) (y+yeps)) 0 1 20 < 0.000001 | + if and [ maxZeroIndex (ymandel (x+xeps) (y+yeps)) 0 1 20 < 0.000001 | val <- [res], xeps <- [-val,val], yeps<-[-val,val]] then Nothing else Just (z,colorFromValue ((ymandel x y z) * 64)) @@ -1913,9 +2093,9 @@ shapeFunc res x y = colorFromValue n = let t :: Point -> Scalar - t i = 0.7 + 0.3*cos( i / 10 ) + t i = 0.7 + 0.3*cos( i / 10 ) in - makeColor (t n) (t (n+5)) (t (n+10)) + makeColor (t n) (t (n+5)) (t (n+10))

    The rest is similar to the preceding sections.

    @@ -1933,8 +2113,8 @@ colorFromValue n = maxZeroIndex _ minval maxval 0 = (minval+maxval)/2 maxZeroIndex func minval maxval n = if (func medpoint) /= 0 - then maxZeroIndex func minval medpoint (n-1) - else maxZeroIndex func medpoint maxval (n-1) + then maxZeroIndex func minval medpoint (n-1) + else maxZeroIndex func medpoint maxval (n-1) where medpoint = (minval+maxval)/2 ymandel :: Point -> Point -> Point -> Point @@ -1961,8 +2141,8 @@ ymandel x y z = fromIntegral (ma
    -
    import YGL -- Most the OpenGL Boilerplate
    -import Mandel -- The 3D Mandelbrot maths
    +
    import YGL -- Most the OpenGL Boilerplate
    +import Mandel -- The 3D Mandelbrot maths
     
     -- Centralize all user input interaction
     inputActionMap :: InputMap World
    @@ -1974,16 +2154,16 @@ inputActionMap = inputMapFromList [
         ,(Press 'l' , rotate ydir (-5))
         ,(Press 'o' , rotate zdir 5)
         ,(Press 'u' , rotate zdir (-5))
    -    ,(Press 'f' , translate xdir 0.1)
    -    ,(Press 's' , translate xdir (-0.1))
    -    ,(Press 'e' , translate ydir 0.1)
    -    ,(Press 'd' , translate ydir (-0.1))
    -    ,(Press 'z' , translate zdir 0.1)
    -    ,(Press 'r' , translate zdir (-0.1))
    -    ,(Press '+' , zoom 1.1)
    -    ,(Press '-' , zoom (1/1.1))
    -    ,(Press 'h' , resize 2.0)
    -    ,(Press 'g' , resize (1/2.0))
    +    ,(Press 'f' , translate xdir 0.1)
    +    ,(Press 's' , translate xdir (-0.1))
    +    ,(Press 'e' , translate ydir 0.1)
    +    ,(Press 'd' , translate ydir (-0.1))
    +    ,(Press 'z' , translate zdir 0.1)
    +    ,(Press 'r' , translate zdir (-0.1))
    +    ,(Press '+' , zoom 1.1)
    +    ,(Press '-' , zoom (1/1.1))
    +    ,(Press 'h' , resize 2.0)
    +    ,(Press 'g' , resize (1/2.0))
         ]
    @@ -2031,7 +2211,7 @@ rotate dir angleValue world = switchRotation :: World -> World switchRotation world = world { - anglePerSec = if anglePerSec world > 0 then 0 else 5.0 } + anglePerSec = if anglePerSec world > 0 then 0 else 5.0 } translate :: Point3D -> Scalar -> World -> World translate dir len world = @@ -2058,12 +2238,12 @@ main = yMainLoop inputActionMap idleAction initialWorld< initialWorld :: World initialWorld = World { angle = makePoint3D (30,30,0) - , anglePerSec = 5.0 + , anglePerSec = 5.0 , position = makePoint3D (0,0,0) - , scale = 1.0 + , scale = 1.0 , box = Box3D { minPoint = makePoint3D (0-eps, 0-eps, 0-eps) , maxPoint = makePoint3D (0+eps, 0+eps, 0+eps) - , resolution = 0.02 } + , resolution = 0.02 } , told = 0 -- We declare cache directly this time , cache = objectFunctionFromWorld initialWorld @@ -2107,7 +2287,7 @@ idleAction tnew world = , told = tnew } where - delta = anglePerSec world * elapsed / 1000.0 + delta = anglePerSec world * elapsed / 1000.0 elapsed = fromIntegral (tnew - (told world)) shapeFunc :: Scalar -> Function3D @@ -2115,7 +2295,7 @@ shapeFunc res x y = let z = maxZeroIndex (ymandel x y) 0 1 20 in - if and [ maxZeroIndex (ymandel (x+xeps) (y+yeps)) 0 1 20 < 0.000001 | + if and [ maxZeroIndex (ymandel (x+xeps) (y+yeps)) 0 1 20 < 0.000001 | val <- [res], xeps <- [-val,val], yeps<-[-val,val]] then Nothing else Just (z,colorFromValue 0) @@ -2124,9 +2304,9 @@ shapeFunc res x y = colorFromValue n = let t :: Point -> Scalar - t i = 0.0 + 0.5*cos( i /10 ) + t i = 0.0 + 0.5*cos( i /10 ) in - makeColor (t n) (t (n+5)) (t (n+10)) + makeColor (t n) (t (n+5)) (t (n+10)) -- given f min max nbtest, -- considering @@ -2141,8 +2321,8 @@ colorFromValue n = maxZeroIndex _ minval maxval 0 = (minval+maxval)/2 maxZeroIndex func minval maxval n = if func medpoint /= 0 - then maxZeroIndex func minval medpoint (n-1) - else maxZeroIndex func medpoint maxval (n-1) + then maxZeroIndex func minval medpoint (n-1) + else maxZeroIndex func medpoint maxval (n-1) where medpoint = (minval+maxval)/2 ymandel :: Point -> Point -> Point -> Point @@ -2386,7 +2566,7 @@ Function declaration return x*x + y*y; }

    In Javascript:

    -
    function f(x,y) {
    +
    function f(x,y) {
         return x*x + y*y;
     }

    in Python:

    @@ -2426,7 +2606,7 @@ main = print (f f :: Int -> Int -> Int f x y = x*x + y*y -main = print (f 2.3 4.2)
    +main = print (f 2.3 4.2)

    You get this error:

    21_very_basic.lhs:6:23:
    @@ -2444,7 +2624,7 @@ main = print (f 
     
    f x y = x*x + y*y
     
    -main = print (f 2.3 4.2)
    +main = print (f 2.3 4.2)

    It works! Great, we don’t have to declare a new function for every single type. For example, in C, you’ll have to declare a function for int, for float, for long, for double, etc…

    But, what type should we declare? To discover the type Haskell has found for us, just launch ghci:

    @@ -2491,7 +2671,7 @@ g y ⇔ 3*3 + y*y
    f :: Num a => a -> a -> a
     f x y = x*x + y*y
     
    -main = print (f 3 2.4)
    +main = print (f 3 2.4)

    It works, because, 3 is a valid representation both for Fractional numbers like Float and for Integer. As 2.4 is a Fractional number, 3 is then interpreted as being also a Fractional number.

    01_basic/10_Introduction/23_very_basic.lhs

    @@ -2505,7 +2685,7 @@ f x y = x*x +x :: Int x = 3 y :: Float -y = 2.4 +y = 2.4 main = print (f x y) -- won't work because type x ≠ type y

    The compiler complains. The two parameters must have the same type.

    @@ -2694,9 +2874,9 @@ Functional style

    example: [1,2,3,4,5] ⇒ 2 + 4 ⇒ 6

    To show differences between the functional and imperative approach, I’ll start by providing an imperative solution (in Javascript):

    -
    function evenSum(list) {
    +
    function evenSum(list) {
         var result = 0;
    -    for (var i=0; i< list.length ; i++) {
    +    for (var i=0; i< list.length ; i++) {
             if (list[i] % 2 ==0) {
                 result += list[i];
             }
    @@ -2937,7 +3117,7 @@ myfunc list = foldl bar initialVa
     
    -- Version 6
     -- foldl' isn't accessible by default
     -- we need to import it from the module Data.List
    -import Data.List
    +import Data.List
     evenSum l = foldl' mysum 0 (filter even l)
       where mysum acc value = acc + value

    Version we can simplify by using directly a lambda notation. This way we don’t have to create the temporary name mysum.

    @@ -2945,7 +3125,7 @@ evenSum l = foldl' mysum 0 (
    -- Version 7
     -- Generally it is considered a good practice
     -- to import only the necessary function(s)
    -import Data.List (foldl')
    +import Data.List (foldl')
     evenSum l = foldl' (\x y -> x+y) 0 (filter even l)

    And of course, we note that

    @@ -2962,7 +3142,7 @@ evenSum l = foldl' (\x y ->02_Hard_Part/16_Functions.lhs

    Finally

    -- Version 8
    -import Data.List (foldl')
    +import Data.List (foldl')
     evenSum :: Integral a => [a] -> a
     evenSum l = foldl' (+) 0 (filter even l)

    foldl' isn’t the easiest function to intuit. If you are not used to it, you should study it a bit.

    @@ -2982,13 +3162,13 @@ evenSum l = foldl' (+) (f . g . h) x ⇔ f ( g (h x))

    We can take advantage of this operator to η-reduce our function:

    -- Version 9
    -import Data.List (foldl')
    +import Data.List (foldl')
     evenSum :: Integral a => [a] -> a
     evenSum = (foldl' (+) 0) . (filter even)

    Also, we could rename some parts to make it clearer:

    -- Version 10 
    -import Data.List (foldl')
    +import Data.List (foldl')
     sum' :: (Num a) => [a] -> a
     sum' = foldl' (+) 0
     evenSum :: Integral a => [a] -> a
    @@ -3140,9 +3320,9 @@ main = putStrLn And many accessors are made for you. Furthermore you can use another order when setting values.

    Example:

    data Complex = Num a => Complex { real :: a, img :: a}
    -c = Complex 1.0 2.0
    +c = Complex 1.0 2.0
     z = Complex { real = 3, img = 4 }
    -real c  1.0
    +real c  1.0
     img z  4

    02_Hard_Part/22_Types.lhs


    @@ -3186,7 +3366,7 @@ Trees

    Magritte, l

    We’ll just give another standard example: binary trees.

    -
    import Data.List
    +
    import Data.List
     
     data BinTree a = Empty
                      | Node a (BinTree a) (BinTree a)
    @@ -3391,7 +3571,7 @@ numbers = 0:map
     
     take' n [] = []
     take' 0 l = []
    -take' n (x:xs) = x:take' (n-1) xs
    +take' n (x:xs) = x:take' (n-1) xs
     
     main = print $ take' 10 numbers
    @@ -3409,8 +3589,8 @@ main = print $<

    This code is mostly the same as the previous one.

    -
    import Debug.Trace (trace)
    -import Data.List
    +
    import Debug.Trace (trace)
    +import Data.List
     data BinTree a = Empty 
                      | Node a (BinTree a) (BinTree a) 
                       deriving (Eq,Ord)
    @@ -3467,8 +3647,8 @@ main = print $< treeTakeDepth _ Empty = Empty treeTakeDepth 0 _ = Empty treeTakeDepth n (Node x left right) = let - nl = treeTakeDepth (n-1) left - nr = treeTakeDepth (n-1) right + nl = treeTakeDepth (n-1) left + nr = treeTakeDepth (n-1) right in Node x nl nr
    @@ -3494,8 +3674,8 @@ treeTakeDepth n (Node x left right) =
    iTree = Node 0 (dec iTree) (inc iTree)
             where
    -           dec (Node x l r) = Node (x-1) (dec l) (dec r) 
    -           inc (Node x l r) = Node (x+1) (inc l) (inc r) 
    + dec (Node x l r) = Node (x-1) (dec l) (dec r) + inc (Node x l r) = Node (x+1) (inc l) (inc r)

    Another way to create this tree is to use a higher order function. This function should be similar to map, but should work on BinTree instead of list. Here is such a function:

    @@ -3510,8 +3690,8 @@ treeMap f (Node x left right) =

    Our definition is now:

    infTreeTwo :: BinTree Int
    -infTreeTwo = Node 0 (treeMap (\x -> x-1) infTreeTwo) 
    -                    (treeMap (\x -> x+1) infTreeTwo) 
    +infTreeTwo = Node 0 (treeMap (\x -> x-1) infTreeTwo) + (treeMap (\x -> x+1) infTreeTwo)

    Look at the result for

    main = print $ treeTakeDepth 4 infTreeTwo
    @@ -3628,7 +3808,7 @@ main = do

    Argh! An evil error message and a crash! The first evolution will be to answer with a more friendly message.

    In order to do this, we must detect that something went wrong. Here is one way to do this. Use the type Maybe. It is a very common type in Haskell.

    -
    import Data.Maybe
    +
    import Data.Maybe

    What is this thing? Maybe is a type which takes one parameter. Its definition is:

    data Maybe a = Nothing | Just a
    @@ -3671,7 +3851,7 @@ main = do

    Our next evolution will be to prompt the user again and again until she enters a valid answer.

    We keep the first part:

    -
    import Data.Maybe
    +
    import Data.Maybe
     
     maybeRead :: Read a => String -> Maybe a
     maybeRead s = case reads s of
    @@ -3934,7 +4114,7 @@ main = do
       print $ sum list

    Is translated into:

    -
    import Data.Maybe
    +
    import Data.Maybe
     
     maybeRead :: Read a => String -> Maybe a
     maybeRead s = case reads s of
    @@ -4107,7 +4287,7 @@ The list monad
     

    Golconde de Magritte

    The list monad helps us to simulate non deterministic computations. Here we go:

    -
    import Control.Monad (guard)
    +
    import Control.Monad (guard)
     
     allCases = [1..10]
     
    @@ -4163,7 +4343,7 @@ More on Infinite Tree
     
     

    This code is mostly the same as the one in the tree section.

    -
    import Data.List
    +
    import Data.List
     data BinTree a = Empty 
                      | Node a (BinTree a) (BinTree a) 
                       deriving (Eq,Ord)
    @@ -4224,8 +4404,8 @@ treeFromList (x:xs) = treeTakeDepth _ Empty = Empty
     treeTakeDepth 0 _     = Empty
     treeTakeDepth n (Node x left right) = let
    -          nl = treeTakeDepth (n-1) left
    -          nr = treeTakeDepth (n-1) right
    +          nl = treeTakeDepth (n-1) left
    +          nr = treeTakeDepth (n-1) right
               in
                   Node x nl nr
    @@ -4275,8 +4455,8 @@ treeTakeDepth 4 (treeFromList shuffle)

    This code is mostly the same as the preceding one.

    -
    import Debug.Trace (trace)
    -import Data.List
    +
    import Debug.Trace (trace)
    +import Data.List
     data BinTree a = Empty 
                      | Node a (BinTree a) (BinTree a) 
                       deriving (Eq,Ord)
    @@ -4323,8 +4503,8 @@ treeTakeDepth 4 (treeFromList shuffle) treeTakeDepth _ Empty = Empty treeTakeDepth 0 _ = Empty treeTakeDepth n (Node x left right) = let - nl = treeTakeDepth (n-1) left - nr = treeTakeDepth (n-1) right + nl = treeTakeDepth (n-1) left + nr = treeTakeDepth (n-1) right in Node x nl nr
    @@ -4368,7 +4548,7 @@ safefilter f l = safefilter' f l nbTry safefilter' f (x:xs) n = if f x then x : safefilter' f xs nbTry - else safefilter' f xs (n-1)
    + else safefilter' f xs (n-1)

    Now run the program and be happy:

    @@ -4573,7 +4753,7 @@ static/tmp
  • config/models
  • Obviously:

    -

    config/routes | is where you’ll configure the map %url → Code. |
    Handler/ | contains the files that will contain the code called when a %url is accessed. |
    templates/ | contains html, js and css templates. |
    config/models | is where you’ll configure the persistent objects (database tables). |

    +

    config/routes | is where you’ll configure the map url → Code. |
    Handler/ | contains the files that will contain the code called when a url is accessed. |
    templates/ | contains html, js and css templates. |
    config/models | is where you’ll configure the persistent objects (database tables). |

    During this tutorial we’ll modify other files as well, but we won’t explore them in detail.

    Also note, shell commands are executed in the root directory of your project instead specified otherwise.

    We are now ready to start!

    @@ -4583,7 +4763,7 @@ static/tmp

    Goal:

    Make a server that when accessed /echo/[some text] should return a web page containing “some text” inside an h1 bloc.

    -

    In a first time, we must declare the %url of the form /echo/... are meaningful. Let’s take a look at the file config/routes:

    +

    In a first time, we must declare the url of the form /echo/... are meaningful. Let’s take a look at the file config/routes:

     /static StaticR Static getStatic
     /auth   AuthR   Auth   getAuth
    @@ -4599,7 +4779,7 @@ static/tmp
     /echo/#String EchoR GET
     
    -

    This line contains three elements: the %url pattern, a handler name, an %http method. I am not particularly fan of the big R notation but this is the standard convention.

    +

    This line contains three elements: the url pattern, a handler name, an %http method. I am not particularly fan of the big R notation but this is the standard convention.

    If you save config/routes, you should see your terminal in which you launched yesod devel activate and certainly displaying an error message.

     Application.hs:31:1: Not in scope: `getEchoR'
    @@ -4616,12 +4796,12 @@ getEchoR theText = do
     

    TADA! It works!

    Bulletproof?

    Neo stops a myriad of bullets

    -

    Even this extremely minimal web application has some impressive properties. For exemple, imagine an attacker entering this %url:

    +

    Even this extremely minimal web application has some impressive properties. For exemple, imagine an attacker entering this url:

    [http://localhost:3000/echo/<a>I'm <script>alert("Bad!");](http://localhost:3000/echo/I’m

    " %>

    The special characters are protected for us. A malicious user could not hide some bad script inside.

    -

    This behavior is a direct consequence of type safety. The %url string is put inside a %url type. Then the interesting part in the %url is put inside a String type. To pass from %url type to String type some transformation are made. For example, replace all “%20” by space characters. Then to show the String inside an html document, the string is put inside an html type. Some transformations occurs like replace “<” by “&lt;”. Thanks to yesod, this tedious job is done for us.

    +

    This behavior is a direct consequence of type safety. The url string is put inside a url type. Then the interesting part in the url is put inside a String type. To pass from url type to String type some transformation are made. For example, replace all “%20” by space characters. Then to show the String inside an html document, the string is put inside an html type. Some transformations occurs like replace “<” by “&lt;”. Thanks to yesod, this tedious job is done for us.

    "http://localhost:3000/echo/some%20text<a>" :: URL
                         ↓
                   "some text<a>"                 :: String
    @@ -4666,7 +4846,7 @@ a:visited { col
     

    Generally you don’t want to have all your code inside a unique file. This is why we will separate our handlers. In a first time create a new file Handler/Echo.hs containing:

    module Handler.Echo where
     
    -import Import
    +import Import
     
     getEchoR :: String -> Handler RepHtml
     getEchoR theText = do
    @@ -4679,7 +4859,7 @@ getEchoR theText = do
     

    We must also declare this new Handler module inside Application.hs. Just after the “import Handler.Home”, add:

    -
    import Handler.Echo
    +
    import Handler.Echo

    This is it.

    ps: I am sure not so far in the future we could simply write yesod add-handler Echo to declare it and create a new handler file.

    Data.Text

    @@ -4694,7 +4874,7 @@ getEchoR theText = do

    And do the same in Handler/Echo.hs:

    module Handler.Echo where
     
    -import Import
    +import Import
     
     getEchoR :: Text -> Handler RepHtml
     getEchoR theText = do
    @@ -4720,8 +4900,8 @@ getEchoR theText = do
     

    This time the path /mirror will accept GET and POST requests. Add the corresponding new Handler file:

    module Handler.Mirror where
     
    -import Import
    -import qualified Data.Text as T
    +import Import
    +import qualified Data.Text as T
     
     getMirrorR :: Handler RepHtml
     getMirrorR = do
    @@ -4779,11 +4959,11 @@ Article
         )
     where
     
    -import Import
    -import Data.Monoid
    +import Import
    +import Data.Monoid
     
     -- to use Html into forms
    -import Yesod.Form.Nic (YesodNic, nicHtmlField)
    +import Yesod.Form.Nic (YesodNic, nicHtmlField)
     instance YesodNic App

    Remark: it is a best practice to add the YesodNic instance inside Foundation.hs. I put this definition here to make things easier but you should see a warning about this orphan instance. To put the include inside Foundation.hs is left as an exercice to the reader.

    Hint: Do not forget to put YesodNic and nicHtmlField inside the exported objects of the module.

    @@ -4858,7 +5038,7 @@ getArticleR articleId = do
    <p>A last try to <em>cross script</em> 
        and <em>SQL injection</em></p>
     <p>Here is the first try: 
    -   <script>alert("You loose");</script></p>
    +   <script>alert("You loose");</script></p>
     <p> And Here is the last </p>
     "); DROP TABLE ARTICLE;;

    Conclusion

    @@ -5039,7 +5219,7 @@ getArticleR articleId = do SQL injection by a mom

    SQL injection by a mom

    When you create a web application, a lot of time is spent dealing with strings. Strings for URL, HTML, JavaScript, CSS, SQL, etc… To prevent malicious usage you have to protect each strings to be sure, no script will pass from one point to another. Suppose a user enter this user name:

    -
    Newton<script>alert("An apple fall")</script>
    +
    Newton<script>alert("An apple fall")</script>

    You must transform each < into &lt;. Without this transformation alert will appear each time you try to display this user name. Safe types associate with each string what kind of string it is. Is it a string for URL? For javascript? For HTML? And the right protection is made by default to prevent problems.

    Yesod does its best to handle cross scripting issues. Both between the client and the server and between the server and your DB. Here is an example:

    Go to the other page ~~~~~~

    @@ -5321,11 +5501,11 @@ done
  • The :t means tail; if toto=/path/to/file.ext then ${toto:t}=file.ext.
  • After ⇒

    -
    gif_to_png() { convert $1 ${1:r}.png && \rm -f $1 }
    +
    gif_to_png() { convert $1 ${1:r}.png && \rm -f $1 }
     
    -handle_resources() { map gif_to_png $1/resources/*.gif(.N) }
    +handle_resources() { map gif_to_png $1/resources/*.gif(.N) }
     
    -map handle_resources /path/to/projects/*(/N)
    +map handle_resources /path/to/projects/*(/N)

    No more bloc! It might be a little bit harder to read if you’re not used to functional programming notation. But it is more concise and robusts.

    Another example with some tests.

    Find all files in project not containing an s which their name contains their project name:

    @@ -5417,268 +5597,5 @@ function filter { print $result }
    ]]> - - Learn Vim Progressively - - http://yannesposito.com/Scratch/en/blog/Learn-Vim-Progressively/index.html - 2011-08-25T00:00:00Z - 2011-08-25T00:00:00Z - Über leet use vim!

    -
    - -

    tl;dr: You want to teach yourself vim (the best text editor known to human kind) in the fastest way possible. This is my way of doing it. You start by learning the minimal to survive, then you integrate all the tricks slowly.

    -
    - -

    Vim the Six Billion Dollar editor

    -
    -

    Better, Stronger, Faster.

    -
    -

    Learn vim and it will be your last text editor. There isn’t any better text editor that I know of. It is hard to learn, but incredible to use.

    -

    I suggest you teach yourself Vim in 4 steps:

    -
      -
    1. Survive
    2. -
    3. Feel comfortable
    4. -
    5. Feel Better, Stronger, Faster
    6. -
    7. Use superpowers of vim
    8. -
    -

    By the end of this journey, you’ll become a vim superstar.

    -

    But before we start, just a warning. Learning vim will be painful at first. It will take time. It will be a lot like playing a musical instrument. Don’t expect to be more efficient with vim than with another editor in less than 3 days. In fact it will certainly take 2 weeks instead of 3 days.

    -

    1st Level – Survive

    -
      -
    1. Install vim
    2. -
    3. Launch vim
    4. -
    5. DO NOTHING! Read.
    6. -
    -

    In a standard editor, typing on the keyboard is enough to write something and see it on the screen. Not this time. Vim is in Normal mode. Let’s go to Insert mode. Type the letter i.

    -

    You should feel a bit better. You can type letters like in a standard editor. To get back to Normal mode just press the ESC key.

    -

    You now know how to switch between Insert and Normal mode. And now, here are the commands that you need in order to survive in Normal mode:

    -
    -
      -
    • iInsert mode. Type ESC to return to Normal mode.
    • -
    • x → Delete the char under the cursor
    • -
    • :wq → Save and Quit (:w save, :q quit)
    • -
    • dd → Delete (and copy) the current line
    • -
    • p → Paste
    • -
    -

    Recommended:

    -
      -
    • hjkl (highly recommended but not mandatory) → basic cursor move (←↓↑→). Hint: j looks like a down arrow.
    • -
    • :help <command> → Show help about <command>. You can use :help without a <command> to get general help.
    • -
    -
    -

    Only 5 commands. That is all you need to get started. Once these command start to become natural (maybe after a day or so), you should move on to level 2.

    -

    But first, just a little remark about Normal mode. In standard editors, to copy you have to use the Ctrl key (Ctrl-c generally). In fact, when you press Ctrl, it is as if all of your keys change meaning. Using vim in normal mode is a bit like having the editor automatically press the Ctrl key for you.

    -

    A last word about notations:

    -
      -
    • instead of writing Ctrl-λ, I’ll write <C-λ>.
    • -
    • commands starting with : end with <enter>. For example, when I write :q, I mean :q<enter>.
    • -
    -

    2nd Level – Feel comfortable

    -

    You know the commands required for survival. It’s time to learn a few more commands. These are my suggestions:

    -
      -
    1. Insert mode variations:

      -
      -
        -
      • a → insert after the cursor
      • -
      • o → insert a new line after the current one
      • -
      • O → insert a new line before the current one
      • -
      • cw → replace from the cursor to the end of the word
      • -
      -
    2. -
    3. Basic moves

      -
      -
        -
      • 0 → go to the first column
      • -
      • ^ → go to the first non-blank character of the line
      • -
      • $ → go to the end of line
      • -
      • g_ → go to the last non-blank character of line
      • -
      • /pattern → search for pattern
      • -
      -
    4. -
    5. Copy/Paste

      -
      -
        -
      • P → paste before, remember p is paste after current position.
      • -
      • yy → copy the current line, easier but equivalent to ddP
      • -
      -
    6. -
    7. Undo/Redo

      -
      -
        -
      • u → undo
      • -
      • <C-r> → redo
      • -
      -
    8. -
    9. Load/Save/Quit/Change File (Buffer)

      -
      -
        -
      • :e <path/to/file> → open
      • -
      • :w → save
      • -
      • :saveas <path/to/file> → save to <path/to/file>
      • -
      • :x, ZZ or :wq → save and quit (:x only save if necessary)
      • -
      • :q! → quit without saving, also: :qa! to quit even if there are modified hidden buffers.
      • -
      • :bn (resp. :bp) → show next (resp. previous) file (buffer)
      • -
      -
    10. -
    -

    Take the time to learn all of these command. Once done, you should be able to do every thing you are able to do in other editors. You may still feel a bit awkward. But follow me to the next level and you’ll see why vim is worth the extra work.

    -

    3rd Level – Better. Stronger. Faster.

    -

    Congratulation for reaching this far! Now we can start with the interesting stuff. At level 3, we’ll only talk about commands which are compatible with the old vi editor.

    -

    Better

    -

    Let’s look at how vim could help you to repeat yourself:

    -
      -
    1. . → (dot) will repeat the last command,
    2. -
    3. N<command> → will repeat the command N times.
    4. -
    -

    Some examples, open a file and type:

    -
    -
      -
    • 2dd → will delete 2 lines
    • -
    • 3p → will paste the text 3 times
    • -
    • 100idesu [ESC] → will write “desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu”
    • -
    • . → Just after the last command will write again the 100 “desu”.
    • -
    • 3. → Will write 3 “desu” (and not 300, how clever).
    • -
    -
    -

    Stronger

    -

    Knowing how to move efficiently with vim is very important. Don’t skip this section.

    -
      -
    1. NG → Go to line N
    2. -
    3. gg → shortcut for 1G - go to the start of the file
    4. -
    5. G → Go to last line
    6. -
    7. Word moves:

      -
      -
        -
      1. w → go to the start of the following word,
      2. -
      3. e → go to the end of this word.
      4. -
      -

      By default, words are composed of letters and the underscore character. Let’s call a WORD a group of letter separated by blank characters. If you want to consider WORDS, then just use uppercase characters:

      -
        -
      1. W → go to the start of the following WORD,
      2. -
      3. E → go to the end of this WORD.
      4. -
      -

      Word moves example

      -
    8. -
    -

    Now let’s talk about very efficient moves:

    -
    -
      -
    • % : Go to the corresponding (, {, [.
    • -
    • * (resp. #) : go to next (resp. previous) occurrence of the word under the cursor
    • -
    -
    -

    Believe me, the last three commands are gold.

    -

    Faster

    -

    Remember about the importance of vi moves? Here is the reason. Most commands can be used using the following general format:

    -

    <start position><command><end position>

    -

    For example : 0y$ means

    -
      -
    • 0 → go to the beginning of this line
    • -
    • y → yank from here
    • -
    • $ → up to the end of this line
    • -
    -

    We also can do things like ye, yank from here to the end of the word. But also y2/foo yank up to the second occurrence of “foo”.

    -

    But what was true for y (yank), is also true for d (delete), v (visual select), gU (uppercase), gu (lowercase), etc…

    -

    4th Level – Vim Superpowers

    -

    With all preceding commands you should be comfortable using vim. But now, here are the killer features. Some of these features were the reason I started to use vim.

    -

    Move on current line: 0 ^ $ g_ f F t T , ;

    -
    -
      -
    • 0 → go to column 0
    • -
    • ^ → go to first character on the line
    • -
    • $ → go to the last column
    • -
    • g_ → go to the last character on the line
    • -
    • fa → go to next occurrence of the letter a on the line. , (resp. ;) will find the next (resp. previous) occurrence.
    • -
    • t, → go to just before the character ,.
    • -
    • 3fa → find the 3rd occurrence of a on this line.
    • -
    • F and T → like f and t but backward. Line moves
    • -
    -
    -

    A useful tip is: dt" → remove everything until the ".

    -

    Zone selection <action>a<object> or <action>i<object>

    -

    These command can only be used after an operator in visual mode. But they are very powerful. Their main pattern is:

    -

    <action>a<object> and <action>i<object>

    -

    Where action can be any action, for example, d (delete), y (yank), v (select in visual mode). The object can be: w a word, W a WORD (extended word), s a sentence, p a paragraph. But also, natural character such as ", ', ), }, ].

    -

    Suppose the cursor is on the first o of (map (+) ("foo")).

    -
    -
      -
    • vi" → will select foo.
    • -
    • va" → will select "foo".
    • -
    • vi) → will select "foo".
    • -
    • va) → will select ("foo").
    • -
    • v2i) → will select map (+) ("foo")
    • -
    • v2a) → will select (map (+) ("foo"))
    • -
    -
    -

    Text objects selection

    -

    Select rectangular blocks: <C-v>.

    -

    Rectangular blocks are very useful for commenting many lines of code. Typically: 0<C-v><C-d>I-- [ESC]

    -
      -
    • ^ → go to the first non-blank character of the line
    • -
    • <C-v> → Start block selection
    • -
    • <C-d> → move down (could also be jjj or %, etc…)
    • -
    • I-- [ESC] → write -- to comment each line
    • -
    -

    Rectangular blocks

    -

    Note: in Windows you might have to use <C-q> instead of <C-v> if your clipboard is not empty.

    -

    Completion: <C-n> and <C-p>.

    -

    In Insert mode, just type the start of a word, then type <C-p>, magic… Completion

    -

    Macros : qa do something q, @a, @@

    -

    qa record your actions in the register a. Then @a will replay the macro saved into the register a as if you typed it. @@ is a shortcut to replay the last executed macro.

    -
    -

    Example

    -

    On a line containing only the number 1, type this:

    -
      -
    • qaYp<C-a>q

    • -
    • qa start recording.
    • -
    • Yp duplicate this line.
    • -
    • <C-a> increment the number.
    • -
    • q stop recording.

    • -
    • @a → write 2 under the 1
    • -
    • @@ → write 3 under the 2
    • -
    • Now do 100@@ will create a list of increasing numbers until 103.

    • -
    -
    -

    Macros

    -

    Visual selection: v,V,<C-v>

    -

    We saw an example with <C-v>. There is also v and V. Once the selection has been made, you can:

    -
      -
    • J → join all the lines together.
    • -
    • < (resp. >) → indent to the left (resp. to the right).
    • -
    • = → auto indent
    • -
    -

    Autoindent

    -

    Add something at the end of all visually selected lines:

    -
      -
    • <C-v>
    • -
    • go to desired line (jjj or <C-d> or /pattern or % etc…)
    • -
    • $ go to the end of the line
    • -
    • A, write text, ESC.
    • -
    -

    Append to many lines

    -

    Splits: :split and vsplit.

    -

    These are the most important commands, but you should look at :help split.

    -
    -
      -
    • :split → create a split (:vsplit create a vertical split)
    • -
    • <C-w><dir> : where dir is any of hjkl or ←↓↑→ to change the split.
    • -
    • <C-w>_ (resp. <C-w>|) : maximise the size of the split (resp. vertical split)
    • -
    • <C-w>+ (resp. <C-w>-) : Grow (resp. shrink) split
    • -
    -
    -

    Split

    -

    Conclusion

    -

    That was 90% of the commands I use every day. I suggest that you learn no more than one or two new commands per day. After two to three weeks you’ll start to feel the power of vim in your hands.

    -

    Learning Vim is more a matter of training than plain memorization. Fortunately vim comes with some very good tools and excellent documentation. Run vimtutor until you are familiar with most basic commands. Also, you should read this page carefully: :help usr_02.txt.

    -

    Then, you will learn about !, folds, registers, plugins and many other features. Learn vim like you’d learn piano and all should be fine.

    - - -]]>
    - diff --git a/Scratch/en/blog/index.html b/Scratch/en/blog/index.html index df6106f..e52e41b 100644 --- a/Scratch/en/blog/index.html +++ b/Scratch/en/blog/index.html @@ -103,6 +103,9 @@ Learn Haskell Fast and Hard »
    -
    @@ -49,7 +41,7 @@

    MVC explained

    -
    +

    Why This article and for whom?

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

    @@ -69,25 +61,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -105,6 +98,7 @@ comments powered by Disqus
    +
    Published on 2009-07-06 diff --git a/Scratch/en/blog/programming-language-experience/index.html b/Scratch/en/blog/programming-language-experience/index.html index 5b552eb..11d8b7f 100644 --- a/Scratch/en/blog/programming-language-experience/index.html +++ b/Scratch/en/blog/programming-language-experience/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Programming Language Experience

    -
    +

    Title image

    @@ -209,25 +201,26 @@ X=whatever[C,D]
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + These social sharing links preserve your privacy
    + +

    Comments

    @@ -245,6 +238,7 @@ X=whatever[C,D]
    comments powered by Disqus
    +
    Published on 2011-09-28 diff --git a/Scratch/fr/about/old/index.html b/Scratch/fr/about/old/index.html index 296bcb9..793c839 100644 --- a/Scratch/fr/about/old/index.html +++ b/Scratch/fr/about/old/index.html @@ -60,7 +60,7 @@
    diff --git a/Scratch/fr/blog/01_nanoc/index.html b/Scratch/fr/blog/01_nanoc/index.html index c348003..c14214c 100644 --- a/Scratch/fr/blog/01_nanoc/index.html +++ b/Scratch/fr/blog/01_nanoc/index.html @@ -32,16 +32,8 @@ document.write(''); // +
    -
    -
    @@ -49,7 +41,7 @@

    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.

    @@ -59,25 +51,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -95,6 +88,7 @@ comments powered by Disqus
    +
    Published on 2008-10-10 diff --git a/Scratch/fr/blog/02_ackgrep/index.html b/Scratch/fr/blog/02_ackgrep/index.html index 757e899..0a0013b 100644 --- a/Scratch/fr/blog/02_ackgrep/index.html +++ b/Scratch/fr/blog/02_ackgrep/index.html @@ -32,16 +32,8 @@ document.write(''); // +
    -
    -
    @@ -49,7 +41,7 @@

    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.

    @@ -74,25 +66,26 @@ listeFic=( /(.) ) autoload zargs zargs – $listeFic – grep $1 |
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -110,6 +103,7 @@ listeFic=( /(.) ) autoload zargs zargs – $listeFic – grep $1 | comments powered by Disqus
    +
    Published on 2009-07-22 diff --git a/Scratch/fr/blog/03_losthighway/index.html b/Scratch/fr/blog/03_losthighway/index.html index 1fd3444..7949161 100644 --- a/Scratch/fr/blog/03_losthighway/index.html +++ b/Scratch/fr/blog/03_losthighway/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Lost Highway démystifié (un peu)

    -
    +

    Lost Highway

    @@ -133,25 +125,26 @@ Lost Highway ne laisse pas indiférent. Le revoir ne lasse pas même s’il parr
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -169,6 +162,7 @@ Lost Highway ne laisse pas indiférent. Le revoir ne lasse pas même s’il parr comments powered by Disqus
    +
    Published on 2009-08-04 diff --git a/Scratch/fr/blog/04_drm/index.html b/Scratch/fr/blog/04_drm/index.html index 7bae0af..13b8940 100644 --- a/Scratch/fr/blog/04_drm/index.html +++ b/Scratch/fr/blog/04_drm/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Les protections anti-copies sont LE MAL

    -
    +

    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 !

    @@ -70,25 +62,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -106,6 +99,7 @@ comments powered by Disqus
    +
    Published on 2009-08-15 diff --git a/Scratch/fr/blog/05_git_create_remote_branch/index.html b/Scratch/fr/blog/05_git_create_remote_branch/index.html index 78eb5f4..7b0fc39 100644 --- a/Scratch/fr/blog/05_git_create_remote_branch/index.html +++ b/Scratch/fr/blog/05_git_create_remote_branch/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

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

    @@ -66,25 +58,26 @@ branch=1gitbr
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -102,6 +95,7 @@ branch=1gitbrPlease enable JavaScript to view the comments powered by Disqus. comments powered by Disqus
    +
    Published on 2009-08-17 diff --git a/Scratch/fr/blog/06_How_I_use_git/index.html b/Scratch/fr/blog/06_How_I_use_git/index.html index f99fbef..47f8ce5 100644 --- a/Scratch/fr/blog/06_How_I_use_git/index.html +++ b/Scratch/fr/blog/06_How_I_use_git/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Git en solo

    -
    +

    central architecture

    @@ -184,25 +176,26 @@ done
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -220,6 +213,7 @@ done
    comments powered by Disqus
    +
    Published on 2009-08-18 diff --git a/Scratch/fr/blog/07_Screensaver_compilation_option_for_Snow_Leopard/index.html b/Scratch/fr/blog/07_Screensaver_compilation_option_for_Snow_Leopard/index.html index 718953e..208359a 100644 --- a/Scratch/fr/blog/07_Screensaver_compilation_option_for_Snow_Leopard/index.html +++ b/Scratch/fr/blog/07_Screensaver_compilation_option_for_Snow_Leopard/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Compilation d'économiseur d'écran sous Snow Leopard©

    -
    +

    Comment recompiler un économiseur d’écran sous Snow Leopard(c)

    Mon économiseur d’écran ne fonctionnait plus sous Mac OS X 10.6 Snow Leopard(c). 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.

    @@ -60,25 +52,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -96,6 +89,7 @@ comments powered by Disqus
    +
    Published on 2009-09-06 diff --git a/Scratch/fr/blog/08_Configure_ssh_to_listen_the_port_443_on_Snow_Leopard/index.html b/Scratch/fr/blog/08_Configure_ssh_to_listen_the_port_443_on_Snow_Leopard/index.html index 2d022ef..ec9b1f6 100644 --- a/Scratch/fr/blog/08_Configure_ssh_to_listen_the_port_443_on_Snow_Leopard/index.html +++ b/Scratch/fr/blog/08_Configure_ssh_to_listen_the_port_443_on_Snow_Leopard/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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.

    @@ -111,25 +103,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -147,6 +140,7 @@ comments powered by Disqus
    +
    Published on 2009-09-07 diff --git a/Scratch/fr/blog/09_Why_I_didn-t_keep_whosamung-us/index.html b/Scratch/fr/blog/09_Why_I_didn-t_keep_whosamung-us/index.html index 3874157..8f982f6 100644 --- a/Scratch/fr/blog/09_Why_I_didn-t_keep_whosamung-us/index.html +++ b/Scratch/fr/blog/09_Why_I_didn-t_keep_whosamung-us/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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.

    @@ -66,25 +58,26 @@ Google Analytics > Who’s Amung Us
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -102,6 +95,7 @@ Google Analytics > Who’s Amung Us comments powered by Disqus
    +
    Published on 2009-09-11 diff --git a/Scratch/fr/blog/10_Synchronize_Custom_WebSite_with_mobileMe/index.html b/Scratch/fr/blog/10_Synchronize_Custom_WebSite_with_mobileMe/index.html index b202aad..0d1a342 100644 --- a/Scratch/fr/blog/10_Synchronize_Custom_WebSite_with_mobileMe/index.html +++ b/Scratch/fr/blog/10_Synchronize_Custom_WebSite_with_mobileMe/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Héberger son site personnel sur le site mobileMe

    -
    +

    Mise à jour du (2012/01/11)

    iDisk va bientôt disparaître. Cet article est donc presque complètement obsolète.

    @@ -284,25 +276,26 @@ print -P -- " Publish terminated"
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -320,6 +313,7 @@ print -P -- " Publish terminated" comments powered by Disqus
    +
    Published on 2009-09-11 diff --git a/Scratch/fr/blog/11_Load_Disqus_Asynchronously/index.html b/Scratch/fr/blog/11_Load_Disqus_Asynchronously/index.html index af37d50..e956657 100644 --- a/Scratch/fr/blog/11_Load_Disqus_Asynchronously/index.html +++ b/Scratch/fr/blog/11_Load_Disqus_Asynchronously/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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.

    @@ -73,14 +65,14 @@

    Javascript

    replace:

    -
    <script type="text/javascript" src="http://disqus.com/forums/YOUR_DISQUS_ID/embed.js"></script>
    +
    <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");
    +
    window.disqus_no_style=true;
    +$(document).ready(function(){
    +    $.getScript("http://disqus.com/forums/YOUR_DISQUS_ID/embed.js");
     });
    @@ -92,25 +84,26 @@ $(document).ready( - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -128,6 +121,7 @@ $(document).ready(comments powered by Disqus. comments powered by Disqus
    +
    Published on 2009-09-17 diff --git a/Scratch/fr/blog/2009-09-Disqus-versus-Intense-Debate--Why-I-switched-/index.html b/Scratch/fr/blog/2009-09-Disqus-versus-Intense-Debate--Why-I-switched-/index.html index 51be9a1..829c1df 100644 --- a/Scratch/fr/blog/2009-09-Disqus-versus-Intense-Debate--Why-I-switched-/index.html +++ b/Scratch/fr/blog/2009-09-Disqus-versus-Intense-Debate--Why-I-switched-/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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.

    @@ -59,13 +51,13 @@

    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);
    +
    document.getElementsByTagName("head")[0].appendChild(commentScript);

    par (si vous utilisez jQuery) :

    -
    $(document).ready( function() {
    -    document.getElementsByTagName("head")[0].appendChild(commentScript);
    +
    $(document).ready( function() {
    +    document.getElementsByTagName("head")[0].appendChild(commentScript);
     });
    @@ -79,25 +71,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -115,6 +108,7 @@ comments powered by Disqus
    +
    Published on 2009-09-28 diff --git a/Scratch/fr/blog/2009-09-jQuery-Tag-Cloud/index.html b/Scratch/fr/blog/2009-09-jQuery-Tag-Cloud/index.html index 1f70200..e4ce7e6 100644 --- a/Scratch/fr/blog/2009-09-jQuery-Tag-Cloud/index.html +++ b/Scratch/fr/blog/2009-09-jQuery-Tag-Cloud/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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.

    @@ -64,12 +56,12 @@

    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');
    +
        $(document).ready( function(){$('.list').hide();} );
    +    function tagSelected(id) {
    +        $('.list').hide();
    +        $('#'+id).fadeIn();
    +        $('.tag.selected').removeClass('selected');
    +        $('#tag_'+id).addClass('selected');
         }
    @@ -248,25 +240,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -284,6 +277,7 @@ comments powered by Disqus
    +
    Published on 2009-09-23 diff --git a/Scratch/fr/blog/2009-09-replace-all-except-some-part/index.html b/Scratch/fr/blog/2009-09-replace-all-except-some-part/index.html index 6c81b63..d0fd3ed 100644 --- a/Scratch/fr/blog/2009-09-replace-all-except-some-part/index.html +++ b/Scratch/fr/blog/2009-09-replace-all-except-some-part/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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

    @@ -123,25 +115,26 @@ allExceptCode(:filter, content)
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -159,6 +152,7 @@ allExceptCode(:filter, content) comments powered by Disqus
    +
    Published on 2009-09-22 diff --git a/Scratch/fr/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/index.html b/Scratch/fr/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/index.html index 64d2f99..b9b0236 100644 --- a/Scratch/fr/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/index.html +++ b/Scratch/fr/blog/2009-10-28-custom-website-synchronisation-with-mobileme--2-/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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.

    @@ -136,25 +128,26 @@ fi
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -172,6 +165,7 @@ fi
    comments powered by Disqus
    +
    Published on 2009-10-28 diff --git a/Scratch/fr/blog/2009-10-30-How-to-handle-evil-IE/index.html b/Scratch/fr/blog/2009-10-30-How-to-handle-evil-IE/index.html index 95a17ad..69e282d 100644 --- a/Scratch/fr/blog/2009-10-30-How-to-handle-evil-IE/index.html +++ b/Scratch/fr/blog/2009-10-30-How-to-handle-evil-IE/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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.

    @@ -76,25 +68,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +

    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -112,6 +105,7 @@ comments powered by Disqus
    +
    Published on 2009-10-30 diff --git a/Scratch/fr/blog/2009-10-Focus-vs-Minimalism/index.html b/Scratch/fr/blog/2009-10-Focus-vs-Minimalism/index.html index 4fa6ea1..d51f7bd 100644 --- a/Scratch/fr/blog/2009-10-Focus-vs-Minimalism/index.html +++ b/Scratch/fr/blog/2009-10-Focus-vs-Minimalism/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Focus > Minimalisme

    -
    +

    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.

    @@ -74,19 +66,19 @@ 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 hideMenu() {
    +    $('#entete').animate({left:"-10em"}, 500 );
    +    $('#menuButton').html('&rarr;');
     }
    -function showMenu() {
    -    $('#entete').animate({left:"0em"}, 500 );
    -    $('#menuButton').html('&larr;');
    +function showMenu() {
    +    $('#entete').animate({left:"0em"}, 500 );
    +    $('#menuButton').html('&larr;');
     }
    -function toggleMenu() {
    -    if ( $('#entete').css('left')=='-10em' ) {
    -        showMenu();
    +function toggleMenu() {
    +    if ( $('#entete').css('left')=='-10em' ) {
    +        showMenu();
         } else {
    -        hideMenu();
    +        hideMenu();
         }
     }
    @@ -95,25 +87,26 @@ top: 5em; left: 0; position: fixed; width: 10em; z-index: 9000; } ~~~~~~
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -131,6 +124,7 @@ top: 5em; left: 0; position: fixed; width: 10em; z-index: 9000; } ~~~~~~ comments powered by Disqus
    +
    Published on 2009-10-22 diff --git a/Scratch/fr/blog/2009-10-How-to-preload-your-site-with-style/index.html b/Scratch/fr/blog/2009-10-How-to-preload-your-site-with-style/index.html index 7b2f677..d34d4a9 100644 --- a/Scratch/fr/blog/2009-10-How-to-preload-your-site-with-style/index.html +++ b/Scratch/fr/blog/2009-10-How-to-preload-your-site-with-style/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Charger une page web avec style

    -
    +

    Exemple

    Voici comment apparaissent mes pages pendant leur chargement.

    @@ -114,8 +106,8 @@ Loading… ainsi que le code jQuery associé :

    -
    $(document).ready(function(){
    -    $('#blackpage').fadeOut();
    +
    $(document).ready(function(){
    +    $('#blackpage').fadeOut();
     });
    @@ -124,25 +116,26 @@ Loading…
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -160,6 +153,7 @@ Loading… Please enable JavaScript to view the comments powered by Disqus. comments powered by Disqus
    +
    Published on 2009-10-03 diff --git a/Scratch/fr/blog/2009-10-Wait-to-hide-a-menu-in-jQuery/index.html b/Scratch/fr/blog/2009-10-Wait-to-hide-a-menu-in-jQuery/index.html index 0c7fb79..5da1186 100644 --- a/Scratch/fr/blog/2009-10-Wait-to-hide-a-menu-in-jQuery/index.html +++ b/Scratch/fr/blog/2009-10-Wait-to-hide-a-menu-in-jQuery/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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

    @@ -102,25 +94,26 @@ autoHideMenu(0);
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -138,6 +131,7 @@ autoHideMenu(0);
    comments powered by Disqus
    +
    Published on 2009-10-26 diff --git a/Scratch/fr/blog/2009-10-launch-daemon-from-command-line/index.html b/Scratch/fr/blog/2009-10-launch-daemon-from-command-line/index.html index 4872bc0..bb63820 100644 --- a/Scratch/fr/blog/2009-10-launch-daemon-from-command-line/index.html +++ b/Scratch/fr/blog/2009-10-launch-daemon-from-command-line/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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 :

    @@ -62,25 +54,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -98,6 +91,7 @@ comments powered by Disqus
    +
    Published on 2009-10-23 diff --git a/Scratch/fr/blog/2009-10-untaught-git-usage/index.html b/Scratch/fr/blog/2009-10-untaught-git-usage/index.html index ead7a9c..9f22a44 100644 --- a/Scratch/fr/blog/2009-10-untaught-git-usage/index.html +++ b/Scratch/fr/blog/2009-10-untaught-git-usage/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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.

    @@ -190,25 +182,26 @@ OK
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -226,6 +219,7 @@ OK comments powered by Disqus
    +
    Published on 2009-10-13 diff --git a/Scratch/fr/blog/2009-11-12-Git-for-n00b/index.html b/Scratch/fr/blog/2009-11-12-Git-for-n00b/index.html index 356df6d..ff1cc6d 100644 --- a/Scratch/fr/blog/2009-11-12-Git-for-n00b/index.html +++ b/Scratch/fr/blog/2009-11-12-Git-for-n00b/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Git pour les nuls

    -
    +
    @@ -431,25 +423,26 @@ $ git logfull
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -467,6 +460,7 @@ $ git logfull comments powered by Disqus
    +
    Published on 2009-11-12 diff --git a/Scratch/fr/blog/2009-12-06-iphone-call-filter/index.html b/Scratch/fr/blog/2009-12-06-iphone-call-filter/index.html index f645264..e8a5529 100644 --- a/Scratch/fr/blog/2009-12-06-iphone-call-filter/index.html +++ b/Scratch/fr/blog/2009-12-06-iphone-call-filter/index.html @@ -33,8 +33,32 @@ document.write(''); // +
    +
    + +
    +

    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

    +
    + +
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée +
    -
    - -
    -

    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

    -
    - -
    - - RSS - - - - - - -
    - -
    -
    -
    +

    Comments

    @@ -93,6 +86,7 @@ comments powered by Disqus
    +
    Published on 2009-12-06 diff --git a/Scratch/fr/blog/2009-12-14-Git-vs--Bzr/index.html b/Scratch/fr/blog/2009-12-14-Git-vs--Bzr/index.html index 6f0492d..bc5c1c8 100644 --- a/Scratch/fr/blog/2009-12-14-Git-vs--Bzr/index.html +++ b/Scratch/fr/blog/2009-12-14-Git-vs--Bzr/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Git ou Bazaar ?

    -
    +
    @@ -140,25 +132,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -176,6 +169,7 @@ comments powered by Disqus
    +
    Published on 2009-12-14 diff --git a/Scratch/fr/blog/2010-01-04-Change-default-shell-on-Mac-OS-X/index.html b/Scratch/fr/blog/2010-01-04-Change-default-shell-on-Mac-OS-X/index.html index f75d2f6..41c678b 100644 --- a/Scratch/fr/blog/2010-01-04-Change-default-shell-on-Mac-OS-X/index.html +++ b/Scratch/fr/blog/2010-01-04-Change-default-shell-on-Mac-OS-X/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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 :

    @@ -61,25 +53,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -97,6 +90,7 @@ comments powered by Disqus
    +
    Published on 2010-01-04 diff --git a/Scratch/fr/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/index.html b/Scratch/fr/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/index.html index 4b59b98..89c1681 100644 --- a/Scratch/fr/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/index.html +++ b/Scratch/fr/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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 :

    @@ -115,25 +107,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -151,6 +144,7 @@ comments powered by Disqus
    +
    Published on 2010-01-12 diff --git a/Scratch/fr/blog/2010-02-15-All-but-something-regexp/index.html b/Scratch/fr/blog/2010-02-15-All-but-something-regexp/index.html index 2c50776..76124d7 100644 --- a/Scratch/fr/blog/2010-02-15-All-but-something-regexp/index.html +++ b/Scratch/fr/blog/2010-02-15-All-but-something-regexp/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Expression régulière pour tout sauf quelquechose

    -
    +

    Parfois vous ne pouvez simplement pas écrire :

    @@ -89,25 +81,26 @@ Notez que cette méthode n’est pas toujours la meilleure. Par exemple essayons
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -125,6 +118,7 @@ Notez que cette méthode n’est pas toujours la meilleure. Par exemple essayons comments powered by Disqus
    +
    Published on 2010-02-15 diff --git a/Scratch/fr/blog/2010-02-16-All-but-something-regexp--2-/index.html b/Scratch/fr/blog/2010-02-16-All-but-something-regexp--2-/index.html index 8361715..6ff7bf4 100644 --- a/Scratch/fr/blog/2010-02-16-All-but-something-regexp--2-/index.html +++ b/Scratch/fr/blog/2010-02-16-All-but-something-regexp--2-/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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 :

    @@ -120,7 +112,7 @@ Cette chaine ne matchera pas. C’est pourquoi si on veut vraiment la matcher co
     

    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 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/wasx_/g s/Y/wasy_/g

    transforme la longue chaine de caractère

    en un seul caractère

    s/ @@ -134,7 +126,7 @@ s/X/
  • /g s/Y/</li>/g

    retour des anciens caractères.

    -s/was_x/X/g s/was_y/Y/g
    +s/wasx_/X/g s/wasy_/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.

    @@ -143,25 +135,26 @@ s/was_x/X/g s/was_y/Y/g
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -179,6 +172,7 @@ s/was_x/X/g s/was_y/Y/g comments powered by Disqus
    +
    Published on 2010-02-16 diff --git a/Scratch/fr/blog/2010-02-18-split-a-file-by-keyword/index.html b/Scratch/fr/blog/2010-02-18-split-a-file-by-keyword/index.html index 4c7761e..be661d7 100644 --- a/Scratch/fr/blog/2010-02-18-split-a-file-by-keyword/index.html +++ b/Scratch/fr/blog/2010-02-18-split-a-file-by-keyword/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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.

    @@ -71,25 +63,26 @@ Mon Dec 7 10:32:30 UTC 2009
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -107,6 +100,7 @@ Mon Dec 7 10:32:30 UTC 2009 comments powered by Disqus
    +
    Published on 2010-02-18 diff --git a/Scratch/fr/blog/2010-02-23-When-regexp-is-not-the-best-solution/index.html b/Scratch/fr/blog/2010-02-23-When-regexp-is-not-the-best-solution/index.html index 2a4654b..b5e4088 100644 --- a/Scratch/fr/blog/2010-02-23-When-regexp-is-not-the-best-solution/index.html +++ b/Scratch/fr/blog/2010-02-23-When-regexp-is-not-the-best-solution/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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à :

    @@ -97,25 +89,26 @@ chomp: 0.820000 0.040000 0.860000 ( 0.947432)
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -133,6 +126,7 @@ chomp: 0.820000 0.040000 0.860000 ( 0.947432) comments powered by Disqus
    +
    Published on 2010-02-23 diff --git a/Scratch/fr/blog/2010-03-22-Git-Tips/index.html b/Scratch/fr/blog/2010-03-22-Git-Tips/index.html index cd99b9f..b1a620e 100644 --- a/Scratch/fr/blog/2010-03-22-Git-Tips/index.html +++ b/Scratch/fr/blog/2010-03-22-Git-Tips/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Astuces Git

    -
    +

    Cloner de github à travers un pare-feu

    La façon standard:

    @@ -86,25 +78,26 @@ $ zsh $ cd project $ for br in (git
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -122,6 +115,7 @@ $ zsh $ cd project $ for br in (gitPlease enable JavaScript to view the comments powered by Disqus. comments powered by Disqus
    +
    Published on 2010-03-22 diff --git a/Scratch/fr/blog/2010-03-23-Encapsulate-git/index.html b/Scratch/fr/blog/2010-03-23-Encapsulate-git/index.html index d40becf..2795236 100644 --- a/Scratch/fr/blog/2010-03-23-Encapsulate-git/index.html +++ b/Scratch/fr/blog/2010-03-23-Encapsulate-git/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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

    @@ -110,25 +102,26 @@ case ARGV[0] when ‘allmerges’ then do_all_merges when ‘merge’ then do_me
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -146,6 +139,7 @@ case ARGV[0] when ‘allmerges’ then do_all_merges when ‘merge’ then do_me comments powered by Disqus
    +
    Published on 2010-03-23 diff --git a/Scratch/fr/blog/2010-05-17-at-least-this-blog-revive/index.html b/Scratch/fr/blog/2010-05-17-at-least-this-blog-revive/index.html index ebe7122..567f847 100644 --- a/Scratch/fr/blog/2010-05-17-at-least-this-blog-revive/index.html +++ b/Scratch/fr/blog/2010-05-17-at-least-this-blog-revive/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Je reviens à la vie !

    -
    +

    Bonjour à tous !

    @@ -76,25 +68,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -112,6 +105,7 @@ comments powered by Disqus
    +
    Published on 2010-05-17 diff --git a/Scratch/fr/blog/2010-05-19-How-to-cut-HTML-and-repair-it/index.html b/Scratch/fr/blog/2010-05-19-How-to-cut-HTML-and-repair-it/index.html index 6fdee27..8f8cfbe 100644 --- a/Scratch/fr/blog/2010-05-19-How-to-cut-HTML-and-repair-it/index.html +++ b/Scratch/fr/blog/2010-05-19-How-to-cut-HTML-and-repair-it/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Comment réparer un XML coupé ?

    -
    +

    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 :

    @@ -121,25 +113,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -157,6 +150,7 @@ comments powered by Disqus
    +
    Published on 2010-05-19 diff --git a/Scratch/fr/blog/2010-05-24-Trees--Pragmatism-and-Formalism/index.html b/Scratch/fr/blog/2010-05-24-Trees--Pragmatism-and-Formalism/index.html index e493d29..d0c2c49 100644 --- a/Scratch/fr/blog/2010-05-24-Trees--Pragmatism-and-Formalism/index.html +++ b/Scratch/fr/blog/2010-05-24-Trees--Pragmatism-and-Formalism/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Arbres ; Pragmatisme et Formalisme

    -
    +
    @@ -243,25 +235,26 @@ M - V - M - V - tag2 tag1
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -279,6 +272,7 @@ M - V - M - V - tag2 tag1 comments powered by Disqus
    +
    Published on 2010-05-24 diff --git a/Scratch/fr/blog/2010-06-14-multi-language-choices/index.html b/Scratch/fr/blog/2010-06-14-multi-language-choices/index.html index 806cfc7..88424a7 100644 --- a/Scratch/fr/blog/2010-06-14-multi-language-choices/index.html +++ b/Scratch/fr/blog/2010-06-14-multi-language-choices/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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.

    @@ -84,25 +76,26 @@ here is an example of english text.
     				
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -120,6 +113,7 @@ here is an example of english text. comments powered by Disqus
    +
    Published on 2010-06-14 diff --git a/Scratch/fr/blog/2010-06-15-Get-my-blog-engine/index.html b/Scratch/fr/blog/2010-06-15-Get-my-blog-engine/index.html index 821c7b6..dc3eacf 100644 --- a/Scratch/fr/blog/2010-06-15-Get-my-blog-engine/index.html +++ b/Scratch/fr/blog/2010-06-15-Get-my-blog-engine/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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 ?

    @@ -119,25 +111,26 @@ multi/blog/2010-06-01-the-title/third_part.md
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -155,6 +148,7 @@ multi/blog/2010-06-01-the-title/third_part.md comments powered by Disqus
    +
    Published on 2010-06-15 diff --git a/Scratch/fr/blog/2010-06-17-hide-yourself-to-analytics/index.html b/Scratch/fr/blog/2010-06-17-hide-yourself-to-analytics/index.html index 7e8a69a..5ee6cef 100644 --- a/Scratch/fr/blog/2010-06-17-hide-yourself-to-analytics/index.html +++ b/Scratch/fr/blog/2010-06-17-hide-yourself-to-analytics/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,16 +42,16 @@

    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');
    +
        var admin = $.cookie('admin');
         if (! admin) {
             // put your analytics code here
         } else {
    -        console.log("[WARNING] you're HIDDEN to analytics");
    +        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"?>
    @@ -72,8 +64,8 @@
             <script type="text/javascript" src="jquery.cookie.js"></script>
             <script>
                 $(document).ready(function(){
    -                $.cookie('admin',1);
    -                $('#info').html('Analytics can no more see you.')
    +                $.cookie('admin',1);
    +                $('#info').html('Analytics can no more see you.')
                 });
             </script>
             <title>Hide to analytics</title>
    @@ -93,8 +85,8 @@
             <script type="text/javascript" src="jquery.cookie.js"></script>
             <script>
                 $(document).ready(function(){
    -                $.cookie('admin',null);
    -                $('#info').html('Analytics can see you.')
    +                $.cookie('admin',null);
    +                $('#info').html('Analytics can see you.')
                 });
             </script>
             <title>Hide to analytics</title>
    @@ -107,25 +99,26 @@
     				
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -143,6 +136,7 @@ comments powered by Disqus
    +
    Published on 2010-06-17 diff --git a/Scratch/fr/blog/2010-06-17-track-events-with-google-analytics/index.html b/Scratch/fr/blog/2010-06-17-track-events-with-google-analytics/index.html index c8ffb3b..83484c2 100644 --- a/Scratch/fr/blog/2010-06-17-track-events-with-google-analytics/index.html +++ b/Scratch/fr/blog/2010-06-17-track-events-with-google-analytics/index.html @@ -33,8 +33,84 @@ document.write(''); // +
    +
    + +
    +

    Analyser les clicks sur votre Site

    +
    +
    +
    +
    +

    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 :

    +

    +

    Joyeuse inspection du comportement de vos utilisateurs.

    +
    + +
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée +
    -
    - -
    -

    Analyser les clicks sur votre Site

    -
    -
    -
    -
    -

    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 :

    -

    -

    Joyeuse inspection du comportement de vos utilisateurs.

    -
    - -
    - - RSS - - - - - - -
    - -
    -
    -
    +

    Comments

    @@ -145,6 +138,7 @@ comments powered by Disqus
    +
    Published on 2010-06-17 diff --git a/Scratch/fr/blog/2010-06-19-jQuery-popup-the-easy-way/index.html b/Scratch/fr/blog/2010-06-19-jQuery-popup-the-easy-way/index.html index bb6a2dd..8d718ef 100644 --- a/Scratch/fr/blog/2010-06-19-jQuery-popup-the-easy-way/index.html +++ b/Scratch/fr/blog/2010-06-19-jQuery-popup-the-easy-way/index.html @@ -33,8 +33,56 @@ document.write(''); // +
    +
    + +
    +

    Comment faire des popups en jQuery rapidement

    +
    +
    +
    +
    +

    Voici une façon simple et rapide pour faire des popups avec jQuery.

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

    Que fait ce code ?

    +

    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.

    +
    + +
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée +
    -
    - -
    -

    Comment faire des popups en jQuery rapidement

    -
    -
    -
    -
    -

    Voici une façon simple et rapide pour faire des popups avec jQuery.

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

    Que fait ce code ?

    -

    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.

    -
    - -
    - - RSS - - - - - - -
    - -
    -
    -
    +

    Comments

    @@ -117,6 +110,7 @@ comments powered by Disqus
    +
    Published on 2010-06-19 diff --git a/Scratch/fr/blog/2010-07-05-Cappuccino-and-Web-applications/index.html b/Scratch/fr/blog/2010-07-05-Cappuccino-and-Web-applications/index.html index 71f2dad..1dffe99 100644 --- a/Scratch/fr/blog/2010-07-05-Cappuccino-and-Web-applications/index.html +++ b/Scratch/fr/blog/2010-07-05-Cappuccino-and-Web-applications/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Cappuccino ou jQuery ?

    -
    +
    @@ -145,25 +137,26 @@ hash=sha1( masterPassword + leakedTimes + domainName )
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -181,6 +174,7 @@ hash=sha1( masterPassword + leakedTimes + domainName ) comments powered by Disqus
    +
    Published on 2010-07-05 diff --git a/Scratch/fr/blog/2010-07-07-CSS-rendering-problems-by-navigator/index.html b/Scratch/fr/blog/2010-07-07-CSS-rendering-problems-by-navigator/index.html index 295cb67..91a57d5 100644 --- a/Scratch/fr/blog/2010-07-07-CSS-rendering-problems-by-navigator/index.html +++ b/Scratch/fr/blog/2010-07-07-CSS-rendering-problems-by-navigator/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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 :

      @@ -70,25 +62,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -106,6 +99,7 @@ comments powered by Disqus
    +
    Published on 2010-07-07 diff --git a/Scratch/fr/blog/2010-07-09-Indecidabilities/index.html b/Scratch/fr/blog/2010-07-09-Indecidabilities/index.html index 9d2d294..6766d27 100644 --- a/Scratch/fr/blog/2010-07-09-Indecidabilities/index.html +++ b/Scratch/fr/blog/2010-07-09-Indecidabilities/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Indécidabilités (partie 1)

    -
    +

    <% # toremove_ %>

    @@ -146,25 +138,26 @@ Q(x) :
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -182,6 +175,7 @@ Q(x) : comments powered by Disqus
    +
    Published on 2010-08-11 diff --git a/Scratch/fr/blog/2010-07-31-New-style-after-holidays/index.html b/Scratch/fr/blog/2010-07-31-New-style-after-holidays/index.html index dc5c4ff..18d8346 100644 --- a/Scratch/fr/blog/2010-07-31-New-style-after-holidays/index.html +++ b/Scratch/fr/blog/2010-07-31-New-style-after-holidays/index.html @@ -33,8 +33,32 @@ document.write(''); // +
    +
    + +
    +

    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(c) sur iPhone(c).

    +

    Dites moi ce que vous pensez de ce nouveau design.

    +
    + +
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée +
    -
    - -
    -

    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(c) sur iPhone(c).

    -

    Dites moi ce que vous pensez de ce nouveau design.

    -
    - -
    - - RSS - - - - - - -
    - -
    -
    -
    +

    Comments

    @@ -93,6 +86,7 @@ comments powered by Disqus
    +
    Published on 2010-07-31 diff --git a/Scratch/fr/blog/2010-08-23-Now-heberged-on-heroku/index.html b/Scratch/fr/blog/2010-08-23-Now-heberged-on-heroku/index.html index 2691981..c4bed58 100644 --- a/Scratch/fr/blog/2010-08-23-Now-heberged-on-heroku/index.html +++ b/Scratch/fr/blog/2010-08-23-Now-heberged-on-heroku/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

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

    @@ -117,25 +109,26 @@ git push heroku master
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -153,6 +146,7 @@ git push heroku master
    comments powered by Disqus
    +
    Published on 2010-08-23 diff --git a/Scratch/fr/blog/2010-08-31-send-mail-from-command-line-with-attached-file/index.html b/Scratch/fr/blog/2010-08-31-send-mail-from-command-line-with-attached-file/index.html index e554ef6..20cf5da 100644 --- a/Scratch/fr/blog/2010-08-31-send-mail-from-command-line-with-attached-file/index.html +++ b/Scratch/fr/blog/2010-08-31-send-mail-from-command-line-with-attached-file/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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 :

    @@ -94,38 +86,36 @@ H4sICB6Ke0wAA2Rjcl93aXRob3V0X2tleXdvcmQuY3N2ANSdW5ubOJPH7/e7 </div> <div id="social"> - <span> - <a class="rss" href="http://feeds.feedburner.com/yannespositocomfr">RSS</a> - </span> - <span> - <a href="https://twitter.com/share" class="twitter-share-button" data-via="yogsototh">Tweet</a> - <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script> - </span> - <span> - <div class="g-plusone" data-size="medium" data-annotation="inline" data-width="106"></div> - <script type="text/javascript"> - (function() { - var po = document.createElement(" script'); po.type="text/javascript" ; po.async="true;" po.src="https://apis.google.com/js/plusone.js" ; var s="document.getElementsByTagName('script')[0];" s.parentNode.insertBefore(po, s); })(); < script> - -
    -
    -
    -

    Comments

    -
    - + var disqus_shortname = " yannesposito'; required: replace example with your forum shortname * * * DON'T EDIT BELOW THIS LINE * * * (function() { var dsq="document.createElement('script');" dsq.type="text/javascript" ; dsq.async="true;" dsq.src="http://" + disqus_shortname + '.disqus.com embed.js'; (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); })(); < script> comments powered by Disqus
    +
    Published on 2010-08-31 diff --git a/Scratch/fr/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes/index.html b/Scratch/fr/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes/index.html index 8606644..f5a2046 100644 --- a/Scratch/fr/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes/index.html +++ b/Scratch/fr/blog/2010-09-02-Use-git-to-calculate-trusted-mtimes/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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 :

    @@ -73,25 +65,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -109,6 +102,7 @@ comments powered by Disqus
    +
    Published on 2010-09-02 diff --git a/Scratch/fr/blog/2010-09-02-base64-and-sha1-on-iPhone/index.html b/Scratch/fr/blog/2010-09-02-base64-and-sha1-on-iPhone/index.html index ca4a525..446c0ff 100644 --- a/Scratch/fr/blog/2010-09-02-base64-and-sha1-on-iPhone/index.html +++ b/Scratch/fr/blog/2010-09-02-base64-and-sha1-on-iPhone/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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 :

    @@ -105,25 +97,26 @@ NSString *hex_hash = [self hex_sha1:@"some NSString to be sha1'ed"];
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -141,6 +134,7 @@ NSString *hex_hash = [self hex_sha1:@"some NSString to be sha1'ed"];Please enable JavaScript to view the comments powered by Disqus. comments powered by Disqus
    +
    Published on 2010-09-02 diff --git a/Scratch/fr/blog/2010-10-06-New-Blog-Design-Constraints/index.html b/Scratch/fr/blog/2010-10-06-New-Blog-Design-Constraints/index.html index 4141e0f..0c7280a 100644 --- a/Scratch/fr/blog/2010-10-06-New-Blog-Design-Constraints/index.html +++ b/Scratch/fr/blog/2010-10-06-New-Blog-Design-Constraints/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    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:

      @@ -62,25 +54,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -98,6 +91,7 @@ comments powered by Disqus
    +
    Published on 2010-10-06 diff --git a/Scratch/fr/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/index.html b/Scratch/fr/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/index.html index 32e8596..d224ed1 100644 --- a/Scratch/fr/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/index.html +++ b/Scratch/fr/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Sécurisez vos emails

    -
    +

    Title image

    @@ -79,25 +71,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -115,6 +108,7 @@ comments powered by Disqus
    +
    Published on 2010-10-10 diff --git a/Scratch/fr/blog/2010-10-14-Fun-with-wav/index.html b/Scratch/fr/blog/2010-10-14-Fun-with-wav/index.html index 8d3501b..95e2245 100644 --- a/Scratch/fr/blog/2010-10-14-Fun-with-wav/index.html +++ b/Scratch/fr/blog/2010-10-14-Fun-with-wav/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    S'amuser avec un .wav

    -
    +
    @@ -305,25 +297,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -341,6 +334,7 @@ comments powered by Disqus
    +
    Published on 2010-10-14 diff --git a/Scratch/fr/blog/2010-10-26-LaTeX-like-macro-and-markdown/index.html b/Scratch/fr/blog/2010-10-26-LaTeX-like-macro-and-markdown/index.html index eab82a9..9a4df01 100644 --- a/Scratch/fr/blog/2010-10-26-LaTeX-like-macro-and-markdown/index.html +++ b/Scratch/fr/blog/2010-10-26-LaTeX-like-macro-and-markdown/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Des macros LaTeX pour markdown

    -
    +
    @@ -113,25 +105,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -149,6 +142,7 @@ comments powered by Disqus
    +
    Published on 2010-10-26 diff --git a/Scratch/fr/blog/2011-01-03-Happy-New-Year/index.html b/Scratch/fr/blog/2011-01-03-Happy-New-Year/index.html index 1cb1a07..4eafc76 100644 --- a/Scratch/fr/blog/2011-01-03-Happy-New-Year/index.html +++ b/Scratch/fr/blog/2011-01-03-Happy-New-Year/index.html @@ -32,16 +32,8 @@ document.write(''); // +
    -
    -
    @@ -49,7 +41,7 @@

    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.

    @@ -59,25 +51,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -95,6 +88,7 @@ comments powered by Disqus
    +
    Published on 2011-01-01 diff --git a/Scratch/fr/blog/2011-01-03-Why-I-sadly-won-t-use-coffeescript/index.html b/Scratch/fr/blog/2011-01-03-Why-I-sadly-won-t-use-coffeescript/index.html index f86d938..7da47ef 100644 --- a/Scratch/fr/blog/2011-01-03-Why-I-sadly-won-t-use-coffeescript/index.html +++ b/Scratch/fr/blog/2011-01-03-Why-I-sadly-won-t-use-coffeescript/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Pourquoi je n'utiliserai pas CoffeeScript (malheureusement)

    -
    +

    Title image

    @@ -132,25 +124,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -168,6 +161,7 @@ comments powered by Disqus
    +
    Published on 2011-01-03 diff --git a/Scratch/fr/blog/2011-04-20-Now-hosted-on-github/index.html b/Scratch/fr/blog/2011-04-20-Now-hosted-on-github/index.html index 7deef5d..29bc383 100644 --- a/Scratch/fr/blog/2011-04-20-Now-hosted-on-github/index.html +++ b/Scratch/fr/blog/2011-04-20-Now-hosted-on-github/index.html @@ -32,8 +32,32 @@ document.write(''); // +
    +
    + +
    +

    Hébergement github

    +
    +
    +
    +
    +

    Title image

    +

    J’héberge mon site sur github à partir d’aujourd’hui.

    +
    + +
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée +
    -
    - -
    -

    Hébergement github

    -
    -
    -
    -
    -

    Title image

    -

    J’héberge mon site sur github à partir d’aujourd’hui.

    -
    - -
    - - RSS - - - - - - -
    - -
    -
    -
    +

    Comments

    @@ -92,6 +85,7 @@ comments powered by Disqus
    +
    Published on 2011-04-20 diff --git a/Scratch/fr/blog/A-more-convenient-diff/index.html b/Scratch/fr/blog/A-more-convenient-diff/index.html index f76f7ce..68c4c1c 100644 --- a/Scratch/fr/blog/A-more-convenient-diff/index.html +++ b/Scratch/fr/blog/A-more-convenient-diff/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Un diff plus pratique

    -
    +

    diff est un utilitaire très pratique, mais il n’est pas facile à lire pour nous, les Hommes.

    C’est pourquoi, lorsque vous utilisez git, il vous montre un formatage plus agréable avec des couleurs.

    @@ -80,25 +72,26 @@ diff -u $* | colorize_diff
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -116,6 +109,7 @@ diff -u $* | colorize_diff comments powered by Disqus
    +
    Published on 2011-08-17 diff --git a/Scratch/fr/blog/Category-Theory-Presentation/index.html b/Scratch/fr/blog/Category-Theory-Presentation/index.html index 81c3cc1..9d4b1a3 100644 --- a/Scratch/fr/blog/Category-Theory-Presentation/index.html +++ b/Scratch/fr/blog/Category-Theory-Presentation/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Category Theory Presentation

    -
    +
    Cateogry of Hask's endofunctors @@ -1018,25 +1010,26 @@ depth = cata phi where
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -1054,6 +1047,7 @@ depth = cata phi where comments powered by Disqus
    +
    Published on 2012-12-12 diff --git a/Scratch/fr/blog/Haskell-Mandelbrot/index.html b/Scratch/fr/blog/Haskell-Mandelbrot/index.html index 9b46d3f..672eaf2 100644 --- a/Scratch/fr/blog/Haskell-Mandelbrot/index.html +++ b/Scratch/fr/blog/Haskell-Mandelbrot/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,14 +42,14 @@

    Mandelbrot avec haskell

    -
    +

    Voici le code “obfusqué” :

    -
    a=27;b=79;c=C(-2.0,-1.0);d=C(1.0,1.0);e=C(-2.501,-1.003)
    +
    a=27;b=79;c=C(-2.0,-1.0);d=C(1.0,1.0);e=C(-2.501,-1.003)
     newtype C = C (Double,Double) deriving (Show,Eq)
    -instance Num C where C(x,y)*C(z,t)=C(z*x-y*t,y*z+x*t);C(x,y)+C(z,t)=C(x+z,y+t);abs(C(x,y))=C(sqrt(x*x+y*y),0.0)
    +instance Num C where C(x,y)*C(z,t)=C(z*x-y*t,y*z+x*t);C(x,y)+C(z,t)=C(x+z,y+t);abs(C(x,y))=C(sqrt(x*x+y*y),0.0)
     r(C(x,y))=x;i(C(x,y))=y
    -f c z 0=0;f c z n=if(r(abs(z))>2)then n else f c ((z*z)+c) (n-1)
    +f c z 0=0;f c z n=if(r(abs(z))>2)then n else f c ((z*z)+c) (n-1)
     h j k = map (\z->(f (C z) (C(0,0)) 32,(fst z>l - q/2))) [(x,y)|y<-[p,(p+((o-p)/a))..o],x<-[m,(m + q)..l]] where o=i k;p=i j;m=r j;l=r k;q=(l-m)/b
     u j k = concat $ map v $ h j k where v (i,p)=(" .,`'°\":;-+oO0123456789=!%*§&$@#"!!i):rst p;rst True="\n";rst False=""
     main = putStrLn $ im 0 where cl n (C (x,y))=let cs=(1.1**n-1) in C ((x+cs*(r e))/cs+1,(y+cs*(i e))/cs+1);bl n=cl n c;tr n=cl n d;im n=u (bl n) (tr n)++"\x1b[H\x1b[25A"++im (n+1)
    @@ -96,18 +88,18 @@ $$$$$$$$$$$$$$$$$$$$$$$$$$&&&&&&&&&&WWWW

    Here is the more readable version. I believe with this far more readable version, no more explanation is needed.

    nbvert = 30
     nbhor = 79
    -zoomfactor = 1.01
    -init_bottom_left = C (-2.0,-2.0)
    -init_top_right   = C (3.0,2.0)
    -interrest        = C (-1.713,-0.000)
    +zoomfactor = 1.01
    +init_bottom_left = C (-2.0,-2.0)
    +init_top_right   = C (3.0,2.0)
    +interrest        = C (-1.713,-0.000)
     
     newtype Complex = C (Float,Float) deriving (Show,Eq)
     instance Num Complex where
    -    fromInteger n     = C (fromIntegral n,0.0)
    +    fromInteger n     = C (fromIntegral n,0.0)
         C (x,y) * C (z,t) = C (z*x - y*t, y*z + x*t)
         C (x,y) + C (z,t) = C (x+z, y+t)
    -    abs (C (x,y))     = C (sqrt (x*x + y*y),0.0)
    -    signum (C (x,y))  = C (signum x , 0.0)
    +    abs (C (x,y))     = C (sqrt (x*x + y*y),0.0)
    +    signum (C (x,y))  = C (signum x , 0.0)
     
     real :: Complex -> Float
     real (C (x,y))    = x
    @@ -119,7 +111,7 @@ cabs = real.abs
     
     f :: Complex -> Complex -> Int -> Int
     f c z 0 = 0
    -f c z n = if (cabs z > 2) then n else f c ((z*z)+c) (n-1) 
    +f c z n = if (cabs z > 2) then n else f c ((z*z)+c) (n-1) 
     
     bmandel bottomleft topright = map (\z -> (f (C z) (C(0,0)) 32, (fst z > right - hstep/2 ))) [(x,y) | y <- [bottom,(bottom + vstep)..top], x<-[left,(left + hstep)..right]]
         where
    @@ -152,29 +144,30 @@ main = do
         putStrLn $ infinitemandel 0
         where
             window n = zoom init_bottom_left init_top_right interrest (zoomfactor**n) 
    -        infinitemandel n = mandel (window n) ++ "\x1b[H\x1b[25A" ++ infinitemandel (n+1)
    + infinitemandel n = mandel (window n) ++ "\x1b[H\x1b[25A" ++ infinitemandel (n+1)
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -192,6 +185,7 @@ main = do comments powered by Disqus
    +
    Published on 2011-07-10 diff --git a/Scratch/fr/blog/Haskell-OpenGL-Mandelbrot/index.html b/Scratch/fr/blog/Haskell-OpenGL-Mandelbrot/index.html index 1cf50d0..bd9ac9b 100644 --- a/Scratch/fr/blog/Haskell-OpenGL-Mandelbrot/index.html +++ b/Scratch/fr/blog/Haskell-OpenGL-Mandelbrot/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Un example progressif avec Haskell

    -
    +

    The B in Benoît B. Mandelbrot stand for Benoît B. Mandelbrot

    @@ -98,9 +90,9 @@ Another detail of the Mandelbulb

    We can consider two parts. The first being mostly some boilerplate2. And the second part more focused on OpenGL and content.

    Let’s play the song of our people

    -
    import Graphics.Rendering.OpenGL
    -import Graphics.UI.GLUT
    -import Data.IORef
    +
    import Graphics.Rendering.OpenGL
    +import Graphics.UI.GLUT
    +import Data.IORef

    For efficiency reason3, I will not use the default Haskell Complex data type.

    @@ -110,11 +102,11 @@ Another detail of the Mandelbulb
    instance Num Complex where
    -    fromInteger n = C (fromIntegral n,0.0)
    +    fromInteger n = C (fromIntegral n,0.0)
         C (x,y) * C (z,t) = C (z*x - y*t, y*z + x*t)
         C (x,y) + C (z,t) = C (x+z, y+t)
    -    abs (C (x,y))     = C (sqrt (x*x + y*y),0.0)
    -    signum (C (x,y))  = C (signum x , 0.0)
    + abs (C (x,y)) = C (sqrt (x*x + y*y),0.0) + signum (C (x,y)) = C (signum x , 0.0)

    We declare some useful functions for manipulating complex numbers:

    @@ -201,16 +193,16 @@ allPoints = [ (x/width,ycolorFromValue n = let t :: Int -> GLfloat - t i = 0.5 + 0.5*cos( fromIntegral i / 10 ) + t i = 0.5 + 0.5*cos( fromIntegral i / 10 ) in - Color3 (t n) (t (n+5)) (t (n+10)) + Color3 (t n) (t (n+5)) (t (n+10))

    And now the mandel function. Given two coordinates in pixels, it returns some integer value:

    mandel x y = 
    -  let r = 2.0 * x / width
    -      i = 2.0 * y / height
    +  let r = 2.0 * x / width
    +      i = 2.0 * y / height
       in
           f (complex r i) 0 64
    @@ -226,7 +218,7 @@ allPoints = [ (x/width,y0 = 0 f c z n = if (magnitude z > 2 ) then n - else f c ((z*z)+c) (n-1) + else f c ((z*z)+c) (n-1)

    Well, if you download this file (look at the bottom of this section), compile it and run it this is the result:

    @@ -242,20 +234,20 @@ f c z n = if (magnitude z
    -
    import Graphics.Rendering.OpenGL
    -import Graphics.UI.GLUT
    -import Data.IORef
    +
    import Graphics.Rendering.OpenGL
    +import Graphics.UI.GLUT
    +import Data.IORef
     -- Use UNPACK data because it is faster
     -- The ! is for strict instead of lazy
     data Complex = C  {-# UNPACK #-} !Float 
                       {-# UNPACK #-} !Float 
                    deriving (Show,Eq)
     instance Num Complex where
    -    fromInteger n = C (fromIntegral n) 0.0
    +    fromInteger n = C (fromIntegral n) 0.0
         (C x y) * (C z t) = C (z*x - y*t) (y*z + x*t)
         (C x y) + (C z t) = C (x+z) (y+t)
    -    abs (C x y)     = C (sqrt (x*x + y*y)) 0.0
    -    signum (C x y)  = C (signum x) 0.0
    +    abs (C x y)     = C (sqrt (x*x + y*y)) 0.0
    +    signum (C x y)  = C (signum x) 0.0
     complex :: Float -> Float -> Complex
     complex x y = C x y
     
    @@ -282,7 +274,7 @@ main = do
       mainLoop
     display = do
        -- set the background color (dark solarized theme)
    -  clearColor $= Color4 0 0.1686 0.2117 1
    +  clearColor $= Color4 0 0.1686 0.2117 1
       clear [ColorBuffer] -- make the window black
       loadIdentity -- reset any transformation
       preservingMatrix drawMandelbrot
    @@ -347,8 +339,8 @@ positivePoints = do
     maxZeroIndex func minval maxval 0 = (minval+maxval)/2
     maxZeroIndex func minval maxval n = 
       if (func medpoint) /= 0 
    -       then maxZeroIndex func minval medpoint (n-1)
    -       else maxZeroIndex func medpoint maxval (n-1)
    +       then maxZeroIndex func minval medpoint (n-1)
    +       else maxZeroIndex func medpoint maxval (n-1)
       where medpoint = (minval+maxval)/2
    @@ -360,15 +352,15 @@ maxZeroIndex func minval maxval n =
    colorFromValue n =
       let 
           t :: Int -> GLfloat
    -      t i = 0.5 + 0.5*cos( fromIntegral i / 10 )
    +      t i = 0.5 + 0.5*cos( fromIntegral i / 10 )
       in
    -    Color3 (t n) (t (n+5)) (t (n+10))
    + Color3 (t n) (t (n+5)) (t (n+10))
    mandel x y = 
    -  let r = 2.0 * x / width
    -      i = 2.0 * y / height
    +  let r = 2.0 * x / width
    +      i = 2.0 * y / height
       in
           f (complex r i) 0 64
    @@ -378,7 +370,7 @@ maxZeroIndex func minval maxval n = f c z 0 = 0 f c z n = if (magnitude z > 2 ) then n - else f c ((z*z)+c) (n-1) + else f c ((z*z)+c) (n-1)
    @@ -406,9 +398,9 @@ f c z n = if (magnitude z
    -
    import Graphics.Rendering.OpenGL
    -import Graphics.UI.GLUT
    -import Data.IORef
    +
    import Graphics.Rendering.OpenGL
    +import Graphics.UI.GLUT
    +import Data.IORef
     type ColoredPoint = (GLfloat,GLfloat,GLfloat,Color3 GLfloat)
    @@ -476,7 +468,7 @@ main = do -- Some state variables (I know it feels BAD) angle <- newIORef ((35,0)::(GLfloat,GLfloat)) zoom <- newIORef (2::GLfloat) - campos <- newIORef ((0.7,0)::(GLfloat,GLfloat)) + campos <- newIORef ((0.7,0)::(GLfloat,GLfloat)) -- Function to call each frame idleCallback $= Just idle -- Function to call when keyboard or mouse is used @@ -516,18 +508,18 @@ mapSnd f (x,y) = ( x,f y) z $= 1 -- zoom p $= (0,0) -- camera position -- use of hjkl to rotate - kact a _ _ (Char 'h') Down = modVar a (mapFst (+0.5)) - kact a _ _ (Char 'l') Down = modVar a (mapFst (+(-0.5))) - kact a _ _ (Char 'j') Down = modVar a (mapSnd (+0.5)) - kact a _ _ (Char 'k') Down = modVar a (mapSnd (+(-0.5))) + kact a _ _ (Char 'h') Down = modVar a (mapFst (+0.5)) + kact a _ _ (Char 'l') Down = modVar a (mapFst (+(-0.5))) + kact a _ _ (Char 'j') Down = modVar a (mapSnd (+0.5)) + kact a _ _ (Char 'k') Down = modVar a (mapSnd (+(-0.5))) -- use o and i to zoom - kact _ z _ (Char 'o') Down = modVar z (*1.1) - kact _ z _ (Char 'i') Down = modVar z (*0.9) + kact _ z _ (Char 'o') Down = modVar z (*1.1) + kact _ z _ (Char 'i') Down = modVar z (*0.9) -- use sdfe to move the camera - kact _ _ p (Char 's') Down = modVar p (mapFst (+0.1)) - kact _ _ p (Char 'f') Down = modVar p (mapFst (+(-0.1))) - kact _ _ p (Char 'd') Down = modVar p (mapSnd (+0.1)) - kact _ _ p (Char 'e') Down = modVar p (mapSnd (+(-0.1))) + kact _ _ p (Char 's') Down = modVar p (mapFst (+0.1)) + kact _ _ p (Char 'f') Down = modVar p (mapFst (+(-0.1))) + kact _ _ p (Char 'd') Down = modVar p (mapSnd (+0.1)) + kact _ _ p (Char 'e') Down = modVar p (mapSnd (+(-0.1))) -- any other keys does nothing kact _ _ _ _ _ = return ()
    @@ -536,7 +528,7 @@ mapSnd f (x,y) = ( x,f y)
    display angle zoom position = do
        -- set the background color (dark solarized theme)
    -  clearColor $= Color4 0 0.1686 0.2117 1
    +  clearColor $= Color4 0 0.1686 0.2117 1
       clear [ColorBuffer,DepthBuffer]
       -- Transformation to change the view
       loadIdentity -- reset any transformation
    @@ -548,8 +540,8 @@ mapSnd f (x,y) = (  x,f y)
    scale z z z -- rotate (xangle,yangle) <- get angle - rotate xangle $ Vector3 1.0 0.0 (0.0::GLfloat) - rotate yangle $ Vector3 0.0 1.0 (0.0::GLfloat) + rotate xangle $ Vector3 1.0 0.0 (0.0::GLfloat) + rotate yangle $ Vector3 0.0 1.0 (0.0::GLfloat) -- Now that all transformation were made -- We create the object(s) @@ -598,17 +590,17 @@ depthPoints = do depthOf x' y' = maxZeroIndex (mandel x' y') 0 deep logdeep logdeep = floor ((log deep) / log 2) z1 = depthOf x y - z2 = depthOf (x+1) y - z3 = depthOf (x+1) (y+1) - z4 = depthOf x (y+1) - c1 = mandel x y (z1+1) - c2 = mandel (x+1) y (z2+1) - c3 = mandel (x+1) (y+1) (z3+1) - c4 = mandel x (y+1) (z4+1) + z2 = depthOf (x+1) y + z3 = depthOf (x+1) (y+1) + z4 = depthOf x (y+1) + c1 = mandel x y (z1+1) + c2 = mandel (x+1) y (z2+1) + c3 = mandel (x+1) (y+1) (z3+1) + c4 = mandel x (y+1) (z4+1) p1 = ( x /width, y /height, z1/deep, colorFromValue c1) - p2 = ((x+1)/width, y /height, z2/deep, colorFromValue c2) - p3 = ((x+1)/width,(y+1)/height, z3/deep, colorFromValue c3) - p4 = ( x /width,(y+1)/height, z4/deep, colorFromValue c4) + p2 = ((x+1)/width, y /height, z2/deep, colorFromValue c2) + p3 = ((x+1)/width,(y+1)/height, z3/deep, colorFromValue c3) + p4 = ( x /width,(y+1)/height, z4/deep, colorFromValue c4) if (and $ map (>=57) [c1,c2,c3,c4]) then [] else [p1,p2,p3,p1,p3,p4] @@ -619,13 +611,13 @@ depthPoints = do x <- [-width..width] y <- [-height..height] let - neighbors = [(x,y),(x+1,y),(x+1,y+1),(x,y+1)] + neighbors = [(x,y),(x+1,y),(x+1,y+1),(x,y+1)] depthOf (u,v) = maxZeroIndex (mandel u v) 0 deep logdeep logdeep = floor ((log deep) / log 2) -- zs are 3D points with found depth zs = map (\(u,v) -> (u,v,depthOf (u,v))) neighbors -- ts are 3D pixels + mandel value - ts = map (\(u,v,w) -> (u,v,w,mandel u v (w+1))) zs + ts = map (\(u,v,w) -> (u,v,w,mandel u v (w+1))) zs -- ps are 3D opengl points + color value ps = map (\(u,v,w,c') -> (u/width,v/height,w/deep,colorFromValue c')) ts @@ -643,7 +635,7 @@ depthPoints = do allPoints = planPoints ++ map inverseDepth planPoints where planPoints = depthPoints - inverseDepth (x,y,z,c) = (x,y,-z+1/deep,c) + inverseDepth (x,y,z,c) = (x,y,-z+1/deep,c)

    The rest of the program is very close to the preceding one.

    @@ -663,8 +655,8 @@ allPoints = planPoints ++ 0 = (minval+maxval)/2 maxZeroIndex func minval maxval n = if (func medpoint) /= 0 - then maxZeroIndex func minval medpoint (n-1) - else maxZeroIndex func medpoint maxval (n-1) + then maxZeroIndex func minval medpoint (n-1) + else maxZeroIndex func medpoint maxval (n-1) where medpoint = (minval+maxval)/2
    @@ -673,9 +665,9 @@ maxZeroIndex func minval maxval n =
    colorFromValue n =
       let 
           t :: Int -> GLfloat
    -      t i = 0.7 + 0.3*cos( fromIntegral i / 10 )
    +      t i = 0.7 + 0.3*cos( fromIntegral i / 10 )
       in
    -    Color3 (t n) (t (n+5)) (t (n+10))
    + Color3 (t n) (t (n+5)) (t (n+10))

    We only changed from Complex to ExtComplex of the main f function.

    @@ -684,7 +676,7 @@ maxZeroIndex func minval maxval n = f c z 0 = 0 f c z n = if (magnitude z > 2 ) then n - else f c ((z*z)+c) (n-1) + else f c ((z*z)+c) (n-1)
    @@ -692,9 +684,9 @@ f c z n = if (magnitude z We simply add a new dimension to the mandel function and change the type signature of f from Complex to ExtComplex.

    mandel x y z = 
    -  let r = 2.0 * x / width
    -      i = 2.0 * y / height
    -      s = 2.0 * z / deep
    +  let r = 2.0 * x / width
    +      i = 2.0 * y / height
    +      s = 2.0 * z / deep
       in
           f (extcomplex r i s) 0 64
    @@ -712,8 +704,8 @@ f c z n = if (magnitude z ExtComplex, the extended complexes
    -
    import YBoiler -- Most the OpenGL Boilerplate
    -import Mandel -- The 3D Mandelbrot maths
    +
    import YBoiler -- Most the OpenGL Boilerplate
    +import Mandel -- The 3D Mandelbrot maths

    The yMainLoop takes two arguments: the title of the window and a function from time to triangles

    @@ -737,7 +729,7 @@ allPoints = planPoints ++ where planPoints = depthPoints ++ map inverseHeight depthPoints inverseHeight (x,y,z,c) = (x,-y,z,c) - inverseDepth (x,y,z,c) = (x,y,-z+1/deep,c) + inverseDepth (x,y,z,c) = (x,y,-z+1/deep,c)
    @@ -746,12 +738,12 @@ depthPoints = do x <- [-width..width] y <- [0..height] let - neighbors = [(x,y),(x+1,y),(x+1,y+1),(x,y+1)] + neighbors = [(x,y),(x+1,y),(x+1,y+1),(x,y+1)] depthOf (u,v) = maxZeroIndex (ymandel u v) 0 deep 7 -- zs are 3D points with found depth zs = map (\(u,v) -> (u,v,depthOf (u,v))) neighbors -- ts are 3D pixels + mandel value - ts = map (\(u,v,w) -> (u,v,w,ymandel u v (w+1))) zs + ts = map (\(u,v,w) -> (u,v,w,ymandel u v (w+1))) zs -- ps are 3D opengl points + color value ps = map (\(u,v,w,c') -> (u/width,v/height,w/deep,colorFromValue c')) ts @@ -772,16 +764,16 @@ depthPoints = do maxZeroIndex func minval maxval 0 = (minval+maxval)/2 maxZeroIndex func minval maxval n = if (func medpoint) /= 0 - then maxZeroIndex func minval medpoint (n-1) - else maxZeroIndex func medpoint maxval (n-1) + then maxZeroIndex func minval medpoint (n-1) + else maxZeroIndex func medpoint maxval (n-1) where medpoint = (minval+maxval)/2 colorFromValue n = let t :: Int -> GLfloat - t i = 0.7 + 0.3*cos( fromIntegral i / 10 ) + t i = 0.7 + 0.3*cos( fromIntegral i / 10 ) in - ((t n),(t (n+5)),(t (n+10))) + ((t n),(t (n+5)),(t (n+10))) ymandel x y z = mandel (2*x/width) (2*y/height) (2*z/deep) 64
    @@ -815,8 +807,8 @@ ymandel x y z = mandel (2

    Here is a real working code, I’ve hidden most display functions. The YGL, is a kind of framework to display 3D functions. But it can easily be extended to many kind of representation.

    -
    import YGL -- Most the OpenGL Boilerplate
    -import Mandel -- The 3D Mandelbrot maths
    +
    import YGL -- Most the OpenGL Boilerplate
    +import Mandel -- The 3D Mandelbrot maths

    We first set the mapping between user input and actions. The type of each couple should be of the form (user input, f) where (in a first time) f:World -> World. It means, the user input will transform the world state.

    @@ -830,16 +822,16 @@ inputActionMap = inputMapFromList [ ,(Press 'l' , rotate ydir (-5)) ,(Press 'o' , rotate zdir 5) ,(Press 'u' , rotate zdir (-5)) - ,(Press 'f' , translate xdir 0.1) - ,(Press 's' , translate xdir (-0.1)) - ,(Press 'e' , translate ydir 0.1) - ,(Press 'd' , translate ydir (-0.1)) - ,(Press 'z' , translate zdir 0.1) - ,(Press 'r' , translate zdir (-0.1)) - ,(Press '+' , zoom 1.1) - ,(Press '-' , zoom (1/1.1)) - ,(Press 'h' , resize 1.2) - ,(Press 'g' , resize (1/1.2)) + ,(Press 'f' , translate xdir 0.1) + ,(Press 's' , translate xdir (-0.1)) + ,(Press 'e' , translate ydir 0.1) + ,(Press 'd' , translate ydir (-0.1)) + ,(Press 'z' , translate zdir 0.1) + ,(Press 'r' , translate zdir (-0.1)) + ,(Press '+' , zoom 1.1) + ,(Press '-' , zoom (1/1.1)) + ,(Press 'h' , resize 1.2) + ,(Press 'g' , resize (1/1.2)) ]
    @@ -932,11 +924,11 @@ main = yMainLoop inputActionMap idleAction initialWorld< initialWorld = World { angle = makePoint3D (-30,-30,0) , position = makePoint3D (0,0,0) - , scale = 0.8 + , scale = 0.8 , shape = shapeFunc , box = Box3D { minPoint = makePoint3D (-2,-2,-2) , maxPoint = makePoint3D (2,2,2) - , resolution = 0.16 } + , resolution = 0.16 } , told = 0 }
    @@ -949,8 +941,8 @@ idleAction tnew world = world { , told = tnew } where - anglePerSec = 5.0 - delta = anglePerSec * elapsed / 1000.0 + anglePerSec = 5.0 + delta = anglePerSec * elapsed / 1000.0 elapsed = fromIntegral (tnew - (told world))
    @@ -962,7 +954,7 @@ shapeFunc res x y = let z = maxZeroIndex (ymandel x y) 0 1 20 in - if and [ maxZeroIndex (ymandel (x+xeps) (y+yeps)) 0 1 20 < 0.000001 | + if and [ maxZeroIndex (ymandel (x+xeps) (y+yeps)) 0 1 20 < 0.000001 | val <- [res], xeps <- [-val,val], yeps<-[-val,val]] then Nothing else Just (z,colorFromValue ((ymandel x y z) * 64)) @@ -974,9 +966,9 @@ shapeFunc res x y = colorFromValue n = let t :: Point -> Scalar - t i = 0.7 + 0.3*cos( i / 10 ) + t i = 0.7 + 0.3*cos( i / 10 ) in - makeColor (t n) (t (n+5)) (t (n+10)) + makeColor (t n) (t (n+5)) (t (n+10))

    The rest is similar to the preceding sections.

    @@ -994,8 +986,8 @@ colorFromValue n = maxZeroIndex _ minval maxval 0 = (minval+maxval)/2 maxZeroIndex func minval maxval n = if (func medpoint) /= 0 - then maxZeroIndex func minval medpoint (n-1) - else maxZeroIndex func medpoint maxval (n-1) + then maxZeroIndex func minval medpoint (n-1) + else maxZeroIndex func medpoint maxval (n-1) where medpoint = (minval+maxval)/2 ymandel :: Point -> Point -> Point -> Point @@ -1022,8 +1014,8 @@ ymandel x y z = fromIntegral (ma
    -
    import YGL -- Most the OpenGL Boilerplate
    -import Mandel -- The 3D Mandelbrot maths
    +
    import YGL -- Most the OpenGL Boilerplate
    +import Mandel -- The 3D Mandelbrot maths
     
     -- Centralize all user input interaction
     inputActionMap :: InputMap World
    @@ -1035,16 +1027,16 @@ inputActionMap = inputMapFromList [
         ,(Press 'l' , rotate ydir (-5))
         ,(Press 'o' , rotate zdir 5)
         ,(Press 'u' , rotate zdir (-5))
    -    ,(Press 'f' , translate xdir 0.1)
    -    ,(Press 's' , translate xdir (-0.1))
    -    ,(Press 'e' , translate ydir 0.1)
    -    ,(Press 'd' , translate ydir (-0.1))
    -    ,(Press 'z' , translate zdir 0.1)
    -    ,(Press 'r' , translate zdir (-0.1))
    -    ,(Press '+' , zoom 1.1)
    -    ,(Press '-' , zoom (1/1.1))
    -    ,(Press 'h' , resize 2.0)
    -    ,(Press 'g' , resize (1/2.0))
    +    ,(Press 'f' , translate xdir 0.1)
    +    ,(Press 's' , translate xdir (-0.1))
    +    ,(Press 'e' , translate ydir 0.1)
    +    ,(Press 'd' , translate ydir (-0.1))
    +    ,(Press 'z' , translate zdir 0.1)
    +    ,(Press 'r' , translate zdir (-0.1))
    +    ,(Press '+' , zoom 1.1)
    +    ,(Press '-' , zoom (1/1.1))
    +    ,(Press 'h' , resize 2.0)
    +    ,(Press 'g' , resize (1/2.0))
         ]
    @@ -1092,7 +1084,7 @@ rotate dir angleValue world = switchRotation :: World -> World switchRotation world = world { - anglePerSec = if anglePerSec world > 0 then 0 else 5.0 } + anglePerSec = if anglePerSec world > 0 then 0 else 5.0 } translate :: Point3D -> Scalar -> World -> World translate dir len world = @@ -1119,12 +1111,12 @@ main = yMainLoop inputActionMap idleAction initialWorld< initialWorld :: World initialWorld = World { angle = makePoint3D (30,30,0) - , anglePerSec = 5.0 + , anglePerSec = 5.0 , position = makePoint3D (0,0,0) - , scale = 1.0 + , scale = 1.0 , box = Box3D { minPoint = makePoint3D (0-eps, 0-eps, 0-eps) , maxPoint = makePoint3D (0+eps, 0+eps, 0+eps) - , resolution = 0.02 } + , resolution = 0.02 } , told = 0 -- We declare cache directly this time , cache = objectFunctionFromWorld initialWorld @@ -1168,7 +1160,7 @@ idleAction tnew world = , told = tnew } where - delta = anglePerSec world * elapsed / 1000.0 + delta = anglePerSec world * elapsed / 1000.0 elapsed = fromIntegral (tnew - (told world)) shapeFunc :: Scalar -> Function3D @@ -1176,7 +1168,7 @@ shapeFunc res x y = let z = maxZeroIndex (ymandel x y) 0 1 20 in - if and [ maxZeroIndex (ymandel (x+xeps) (y+yeps)) 0 1 20 < 0.000001 | + if and [ maxZeroIndex (ymandel (x+xeps) (y+yeps)) 0 1 20 < 0.000001 | val <- [res], xeps <- [-val,val], yeps<-[-val,val]] then Nothing else Just (z,colorFromValue 0) @@ -1185,9 +1177,9 @@ shapeFunc res x y = colorFromValue n = let t :: Point -> Scalar - t i = 0.0 + 0.5*cos( i /10 ) + t i = 0.0 + 0.5*cos( i /10 ) in - makeColor (t n) (t (n+5)) (t (n+10)) + makeColor (t n) (t (n+5)) (t (n+10)) -- given f min max nbtest, -- considering @@ -1202,8 +1194,8 @@ colorFromValue n = maxZeroIndex _ minval maxval 0 = (minval+maxval)/2 maxZeroIndex func minval maxval n = if func medpoint /= 0 - then maxZeroIndex func minval medpoint (n-1) - else maxZeroIndex func medpoint maxval (n-1) + then maxZeroIndex func minval medpoint (n-1) + else maxZeroIndex func medpoint maxval (n-1) where medpoint = (minval+maxval)/2 ymandel :: Point -> Point -> Point -> Point @@ -1237,25 +1229,26 @@ ymandel x y z = fromIntegral (ma
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -1273,6 +1266,7 @@ ymandel x y z = fromIntegral (ma comments powered by Disqus
    +
    Published on 2012-06-15 diff --git a/Scratch/fr/blog/Haskell-the-Hard-Way/index.html b/Scratch/fr/blog/Haskell-the-Hard-Way/index.html index 2527b2f..a2cd4b2 100644 --- a/Scratch/fr/blog/Haskell-the-Hard-Way/index.html +++ b/Scratch/fr/blog/Haskell-the-Hard-Way/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Haskell comme un vrai!

    -
    +

    Magritte pleasure principle

    @@ -259,7 +251,7 @@ Function declaration return x*x + y*y; }

    In Javascript:

    -
    function f(x,y) {
    +
    function f(x,y) {
         return x*x + y*y;
     }

    in Python:

    @@ -299,7 +291,7 @@ main = print (f f :: Int -> Int -> Int f x y = x*x + y*y -main = print (f 2.3 4.2)
    +main = print (f 2.3 4.2)

    You get this error:

    21_very_basic.lhs:6:23:
    @@ -317,7 +309,7 @@ main = print (f 
     
    f x y = x*x + y*y
     
    -main = print (f 2.3 4.2)
    +main = print (f 2.3 4.2)

    It works! Great, we don’t have to declare a new function for every single type. For example, in C, you’ll have to declare a function for int, for float, for long, for double, etc…

    But, what type should we declare? To discover the type Haskell has found for us, just launch ghci:

    @@ -364,7 +356,7 @@ g y ⇔ 3*3 + y*y
    f :: Num a => a -> a -> a
     f x y = x*x + y*y
     
    -main = print (f 3 2.4)
    +main = print (f 3 2.4)

    It works, because, 3 is a valid representation both for Fractional numbers like Float and for Integer. As 2.4 is a Fractional number, 3 is then interpreted as being also a Fractional number.

    01_basic/10_Introduction/23_very_basic.lhs

    @@ -378,7 +370,7 @@ f x y = x*x +x :: Int x = 3 y :: Float -y = 2.4 +y = 2.4 main = print (f x y) -- won't work because type x ≠ type y

    The compiler complains. The two parameters must have the same type.

    @@ -567,9 +559,9 @@ Functional style

    example: [1,2,3,4,5] ⇒ 2 + 4 ⇒ 6

    To show differences between the functional and imperative approach, I’ll start by providing an imperative solution (in Javascript):

    -
    function evenSum(list) {
    +
    function evenSum(list) {
         var result = 0;
    -    for (var i=0; i< list.length ; i++) {
    +    for (var i=0; i< list.length ; i++) {
             if (list[i] % 2 ==0) {
                 result += list[i];
             }
    @@ -810,7 +802,7 @@ myfunc list = foldl bar initialVa
     
    -- Version 6
     -- foldl' isn't accessible by default
     -- we need to import it from the module Data.List
    -import Data.List
    +import Data.List
     evenSum l = foldl' mysum 0 (filter even l)
       where mysum acc value = acc + value

    Version we can simplify by using directly a lambda notation. This way we don’t have to create the temporary name mysum.

    @@ -818,7 +810,7 @@ evenSum l = foldl' mysum 0 (-- Version 7 -- Generally it is considered a good practice -- to import only the necessary function(s) -import Data.List (foldl') +import Data.List (foldl') evenSum l = foldl' (\x y -> x+y) 0 (filter even l)

    And of course, we note that

    @@ -835,7 +827,7 @@ evenSum l = foldl' (\x y -> x

    02_Hard_Part/16_Functions.lhs

    Finally

    -- Version 8
    -import Data.List (foldl')
    +import Data.List (foldl')
     evenSum :: Integral a => [a] -> a
     evenSum l = foldl' (+) 0 (filter even l)

    foldl' isn’t the easiest function to intuit. If you are not used to it, you should study it a bit.

    @@ -855,13 +847,13 @@ evenSum l = foldl' (+) (f . g . h) x ⇔ f ( g (h x))

    We can take advantage of this operator to η-reduce our function:

    -- Version 9
    -import Data.List (foldl')
    +import Data.List (foldl')
     evenSum :: Integral a => [a] -> a
     evenSum = (foldl' (+) 0) . (filter even)

    Also, we could rename some parts to make it clearer:

    -- Version 10 
    -import Data.List (foldl')
    +import Data.List (foldl')
     sum' :: (Num a) => [a] -> a
     sum' = foldl' (+) 0
     evenSum :: Integral a => [a] -> a
    @@ -1013,9 +1005,9 @@ main = putStrLn And many accessors are made for you. Furthermore you can use another order when setting values.

    Example:

    data Complex = Num a => Complex { real :: a, img :: a}
    -c = Complex 1.0 2.0
    +c = Complex 1.0 2.0
     z = Complex { real = 3, img = 4 }
    -real c  1.0
    +real c  1.0
     img z  4

    02_Hard_Part/22_Types.lhs


    @@ -1059,7 +1051,7 @@ Trees

    Magritte, l

    We’ll just give another standard example: binary trees.

    -
    import Data.List
    +
    import Data.List
     
     data BinTree a = Empty
                      | Node a (BinTree a) (BinTree a)
    @@ -1264,7 +1256,7 @@ numbers = 0:map
     
     take' n [] = []
     take' 0 l = []
    -take' n (x:xs) = x:take' (n-1) xs
    +take' n (x:xs) = x:take' (n-1) xs
     
     main = print $ take' 10 numbers
    @@ -1282,8 +1274,8 @@ main = print $<

    This code is mostly the same as the previous one.

    -
    import Debug.Trace (trace)
    -import Data.List
    +
    import Debug.Trace (trace)
    +import Data.List
     data BinTree a = Empty 
                      | Node a (BinTree a) (BinTree a) 
                       deriving (Eq,Ord)
    @@ -1340,8 +1332,8 @@ main = print $< treeTakeDepth _ Empty = Empty treeTakeDepth 0 _ = Empty treeTakeDepth n (Node x left right) = let - nl = treeTakeDepth (n-1) left - nr = treeTakeDepth (n-1) right + nl = treeTakeDepth (n-1) left + nr = treeTakeDepth (n-1) right in Node x nl nr
    @@ -1367,8 +1359,8 @@ treeTakeDepth n (Node x left right) =
    iTree = Node 0 (dec iTree) (inc iTree)
             where
    -           dec (Node x l r) = Node (x-1) (dec l) (dec r) 
    -           inc (Node x l r) = Node (x+1) (inc l) (inc r) 
    + dec (Node x l r) = Node (x-1) (dec l) (dec r) + inc (Node x l r) = Node (x+1) (inc l) (inc r)

    Another way to create this tree is to use a higher order function. This function should be similar to map, but should work on BinTree instead of list. Here is such a function:

    @@ -1383,8 +1375,8 @@ treeMap f (Node x left right) =

    Our definition is now:

    infTreeTwo :: BinTree Int
    -infTreeTwo = Node 0 (treeMap (\x -> x-1) infTreeTwo) 
    -                    (treeMap (\x -> x+1) infTreeTwo) 
    +infTreeTwo = Node 0 (treeMap (\x -> x-1) infTreeTwo) + (treeMap (\x -> x+1) infTreeTwo)

    Look at the result for

    main = print $ treeTakeDepth 4 infTreeTwo
    @@ -1501,7 +1493,7 @@ main = do

    Argh! An evil error message and a crash! The first evolution will be to answer with a more friendly message.

    In order to do this, we must detect that something went wrong. Here is one way to do this. Use the type Maybe. It is a very common type in Haskell.

    -
    import Data.Maybe
    +
    import Data.Maybe

    What is this thing? Maybe is a type which takes one parameter. Its definition is:

    data Maybe a = Nothing | Just a
    @@ -1544,7 +1536,7 @@ main = do

    Our next evolution will be to prompt the user again and again until she enters a valid answer.

    We keep the first part:

    -
    import Data.Maybe
    +
    import Data.Maybe
     
     maybeRead :: Read a => String -> Maybe a
     maybeRead s = case reads s of
    @@ -1807,7 +1799,7 @@ main = do
       print $ sum list

    Is translated into:

    -
    import Data.Maybe
    +
    import Data.Maybe
     
     maybeRead :: Read a => String -> Maybe a
     maybeRead s = case reads s of
    @@ -1980,7 +1972,7 @@ The list monad
     

    Golconde de Magritte

    The list monad helps us to simulate non deterministic computations. Here we go:

    -
    import Control.Monad (guard)
    +
    import Control.Monad (guard)
     
     allCases = [1..10]
     
    @@ -2036,7 +2028,7 @@ More on Infinite Tree
     
     

    This code is mostly the same as the one in the tree section.

    -
    import Data.List
    +
    import Data.List
     data BinTree a = Empty 
                      | Node a (BinTree a) (BinTree a) 
                       deriving (Eq,Ord)
    @@ -2097,8 +2089,8 @@ treeFromList (x:xs) = treeTakeDepth _ Empty = Empty
     treeTakeDepth 0 _     = Empty
     treeTakeDepth n (Node x left right) = let
    -          nl = treeTakeDepth (n-1) left
    -          nr = treeTakeDepth (n-1) right
    +          nl = treeTakeDepth (n-1) left
    +          nr = treeTakeDepth (n-1) right
               in
                   Node x nl nr
    @@ -2148,8 +2140,8 @@ treeTakeDepth 4 (treeFromList shuffle)

    This code is mostly the same as the preceding one.

    -
    import Debug.Trace (trace)
    -import Data.List
    +
    import Debug.Trace (trace)
    +import Data.List
     data BinTree a = Empty 
                      | Node a (BinTree a) (BinTree a) 
                       deriving (Eq,Ord)
    @@ -2196,8 +2188,8 @@ treeTakeDepth 4 (treeFromList shuffle) treeTakeDepth _ Empty = Empty treeTakeDepth 0 _ = Empty treeTakeDepth n (Node x left right) = let - nl = treeTakeDepth (n-1) left - nr = treeTakeDepth (n-1) right + nl = treeTakeDepth (n-1) left + nr = treeTakeDepth (n-1) right in Node x nl nr
    @@ -2241,7 +2233,7 @@ safefilter f l = safefilter' f l nbTry safefilter' f (x:xs) n = if f x then x : safefilter' f xs nbTry - else safefilter' f xs (n-1)
    + else safefilter' f xs (n-1)

    Now run the program and be happy:

    @@ -2292,25 +2284,26 @@ treeFromList' (x:xs) n =
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -2328,6 +2321,7 @@ treeFromList' (x:xs) n = Please enable JavaScript to view the comments powered by Disqus. comments powered by Disqus
    +
    Published on 2012-02-08 diff --git a/Scratch/fr/blog/Higher-order-function-in-zsh/index.html b/Scratch/fr/blog/Higher-order-function-in-zsh/index.html index e89d21f..e3637eb 100644 --- a/Scratch/fr/blog/Higher-order-function-in-zsh/index.html +++ b/Scratch/fr/blog/Higher-order-function-in-zsh/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Fonctions d'ordre supérieur en zsh

    -
    +

    Title image

    @@ -107,11 +99,11 @@ done
  • Le :t signfie “tail” ; si toto=/path/to/file.ext alors ${toto:t}=file.ext.
  • Après

    -
    gif_to_png() { convert $1 ${1:r}.png && \rm -f $1 }
    +
    gif_to_png() { convert $1 ${1:r}.png && \rm -f $1 }
     
    -handle_resources() { map gif_to_png $1/resources/*.gif(.N) }
    +handle_resources() { map gif_to_png $1/resources/*.gif(.N) }
     
    -map handle_resources /path/to/projects/*(/N)
    +map handle_resources /path/to/projects/*(/N)

    Plus de bloc ! Oui, c’est un poil plus difficile à lire pour les non initiés. Mais c’est à la fois plus concis et plus robuste.

    Et encore ce code ne possède pas de test. Recommençons sur le même principe.

    Trouver les fichiers des projets qui ne contiennent pas de s dans leur nom qui ont le même nom que leur projet.

    @@ -205,25 +197,26 @@ function filter {
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -241,6 +234,7 @@ function filter { comments powered by Disqus
    +
    Published on 2011-09-28 diff --git a/Scratch/fr/blog/Learn-Vim-Progressively/index.html b/Scratch/fr/blog/Learn-Vim-Progressively/index.html index 77f9402..180101e 100644 --- a/Scratch/fr/blog/Learn-Vim-Progressively/index.html +++ b/Scratch/fr/blog/Learn-Vim-Progressively/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Apprenez Vim Progressivement

    -
    +

    Über leet use vim!

    @@ -309,25 +301,26 @@ $(document).ready(function() {
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -345,6 +338,7 @@ $(document).ready(function() { comments powered by Disqus
    +
    Published on 2011-08-25 diff --git a/Scratch/fr/blog/Password-Management/index.html b/Scratch/fr/blog/Password-Management/index.html index f5940f1..04e5d1d 100644 --- a/Scratch/fr/blog/Password-Management/index.html +++ b/Scratch/fr/blog/Password-Management/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Password Management

    -
    +

    Title image

    @@ -113,25 +105,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -149,6 +142,7 @@ comments powered by Disqus
    +
    Published on 2011-05-18 diff --git a/Scratch/fr/blog/SVG-and-m4-fractals/index.html b/Scratch/fr/blog/SVG-and-m4-fractals/index.html index e0a96f0..f34cb96 100644 --- a/Scratch/fr/blog/SVG-and-m4-fractals/index.html +++ b/Scratch/fr/blog/SVG-and-m4-fractals/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Accroître le pouvoir des languages déficients.

    -
    +

    Yesod logo made in SVG and m4

    @@ -174,25 +166,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -210,6 +203,7 @@ comments powered by Disqus
    +
    Published on 2011-10-20 diff --git a/Scratch/fr/blog/Social-link-the-right-way/index.html b/Scratch/fr/blog/Social-link-the-right-way/index.html new file mode 100644 index 0000000..120ce48 --- /dev/null +++ b/Scratch/fr/blog/Social-link-the-right-way/index.html @@ -0,0 +1,285 @@ + + + + + + YBlog - Être correct avec les boutons share + + + + + + + + + + + + + +
    + + +
    +

    Être correct avec les boutons share

    +
    +
    +
    +
    +

    Main image

    +
    + + +

    tlpl: Les boutons des réseaux sociaux traquent vos utilisateurs, ont un design incohérent avec celui de votre site, utilisent des ressources, ralentissent le rendu de vos pages.

    +

    Faite les choses bien. Utilisez des liens statiques.

    +

    Si vous n’avez pas envie de lire, copiez et collez simplement le code suivant dans votre html :

    +
    <script>
    +var url=document.location;
    +document.write(
    +  '<'+'a href="https://twitter.com/home?status='+url+'" '
    +    +'target="_blank">Tweet this<'+'/a> - '
    +
    ++ '<'+'a href="http://www.facebook.com/sharer/sharer.php?u='+url+'" '
    +    +'target="_blank">Like this<'+'/a> - '
    +
    ++ '<'+'a href="https://plus.google.com/share?url='+url+'" '
    +    +'target="_blank">Share on G+<'+'/a>');
    +</script>
    +
    + +

    The problem

    +

    Ever been on a website and want to tweet about it? Fortunately, the website might have a button to help you. But do you really know what this button do?

    +

    The “Like”, “Tweet” and “+1” buttons will call a javascript. It will get access to your cookies. It helps the provider of the button to know who you are.

    +

    In plain English, the “+1” button will inform Google you are visiting the website, even if you don’t click on “+1”. The same is true for the “like” button for facebook and the “tweet this” button for twitter.

    +

    The problem is not only a privacy issue. In fact (sadly imho) this isn’t an issue for most people. These button consume computer ressources. Far more than a simple link. It thus slow down a bit the computer and consume energy. These button could also slow down the rendering of your web page.

    +

    Another aspect is their design. Their look and feel is mostly imposed by the provider.

    +

    The most problematic aspect in my opinion is to use a third party js on your website. What if tomorrow twitter update their tweet button? If the upgrade broke something for only a minority of people, they won’t fix it. This could occur anytime without any notification. They just have to add a document.write in their js you call asynchronously and BAM! Your website is just an empty blank page. And as you call many external ressources, it can be very difficult to find the origin of the problem.

    +

    Using social network buttons:

    +
      +
    • Pros: +
        +
      • help user share your website,
      • +
      • can provide a popularity indicator to your users.
      • +
    • +
    • Cons: +
        +
      • you help tracking your users,
      • +
      • generally doesn’t follow the design of your website,
      • +
      • use more computer ressources,
      • +
      • slow down your website,
      • +
      • executing third party js can break things silently.
      • +
    • +
    +

    Solutions

    +

    I will provide you two solutions with the following properties:

    +
      +
    • Pros: +
        +
      • help user share your website,
      • +
      • doesn’t follow your user,
      • +
      • use almost no computer ressource,
      • +
      • doesn’t slow down your website,
      • +
      • doesn’t execute any third party js on your website.
      • +
    • +
    • Cons: +
        +
      • doesn’t provide any popularity information.
      • +
    • +
    +

    Solution 1 (no js):

    +
    <a href="https://twitter.com/home?status=$url$"
    +    target="_blank">Tweet this</a>
    +
    +<a href="http://www.facebook.com/sharer/sharer.php?u=$url$"
    +    target="_blank">Like this</a>
    +
    +<a href="https://plus.google.com/share?url=$url$"
    +    target="_blank">Share on G+</a>
    +

    But you have to replace $url$ by the current url.

    +

    Solution 2 (Just copy/paste):

    +

    If you don’t want to write the url yourself, you could use some minimal js:

    +
    <script>
    +var url=document.location;
    +document.write(
    +  '<'+'a href="https://twitter.com/home?status='+url+'" '
    +    +'target="_blank">Tweet this<'+'/a> - '
    +
    ++ '<'+'a href="http://www.facebook.com/sharer/sharer.php?u='+url+'" '
    +    +'target="_blank">Like this<'+'/a> - '
    +
    ++ '<'+'a href="https://plus.google.com/share?url='+url+'" '
    +    +'target="_blank">Share on G+<'+'/a>');
    +</script>
    +

    Here is the result:

    +
    + +
    + +

    Good looking solutions

    +

    If you don’t want just text but nice icons. You have many choices:

    +
      +
    • Use images <img src="..."/> in the links.
    • +
    • Use icon fonts
    • +
    +

    As the first solution is pretty straightforward, I’ll explain the second one.

    +
      +
    1. Download the icon font here
    2. +
    3. put the font file(s) at some place (here ‘fonts/social_font.ttf’ relatively to your css file)
    4. +
    5. Add this to your css
    6. +
    +
    @font-face
    +  font-family: 'social'
    +  src: url('fonts/social_font.ttf') format('truetype')
    +  font-weight: normal
    +  font-style: normal
    +.social
    +  font-family: social
    +

    Now add this to your html:

    +

    Solution 1 (without js):

    +
    <a href="https://twitter.com/home?status=$url$"
    +    target="_blank"
    +    class="social">&#116;</a>
    +·
    +<a href="http://www.facebook.com/sharer/sharer.php?u=$url$"
    +   target="_blank"
    +   class="social">&#0096;</a>
    +·
    +<a href="https://plus.google.com/share?url=$url$"
    +    target="_blank"
    +    class="social">&#0103;</a>
    +

    Solution 2 (just copy/paste):

    +
    <script>
    +var url=document.location;
    +document.write(
    +    '<a href="https://twitter.com/home?status='+url+'"'
    +        + ' target="_blank"'
    +        + ' class="social">&#116;<'+'/a>'
    +    + ' · '
    +    + '<' + 'a href="http://www.facebook.com/sharer/sharer.php?u='+url+'"'
    +       + ' target="_blank"'
    +       + ' class="social">&#0096;<'+'/a>'
    +    + ' · '
    +    + '<a href="https://plus.google.com/share?url='+url+'"'
    +        + ' target="_blank"'
    +        + ' class="social">&#0103;<'+'/a>');
    +</script>
    +

    Here is the result:

    +
    + +
    + +

    Conclusion

    +
      +
    1. You get your design back,
    2. +
    3. You stop to help tracking people,
    4. +
    5. You use less computer ressources and more generally power ressources which is good for the planet,
    6. +
    7. Your web pages will load faster.
    8. +
    +

    ps: On my personal website I continue to use Google analytics. Therefore, Google (and only Google, not facebook nor twitter) can track you here. But I might change this in the future.

    +
    + +
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée +
    + + +
    +

    Comments

    +
    + + + comments powered by Disqus +
    + +
    +
    + Published on 2013-03-14 +
    + +
    + Yann Esposito© +
    +
    + Done with + Vim + & + Hakyll +
    +
    +
    + +
    + + + + + + + + diff --git a/Scratch/fr/blog/Typography-and-the-Web/index.html b/Scratch/fr/blog/Typography-and-the-Web/index.html index d2b171d..338e27b 100644 --- a/Scratch/fr/blog/Typography-and-the-Web/index.html +++ b/Scratch/fr/blog/Typography-and-the-Web/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    La typography et le Web

    -
    +

    @@ -111,25 +103,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -147,6 +140,7 @@ comments powered by Disqus
    +
    Published on 2012-02-02 diff --git a/Scratch/fr/blog/Yesod-excellent-ideas/index.html b/Scratch/fr/blog/Yesod-excellent-ideas/index.html index cf7923c..ef00a15 100644 --- a/Scratch/fr/blog/Yesod-excellent-ideas/index.html +++ b/Scratch/fr/blog/Yesod-excellent-ideas/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Les idées de yesod

    -
    +

    Title image

    @@ -65,7 +57,7 @@ SQL injection by a mom

    SQL injection by a mom

    Lorsque vous créez une application web, beaucoup de temps est passé à s’occuper de chaînes de caractères. Des chaînes de caractère pour les URL, le HTML, le Javascript, les CSS, les requêtes SQL, etc… Pour éviter des utilisation malicieuses vous devez protéger chaque chaîne de caractère entre chaque étape. Par exemple supposons que vous entriez comme nom :

    -
    Newton<script>alert("An apple fall")</script>
    +
    Newton<script>alert("An apple fall")</script>

    Sans une protection correcte, le message “An apple fall” sera affiché à chaque fois que quelqu’un essayera d’accéder au nom de cet utilisateur. Les “types saufs” sont le tonyglandil du web. A chaque chaine de caractère, on lui associe un “type”. A quoi sert cette chaîne de caractère ? Est-ce une URL ? Du javascript ? De l’HTML ? Entre chaque passage d’une représentation à une autre, un transformation is faite par défaut.

    Yesod fait de son mieux pour typer les objets manipulés et ainsi il fera ce qu’il faut pour ne pas mettre du script dans une URL par exemple.

    Go to the other page ~~~~~~

    @@ -127,25 +119,26 @@ toWidget hamletFile "buttonTemplate.hamlet"
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -163,6 +156,7 @@ toWidget hamletFile "buttonTemplate.hamlet"Please enable JavaScript to view the comments powered by Disqus. comments powered by Disqus
    +
    Published on 2011-10-04 diff --git a/Scratch/fr/blog/Yesod-tutorial-for-newbies/index.html b/Scratch/fr/blog/Yesod-tutorial-for-newbies/index.html index 84212d5..7b7d794 100644 --- a/Scratch/fr/blog/Yesod-tutorial-for-newbies/index.html +++ b/Scratch/fr/blog/Yesod-tutorial-for-newbies/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Site en Haskell

    -
    +

    Neo Flying at warp speed

    @@ -143,7 +135,7 @@ static/tmp
  • config/models
  • Obviously:

    -

    config/routes | is where you’ll configure the map %url → Code. |
    Handler/ | contains the files that will contain the code called when a %url is accessed. |
    templates/ | contains html, js and css templates. |
    config/models | is where you’ll configure the persistent objects (database tables). |

    +

    config/routes | is where you’ll configure the map url → Code. |
    Handler/ | contains the files that will contain the code called when a url is accessed. |
    templates/ | contains html, js and css templates. |
    config/models | is where you’ll configure the persistent objects (database tables). |

    During this tutorial we’ll modify other files as well, but we won’t explore them in detail.

    Also note, shell commands are executed in the root directory of your project instead specified otherwise.

    We are now ready to start!

    @@ -153,7 +145,7 @@ static/tmp

    Goal:

    Make a server that when accessed /echo/[some text] should return a web page containing “some text” inside an h1 bloc.

    -

    In a first time, we must declare the %url of the form /echo/... are meaningful. Let’s take a look at the file config/routes:

    +

    In a first time, we must declare the url of the form /echo/... are meaningful. Let’s take a look at the file config/routes:

     /static StaticR Static getStatic
     /auth   AuthR   Auth   getAuth
    @@ -169,7 +161,7 @@ static/tmp
     /echo/#String EchoR GET
     
    -

    This line contains three elements: the %url pattern, a handler name, an %http method. I am not particularly fan of the big R notation but this is the standard convention.

    +

    This line contains three elements: the url pattern, a handler name, an %http method. I am not particularly fan of the big R notation but this is the standard convention.

    If you save config/routes, you should see your terminal in which you launched yesod devel activate and certainly displaying an error message.

     Application.hs:31:1: Not in scope: `getEchoR'
    @@ -186,12 +178,12 @@ getEchoR theText = do
     

    TADA! It works!

    Bulletproof?

    Neo stops a myriad of bullets

    -

    Even this extremely minimal web application has some impressive properties. For exemple, imagine an attacker entering this %url:

    +

    Even this extremely minimal web application has some impressive properties. For exemple, imagine an attacker entering this url:

    [http://localhost:3000/echo/<a>I'm <script>alert("Bad!");](http://localhost:3000/echo/I’m

    " %>

    The special characters are protected for us. A malicious user could not hide some bad script inside.

    -

    This behavior is a direct consequence of type safety. The %url string is put inside a %url type. Then the interesting part in the %url is put inside a String type. To pass from %url type to String type some transformation are made. For example, replace all “%20” by space characters. Then to show the String inside an html document, the string is put inside an html type. Some transformations occurs like replace “<” by “&lt;”. Thanks to yesod, this tedious job is done for us.

    +

    This behavior is a direct consequence of type safety. The url string is put inside a url type. Then the interesting part in the url is put inside a String type. To pass from url type to String type some transformation are made. For example, replace all “%20” by space characters. Then to show the String inside an html document, the string is put inside an html type. Some transformations occurs like replace “<” by “&lt;”. Thanks to yesod, this tedious job is done for us.

    "http://localhost:3000/echo/some%20text<a>" :: URL
                         ↓
                   "some text<a>"                 :: String
    @@ -236,7 +228,7 @@ a:visited { col
     

    Generally you don’t want to have all your code inside a unique file. This is why we will separate our handlers. In a first time create a new file Handler/Echo.hs containing:

    module Handler.Echo where
     
    -import Import
    +import Import
     
     getEchoR :: String -> Handler RepHtml
     getEchoR theText = do
    @@ -249,7 +241,7 @@ getEchoR theText = do
     

    We must also declare this new Handler module inside Application.hs. Just after the “import Handler.Home”, add:

    -
    import Handler.Echo
    +
    import Handler.Echo

    This is it.

    ps: I am sure not so far in the future we could simply write yesod add-handler Echo to declare it and create a new handler file.

    Data.Text

    @@ -264,7 +256,7 @@ getEchoR theText = do

    And do the same in Handler/Echo.hs:

    module Handler.Echo where
     
    -import Import
    +import Import
     
     getEchoR :: Text -> Handler RepHtml
     getEchoR theText = do
    @@ -290,8 +282,8 @@ getEchoR theText = do
     

    This time the path /mirror will accept GET and POST requests. Add the corresponding new Handler file:

    module Handler.Mirror where
     
    -import Import
    -import qualified Data.Text as T
    +import Import
    +import qualified Data.Text as T
     
     getMirrorR :: Handler RepHtml
     getMirrorR = do
    @@ -349,11 +341,11 @@ Article
         )
     where
     
    -import Import
    -import Data.Monoid
    +import Import
    +import Data.Monoid
     
     -- to use Html into forms
    -import Yesod.Form.Nic (YesodNic, nicHtmlField)
    +import Yesod.Form.Nic (YesodNic, nicHtmlField)
     instance YesodNic App

    Remark: it is a best practice to add the YesodNic instance inside Foundation.hs. I put this definition here to make things easier but you should see a warning about this orphan instance. To put the include inside Foundation.hs is left as an exercice to the reader.

    Hint: Do not forget to put YesodNic and nicHtmlField inside the exported objects of the module.

    @@ -428,7 +420,7 @@ getArticleR articleId = do
    <p>A last try to <em>cross script</em> 
        and <em>SQL injection</em></p>
     <p>Here is the first try: 
    -   <script>alert("You loose");</script></p>
    +   <script>alert("You loose");</script></p>
     <p> And Here is the last </p>
     "); DROP TABLE ARTICLE;;

    Conclusion

    @@ -458,25 +450,26 @@ getArticleR articleId = do
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -494,6 +487,7 @@ getArticleR articleId = do comments powered by Disqus
    +
    Published on 2012-01-15 diff --git a/Scratch/fr/blog/feed/feed.xml b/Scratch/fr/blog/feed/feed.xml index cfe47b7..0e18d1c 100644 --- a/Scratch/fr/blog/feed/feed.xml +++ b/Scratch/fr/blog/feed/feed.xml @@ -8,8 +8,176 @@ Yann Esposito yann.esposito@gmail.com - 2012-12-12T00:00:00Z + 2013-03-14T00:00:00Z + Être correct avec les boutons share + + http://yannesposito.com/Scratch/fr/blog/Social-link-the-right-way/index.html + 2013-03-14T00:00:00Z + 2013-03-14T00:00:00Z + Main image

    +
    + + +

    tlpl: Les boutons des réseaux sociaux traquent vos utilisateurs, ont un design incohérent avec celui de votre site, utilisent des ressources, ralentissent le rendu de vos pages.

    +

    Faite les choses bien. Utilisez des liens statiques.

    +
    + +

    The problem

    +

    Ever been on a website and want to tweet about it? Fortunately, the website might have a button to help you. But do you really know what this button do?

    +

    The “Like”, “Tweet” and “+1” buttons will call a javascript. It will get access to your cookies. It helps the provider of the button to know who you are.

    +

    In plain English, the “+1” button will inform Google you are visiting the website, even if you don’t click on “+1”. The same is true for the “like” button for facebook and the “tweet this” button for twitter.

    +

    The problem is not only a privacy issue. In fact (sadly imho) this isn’t an issue for most people. These button consume computer ressources. Far more than a simple link. It thus slow down a bit the computer and consume energy. These button could also slow down the rendering of your web page.

    +

    Another aspect is their design. Their look and feel is mostly imposed by the provider.

    +

    The most problematic aspect in my opinion is to use a third party js on your website. What if tomorrow twitter update their tweet button? If the upgrade broke something for only a minority of people, they won’t fix it. This could occur anytime without any notification. They just have to add a document.write in their js you call asynchronously and BAM! Your website is just an empty blank page. And as you call many external ressources, it can be very difficult to find the origin of the problem.

    +

    Using social network buttons:

    +
      +
    • Pros: +
        +
      • help user share your website,
      • +
      • can provide a popularity indicator to your users.
      • +
    • +
    • Cons: +
        +
      • you help tracking your users,
      • +
      • generally doesn’t follow the design of your website,
      • +
      • use more computer ressources,
      • +
      • slow down your website,
      • +
      • executing third party js can break things silently.
      • +
    • +
    +

    Solutions

    +

    I will provide you two solutions with the following properties:

    +
      +
    • Pros: +
        +
      • help user share your website,
      • +
      • doesn’t follow your user,
      • +
      • use almost no computer ressource,
      • +
      • doesn’t slow down your website,
      • +
      • doesn’t execute any third party js on your website.
      • +
    • +
    • Cons: +
        +
      • doesn’t provide any popularity information.
      • +
    • +
    +

    Solution 1 (no js):

    +
    <a href="https://twitter.com/home?status=$url$"
    +    target="_blank">Tweet this</a>
    +
    +<a href="http://www.facebook.com/sharer/sharer.php?u=$url$"
    +    target="_blank">Like this</a>
    +
    +<a href="https://plus.google.com/share?url=$url$"
    +    target="_blank">+1 this</a>
    +

    But you have to replace $url$ by the current url.

    +

    Solution 2 (Just copy/paste):

    +

    If you don’t want to write the url yourself, you could use some minimal js:

    +
    <script>
    +var url=document.location;
    +document.write(
    +  '<'+'a href="https://twitter.com/home?status='+url+'" '
    +    +'target="_blank">Tweet this<'+'/a> - '
    +
    ++ '<'+'a href="http://www.facebook.com/sharer/sharer.php?u='+url+'" '
    +    +'target="_blank">Like this<'+'/a> - '
    +
    ++ '<'+'a href="https://plus.google.com/share?url='+url+'" '
    +    +'target="_blank">+1 this<'+'/a>');
    +</script>
    +

    Here is the result:

    +
    + +
    + +

    Good looking solutions

    +

    If you don’t want just text but nice icons. You have many choices:

    +
      +
    • Use images <img src="..."/> in the links.
    • +
    • Use icon fonts
    • +
    +

    As the first solution is pretty straightforward, I’ll explain the second one.

    +
      +
    1. Download the icon font here
    2. +
    3. put the font file(s) at some place (here ‘fonts/social_font.ttf’ relatively to your css file)
    4. +
    5. Add this to your css
    6. +
    +
    @font-face
    +  font-family: 'social'
    +  src: url('fonts/social_font.ttf') format('truetype')
    +  font-weight: normal
    +  font-style: normal
    +.social
    +  font-family: social
    +

    Now add this to your html:

    +

    Solution 1 (without js):

    +
    <a href="https://twitter.com/home?status=$url$"
    +    target="_blank"
    +    class="social">&#116;</a>
    +·
    +<a href="http://www.facebook.com/sharer/sharer.php?u=$url$"
    +   target="_blank"
    +   class="social">&#0096;</a>
    +·
    +<a href="https://plus.google.com/share?url=$url$"
    +    target="_blank"
    +    class="social">&#0103;</a>
    +

    Solution 2 (just copy/paste):

    +
    <script>
    +var url=document.location;
    +document.write(
    +    '<a href="https://twitter.com/home?status='+url+'"'
    +        + ' target="_blank"'
    +        + ' class="social">&#116;<'+'/a>'
    +    + ' · '
    +    + '<' + 'a href="http://www.facebook.com/sharer/sharer.php?u='+url+'"'
    +       + ' target="_blank"'
    +       + ' class="social">&#0096;<'+'/a>'
    +    + ' · '
    +    + '<a href="https://plus.google.com/share?url='+url+'"'
    +        + ' target="_blank"'
    +        + ' class="social">&#0103;<'+'/a>');
    +</script>
    +

    Here is the result:

    +
    + +
    + +

    Conclusion

    +
      +
    1. You get your design back,
    2. +
    3. You stop to help tracking people,
    4. +
    5. You use less computer ressources and more generally power ressources which is good for the planet,
    6. +
    7. Your web pages will load faster.
    8. +
    +

    ps: On my personal website I continue to use Google analytics. Therefore, Google (and only Google, not facebook nor twitter) can track you here. But I might change this in the future.

    ]]>
    +
    + Category Theory Presentation http://yannesposito.com/Scratch/fr/blog/Category-Theory-Presentation/index.html @@ -1035,9 +1203,9 @@ Another detail of the Mandelbulb

    We can consider two parts. The first being mostly some boilerplate2. And the second part more focused on OpenGL and content.

    Let’s play the song of our people

    -
    import Graphics.Rendering.OpenGL
    -import Graphics.UI.GLUT
    -import Data.IORef
    +
    import Graphics.Rendering.OpenGL
    +import Graphics.UI.GLUT
    +import Data.IORef

    For efficiency reason3, I will not use the default Haskell Complex data type.

    @@ -1047,11 +1215,11 @@ Another detail of the Mandelbulb
    instance Num Complex where
    -    fromInteger n = C (fromIntegral n,0.0)
    +    fromInteger n = C (fromIntegral n,0.0)
         C (x,y) * C (z,t) = C (z*x - y*t, y*z + x*t)
         C (x,y) + C (z,t) = C (x+z, y+t)
    -    abs (C (x,y))     = C (sqrt (x*x + y*y),0.0)
    -    signum (C (x,y))  = C (signum x , 0.0)
    + abs (C (x,y)) = C (sqrt (x*x + y*y),0.0) + signum (C (x,y)) = C (signum x , 0.0)

    We declare some useful functions for manipulating complex numbers:

    @@ -1138,16 +1306,16 @@ allPoints = [ (x/width,ycolorFromValue n = let t :: Int -> GLfloat - t i = 0.5 + 0.5*cos( fromIntegral i / 10 ) + t i = 0.5 + 0.5*cos( fromIntegral i / 10 ) in - Color3 (t n) (t (n+5)) (t (n+10)) + Color3 (t n) (t (n+5)) (t (n+10))

    And now the mandel function. Given two coordinates in pixels, it returns some integer value:

    mandel x y = 
    -  let r = 2.0 * x / width
    -      i = 2.0 * y / height
    +  let r = 2.0 * x / width
    +      i = 2.0 * y / height
       in
           f (complex r i) 0 64
    @@ -1163,7 +1331,7 @@ allPoints = [ (x/width,y0 = 0 f c z n = if (magnitude z > 2 ) then n - else f c ((z*z)+c) (n-1)
    + else f c ((z*z)+c) (n-1)

    Well, if you download this file (look at the bottom of this section), compile it and run it this is the result:

    @@ -1179,20 +1347,20 @@ f c z n = if (magnitude z
    -
    import Graphics.Rendering.OpenGL
    -import Graphics.UI.GLUT
    -import Data.IORef
    +
    import Graphics.Rendering.OpenGL
    +import Graphics.UI.GLUT
    +import Data.IORef
     -- Use UNPACK data because it is faster
     -- The ! is for strict instead of lazy
     data Complex = C  {-# UNPACK #-} !Float 
                       {-# UNPACK #-} !Float 
                    deriving (Show,Eq)
     instance Num Complex where
    -    fromInteger n = C (fromIntegral n) 0.0
    +    fromInteger n = C (fromIntegral n) 0.0
         (C x y) * (C z t) = C (z*x - y*t) (y*z + x*t)
         (C x y) + (C z t) = C (x+z) (y+t)
    -    abs (C x y)     = C (sqrt (x*x + y*y)) 0.0
    -    signum (C x y)  = C (signum x) 0.0
    +    abs (C x y)     = C (sqrt (x*x + y*y)) 0.0
    +    signum (C x y)  = C (signum x) 0.0
     complex :: Float -> Float -> Complex
     complex x y = C x y
     
    @@ -1219,7 +1387,7 @@ main = do
       mainLoop
     display = do
        -- set the background color (dark solarized theme)
    -  clearColor $= Color4 0 0.1686 0.2117 1
    +  clearColor $= Color4 0 0.1686 0.2117 1
       clear [ColorBuffer] -- make the window black
       loadIdentity -- reset any transformation
       preservingMatrix drawMandelbrot
    @@ -1284,8 +1452,8 @@ positivePoints = do
     maxZeroIndex func minval maxval 0 = (minval+maxval)/2
     maxZeroIndex func minval maxval n = 
       if (func medpoint) /= 0 
    -       then maxZeroIndex func minval medpoint (n-1)
    -       else maxZeroIndex func medpoint maxval (n-1)
    +       then maxZeroIndex func minval medpoint (n-1)
    +       else maxZeroIndex func medpoint maxval (n-1)
       where medpoint = (minval+maxval)/2
    @@ -1297,15 +1465,15 @@ maxZeroIndex func minval maxval n =
    colorFromValue n =
       let 
           t :: Int -> GLfloat
    -      t i = 0.5 + 0.5*cos( fromIntegral i / 10 )
    +      t i = 0.5 + 0.5*cos( fromIntegral i / 10 )
       in
    -    Color3 (t n) (t (n+5)) (t (n+10))
    + Color3 (t n) (t (n+5)) (t (n+10))
    mandel x y = 
    -  let r = 2.0 * x / width
    -      i = 2.0 * y / height
    +  let r = 2.0 * x / width
    +      i = 2.0 * y / height
       in
           f (complex r i) 0 64
    @@ -1315,7 +1483,7 @@ maxZeroIndex func minval maxval n = f c z 0 = 0 f c z n = if (magnitude z > 2 ) then n - else f c ((z*z)+c) (n-1) + else f c ((z*z)+c) (n-1)
    @@ -1345,9 +1513,9 @@ f c z n = if (magnitude z
    -
    import Graphics.Rendering.OpenGL
    -import Graphics.UI.GLUT
    -import Data.IORef
    +
    import Graphics.Rendering.OpenGL
    +import Graphics.UI.GLUT
    +import Data.IORef
     type ColoredPoint = (GLfloat,GLfloat,GLfloat,Color3 GLfloat)
    @@ -1415,7 +1583,7 @@ main = do -- Some state variables (I know it feels BAD) angle <- newIORef ((35,0)::(GLfloat,GLfloat)) zoom <- newIORef (2::GLfloat) - campos <- newIORef ((0.7,0)::(GLfloat,GLfloat)) + campos <- newIORef ((0.7,0)::(GLfloat,GLfloat)) -- Function to call each frame idleCallback $= Just idle -- Function to call when keyboard or mouse is used @@ -1455,18 +1623,18 @@ mapSnd f (x,y) = ( x,f y) z $= 1 -- zoom p $= (0,0) -- camera position -- use of hjkl to rotate - kact a _ _ (Char 'h') Down = modVar a (mapFst (+0.5)) - kact a _ _ (Char 'l') Down = modVar a (mapFst (+(-0.5))) - kact a _ _ (Char 'j') Down = modVar a (mapSnd (+0.5)) - kact a _ _ (Char 'k') Down = modVar a (mapSnd (+(-0.5))) + kact a _ _ (Char 'h') Down = modVar a (mapFst (+0.5)) + kact a _ _ (Char 'l') Down = modVar a (mapFst (+(-0.5))) + kact a _ _ (Char 'j') Down = modVar a (mapSnd (+0.5)) + kact a _ _ (Char 'k') Down = modVar a (mapSnd (+(-0.5))) -- use o and i to zoom - kact _ z _ (Char 'o') Down = modVar z (*1.1) - kact _ z _ (Char 'i') Down = modVar z (*0.9) + kact _ z _ (Char 'o') Down = modVar z (*1.1) + kact _ z _ (Char 'i') Down = modVar z (*0.9) -- use sdfe to move the camera - kact _ _ p (Char 's') Down = modVar p (mapFst (+0.1)) - kact _ _ p (Char 'f') Down = modVar p (mapFst (+(-0.1))) - kact _ _ p (Char 'd') Down = modVar p (mapSnd (+0.1)) - kact _ _ p (Char 'e') Down = modVar p (mapSnd (+(-0.1))) + kact _ _ p (Char 's') Down = modVar p (mapFst (+0.1)) + kact _ _ p (Char 'f') Down = modVar p (mapFst (+(-0.1))) + kact _ _ p (Char 'd') Down = modVar p (mapSnd (+0.1)) + kact _ _ p (Char 'e') Down = modVar p (mapSnd (+(-0.1))) -- any other keys does nothing kact _ _ _ _ _ = return ()
    @@ -1475,7 +1643,7 @@ mapSnd f (x,y) = ( x,f y)
    display angle zoom position = do
        -- set the background color (dark solarized theme)
    -  clearColor $= Color4 0 0.1686 0.2117 1
    +  clearColor $= Color4 0 0.1686 0.2117 1
       clear [ColorBuffer,DepthBuffer]
       -- Transformation to change the view
       loadIdentity -- reset any transformation
    @@ -1487,8 +1655,8 @@ mapSnd f (x,y) = (  x,f y)
    scale z z z -- rotate (xangle,yangle) <- get angle - rotate xangle $ Vector3 1.0 0.0 (0.0::GLfloat) - rotate yangle $ Vector3 0.0 1.0 (0.0::GLfloat) + rotate xangle $ Vector3 1.0 0.0 (0.0::GLfloat) + rotate yangle $ Vector3 0.0 1.0 (0.0::GLfloat) -- Now that all transformation were made -- We create the object(s) @@ -1537,17 +1705,17 @@ depthPoints = do depthOf x' y' = maxZeroIndex (mandel x' y') 0 deep logdeep logdeep = floor ((log deep) / log 2) z1 = depthOf x y - z2 = depthOf (x+1) y - z3 = depthOf (x+1) (y+1) - z4 = depthOf x (y+1) - c1 = mandel x y (z1+1) - c2 = mandel (x+1) y (z2+1) - c3 = mandel (x+1) (y+1) (z3+1) - c4 = mandel x (y+1) (z4+1) + z2 = depthOf (x+1) y + z3 = depthOf (x+1) (y+1) + z4 = depthOf x (y+1) + c1 = mandel x y (z1+1) + c2 = mandel (x+1) y (z2+1) + c3 = mandel (x+1) (y+1) (z3+1) + c4 = mandel x (y+1) (z4+1) p1 = ( x /width, y /height, z1/deep, colorFromValue c1) - p2 = ((x+1)/width, y /height, z2/deep, colorFromValue c2) - p3 = ((x+1)/width,(y+1)/height, z3/deep, colorFromValue c3) - p4 = ( x /width,(y+1)/height, z4/deep, colorFromValue c4) + p2 = ((x+1)/width, y /height, z2/deep, colorFromValue c2) + p3 = ((x+1)/width,(y+1)/height, z3/deep, colorFromValue c3) + p4 = ( x /width,(y+1)/height, z4/deep, colorFromValue c4) if (and $ map (>=57) [c1,c2,c3,c4]) then [] else [p1,p2,p3,p1,p3,p4] @@ -1558,13 +1726,13 @@ depthPoints = do x <- [-width..width] y <- [-height..height] let - neighbors = [(x,y),(x+1,y),(x+1,y+1),(x,y+1)] + neighbors = [(x,y),(x+1,y),(x+1,y+1),(x,y+1)] depthOf (u,v) = maxZeroIndex (mandel u v) 0 deep logdeep logdeep = floor ((log deep) / log 2) -- zs are 3D points with found depth zs = map (\(u,v) -> (u,v,depthOf (u,v))) neighbors -- ts are 3D pixels + mandel value - ts = map (\(u,v,w) -> (u,v,w,mandel u v (w+1))) zs + ts = map (\(u,v,w) -> (u,v,w,mandel u v (w+1))) zs -- ps are 3D opengl points + color value ps = map (\(u,v,w,c') -> (u/width,v/height,w/deep,colorFromValue c')) ts @@ -1582,7 +1750,7 @@ depthPoints = do allPoints = planPoints ++ map inverseDepth planPoints where planPoints = depthPoints - inverseDepth (x,y,z,c) = (x,y,-z+1/deep,c) + inverseDepth (x,y,z,c) = (x,y,-z+1/deep,c)

    The rest of the program is very close to the preceding one.

    @@ -1602,8 +1770,8 @@ allPoints = planPoints ++ 0 = (minval+maxval)/2 maxZeroIndex func minval maxval n = if (func medpoint) /= 0 - then maxZeroIndex func minval medpoint (n-1) - else maxZeroIndex func medpoint maxval (n-1) + then maxZeroIndex func minval medpoint (n-1) + else maxZeroIndex func medpoint maxval (n-1) where medpoint = (minval+maxval)/2
    @@ -1612,9 +1780,9 @@ maxZeroIndex func minval maxval n =
    colorFromValue n =
       let 
           t :: Int -> GLfloat
    -      t i = 0.7 + 0.3*cos( fromIntegral i / 10 )
    +      t i = 0.7 + 0.3*cos( fromIntegral i / 10 )
       in
    -    Color3 (t n) (t (n+5)) (t (n+10))
    + Color3 (t n) (t (n+5)) (t (n+10))

    We only changed from Complex to ExtComplex of the main f function.

    @@ -1623,7 +1791,7 @@ maxZeroIndex func minval maxval n = f c z 0 = 0 f c z n = if (magnitude z > 2 ) then n - else f c ((z*z)+c) (n-1) + else f c ((z*z)+c) (n-1)
    @@ -1631,9 +1799,9 @@ f c z n = if (magnitude z We simply add a new dimension to the mandel function and change the type signature of f from Complex to ExtComplex.

    mandel x y z = 
    -  let r = 2.0 * x / width
    -      i = 2.0 * y / height
    -      s = 2.0 * z / deep
    +  let r = 2.0 * x / width
    +      i = 2.0 * y / height
    +      s = 2.0 * z / deep
       in
           f (extcomplex r i s) 0 64
    @@ -1651,8 +1819,8 @@ f c z n = if (magnitude z ExtComplex, the extended complexes
    -
    import YBoiler -- Most the OpenGL Boilerplate
    -import Mandel -- The 3D Mandelbrot maths
    +
    import YBoiler -- Most the OpenGL Boilerplate
    +import Mandel -- The 3D Mandelbrot maths

    The yMainLoop takes two arguments: the title of the window and a function from time to triangles

    @@ -1676,7 +1844,7 @@ allPoints = planPoints ++ where planPoints = depthPoints ++ map inverseHeight depthPoints inverseHeight (x,y,z,c) = (x,-y,z,c) - inverseDepth (x,y,z,c) = (x,y,-z+1/deep,c) + inverseDepth (x,y,z,c) = (x,y,-z+1/deep,c)
    @@ -1685,12 +1853,12 @@ depthPoints = do x <- [-width..width] y <- [0..height] let - neighbors = [(x,y),(x+1,y),(x+1,y+1),(x,y+1)] + neighbors = [(x,y),(x+1,y),(x+1,y+1),(x,y+1)] depthOf (u,v) = maxZeroIndex (ymandel u v) 0 deep 7 -- zs are 3D points with found depth zs = map (\(u,v) -> (u,v,depthOf (u,v))) neighbors -- ts are 3D pixels + mandel value - ts = map (\(u,v,w) -> (u,v,w,ymandel u v (w+1))) zs + ts = map (\(u,v,w) -> (u,v,w,ymandel u v (w+1))) zs -- ps are 3D opengl points + color value ps = map (\(u,v,w,c') -> (u/width,v/height,w/deep,colorFromValue c')) ts @@ -1711,16 +1879,16 @@ depthPoints = do maxZeroIndex func minval maxval 0 = (minval+maxval)/2 maxZeroIndex func minval maxval n = if (func medpoint) /= 0 - then maxZeroIndex func minval medpoint (n-1) - else maxZeroIndex func medpoint maxval (n-1) + then maxZeroIndex func minval medpoint (n-1) + else maxZeroIndex func medpoint maxval (n-1) where medpoint = (minval+maxval)/2 colorFromValue n = let t :: Int -> GLfloat - t i = 0.7 + 0.3*cos( fromIntegral i / 10 ) + t i = 0.7 + 0.3*cos( fromIntegral i / 10 ) in - ((t n),(t (n+5)),(t (n+10))) + ((t n),(t (n+5)),(t (n+10))) ymandel x y z = mandel (2*x/width) (2*y/height) (2*z/deep) 64
    @@ -1754,8 +1922,8 @@ ymandel x y z = mandel (2

    Here is a real working code, I’ve hidden most display functions. The YGL, is a kind of framework to display 3D functions. But it can easily be extended to many kind of representation.

    -
    import YGL -- Most the OpenGL Boilerplate
    -import Mandel -- The 3D Mandelbrot maths
    +
    import YGL -- Most the OpenGL Boilerplate
    +import Mandel -- The 3D Mandelbrot maths

    We first set the mapping between user input and actions. The type of each couple should be of the form (user input, f) where (in a first time) f:World -> World. It means, the user input will transform the world state.

    @@ -1769,16 +1937,16 @@ inputActionMap = inputMapFromList [ ,(Press 'l' , rotate ydir (-5)) ,(Press 'o' , rotate zdir 5) ,(Press 'u' , rotate zdir (-5)) - ,(Press 'f' , translate xdir 0.1) - ,(Press 's' , translate xdir (-0.1)) - ,(Press 'e' , translate ydir 0.1) - ,(Press 'd' , translate ydir (-0.1)) - ,(Press 'z' , translate zdir 0.1) - ,(Press 'r' , translate zdir (-0.1)) - ,(Press '+' , zoom 1.1) - ,(Press '-' , zoom (1/1.1)) - ,(Press 'h' , resize 1.2) - ,(Press 'g' , resize (1/1.2)) + ,(Press 'f' , translate xdir 0.1) + ,(Press 's' , translate xdir (-0.1)) + ,(Press 'e' , translate ydir 0.1) + ,(Press 'd' , translate ydir (-0.1)) + ,(Press 'z' , translate zdir 0.1) + ,(Press 'r' , translate zdir (-0.1)) + ,(Press '+' , zoom 1.1) + ,(Press '-' , zoom (1/1.1)) + ,(Press 'h' , resize 1.2) + ,(Press 'g' , resize (1/1.2)) ]
    @@ -1871,11 +2039,11 @@ main = yMainLoop inputActionMap idleAction initialWorld< initialWorld = World { angle = makePoint3D (-30,-30,0) , position = makePoint3D (0,0,0) - , scale = 0.8 + , scale = 0.8 , shape = shapeFunc , box = Box3D { minPoint = makePoint3D (-2,-2,-2) , maxPoint = makePoint3D (2,2,2) - , resolution = 0.16 } + , resolution = 0.16 } , told = 0 }
    @@ -1888,8 +2056,8 @@ idleAction tnew world = world { , told = tnew } where - anglePerSec = 5.0 - delta = anglePerSec * elapsed / 1000.0 + anglePerSec = 5.0 + delta = anglePerSec * elapsed / 1000.0 elapsed = fromIntegral (tnew - (told world))
    @@ -1901,7 +2069,7 @@ shapeFunc res x y = let z = maxZeroIndex (ymandel x y) 0 1 20 in - if and [ maxZeroIndex (ymandel (x+xeps) (y+yeps)) 0 1 20 < 0.000001 | + if and [ maxZeroIndex (ymandel (x+xeps) (y+yeps)) 0 1 20 < 0.000001 | val <- [res], xeps <- [-val,val], yeps<-[-val,val]] then Nothing else Just (z,colorFromValue ((ymandel x y z) * 64)) @@ -1913,9 +2081,9 @@ shapeFunc res x y = colorFromValue n = let t :: Point -> Scalar - t i = 0.7 + 0.3*cos( i / 10 ) + t i = 0.7 + 0.3*cos( i / 10 ) in - makeColor (t n) (t (n+5)) (t (n+10)) + makeColor (t n) (t (n+5)) (t (n+10))

    The rest is similar to the preceding sections.

    @@ -1933,8 +2101,8 @@ colorFromValue n = maxZeroIndex _ minval maxval 0 = (minval+maxval)/2 maxZeroIndex func minval maxval n = if (func medpoint) /= 0 - then maxZeroIndex func minval medpoint (n-1) - else maxZeroIndex func medpoint maxval (n-1) + then maxZeroIndex func minval medpoint (n-1) + else maxZeroIndex func medpoint maxval (n-1) where medpoint = (minval+maxval)/2 ymandel :: Point -> Point -> Point -> Point @@ -1961,8 +2129,8 @@ ymandel x y z = fromIntegral (ma
    -
    import YGL -- Most the OpenGL Boilerplate
    -import Mandel -- The 3D Mandelbrot maths
    +
    import YGL -- Most the OpenGL Boilerplate
    +import Mandel -- The 3D Mandelbrot maths
     
     -- Centralize all user input interaction
     inputActionMap :: InputMap World
    @@ -1974,16 +2142,16 @@ inputActionMap = inputMapFromList [
         ,(Press 'l' , rotate ydir (-5))
         ,(Press 'o' , rotate zdir 5)
         ,(Press 'u' , rotate zdir (-5))
    -    ,(Press 'f' , translate xdir 0.1)
    -    ,(Press 's' , translate xdir (-0.1))
    -    ,(Press 'e' , translate ydir 0.1)
    -    ,(Press 'd' , translate ydir (-0.1))
    -    ,(Press 'z' , translate zdir 0.1)
    -    ,(Press 'r' , translate zdir (-0.1))
    -    ,(Press '+' , zoom 1.1)
    -    ,(Press '-' , zoom (1/1.1))
    -    ,(Press 'h' , resize 2.0)
    -    ,(Press 'g' , resize (1/2.0))
    +    ,(Press 'f' , translate xdir 0.1)
    +    ,(Press 's' , translate xdir (-0.1))
    +    ,(Press 'e' , translate ydir 0.1)
    +    ,(Press 'd' , translate ydir (-0.1))
    +    ,(Press 'z' , translate zdir 0.1)
    +    ,(Press 'r' , translate zdir (-0.1))
    +    ,(Press '+' , zoom 1.1)
    +    ,(Press '-' , zoom (1/1.1))
    +    ,(Press 'h' , resize 2.0)
    +    ,(Press 'g' , resize (1/2.0))
         ]
    @@ -2031,7 +2199,7 @@ rotate dir angleValue world = switchRotation :: World -> World switchRotation world = world { - anglePerSec = if anglePerSec world > 0 then 0 else 5.0 } + anglePerSec = if anglePerSec world > 0 then 0 else 5.0 } translate :: Point3D -> Scalar -> World -> World translate dir len world = @@ -2058,12 +2226,12 @@ main = yMainLoop inputActionMap idleAction initialWorld< initialWorld :: World initialWorld = World { angle = makePoint3D (30,30,0) - , anglePerSec = 5.0 + , anglePerSec = 5.0 , position = makePoint3D (0,0,0) - , scale = 1.0 + , scale = 1.0 , box = Box3D { minPoint = makePoint3D (0-eps, 0-eps, 0-eps) , maxPoint = makePoint3D (0+eps, 0+eps, 0+eps) - , resolution = 0.02 } + , resolution = 0.02 } , told = 0 -- We declare cache directly this time , cache = objectFunctionFromWorld initialWorld @@ -2107,7 +2275,7 @@ idleAction tnew world = , told = tnew } where - delta = anglePerSec world * elapsed / 1000.0 + delta = anglePerSec world * elapsed / 1000.0 elapsed = fromIntegral (tnew - (told world)) shapeFunc :: Scalar -> Function3D @@ -2115,7 +2283,7 @@ shapeFunc res x y = let z = maxZeroIndex (ymandel x y) 0 1 20 in - if and [ maxZeroIndex (ymandel (x+xeps) (y+yeps)) 0 1 20 < 0.000001 | + if and [ maxZeroIndex (ymandel (x+xeps) (y+yeps)) 0 1 20 < 0.000001 | val <- [res], xeps <- [-val,val], yeps<-[-val,val]] then Nothing else Just (z,colorFromValue 0) @@ -2124,9 +2292,9 @@ shapeFunc res x y = colorFromValue n = let t :: Point -> Scalar - t i = 0.0 + 0.5*cos( i /10 ) + t i = 0.0 + 0.5*cos( i /10 ) in - makeColor (t n) (t (n+5)) (t (n+10)) + makeColor (t n) (t (n+5)) (t (n+10)) -- given f min max nbtest, -- considering @@ -2141,8 +2309,8 @@ colorFromValue n = maxZeroIndex _ minval maxval 0 = (minval+maxval)/2 maxZeroIndex func minval maxval n = if func medpoint /= 0 - then maxZeroIndex func minval medpoint (n-1) - else maxZeroIndex func medpoint maxval (n-1) + then maxZeroIndex func minval medpoint (n-1) + else maxZeroIndex func medpoint maxval (n-1) where medpoint = (minval+maxval)/2 ymandel :: Point -> Point -> Point -> Point @@ -2387,7 +2555,7 @@ Function declaration return x*x + y*y; }

    In Javascript:

    -
    function f(x,y) {
    +
    function f(x,y) {
         return x*x + y*y;
     }

    in Python:

    @@ -2427,7 +2595,7 @@ main = print (f f :: Int -> Int -> Int f x y = x*x + y*y -main = print (f 2.3 4.2)
    +main = print (f 2.3 4.2)

    You get this error:

    21_very_basic.lhs:6:23:
    @@ -2445,7 +2613,7 @@ main = print (f 
     
    f x y = x*x + y*y
     
    -main = print (f 2.3 4.2)
    +main = print (f 2.3 4.2)

    It works! Great, we don’t have to declare a new function for every single type. For example, in C, you’ll have to declare a function for int, for float, for long, for double, etc…

    But, what type should we declare? To discover the type Haskell has found for us, just launch ghci:

    @@ -2492,7 +2660,7 @@ g y ⇔ 3*3 + y*y
    f :: Num a => a -> a -> a
     f x y = x*x + y*y
     
    -main = print (f 3 2.4)
    +main = print (f 3 2.4)

    It works, because, 3 is a valid representation both for Fractional numbers like Float and for Integer. As 2.4 is a Fractional number, 3 is then interpreted as being also a Fractional number.

    01_basic/10_Introduction/23_very_basic.lhs

    @@ -2506,7 +2674,7 @@ f x y = x*x +x :: Int x = 3 y :: Float -y = 2.4 +y = 2.4 main = print (f x y) -- won't work because type x ≠ type y

    The compiler complains. The two parameters must have the same type.

    @@ -2695,9 +2863,9 @@ Functional style

    example: [1,2,3,4,5] ⇒ 2 + 4 ⇒ 6

    To show differences between the functional and imperative approach, I’ll start by providing an imperative solution (in Javascript):

    -
    function evenSum(list) {
    +
    function evenSum(list) {
         var result = 0;
    -    for (var i=0; i< list.length ; i++) {
    +    for (var i=0; i< list.length ; i++) {
             if (list[i] % 2 ==0) {
                 result += list[i];
             }
    @@ -2938,7 +3106,7 @@ myfunc list = foldl bar initialVa
     
    -- Version 6
     -- foldl' isn't accessible by default
     -- we need to import it from the module Data.List
    -import Data.List
    +import Data.List
     evenSum l = foldl' mysum 0 (filter even l)
       where mysum acc value = acc + value

    Version we can simplify by using directly a lambda notation. This way we don’t have to create the temporary name mysum.

    @@ -2946,7 +3114,7 @@ evenSum l = foldl' mysum 0 (
    -- Version 7
     -- Generally it is considered a good practice
     -- to import only the necessary function(s)
    -import Data.List (foldl')
    +import Data.List (foldl')
     evenSum l = foldl' (\x y -> x+y) 0 (filter even l)

    And of course, we note that

    @@ -2963,7 +3131,7 @@ evenSum l = foldl' (\x y ->02_Hard_Part/16_Functions.lhs

    Finally

    -- Version 8
    -import Data.List (foldl')
    +import Data.List (foldl')
     evenSum :: Integral a => [a] -> a
     evenSum l = foldl' (+) 0 (filter even l)

    foldl' isn’t the easiest function to intuit. If you are not used to it, you should study it a bit.

    @@ -2983,13 +3151,13 @@ evenSum l = foldl' (+) (f . g . h) x ⇔ f ( g (h x))

    We can take advantage of this operator to η-reduce our function:

    -- Version 9
    -import Data.List (foldl')
    +import Data.List (foldl')
     evenSum :: Integral a => [a] -> a
     evenSum = (foldl' (+) 0) . (filter even)

    Also, we could rename some parts to make it clearer:

    -- Version 10 
    -import Data.List (foldl')
    +import Data.List (foldl')
     sum' :: (Num a) => [a] -> a
     sum' = foldl' (+) 0
     evenSum :: Integral a => [a] -> a
    @@ -3141,9 +3309,9 @@ main = putStrLn And many accessors are made for you. Furthermore you can use another order when setting values.

    Example:

    data Complex = Num a => Complex { real :: a, img :: a}
    -c = Complex 1.0 2.0
    +c = Complex 1.0 2.0
     z = Complex { real = 3, img = 4 }
    -real c  1.0
    +real c  1.0
     img z  4

    02_Hard_Part/22_Types.lhs


    @@ -3187,7 +3355,7 @@ Trees

    Magritte, l

    We’ll just give another standard example: binary trees.

    -
    import Data.List
    +
    import Data.List
     
     data BinTree a = Empty
                      | Node a (BinTree a) (BinTree a)
    @@ -3392,7 +3560,7 @@ numbers = 0:map
     
     take' n [] = []
     take' 0 l = []
    -take' n (x:xs) = x:take' (n-1) xs
    +take' n (x:xs) = x:take' (n-1) xs
     
     main = print $ take' 10 numbers
    @@ -3410,8 +3578,8 @@ main = print $<

    This code is mostly the same as the previous one.

    -
    import Debug.Trace (trace)
    -import Data.List
    +
    import Debug.Trace (trace)
    +import Data.List
     data BinTree a = Empty 
                      | Node a (BinTree a) (BinTree a) 
                       deriving (Eq,Ord)
    @@ -3468,8 +3636,8 @@ main = print $< treeTakeDepth _ Empty = Empty treeTakeDepth 0 _ = Empty treeTakeDepth n (Node x left right) = let - nl = treeTakeDepth (n-1) left - nr = treeTakeDepth (n-1) right + nl = treeTakeDepth (n-1) left + nr = treeTakeDepth (n-1) right in Node x nl nr
    @@ -3495,8 +3663,8 @@ treeTakeDepth n (Node x left right) =
    iTree = Node 0 (dec iTree) (inc iTree)
             where
    -           dec (Node x l r) = Node (x-1) (dec l) (dec r) 
    -           inc (Node x l r) = Node (x+1) (inc l) (inc r) 
    + dec (Node x l r) = Node (x-1) (dec l) (dec r) + inc (Node x l r) = Node (x+1) (inc l) (inc r)

    Another way to create this tree is to use a higher order function. This function should be similar to map, but should work on BinTree instead of list. Here is such a function:

    @@ -3511,8 +3679,8 @@ treeMap f (Node x left right) =

    Our definition is now:

    infTreeTwo :: BinTree Int
    -infTreeTwo = Node 0 (treeMap (\x -> x-1) infTreeTwo) 
    -                    (treeMap (\x -> x+1) infTreeTwo) 
    +infTreeTwo = Node 0 (treeMap (\x -> x-1) infTreeTwo) + (treeMap (\x -> x+1) infTreeTwo)

    Look at the result for

    main = print $ treeTakeDepth 4 infTreeTwo
    @@ -3629,7 +3797,7 @@ main = do

    Argh! An evil error message and a crash! The first evolution will be to answer with a more friendly message.

    In order to do this, we must detect that something went wrong. Here is one way to do this. Use the type Maybe. It is a very common type in Haskell.

    -
    import Data.Maybe
    +
    import Data.Maybe

    What is this thing? Maybe is a type which takes one parameter. Its definition is:

    data Maybe a = Nothing | Just a
    @@ -3672,7 +3840,7 @@ main = do

    Our next evolution will be to prompt the user again and again until she enters a valid answer.

    We keep the first part:

    -
    import Data.Maybe
    +
    import Data.Maybe
     
     maybeRead :: Read a => String -> Maybe a
     maybeRead s = case reads s of
    @@ -3935,7 +4103,7 @@ main = do
       print $ sum list

    Is translated into:

    -
    import Data.Maybe
    +
    import Data.Maybe
     
     maybeRead :: Read a => String -> Maybe a
     maybeRead s = case reads s of
    @@ -4108,7 +4276,7 @@ The list monad
     

    Golconde de Magritte

    The list monad helps us to simulate non deterministic computations. Here we go:

    -
    import Control.Monad (guard)
    +
    import Control.Monad (guard)
     
     allCases = [1..10]
     
    @@ -4164,7 +4332,7 @@ More on Infinite Tree
     
     

    This code is mostly the same as the one in the tree section.

    -
    import Data.List
    +
    import Data.List
     data BinTree a = Empty 
                      | Node a (BinTree a) (BinTree a) 
                       deriving (Eq,Ord)
    @@ -4225,8 +4393,8 @@ treeFromList (x:xs) = treeTakeDepth _ Empty = Empty
     treeTakeDepth 0 _     = Empty
     treeTakeDepth n (Node x left right) = let
    -          nl = treeTakeDepth (n-1) left
    -          nr = treeTakeDepth (n-1) right
    +          nl = treeTakeDepth (n-1) left
    +          nr = treeTakeDepth (n-1) right
               in
                   Node x nl nr
    @@ -4276,8 +4444,8 @@ treeTakeDepth 4 (treeFromList shuffle)

    This code is mostly the same as the preceding one.

    -
    import Debug.Trace (trace)
    -import Data.List
    +
    import Debug.Trace (trace)
    +import Data.List
     data BinTree a = Empty 
                      | Node a (BinTree a) (BinTree a) 
                       deriving (Eq,Ord)
    @@ -4324,8 +4492,8 @@ treeTakeDepth 4 (treeFromList shuffle) treeTakeDepth _ Empty = Empty treeTakeDepth 0 _ = Empty treeTakeDepth n (Node x left right) = let - nl = treeTakeDepth (n-1) left - nr = treeTakeDepth (n-1) right + nl = treeTakeDepth (n-1) left + nr = treeTakeDepth (n-1) right in Node x nl nr
    @@ -4369,7 +4537,7 @@ safefilter f l = safefilter' f l nbTry safefilter' f (x:xs) n = if f x then x : safefilter' f xs nbTry - else safefilter' f xs (n-1)
    + else safefilter' f xs (n-1)

    Now run the program and be happy:

    @@ -4578,7 +4746,7 @@ static/tmp
  • config/models
  • Obviously:

    -

    config/routes | is where you’ll configure the map %url → Code. |
    Handler/ | contains the files that will contain the code called when a %url is accessed. |
    templates/ | contains html, js and css templates. |
    config/models | is where you’ll configure the persistent objects (database tables). |

    +

    config/routes | is where you’ll configure the map url → Code. |
    Handler/ | contains the files that will contain the code called when a url is accessed. |
    templates/ | contains html, js and css templates. |
    config/models | is where you’ll configure the persistent objects (database tables). |

    During this tutorial we’ll modify other files as well, but we won’t explore them in detail.

    Also note, shell commands are executed in the root directory of your project instead specified otherwise.

    We are now ready to start!

    @@ -4588,7 +4756,7 @@ static/tmp

    Goal:

    Make a server that when accessed /echo/[some text] should return a web page containing “some text” inside an h1 bloc.

    -

    In a first time, we must declare the %url of the form /echo/... are meaningful. Let’s take a look at the file config/routes:

    +

    In a first time, we must declare the url of the form /echo/... are meaningful. Let’s take a look at the file config/routes:

     /static StaticR Static getStatic
     /auth   AuthR   Auth   getAuth
    @@ -4604,7 +4772,7 @@ static/tmp
     /echo/#String EchoR GET
     
    -

    This line contains three elements: the %url pattern, a handler name, an %http method. I am not particularly fan of the big R notation but this is the standard convention.

    +

    This line contains three elements: the url pattern, a handler name, an %http method. I am not particularly fan of the big R notation but this is the standard convention.

    If you save config/routes, you should see your terminal in which you launched yesod devel activate and certainly displaying an error message.

     Application.hs:31:1: Not in scope: `getEchoR'
    @@ -4621,12 +4789,12 @@ getEchoR theText = do
     

    TADA! It works!

    Bulletproof?

    Neo stops a myriad of bullets

    -

    Even this extremely minimal web application has some impressive properties. For exemple, imagine an attacker entering this %url:

    +

    Even this extremely minimal web application has some impressive properties. For exemple, imagine an attacker entering this url:

    [http://localhost:3000/echo/<a>I'm <script>alert("Bad!");](http://localhost:3000/echo/I’m

    " %>

    The special characters are protected for us. A malicious user could not hide some bad script inside.

    -

    This behavior is a direct consequence of type safety. The %url string is put inside a %url type. Then the interesting part in the %url is put inside a String type. To pass from %url type to String type some transformation are made. For example, replace all “%20” by space characters. Then to show the String inside an html document, the string is put inside an html type. Some transformations occurs like replace “<” by “&lt;”. Thanks to yesod, this tedious job is done for us.

    +

    This behavior is a direct consequence of type safety. The url string is put inside a url type. Then the interesting part in the url is put inside a String type. To pass from url type to String type some transformation are made. For example, replace all “%20” by space characters. Then to show the String inside an html document, the string is put inside an html type. Some transformations occurs like replace “<” by “&lt;”. Thanks to yesod, this tedious job is done for us.

    "http://localhost:3000/echo/some%20text<a>" :: URL
                         ↓
                   "some text<a>"                 :: String
    @@ -4671,7 +4839,7 @@ a:visited { col
     

    Generally you don’t want to have all your code inside a unique file. This is why we will separate our handlers. In a first time create a new file Handler/Echo.hs containing:

    module Handler.Echo where
     
    -import Import
    +import Import
     
     getEchoR :: String -> Handler RepHtml
     getEchoR theText = do
    @@ -4684,7 +4852,7 @@ getEchoR theText = do
     

    We must also declare this new Handler module inside Application.hs. Just after the “import Handler.Home”, add:

    -
    import Handler.Echo
    +
    import Handler.Echo

    This is it.

    ps: I am sure not so far in the future we could simply write yesod add-handler Echo to declare it and create a new handler file.

    Data.Text

    @@ -4699,7 +4867,7 @@ getEchoR theText = do

    And do the same in Handler/Echo.hs:

    module Handler.Echo where
     
    -import Import
    +import Import
     
     getEchoR :: Text -> Handler RepHtml
     getEchoR theText = do
    @@ -4725,8 +4893,8 @@ getEchoR theText = do
     

    This time the path /mirror will accept GET and POST requests. Add the corresponding new Handler file:

    module Handler.Mirror where
     
    -import Import
    -import qualified Data.Text as T
    +import Import
    +import qualified Data.Text as T
     
     getMirrorR :: Handler RepHtml
     getMirrorR = do
    @@ -4784,11 +4952,11 @@ Article
         )
     where
     
    -import Import
    -import Data.Monoid
    +import Import
    +import Data.Monoid
     
     -- to use Html into forms
    -import Yesod.Form.Nic (YesodNic, nicHtmlField)
    +import Yesod.Form.Nic (YesodNic, nicHtmlField)
     instance YesodNic App

    Remark: it is a best practice to add the YesodNic instance inside Foundation.hs. I put this definition here to make things easier but you should see a warning about this orphan instance. To put the include inside Foundation.hs is left as an exercice to the reader.

    Hint: Do not forget to put YesodNic and nicHtmlField inside the exported objects of the module.

    @@ -4863,7 +5031,7 @@ getArticleR articleId = do
    <p>A last try to <em>cross script</em> 
        and <em>SQL injection</em></p>
     <p>Here is the first try: 
    -   <script>alert("You loose");</script></p>
    +   <script>alert("You loose");</script></p>
     <p> And Here is the last </p>
     "); DROP TABLE ARTICLE;;

    Conclusion

    @@ -5036,7 +5204,7 @@ getArticleR articleId = do SQL injection by a mom

    SQL injection by a mom

    Lorsque vous créez une application web, beaucoup de temps est passé à s’occuper de chaînes de caractères. Des chaînes de caractère pour les URL, le HTML, le Javascript, les CSS, les requêtes SQL, etc… Pour éviter des utilisation malicieuses vous devez protéger chaque chaîne de caractère entre chaque étape. Par exemple supposons que vous entriez comme nom :

    -
    Newton<script>alert("An apple fall")</script>
    +
    Newton<script>alert("An apple fall")</script>

    Sans une protection correcte, le message “An apple fall” sera affiché à chaque fois que quelqu’un essayera d’accéder au nom de cet utilisateur. Les “types saufs” sont le tonyglandil du web. A chaque chaine de caractère, on lui associe un “type”. A quoi sert cette chaîne de caractère ? Est-ce une URL ? Du javascript ? De l’HTML ? Entre chaque passage d’une représentation à une autre, un transformation is faite par défaut.

    Yesod fait de son mieux pour typer les objets manipulés et ainsi il fera ce qu’il faut pour ne pas mettre du script dans une URL par exemple.

    Go to the other page ~~~~~~

    @@ -5308,11 +5476,11 @@ done
  • Le :t signfie “tail” ; si toto=/path/to/file.ext alors ${toto:t}=file.ext.
  • Après

    -
    gif_to_png() { convert $1 ${1:r}.png && \rm -f $1 }
    +
    gif_to_png() { convert $1 ${1:r}.png && \rm -f $1 }
     
    -handle_resources() { map gif_to_png $1/resources/*.gif(.N) }
    +handle_resources() { map gif_to_png $1/resources/*.gif(.N) }
     
    -map handle_resources /path/to/projects/*(/N)
    +map handle_resources /path/to/projects/*(/N)

    Plus de bloc ! Oui, c’est un poil plus difficile à lire pour les non initiés. Mais c’est à la fois plus concis et plus robuste.

    Et encore ce code ne possède pas de test. Recommençons sur le même principe.

    Trouver les fichiers des projets qui ne contiennent pas de s dans leur nom qui ont le même nom que leur projet.

    @@ -5404,266 +5572,5 @@ function filter { print $result }
    ]]> - - Apprenez Vim Progressivement - - http://yannesposito.com/Scratch/fr/blog/Learn-Vim-Progressively/index.html - 2011-08-25T00:00:00Z - 2011-08-25T00:00:00Z - Über leet use vim!

    -
    - -

    tlpl: Vous désirez apprendre vim (le meilleur editeur de texte connu à ce jour) le plus rapidement possible. Voici mes conseils pour vous aider. Commencez à apprendre le minimum vital, puis apprenez doucement de nouvelles commandes.

    -
    - -

    Vim ou l’éditeur qui vallait 3 milliards :

    -
    -

    Meilleur, plus fort, plus rapide.

    -
    -

    Apprenez vim et ce sera votre dernier éditeur. Aucun éditeur que je connaisse ne le surpasse. Sa prise en mais est difficile, mais payante.

    -

    Je vous conseille de l’apprendre en 4 étapes :

    -
      -
    1. La survie
    2. -
    3. Se sentir à son aise
    4. -
    5. Se sentir meilleur, plus fort et plus rapide
    6. -
    7. Tirer parti des super-pouvoirs de vim
    8. -
    -

    À la fin de ces leçons vous serez transformé.

    -

    Avant de commencer, un message pour vous prévenir. Apprendre vim sera difficile au début. Ça prendra du temps. Vous devrez vous entraîner. Apprendre vim ressemble beaucoup à apprendre un instrument de musique. N’espérez pas être plus efficace avec vim qu’avec un autre éditeur avant au moins trois jours. En fait ça sera certainement plus 2 semaines que 3 jours.

    -

    1er Niveau – Survivre

    -
      -
    1. Installez vim
    2. -
    3. Lancez vim
    4. -
    5. NE TOUCHEZ A RIEN! Lisez
    6. -
    -

    Dans un éditeur normal, il suffit de taper sur une touche du clavier et la lettre s’affiche à l’écran. Pas ici. Vim est en mode Normal. Commençons par placer vim en mode Insert. Tapez sur la touche i.

    -

    Voilà, c’est magique. Vous pouvez tapez comme dans un éditeur standard. Pour repasser en mode Normal tapez sur la touche Echap.

    -

    Maintenant que vous savez passer du mode Normal au mode Insert. Voici les commandes de survie (toutes en mode Normal) :

    -
    -
      -
    • i → Passer en mode insértion. Taper Echap pour repasser en mode Normal.
    • -
    • x → Supprimer le caractère sous le curseur
    • -
    • :wq → Sauvegarder et quitter (:w sauvegarde, :q<enter> quitter)
    • -
    • dd → Supprimer (et copier) la ligne courante
    • -
    • p → Coller
    • -
    -

    Récommandées :

    -
      -
    • hjkl (optionnel) → se déplacer (<-↓↑→). Souvenez vous j ressemble à une flèche vers le bas.
    • -
    • :help <commande> → Affiche l’aide pour <commande>. Vous pouvez aussi écrire :help pour atterir sur l’aide générale.
    • -
    -
    -

    Seulement 5 commandes. Voilà, c’est tout pour un début. Essayez d’éditer vos fichiers comme ça pendant une petite journée. Lorsque ces commandes vous sembleront naturelles, vous pourrez passer à l’étape d’après.

    -

    Mais avant un petit mot sur le mode Normal. Dans un éditeur normal pour copier il faut utiliser une combinaison de touches (Ctrl-c). En fait, lorsque vous appuyez sur la touche Ctrl, c’est un peu comme si toutes les touches du clavier avaient un autre usage. Dans vim, lorsque vous êtes en mode Normal, c’est comme si vous mainteniez Ctrl enfoncé.

    -

    Quelques mots concernant les notations :

    -
      -
    • Au lieu d’écrire Ctrl-λ, j’écrirai <C-λ>.
    • -
    • Les commandes qui commencent par : ont un retour à la ligne implicite à la fin. Par exemple lorsque que j’écris, :q celà signifi qu’il faut taper :, suivi de q, suivi de <Return>.
    • -
    -

    2ème Niveau – Se sentir à son aise

    -

    Vous connaissez les commandes de survie. Passons à des commandes pour être un peu plus à notre aise. Je vous suggère :

    -
      -
    1. Les variantes de l’insertion

      -
      -
        -
      • a → Comme i, mais après la position du curseur.
      • -
      • o → Comme i, mais à la ligne suivante.
      • -
      • O → Comme o mais ajoute la ligne avant.
      • -
      • cw → Remplacer la fin du mot.
      • -
      -
    2. -
    3. Déplacements basiques

      -
      -
        -
      • 0 → Aller à la première colonne.
      • -
      • ^ → Aller au premier caractère de la ligne.
      • -
      • $ → Aller à la fin de la ligne.
      • -
      • g_ → Aller au dernier caractère de la ligne.
      • -
      • /pattern → Rechercher pattern dans le fichier.
      • -
      -
    4. -
    5. Copier/Coller

      -
      -
        -
      • P → Coller avant. Souvenez vous, p colle après la position du curseur.
      • -
      • yy → Copier la ligne courante. C’est plus simple et équivalent à ddP
      • -
      -
    6. -
    7. Annuler/Refaire

      -
      -
        -
      • u → Annuler (undo)
      • -
      • <C-r> → Refaire
      • -
      -
    8. -
    9. Ouvrir/Sauvegarder/Quitter/Changer de fichier (buffer)

      -
      -
        -
      • :e <path/to/file> → Ouvrir.
      • -
      • :w → Sauvegarder.
      • -
      • :saveas <path/to/file> → Sauvegarder sous …
      • -
      • :x, ZZ ou :wq → Sauvegarder et quitter (:x sauvegarde seulement si nécessaire).
      • -
      • :q! → Quitter sans sauvegarder. De même :qa! quitte même si d’autres fichiers (buffers) ont des modifications non sauvegardées.
      • -
      • :bn (resp. :bp) → Affiche le fichier suivant (resp. précédent).
      • -
      -
    10. -
    -

    Prenez le temps de bien intégrer ces commandes. Une fois fait, vous devriez être capable de faire tout ce qu’on peut attendre d’un éditeur de texte classique.

    -

    3ième Niveau – Meilleur. Plus fort. Plus rapide.

    -

    Bravo ! Si vous êtes arrivé jusqu’ici nous allons pouvoir commencer à apprendre les choses vraiment intéressantes. Pour cette section, je vais seulement parler de commandes disponible dans vi et vim. Vim est la contraction de “vi improved”, ou en Français, “vi amélioré”.

    -

    Meilleur

    -

    Voyons comment nous pouvons éviter les répétitions avec vi :

    -
      -
    1. . → Le caractère point répètera la dernière commande. Très utile.
    2. -
    3. N<commande> → répètera la commande N fois.
    4. -
    -

    Quelques exemples, ouvrez un fichier (non vide) avec vim et tapez :

    -
    -
      -
    • 2dd → Supprimera 2 lignes
    • -
    • 3p → copiera 3 fois d’affiler le texte copié
    • -
    • 100idesu [ESC] → écrira “desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu”
    • -
    • . → Juste après la dernière commande réécrira les 100 “desu”.
    • -
    • 3. → Écrira 3 “desu” et non pas 300. Bien vu n’est-ce pas ?
    • -
    -
    -

    Plus fort

    -

    Savoir se déplacer efficacement avec vim est très important. Ne sautez pas cette section.

    -
      -
    1. NG → Aller à la ligne N
    2. -
    3. gg → raccourci pour 1G, retourner au début du fichier
    4. -
    5. G → Aller à la dernière ligne.
    6. -
    7. Déplacement autour des mots:

      -
      -
        -
      1. w → aller au début du mot suivant
      2. -
      3. e → aller à la fin du mot courant
      4. -
      -

      Par défaut les mots sont seulement composés de lettres (et du caractère souligné _). Appelons un MOT un ensemble de lettre séparé par des caractères blancs (espaces, tabulation). Si vous voulez considérer des MOTS alors il suffit d’utiliser les majuscules.

      -
        -
      1. W → aller au début du MOT suivant
      2. -
      3. E → aller à la fin du MOT courant
      4. -
      -

      Word moves example

      -
    8. -
    -

    Passons aux commandes de déplacement les plus efficaces :

    -
    -
      -
    • % : Aller à la parenthèse, accolade, crochet correspondante.
    • -
    • * (resp. #) : Aller à la prochaine (resp. précédente) occurrence du mot sous le curseur
    • -
    -
    -

    Croyez moi, ces trois dernières commandes valent de l’or. Retenez les et vous gagnerez beaucoup de temps.

    -

    Plus rapide

    -

    Vous vous souvenez que j’ai dit que les déplacements étaient très importants en vi. Voilà pourquoi. Une façon de travailler avec vim est de se dire que l’on fait des “phrases”. Le verbe étant la commande et les compléments définissent la zone d’action. De façon générale :

    -

    <position de depart><commande><position d'arrivee>

    -

    Par exemple : 0y$ signifie :

    -
      -
    • 0 → Aller au début de la ligne,
    • -
    • y → copie à partir d’ici,
    • -
    • $ → jusqu’à la fin de cette ligne.
    • -
    -

    On peut donc faire des choses comme ye, copie à partir de la position courante du curseur jusqu’à là fin du mot. Mais aussi: y2/toto copie jusqu’à la seconde prochaine occurrence de “toto”.

    -

    Ce qui est vrai pour y (yank → copier), est aussi vrai pour d (delete → supprimer), v (sélection visuelle), gU (uppercase → majuscule),gu (lowercase → minuscule), etc…

    -

    4ième Niveau – Les super pouvoirs de Vim

    -

    Jusqu’ici vous avez appris les commandes les plus courantes. Mais voici les killer features de vim. Celles que je n’ai retrouvé que dans vim (ou presque).

    -

    Déplacement sur la ligne : 0 ^ $ g_ f F t T , ;

    -
    -
      -
    • 0 → aller à la colonne 0,
    • -
    • ^ → aller au premier caractère de la ligne
    • -
    • $ → aller à la dernière colonne de la ligne
    • -
    • g_ → aller au dernier caractère de la ligne
    • -
    • fa → vous amène à la prochaine occurrence de a sur la ligne courante. , (resp. ;) recherche l’occurrence suivante (resp. précédente).
    • -
    • t, → vous amène juste avant le ,.
    • -
    • 3fa → recherche la 3ième occurrence de a.
    • -
    • F et T → comme f et t mais en arrière. Line moves
    • -
    -
    -

    Un truc pratique : dt" → supprime tout jusqu’au prochain ".

    -

    Selection de zone <action>a<object> ou <action>i<object>

    -

    Ces commandes sont utilisable seulement en mode visuel ou après un “opérateur”. Mais elles sont très puissantes. Leur forme générale est:

    -

    <action>a<objet> et <action>i<objet>

    -

    Où action peut être par exemple d (delete), y (yank), v (select in visual mode), etc… Un objet peut être: w un mot, W un MOT (mot étendu), s une phrase, p un paragraphe. Mais aussi des caractère plus naturels comme ", ', ), }, ].

    -

    Supposons que le curseur soit positionné sur le premier o dans (map (+) ("foo")).

    -
    -
      -
    • vi" → sélectionnera foo.
    • -
    • va" → sélectionnera "foo".
    • -
    • vi) → sélectionnera "foo".
    • -
    • va) → sélectionnera ("foo").
    • -
    • v2i) → sélectionnera map (+) ("foo")
    • -
    • v2a) → sélectionnera (map (+) ("foo"))
    • -
    -
    -

    Text objects selection

    -

    Sélection de blocs rectangulaires : <C-V>.

    -

    Les blocs rectangulaires sont très commodes pour commenter plusieurs lignes de codes. Typiquement: ^<C-V><C-d>I-- [ESC]

    -
      -
    • ^ → aller au premier caractère de la ligne
    • -
    • <C-V> → Commencer la sélection du bloc
    • -
    • <C-d> → se déplacer vers le bas (pourrait être jjj ou % etc…)
    • -
    • I-- [ESC] → écrit -- pour commenter le reste de la ligne.
    • -
    -

    Rectangular blocks

    -

    Remarquez que sous windows, vous devez utiliser <C-q> plutôt que <C-v> si votre “presse papier” n’est pas vide.

    -

    Complétion : <C-n> et <C-p>.

    -

    En mode Insert, commencez à écrire le début d’un mot déjà présent dans l’un des buffers (fichers) ouvert et tapes <C-p>. Magique. Completion

    -

    Macros : qa faire quelque chose q, @a, @@

    -

    qa enregistre tout ce que vous faite et enregistre le tout dans le registre a. Ensuite @a va rejouer la macro enregistrée dans le registre a comme si c’est vous qui tapiez au clavier. @@ est un raccourci pour rejouer la dernière macro exécutée.

    -
    -

    Exemple : Sur une ligne contenant seulement un 1 tapez :

    -
      -
    • qaYp<C-a>q

    • -
    • qa → début de l’enregistrement.
    • -
    • Yp → copier cette ligne.
    • -
    • <C-a> → incrémente le nombre.
    • -
    • q → arrête d’enregistrer.

    • -
    • @a → écrit un 2 sous le 1.
    • -
    • Écrivez 100@@. Cela va créer une liste de nombre croissants jusqu’à 103.

    • -
    -
    -

    Macros

    -

    Sélection visuelle : v,V,<C-v>

    -

    On a déjà vu un exemple avec <C-V>. Mais il y a aussi, v et V. Et une fois la sélection visuelle faite vous pouvez par exemple:

    -
      -
    • J → joindre toutes les lignes pour en faire une seule
    • -
    • < (resp. >) → indenter à gauche (resp. à droite).
    • -
    • = → auto indenter
    • -
    -

    Autoindent

    -

    Ajouter quelque chose à la fin de toutes les lignes sélectionnées visuellement :

    -
      -
    • <C-v>
    • -
    • aller jusqu’à la ligne désirée (jjj ou <C-d> ou /pattern ou % etc…)
    • -
    • $ aller à la fin
    • -
    • A, écrire le texte, Echap.
    • -
    -

    Ajouter à la fin de plusieurs lignes

    -

    Splits : :split et vsplit.

    -

    Je vous conseille de faire un :help split. Celà permet de manipuler plusieurs buffer sur la même fenêtre. Voici les commandes principales :

    -
    -
      -
    • :split → crée un split (:vsplit crée un split vertical)
    • -
    • <C-w><dir> → où dir est l’un de hjkl ou ←↓↑→ permet de changer de split.
    • -
    • <C-w>_ (resp. <C-w>|) → Maximise la taille du split (resp. split vertical)
    • -
    • <C-w>+ (resp. <C-w>-) → Agrandi (resp. diminue) le split
    • -
    -
    -

    Split

    -

    Conclusion

    -

    Voilà, je vous ai donné 90% des commandes que j’utilise tous les jours. N’essayez pas de toutes les apprendre en une journée. Il faut le temps de s’habituer à chaque nouvelle commande. Je vous conseille de ne pas apprendre plus d’une ou deux commandes par jour.

    -

    Apprendre Vim est plus une question d’entraînement que de mémorisation. Heureusement vim est founi avec un très bon tutoriel et une excellente documentation. Lancez vimtutor jusqu’à ce que vous vous sentiez à l’aise avec les commandes basiques. De plus, vous devriez aussi lire en détail la page suivate : :help usr_02.txt.

    -

    Ensuite vous découvrirez !, les folds, les registres, les plugins et tout un tas d’autres choses. Apprenez vim comme vous apprendriez le piano et vous devriez très bien vous en sortir.

    - - -]]>
    - diff --git a/Scratch/fr/blog/index.html b/Scratch/fr/blog/index.html index a82f3f7..20b36f6 100644 --- a/Scratch/fr/blog/index.html +++ b/Scratch/fr/blog/index.html @@ -103,6 +103,9 @@ Learn Haskell Fast and Hard »
    -
    @@ -49,7 +41,7 @@

    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.

    @@ -69,25 +61,26 @@
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -105,6 +98,7 @@ comments powered by Disqus
    +
    Published on 2009-07-06 diff --git a/Scratch/fr/blog/programming-language-experience/index.html b/Scratch/fr/blog/programming-language-experience/index.html index 9d8e24e..06c803e 100644 --- a/Scratch/fr/blog/programming-language-experience/index.html +++ b/Scratch/fr/blog/programming-language-experience/index.html @@ -33,16 +33,8 @@ document.write(''); // +
    -
    -
    @@ -50,7 +42,7 @@

    Mon expérience avec les languages de programmation

    -
    +

    Title image

    @@ -199,25 +191,26 @@ X=whatever[C,D]
    - - RSS - - - - - - -
    - -
    -
    + + · + + · + + · + +
    + Ces liens sociaux préservent votre vie privée
    + +

    Comments

    @@ -235,6 +228,7 @@ X=whatever[C,D]
    comments powered by Disqus
    +
    Published on 2011-09-28 diff --git a/Scratch/img/blog/Social-link-the-right-way/main.png b/Scratch/img/blog/Social-link-the-right-way/main.png new file mode 100644 index 0000000..0fb5549 Binary files /dev/null and b/Scratch/img/blog/Social-link-the-right-way/main.png differ diff --git a/Scratch/js/index.js b/Scratch/js/index.js index eabb7e4..7d0df72 100644 --- a/Scratch/js/index.js +++ b/Scratch/js/index.js @@ -112,11 +112,23 @@ function switchcss() { }); } +function animatedToTop() { + $('#totop a').click(function(){ + $('body,html').animate({scrollTop:0},800);}); +} +function animatedToMenu() { + $('.tomenu a').click(function(){ + $('body,html').animate({ + scrollTop: $('#navigation').offset().top - ($(window).height()/2)},800);}); +} + // Ce que l'on va lancer à l'init. $(document).ready(function() { var client=detectClient(); if ( ! /msie/.test(client) ) { initCode(); } $('#blackpage').fadeOut('slow',function(){ $('#blackpage').remove(); }); + animatedToTop(); + animatedToMenu(); analytics(); switchcss(); }); diff --git a/YBlog/YPassword_files/YPassword-1.6.zip b/YBlog/YPassword_files/YPassword-1.6.zip new file mode 100644 index 0000000..769002d Binary files /dev/null and b/YBlog/YPassword_files/YPassword-1.6.zip differ diff --git a/YBlog/YPassword_files/forcePaste.app.zip b/YBlog/YPassword_files/forcePaste.app.zip new file mode 100644 index 0000000..8cd3cc3 Binary files /dev/null and b/YBlog/YPassword_files/forcePaste.app.zip differ diff --git a/YPassword/index.html b/YPassword/index.html new file mode 100644 index 0000000..033f94b --- /dev/null +++ b/YPassword/index.html @@ -0,0 +1,28 @@ + + + Redirect to the right page. + + + + +

    You should be redirected to http://ypassword.espozito.com

    + + diff --git a/index.html b/index.html index 881cd3e..6d81b93 100644 --- a/index.html +++ b/index.html @@ -41,14 +41,14 @@ - + + Social link the right way » +
    + Category Theory Presentation »
    Haskell Progressive Example » -
    - - Learn Haskell Fast and Hard »
    @@ -64,14 +64,14 @@ - + + Être correct avec les boutons share » +
    + Category Theory Presentation »
    Un example progressif avec Haskell » -
    - - Haskell comme un vrai! »