<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>In the rabbit hole</title><link href="https://hole.tuziwo.info/" rel="alternate"></link><link href="https://hole.tuziwo.info/feeds/all.atom.xml" rel="self"></link><id>https://hole.tuziwo.info/</id><updated>2023-06-30T00:00:00+02:00</updated><entry><title>Don’t be lazy</title><link href="https://hole.tuziwo.info/don-t-be-lazy.html" rel="alternate"></link><published>2023-06-30T00:00:00+02:00</published><updated>2023-06-30T00:00:00+02:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2023-06-30:/don-t-be-lazy.html</id><summary type="html">&lt;div class="paragraph"&gt;
&lt;p&gt;I consider lazyness a quality for developers. Let me&amp;nbsp;explain.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;If I do something twice, there is a good chance I&amp;#8217;m going to need to do it a
third time. Therefore, I want to help my future self to not do it a third time,
to be &lt;strong&gt;lazy&lt;/strong&gt; by …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="paragraph"&gt;
&lt;p&gt;I consider lazyness a quality for developers. Let me&amp;nbsp;explain.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;If I do something twice, there is a good chance I&amp;#8217;m going to need to do it a
third time. Therefore, I want to help my future self to not do it a third time,
to be &lt;strong&gt;lazy&lt;/strong&gt; by avoiding future&amp;nbsp;work.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This precept can take different flavors. For example, I can factorize a common
functionality into a function, or into a script. Or maybe this is something that
can be automated: doing a release, deploying,&amp;nbsp;testing.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;But if you take a close look, it&amp;#8217;s not exactly lazyness, because you need to
engage more work now, to save some work later. It&amp;#8217;s a tradeoff. And like with
any tradeoff, you might first want to&amp;nbsp;evaluate:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;how much time will it take to factorize or automate&amp;nbsp;it?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;how probable the situation is going to happen in the&amp;nbsp;future?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Let&amp;#8217;s make a truth table out of&amp;nbsp;it.&lt;/p&gt;
&lt;/div&gt;
&lt;table class="tableblock frame-all grid-all stretch"&gt;
&lt;colgroup&gt;
&lt;col style="width: 7.6923%;"&gt;
&lt;col style="width: 30.7692%;"&gt;
&lt;col style="width: 30.7692%;"&gt;
&lt;col style="width: 30.7693%;"&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th class="tableblock halign-left valign-top"&gt;#&lt;/th&gt;
&lt;th class="tableblock halign-left valign-top"&gt;Time to Factorize/Automate&lt;/th&gt;
&lt;th class="tableblock halign-left valign-top"&gt;Probability of happening again&lt;/th&gt;
&lt;th class="tableblock halign-left valign-top"&gt;Spend the time?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class="tableblock halign-left valign-top"&gt;&lt;p class="tableblock"&gt;1&lt;/p&gt;&lt;/td&gt;
&lt;td class="tableblock halign-left valign-top"&gt;&lt;p class="tableblock"&gt;Long&lt;/p&gt;&lt;/td&gt;
&lt;td class="tableblock halign-left valign-top"&gt;&lt;p class="tableblock"&gt;Low&lt;/p&gt;&lt;/td&gt;
&lt;td class="tableblock halign-left valign-top"&gt;&lt;p class="tableblock"&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="tableblock halign-left valign-top"&gt;&lt;p class="tableblock"&gt;2&lt;/p&gt;&lt;/td&gt;
&lt;td class="tableblock halign-left valign-top"&gt;&lt;p class="tableblock"&gt;Short&lt;/p&gt;&lt;/td&gt;
&lt;td class="tableblock halign-left valign-top"&gt;&lt;p class="tableblock"&gt;High&lt;/p&gt;&lt;/td&gt;
&lt;td class="tableblock halign-left valign-top"&gt;&lt;p class="tableblock"&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="tableblock halign-left valign-top"&gt;&lt;p class="tableblock"&gt;3&lt;/p&gt;&lt;/td&gt;
&lt;td class="tableblock halign-left valign-top"&gt;&lt;p class="tableblock"&gt;Long&lt;/p&gt;&lt;/td&gt;
&lt;td class="tableblock halign-left valign-top"&gt;&lt;p class="tableblock"&gt;High&lt;/p&gt;&lt;/td&gt;
&lt;td class="tableblock halign-left valign-top"&gt;&lt;p class="tableblock"&gt;🤷&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="tableblock halign-left valign-top"&gt;&lt;p class="tableblock"&gt;4&lt;/p&gt;&lt;/td&gt;
&lt;td class="tableblock halign-left valign-top"&gt;&lt;p class="tableblock"&gt;Short&lt;/p&gt;&lt;/td&gt;
&lt;td class="tableblock halign-left valign-top"&gt;&lt;p class="tableblock"&gt;Low&lt;/p&gt;&lt;/td&gt;
&lt;td class="tableblock halign-left valign-top"&gt;&lt;p class="tableblock"&gt;🤷&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;And today, I&amp;#8217;d like to talk about something clearly in the category 2 and yet,
too often, people don&amp;#8217;t spend the&amp;nbsp;time.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Let&amp;#8217;s take an example to illustrate. Let&amp;#8217;s say I&amp;#8217;m writing a script. At some
point in the script, there is the following &lt;code&gt;sed&lt;/code&gt; command.&lt;sup class="footnote"&gt;[&lt;a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote."&gt;1&lt;/a&gt;]&lt;/sup&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="sh"&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-niE&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; 80 &lt;span class="s1"&gt;'s/Referer/Referrer/g'&lt;/span&gt; request.http&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;What do you think &lt;code&gt;-niE&lt;/code&gt; and &lt;code&gt;-l&lt;/code&gt; does? You don&amp;#8217;t know? Well this is a problem
because you&amp;#8217;re not the only one who is going to read that piece of code. Since
there is much more people who are going to read that code, than to write it,
making it readable should be a priority over&amp;nbsp;conciseness.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now, how about that&amp;nbsp;version?&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="sh"&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;--silent&lt;/span&gt; &lt;span class="nt"&gt;--in-place&lt;/span&gt; &lt;span class="nt"&gt;--regexp-extend&lt;/span&gt; &lt;span class="nt"&gt;--line-length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;80 &lt;span class="s1"&gt;'s/Referer/Referrer/g'&lt;/span&gt; request.http&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;It&amp;#8217;s much better. Not perfect, but much better. You&amp;#8217;re going to spend much less
time (or no time?) in the documentation trying to understand what each of the
option&amp;nbsp;means.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;So, dear developers, &lt;strong&gt;please&lt;/strong&gt;, &lt;strong&gt;pretty please&lt;/strong&gt;, in scripts, always choose
the long version for options. It&amp;#8217;s going to save a lot of time to the future
readers of the code, including you.&amp;nbsp;😉&lt;/p&gt;
&lt;/div&gt;
&lt;div id="footnotes"&gt;
&lt;hr&gt;
&lt;div class="footnote" id="_footnotedef_1"&gt;
&lt;a href="#_footnoteref_1"&gt;1&lt;/a&gt;. Wondering about this typo? Take a look &lt;a href="https://developer.mozilla.org/fr/docs/Web/HTTP/Headers/Referrer-Policy#sect1"&gt;here&lt;/a&gt;.
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="best-practice"></category></entry><entry><title>Make it look like rainbows 🌈</title><link href="https://hole.tuziwo.info/make-it-look-like-rainbows.html" rel="alternate"></link><published>2022-02-22T00:00:00+01:00</published><updated>2022-02-22T00:00:00+01:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2022-02-22:/make-it-look-like-rainbows.html</id><summary type="html">&lt;div id="preamble"&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This post is part of an ongoing series about tests in&amp;nbsp;Rust:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="olist arabic"&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./rust-testing-ecosystem.html"&gt;Rust testing&amp;nbsp;ecosystem&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./fluent-assertions-for-numbers-in-rust.html"&gt;Fluent assertions for numbers in&amp;nbsp;Rust&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./equality-assertions.html"&gt;Equality&amp;nbsp;assertions&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./assertion-reporting.html"&gt;Assertion&amp;nbsp;reporting&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Make it look like rainbows&amp;nbsp;🌈&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_what_can_we_do_to_improve_the_reporting"&gt;What can we do to improve the&amp;nbsp;reporting?&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In the &lt;a href="./assertion-reporting.html"&gt;previous post&lt;/a&gt;, we ended up with the
following report when …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div id="preamble"&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This post is part of an ongoing series about tests in&amp;nbsp;Rust:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="olist arabic"&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./rust-testing-ecosystem.html"&gt;Rust testing&amp;nbsp;ecosystem&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./fluent-assertions-for-numbers-in-rust.html"&gt;Fluent assertions for numbers in&amp;nbsp;Rust&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./equality-assertions.html"&gt;Equality&amp;nbsp;assertions&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./assertion-reporting.html"&gt;Assertion&amp;nbsp;reporting&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Make it look like rainbows&amp;nbsp;🌈&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_what_can_we_do_to_improve_the_reporting"&gt;What can we do to improve the&amp;nbsp;reporting?&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In the &lt;a href="./assertion-reporting.html"&gt;previous post&lt;/a&gt;, we ended up with the
following report when running&amp;nbsp;tests.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="txt"&gt;stderr:
thread 'main' panicked at '
runit-assertions/src/lib.rs:66
    ✓ should be not equal to `0`, was `42`
    ⨯ should be not equal to `42`, was `42`
'&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This is already nice but can we improve on that? First of all, it be real nice
to color it. How about we use red/green colors to quickly identify which tests&amp;nbsp;failed?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_colors_in_the_terminal"&gt;Colors in the&amp;nbsp;terminal&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To display colors in the terminal, I searched for a crate with the keyword
&lt;strong&gt;color&lt;/strong&gt; in crates.io
(see &lt;a href="https://crates.io/search?q=color&amp;amp;sort=downloads"&gt;link&lt;/a&gt;).
&lt;sup class="footnote"&gt;[&lt;a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote."&gt;1&lt;/a&gt;]&lt;/sup&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;A few of them showed up and all are done by known people &lt;sup class="footnote"&gt;[&lt;a id="_footnoteref_2" class="footnote" href="#_footnotedef_2" title="View footnote."&gt;2&lt;/a&gt;]&lt;/sup&gt; in the&amp;nbsp;community:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://crates.io/crates/ansi_term"&gt;&lt;code&gt;ansi_term&lt;/code&gt;&lt;/a&gt; by
&lt;a href="https://crates.io/users/joshtriplett"&gt;Josh Triplett&lt;/a&gt; (owner on
&lt;a href="https://crates.io/crates/cargo"&gt;&lt;code&gt;cargo&lt;/code&gt;&lt;/a&gt;) and
&lt;a href="https://crates.io/users/ogham"&gt;Benjamin Sago&lt;/a&gt; (author of
&lt;a href="https://crates.io/crates/exa"&gt;&lt;code&gt;exa&lt;/code&gt;&lt;/a&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://crates.io/crates/termcolor"&gt;&lt;code&gt;termcolor&lt;/code&gt;&lt;/a&gt; by
&lt;a href="https://crates.io/users/BurntSushi"&gt;Andrew Gallant&lt;/a&gt; also know as
&lt;a href="https://github.com/BurntSushi"&gt;&lt;code&gt;BurntSushi&lt;/code&gt;&lt;/a&gt; (prolific author of at least
&lt;a href="https://crates.io/crates/regex"&gt;&lt;code&gt;regex&lt;/code&gt;&lt;/a&gt;,
&lt;a href="https://crates.io/crates/csv"&gt;&lt;code&gt;csv&lt;/code&gt;&lt;/a&gt;,
&lt;a href="https://crates.io/crates/ripgrep"&gt;&lt;code&gt;ripgrep&lt;/code&gt;&lt;/a&gt; to name only a&amp;nbsp;few)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://crates.io/crates/term"&gt;&lt;code&gt;term&lt;/code&gt;&lt;/a&gt; by
&lt;a href="https://crates.io/users/alexcrichton"&gt;Alex Crichton&lt;/a&gt; (owner on
&lt;a href="https://crates.io/crates/cargo"&gt;&lt;code&gt;cargo&lt;/code&gt;&lt;/a&gt;),
&lt;a href="https://crates.io/users/huonw"&gt;Huon Wilson&lt;/a&gt; and
&lt;a href="https://crates.io/users/Stebalien"&gt;Steven&amp;nbsp;Allen&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://crates.io/crates/console"&gt;&lt;code&gt;console&lt;/code&gt;&lt;/a&gt; by
&lt;a href="https://crates.io/users/mitsuhiko"&gt;Armin Ronacher&lt;/a&gt; (which I&amp;#8217;ve known
through &lt;a href="https://crates.io/crates/cargo-insta"&gt;&lt;code&gt;cargo-insta&lt;/code&gt;&lt;/a&gt;) and
&lt;a href="https://crates.io/users/pksunkara"&gt;Pavan Kumar&amp;nbsp;Sunkara&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Ok, that is a lot of dropped names but that is also a way for me to thank them.
I&amp;#8217;ve known by name most of them, interacted with some of them. But for sure,
all of them brought a lot to the Rust ecosystem: thank&amp;nbsp;you.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now, which one to choose? To be honest, I&amp;#8217;ve picked the most downloaded one:
&lt;code&gt;ansi_term&lt;/code&gt;. It&amp;#8217;s not the most recently updated (&lt;code&gt;ansi_term&lt;/code&gt;: 2 years,
&lt;code&gt;termcolor&lt;/code&gt;: 1 year, &lt;code&gt;term&lt;/code&gt;: 1 year, &lt;code&gt;console&lt;/code&gt;: 4 months) but it is the most
downloaded one by about 15 millions. In any case, it should not be to
difficult to change for another one if that was necessary so I&amp;#8217;m not spending
too much time thinking about&amp;nbsp;it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Additional note, most of these libraries basically brings colors but also bold,
underlined and a few other stylish&amp;nbsp;stuff.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_lets_make_it_green_and_red"&gt;Let&amp;#8217;s make it green and&amp;nbsp;red&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;First of all, I&amp;#8217;m not gonna get through code here because it&amp;#8217;s not really
interesting. The only technical part worth mentioning is that I&amp;#8217;ve made
&lt;code&gt;ansi_term&lt;/code&gt; an &lt;code&gt;optional&lt;/code&gt; dependency, although part of the default features.
This means that I want colored output to be part of the default provided
behavior of &lt;code&gt;runit&lt;/code&gt;&amp;#8230;&amp;#8203; but people should be able to suppress that if they
believe it&amp;#8217;s just fancy and add too much to the building time (even if it&amp;#8217;s
probably going to be test&amp;nbsp;building).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_first_iteration"&gt;First&amp;nbsp;iteration&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Very simple start. How about&amp;nbsp;this?&lt;/p&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="images/colored-emoji.png" alt="Colored Emoji and bold location" height="80"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Some colored checkmarks or crosses with a flashy green and red color. On top of
that, some bold fonts for the location. Pretty good already, right? We can do&amp;nbsp;more.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_second_iteration"&gt;Second&amp;nbsp;iteration&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;How about we highlight more the failed tests and make the passed tests a bit
more&amp;nbsp;discrete.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="images/colored-lines.png" alt="Colored background lines with red/green for failed/pass tests" height="80"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now, the entire background&amp;#8217;s line is colored. The failed tests are more flashy
with bold, whereas the passed tests use a more pastel color with normal&amp;nbsp;font.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Can we do more? Let&amp;#8217;s&amp;nbsp;try!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_third_iteration"&gt;Third&amp;nbsp;iteration&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The inspiration for this third iteration is purely inherited from
&lt;a href="https://crates.io/crates/pretty_assertions"&gt;&lt;code&gt;pretty_assertions&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="images/colored-diff.png" alt="Colored diff of the compared values" height="144"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;First of all, compared values are aligned to ease the comparison. I also used
a diffing algorithm thanks to
&lt;a href="https://crates.io/crates/dissimilar"&gt;&lt;code&gt;dissimilar&lt;/code&gt;&lt;/a&gt; to precisely show the
difference between the strings. I you&amp;#8217;re interested in the details of how
complex that nice feature was to implement, it&amp;#8217;s only about
&lt;a href="https://gitlab.com/woshilapin/runit/-/blob/667dd1f158364a9532fb8d3862ec194b73c3ff7b/runit-assertions/src/lib.rs#L43-70"&gt;27 lines of code&lt;/a&gt;.
&lt;code&gt;dissimilar&lt;/code&gt; is really pulling all the hard work for&amp;nbsp;us.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Since the output is now on 2 lines, I&amp;#8217;ve underlined some lines to create a
separation between each&amp;nbsp;assertion.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I like this last rendering&amp;#8230;&amp;#8203; although, there is a bunch of problems with&amp;nbsp;it.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_problems_to_address_later"&gt;Problems to address&amp;nbsp;later&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;When I worked on these features, I worked head-on on the coloring improvement.
Now that it&amp;#8217;s done, I can take a step back and think a bit. So far, I&amp;#8217;ve been
exploring the rendering of only &lt;code&gt;is_equal_to&lt;/code&gt; (and its friend
&lt;code&gt;is_not_equal_to&lt;/code&gt;). But the plan always was to expand to more&amp;nbsp;assertions.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;What good is going to be a diff output for something like &lt;code&gt;is_greater_than&lt;/code&gt;?
Yeah, you&amp;#8217;re right, it doesn&amp;#8217;t make any&amp;nbsp;sense.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;How about if we start using regular expression and have a &lt;code&gt;matches&lt;/code&gt; assertion?&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Or asserting on a map with &lt;code&gt;has_key&lt;/code&gt; or &lt;code&gt;contains&lt;/code&gt;?&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;And I&amp;#8217;m sure I could find thousands of these little examples where a diff would
not make any sense. It feel like a diff is only useful when comparing for
equality which is exactly what &lt;code&gt;PartialEq&lt;/code&gt; is&amp;nbsp;about.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Let&amp;#8217;s pin these and we&amp;#8217;ll try to address them on a later post. One thing that
seems to emerge is that the reporting is tightly coupled with the assertion.
In term of code architecture, it probably means that the current version, that
you can find on
&lt;a href="https://gitlab.com/woshilapin/runit/-/tree/667dd1f158364a9532fb8d3862ec194b73c3ff7b"&gt;&lt;code&gt;woshilapin/runit&lt;/code&gt;&lt;/a&gt;,
is not well-suited for what&amp;#8217;s&amp;nbsp;coming.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="footnotes"&gt;
&lt;hr&gt;
&lt;div class="footnote" id="_footnotedef_1"&gt;
&lt;a href="#_footnoteref_1"&gt;1&lt;/a&gt;. Pretty original ugh!
&lt;/div&gt;
&lt;div class="footnote" id="_footnotedef_2"&gt;
&lt;a href="#_footnoteref_2"&gt;2&lt;/a&gt;. I can even say famous for some of them.
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="rust"></category><category term="test"></category><category term="runit"></category></entry><entry><title>Assertion reporting</title><link href="https://hole.tuziwo.info/assertion-reporting.html" rel="alternate"></link><published>2022-02-16T00:00:00+01:00</published><updated>2022-02-16T00:00:00+01:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2022-02-16:/assertion-reporting.html</id><summary type="html">&lt;div id="preamble"&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This post is part of an ongoing series about tests in&amp;nbsp;Rust:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="olist arabic"&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./rust-testing-ecosystem.html"&gt;Rust testing&amp;nbsp;ecosystem&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./fluent-assertions-for-numbers-in-rust.html"&gt;Fluent assertions for numbers in&amp;nbsp;Rust&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./equality-assertions.html"&gt;Equality&amp;nbsp;assertions&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Assertion&amp;nbsp;reporting&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./make-it-look-like-rainbows.html"&gt;Make it look like rainbows&amp;nbsp;🌈&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_little_recap"&gt;Little&amp;nbsp;recap&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In the last post, we basically designed &lt;code&gt;Assertion&lt;/code&gt; so we would use it like&amp;nbsp;this.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;some_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String …&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div id="preamble"&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This post is part of an ongoing series about tests in&amp;nbsp;Rust:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="olist arabic"&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./rust-testing-ecosystem.html"&gt;Rust testing&amp;nbsp;ecosystem&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./fluent-assertions-for-numbers-in-rust.html"&gt;Fluent assertions for numbers in&amp;nbsp;Rust&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./equality-assertions.html"&gt;Equality&amp;nbsp;assertions&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Assertion&amp;nbsp;reporting&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./make-it-look-like-rainbows.html"&gt;Make it look like rainbows&amp;nbsp;🌈&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_little_recap"&gt;Little&amp;nbsp;recap&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In the last post, we basically designed &lt;code&gt;Assertion&lt;/code&gt; so we would use it like&amp;nbsp;this.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;some_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nn"&gt;Assertion&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;some_value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foobar"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;or, since we provided a short macro for building &lt;code&gt;Assertion&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;some_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nd"&gt;assert_that!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some_value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foobar"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;And remember, we can chain assertions too. For example, let&amp;#8217;s say we know our
function &lt;code&gt;life()&lt;/code&gt; should never return &lt;code&gt;0&lt;/code&gt; nor &lt;code&gt;42&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;life&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;life&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nd"&gt;assert_that!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;life&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.is_not_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.is_not_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;So far, the actual assertion will panic if one of the condition is not met. But
since we&amp;#8217;re chaining assertions, it might actually be useful to know the
results for the entire chain instead of failing on the first incorrect&amp;nbsp;one.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_storing_the_results"&gt;Storing the&amp;nbsp;results&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This should actually be pretty easy to store all the results since we&amp;#8217;re having
the &lt;code&gt;Assertion&lt;/code&gt; object all along. We can stick a &lt;code&gt;Vec&lt;/code&gt; into &lt;code&gt;Assertion&lt;/code&gt;. This
&lt;code&gt;Vec&lt;/code&gt; will contain a &lt;code&gt;Report&lt;/code&gt; that needs a few&amp;nbsp;information:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;did the assertion&amp;nbsp;pass?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;what was the test (so we can report to the&amp;nbsp;end-user)?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;what was the tested&amp;nbsp;value?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;what was the compared&amp;nbsp;value?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="nd"&gt;#[derive(Debug)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Report&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;compared&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[derive(Debug)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Assertion&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt;
    &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'v&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;reports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Report&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We can now implement &lt;code&gt;is_equal_to()&lt;/code&gt; as&amp;nbsp;follows.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;is_equal_to&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;compared&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt;
    &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;PartialEq&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'v&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;pass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="nf"&gt;.eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;compared&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;reporter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Report&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"be equal to"&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;compared&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;compared&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.reports&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reporter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;self&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;There is a few things going on. First of all, we changed the signature of the
function &lt;code&gt;is_equal_to&lt;/code&gt; so it now takes ownership of &lt;code&gt;self&lt;/code&gt;. This will allow us
to mutate it.&lt;sup class="footnote"&gt;[&lt;a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote."&gt;1&lt;/a&gt;]&lt;/sup&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We also transformed &lt;code&gt;value&lt;/code&gt; and &lt;code&gt;compared&lt;/code&gt; into their &lt;code&gt;Debug&lt;/code&gt; formatted&amp;nbsp;string.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;And know, we can try to run the following to see how it&amp;nbsp;goes.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;life&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;life&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nd"&gt;assert_that!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;life&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_not_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;And it passes. Great! Hmm, just to be sure, does this&amp;nbsp;fails?&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;life&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nd"&gt;assert_that!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;life&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_not_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;What, it pass too? Something is wrong. And indeed, remember how we had the
following in &lt;code&gt;is_equal_to()&lt;/code&gt; implementation before&amp;#8230;&amp;#8203; but we do not have it&amp;nbsp;anymore!&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This is the line that made the test panic or not, and therefore the test pass
or&amp;nbsp;fail.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_failing_again"&gt;Failing&amp;nbsp;again&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;&lt;sup class="footnote"&gt;[&lt;a id="_footnoteref_2" class="footnote" href="#_footnotedef_2" title="View footnote."&gt;2&lt;/a&gt;]&lt;/sup&gt; Where do we insert the &lt;code&gt;assert!()&lt;/code&gt; back into our
code? We cannot put it in &lt;code&gt;is_equal_to&lt;/code&gt; nor &lt;code&gt;is_not_equal_to&lt;/code&gt; as this would
defeat the purpose of not failing early. However, there is one piece of code
that is always executed when a object goes out of scope:
&lt;a href="https://doc.rust-lang.org/std/ops/trait.Drop.html"&gt;&lt;code&gt;Drop&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Let&amp;#8217;s try&amp;nbsp;it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;ops&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Drop&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Assertion&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt;
    &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;nb_fails&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.reports&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.filter&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="py"&gt;.pass&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.count&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.reports&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.fold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;emoji&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="py"&gt;.pass&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="sc"&gt;'✓'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="sc"&gt;'⨯'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
            &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;{} should be {} `{}`, was `{}`&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;emoji&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="py"&gt;.condition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="py"&gt;.compared&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="py"&gt;.value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nb_fails&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Does it work? Let try back the following&amp;nbsp;code.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;life&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nd"&gt;assert_that!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;life&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_not_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Here the output result. It does&amp;nbsp;work!&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="txt"&gt;stderr:
thread 'main' panicked at '
    ⨯ should not be equal to `42`, was `42`
'&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_more_information_in_the_report"&gt;More information in the&amp;nbsp;report&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We can add a little more useful information about where the assertion failed
thanks to the &lt;a href="https://doc.rust-lang.org/std/macro.file.html"&gt;&lt;code&gt;file!()&lt;/code&gt;&lt;/a&gt; and
&lt;a href="https://doc.rust-lang.org/std/macro.line.html"&gt;&lt;code&gt;line!()&lt;/code&gt;&lt;/a&gt;&amp;nbsp;macros.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Let&amp;#8217;s make these modifications to &lt;code&gt;Assertion&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="nd"&gt;#[derive(Debug)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Location&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[derive(Debug)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Assertion&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt;
    &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'v&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;reports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Report&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;From&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'v&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Assertion&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt;
    &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;'v&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'v&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Assertion&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;reports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;Vec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Assertion&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt;
    &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;'v&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;with_location&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Location&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="nf"&gt;.to_owned&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Note that &lt;code&gt;file!()&lt;/code&gt; and especially &lt;code&gt;line!()&lt;/code&gt; must be invoked at the exact place
where the &lt;code&gt;Assertion&lt;/code&gt; is built. If we stick them in the implementation of
&lt;code&gt;From&lt;/code&gt; above, this would not work because it would be expanded to our library
file and line, not the one of the end-users. Once again, we need to rely on
macros which will be expanded on-site and give use the correct result. Let&amp;#8217;s
modify &lt;code&gt;assert_that&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="nd"&gt;#[macro_export]&lt;/span&gt;
&lt;span class="nd"&gt;macro_rules!&lt;/span&gt; &lt;span class="n"&gt;assert_that&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value:expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt;
        &lt;span class="nn"&gt;runit_assertions&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Assertion&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="nf"&gt;.with_location&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;file!&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nd"&gt;line!&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;}};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now, we can modify the &lt;code&gt;Drop&lt;/code&gt; implementation like&amp;nbsp;this.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;ops&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Drop&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Assertion&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt;
    &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;fails&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.reports&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.filter&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="py"&gt;.pass&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.count&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.location&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;{}:{}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="py"&gt;.file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="py"&gt;.line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.reports&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.fold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;emoji&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="py"&gt;.pass&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="sc"&gt;'✓'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="sc"&gt;'⨯'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
            &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;{} should be {} `{}`, was `{}`&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;emoji&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="py"&gt;.condition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="py"&gt;.compared&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="py"&gt;.value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fails&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Let run some tests&amp;nbsp;again.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;life&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nd"&gt;assert_that!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;life&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.is_not_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.is_not_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The output now looks like&amp;nbsp;this.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="txt"&gt;stderr:
thread 'main' panicked at '
runit-assertions/src/lib.rs:66
    ✓ should be not equal to `0`, was `42`
    ⨯ should be not equal to `42`, was `42`
'&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_some_notes"&gt;Some&amp;nbsp;notes&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I found out this little exercises pretty cool. Especially the need trick
about displaying the file and line. There is however and drawback with this
feature: it will not work for RustDoc, or at least, the line number will be
wrong. Test it, you&amp;#8217;ll&amp;nbsp;see!&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Again, you can browse the current implementation in
&lt;a href="https://gitlab.com/woshilapin/runit/-/tree/d284e7075f2d93e79eeae0b585e6c36616b5c82c"&gt;&lt;code&gt;woshilapin/runit&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="footnotes"&gt;
&lt;hr&gt;
&lt;div class="footnote" id="_footnotedef_1"&gt;
&lt;a href="#_footnoteref_1"&gt;1&lt;/a&gt;. We could have used &lt;code&gt;&amp;amp;mut self&lt;/code&gt; instead of &lt;code&gt;self&lt;/code&gt;, but there is no good reason to not consume it.
&lt;/div&gt;
&lt;div class="footnote" id="_footnotedef_2"&gt;
&lt;a href="#_footnoteref_2"&gt;2&lt;/a&gt;. I like this title!
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="rust"></category><category term="test"></category><category term="runit"></category></entry><entry><title>Equality assertions</title><link href="https://hole.tuziwo.info/equality-assertions.html" rel="alternate"></link><published>2022-02-14T00:00:00+01:00</published><updated>2022-02-14T00:00:00+01:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2022-02-14:/equality-assertions.html</id><summary type="html">&lt;div id="preamble"&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This post is part of an ongoing series about tests in&amp;nbsp;Rust:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="olist arabic"&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./rust-testing-ecosystem.html"&gt;Rust testing&amp;nbsp;ecosystem&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./fluent-assertions-for-numbers-in-rust.html"&gt;Fluent assertions for numbers in&amp;nbsp;Rust&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Equality&amp;nbsp;assertions&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./assertion-reporting.html"&gt;Assertion&amp;nbsp;reporting&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./make-it-look-like-rainbows.html"&gt;Make it look like rainbows&amp;nbsp;🌈&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_equality_for_other_types"&gt;Equality for other&amp;nbsp;types&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In the possible improvements mentioned in the
&lt;a href="./fluent-assertions-for-numbers-in-rust.html"&gt;last post&lt;/a&gt;, I mentioned
splitting &lt;code&gt;NumberAssertions&lt;/code&gt; into 2&amp;nbsp;functionalities …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div id="preamble"&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This post is part of an ongoing series about tests in&amp;nbsp;Rust:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="olist arabic"&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./rust-testing-ecosystem.html"&gt;Rust testing&amp;nbsp;ecosystem&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./fluent-assertions-for-numbers-in-rust.html"&gt;Fluent assertions for numbers in&amp;nbsp;Rust&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Equality&amp;nbsp;assertions&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./assertion-reporting.html"&gt;Assertion&amp;nbsp;reporting&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./make-it-look-like-rainbows.html"&gt;Make it look like rainbows&amp;nbsp;🌈&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_equality_for_other_types"&gt;Equality for other&amp;nbsp;types&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In the possible improvements mentioned in the
&lt;a href="./fluent-assertions-for-numbers-in-rust.html"&gt;last post&lt;/a&gt;, I mentioned
splitting &lt;code&gt;NumberAssertions&lt;/code&gt; into 2&amp;nbsp;functionalities:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;comparing equality of 2 objects (&lt;code&gt;is_equal_to&lt;/code&gt;, &lt;code&gt;is_not_equal_to&lt;/code&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;comparing order of 2 objects (&lt;code&gt;is_greater_than&lt;/code&gt;, &lt;code&gt;is_less_than&lt;/code&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The funny thing is: we don&amp;#8217;t need a new trait for these, they already exist and
are called &lt;code&gt;PartialEq&lt;/code&gt; et &lt;code&gt;PartialOrd&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Let&amp;#8217;s focus on &lt;code&gt;PartialEq&lt;/code&gt; for the rest of this&amp;nbsp;post.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_what_about_chaining"&gt;What about&amp;nbsp;chaining?&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In the previous post, the &lt;span class="caps"&gt;API&lt;/span&gt; was allowing to chain multiple assertions. For
example, this should be&amp;nbsp;possible.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="n"&gt;some_vec&lt;/span&gt;&lt;span class="nf"&gt;.has_length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;However, we do not have the &lt;code&gt;NumberAssertions&lt;/code&gt; trait anymore that can be pass
from assertion to the next one. So let&amp;#8217;s create a &lt;code&gt;struct&lt;/code&gt; that will refer to
the tested value and might also contains more useful information that may be
printed out for test results. For now, let&amp;#8217;s do it simple and just retain
information about the tested&amp;nbsp;value.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Assertion&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'v&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_construct_an_assertion"&gt;Construct an &lt;code&gt;Assertion&lt;/code&gt;&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Let&amp;#8217;s create a quick constructor for this new &lt;code&gt;struct&lt;/code&gt; and name it
&lt;code&gt;assert_that&lt;/code&gt;. This should allow us to write the&amp;nbsp;following.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="nf"&gt;assert_that&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_assert_that_as_a_function"&gt;&lt;code&gt;assert_that&lt;/code&gt; as a&amp;nbsp;function&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;How about a simple function to&amp;nbsp;start.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;assert_that&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Assertion&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Assertion&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Oh wait, this consumes the value, we probably don&amp;#8217;t want that. And it doesn&amp;#8217;t
work&amp;nbsp;anyway.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code&gt;error[E0106]: missing lifetime specifier
  --&amp;gt; runit-assertions/src/lib.rs:46:46
   |
46 | pub fn assert_that&amp;lt;V&amp;gt;(value: V) -&amp;gt; Assertion&amp;lt;'_, V&amp;gt; {
   |                                              ^^ expected named lifetime parameter
   |
= help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
help: consider using the `'static` lifetime
   |
46 | pub fn assert_that&amp;lt;V&amp;gt;(value: V) -&amp;gt; Assertion&amp;lt;'static, V&amp;gt; {
   |                                              ~~~~~~~

For more information about this error, try `rustc --explain E0106`.&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Let&amp;#8217;s fix&amp;nbsp;it&amp;#8230;&amp;#8203;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;assert_that&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Assertion&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Assertion&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Argh, it doesn&amp;#8217;t work&amp;nbsp;either.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code&gt;error[E0308]: mismatched types
 --&amp;gt; src/lib.rs:44:13
  |
5 | assert_that(1 + 1).is_equal_to(2);
  |             ^^^^^
  |             |
  |             expected reference, found integer
  |             help: consider borrowing here: `&amp;amp;(1 + 1)`
  |
  = note: expected reference `&amp;amp;_`
                  found type `{integer}`&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Ok, we do not want to take ownership but typing &lt;code&gt;&amp;amp;(1+1)&lt;/code&gt; intead of &lt;code&gt;1+1&lt;/code&gt;
would make our &lt;span class="caps"&gt;API&lt;/span&gt; not easy to use. Can we do better? I believe we can thanks
to&amp;nbsp;macros.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_assert_that_as_a_macro"&gt;&lt;code&gt;assert_that&lt;/code&gt; as a&amp;nbsp;macro&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Let&amp;#8217;s try&amp;nbsp;it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="nd"&gt;macro_rules!&lt;/span&gt; &lt;span class="n"&gt;assert_that&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value:expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt;
        &lt;span class="nn"&gt;runit_assertions&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Assertion&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Oh, but that wouldn&amp;#8217;t work because &lt;code&gt;value&lt;/code&gt; is a private field. We could make
the field &lt;code&gt;pub&lt;/code&gt; but no reason to expose it only for the constructor. There is
actually another simple&amp;nbsp;fix.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;From&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'v&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Assertion&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt;
    &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;'v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'v&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Assertion&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;macro_rules!&lt;/span&gt; &lt;span class="n"&gt;assert_that&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value:expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt;
        &lt;span class="nn"&gt;runit_assertions&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Assertion&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Here we are, this finally works! Back to business after this little
constructor&amp;#8217;s&amp;nbsp;digression.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_implementing_is_equal_to"&gt;Implementing &lt;code&gt;is_equal_to&lt;/code&gt;&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Let&amp;#8217;s implement &lt;code&gt;is_equal_to&lt;/code&gt; for &lt;code&gt;Assertion&lt;/code&gt; now.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Assertion&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;is_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;
    &lt;span class="k"&gt;where&lt;/span&gt;
        &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;PartialEq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;V&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The problem of that implementation? It doesn&amp;#8217;t allow to do the&amp;nbsp;following.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;some_function_under_test&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nd"&gt;assert_that!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foobar"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Indeed, &lt;code&gt;"foobar"&lt;/code&gt; is of type &lt;code&gt;&amp;amp;str&lt;/code&gt; but &lt;code&gt;s&lt;/code&gt; is of type &lt;code&gt;String&lt;/code&gt;. But I do
remember an &lt;span class="caps"&gt;API&lt;/span&gt; of &lt;code&gt;std&lt;/code&gt; that does exactly that: &lt;code&gt;HashMap::get()&lt;/code&gt;. For example,
the following does compile, even if the keys of the &lt;code&gt;HashMap&lt;/code&gt; are &lt;code&gt;String&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;HashMap&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="nf"&gt;.insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This works thanks to the trait
&lt;a href="https://doc.rust-lang.org/std/borrow/trait.Borrow.html"&gt;&lt;code&gt;Borrow&lt;/code&gt;&lt;/a&gt;:
with it, you can have a &lt;code&gt;String&lt;/code&gt; and borrow it as if it was a &lt;code&gt;&amp;amp;str&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Will &lt;code&gt;Borrow&lt;/code&gt; help in our case? Well, yes and no. Ideally, I believe we should
be able to support all of the following&amp;nbsp;combinations.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="nd"&gt;assert_that!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;assert_that!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="nf"&gt;.is_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;assert_that!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nd"&gt;assert_that!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="nf"&gt;.is_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;And I did try multiple different combinations using &lt;code&gt;Borrow&lt;/code&gt;, &lt;code&gt;Into&lt;/code&gt;, or
&lt;code&gt;AsRef&lt;/code&gt;&amp;#8230;&amp;#8203; but none of them worked. Until I realized something. Will you find
the important part in the following fixed&amp;nbsp;implementation?&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;is_equal_to&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt;
    &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;PartialEq&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;V&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;self&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Of course you did spot that a new generic &lt;code&gt;E&lt;/code&gt; was introduced. This is mandatory
if we want to support a different type from &lt;code&gt;V&lt;/code&gt;. However, the important piece
is in the bounds of &lt;code&gt;V&lt;/code&gt;: it went from &lt;code&gt;V: PartialEq&lt;/code&gt; to &lt;code&gt;V: PartialEq&amp;lt;E&amp;gt;&lt;/code&gt;. Yes,
this single change will do the trick because &lt;code&gt;String&lt;/code&gt; does implement
&lt;code&gt;PartialEq&amp;lt;String&amp;gt;&lt;/code&gt;, &lt;code&gt;PartialEq&amp;lt;&amp;amp;str&amp;gt;&lt;/code&gt;, &lt;code&gt;PartialEq&amp;lt;str&amp;gt;&lt;/code&gt; and even
&lt;code&gt;PartialEq&amp;lt;Cow&amp;lt;'a, str&amp;gt;&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In the end, we were able to implement something that allows us to write the
following assertions and I find it pretty nice so&amp;nbsp;far.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="nd"&gt;assert_that!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;foobar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foobar"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;assert_that!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;foobar&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foobar"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// String == &amp;amp;str&lt;/span&gt;
&lt;span class="nd"&gt;assert_that!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foobar"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foobar"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// &amp;amp;str == &amp;amp;str&lt;/span&gt;
&lt;span class="nd"&gt;assert_that!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foobar"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;foobar&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// &amp;amp;str == &amp;amp;String&lt;/span&gt;
&lt;span class="nd"&gt;assert_that!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foobar"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;foobar&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// &amp;amp;str == String&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Looks good, isn&amp;#8217;t it? You can browse the result of this implementation in
&lt;a href="https://gitlab.com/woshilapin/runit/-/tree/9129cd64d0ab4746b9a216a910a0ea7e2f3e70a2"&gt;&lt;code&gt;woshilapin/runit&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="rust"></category><category term="test"></category><category term="runit"></category></entry><entry><title>`cargo-sonar`</title><link href="https://hole.tuziwo.info/cargo-sonar.html" rel="alternate"></link><published>2021-11-17T00:00:00+01:00</published><updated>2021-11-17T00:00:00+01:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2021-11-17:/cargo-sonar.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_announcing_cargo_sonar"&gt;Announcing &lt;code&gt;cargo-sonar&lt;/code&gt;&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;For a few days, I&amp;#8217;ve been working on a small project called
&lt;a href="https://crates.io/crates/cargo-sonar"&gt;&lt;code&gt;cargo-sonar&lt;/code&gt;&lt;/a&gt; and now is the time to
make it&amp;nbsp;public.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_why"&gt;Why?&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Sonar &lt;sup class="footnote"&gt;[&lt;a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote."&gt;1&lt;/a&gt;]&lt;/sup&gt;
is a great tool for managing the quality of your software. Although, you might
disagree if you&amp;#8217;ve been using it 10 …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_announcing_cargo_sonar"&gt;Announcing &lt;code&gt;cargo-sonar&lt;/code&gt;&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;For a few days, I&amp;#8217;ve been working on a small project called
&lt;a href="https://crates.io/crates/cargo-sonar"&gt;&lt;code&gt;cargo-sonar&lt;/code&gt;&lt;/a&gt; and now is the time to
make it&amp;nbsp;public.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_why"&gt;Why?&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Sonar &lt;sup class="footnote"&gt;[&lt;a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote."&gt;1&lt;/a&gt;]&lt;/sup&gt;
is a great tool for managing the quality of your software. Although, you might
disagree if you&amp;#8217;ve been using it 10 years&amp;nbsp;ago!&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;However, our beloved language Rust has not been supported by Sonar (although
there have been
&lt;a href="https://community.sonarsource.com/t/add-rust-language-support/13443/22"&gt;discussion&lt;/a&gt;
about&amp;nbsp;it).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In a company, Sonar is a great tool for centralizing all metrics about code
quality. So not having Rust&amp;#8217;s support is another reason a company could rule
out Rust as a technical solution (a small one but still a valid&amp;nbsp;one).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The community already provided a great plugin for
&lt;a href="https://www.sonarqube.org"&gt;SonarQube&lt;/a&gt; called
&lt;a href="https://github.com/elegoff/sonar-rust"&gt;&lt;code&gt;sonar-rust&lt;/code&gt;&lt;/a&gt;. Even if the
maintenance of the code has not been very active in the last few months, the
plugin just works fine. But there is one trick, it has to be installed
server-side. If you want to manage your own in-house instance of Sonar,
that&amp;#8217;s the go-to solution. But &lt;a href="https://sonarcloud.io"&gt;sonarcloud.io&lt;/a&gt;
who provides hosted instances of Sonar doesn&amp;#8217;t allow custom plugins to be
installed. So how do we do&amp;nbsp;it?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_how"&gt;How?&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Well, Sonar actually have an &lt;span class="caps"&gt;API&lt;/span&gt; to provide
&lt;a href="https://sonarcloud.io/documentation/enriching/generic-issue"&gt;generic issues&lt;/a&gt;.
How about we use the output from &lt;code&gt;clippy&lt;/code&gt;, transform it into this generic issue
format, then send it to Sonar? That&amp;#8217;s exactly what &lt;code&gt;cargo-sonar&lt;/code&gt; is made for&amp;#8230;&amp;#8203;
and a bit&amp;nbsp;more.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_setting_up_cargo_sonar"&gt;Setting up &lt;code&gt;cargo-sonar&lt;/code&gt;&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The best example of a working setup of &lt;code&gt;cargo-sonar&lt;/code&gt; is probably the
&lt;a href="https://gitlab.com/woshilapin/cargo-sonar"&gt;&lt;code&gt;cargo-sonar&lt;/code&gt;&lt;/a&gt; project itself.
You can see the result on
&lt;a href="https://sonarcloud.io/project/overview?id=woshilapin_cargo-sonar"&gt;sonarcloud.io&lt;/a&gt;
directly. But let me show you the big lines as a&amp;nbsp;starter.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_generate_clippy_output"&gt;Generate &lt;code&gt;clippy&lt;/code&gt; output&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;First of all, you&amp;#8217;ll have to generate &lt;code&gt;clippy&lt;/code&gt; output in &lt;span class="caps"&gt;JSON&lt;/span&gt; format. You can
even activate &lt;code&gt;clippy::pedantic&lt;/code&gt; in this case to have maximum&amp;nbsp;feedback.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="bash"&gt;cargo clippy &lt;span class="nt"&gt;--all-features&lt;/span&gt; &lt;span class="nt"&gt;--all-targets&lt;/span&gt; &lt;span class="nt"&gt;--message-format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;json &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--warn&lt;/span&gt; clippy::pedantic &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; clippy.json&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_convert_into_sonar_generic_issues"&gt;Convert into Sonar generic&amp;nbsp;issues&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Here is where &lt;code&gt;cargo-sonar&lt;/code&gt; do its&amp;nbsp;work.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="bash"&gt;cargo &lt;span class="nb"&gt;install &lt;/span&gt;cargo-sonar
cargo sonar &lt;span class="nt"&gt;--clippy&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This is going to produce a file &lt;code&gt;sonar.json&lt;/code&gt; from the &lt;code&gt;clippy.json&lt;/code&gt; file
&lt;sup class="footnote"&gt;[&lt;a id="_footnoteref_2" class="footnote" href="#_footnotedef_2" title="View footnote."&gt;2&lt;/a&gt;]&lt;/sup&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_push_the_generic_issues_to_sonarcloud_io"&gt;Push the generic issues to&amp;nbsp;sonarcloud.io&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You&amp;#8217;ll need an account on sonarcloud.io and a existing project. To push the
generic issues, we&amp;#8217;re going to use
&lt;a href="https://docs.sonarqube.org/latest/analysis/scan/sonarscanner"&gt;&lt;code&gt;sonar-scanner&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Once you&amp;#8217;ve installed &lt;code&gt;sonar-scanner&lt;/code&gt;, you&amp;#8217;ll have to create a
&lt;code&gt;sonar-project.properties&lt;/code&gt; file. I&amp;#8217;ll take &lt;code&gt;cargo-sonar&lt;/code&gt; as an&amp;nbsp;example.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code&gt;sonar.organization=woshilapin
sonar.projectKey=woshilapin_cargo-sonar
sonar.projectName=cargo-sonar
sonar.sources=.
sonar.host.url=https://sonarcloud.io
sonar.sourceEncoding=UTF-8
sonar.externalIssuesReportPaths=sonar.json
sonar.login=the_token_of_the_project&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Do not forget to replace the &lt;code&gt;sonar.login&lt;/code&gt; property with your project&amp;#8217;s token.
Did you see the &lt;code&gt;sonar.externalIssuesReportPaths&lt;/code&gt; property refering to our
&lt;code&gt;sonar.json&lt;/code&gt; file. Now, you can just run &lt;code&gt;sonar-scanner&lt;/code&gt; and go see on
&lt;a href="https://sonarcloud.io/project/overview?id=woshilapin_cargo-sonar"&gt;sonarcloud.io&lt;/a&gt;
the&amp;nbsp;result.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_whats_more"&gt;What&amp;#8217;s&amp;nbsp;more?&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Well, &lt;code&gt;clippy&lt;/code&gt; is nice but we have tons of tools in the Rust ecosystem. How
about seing &lt;span class="caps"&gt;CVE&lt;/span&gt; in Sonar? How about outdated dependencies? Or licenses&amp;nbsp;incompatibilities?&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;With the same logic, I&amp;#8217;ve been implementing conversion into generic issues for
the following&amp;nbsp;tools.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_cargo_audit"&gt;&lt;code&gt;cargo-audit&lt;/code&gt;&lt;/h3&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="bash"&gt;cargo audit &lt;span class="nt"&gt;--json&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; audit.json
cargo sonar &lt;span class="nt"&gt;--audit&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_cargo_deny"&gt;&lt;code&gt;cargo-deny&lt;/code&gt;&lt;/h3&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="bash"&gt;cargo deny &lt;span class="nt"&gt;--format&lt;/span&gt; json check 2&amp;gt; deny.json
cargo sonar &lt;span class="nt"&gt;--deny&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_cargo_outdated"&gt;&lt;code&gt;cargo-outdated&lt;/code&gt;&lt;/h3&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="bash"&gt;cargo outdated &lt;span class="nt"&gt;--depth&lt;/span&gt; 1 &lt;span class="nt"&gt;--format&lt;/span&gt; json &lt;span class="nt"&gt;--workspace&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; outdated.json
cargo sonar &lt;span class="nt"&gt;--outdated&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_whats_next"&gt;What&amp;#8217;s&amp;nbsp;next&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The project is pretty young. Not a lot of tests, the documentation can
definitely be better, the code is made of huge functions and could probably have
a better architecture&amp;#8230;&amp;#8203; but it works. I&amp;#8217;m hoping for some feedbacks to better
focus on the next steps. You can post on
&lt;a href="https://gitlab.com/woshilapin/cargo-sonar/-/issues"&gt;issues&lt;/a&gt;, or on forums
like &lt;a href="https://users.rust-lang.org"&gt;&lt;span class="caps"&gt;URLO&lt;/span&gt;&lt;/a&gt; or
&lt;a href="https://community.sonarsource.com"&gt;Sonar&lt;/a&gt;, I&amp;#8217;m &lt;code&gt;woshilapin&lt;/code&gt; on both of&amp;nbsp;them.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="footnotes"&gt;
&lt;hr&gt;
&lt;div class="footnote" id="_footnotedef_1"&gt;
&lt;a href="#_footnoteref_1"&gt;1&lt;/a&gt;. I&amp;#8217;m going to refer to Sonar for both SonarQube and Sonarcloud
&lt;/div&gt;
&lt;div class="footnote" id="_footnotedef_2"&gt;
&lt;a href="#_footnoteref_2"&gt;2&lt;/a&gt;. You can change the filename of the &lt;code&gt;clippy&lt;/code&gt; output with &lt;code&gt;--clippy-path&lt;/code&gt;.
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="rust"></category><category term="sonar"></category></entry><entry><title>Dynamic iterators</title><link href="https://hole.tuziwo.info/dyn-iterator.html" rel="alternate"></link><published>2020-09-21T00:00:00+02:00</published><updated>2020-09-21T00:00:00+02:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2020-09-21:/dyn-iterator.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;If you ever tried to return an &lt;code&gt;Iterator&lt;/code&gt; from a function and had difficulties
with it, this article might&amp;nbsp;help.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Let&amp;#8217;s introduce a context first. Imagine for a minute you&amp;#8217;re trying to define
a trait to list the colors of anything.  For example, you could implement this …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;If you ever tried to return an &lt;code&gt;Iterator&lt;/code&gt; from a function and had difficulties
with it, this article might&amp;nbsp;help.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Let&amp;#8217;s introduce a context first. Imagine for a minute you&amp;#8217;re trying to define
a trait to list the colors of anything.  For example, you could implement this
for vegetables, logos or even&amp;nbsp;flags.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You&amp;#8217;ll probably define the trait like&amp;nbsp;this.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="nd"&gt;#[derive(Clone,&lt;/span&gt; &lt;span class="nd"&gt;Copy,&lt;/span&gt; &lt;span class="nd"&gt;Eq,&lt;/span&gt; &lt;span class="nd"&gt;Hash)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nf"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
	&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Very simple right? But what about the zero-cost abstraction that Rust
embraces. Why would we want to return a &lt;code&gt;Vec&amp;lt;Color&amp;gt;&lt;/code&gt; if when we use it, we only
need the first one for example? No need to allocate memory space for an entire
&lt;code&gt;Vec&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h1 id="_first_try_return_an_iterator_type" class="sect0"&gt;First try: return an &lt;code&gt;Iterator&lt;/code&gt; type&lt;/h1&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Fine, let&amp;#8217;s use an
&lt;a href="https://doc.rust-lang.org/std/iter/trait.Iterator.html"&gt;&lt;code&gt;Iterator&lt;/code&gt;&lt;/a&gt; instead:
the one returned by
&lt;a href="https://doc.rust-lang.org/std/vec/struct.Vec.html#method.iter"&gt;&lt;code&gt;Vec::iter()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
	&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Iter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;At this point, we are enforcing which type of &lt;code&gt;Iterator&lt;/code&gt; any implementor of
&lt;code&gt;Colors&lt;/code&gt; would need to use. If you don&amp;#8217;t see the problem, let&amp;#8217;s understand what
is wrong with it before going&amp;nbsp;forward.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Imagine the following implementation for &lt;code&gt;struct Flag&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Flag&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
	&lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
	&lt;span class="n"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Flag&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
	&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Iter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
		&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.colors&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Everything looks fine so far. But why do we use a &lt;code&gt;Vec&amp;lt;Color&amp;gt;&lt;/code&gt; for the list of
colors. We shouldn&amp;#8217;t have twice the same color in this list so let&amp;#8217;s replace
&lt;code&gt;Vec&amp;lt;Color&amp;gt;&lt;/code&gt; with &lt;code&gt;HashSet&amp;lt;Color&amp;gt;&lt;/code&gt; (&lt;code&gt;Eq&lt;/code&gt; and &lt;code&gt;Hash&lt;/code&gt; are implemented on &lt;code&gt;Color&lt;/code&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You will get the following compilation error because &lt;code&gt;self.colors.iter()&lt;/code&gt;
doesn&amp;#8217;t produce a &lt;code&gt;std::slice::Iter&lt;/code&gt; but a &lt;code&gt;std::collections::hash_set::Iter&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="txt"&gt;error[E0308]: mismatched types
  --&amp;gt; src/lib.rs:15:9
   |
15 |         self.colors.iter()
   |         ^^^^^^^^^^^^^^^^^^ expected struct `std::slice::Iter`, found struct `std::collections::hash_set::Iter`
   |
   = note: expected struct `std::slice::Iter&amp;lt;'a, Color&amp;gt;`
              found struct `std::collections::hash_set::Iter&amp;lt;'_, Color&amp;gt;`&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h1 id="_second_try_associated_type" class="sect0"&gt;Second try: associated&amp;nbsp;type&lt;/h1&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Let&amp;#8217;s change a bit our trait definition so the implementor can decide the
&lt;code&gt;Iterator&lt;/code&gt; type.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;ColorsIter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Iterator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ColorsIter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;And then the implementation would become the&amp;nbsp;following.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Flag&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;ColorsIter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;hash_set&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Iter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ColorsIter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.colors&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Perfect, we&amp;#8217;re done. Are we, really? Something itches me. Indeed, we basically
push the complexity to the implementor. If I could, I&amp;#8217;d like to have an &lt;span class="caps"&gt;API&lt;/span&gt; as
simple as possible. On top of that, the complexity here might actually become
close to a nightmare. Let&amp;#8217;s say for example that &lt;code&gt;Colors&lt;/code&gt; trait is documented as
follow &amp;#8220;list all the colors of an object
(&lt;a href="https://www.colormatters.com/color-and-design/are-black-and-white-colors"&gt;black
is not considered a color&lt;/a&gt;)&amp;#8221;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;But you&amp;#8217;re the implementor of &lt;code&gt;struct Flag&lt;/code&gt; and you do not really care of the
consideration of some scientists to consider that black is not a color: some
flags contains black and you have to store it. But that&amp;#8217;s fine, you can still
implement it by filtering out the&amp;nbsp;black.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Flag&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;ColorsIter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;hash_set&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Iter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ColorsIter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.colors&lt;/span&gt;
            &lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;.filter&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="na"&gt;.1&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="na"&gt;.2&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Here is the compilation error you&amp;#8217;ll&amp;nbsp;get.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="txt"&gt;error[E0308]: mismatched types
  --&amp;gt; src/lib.rs:17:9
   |
16 |       fn colors(&amp;amp;'a self) -&amp;gt; Self::ColorsIter {
   |                              ---------------- expected `std::collections::hash_set::Iter&amp;lt;'_, Color&amp;gt;` because of return type
17 | /         self.colors
18 | |             .iter()
19 | |             .filter(|color| color.0 != 0 &amp;amp;&amp;amp; color.1 != 0 &amp;amp;&amp;amp; color.2 != 0)
   | |_________________________________________________________________________^ expected struct `std::collections::hash_set::Iter`, found struct `std::iter::Filter`
   |
   = note: expected struct `std::collections::hash_set::Iter&amp;lt;'_, _&amp;gt;`
              found struct `std::iter::Filter&amp;lt;std::collections::hash_set::Iter&amp;lt;'_, _&amp;gt;, [closure@src/lib.rs:19:21: 19:73]&amp;gt;`&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Of course, using &lt;code&gt;.filter()&lt;/code&gt; doesn&amp;#8217;t get you
a &lt;code&gt;std::collections::hash_set::Iter&lt;/code&gt; anymore but a &lt;code&gt;std::iter::Filter&lt;/code&gt;. Lucky
for you, the compiler is nice and tell you the type you need to use&amp;#8230;&amp;#8203; or is it?
Did you notice the part that looks like &lt;code&gt;[closure@src/lib.rs:19:21: 19:73]&lt;/code&gt;?
How do you define&amp;nbsp;that?&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Either you&amp;#8217;re experienced enough and know how to get out of this situation, or
you&amp;#8217;re not and feel like maybe, you&amp;#8217;re not going to use this &lt;code&gt;Colors&lt;/code&gt; trait
afterall (read &lt;a href="#_fourth_try_boxdyn_iterator"&gt;fourth try&lt;/a&gt; below, it might
help!). In any case, I hope you&amp;#8217;re convinced our &lt;span class="caps"&gt;API&lt;/span&gt; leaked some bad complexity
to the implementor. Can we do&amp;nbsp;better?&lt;/p&gt;
&lt;/div&gt;
&lt;h1 id="_third_try_impl_iterator" class="sect0"&gt;Third try: &lt;code&gt;impl Iterator&lt;/code&gt;&lt;/h1&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Since &lt;a href="https://blog.rust-lang.org/2018/05/10/Rust-1.26.html"&gt;Rust 1.26&lt;/a&gt;, we
can use the
&lt;a href="https://blog.rust-lang.org/2018/05/10/Rust-1.26.html#impl-trait"&gt;&lt;code&gt;impl&lt;/code&gt;
keyword&lt;/a&gt; in function parameters and return types. Let&amp;#8217;s try&amp;nbsp;it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="nb"&gt;Iterator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Flag&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="nb"&gt;Iterator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.colors&lt;/span&gt;
            &lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;.filter&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="na"&gt;.1&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="na"&gt;.2&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Well, here is what the compiler will tell&amp;nbsp;you.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="txt"&gt;error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
 --&amp;gt; src/lib.rs:6:28
  |
6 |     fn colors(&amp;amp;'a self) -&amp;gt; impl Iterator&amp;lt;Item = &amp;amp;'a Color&amp;gt;;
  |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;And indeed, if we jump to the
&lt;a href="https://github.com/rust-lang/rfcs/blob/master/text/1522-conservative-impl-trait.md"&gt;&lt;span class="caps"&gt;RFC1522&lt;/span&gt;&lt;/a&gt;
that introduced this nice behavior, there is a limitation (might be lifted in
the future but not&amp;nbsp;now).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;`impl Trait` may only be written within the return type of a freestanding or
inherent-impl function, not in trait definitions or any non-return type
position. They may also not appear in the return type of closure traits or
function pointers, unless these are themselves part of a legal return type.&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;&lt;a href="https://thegoodplace.fandom.com/wiki/Censored_Curse_Words"&gt;Fork&lt;/a&gt;! It seems
like the ideal solution but is not yet supported in the&amp;nbsp;language.&lt;/p&gt;
&lt;/div&gt;
&lt;h1 id="_fourth_try_boxdyn_iterator" class="sect0"&gt;Fourth try: &lt;code&gt;Box&amp;lt;dyn Iterator&amp;gt;&lt;/code&gt;&lt;/h1&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Associated types were not a nice solution because we let the implementor deal
with the complexity. But maybe there is a solution not so complex for the
implementor.  We know we want to return something that implements
&lt;code&gt;Iterator&lt;/code&gt;. &lt;a href="https://doc.rust-lang.org/book/ch17-02-trait-objects.html"&gt;Trait-objects&lt;/a&gt;
might be the solution&amp;nbsp;here.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Let&amp;#8217;s get back to our previous definition using an associated type with a little&amp;nbsp;tweak.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;ColorsIter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Iterator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ColorsIter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Note that since we iterate over references of colors, the &lt;code&gt;Iterator&lt;/code&gt; itself must
live at least as long as these references, which explains why we need to add &lt;code&gt;+
'a&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Then we now can use some boxed trait-object to solve our&amp;nbsp;problems.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Flag&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;ColorsIter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nb"&gt;Iterator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ColorsIter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.colors&lt;/span&gt;
                &lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="nf"&gt;.filter&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="na"&gt;.1&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="na"&gt;.2&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This works just fine. Using trait-object, the implementor don&amp;#8217;t need to know the
exact &lt;code&gt;Iterator&lt;/code&gt; type, just that it implements &lt;code&gt;Iterator&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;h1 id="_fifth_try_wrapping_boxdyn_iterator" class="sect0"&gt;Fifth try: wrapping &lt;code&gt;Box&amp;lt;dyn Iterator&amp;gt;&lt;/code&gt;&lt;/h1&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Are we not done here? Well, here is me splitting hairs. Sure we&amp;#8217;ve found
something manageable but can we simplify a bit the life of a potential
implementor by hiding some of these &lt;code&gt;Box&lt;/code&gt; and &lt;code&gt;dyn&lt;/code&gt;? How about we create a type
to hide this&amp;nbsp;complexity.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;DynIter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'iter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
	&lt;span class="n"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nb"&gt;Iterator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;'iter&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;And then we need to implement &lt;code&gt;Iterator&lt;/code&gt; on&amp;nbsp;it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'iter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Iterator&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;DynIter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'iter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.iter&lt;/span&gt;&lt;span class="nf"&gt;.next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Let&amp;#8217;s also create a &lt;code&gt;new()&lt;/code&gt; method to remove some of the boilerplate of
creating a &lt;code&gt;DynIter&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'iter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;DynIter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'iter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;
    &lt;span class="k"&gt;where&lt;/span&gt;
        &lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Iterator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;'iter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;Self&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;And here we are, no more &lt;code&gt;dyn&lt;/code&gt; or &lt;code&gt;Box&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Flag&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;ColorsIter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DynIter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ColorsIter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;DynIter&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.colors&lt;/span&gt;
                &lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="nf"&gt;.filter&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="na"&gt;.1&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="na"&gt;.2&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h1 id="_conclusion" class="sect0"&gt;Conclusion&lt;/h1&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Since I&amp;#8217;ve found out that the above solution could be reusable, I actually made
a crate out of it: &lt;a href="https://crates.io/crates/dyn-iter"&gt;&lt;code&gt;dyn-iter&lt;/code&gt;&lt;/a&gt;. Please
report issue or improvement in the
&lt;a href="https://gitlab.com/woshilapin/dyn-iter"&gt;project repository&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I hope you learned something. At least, I&amp;#8217;ve learned a lot by trying to make all
of this work. I&amp;#8217;m sure there is still some hidden corners that I don&amp;#8217;t master
yet. If you found any mistake in what I&amp;#8217;m saying, or some ideas to improve this
blog post, please let me know &lt;a href="https://gitlab.com/woshilapin/hole"&gt;on the
blog repository&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;h1 id="_take_second_try_and_third_try_shake_and_here_we_go" class="sect0"&gt;Take &lt;a href="#_second_try_associated_type"&gt;second try&lt;/a&gt; and &lt;a href="#_third_try_impl_iterator"&gt;third try&lt;/a&gt;, shake, and here we&amp;nbsp;go&lt;/h1&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;After the first publication of this article,
&lt;a href="https://gitlab.com/chrysn"&gt;chrysn&lt;/a&gt; provided some
&lt;a href="https://gitlab.com/woshilapin/hole/-/issues/1"&gt;more information&lt;/a&gt; about
&lt;a href="https://github.com/rust-lang/rfcs/blob/master/text/2515-type_alias_impl_trait.md"&gt;&lt;span class="caps"&gt;RFC2515&lt;/span&gt;&lt;/a&gt;
that actually brings the &lt;code&gt;impl&lt;/code&gt; keyword into associated types. At the time of
writing &lt;sup class="footnote"&gt;[&lt;a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote."&gt;1&lt;/a&gt;]&lt;/sup&gt;, this is already available in
&lt;em&gt;nightly&lt;/em&gt;&amp;nbsp;compiler.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="nd"&gt;#![feature(type_alias_impl_trait)]&lt;/span&gt;

&lt;span class="nd"&gt;#[derive(Clone,&lt;/span&gt; &lt;span class="nd"&gt;Copy,&lt;/span&gt; &lt;span class="nd"&gt;PartialEq,&lt;/span&gt; &lt;span class="nd"&gt;Eq,&lt;/span&gt; &lt;span class="nd"&gt;Hash)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nf"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Flag&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;ColorsIter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Iterator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ColorsIter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Flag&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;ColorsIter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="nb"&gt;Iterator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ColorsIter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.colors&lt;/span&gt;
            &lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;.filter&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="na"&gt;.1&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="na"&gt;.2&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Once this is stable, I&amp;#8217;ll pretty much forget about
&lt;a href="https://crates.io/crates/dyn-iter"&gt;&lt;code&gt;dyn-iter&lt;/code&gt;&lt;/a&gt; crate and use this new
solution&amp;nbsp;instead.&lt;/p&gt;
&lt;/div&gt;
&lt;div id="footnotes"&gt;
&lt;hr&gt;
&lt;div class="footnote" id="_footnotedef_1"&gt;
&lt;a href="#_footnoteref_1"&gt;1&lt;/a&gt;. Written on October 24th, 2020
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="rust"></category><category term="iterator"></category></entry><entry><title>Fluent assertions for numbers in Rust</title><link href="https://hole.tuziwo.info/fluent-assertions-for-numbers-in-rust.html" rel="alternate"></link><published>2020-05-21T00:00:00+02:00</published><updated>2020-05-21T00:00:00+02:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2020-05-21:/fluent-assertions-for-numbers-in-rust.html</id><summary type="html">&lt;div id="preamble"&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This post is part of an ongoing series about tests in&amp;nbsp;Rust:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="olist arabic"&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./rust-testing-ecosystem.html"&gt;Rust testing&amp;nbsp;ecosystem&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fluent assertions for numbers in&amp;nbsp;Rust&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./equality-assertions.html"&gt;Equality&amp;nbsp;assertions&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./assertion-reporting.html"&gt;Assertion&amp;nbsp;reporting&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./make-it-look-like-rainbows.html"&gt;Make it look like rainbows&amp;nbsp;🌈&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Following up on my previous blog post about the
&lt;a href="rust-testing-ecosystem.html"&gt;testing ecosystem in Rust&lt;/a&gt;, I decided to try
something on …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div id="preamble"&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This post is part of an ongoing series about tests in&amp;nbsp;Rust:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="olist arabic"&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./rust-testing-ecosystem.html"&gt;Rust testing&amp;nbsp;ecosystem&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fluent assertions for numbers in&amp;nbsp;Rust&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./equality-assertions.html"&gt;Equality&amp;nbsp;assertions&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./assertion-reporting.html"&gt;Assertion&amp;nbsp;reporting&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./make-it-look-like-rainbows.html"&gt;Make it look like rainbows&amp;nbsp;🌈&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Following up on my previous blog post about the
&lt;a href="rust-testing-ecosystem.html"&gt;testing ecosystem in Rust&lt;/a&gt;, I decided to try
something on my own.  I need to make a disclaimer right away: even if I already
evaluated &lt;a href="https://crates.io/crates/spectral"&gt;spectral&lt;/a&gt; as a nice candidate
to start from, I decided to start from scratch because I want to discover all
the tiny details by&amp;nbsp;myself.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In this blog post, I&amp;#8217;ll talk about my very first attempt to write some
assertions for&amp;nbsp;numbers.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_api_driven_design"&gt;&lt;span class="caps"&gt;API&lt;/span&gt; driven&amp;nbsp;design&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Let&amp;#8217;s start by talking about the &lt;span class="caps"&gt;API&lt;/span&gt; we want.  How about we start with this&amp;nbsp;trait.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;NumberAssertions&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
	&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;is_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
	&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;is_greater_than&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
	&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;is_less_than&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I know there is a bunch more we could write like &lt;code&gt;is_not_equal_to&lt;/code&gt;,
&lt;code&gt;is_greater_or_equal_than&lt;/code&gt;, etc. but they can all be derived from the three
above&amp;nbsp;functions.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonitionblock note"&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td class="icon"&gt;
&lt;div class="title"&gt;Note&lt;/div&gt;
&lt;/td&gt;
&lt;td class="content"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The functions don&amp;#8217;t return a value and you might be wondering why?  We&amp;#8217;re
writing a framework for tests.  If the &lt;code&gt;self&lt;/code&gt; &lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;is not greater than&amp;#8221; some other
value, we can &lt;code&gt;panic!()&lt;/code&gt;, no need to return a &lt;code&gt;bool&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;With the above trait, and if we implement it on standard numbers (&lt;code&gt;i32&lt;/code&gt;, &lt;code&gt;u8&lt;/code&gt;,
etc.), we should be able to write tests like&amp;nbsp;this.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="nd"&gt;#[test]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;it_works&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
	&lt;span class="mi"&gt;2u8&lt;/span&gt;&lt;span class="nf"&gt;.is_greater_than&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In the future code samples, I will simply ignore the redundant &lt;code&gt;#[test]&lt;/code&gt; and
function&amp;nbsp;wrapping.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_chaining_assertions"&gt;Chaining&amp;nbsp;assertions&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I see one first problem with the previous example, this &lt;span class="caps"&gt;API&lt;/span&gt; never mentions the
concept of an assertion.  For now, let&amp;#8217;s do something really dumb.&lt;sup class="footnote"&gt;[&lt;a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote."&gt;1&lt;/a&gt;]&lt;/sup&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;assert_that&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;provided&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
	&lt;span class="n"&gt;provided&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;assert_that&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2u8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_greater_than&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Great.  But how would I test that a number is between 2&amp;nbsp;values?&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="nf"&gt;assert_that&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2u8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_greater_than&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;assert_that&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2u8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_less_than&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;How about we provide the ability to chain&amp;nbsp;calls.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="nf"&gt;assert_that&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2u8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_greater_than&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_less_than&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To do this, we can change the trait to something&amp;nbsp;like.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;NumberAssertions&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
	&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;is_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
	&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;is_greater_than&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
	&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;is_less_than&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_owned_versus_referenced_value"&gt;Owned versus referenced&amp;nbsp;value&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;There is another problem.  Let&amp;#8217;s imagine we do 2 different computations that
should result in the same expected&amp;nbsp;value.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;78648u64&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;assert_that&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;compute_1&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.is_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;assert_that&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;compute_2&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.is_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In this case, we&amp;#8217;re lucky because &lt;code&gt;u64&lt;/code&gt; is
&lt;a href="https://doc.rust-lang.org/std/marker/trait.Copy.html"&gt;&lt;code&gt;Copy&lt;/code&gt;&lt;/a&gt;, otherwise, we
would have a compile error.&lt;sup class="footnote"&gt;[&lt;a id="_footnoteref_2" class="footnote" href="#_footnotedef_2" title="View footnote."&gt;2&lt;/a&gt;]&lt;/sup&gt;  But if
&lt;code&gt;expected&lt;/code&gt; was not
&lt;a href="https://doc.rust-lang.org/std/marker/trait.Copy.html"&gt;&lt;code&gt;Copy&lt;/code&gt;&lt;/a&gt;, we probably
want to be able to take the parameter as a reference or as a&amp;nbsp;value.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;78648&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;assert_that&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;compute_1&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.is_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;assert_that&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;compute_2&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.is_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The
&lt;a href="https://doc.rust-lang.org/std/borrow/trait.Borrow.html"&gt;&lt;code&gt;std::borrow::Borrow&lt;/code&gt;&lt;/a&gt;
trait can help&amp;nbsp;here.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;NumberAssertions&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
	&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;is_equal_to&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Borrow&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
	&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;is_greater_than&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Borrow&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
	&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;is_less_than&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Borrow&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_constraints"&gt;Constraints&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Finally, we forgot some constraints on &lt;code&gt;Self&lt;/code&gt; to compare numbers.  Let&amp;#8217;s add
&lt;a href="https://doc.rust-lang.org/std/cmp/trait.PartialEq.html"&gt;&lt;code&gt;PartialEq&lt;/code&gt;&lt;/a&gt; and
&lt;a href="https://doc.rust-lang.org/std/cmp/trait.PartialOrd.html"&gt;&lt;code&gt;PartialOrd&lt;/code&gt;&lt;/a&gt; as&amp;nbsp;needed.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;NumberAssertions&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
	&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;is_equal_to&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;
	&lt;span class="k"&gt;where&lt;/span&gt;
		&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;PartialEq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
		&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Borrow&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
	&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;is_greater_than&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;
	&lt;span class="k"&gt;where&lt;/span&gt;
		&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;PartialOrd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
		&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Borrow&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
	&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;is_less_than&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;
	&lt;span class="k"&gt;where&lt;/span&gt;
		&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;PartialOrd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
		&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Borrow&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_implementation"&gt;Implementation&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We can now implement a simple version for every number&amp;nbsp;types.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;NumberAssertions&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
	&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;is_equal_to&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;
	&lt;span class="k"&gt;where&lt;/span&gt;
		&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Borrow&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
		&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;PartialEq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
	&lt;span class="p"&gt;{&lt;/span&gt;
		&lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="nf"&gt;.eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="nf"&gt;.borrow&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
		&lt;span class="k"&gt;self&lt;/span&gt;
	&lt;span class="p"&gt;}&lt;/span&gt;
	&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;is_greater_than&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;
	&lt;span class="k"&gt;where&lt;/span&gt;
		&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Borrow&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
		&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;PartialOrd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
	&lt;span class="p"&gt;{&lt;/span&gt;
		&lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="nf"&gt;.partial_cmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="nf"&gt;.borrow&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;cmp&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Ordering&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Greater&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
		&lt;span class="k"&gt;self&lt;/span&gt;
	&lt;span class="p"&gt;}&lt;/span&gt;
	&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;is_less_than&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;
	&lt;span class="k"&gt;where&lt;/span&gt;
		&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Borrow&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
		&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;PartialOrd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
	&lt;span class="p"&gt;{&lt;/span&gt;
		&lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="nf"&gt;.partial_cmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="nf"&gt;.borrow&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;cmp&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Ordering&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Less&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
		&lt;span class="k"&gt;self&lt;/span&gt;
	&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We can also add some provided methods in the trait like &lt;code&gt;is_between(n1, n2)&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;NumberAssertions&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
	&lt;span class="c1"&gt;// other functions not displayed here&lt;/span&gt;
	&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;is_between&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;B1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;B2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;B1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;B2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;
	&lt;span class="k"&gt;where&lt;/span&gt;
		&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;PartialEq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
		&lt;span class="n"&gt;B1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Borrow&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
		&lt;span class="n"&gt;B2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Borrow&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
	&lt;span class="p"&gt;{&lt;/span&gt;
		&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="nf"&gt;.is_greater_than&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_less_than&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
	&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_testing_the_implementation"&gt;Testing the&amp;nbsp;implementation&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Let&amp;#8217;s write a bunch of tests to see if everything is working as&amp;nbsp;expected.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="nd"&gt;#[test]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;greater_than&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
	&lt;span class="nf"&gt;assert_that&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2u8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_equal_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
	&lt;span class="nf"&gt;assert_that&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_greater_than&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
	&lt;span class="nf"&gt;assert_that&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2.0f64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_greater_than&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
	&lt;span class="nf"&gt;assert_that&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1u64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_less_than&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
	&lt;span class="nf"&gt;assert_that&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0f32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_less_than&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
	&lt;span class="nf"&gt;assert_that&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_between&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
	&lt;span class="nf"&gt;assert_that&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2u16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_greater_than&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_less_than&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[test]&lt;/span&gt;
&lt;span class="nd"&gt;#[should_panic]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;greater_than_panics&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
	&lt;span class="nf"&gt;assert_that&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.is_greater_than&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;That&amp;#8217;s a great start&amp;#8230;&amp;#8203; but I already see room for&amp;nbsp;improvement.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_is_not_equal_and_friends"&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;Is not equal&amp;#8221; and&amp;nbsp;friends&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;First of all, I did not provide an implementation for &lt;code&gt;is_not_equal_to()&lt;/code&gt;?  Did
you think I forgot?  Well, in fact, I cannot implement &lt;code&gt;is_not_equal_to()&lt;/code&gt;
because &lt;code&gt;is_equal_to()&lt;/code&gt; panics in case of failure.  So basically, we would need
to not panic when &lt;code&gt;is_equal_to()&lt;/code&gt; panics which is not possible.&lt;sup class="footnote"&gt;[&lt;a id="_footnoteref_3" class="footnote" href="#_footnotedef_3" title="View footnote."&gt;3&lt;/a&gt;]&lt;/sup&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Do I need to go back to functions that return &lt;code&gt;bool&lt;/code&gt;?  But if I do, what
about chaining?  Another solution would be to let the implementors implement the
functions but that means more work for each implementor.  Ideally, someone
should be able to implement &lt;code&gt;NumberAssertions&lt;/code&gt; easily for a new type.  Not yet
sure how to overcome this&amp;nbsp;problem.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_more_functions"&gt;More&amp;nbsp;functions&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In this blog post, I focused on a very simple &lt;span class="caps"&gt;API&lt;/span&gt; about equality and comparison.
I&amp;#8217;m sure we could imagine more useful assertions functions like
&lt;code&gt;is_multiple_of()&lt;/code&gt;, &lt;code&gt;is_zero()&lt;/code&gt;, &lt;code&gt;is_not_a_number()&lt;/code&gt;, &lt;code&gt;is_prime()&lt;/code&gt;, etc.  I&amp;#8217;ll
probably add more functions later, once I&amp;#8217;m satisfied the code&amp;nbsp;architecture.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_equality_for_other_types"&gt;Equality for other&amp;nbsp;types&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;&lt;code&gt;is_equal_to()&lt;/code&gt; is part of the trait &lt;code&gt;NumberAssertions&lt;/code&gt;.  But equality is not
exclusive to numbers, we could also compare &lt;code&gt;String&lt;/code&gt;, and any kind of object
that implements &lt;code&gt;PartialEq&lt;/code&gt;.  I might need to split into two parts the
&lt;code&gt;NumberAssertions&lt;/code&gt; trait.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_naming_test"&gt;Naming&amp;nbsp;test&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;When using &lt;code&gt;assert!()&lt;/code&gt;, we can name the test by doing &lt;code&gt;assert!(1 == 1, "Test
dumb equality")&lt;/code&gt;.  Our current solution forbids that.  When looking into
&lt;a href="https://crates.io/crates/spectral"&gt;spectral&lt;/a&gt;, we can see that
&lt;code&gt;assert_that(provided)&lt;/code&gt; doesn&amp;#8217;t return &lt;code&gt;provided&lt;/code&gt; but a wrapper type named
&lt;code&gt;Spec&amp;lt;T&amp;gt;&lt;/code&gt;.  This &lt;code&gt;Spec&lt;/code&gt; can contain more information about the current assertion
(the name of the test or the&amp;nbsp;location).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_feedbacks"&gt;Feedbacks&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Implementation can be found at &lt;a href="https://gitlab.com/woshilapin/runit" class="bare"&gt;https://gitlab.com/woshilapin/runit&lt;/a&gt;.  I&amp;#8217;d be
happy to hear feedbacks, suggestions, or even better, contributors if you&amp;#8217;re
interested in this&amp;nbsp;project.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="footnotes"&gt;
&lt;hr&gt;
&lt;div class="footnote" id="_footnotedef_1"&gt;
&lt;a href="#_footnoteref_1"&gt;1&lt;/a&gt;. We could also rename all our functions with &lt;code&gt;assert_is_equal_to()&lt;/code&gt; but that would make the functions much longer, repetitive and less fluent.
&lt;/div&gt;
&lt;div class="footnote" id="_footnotedef_2"&gt;
&lt;a href="#_footnoteref_2"&gt;2&lt;/a&gt;. First call to &lt;code&gt;is_equal_to()&lt;/code&gt; takes ownership of &lt;code&gt;expected&lt;/code&gt;, second call will fail the compilation
&lt;/div&gt;
&lt;div class="footnote" id="_footnotedef_3"&gt;
&lt;a href="#_footnoteref_3"&gt;3&lt;/a&gt;. I might be able to use &lt;a href="https://doc.rust-lang.org/std/panic/fn.catch_unwind.html"&gt;&lt;code&gt;std::panic::catch_unwind&lt;/code&gt;&lt;/a&gt; but that would mean running assertions in another thread which is not an option for tests.
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="rust"></category><category term="test"></category><category term="runit"></category></entry><entry><title>vim running Rust tests</title><link href="https://hole.tuziwo.info/vim-running-rust-tests.html" rel="alternate"></link><published>2020-05-21T00:00:00+02:00</published><updated>2020-05-21T00:00:00+02:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2020-05-21:/vim-running-rust-tests.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;If you ever used &lt;span class="caps"&gt;VS&lt;/span&gt; Code to edit Rust source code, you might already know you
can launch just the test you care&amp;nbsp;about.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="images/vscode-run-rust-test.png" alt="Run a Rust test in VSCode"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;But I love too much Vim to convert to VSCode.  And yes, I know there is
a &lt;a href="https://marketplace.visualstudio.com/items?itemName=vscodevim.vim"&gt;Vim
plugin&lt;/a&gt; but these emulation plugins are never …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;If you ever used &lt;span class="caps"&gt;VS&lt;/span&gt; Code to edit Rust source code, you might already know you
can launch just the test you care&amp;nbsp;about.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="images/vscode-run-rust-test.png" alt="Run a Rust test in VSCode"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;But I love too much Vim to convert to VSCode.  And yes, I know there is
a &lt;a href="https://marketplace.visualstudio.com/items?itemName=vscodevim.vim"&gt;Vim
plugin&lt;/a&gt; but these emulation plugins are never complete and I always end up using
vim shortcuts that doesn&amp;#8217;t exist in the plugin.  It annoys me.&lt;sup class="footnote"&gt;[&lt;a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote."&gt;1&lt;/a&gt;]&lt;/sup&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;However, there is a bunch of nice things in VSCode like running the test you
want, without running the entire suite&amp;nbsp;test.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_selecting_tests_with_cargo"&gt;Selecting tests with &lt;code&gt;cargo&lt;/code&gt;&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;First of all, let see how to run a test and only the tests you&amp;nbsp;want.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;If you have a &lt;code&gt;lib.rs&lt;/code&gt; with the following&amp;nbsp;test.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="nd"&gt;#[cfg(test)]&lt;/span&gt;
&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;tests&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
	&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
	&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;addition_tests&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
		&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
		&lt;span class="nd"&gt;#[test]&lt;/span&gt;
		&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;add_works&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
			&lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
		&lt;span class="p"&gt;}&lt;/span&gt;

		&lt;span class="nd"&gt;#[test]&lt;/span&gt;
		&lt;span class="nd"&gt;#[should_panic]&lt;/span&gt;
		&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;add_panics&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
			&lt;span class="nd"&gt;assert_ne!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
		&lt;span class="p"&gt;}&lt;/span&gt;
	&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Then you can run the &lt;code&gt;add_work()&lt;/code&gt; test function&amp;nbsp;with&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;cargo test --lib -- --exact tests::addition_tests::add_works&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Or run all the tests in this file&amp;nbsp;with&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;cargo test --lib -- tests::addition_tests&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;And it works similarly for integration&amp;nbsp;tests.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;cargo test --test addition&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;will run all the tests in &lt;code&gt;tests/addition.rs&lt;/code&gt; and&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;cargo test --test addition -- --exact add_works&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;will only run the &lt;code&gt;add_works()&lt;/code&gt; function in &lt;code&gt;tests/addition.rs&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_lets_do_it_in_vim"&gt;Let&amp;#8217;s do it in&amp;nbsp;vim&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The algorithm is relatively simple.  We start from the position of the cursor
and try to deduce what test the user want to launch.  If the cursor is inside
a test function, let&amp;#8217;s launch only this function.  If the cursor is in a file
that contains test, let&amp;#8217;s launch all the tests of this file,&amp;nbsp;etc.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Here is a simplified algorithm.  First, we iterate over the blocks &lt;code&gt;{ &amp;#8230;&amp;#8203; }&lt;/code&gt;
going from the narrower block containing the cursor, to the larger block
containing the cursor.  During this iteration, we identify the block of the test
function (function annotated with &lt;code&gt;#[test]&lt;/code&gt;) if there is one, and all the
wrapping modules.  Then we can iterate on the file path to deduce the rest of
the&amp;nbsp;modules.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;From the file path, we can also deduce if this is an integration test or not.
This will help to choose between &lt;code&gt;--lib&lt;/code&gt; or &lt;code&gt;--test&lt;/code&gt; options.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You can find the code in my vim script
&lt;a href="https://github.com/woshilapin/dot/blob/34f95098ac6c34500b30f421774cf74ead2f00a2/vim/ftplugin/rust_Rust.vim#L81-L144"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now, you have a nice function that you can map to a shortcut.  I use
&lt;a href="https://github.com/woshilapin/dot/blob/34f95098ac6c34500b30f421774cf74ead2f00a2/vim/ftplugin/rust_Rust.vim#L14"&gt;&lt;code&gt;F6&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;noremap &amp;lt;F6&amp;gt; &amp;lt;Esc&amp;gt;:call &amp;lt;SID&amp;gt;rust_execute_test()&amp;lt;Enter&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I will add an additional comment because we forget too often about that, &lt;code&gt;vim&lt;/code&gt;
documentation is awesome.  Most of my problems in writing this script was solved
through documentation.  The only drawback of the documentation is to find the
right section. &lt;sup class="footnote"&gt;[&lt;a id="_footnoteref_2" class="footnote" href="#_footnotedef_2" title="View footnote."&gt;2&lt;/a&gt;]&lt;/sup&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="footnotes"&gt;
&lt;hr&gt;
&lt;div class="footnote" id="_footnotedef_1"&gt;
&lt;a href="#_footnoteref_1"&gt;1&lt;/a&gt;. I&amp;#8217;ve had the same problem with &lt;a href="https://plugins.jetbrains.com/plugin/164-ideavim"&gt;IdeaVim&lt;/a&gt; in IntelliJ or with &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/vimium-ff/"&gt;Vimium&lt;/a&gt; to name a few
&lt;/div&gt;
&lt;div class="footnote" id="_footnotedef_2"&gt;
&lt;a href="#_footnoteref_2"&gt;2&lt;/a&gt;. As I am writing this blog post, I&amp;#8217;m discovering the command &lt;code&gt;:helpgrep&lt;/code&gt; which might have help me.
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="rust"></category><category term="test"></category><category term="vim"></category></entry><entry><title>Hole is back</title><link href="https://hole.tuziwo.info/hole-is-back.html" rel="alternate"></link><published>2020-05-17T00:00:00+02:00</published><updated>2020-05-17T00:00:00+02:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2020-05-17:/hole-is-back.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;It has been about 6 years or so since I last wrote on this blog.  Life happened
I guess!  But I once again have the envy to express myself: document things I
experiment, publish experiences I do.  Always about computer sciences, what&amp;nbsp;else!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_what_changed"&gt;What&amp;nbsp;changed?&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Well, quite a lot …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;It has been about 6 years or so since I last wrote on this blog.  Life happened
I guess!  But I once again have the envy to express myself: document things I
experiment, publish experiences I do.  Always about computer sciences, what&amp;nbsp;else!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_what_changed"&gt;What&amp;nbsp;changed?&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Well, quite a lot changed in 6 years, professionally and personally but I&amp;#8217;m not
here to talk about my life.  However, I can say that my topics of interest
evolved and also narrowed in some ways.  I&amp;#8217;m still pretty much interested in a
lot of things and here are the non-exhaustive list of things I&amp;#8217;ve touch in the
last&amp;nbsp;years.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_javascript"&gt;Javascript&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;With front-end and back-end, I experimented with a lot of different technologies
build tools, automatic integration and deployment.  I tried the &lt;code&gt;async/await&lt;/code&gt;
before it was wide-spread (with some exotic configuration of
&lt;a href="https://babeljs.io/"&gt;Babel&lt;/a&gt; transpiler).  With it, I obviously tried some
&lt;span class="caps"&gt;CSS&lt;/span&gt; frameworks too (&lt;a href="http://lesscss.org/"&gt;&lt;span class="caps"&gt;LESS&lt;/span&gt;&lt;/a&gt;,
&lt;a href="https://postcss.org/"&gt;PostCSS&lt;/a&gt;) as well as templating for &lt;span class="caps"&gt;HTML&lt;/span&gt; (like
&lt;a href="http://jade-lang.com/"&gt;Jade&lt;/a&gt;).  I tried to explore the &lt;span class="caps"&gt;HTML5&lt;/span&gt; world as much
as&amp;nbsp;possible.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_docker"&gt;Docker&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I also discovered Docker which I used quite a lot for development.  I was not
confident enough to use it for deployment in production most of the time but as
a developer tool, it was wonderful to install different database version or some
&lt;span class="caps"&gt;MQ&lt;/span&gt; tools without polluting my own &lt;span class="caps"&gt;OS&lt;/span&gt;.  And I used Docker almost exclusively
through &lt;a href="https://docs.docker.com/compose/"&gt;Docker Compose&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_java"&gt;Java&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I love and don&amp;#8217;t like this language at the same time.  I love it so much because
it has the richest ecosystem that I know.  But I also don&amp;#8217;t like it that much
because, well, the language is not that fun to write.  Maybe the only other
language with such a rich ecosystem is C but in a much more chaotic way.  In
Java, you have tons of very complete tools for doing pretty much anything.
Testing in Java is awesome.  Build tools are quite complete (Maven might be slow
and &lt;span class="caps"&gt;XML&lt;/span&gt; but you can pretty much do anything with it).  I&amp;#8217;d like to try Gradle at
some point.  And so much more, &lt;a href="https://junit.org/junit5/"&gt;Junit5&lt;/a&gt;, asserting
libraries like &lt;a href="https://joel-costigliola.github.io/assertj/"&gt;AssertJ&lt;/a&gt;, code
quality and coverage with &lt;a href="https://www.sonarqube.org/"&gt;SonarQube&lt;/a&gt; (this tool
is so&amp;nbsp;excellent).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_rust"&gt;Rust&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;More recently, I&amp;#8217;ve been able to find much more time to explore my curiosity
about, I can say it now, this wonderful language and community that is Rust.
And Rust ecosystem is actually the reason why at some point, I wanted to
unearth this blog.  I won&amp;#8217;t talk much more about it since future blog post will
probably talk about&amp;nbsp;it.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_others"&gt;Others&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I also took a look at things like &lt;a href="https://golang.org/"&gt;Go&lt;/a&gt;,
&lt;a href="https://docs.docker.com/engine/swarm/"&gt;Docker Swarm&lt;/a&gt;,
&lt;a href="https://kubernetes.io/fr/"&gt;Kubernetes&lt;/a&gt;,
&lt;a href="https://docs.gitlab.com/ee/ci/"&gt;Gitlab &lt;span class="caps"&gt;CI&lt;/span&gt;&lt;/a&gt;,
&lt;a href="https://www.codingame.com/"&gt;CodingGame&lt;/a&gt;, &lt;a href="https://vuejs.org/"&gt;VueJS&lt;/a&gt;,
&lt;a href="https://webassembly.org/"&gt;WebAssembly&lt;/a&gt;,
&lt;a href="https://developer.mozilla.org/fr/docs/Mozilla/Add-ons/WebExtensions"&gt;WebExtensions&lt;/a&gt;
and I probably forgot more of&amp;nbsp;them.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_what_else"&gt;What&amp;nbsp;else?&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Well, I&amp;#8217;ve changed the way I deploy this blog, using Gitlab &lt;span class="caps"&gt;CI&lt;/span&gt;.  It&amp;#8217;s now much
easier than it used to be to write a new blog post because it&amp;#8217;s only about
adding a ASCIIDoc file into the repository, and Gitlab take care of the&amp;nbsp;rest.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;What, do we really need a conclusion?  Well, see you in the next blog&amp;nbsp;post!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><category term="misc"></category><category term="blog"></category></entry><entry><title>Rust testing ecosystem</title><link href="https://hole.tuziwo.info/rust-testing-ecosystem.html" rel="alternate"></link><published>2020-05-17T00:00:00+02:00</published><updated>2020-05-17T00:00:00+02:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2020-05-17:/rust-testing-ecosystem.html</id><summary type="html">&lt;div id="preamble"&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This post is part of an ongoing series about tests in&amp;nbsp;Rust:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="olist arabic"&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;
&lt;p&gt;Rust testing&amp;nbsp;ecosystem&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./fluent-assertions-for-numbers-in-rust.html"&gt;Fluent assertions for numbers in&amp;nbsp;Rust&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./equality-assertions.html"&gt;Equality&amp;nbsp;assertions&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./assertion-reporting.html"&gt;Assertion&amp;nbsp;reporting&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./make-it-look-like-rainbows.html"&gt;Make it look like rainbows&amp;nbsp;🌈&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I&amp;#8217;ve been working with Rust daily for a year now and generally, I have been very
happy with …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div id="preamble"&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This post is part of an ongoing series about tests in&amp;nbsp;Rust:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="olist arabic"&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;
&lt;p&gt;Rust testing&amp;nbsp;ecosystem&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./fluent-assertions-for-numbers-in-rust.html"&gt;Fluent assertions for numbers in&amp;nbsp;Rust&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./equality-assertions.html"&gt;Equality&amp;nbsp;assertions&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./assertion-reporting.html"&gt;Assertion&amp;nbsp;reporting&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="./make-it-look-like-rainbows.html"&gt;Make it look like rainbows&amp;nbsp;🌈&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I&amp;#8217;ve been working with Rust daily for a year now and generally, I have been very
happy with this language and it&amp;#8217;s ecosystem.  Of course, the ecosystem is still
pretty new, a lot of things are missing or incomplete but it&amp;#8217;s only a
&lt;a href="https://blog.rust-lang.org/2020/05/15/five-years-of-rust.html"&gt;five
year&amp;#8217;s language&lt;/a&gt; and I feel that for this age, its already pretty&amp;nbsp;mature.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;However, there is one domain in which I feel this language is still pretty poor
in term of ecosystem: testing.  And I love testing!  No really, I know most
people find the task of writing tests boring, annoying but this is a task I am
generally enthusiast to do for multiple&amp;nbsp;reasons:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;I don&amp;#8217;t trust my code, test is a fun way to automatically verify what I&amp;#8217;ve&amp;nbsp;done&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I found out that in general,
&lt;a href="https://en.wikipedia.org/wiki/Test-driven_development"&gt;&lt;span class="caps"&gt;TDD&lt;/span&gt;&lt;/a&gt; helps me think
better of a problem before implementing&amp;nbsp;it&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I believe that testable code is producing better code&amp;nbsp;architecture&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_testing_in_rust_language"&gt;Testing in Rust&amp;nbsp;language&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Today in Rust, testing can be summarized in a few&amp;nbsp;functionalities:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;a &lt;code&gt;#[test]&lt;/code&gt; macro&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;an &lt;code&gt;assert!()&lt;/code&gt; macro&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;a &lt;code&gt;test&lt;/code&gt; configuration option (used in &lt;code&gt;#[cfg(test)]&lt;/code&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;a folder &lt;code&gt;tests/&lt;/code&gt; with &lt;code&gt;cargo&lt;/code&gt; &lt;sup class="footnote"&gt;[&lt;a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote."&gt;1&lt;/a&gt;]&lt;/sup&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://doc.rust-lang.org/rustdoc/documentation-tests.html"&gt;Documentation&amp;nbsp;tests&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Compared to other languages, it&amp;#8217;s pretty similar: an assert command and the rest
is to declare what and where is a test.  The notable exception is Documentation
Tests which is quite innovative and&amp;nbsp;awesome.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In this post, I will focus on assertions.  Indeed, &lt;code&gt;assert!()&lt;/code&gt; is a necessary
building block and a simple one, but it&amp;#8217;s not really fun to use.  Better &lt;span class="caps"&gt;API&lt;/span&gt; can
be built on top of&amp;nbsp;it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In this post, I will not talk about mocking (there is a bunch of
&lt;a href="https://crates.io/search?q=mock"&gt;libraries around&lt;/a&gt;) or other types of
testing like property testing (check
&lt;a href="https://crates.io/crates/quickcheck"&gt;quickcheck&lt;/a&gt; and
&lt;a href="https://crates.io/crates/proptest"&gt;proptest&lt;/a&gt;) or&amp;nbsp;fuzzing.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_assertion"&gt;Assertion&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;For asserting in tests, most languages provides libraries on top of the &lt;code&gt;assert&lt;/code&gt;
function in order to make it more fluent to write unit tests.  I will cite two
notable examples I&amp;#8217;ve worked with in other languages (but there is much more
libraries out there): &lt;a href="https://joel-costigliola.github.io/assertj/"&gt;AssertJ&lt;/a&gt;
and &lt;a href="https://www.chaijs.com/"&gt;ChaiJS&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Let&amp;#8217;s take a look at some existing libraries in Rust&amp;nbsp;ecosystem.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_difference"&gt;&lt;a href="https://crates.io/crates/difference"&gt;difference&lt;/a&gt;&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This library is specialized in asserting equalities between &lt;code&gt;&amp;amp;str&lt;/code&gt;.  The quality
is quite good and it also show a very nice diff output&amp;#8230;&amp;#8203; but of course, it&amp;#8217;s
only about asserting equality of &lt;code&gt;&amp;amp;str&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_approx"&gt;&lt;a href="https://crates.io/crates/approx"&gt;approx&lt;/a&gt;&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This library is specialized in asserting floating numbers.  Assertion on
floating numbers is not as easy because of rounding errors.  &lt;code&gt;approx&lt;/code&gt; helps in
asserting floating numbers that are almost&amp;nbsp;equals!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_totems"&gt;&lt;a href="https://crates.io/crates/totems"&gt;totems&lt;/a&gt;&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This library is the first with an intuitive yet simple syntax for asserting
things like enum assertions (although only for &lt;code&gt;Result&lt;/code&gt; and &lt;code&gt;Option&lt;/code&gt;), tuples,
and collections.  It&amp;#8217;s pretty simple but effective.  However, a more fluent &lt;span class="caps"&gt;API&lt;/span&gt;
would be&amp;nbsp;nice.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;There hasn&amp;#8217;t been a release in a year and everything has been developed in a
month by one developer.  This is not promising in term of&amp;nbsp;maintenance.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_hamcrest_rust_and_hamcrest2"&gt;&lt;a href="https://github.com/ujh/hamcrest-rust"&gt;hamcrest-rust&lt;/a&gt; and &lt;a href="https://crates.io/crates/hamcrest2"&gt;hamcrest2&lt;/a&gt;&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The former is not maintained anymore, the second being a fork.  &lt;code&gt;hamcrest2&lt;/code&gt; is
the effort of one developer and no release (no commit on the project either) has
been done in the last 6 months.  And also, but that might be a personal
preference of me, writing assertions with Hamcrest is not pleasant: you have to
wrap in parenthesis everything.  See this&amp;nbsp;example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="nd"&gt;assert_that!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;not&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_expecttest"&gt;&lt;a href="https://crates.io/crates/expectest"&gt;expecttest&lt;/a&gt;&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Another very nice and relatively complete library.  However, it seems to me it
has almost the same kind of problems than &lt;code&gt;hamcrest2&lt;/code&gt;, you have to wrap most of
things in parenthesis (although the syntax is slightly better), there is only
one developer and last release has been 7 months ago.  One thing to notice is
that the developer explicitely flagged the project as &lt;em&gt;passively maintained&lt;/em&gt; so
maybe some contributions would revive the&amp;nbsp;project?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_spectral"&gt;&lt;a href="https://crates.io/crates/spectral"&gt;spectral&lt;/a&gt;&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This one provide a more fluent &lt;span class="caps"&gt;API&lt;/span&gt;.  For example, you can write things&amp;nbsp;like:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="rust"&gt;&lt;span class="nf"&gt;assert_that&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="nf"&gt;.has_length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;On top of that, the output failure message is improved to show in a more
structured way the expected and the produced value.  The default printing is not
always easy to&amp;nbsp;read.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This library is actually really close to something I would look for but, there
is few problems with&amp;nbsp;it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;First of all, it&amp;#8217;s far from complete, more assertions functions could be added.
I actually tried to add some more in
&lt;a href="https://github.com/cfrancia/spectral/pull/19"&gt;this &lt;span class="caps"&gt;PR&lt;/span&gt;&lt;/a&gt; but this leads me to
my second&amp;nbsp;point.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The library is not maintained anymore.  Last release was three years ago and
since this crate is owned by the only developer who implemented it, only a fork
seems to be a way forward at this&amp;nbsp;point.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Finally, I don&amp;#8217;t see anything about chaining assertions in this library.  For
example, in &lt;a href="https://assertj.github.io/doc/"&gt;AssertJ&lt;/a&gt;, you can do things like&amp;nbsp;this.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="java"&gt;&lt;span class="n"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"QXNzZXJ0Sg"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;decodedAsBase64&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
	&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;containsExactly&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"AssertJ"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBytes&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="n"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;throwable&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hasMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"top level"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCause&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
	&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hasMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"cause message"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Ideally, something like &lt;code&gt;spectral&lt;/code&gt; is close from what I would look for.  Forking
might be a solution.  I actually started to improve some annoyments I had in a
&lt;a href="https://github.com/woshilapin/spectral/commits/v1.0.0"&gt;branch&lt;/a&gt;.  Much more
functionalities could be added to it.  Here is a non-exhaustive list of&amp;nbsp;things:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;more APIs (take example on other libraries in other&amp;nbsp;languages)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ability to chain&amp;nbsp;calls&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;implement as &lt;em&gt;features&lt;/em&gt; for other libraries (for example, a specific map
implementation like &lt;a href="https://crates.io/crates/vec_map"&gt;vec_map&lt;/a&gt; could
implement &lt;code&gt;HashMapAssertions&lt;/code&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;colorize output error&amp;nbsp;messages&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Of course, I might have missed other libraries.  I mostly used crates.io to
search with only a bunch of&amp;nbsp;keywords.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_sources"&gt;Sources&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://crates.io"&gt;crates.io&lt;/a&gt;, where you can find most of the libraries
from this post (the only exception seems to be &lt;code&gt;hamcrest-rust&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/rust-unofficial/awesome-rust#testing"&gt;Awesome Rust&lt;/a&gt;,
which lists interesting project in Rust, especially the &amp;#8220;Testing&amp;#8221;&amp;nbsp;section&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="footnotes"&gt;
&lt;hr&gt;
&lt;div class="footnote" id="_footnotedef_1"&gt;
&lt;a href="#_footnoteref_1"&gt;1&lt;/a&gt;. There is also &lt;code&gt;benches/&lt;/code&gt; but most of what you need to use it is only available in &lt;em&gt;nightly&lt;/em&gt; Rust, see &lt;a href="https://doc.rust-lang.org/test/bench/index.html"&gt;&lt;code&gt;test::bench&lt;/code&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="rust"></category><category term="test"></category></entry><entry><title>Displaying dates and time in Gnuplot</title><link href="https://hole.tuziwo.info/displaying-dates-and-time-in-gnuplot.html" rel="alternate"></link><published>2014-08-01T00:00:00+02:00</published><updated>2014-08-01T00:00:00+02:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2014-08-01:/displaying-dates-and-time-in-gnuplot.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;When you need to display some specific data in Gnuplot, it may be hard.
However, for dates, it is easy, there is already a&amp;nbsp;functionality.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;For example, if you want to display date and hour base on a timestamp you have
in your data, you can and that is …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;When you need to display some specific data in Gnuplot, it may be hard.
However, for dates, it is easy, there is already a&amp;nbsp;functionality.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;For example, if you want to display date and hour base on a timestamp you have
in your data, you can and that is what I will&amp;nbsp;explain.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_what_we_want"&gt;What we&amp;nbsp;want?&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The log file we want to display contains a abscissa which is a time information
stored as a timestamp (number of seconds since the
&lt;a href="https://en.wikipedia.org/wiki/Unix_epoch"&gt;epoch&lt;/a&gt;).  However, we do not want
that this big number appears on the abscissa axis.  We want the time to be
displayed as &amp;#8220;31/12 12h&amp;#8221; (day and month then only the hour).  Moreover, we want
a axis which have tic every half-day (midnight and&amp;nbsp;midday).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_specify_the_type_of_data"&gt;Specify the type of&amp;nbsp;data&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;First of all, we will specify that the &lt;em&gt;x&lt;/em&gt; axis will display time&amp;nbsp;information.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;set xdata time;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We will now define the format of the input data with the &lt;code&gt;timefmt&lt;/code&gt; option.
Gnuplot use a standard way to describe date and time (try &lt;code&gt;help timefmt&lt;/code&gt; to have
more information).  For us, it is a timestamp so we will use the &lt;code&gt;"%s"&lt;/code&gt; time&amp;nbsp;format.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;set timefmt "%s";&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We also want to format the output time format (the one that will be displayed on
the graphic) with the following:
- &lt;code&gt;%d&lt;/code&gt; for the day
- &lt;code&gt;%m&lt;/code&gt; for the month
- &lt;code&gt;%H&lt;/code&gt; for the&amp;nbsp;hour&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;set format x "%d/%m %Hh";&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Finally, we need to define the interval between to ticks in order to displayed
ticks only on midnight and midday.  For this, we need to make a small&amp;nbsp;calculus.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The timestamp is expressed in seconds.  The interval we are taking to is 12
hours.  So we need to express 12 hours in seconds which is&amp;nbsp;43200.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;set xtics 43200;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Do not forget to use help to find what possibilities you have for time&amp;nbsp;format.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="gnuplot"></category></entry><entry><title>Gnuplot graphic with 2 different scales</title><link href="https://hole.tuziwo.info/gnuplot-graphic-with-2-different-scales.html" rel="alternate"></link><published>2014-08-01T00:00:00+02:00</published><updated>2014-08-01T00:00:00+02:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2014-08-01:/gnuplot-graphic-with-2-different-scales.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Gnuplot is a nice tool to create graphics.  However, sometimes, we need more
specific functionalities we may think Gnuplot does not have.  A deeper look into
Gnuplot functionalities show us that it is a &lt;strong&gt;very&lt;/strong&gt; powerfull&amp;nbsp;tool!&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Yesterday, I needed to create a graphic with 2 curves on it …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Gnuplot is a nice tool to create graphics.  However, sometimes, we need more
specific functionalities we may think Gnuplot does not have.  A deeper look into
Gnuplot functionalities show us that it is a &lt;strong&gt;very&lt;/strong&gt; powerfull&amp;nbsp;tool!&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Yesterday, I needed to create a graphic with 2 curves on it.  The problem is
that the first is below 1000 and the other may be over 5000.  I need a two
scales graphic with one scale on the left and the other scale on the right.  How
do we do that on&amp;nbsp;Gnuplot?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_what_we_want"&gt;What we&amp;nbsp;want?&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;There is 2 datasets that we want to display on the same graphic.  The scale of
the two datasets would be different.  Consequently, we will have a left axis
with different label and tics than the right axis.  Moreover, we will use
different color in order to associate each axis to each curve: red for the left
axis (with the first curve) and blue for the right axis (and the second curve).
Finally, we will hide the legend since the colors should be enough to understand
the&amp;nbsp;datas.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_configure_the_first_part_of_the_graphic"&gt;Configure the first part of the&amp;nbsp;graphic&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The &lt;em&gt;first&lt;/em&gt; part of the graphic is the basic part you would expect from a
graphic: a left scale with a label and&amp;nbsp;tics.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;set yrange [0:1000];
set ylabel "Title on the left";
set ytics 100 nomirror textcolor lt 1;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;First of all, we define the lower and upper bound of the first ordinate curve.
The second point is to set the title of the axis.  Finally, we specify the
number of tics (each 100 units in this case).  For this last step, we also
specify the color of it because we want a red color for the left axis.  The
&lt;code&gt;nomirror&lt;/code&gt; option specify that we want the tics only on the left axis (no
mirrored tics on the right&amp;nbsp;axis).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_configure_the_second_part_of_the_graphic"&gt;Configure the second part of the&amp;nbsp;graphic&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We will do nearly the same for the second graphic.  The only thing to know is
that for each &lt;code&gt;y&amp;lt;something&amp;gt;&lt;/code&gt; option, there is also a &lt;code&gt;y2&amp;lt;something&amp;gt;&lt;/code&gt;
corresponding option for the right&amp;nbsp;axis.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;set y2range [0:8000];
set y2label "Title on the right";
set y2tics 1000 nomirror textcolor lt 3;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Note the change in the color of&amp;nbsp;tics.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_hide_the_legend"&gt;Hide the&amp;nbsp;legend&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Hiding the legend in Gnuplot is easy&amp;#8230;&amp;#8203; as long as you know how the option is&amp;nbsp;called!&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;unset key;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_drawing_the_plots"&gt;Drawing the&amp;nbsp;plots&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To draw the plots, we use the &lt;code&gt;plot&lt;/code&gt; function.  Most of the time, if you want to
draw to curve on the same graphic, that&amp;#8217;s because they have the same dataset in
abscissa.  That&amp;#8217;s mainly imply that all the data are in the same file with
more than 2 columns.  For example, a file like&amp;nbsp;this.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;time	left	right
0.00	100.0	750.0
0.50	150.0	1000.0
1.00	225.0	1500.0
1.50	325.0	2225.0
2.00	450.0	3225.0
2.50	600.0	4500.0
3.00	775.0	6000.0&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In Gnuplot, we can load a multicolumns data file and choose which column to
display on which graphic.  This is how we will plot our data which are stored in
the file &lt;code&gt;data.csv&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;plot \
	"data.csv" using 1:2 linetype 1, \
	"data.csv" using 1:3 linetype 3 axes x1y2&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We give the name of the file to the &lt;code&gt;plot&lt;/code&gt; function.  Then we specify the
columns to use (always the first in this case since it is our abscissa).  We
also change the color of the curve with the &lt;code&gt;linetype&lt;/code&gt; option.  The last
important thing is to specify which axis (and which scale) to use for which
curve (&lt;code&gt;x1y1&lt;/code&gt; is the&amp;nbsp;default).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_bonus_export_as_a_file"&gt;Bonus: export as a&amp;nbsp;file&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To export your Gnuplot result as an image file, you need to add &lt;em&gt;at the
beginning of the script&lt;/em&gt; the following&amp;nbsp;lines.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;set terminal png size 1024,768 enhanced font "Helvetica,20"
set output 'output.png'&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Here is the&amp;nbsp;result.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="images/gnuplot-2-axis.png" alt="Gnuplot graphics with 2 different scales" width="800"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You can find the Gnuplot script &lt;a href="files/gnuplot-2-axis.gnuplot"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="gnuplot"></category></entry><entry><title>Replace multi-lines pattern with sed</title><link href="https://hole.tuziwo.info/replace-multi-lines-pattern-with-sed.html" rel="alternate"></link><published>2014-06-27T00:00:00+02:00</published><updated>2014-06-27T00:00:00+02:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2014-06-27:/replace-multi-lines-pattern-with-sed.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Let&amp;#8217;s define this problem by an example.  This is the kind of text I want to&amp;nbsp;modify.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="c"&gt;&lt;span class="cp"&gt;# include &amp;lt;stdio.h&amp;gt;
&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
	&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello world!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
	&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Version 2.0&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;\
			You can use this program as you want.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
	&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This is …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Let&amp;#8217;s define this problem by an example.  This is the kind of text I want to&amp;nbsp;modify.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="c"&gt;&lt;span class="cp"&gt;# include &amp;lt;stdio.h&amp;gt;
&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
	&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello world!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
	&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Version 2.0&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;\
			You can use this program as you want.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
	&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This is a C program but I want to use &lt;strong&gt;gettext&lt;/strong&gt; to provide translated version of
this program easily.  Usually, the solution is to replace each string by a call
to a function (the string being the key).  I will not enter in details of
&lt;strong&gt;gettext&lt;/strong&gt; here but to resume, we want something like this as the&amp;nbsp;result.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="c"&gt;&lt;span class="cp"&gt;# include &amp;lt;stdio.h&amp;gt;
&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
	&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello world!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
	&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Version 2.0&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;\
				You can use this program as you want.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
	&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Note that each string has been nested into the function &lt;code&gt;_()&lt;/code&gt; wich is the usual
convention for &lt;strong&gt;gettext&lt;/strong&gt;.  If you want the quick solution, go directly to the
end of this&amp;nbsp;article.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_brief_introduction_to_sed"&gt;Brief introduction to &lt;code&gt;sed&lt;/code&gt;&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To understand the explanations that will follow, you must at least understand
the basics from &lt;code&gt;sed&lt;/code&gt;.  You can either read this section but I strongly
encourage to read the official &lt;a href="http://man.cx/sed"&gt;&lt;code&gt;sed&lt;/code&gt; documentation&lt;/a&gt; which
is&amp;nbsp;well-written.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_spaces"&gt;Spaces&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The first thing is that &lt;code&gt;sed&lt;/code&gt; will parse the lines one by one.  Each line parsed
is put inside the &lt;strong&gt;pattern space&lt;/strong&gt;, then actions can be done on it, and finally
the line is&amp;nbsp;printed.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;However, there is also a &lt;strong&gt;hold space&lt;/strong&gt; where you can store informations.  And if
you read the &lt;a href="http://man.cx/sed"&gt;&lt;code&gt;sed&lt;/code&gt; documentation&lt;/a&gt;, you&amp;#8217;ll see that there
is actions which can copy from one space to the other.  This will be fundamental
for the multi-line pattern replacement since &lt;code&gt;sed&lt;/code&gt; is mostly for line-by-line
edition.  Keep that in&amp;nbsp;mind.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_sed_with_a_script_file"&gt;&lt;code&gt;sed&lt;/code&gt; with a script&amp;nbsp;file&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;There is two main way of running &lt;code&gt;sed&lt;/code&gt;.  You can either give arguments to the
command-line or give a &lt;code&gt;sed&lt;/code&gt; script.  For simple commands, you may want to use
command-line since it&amp;#8217;s faster than creating a script file then giving it as an
argument to &lt;code&gt;sed&lt;/code&gt;.  However, for complex commands, you may want to work in a
script file, test it, improve it, correct it.  For example, lets do a simple
replacement/deletion and see how we can run it in one or the other&amp;nbsp;way.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;With command-line, you&amp;#8217;ll do the replacement this&amp;nbsp;way&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="sh"&gt;	&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/PATTERN/TEXTIWANT/'&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'/OTHERPATTERN/d'&lt;/span&gt; my_file.txt&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You can add multiple actions by appending &lt;code&gt;-e&lt;/code&gt; for each new&amp;nbsp;action.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;For the script-file solution, you would create a file &lt;code&gt;my_file.sed&lt;/code&gt; for example
that will contains the&amp;nbsp;actions.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="txt"&gt;	s/PATTERN/TEXTIWANT/
	/OTHERPATTERN/d&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Note that the quotes are not needed in the script file.  Now, you can run the&amp;nbsp;script.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="sh"&gt;	&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; my_file.sed my_file.txt&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_actions_on_target"&gt;Actions on&amp;nbsp;target&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In &lt;code&gt;sed&lt;/code&gt;, most of the possible actions can be restricted to specific lines.  For
example, in the previous section, we used the &lt;code&gt;d&lt;/code&gt; action to delete lines.  This
action has been prefixed with the pattern that should trigger this&amp;nbsp;action.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;n&lt;/em&gt; will look for the &lt;em&gt;n&lt;/em&gt; th line of the input&amp;nbsp;text&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;$&lt;/code&gt; refers to the last line of the input&amp;nbsp;text&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;/PATTERN/&lt;/code&gt; will look for lines containing &lt;code&gt;PATTERN&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You can also select ranges by using 2 of the previous possibilities separated
with a comma.  For example, the following will select and delete any line between a line
containing &lt;code&gt;BPATTERN&lt;/code&gt; and a line containing &lt;code&gt;EPATTERN&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="txt"&gt;	/BPATTERN/,/EPATTERN/d&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_group_actions"&gt;Group&amp;nbsp;actions&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Sometimes, you need to apply more than one action to the same selected line.  In
this case, you can nest the actions into &lt;code&gt;{&lt;/code&gt; and &lt;code&gt;}&lt;/code&gt;.  For example, if between
&lt;code&gt;BPATTERN&lt;/code&gt; and &lt;code&gt;EPATTERN&lt;/code&gt;, there is line you want to delete (line containing
&lt;code&gt;BAR&lt;/code&gt;) and others you want to modify (change &lt;code&gt;PATT&lt;/code&gt; into &lt;code&gt;OUT&lt;/code&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="txt"&gt;	/BPATTERN/,/EPATTERN/ {
		/BAR/d
		s/PATT/OUT/g
	}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_multi_lines_pattern"&gt;Multi-lines&amp;nbsp;pattern&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now, you should have the basics to understand what will follow.  These are the
steps to follow to make it&amp;nbsp;possible:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Print all unconcerned line as it&amp;nbsp;is&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Put the line that contains the beginning of our pattern into the &lt;strong&gt;hold&amp;nbsp;space&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Append all lines that are not the beginning of our pattern into the &lt;strong&gt;hold&amp;nbsp;space&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Operate multiple operations only on our pattern and when the last line of the
pattern is&amp;nbsp;reached&lt;/p&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Copy what&amp;#8217;s in &lt;strong&gt;hold space&lt;/strong&gt; into the &lt;strong&gt;pattern space&lt;/strong&gt; (should contain all the
lines we&amp;nbsp;need)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Do the&amp;nbsp;replacement&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Print the&amp;nbsp;result&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_the_pattern"&gt;The&amp;nbsp;pattern&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The pattern is simple, we know where it begins and when it ends.  The start of
the pattern is &lt;code&gt;/("/&lt;/code&gt; and the end is &lt;code&gt;/");/&lt;/code&gt;.  Our pattern can be defined as a
range of line like the&amp;nbsp;following.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="txt"&gt;	/("/,/");/&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_print_lines_not_in_the_pattern"&gt;Print lines not in the&amp;nbsp;pattern&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We know how to select our pattern.  However, we don&amp;#8217;t know how to select all
lines that &lt;strong&gt;are not&lt;/strong&gt; in the pattern.  &lt;code&gt;sed&lt;/code&gt; provides us a way to do that with
the character &lt;code&gt;!&lt;/code&gt;.  Prefixing an action with this character will apply the
actions on all lines that are not the selected pattern or&amp;nbsp;range.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The action to print the current line is &lt;code&gt;p&lt;/code&gt;.  Printing the lines that are not in
our pattern can be done like the&amp;nbsp;following.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="txt"&gt;	/("/,/");/!p&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_filling_the_hold_space"&gt;Filling the &lt;strong&gt;hold&amp;nbsp;space&lt;/strong&gt;&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To fill the &lt;strong&gt;hold space&lt;/strong&gt;, there is 2 possible actions (there is a third one, &lt;code&gt;x&lt;/code&gt;
but we will not discuss&amp;nbsp;it):&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;h&lt;/code&gt; will replace the &lt;strong&gt;hold space&lt;/strong&gt; with the content of the &lt;strong&gt;pattern space&lt;/strong&gt;
(usually the current&amp;nbsp;line).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;H&lt;/code&gt; will append to the &lt;strong&gt;hold space&lt;/strong&gt; what&amp;#8217;s in the &lt;strong&gt;pattern&amp;nbsp;space&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;When we reach the beginning of our pattern, we will call the &lt;code&gt;h&lt;/code&gt; action.  Else,
we will append the current line to the &lt;strong&gt;hold space&lt;/strong&gt; with &lt;code&gt;H&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="txt"&gt;	/("/h
	/("/!H&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In our example of 7 lnies, the &lt;strong&gt;hold space&lt;/strong&gt; will successively have the following
values (you may use &lt;code&gt;g&lt;/code&gt; then &lt;code&gt;l&lt;/code&gt; to see&amp;nbsp;it).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="olist arabic"&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;# include &amp;lt;stdio.h&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;# include &amp;lt;stdio.h&amp;gt;\nvoid main(int argc, char ** argv) {&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;\tprintf("Hello world!\\n");&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;\tprintf("Version 2.0\\n\&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;\tprintf("Version 2.0\\n\\\n\t\tYou can use this program as you want.\\n");&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;\tprintf("Version 2.0\\n\\\n\t\tYou can use this program as you want.\\n");\n\treturn 0;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;\tprintf("Version 2.0\\n\\\n\t\tYou can use this program as you want.\\n");\n\treturn 0;\n}&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Note that the backslash and the tabulation has been escaped with a&amp;nbsp;backslash.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_do_the_replacement"&gt;Do the&amp;nbsp;replacement&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now, we want do the replacement when the last line of our pattern is reached.
To confine this modification, we first nest all the following operations into
the desired&amp;nbsp;range.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="txt"&gt;	/("/,/");/ {
		...
	}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Then, when we reach the end of our pattern, we create a new block where the
actions will take&amp;nbsp;place.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="txt"&gt;	/("/,/");/ {
		/");/ {
			...
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The actions will be the following.  First, we restore (with &lt;code&gt;g&lt;/code&gt;) the content of the &lt;strong&gt;hold
space&lt;/strong&gt; into the &lt;strong&gt;pattern space&lt;/strong&gt; (where actions take place).  Then we do the
replacement.  And finally, we print the&amp;nbsp;result.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="txt"&gt;	/("/,/");/ {
		/");/ {
			g
			s/(\("[^"]*"\))/(_(\1))/g
			p
		}
	}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_resume"&gt;Resume&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;First, we have the following file &lt;code&gt;main.c&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="c"&gt;&lt;span class="cp"&gt;# include &amp;lt;stdio.h&amp;gt;
&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
	&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello world!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
	&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Version 2.0&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;\
			You can use this program as you want.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
	&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Then we have the &lt;code&gt;main.sed&lt;/code&gt; script.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="txt"&gt;/("/,/");/!p
/("/h
/("/!H
/("/,/");/ {
	/");/ {
		g
		s/(\("[^"]*"\))/(_(\1))/g
		p
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We can run the following&amp;nbsp;command.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="sh"&gt;	&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; main.sed main.c&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Then we should obtain the following&amp;nbsp;result.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="c"&gt;&lt;span class="cp"&gt;# include &amp;lt;stdio.h&amp;gt;
&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
	&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello world!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
	&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Version 2.0&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;\
				You can use this program as you want.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
	&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_references"&gt;References&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://man.cx/sed"&gt;&lt;code&gt;sed&lt;/code&gt; documentation&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A (flashy)
&lt;a href="http://austinmatzko.com/2008/04/26/sed-multi-line-search-and-replace/"&gt;web
page&lt;/a&gt; about multi-lines pattern&amp;nbsp;replacement&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="sed"></category></entry><entry><title>Migrating OwnCloud from SQlite to PostgreSQL</title><link href="https://hole.tuziwo.info/migrating-owncloud-from-sqlite-to-postgresql.html" rel="alternate"></link><published>2014-06-26T00:00:00+02:00</published><updated>2014-06-26T00:00:00+02:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2014-06-26:/migrating-owncloud-from-sqlite-to-postgresql.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;SQLite is not a real database system.  It&amp;#8217;s more like a big file of text.  Using
SQLite to manage any kind of system can be dangerous when your database grows.
The best advise is to loose a bit more time to learn how to set up a real …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;SQLite is not a real database system.  It&amp;#8217;s more like a big file of text.  Using
SQLite to manage any kind of system can be dangerous when your database grows.
The best advise is to loose a bit more time to learn how to set up a real
database system like &lt;a href="https://www.mysql.com/"&gt;MySQL&lt;/a&gt; or
&lt;a href="http://www.postgresql.org/"&gt;PostgreSQL&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;However, sometimes you started with a SQLite database.  Then you may want to
migrate to a real database system.  Let&amp;#8217;s do&amp;nbsp;that.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In this article, a SQLite 3 database &lt;code&gt;owncloud.db&lt;/code&gt; will be migrated into a
PostgreSQL 9.1 database (with username &lt;code&gt;owncloud&lt;/code&gt; and database name &lt;code&gt;owncloud&lt;/code&gt;).
The use case is migrating the database of a instance of OwnCloud 6.0.3 with
basic functionalities.  Some applications have also been installed and the only
noticeable one is &lt;a href="https://github.com/owncloud/news/wiki"&gt;&lt;strong&gt;News&lt;/strong&gt;&lt;/a&gt; (allows you
to subscribe to &lt;span class="caps"&gt;RSS&lt;/span&gt;&amp;nbsp;flux).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_export_the_sqlite_database"&gt;Export the SQLite&amp;nbsp;database&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This is a pretty easy step since &lt;code&gt;sqlite3&lt;/code&gt; tool can give you a dump of your
database as &lt;span class="caps"&gt;SQL&lt;/span&gt; commands.  Let&amp;#8217;s put the output into a file &lt;code&gt;dump.sql&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;sqlite3 owncloud.db .dump &amp;gt; dump.sql&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Seems easy, right?  Let&amp;#8217;s go to the next&amp;nbsp;step.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_import_the_dump_into_postgresql"&gt;Import the dump into&amp;nbsp;PostgreSQL&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_the_nomal_way"&gt;The nomal&amp;nbsp;way&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Since &lt;span class="caps"&gt;SQL&lt;/span&gt; is standard, we can try to feed PostgreSQL with this &lt;code&gt;dump.sql&lt;/code&gt; file
with the following&amp;nbsp;command.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;psql -U owncloud -d owncloud &amp;lt; owncloud.db&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;If it works for you, great!  However, as we will see, each database system&amp;#8230;&amp;#8203;
has its own &lt;span class="caps"&gt;SQL&lt;/span&gt;&amp;nbsp;standard.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_converting_the_dump"&gt;Converting the&amp;nbsp;dump&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;There is a few things to adapt between SQLite and PostgreSQL.  An entry point
can be
&lt;a href="http://stackoverflow.com/questions/4581727/convert-sqlite-sql-dump-file-to-postgresql/4581921#4581921"&gt;this
article&lt;/a&gt; which explains what should be adapted.  Let&amp;#8217;s sum up everything that
should be&amp;nbsp;adapted:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Remove &lt;code&gt;PRAGMA&lt;/code&gt; calls&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Convert &lt;code&gt;DATETIME&lt;/code&gt; into &lt;code&gt;TIMESTAMP&lt;/code&gt; (&lt;code&gt;DATETIME&lt;/code&gt; is for SQLite when &lt;code&gt;TIMESTAMP&lt;/code&gt;
seems to be the one for PostgreSQL, see
&lt;a href="http://www.postgresql.org/docs/current/static/datatype-datetime.html"&gt;documentation&lt;/a&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Remove &lt;code&gt;UNSIGNED&lt;/code&gt; (every integer is unsigned in PostgreSQL, see
&lt;a href="http://www.postgresql.org/docs/current/static/datatype-numeric.html"&gt;documentation&lt;/a&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Remove &lt;code&gt;AUTOINCREMENT&lt;/code&gt; then replace &lt;code&gt;INTEGER&lt;/code&gt; with &lt;code&gt;SERIAL&lt;/code&gt; (&lt;code&gt;SERIAL&lt;/code&gt; is the
autoincrement integer in&amp;nbsp;PostgreSQL)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Convert &lt;code&gt;LONGTEXT&lt;/code&gt; and &lt;code&gt;CLOB&lt;/code&gt; into &lt;code&gt;TEXT&lt;/code&gt; or &lt;code&gt;VARCHAR&lt;/code&gt; (see
&lt;a href="http://www.postgresql.org/docs/current/static/datatype-character.html"&gt;documentation&lt;/a&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Convert &lt;code&gt;BLOB&lt;/code&gt; into &lt;code&gt;BYTEA&lt;/code&gt; (and you might need
&lt;a href="http://stackoverflow.com/questions/3103242/inserting-text-string-with-hex-into-postgresql-as-a-bytea/3103461#3103461"&gt;more
work&lt;/a&gt; for these&amp;nbsp;ones)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Convert boolean values from respectively &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;1&lt;/code&gt; to &lt;code&gt;'0'&lt;/code&gt; and &lt;code&gt;'1'&lt;/code&gt; or
&lt;code&gt;TRUE&lt;/code&gt; and &lt;code&gt;FALSE&lt;/code&gt; (see
&lt;a href="http://www.postgresql.org/docs/current/static/datatype-boolean.html"&gt;documentation&lt;/a&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Except the last 2 points that requires more attention, we can do everything with
&lt;code&gt;sed&lt;/code&gt;.  Let&amp;#8217;s do a &lt;code&gt;sed&lt;/code&gt; script &lt;code&gt;migrate.sed&lt;/code&gt; for automatically adapting our
dump &lt;code&gt;dump.sql&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;# Remove every line starting with `PRAGMA'
/^PRAGMA/d
# Change types only in the scope of a table creation
/^CREATE TABLE/ {
	# Remove `UNSIGNED' keyword and spaces following
	s/\&amp;lt;UNSIGNED\&amp;gt; *//g
	# Replace `DATETIME' type (SQLite) with `TIMESTAMP' type (PostgreSQL)
	s/\&amp;lt;DATETIME\&amp;gt;/TIMESTAMP/g
	# `LONGTEXT' and `CLOB' replaced by `TEXT' (could use `VARCHAR' too)
	s/\&amp;lt;LONGTEXT\|CLOB\&amp;gt;/TEXT/g
	# Replace any integer with `AUTOINCREMENT' with `SERIAL'
	s/\&amp;lt;INTEGER\&amp;gt;\([^,]*\)[ ]*AUTOINCREMENT/SERIAL\1/g
	# Replace `BLOB' with `BYTEA' (binary blob in PostgreSQL)
	s/\&amp;lt;BLOB\&amp;gt;/BYTEA/g
}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Some notes about that&amp;nbsp;script.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonitionblock note"&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td class="icon"&gt;
&lt;div class="title"&gt;Note&lt;/div&gt;
&lt;/td&gt;
&lt;td class="content"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;&lt;code&gt;PRAGMA&lt;/code&gt; are only specific commands specific for the database system.
Obviously, if they have sense for SQLite, they will not for PostgreSQL.  We may
find equivalent `&lt;span class="caps"&gt;PRAGMA&lt;/span&gt;&amp;#8217; commands but I didn&amp;#8217;t&amp;nbsp;investigate.&lt;/p&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div class="admonitionblock note"&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td class="icon"&gt;
&lt;div class="title"&gt;Note&lt;/div&gt;
&lt;/td&gt;
&lt;td class="content"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We want to replace types only for table creation.  For example, we want to avoid
to remove &lt;code&gt;UNSIGNED&lt;/code&gt; everywhere it appears in the file &lt;code&gt;dump.sql&lt;/code&gt; because it may
appears in the contents of the database.  &lt;code&gt;sed&lt;/code&gt; allows us to restrict
modification to only some specific&amp;nbsp;lines.&lt;/p&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div class="admonitionblock note"&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td class="icon"&gt;
&lt;div class="title"&gt;Note&lt;/div&gt;
&lt;/td&gt;
&lt;td class="content"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;&lt;code&gt;AUTOINCREMENT&lt;/code&gt; in SQLite is linked with an integer where in PostgreSQL,
&lt;code&gt;SERIAL&lt;/code&gt; replaces&amp;nbsp;both.&lt;/p&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div class="admonitionblock note"&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td class="icon"&gt;
&lt;div class="title"&gt;Note&lt;/div&gt;
&lt;/td&gt;
&lt;td class="content"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;&lt;code&gt;BLOB&lt;/code&gt; is a binary blob which may need to be decoded with the &lt;code&gt;decode()&lt;/code&gt;
function (something like &lt;code&gt;decode(value,"hex")&lt;/code&gt;).  This can be tricky but see
next sections, you may find some&amp;nbsp;help.&lt;/p&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;After these few notes about the &lt;code&gt;sed&lt;/code&gt; script, let&amp;#8217;s apply&amp;nbsp;it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;sed -f migrate.sed dump.sql &amp;gt; dump-adapted.sql&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_blob_and_boolean_adptations"&gt;&lt;code&gt;BLOB&lt;/code&gt; and &lt;code&gt;BOOLEAN&lt;/code&gt; adptations&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This is a more tricky problem since we will need to replace or encapsulate value
that will be inserted into our database (lines that starts with &lt;code&gt;INSERT INTO&lt;/code&gt;).
For this purpose, I made a &lt;code&gt;awk&lt;/code&gt; script to parse lines with &lt;code&gt;CREATE TABLE&lt;/code&gt; and
transform them, for each table, into &lt;code&gt;sed&lt;/code&gt; replacement command that will target
only the needed field (for example, the third one if the third one is a
boolean, and the fifth one if it&amp;#8217;s a &lt;code&gt;BLOB&lt;/code&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="awk"&gt;&lt;span class="c1"&gt;#!/bin/awk -f&lt;/span&gt;

&lt;span class="c1"&gt;# Before program&lt;/span&gt;
&lt;span class="kr"&gt;BEGIN&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Program&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
	&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"# "&lt;/span&gt; &lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
	&lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
	&lt;span class="nx"&gt;lastpatt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
	&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="kc"&gt;NF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
		&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$k&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;/BLOB|BOOLEAN/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
			&lt;span class="nx"&gt;subin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"\\(^INSERT INTO \042\\?"&lt;/span&gt; &lt;span class="kc"&gt;ENVIRON&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"DB"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="s2"&gt;"\042\\? VALUES("&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
			&lt;span class="nx"&gt;subout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
			&lt;span class="nx"&gt;can_be_null&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
			&lt;span class="nx"&gt;subnum&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
			&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="kc"&gt;NF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
				&lt;span class="nx"&gt;patt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
				&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;!~&lt;/span&gt; &lt;span class="sr"&gt;/KEY/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
					&lt;span class="nx"&gt;subin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;subin&lt;/span&gt; &lt;span class="s2"&gt;","&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
				&lt;span class="p"&gt;}&lt;/span&gt;
				&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;/INTEGER/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
					&lt;span class="nx"&gt;patt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"[[:digit:]]\\+"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
				&lt;span class="p"&gt;}&lt;/span&gt;
				&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;/NUMERIC/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
					&lt;span class="nx"&gt;patt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"[[:digit:].-]\\+"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
				&lt;span class="p"&gt;}&lt;/span&gt;
				&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;/VARCHAR|&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;LONG&lt;/span&gt;&lt;span class="se"&gt;)?&lt;/span&gt;&lt;span class="sr"&gt;TEXT|BLOB/&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
					&lt;span class="nx"&gt;patt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"\047.*\047"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
				&lt;span class="p"&gt;}&lt;/span&gt;
				&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;!~&lt;/span&gt; &lt;span class="sr"&gt;/NOT NULL|KEY/&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
					&lt;span class="nx"&gt;patt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"\\(NULL\\|"&lt;/span&gt; &lt;span class="nx"&gt;patt&lt;/span&gt; &lt;span class="s2"&gt;"\\)"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
					&lt;span class="nx"&gt;subnum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;subnum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
				&lt;span class="p"&gt;}&lt;/span&gt;
				&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;/BLOB/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
					&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
						&lt;span class="nx"&gt;patt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"decode("&lt;/span&gt; &lt;span class="nx"&gt;patt&lt;/span&gt; &lt;span class="s2"&gt;",\047hex\047)"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
					&lt;span class="p"&gt;}&lt;/span&gt;
					&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
						&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;patt&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;/NULL/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
							&lt;span class="nx"&gt;bdecnum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
							&lt;span class="nx"&gt;decnum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;subnum&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
							&lt;span class="nx"&gt;adecnum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;decnum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
							&lt;span class="nx"&gt;patt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"\\)"&lt;/span&gt; &lt;span class="nx"&gt;patt&lt;/span&gt; &lt;span class="s2"&gt;"\\("&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
						&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
							&lt;span class="nx"&gt;bdecnum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
							&lt;span class="nx"&gt;decnum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;subnum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
							&lt;span class="nx"&gt;adecnum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;decnum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
							&lt;span class="nx"&gt;patt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"\\)\\("&lt;/span&gt; &lt;span class="nx"&gt;patt&lt;/span&gt; &lt;span class="s2"&gt;"\\)\\("&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
						&lt;span class="p"&gt;}&lt;/span&gt;
						&lt;span class="nx"&gt;subout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"\\"&lt;/span&gt; &lt;span class="nx"&gt;bdecnum&lt;/span&gt; &lt;span class="s2"&gt;"decode(\\"&lt;/span&gt; &lt;span class="nx"&gt;decnum&lt;/span&gt; &lt;span class="s2"&gt;",\047hex\047)\\"&lt;/span&gt; &lt;span class="nx"&gt;adecnum&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
					&lt;span class="p"&gt;}&lt;/span&gt;
				&lt;span class="p"&gt;}&lt;/span&gt;
				&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;/BOOLEAN/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
					&lt;span class="nx"&gt;patt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"[01]"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
					&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
						&lt;span class="nx"&gt;bdecnum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
						&lt;span class="nx"&gt;decnum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;subnum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
						&lt;span class="nx"&gt;adecnum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;decnum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
						&lt;span class="nx"&gt;patt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"\\)\\("&lt;/span&gt; &lt;span class="nx"&gt;patt&lt;/span&gt; &lt;span class="s2"&gt;"\\)\\("&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
						&lt;span class="nx"&gt;subout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"\\"&lt;/span&gt; &lt;span class="nx"&gt;bdecnum&lt;/span&gt; &lt;span class="s2"&gt;"\047\\"&lt;/span&gt; &lt;span class="nx"&gt;decnum&lt;/span&gt; &lt;span class="s2"&gt;"\047\\"&lt;/span&gt; &lt;span class="nx"&gt;adecnum&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
					&lt;span class="p"&gt;}&lt;/span&gt;
				&lt;span class="p"&gt;}&lt;/span&gt;
				&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;!~&lt;/span&gt; &lt;span class="sr"&gt;/KEY/&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
					&lt;span class="nx"&gt;lastpatt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;patt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
				&lt;span class="p"&gt;}&lt;/span&gt;
				&lt;span class="nx"&gt;subin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;subin&lt;/span&gt; &lt;span class="nx"&gt;patt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
				&lt;span class="nx"&gt;can_be_null&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
			&lt;span class="p"&gt;}&lt;/span&gt;
			&lt;span class="nx"&gt;subin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;subin&lt;/span&gt; &lt;span class="s2"&gt;");$\\)"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
			&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
				&lt;span class="nx"&gt;startpatt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;ENVIRON&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"START_PATT"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
				&lt;span class="nx"&gt;endpatt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lastpatt&lt;/span&gt; &lt;span class="kc"&gt;ENVIRON&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"END_PATT"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
				&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"/"&lt;/span&gt; &lt;span class="nx"&gt;startpatt&lt;/span&gt; &lt;span class="s2"&gt;"/,/"&lt;/span&gt; &lt;span class="nx"&gt;endpatt&lt;/span&gt; &lt;span class="s2"&gt;"/ {"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
				&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"/"&lt;/span&gt; &lt;span class="nx"&gt;startpatt&lt;/span&gt; &lt;span class="s2"&gt;"/h"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
				&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"/"&lt;/span&gt; &lt;span class="nx"&gt;startpatt&lt;/span&gt; &lt;span class="s2"&gt;"/!H"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
				&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"/"&lt;/span&gt; &lt;span class="nx"&gt;endpatt&lt;/span&gt; &lt;span class="s2"&gt;"/ {"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
				&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"g"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
				&lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
			&lt;span class="p"&gt;}&lt;/span&gt;
			&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"s/"&lt;/span&gt; &lt;span class="nx"&gt;subin&lt;/span&gt; &lt;span class="s2"&gt;"/"&lt;/span&gt; &lt;span class="nx"&gt;subout&lt;/span&gt; &lt;span class="s2"&gt;"/g"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
		&lt;span class="p"&gt;}&lt;/span&gt;
	&lt;span class="p"&gt;}&lt;/span&gt;
	&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"p"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
	&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"}"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
	&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"d"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
	&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"}"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# After program&lt;/span&gt;
&lt;span class="kr"&gt;END&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;It&amp;#8217;s a pretty unreadable &lt;code&gt;awk&lt;/code&gt;
and &lt;code&gt;sed&lt;/code&gt; collaboration so you may try to understand only if you needed to.
Otherwise, you may want to try the &lt;code&gt;bash&lt;/code&gt; script I wrote which will run the
&lt;code&gt;awk&lt;/code&gt; script to produce the &lt;code&gt;sed&lt;/code&gt; script then run the &lt;code&gt;sed&lt;/code&gt; script to adapt the
dump&amp;nbsp;file.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="sh"&gt;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="c"&gt;# The original database&lt;/span&gt;
&lt;span class="nv"&gt;SRC_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;owncloud.db
&lt;span class="c"&gt;# A list of SQL commands that should create a copy or the source database&lt;/span&gt;
&lt;span class="nv"&gt;DUMP_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dump.sql
&lt;span class="c"&gt;# A list of `sed` actions to convert the SQLite dump into PostgreSQL&lt;/span&gt;
&lt;span class="nv"&gt;SED_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;migrate.sed
&lt;span class="c"&gt;# Awk program to create sed actions for the BYTEA&lt;/span&gt;
&lt;span class="nv"&gt;AWK_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;migrate.awk

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nv"&gt;$DUMP_FILE&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;then
	&lt;/span&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nv"&gt;$DUMP_FILE&lt;/span&gt;
&lt;span class="k"&gt;fi
if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nv"&gt;$SED_FILE&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;then
	&lt;/span&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nv"&gt;$SED_FILE&lt;/span&gt;
&lt;span class="k"&gt;fi

&lt;/span&gt;sqlite3 &lt;span class="nv"&gt;$SRC_FILE&lt;/span&gt; .dump &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$DUMP_FILE&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;to_sed&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$SED_FILE&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

to_sed &lt;span class="s1"&gt;'#!sed -f'&lt;/span&gt;
to_sed &lt;span class="s1"&gt;'/^PRAGMA/d'&lt;/span&gt;
to_sed &lt;span class="s1"&gt;'/^CREATE TABLE/ {'&lt;/span&gt;
to_sed &lt;span class="s1"&gt;'s/\&amp;lt;UNSIGNED\&amp;gt; *//g'&lt;/span&gt;
to_sed &lt;span class="s1"&gt;'s/\&amp;lt;DATETIME\&amp;gt;/TIMESTAMP/g'&lt;/span&gt;
to_sed &lt;span class="s1"&gt;'s/\&amp;lt;LONGTEXT\&amp;gt;/TEXT/g'&lt;/span&gt;
to_sed &lt;span class="s1"&gt;'s/\&amp;lt;INTEGER\&amp;gt;\([^,]*\)[ ]*AUTOINCREMENT/SERIAL\1/g'&lt;/span&gt;
to_sed &lt;span class="s1"&gt;'s/\&amp;lt;CLOB\&amp;gt;/TEXT/g'&lt;/span&gt;
to_sed &lt;span class="s1"&gt;'s/\&amp;lt;BLOB\&amp;gt;/BYTEA/g'&lt;/span&gt;
to_sed &lt;span class="s1"&gt;'}'&lt;/span&gt;

&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="nv"&gt;$DUMP_FILE&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'^CREATE TABLE.*\&amp;lt;\(BLOB\|BOOLEAN\)\&amp;gt;'&lt;/span&gt;| &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read &lt;/span&gt;LINE
&lt;span class="k"&gt;do
	&lt;/span&gt;&lt;span class="nv"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$LINE&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $3}'&lt;/span&gt; | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'s/"//g'&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"s/'//g"&lt;/span&gt; &lt;span class="si"&gt;)&lt;/span&gt;
	&lt;span class="nv"&gt;START_PATT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'^INSERT INTO "\?\&amp;lt;'&lt;/span&gt;&lt;span class="nv"&gt;$DB&lt;/span&gt;&lt;span class="s1"&gt;'\&amp;gt;"\?'&lt;/span&gt;
	&lt;span class="nv"&gt;END_PATT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;');$'&lt;/span&gt;
	&lt;span class="nb"&gt;export &lt;/span&gt;DB START_PATT END_PATT
	&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$LINE&lt;/span&gt; | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'s/^CREATE TABLE "\?\&amp;lt;'&lt;/span&gt;&lt;span class="nv"&gt;$DB&lt;/span&gt;&lt;span class="s1"&gt;'\&amp;gt;"\? (//g'&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'s/);$//g'&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'s/([^)]*)//g'&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="s1"&gt;' *, *'&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nv"&gt;$AWK_FILE&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$SED_FILE&lt;/span&gt;
&lt;span class="k"&gt;done

&lt;/span&gt;to_sed &lt;span class="s2"&gt;"s/decode(NULL,'hex')/NULL/g"&lt;/span&gt;
to_sed &lt;span class="s1"&gt;'p'&lt;/span&gt;

&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nv"&gt;$SED_FILE&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt;.bak &lt;span class="nv"&gt;$DUMP_FILE&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Remember, you may need these scripts if you have either &lt;code&gt;BOOLEAN&lt;/code&gt; and/or &lt;code&gt;BLOB&lt;/code&gt;.
If not, then you probably don&amp;#8217;t wwant them and just use the simple &lt;code&gt;sed&lt;/code&gt; script
I provided in the previous&amp;nbsp;section.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To conclude to this article, even if I do a lot of research and it tooks me time
to write these scripts, I didn&amp;#8217;t success well in migrating from SQLite to
PostgreSQL.  In the meanwhile, I learned a lot of interesting stuff about &lt;code&gt;awk&lt;/code&gt;
and &lt;code&gt;sed&lt;/code&gt; scripting, about playing with PostgreSQL.  I also learned that you
want probably to use PostgreSQL or MySQL from the start and avoid any migration.
This article may helps you to understand some important things about the
migration process, to find information but it will probably not be enough to
make it well.  It&amp;#8217;s can only be a starting point.  Good&amp;nbsp;luck!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_references"&gt;References&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://stackoverflow.com/questions/4248072/how-to-migrate-from-sqlite-to-postgresql-rails#4248203"&gt;Dumping
SQLite&amp;nbsp;database&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://stackoverflow.com/questions/4581727/convert-sqlite-sql-dump-file-to-postgresql/4581921#4581921"&gt;Migrate
from SQLite to PostgreSQL&lt;/a&gt; with a few useful&amp;nbsp;links:&lt;/p&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://gist.github.com/2253099"&gt;A small migration&amp;nbsp;script&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://www.sqlines.com/postgresql/datatypes/int"&gt;About integers in&amp;nbsp;databases&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://www.sqlines.com/postgresql/datatypes/text"&gt;About text
in&amp;nbsp;databases&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://stackoverflow.com/questions/3103242/inserting-text-string-with-hex-into-postgresql-as-a-bytea/3103461#3103461"&gt;About
&lt;code&gt;BLOB&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="owncloud"></category><category term="sqlite"></category><category term="postgresql"></category></entry><entry><title>Installing Movim on PostgreSQL</title><link href="https://hole.tuziwo.info/installing-movim-on-postgresql.html" rel="alternate"></link><published>2014-06-19T00:00:00+02:00</published><updated>2014-06-19T00:00:00+02:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2014-06-19:/installing-movim-on-postgresql.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Do you know &lt;a href="https://movim.eu/"&gt;Movim&lt;/a&gt;?  You should take a look if you&amp;#8217;re
interesting in social network that are trying to take care of your privacy.
With it, you own your&amp;nbsp;data.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;&lt;span class="caps"&gt;OK&lt;/span&gt;, that&amp;#8217;s great&amp;#8230;&amp;#8203; but that means that you must install it on your server.
Let&amp;#8217;s do …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Do you know &lt;a href="https://movim.eu/"&gt;Movim&lt;/a&gt;?  You should take a look if you&amp;#8217;re
interesting in social network that are trying to take care of your privacy.
With it, you own your&amp;nbsp;data.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;&lt;span class="caps"&gt;OK&lt;/span&gt;, that&amp;#8217;s great&amp;#8230;&amp;#8203; but that means that you must install it on your server.
Let&amp;#8217;s do&amp;nbsp;it!&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Thie article will explain how to install the last unstable version of movim,
0.8alpha12 at this time (but it should work with stable versions too), on a
Debian server runned with Apache 2.  We will use PostgreSQL as the database
management system.  It is mainly based on the
&lt;a href="http://wiki.movim.eu/en:install"&gt;installation guide&lt;/a&gt; of&amp;nbsp;Movim.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_prepare_the_database_management_system"&gt;Prepare the database management&amp;nbsp;system&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;After installing PostgreSQL on the system, we will prepare it.  The goal is to
create one user especially for the Movim web application which will have his own
database and nothing&amp;nbsp;else.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_create_the_movim_user"&gt;Create the &lt;code&gt;movim&lt;/code&gt; user&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;First, connect yourself as the &lt;code&gt;postgres&lt;/code&gt; user which will allow you to send
requests to the PostgreSQL&amp;nbsp;engine.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="sh"&gt;	su - postgres&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Then you should be able to create the user.  Either you enter the PostgreSQL
engine to create the user (and you should find the right &lt;span class="caps"&gt;SQL&lt;/span&gt; command to do it),
or you use the facility &lt;code&gt;createuser&lt;/code&gt;.  We will create a user with no rights to
create database or users and with no superuser rights.  We&amp;#8217;ll put no password
since we will connect from the localhost (see next sections for allowing
connections from localhost).  Adding the &lt;code&gt;--echo&lt;/code&gt; option will allow you to see
what should be the &lt;span class="caps"&gt;SQL&lt;/span&gt; commands to&amp;nbsp;send.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="sh"&gt;	createuser &lt;span class="nt"&gt;--no-createdb&lt;/span&gt; &lt;span class="nt"&gt;--echo&lt;/span&gt; &lt;span class="nt"&gt;--encrypted&lt;/span&gt; &lt;span class="nt"&gt;--inherit&lt;/span&gt; &lt;span class="nt"&gt;--login&lt;/span&gt; &lt;span class="nt"&gt;--no-createrole&lt;/span&gt; &lt;span class="nt"&gt;--no-superuser&lt;/span&gt; movim&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_create_the_movim_database"&gt;Create the &lt;code&gt;movim&lt;/code&gt; database&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;For the Movim web application, a dedicated database, called &lt;code&gt;movim&lt;/code&gt; will be
created.  We must associate it to the user &lt;code&gt;movim&lt;/code&gt; and we will use the a unicode
encoding (see
&lt;a href="http://www.postgresql.org/docs/current/static/multibyte.html#MULTIBYTE-CHARSET-SUPPORTED"&gt;PostgreSQL
documentation&lt;/a&gt;).  To create the database, you can use the &lt;code&gt;createdb&lt;/code&gt; facility.
The last field can be used to add a&amp;nbsp;description.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="sh"&gt;	createdb &lt;span class="nt"&gt;--echo&lt;/span&gt; &lt;span class="nt"&gt;--encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Unicode &lt;span class="nt"&gt;--owner&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;movim movim &lt;span class="s2"&gt;"Movim social network database"&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_giving_correct_rights"&gt;Giving correct&amp;nbsp;rights&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The database and the web application will be hosted on the same server.  We
don&amp;#8217;t need a password for the web application to connect to the database; we
will only trust any connection to the &lt;code&gt;movim&lt;/code&gt; database system from &lt;code&gt;movim&lt;/code&gt; user
on the localhost (see
&lt;a href="http://www.postgresql.org/docs/current/interactive/auth-methods.html#AUTH-TRUST"&gt;PostgreSQL
documentation&lt;/a&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The &lt;a href="https://wiki.debian.org/PostgreSql"&gt;Debian documentation&lt;/a&gt; help to
understand where to begin.  We will edit the file
&lt;code&gt;/etc/postgresql/x.y/main/ph_hba.conf&lt;/code&gt; and add 2 lines (one for IPv4 and one for
IPv6) to allow connection from localhost with &lt;code&gt;movim&lt;/code&gt; user on &lt;code&gt;movim&lt;/code&gt; database.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="txt"&gt;	# DO NOT DISABLE!
	# If you change this first entry you will need to make sure that the
	# database superuser can access the database using some other method.
	# Noninteractive access to all databases is required during automatic
	# maintenance (custom daily cronjobs, replication, and similar tasks).
	#
	# Database administrative login by Unix domain socket
	local   all             postgres                                peer&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;# TYPE  DATABASE        USER            ADDRESS                 METHOD&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;# "local" is for Unix domain socket connections only
local   all             all                                     peer
# IPv4 and IPv6 local connections for Movim
host    movim           movim           127.0.0.1/32            trust
host    movim           movim           ::1/128                 trust
# IPv4 local connections:
host    all             all             127.0.0.1/32            md5
# IPv6 local connections:
host    all             all             ::1/128                 md5&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_bonus"&gt;Bonus&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You may want to see what&amp;#8217;s in the database.  You should connect as the
&lt;code&gt;postgres&lt;/code&gt; user then run &lt;code&gt;psql&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In the PostgreSQL shell, you may try &lt;code&gt;\l&lt;/code&gt; to list all the databases.  Then you
may try other commands considering the
&lt;a href="http://www.postgresql.org/docs/9.3/static/app-psql.html"&gt;documentation&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_installing_movim"&gt;Installing&amp;nbsp;Movim&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You did the hard part, installing Movim is very easy.  First, download it on the
&lt;a href="https://launchpad.net/movim/+download"&gt;website&lt;/a&gt;.  Then unzip it in the
directory yuo want (don&amp;#8217;t forget to create a entry with&amp;nbsp;Apache).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now, you need to configure the database for your Movim instance.  In the
unzipped archive, you&amp;#8217;ll find a &lt;code&gt;config/db.example.inc.php&lt;/code&gt;.  Copy this file in
&lt;code&gt;config/db.inc.php&lt;/code&gt; then edit it.  You should be able to modify it yourself
without explanation (but I will help you, the following&amp;nbsp;file).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="php"&gt;	&lt;span class="o"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="n"&gt;php&lt;/span&gt;
	&lt;span class="c1"&gt;# This is the database configuration of Movim&lt;/span&gt;
	&lt;span class="c1"&gt;# You need to copy an rename this file to 'db.inc.php' and complete the values&lt;/span&gt;
	&lt;span class="nv"&gt;$conf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
		&lt;span class="c1"&gt;# The type can be 'pgsql' or 'mysql'&lt;/span&gt;
		&lt;span class="s1"&gt;'type'&lt;/span&gt;        &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'pgsql'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
		&lt;span class="c1"&gt;# The database username&lt;/span&gt;
		&lt;span class="s1"&gt;'username'&lt;/span&gt;    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'movim'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
		&lt;span class="c1"&gt;# The password&lt;/span&gt;
		&lt;span class="s1"&gt;'password'&lt;/span&gt;    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
		&lt;span class="c1"&gt;# Where can we find the database ?&lt;/span&gt;
		&lt;span class="s1"&gt;'host'&lt;/span&gt;        &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
		&lt;span class="c1"&gt;# The port number, 3306 for MySQL and 5432 for PostGreSQL&lt;/span&gt;
		&lt;span class="s1"&gt;'port'&lt;/span&gt;        &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;5432&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
		&lt;span class="c1"&gt;# The database name&lt;/span&gt;
		&lt;span class="s1"&gt;'database'&lt;/span&gt;    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'movim'&lt;/span&gt;
	&lt;span class="p"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now, you should be able to access your&amp;nbsp;website.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_references"&gt;References&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The official website for &lt;a href="https://movim.eu/"&gt;Movim&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://wiki.movim.eu/en:install"&gt;Installation guide&lt;/a&gt; for&amp;nbsp;Movim&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://www.postgresql.org/docs/current/"&gt;PostgreSQL&amp;nbsp;documentation&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;More hints about PostgreSQL with &lt;a href="https://wiki.debian.org/PostgreSql"&gt;Debian&amp;nbsp;documentation&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="movim"></category><category term="postgresql"></category></entry><entry><title>Generate slides from DocBook</title><link href="https://hole.tuziwo.info/generate-slides-from-docbook.html" rel="alternate"></link><published>2014-06-13T00:00:00+02:00</published><updated>2014-06-13T00:00:00+02:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2014-06-13:/generate-slides-from-docbook.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I&amp;#8217;m a big fan of LaTeX.  However, when it comes to details, LaTeX is not what it
sells you: you can&amp;#8217;t really separate the content from the display when you need
something nicer than the default.  Moreover, the semantic description of parts
of the content in LaTeX …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I&amp;#8217;m a big fan of LaTeX.  However, when it comes to details, LaTeX is not what it
sells you: you can&amp;#8217;t really separate the content from the display when you need
something nicer than the default.  Moreover, the semantic description of parts
of the content in LaTeX can be improved.  But why?  DocBook do the job,&amp;nbsp;right?&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Yes, DocBook seems to do a big part of the job.  However, it is still difficult
to produce documents from DocBook
(&lt;a href="http://xmlgraphics.apache.org/fop/"&gt;&lt;span class="caps"&gt;FOP&lt;/span&gt;&lt;/a&gt;&amp;#8230;&amp;#8203;  seriously, you don&amp;#8217;t want to
use that, it&amp;#8217;s heavy).  You can still produce &lt;span class="caps"&gt;HTML&lt;/span&gt;/&lt;span class="caps"&gt;XHTML&lt;/span&gt; documents but for
reports, you may want &lt;span class="caps"&gt;PDF&lt;/span&gt;.  However, for slides, with a bit of &lt;span class="caps"&gt;CSS&lt;/span&gt; and
JavaScript, it start to be interesting.  Let&amp;#8217;s do something like
&lt;a href="files/slides/docbook-slide-example.xhtml"&gt;that&lt;/a&gt;!&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In this article, we will parse a simple slide (with the DocBook and DocBook
Slides formats) on a Linux, thanks to the &lt;code&gt;xsltproc&lt;/code&gt; (part of the &lt;span class="caps"&gt;XSLT&lt;/span&gt; project
of&amp;nbsp;Gnome).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_get_the_docbook_stylesheets"&gt;Get the DocBook&amp;nbsp;stylesheets&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To generate slides from DocBook format, you first need to get the stylesheets
from the official forge
&lt;a href="http://docbook.sourceforge.net/"&gt;docbook.sourceforge.net&lt;/a&gt;.  You can download
latest snapshots from &lt;strong&gt;snapshots&lt;/strong&gt; menu or directly from
&lt;a href="http://snapshots.docbook.org/"&gt;snapshots.docbook.org&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Download the &lt;code&gt;ns&lt;/code&gt; version (and the &lt;code&gt;doc&lt;/code&gt; if you want) then unzip it somewhere.
We&amp;#8217;ll find everything we need for slides into &lt;code&gt;docbook-xsl-ns-snapshot/slides/&lt;/code&gt;
directory.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_how_it_works"&gt;How it&amp;nbsp;works?&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;First you need to create your DocBook file (&lt;span class="caps"&gt;XML&lt;/span&gt; format).  For slides, an
extension is provided with another namespace which allow you to add a few more
things related to a slides.  It is called DocBook
Slides and the namespace is &lt;code&gt;&lt;a href="http://docbook.org/ns/docbook-slides" class="bare"&gt;http://docbook.org/ns/docbook-slides&lt;/a&gt;&lt;/code&gt;.  Once your
document is created, you need to parse it with an &lt;span class="caps"&gt;XSL&lt;/span&gt; stylesheet to produce your
&lt;span class="caps"&gt;HTML&lt;/span&gt;/&lt;span class="caps"&gt;XHTML&lt;/span&gt; file.  Then, there is a few other details to make it&amp;nbsp;work.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_create_the_document"&gt;Create the&amp;nbsp;document&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;First of all, this is simple DocBook file.  you can use either the DocBook roots
or the specific root from DocBook Slides extension to begin your document.  We
will use the extension&amp;#8217;s root for the &lt;span class="caps"&gt;XML&lt;/span&gt;&amp;nbsp;file.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="xml"&gt;	&lt;span class="cp"&gt;&amp;lt;?xml version='1.0'?&amp;gt;&lt;/span&gt;
	&lt;span class="nt"&gt;&amp;lt;dbs:slides&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://docbook.org/ns/docbook"&lt;/span&gt;
		&lt;span class="na"&gt;xmlns:dbs=&lt;/span&gt;&lt;span class="s"&gt;"http://docbook.org/ns/docbook-slides"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
		...
	&lt;span class="nt"&gt;&amp;lt;/dbs:slides&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Each slide will be enclosed in a &lt;code&gt;&amp;lt;dbs:foil&amp;gt;&lt;/code&gt; element.  For each &lt;code&gt;&amp;lt;dbs:foil&amp;gt;&lt;/code&gt;
element, you can add &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt; then content (you can add a lot of things but we
will make it simple for&amp;nbsp;now).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Let&amp;#8217;s try a simple slide with 3 slides with the file
&lt;a href="files/slides/docbook-slide-example.xml"&gt;&lt;code&gt;docbook-slide-example.xml&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="xml"&gt;&lt;span class="cp"&gt;&amp;lt;?xml version='1.0'?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;dbs:slides&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://docbook.org/ns/docbook"&lt;/span&gt;
		&lt;span class="na"&gt;xmlns:dbs=&lt;/span&gt;&lt;span class="s"&gt;"http://docbook.org/ns/docbook-slides"&lt;/span&gt;
		&lt;span class="na"&gt;xmlns:xlink=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/1999/xlink"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
	&lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Create DocBook slides&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
	&lt;span class="nt"&gt;&amp;lt;dbs:foil&amp;gt;&lt;/span&gt;
		&lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Introduction&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
		&lt;span class="nt"&gt;&amp;lt;para&amp;gt;&lt;/span&gt;This is very simple, you'll see&lt;span class="nt"&gt;&amp;lt;/para&amp;gt;&lt;/span&gt;
	&lt;span class="nt"&gt;&amp;lt;/dbs:foil&amp;gt;&lt;/span&gt;
	&lt;span class="nt"&gt;&amp;lt;dbs:foil&lt;/span&gt; &lt;span class="na"&gt;dbs:incremental=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
		&lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Create itemized list&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
		&lt;span class="nt"&gt;&amp;lt;itemizedlist&amp;gt;&lt;/span&gt;
			&lt;span class="nt"&gt;&amp;lt;listitem&amp;gt;&lt;/span&gt;
				&lt;span class="nt"&gt;&amp;lt;para&amp;gt;&lt;/span&gt;For help...&lt;span class="nt"&gt;&amp;lt;/para&amp;gt;&lt;/span&gt;
			&lt;span class="nt"&gt;&amp;lt;/listitem&amp;gt;&lt;/span&gt;
			&lt;span class="nt"&gt;&amp;lt;listitem&amp;gt;&lt;/span&gt;
				&lt;span class="nt"&gt;&amp;lt;para&amp;gt;&lt;/span&gt;... you can refer to...&lt;span class="nt"&gt;&amp;lt;/para&amp;gt;&lt;/span&gt;
			&lt;span class="nt"&gt;&amp;lt;/listitem&amp;gt;&lt;/span&gt;
			&lt;span class="nt"&gt;&amp;lt;listitem&amp;gt;&lt;/span&gt;
				&lt;span class="nt"&gt;&amp;lt;para&amp;gt;&lt;/span&gt;
					... the official website
					&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt;
						&lt;span class="na"&gt;xlink:href=&lt;/span&gt;&lt;span class="s"&gt;"http://www.docbook.org/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
						DocBook
					&lt;span class="nt"&gt;&amp;lt;/link&amp;gt;&lt;/span&gt;
				&lt;span class="nt"&gt;&amp;lt;/para&amp;gt;&lt;/span&gt;
			&lt;span class="nt"&gt;&amp;lt;/listitem&amp;gt;&lt;/span&gt;
		&lt;span class="nt"&gt;&amp;lt;/itemizedlist&amp;gt;&lt;/span&gt;
	&lt;span class="nt"&gt;&amp;lt;/dbs:foil&amp;gt;&lt;/span&gt;
	&lt;span class="nt"&gt;&amp;lt;dbs:foil&amp;gt;&lt;/span&gt;
		&lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Display source code&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
		&lt;span class="nt"&gt;&amp;lt;para&amp;gt;&lt;/span&gt;Every XML file should start with the following line&lt;span class="nt"&gt;&amp;lt;/para&amp;gt;&lt;/span&gt;
		&lt;span class="nt"&gt;&amp;lt;programlisting&amp;gt;&lt;/span&gt;
			&lt;span class="ni"&gt;&amp;amp;lt;&lt;/span&gt;?xml version='1.0'?&lt;span class="ni"&gt;&amp;amp;gt;&lt;/span&gt;
		&lt;span class="nt"&gt;&amp;lt;/programlisting&amp;gt;&lt;/span&gt;
	&lt;span class="nt"&gt;&amp;lt;/dbs:foil&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dbs:slides&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_parse_the_document"&gt;Parse the&amp;nbsp;document&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Every stylesheet that you can use to generate slides are in
&lt;code&gt;docbook-xsl-ns-snapshot/slides/xhtml/&lt;/code&gt;.  The one we are interested in to create
fun presentation is &lt;code&gt;slidy.xsl&lt;/code&gt;.  The document you want to parse is
&lt;a href="files/slides/docbook-slide-example.xml"&gt;&lt;code&gt;docbook-slide-example.xml&lt;/code&gt;&lt;/a&gt;.  To parse it,
we will use &lt;code&gt;xsltproc&lt;/code&gt; then redirect the output in our &lt;span class="caps"&gt;XHTML&lt;/span&gt;&amp;nbsp;file.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="sh"&gt;	xsltproc &lt;span class="se"&gt;\&lt;/span&gt;
		docbook-xsl-ns-snapshot/slides/xhtml/slidy.xsl &lt;span class="se"&gt;\&lt;/span&gt;
		docbook-slide-example.xml &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; docbook-slide-example.xhtml&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now, you can display the file.  However, you&amp;#8217;ll see nothing spectacular since we
do not furnish the &lt;span class="caps"&gt;CSS&lt;/span&gt; and JavaScript&amp;nbsp;files.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_a_few_more_details"&gt;A few more&amp;nbsp;details&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To complete the creation of our slides, we will need to copy the needed &lt;span class="caps"&gt;CSS&lt;/span&gt; and
JavaScript files into the right directory.  All of these files can be found into
&lt;code&gt;docbook-xsl-ns-snapshot/slides/slidy/&lt;/code&gt;.  This &lt;code&gt;slidy&lt;/code&gt; directory is expected to
be found in a directory called &lt;code&gt;files&lt;/code&gt; next to the &lt;span class="caps"&gt;XHTML&lt;/span&gt; file.  Let&amp;#8217;s copy the&amp;nbsp;directory.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="sh"&gt;	&lt;span class="nb"&gt;mkdir &lt;/span&gt;files/
	&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; docbook-xsl-ns-snapshot/slides/slidy/ files/slidy&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In your directory, you should now see the following file&amp;nbsp;structure.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="txt"&gt;	|
	|-- docbook-slide-example.xhtml
	|-- docbook-slide-example.xml
	|-- docbook-xsl-ns-snapshot
	|   |-- slides
	|   |   |-- ...
	|   |   +-- ...
	|   +-- ...
	+-- files
		+-- slidy
			|-- ...
			+-- ...&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Reload the &lt;span class="caps"&gt;XHTML&lt;/span&gt; file in your browser, you should be able to see the nice slide
template from the &lt;a href="http://www.w3.org/"&gt;&lt;span class="caps"&gt;W3C&lt;/span&gt;&lt;/a&gt;!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_references"&gt;References&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://docbook.sourceforge.net/"&gt;docbook.sourceforge.net&lt;/a&gt;, the official
forge of&amp;nbsp;DocBook&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://snapshots.docbook.org/"&gt;snapshots.docbook.org&lt;/a&gt;, where you can
download snapshots of DocBook&amp;nbsp;stylesheets&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In &lt;code&gt;docbook-xsl-ns-snapshot/slides/doc/&lt;/code&gt;, the file &lt;code&gt;slides.xml&lt;/code&gt; can be
processed with &lt;code&gt;xsltproc&lt;/code&gt; and &lt;code&gt;slidy.xsl&lt;/code&gt; to produce a short&amp;nbsp;documentation.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="docbook"></category></entry><entry><title>Connect Firefox OS device to Arch Linux</title><link href="https://hole.tuziwo.info/connect-firefox-os-device-to-arch-linux.html" rel="alternate"></link><published>2014-03-19T00:00:00+01:00</published><updated>2014-03-19T00:00:00+01:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2014-03-19:/connect-firefox-os-device-to-arch-linux.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Firefox &lt;span class="caps"&gt;OS&lt;/span&gt;, what is that?  If it&amp;#8217;s your question, this article is probably not
for you.  You may take some information on
&lt;a href="https://en.wikipedia.org/wiki/Firefox_OS"&gt;Wikipedia&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now, you know.  So, Firefox &lt;span class="caps"&gt;OS&lt;/span&gt; (or Boot2Gecko or &lt;span class="caps"&gt;B2G&lt;/span&gt;) is developed in &lt;span class="caps"&gt;HTML5&lt;/span&gt; (by
&lt;span class="caps"&gt;HTML5&lt;/span&gt;, I mean &lt;span class="caps"&gt;HTML5&lt;/span&gt;+&lt;span class="caps"&gt;CSS3&lt;/span&gt;+ECMAScript/&lt;span class="caps"&gt;JS&lt;/span&gt;).  This is a …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Firefox &lt;span class="caps"&gt;OS&lt;/span&gt;, what is that?  If it&amp;#8217;s your question, this article is probably not
for you.  You may take some information on
&lt;a href="https://en.wikipedia.org/wiki/Firefox_OS"&gt;Wikipedia&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now, you know.  So, Firefox &lt;span class="caps"&gt;OS&lt;/span&gt; (or Boot2Gecko or &lt;span class="caps"&gt;B2G&lt;/span&gt;) is developed in &lt;span class="caps"&gt;HTML5&lt;/span&gt; (by
&lt;span class="caps"&gt;HTML5&lt;/span&gt;, I mean &lt;span class="caps"&gt;HTML5&lt;/span&gt;+&lt;span class="caps"&gt;CSS3&lt;/span&gt;+ECMAScript/&lt;span class="caps"&gt;JS&lt;/span&gt;).  This is a wonderful opportunity to
develop new applications in a simple langage.  However, to be able to do push
applications on your new smartphone, you need to be able to connect it to your&amp;nbsp;computer.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This article will explain how to connect a smartphone device
(&lt;a href="https://www.geeksphone.com/"&gt;Geeksphone Revolution&lt;/a&gt;) running Firefox &lt;span class="caps"&gt;OS&lt;/span&gt; on
an Arch Linux distribution.  Since the connection is done through the Firefox
browser, I will only consider version of the browser greater than 26.0 which
allow the installation of the last Firefox &lt;span class="caps"&gt;OS&lt;/span&gt; simulator&amp;nbsp;extension.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_the_steps"&gt;The&amp;nbsp;steps&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;There is only a few steps to do.  First of all, you will need to configure your
smartphone to be able to connect it to the computer with a remote debugging.
This article is only about a 1.3 version of Firefox &lt;span class="caps"&gt;OS&lt;/span&gt;, the steps may be
different for an older&amp;nbsp;version.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Then we will configure the computer.  First of all, we need to configure the
hardware part of the computer, then we will configure the software&amp;nbsp;part.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_the_smartphone"&gt;The&amp;nbsp;smartphone&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;For the smartphone, the configuration is pretty simple.  You need to enable the
remote debugging.  Go into the &lt;code&gt;Parameters&lt;/code&gt; menu and find &lt;code&gt;Device Information &amp;gt;
More Information &amp;gt; Developer&lt;/code&gt;.  You should find a &lt;code&gt;Remote debugging&lt;/code&gt; option.  If
it&amp;#8217;s not enabled, check the&amp;nbsp;checkbox.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You should also deactivate the screen locking in &lt;code&gt;Parameters&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_the_computer"&gt;The&amp;nbsp;computer&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_hardware_part"&gt;Hardware&amp;nbsp;part&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;On the web, you&amp;#8217;ll find a lot of website that tells you to install &lt;code&gt;adb&lt;/code&gt; tool,
even on the Mozilla website.  However, it seems that this manipulation is not
needed anymore with the last version of the debugging tools in Firefox browser.
You can only install in your browser the
&lt;a href="https://ftp.mozilla.org/pub/mozilla.org/labs/fxos-simulator/"&gt;&lt;code&gt;ADB Helper&lt;/code&gt;
extension&lt;/a&gt;.  W&amp;#8217;ll see this step in the next&amp;nbsp;section.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;However, you still need to configure &lt;code&gt;udev&lt;/code&gt; to read your &lt;span class="caps"&gt;USB&lt;/span&gt; device.  Edit a
file into &lt;code&gt;/etc/udev/rules.d/&lt;/code&gt;, for example &lt;code&gt;51-firefoxos.rules&lt;/code&gt; and put the
following&amp;nbsp;inside.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="txt"&gt;SUBSYSTEM=="usb", ATTR{idVendor}=="8087", ATTR{idProduct}=="0a16", MODE="0666"&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You may check the &lt;code&gt;idVendor&lt;/code&gt; of your device.  First of all, plug it to your
computer.  Then use &lt;code&gt;lsusb&lt;/code&gt;.  If there is multiple lines, unplug it and type
&lt;code&gt;lsusb&lt;/code&gt;; one line should have disappear, it&amp;#8217;s the one we are interested in.  In
the line, you should see something like the&amp;nbsp;following.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="txt"&gt;Bus 001 Device 007: ID 8087:0a16 Intel Corp.&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In the field &lt;code&gt;8087:0a16&lt;/code&gt;, &lt;code&gt;8087&lt;/code&gt; is the &lt;code&gt;idVendor&lt;/code&gt;.  Save your rule and reload
them with the following command (with root&amp;nbsp;privileges).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="bash"&gt;udevadm control &lt;span class="nt"&gt;--reload-rules&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_the_software_part"&gt;The software&amp;nbsp;part&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;First step in software part is installing last version of Firefox browser on
your desktop (if it&amp;#8217;s not already done)&amp;#8230;&amp;#8203;  Done?  Ok, let&amp;#8217;s&amp;nbsp;continue.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You can now open the &lt;code&gt;App Manager&lt;/code&gt;.  You should find it under &lt;code&gt;Tools &amp;gt; Web
Developer &amp;gt; App Manager&lt;/code&gt;.  At the bottom, you should find a &lt;code&gt;Start Simulator&lt;/code&gt;
button.  Click on it.  If a Firefox &lt;span class="caps"&gt;OS&lt;/span&gt; simulator is already installed, you can
start it now and test a Firefox &lt;span class="caps"&gt;OS&lt;/span&gt; simulator.  You may also add one (click on
&lt;code&gt;Add&lt;/code&gt; button and follow the instructions); but that&amp;#8217;s not the subject of this
article.  We want to launch the remote debugging on the smartphone&amp;nbsp;device.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;When you clicked on the &lt;code&gt;Add&lt;/code&gt; button above (if you didn&amp;#8217;t, now you should!),
you&amp;#8217;ll see a link to install the simulators (a big green button with &lt;code&gt;Install
Simulator&lt;/code&gt;), at least at the day I&amp;#8217;m writing this article.  Click on it.  It
will propose you to install the simulators (but you already did it before) &lt;strong&gt;and&lt;/strong&gt;
an extensions called &lt;code&gt;ADB Helper&lt;/code&gt; (remember, I already talked about it in the
hardware part).  Install&amp;nbsp;it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I think now you should see your connected device with a button next to the button
to start the simulator.  If not, try to restart your browser at&amp;nbsp;least.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_possible_errors"&gt;Possible&amp;nbsp;errors&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_get_in_the_app_manager"&gt;Get &lt;code&gt;????????????&lt;/code&gt; in the &lt;code&gt;App Manager&lt;/code&gt;&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;When you connect your smartphone device, the new button appearing in the &lt;code&gt;App
Manager&lt;/code&gt; you should display characters and numbers (for example,
&lt;code&gt;Clovertrail5B2040C1&lt;/code&gt; in my case).  However, at the beginning of my
experimentations, it displayed &lt;code&gt;????????????&lt;/code&gt; and I was unable to start the
remote&amp;nbsp;debugging.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;If you have &lt;code&gt;adb&lt;/code&gt; installed (see below), you also may try &lt;code&gt;adb devices&lt;/code&gt; to see a
similar result &lt;code&gt;???????????? no permissions&lt;/code&gt;.  From what I understand, it&amp;#8217;s
mainly a authorization problem and depends only of the &lt;code&gt;udev&lt;/code&gt; rule so trying to
write correctly this rule should make your problem disappear.  Looking for
information about that on the web, you may find rules that adds (at the end of
the line) &lt;code&gt;OWNER&lt;/code&gt; or &lt;code&gt;GROUP&lt;/code&gt;.  Be careful to be the right user or in the right
group if you use&amp;nbsp;that.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_force_reloading_of_udev_rules"&gt;Force reloading of &lt;code&gt;udev&lt;/code&gt; rules&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;If the reloading of &lt;code&gt;udev&lt;/code&gt; rules, you may try to force to reload your own rules
with the following command (with root&amp;nbsp;privileges).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="bash"&gt;udevadm trigger&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_installing_adb_tools"&gt;Installing &lt;code&gt;adb&lt;/code&gt; tools&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I didn&amp;#8217;t find a nice way to install &lt;code&gt;adb&lt;/code&gt; tools.  These are the 2 methods I
found for Arch&amp;nbsp;Linux.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect3"&gt;
&lt;h4 id="_using_yaourt"&gt;Using &lt;code&gt;yaourt&lt;/code&gt;&lt;/h4&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The simplest way is to install the package &lt;code&gt;android-sdk-platform-tools&lt;/code&gt;.
However, even if the package is highly ranked on &lt;span class="caps"&gt;AUR&lt;/span&gt;, I&amp;#8217;m not really fond of
installing package through &lt;code&gt;yaourt&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect3"&gt;
&lt;h4 id="_installing_adb_from_android_website"&gt;Installing &lt;code&gt;adb&lt;/code&gt; from Android&amp;nbsp;website&lt;/h4&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You can download the
&lt;a href="http://developer.android.com/sdk/index.html#download"&gt;Android Developer
toolkit&lt;/a&gt;.  This is an archive; uncompress it.  However, they move the &lt;code&gt;adb&lt;/code&gt;
tool in this version of the toolkit (see &lt;code&gt;tools/adb_has_moved.txt&lt;/code&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Considering the file &amp;#8216;&lt;span class="caps"&gt;SDK&lt;/span&gt; &lt;span class="caps"&gt;README&lt;/span&gt;.txt&amp;#8217;, you should launch &lt;code&gt;tools/android&lt;/code&gt; from
the root of the uncompress archive.  You&amp;#8217;ll see different packages you can
install.  Select &lt;code&gt;Android SDK Platform-tools&lt;/code&gt; and install&amp;nbsp;it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;If it&amp;#8217;s not enough, you can also update the toolkit by running the following
command from the root of the uncompress directory.  However, it will download
everything and more (around &lt;span class="caps"&gt;10GB&lt;/span&gt; of data to&amp;nbsp;download).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="bash"&gt;tools/android update sdk &lt;span class="nt"&gt;--no-ui&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now, you should have &lt;code&gt;adb&lt;/code&gt; in &lt;code&gt;platform-tools/adb&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To use it, try first this command when your smartphone device is&amp;nbsp;plugged.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="bash"&gt;platform-tools/adb devices&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;If you have the error message &lt;code&gt;???????????? no permissions&lt;/code&gt;, then try the
following (sometimes it&amp;nbsp;works).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="bash"&gt;platform-tools/adb kill-server
platform-tools/adb devices&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_references"&gt;References&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/Firefox_OS/Debugging/Connecting_a_Firefox_OS_device_to_the_desktop"&gt;&lt;span class="caps"&gt;MDN&lt;/span&gt;&lt;/a&gt;
is the first point of reference for everything concerning Firefox &lt;span class="caps"&gt;OS&lt;/span&gt;; for the
hardware part, it will sometimes redirect you to Android&amp;nbsp;documentation&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://wiki.archlinux.org/index.php/Android#Connecting_to_a_real_device_-&lt;em&gt;Android_Debug_Bridge&lt;/em&gt;.&lt;span class="caps"&gt;28ADB&lt;/span&gt;.29&amp;#8221;&gt;Help
to connect Android devices&lt;/a&gt; on the Arch Linux&amp;nbsp;website&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="b2g"></category></entry><entry><title>Screen backlight problem after suspend on Arch</title><link href="https://hole.tuziwo.info/screen-backlight-problem-after-suspend-on-arch.html" rel="alternate"></link><published>2014-03-04T00:00:00+01:00</published><updated>2014-03-04T00:00:00+01:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2014-03-04:/screen-backlight-problem-after-suspend-on-arch.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;On Arch, it seems that there are often problems with the screen backlight.  For
example, I had a problem when suspending my computer with an almost discharged
battery.  When I plugged my computer, it was fully discharged.  Trying to
restart it from suspend didn&amp;#8217;t display something on my …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;On Arch, it seems that there are often problems with the screen backlight.  For
example, I had a problem when suspending my computer with an almost discharged
battery.  When I plugged my computer, it was fully discharged.  Trying to
restart it from suspend didn&amp;#8217;t display something on my screen.  Let me explain
all the details of this&amp;nbsp;problem.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_environment"&gt;Environment&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;First of all, let me describe the environment where it happens.  I am using a
&lt;span class="caps"&gt;ASUS&lt;/span&gt; &lt;span class="caps"&gt;N750JV&lt;/span&gt; computer, with Arch Linux installed on it.  My graphic card is an
Intel; this is the result of &lt;code&gt;lspci&lt;/code&gt; for the Intel&amp;nbsp;card.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="txt"&gt;VGA compatible controller: Intel Corporation 4th Gen Core Processor Integrated Graphics Controller (rev 06)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_description_of_the_problem"&gt;Description of the&amp;nbsp;problem&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I was using my computer on battery and reaching around 5% of battery charge, I
decided to suspend my computer by closing it.  I don&amp;#8217;t really know what kind of
program do the suspend by default on Arch Linux with&amp;nbsp;Gnome.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;However, before I can plugged my computer, the battery fully discharge.  In an
ideal case, the computer would have detected that it has only a few minutes to
shutdown in a clean way.  But I am not really sure that Arch (or Gnome, I don&amp;#8217;t
really know which component should be in charge of this) is doing it&amp;nbsp;right.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;When I tried to reboot the computer, the screen never shows me anything.  After
a few try to hard reboot (holding the power button then reboot), I&amp;nbsp;resigned.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_the_computer_is_started"&gt;The computer is&amp;nbsp;started&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;However, I discovered something interesting, the computer seems to start; I had the
first initializations steps displayed.  After these steps, the screen shutdown.
Based on the assumption that the computer is started and that only the screen
didn&amp;#8217;t work, I tried to blindly connect my session then run a terminal then try
to reboot.  And it&amp;nbsp;works!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_temporary_solution"&gt;Temporary&amp;nbsp;solution&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;That&amp;#8217;s a good news, because I can try to fix it, even if it&amp;#8217;s blindly.  I tried
a lot of things I found on Internet to switch on backlight with no&amp;nbsp;success.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The only final idea I had was: &amp;#8220;I may try to restart properly the suspend
procedure&amp;#8221;.  So instead of trying to swith on the screen backlight, I tried to
suspend my computer in &lt;span class="caps"&gt;CLI&lt;/span&gt; because I suspected than my problem came from a bad
restart after the&amp;nbsp;suspend.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;sudo systemctl suspend&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The computer effectively suspended, the hard drive stopped, it works!  Now,
typing space to restart it&amp;#8230;&amp;#8203; and&amp;#8230;&amp;#8203; magic!  The screen came back to&amp;nbsp;life.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;However, first thing I tried is to close my computer then open it to check if it
works well.  That&amp;#8217;s a deception because, I&amp;#8217;m back to my initial problem.  Trying
to reboot it: same problem.  This solution is only a temporary solution to debug
but the problem is still&amp;nbsp;there.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_the_solution"&gt;The&amp;nbsp;solution&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now, I&amp;#8217;m pretty sure that it&amp;#8217;s a only a problem of my screen backlight.  I then
looked the specific Arch wiki page about
&lt;a href="https://wiki.archlinux.org/index.php/Backlight"&gt;backlight&lt;/a&gt;.  And the
solution is in the &lt;code&gt;brightness&lt;/code&gt; file.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;There is a &lt;code&gt;brightness&lt;/code&gt; file under &lt;code&gt;/sys/class/backlight&lt;/code&gt;.  This brightness only
contains a number with the intensity of the brightness of the screen.  I have
three different subdirectories in the &lt;code&gt;backlight&lt;/code&gt; directory so I checked the
&lt;code&gt;brightness&lt;/code&gt; file in each of them (&lt;code&gt;acpi_video0&lt;/code&gt;, &lt;code&gt;acpi_video1&lt;/code&gt; and
&lt;code&gt;intel_backlight&lt;/code&gt;).  And the one in &lt;code&gt;acpi_video1&lt;/code&gt; was containing the value &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;At this stage, be careful because you can&amp;#8217;t just put any value in this file
without knowing what the maximum value.  In the same folder than your
&lt;code&gt;brightness&lt;/code&gt; file, you should find the &lt;code&gt;max_brightness&lt;/code&gt; file which contains the
maximum allowed value.  For example, for my &lt;code&gt;acpi_video1&lt;/code&gt; directory, it&amp;#8217;s &lt;code&gt;100&lt;/code&gt;
but for my &lt;code&gt;intel_backlight&lt;/code&gt; directory, it&amp;#8217;s &lt;code&gt;5273&lt;/code&gt;.  Now, you can replace the
value in the &lt;code&gt;brightness&lt;/code&gt; file.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="bash"&gt;&lt;span class="nb"&gt;echo &lt;/span&gt;100 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /sys/class/backlight/acpi_video1/brightness&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_bonus"&gt;Bonus&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_check_you_computer_is_started"&gt;Check you computer is&amp;nbsp;started&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;That&amp;#8217;s something I didn&amp;#8217;t tested, because I was lacking the tools.  There is two
ways I&amp;nbsp;learned.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The first one is easy, you just plug another screen on &lt;span class="caps"&gt;VGA&lt;/span&gt;/&lt;span class="caps"&gt;DVI&lt;/span&gt;/DisplayPort.  If
it works, it&amp;#8217;s a proof that your computer is started.  However, it doesn&amp;#8217;t work,
it doesn&amp;#8217;t proove anything; it&amp;#8217;s possibly one of the endless problem of
connecting a second screen on&amp;nbsp;Linux!&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;A more tricky one is using a light.  The hypothesis is that your screen is
working, the only thing that is not working is the backlight of the screen.  In
a black room, using the light with the right angle on your screen, you should
see the &lt;span class="caps"&gt;LCD&lt;/span&gt; pixels displaying&amp;nbsp;things.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_references"&gt;References&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://wiki.archlinux.org/index.php/Backlight"&gt;Backlight page for Arch&amp;nbsp;Linux&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="archlinux"></category><category term="suspend"></category><category term="asus"></category><category term="graphic"></category></entry><entry><title>Transform portrait to squared image by filling</title><link href="https://hole.tuziwo.info/transform-portrait-to-squared-image-by-filling.html" rel="alternate"></link><published>2014-03-04T00:00:00+01:00</published><updated>2014-03-04T00:00:00+01:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2014-03-04:/transform-portrait-to-squared-image-by-filling.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This is my problem.  I have a photo (&lt;code&gt;portrait.png&lt;/code&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="images/portrait.png" alt="Portrait" height="400"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;From this photo, I need a squared image.  However, taking the largest possible
croping, this is what I can&amp;nbsp;get.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="images/portrait.crop.png" alt="Portrait cropped" height="400"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Of course, I don&amp;#8217;t want the face to be cropped like this.  The following
article is presented one …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This is my problem.  I have a photo (&lt;code&gt;portrait.png&lt;/code&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="images/portrait.png" alt="Portrait" height="400"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;From this photo, I need a squared image.  However, taking the largest possible
croping, this is what I can&amp;nbsp;get.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="images/portrait.crop.png" alt="Portrait cropped" height="400"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Of course, I don&amp;#8217;t want the face to be cropped like this.  The following
article is presented one possible solution to get something like this&amp;nbsp;picture.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="images/portrait.squared.png" alt="Portrait squared" height="400"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In this article, we will only use &lt;a href="http://www.imagemagick.org/"&gt;ImageMagick&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_explain_the_procedure"&gt;Explain the&amp;nbsp;procedure&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To create a squared version of the portrait, I will extend the original picture
by adding borders on left and right.  Of course, I don&amp;#8217;t want simple white
borders so I will fill these borders; to do this, I will blur the current border
of the picture (mainly green) with a blurred&amp;nbsp;effect.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;However, if I keep the existing picture as it is and add fuzzy colors in the
borders, I will see the boundary between the center part of the image
(containing the face) and the borders (only made of blurred colors).  To avoid
this virtual border, we will create borders with an increasing blurred effect as
we go from the center of the image to the left and right borders.  Of course,
not exactly from the center since we need to keep the very center of the image
(the one which contains the face) not&amp;nbsp;blurred.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To process this blur effect, we will use a mask which will give the intensity of
the blur for each pixel of the&amp;nbsp;image.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_creating_a_mask"&gt;Creating a&amp;nbsp;mask&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The mask will be a black and white image, white telling us that we want the
maximum blur effect for this pixel and black telling us that we do not want any
blur on this pixel.  Basically, we want black on the important part of the
visage then a black to white gradient as we go to the left and right&amp;nbsp;borders.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_determine_the_parameters_of_the_gradient"&gt;Determine the parameters of the&amp;nbsp;gradient&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We will build it step by step.  First, we need to define the size of our image
to define the size of the gradients.  &lt;code&gt;identify&lt;/code&gt; will do the&amp;nbsp;job.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="bash"&gt;identify portrait.png&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Which results in the following&amp;nbsp;informations.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="txt"&gt;portrait.png PNG 1111x1400 1111x1400+0+0 8-bit sRGB 1.854MB 0.000u 0:00.000&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We will make a &lt;code&gt;1400x1400&lt;/code&gt; squared image.  This means that we will add 289
pixels on the left/right of the image (the half of it, 144.5 pixels, for each&amp;nbsp;side).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To add borders , we can use the following&amp;nbsp;method.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonitionblock note"&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td class="icon"&gt;
&lt;div class="title"&gt;Note&lt;/div&gt;
&lt;/td&gt;
&lt;td class="content"&gt;
&lt;div class="title"&gt;About the transparency&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We will add transparent borders for the display but for the
purpose of the mask, it is not required since all we be erased with black and
white.  All transparent parts in the image have been displayed as a checkerboard
pattern in order to clearly identify it.  The method is the&amp;nbsp;following:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="bash"&gt;convert your_image.png &lt;span class="se"&gt;\&lt;/span&gt;
	&lt;span class="nt"&gt;-size&lt;/span&gt; 1400x1400 &lt;span class="se"&gt;\&lt;/span&gt;
	pattern:checkerboard &lt;span class="se"&gt;\&lt;/span&gt;
	&lt;span class="nt"&gt;-compose&lt;/span&gt; dstover &lt;span class="se"&gt;\&lt;/span&gt;
	&lt;span class="nt"&gt;-composite&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
	your_image_with_checkerboard.png&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="bash"&gt;convert portrait.png &lt;span class="se"&gt;\&lt;/span&gt;
	&lt;span class="nt"&gt;-bordercolor&lt;/span&gt; none &lt;span class="se"&gt;\&lt;/span&gt;
	&lt;span class="nt"&gt;-border&lt;/span&gt; 144.5x0 &lt;span class="se"&gt;\&lt;/span&gt;
	portrait.borders.png&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="images/portrait.borders.png" alt="Portrait with borders" height="400"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Then we need to define the limit where we can begin the gradient.  I choose the
250 pixels on each side as in the following&amp;nbsp;image.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="images/portrait.masklimits.png" alt="Portrait with the limits to create the mask" height="400"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_building_a_one_side_gradient"&gt;Building a one side&amp;nbsp;gradient&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I can now begin to create the gradient.  I will create the right gradient&amp;nbsp;first.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="bash"&gt;convert &lt;span class="se"&gt;\&lt;/span&gt;
	&lt;span class="nt"&gt;-size&lt;/span&gt; 1400x1400 &lt;span class="se"&gt;\&lt;/span&gt;
	xc: &lt;span class="se"&gt;\&lt;/span&gt;
	&lt;span class="nt"&gt;-sparse-color&lt;/span&gt; Barycentric &lt;span class="s1"&gt;'1150.0,0 black %w,0 white'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
	mask.gradient.right.png&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="images/mask.gradient.right.png" alt="Mask gradient (right part)" height="400"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Then for the left gradient, we can just rotate&amp;nbsp;it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="bash"&gt;convert &lt;span class="se"&gt;\&lt;/span&gt;
	mask.gradient.right.png &lt;span class="se"&gt;\&lt;/span&gt;
	&lt;span class="nt"&gt;-rotate&lt;/span&gt; 180 &lt;span class="se"&gt;\&lt;/span&gt;
	mask.gradient.left.png&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="images/mask.gradient.left.png" alt="Mask gradient (left part)" height="400"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Then to obtain the final mask, you combine the two&amp;nbsp;parts.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="bash"&gt;convert &lt;span class="se"&gt;\&lt;/span&gt;
	mask.gradient.right.png &lt;span class="se"&gt;\&lt;/span&gt;
	mask.gradient.left.png &lt;span class="se"&gt;\&lt;/span&gt;
	&lt;span class="nt"&gt;-compose&lt;/span&gt; lighten &lt;span class="se"&gt;\&lt;/span&gt;
	&lt;span class="nt"&gt;-composite&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
	mask.png&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="images/mask.png" alt="Mask" height="400"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_fill_the_image"&gt;Fill the&amp;nbsp;image&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We now have the mask, we will use it on our image to produce the desired result.
Of course, we will apply it on the squared version of our image, the previous
&lt;code&gt;portrait.borders.png&lt;/code&gt; file.  To blur the image considering the mask, we will
use the &lt;code&gt;blur&lt;/code&gt; option from &lt;code&gt;-compose&lt;/code&gt;.  This option can take an argument, the
same kind of argument that the &lt;code&gt;-blur&lt;/code&gt; option takes (the intensity of the
blurred effect).  In our case, the intensity should be enough high to reach the
borders of the image.  Remember, the blur effect is an operation that take, for
each pixel, an average color of all the pixels around; what I mean by the
&lt;em&gt;intensity&lt;/em&gt; of the blur effect is the diameter (in number of pixel) of the
circle where we do this&amp;nbsp;average.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Let&amp;#8217;s try with a arbitrary value:&amp;nbsp;24.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="bash"&gt;convert &lt;span class="se"&gt;\&lt;/span&gt;
	portrait.borders.png &lt;span class="se"&gt;\&lt;/span&gt;
	mask.png &lt;span class="se"&gt;\&lt;/span&gt;
	&lt;span class="nt"&gt;-compose&lt;/span&gt; blur &lt;span class="se"&gt;\&lt;/span&gt;
	&lt;span class="nt"&gt;-set&lt;/span&gt; option:compose:args 24 &lt;span class="se"&gt;\&lt;/span&gt;
	&lt;span class="nt"&gt;-composite&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
	portrait.blur24.png&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="images/portrait.blur24.png" alt="Portrait with a low blur intensity" height="400"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;It seems that it&amp;#8217;s not sufficient, and it already took a long time to generate
the image&amp;#8230;&amp;#8203;  Wait!  We forget something.  It&amp;#8217;s an average of colors but we have
only transparent colors on the borders.  So there is probably pixels in this
image that have a blurred colored corresponding to the image but with a majority
of transparent color: we do not see it.  To only keep the &lt;span class="caps"&gt;RGB&lt;/span&gt; color (which is
the meaningfull information in our picture), we will just remove the
transparency in the image (deactivate the alpha&amp;nbsp;channel).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="bash"&gt;convert &lt;span class="se"&gt;\&lt;/span&gt;
	portrait.blur24.png &lt;span class="se"&gt;\&lt;/span&gt;
	&lt;span class="nt"&gt;-alpha&lt;/span&gt; off &lt;span class="se"&gt;\&lt;/span&gt;
	portrait.blur24.rgb.png&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="images/portrait.blur24.rgb.png" alt="Portrait with a low blur intensity and no transparency" height="400"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;There is clearly a problem.  The size of our blurred effect was so small that
the pixels on the extrems didn&amp;#8217;t beneficied of any color.  We need to increase
the value of our argument.  This time, we will apply the blurred effect and
remove the transparency in one&amp;nbsp;operation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="bash"&gt;convert &lt;span class="se"&gt;\&lt;/span&gt;
	portrait.borders.png &lt;span class="se"&gt;\&lt;/span&gt;
	mask.png &lt;span class="se"&gt;\&lt;/span&gt;
	&lt;span class="nt"&gt;-compose&lt;/span&gt; blur &lt;span class="se"&gt;\&lt;/span&gt;
	&lt;span class="nt"&gt;-set&lt;/span&gt; option:compose:args 48 &lt;span class="se"&gt;\&lt;/span&gt;
	&lt;span class="nt"&gt;-composite&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
	&lt;span class="nt"&gt;-alpha&lt;/span&gt; on &lt;span class="se"&gt;\&lt;/span&gt;
	portrait.squared.png&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="images/portrait.squared.png" alt="Final squared portrait" height="400"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We finally have it, the squared&amp;nbsp;portrait.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_references"&gt;References&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://www.imagemagick.org/"&gt;ImageMagick website&lt;/a&gt;, the only good reference
to use&amp;nbsp;ImageMagick&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="imagemagick"></category></entry><entry><title>Display notifications with IRSSI</title><link href="https://hole.tuziwo.info/display-notifications-with-irssi.html" rel="alternate"></link><published>2014-01-17T00:00:00+01:00</published><updated>2014-01-17T00:00:00+01:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2014-01-17:/display-notifications-with-irssi.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Since a few months now, I used &lt;code&gt;irssi&lt;/code&gt; as my &lt;span class="caps"&gt;IRC&lt;/span&gt; client.  I like it because it
is highly configurable and because it&amp;#8217;s
&lt;a href="https://en.wikipedia.org/wiki/Cli"&gt;&lt;span class="caps"&gt;CLI&lt;/span&gt;&lt;/a&gt;.  However, one thing is a bit
annoying about &lt;code&gt;irssi&lt;/code&gt;: it has no notifications when somebody talk to me.
Either it is some ping on …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Since a few months now, I used &lt;code&gt;irssi&lt;/code&gt; as my &lt;span class="caps"&gt;IRC&lt;/span&gt; client.  I like it because it
is highly configurable and because it&amp;#8217;s
&lt;a href="https://en.wikipedia.org/wiki/Cli"&gt;&lt;span class="caps"&gt;CLI&lt;/span&gt;&lt;/a&gt;.  However, one thing is a bit
annoying about &lt;code&gt;irssi&lt;/code&gt;: it has no notifications when somebody talk to me.
Either it is some ping on a public chan or a private message, if I don&amp;#8217;t check
my terminal, I can&amp;#8217;t know if somebody needs&amp;nbsp;me.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;However, another strength of &lt;code&gt;irssi&lt;/code&gt; is that is can be extended with plugins.  I
will propose an extension to send notification through &lt;code&gt;libnotify&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_the_plugin"&gt;The&amp;nbsp;plugin&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To begin, I only used the plugin proposed by
&lt;a href="http://www.leemhuis.info/"&gt;Thorsten Leemhuis&lt;/a&gt; called
&lt;a href="http://www.leemhuis.info/files/fnotify/fnotify"&gt;&lt;code&gt;fnotify&lt;/code&gt;&lt;/a&gt;.  On &lt;code&gt;irssi&lt;/code&gt;, it
is very easy to use a existing plugin.  You need to put the Perl file
&lt;code&gt;fnotify.pl&lt;/code&gt; into your &lt;code&gt;~/.irssi/scripts/&lt;/code&gt; directory.  Note that it seems it
must have the &lt;code&gt;.pl&lt;/code&gt; extension to be loaded.  Once it&amp;#8217;s done, you can simply load
the plugin into &lt;code&gt;irssi&lt;/code&gt; doing the following command in an opened instance of
&lt;code&gt;irssi&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;/script load fnotify&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_automatically_load_the_plugin"&gt;AUtomatically load the&amp;nbsp;plugin&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To load this plugin each time &lt;code&gt;irssi&lt;/code&gt; is started, you must copy your plugin into
&lt;code&gt;~/.irssi/scripts/autorun/&lt;/code&gt;.  You may create a symbolic link&amp;nbsp;too.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;ln -s ~/.irssi/scripts/fnotify.pl ~/.irssi/scripts/autorun/fnotify.pl&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_modifying_the_plugin_to_send_notifications"&gt;Modifying the plugin to send&amp;nbsp;notifications&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The plugin is only catching the highlights and private message to print them
into the file &lt;code&gt;~/.irssi/fnotify&lt;/code&gt;.  To send notifications, we will use the
&lt;code&gt;libnotify&lt;/code&gt; library which provide the &lt;code&gt;notify-send&lt;/code&gt; command.  To call that
command into our Perl script, we will use the &lt;code&gt;system&lt;/code&gt; function.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To make it work, you will probably need to install &lt;code&gt;libnotify&lt;/code&gt; (which may be
there if you&amp;#8217;re using Gnome) and Perl (which may be installed with &lt;code&gt;irssi&lt;/code&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You can find the modify script &lt;a href="files/fnotify.pl"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_references"&gt;References&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Based on &lt;a href="http://www.leemhuis.info/files/fnotify/fnotify"&gt;&lt;code&gt;fnotify&lt;/code&gt;&lt;/a&gt; script
from &lt;a href="http://www.leemhuis.info/"&gt;Thorsten&amp;nbsp;Leemhuis&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://ttboj.wordpress.com/2013/10/18/desktop-notifications-for-irssi-in-screen-through-ssh-in-gnome-terminal/"&gt;Desktop
notifications for &lt;code&gt;irssi&lt;/code&gt; in screen through &lt;span class="caps"&gt;SSH&lt;/span&gt; in Gnome&amp;nbsp;terminal&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://scripts.irssi.org/"&gt;Library of &lt;code&gt;irssi&lt;/code&gt; scripts&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="irssi"></category><category term="perl"></category><category term="gnome"></category></entry><entry><title>Patch a dependency of Maven</title><link href="https://hole.tuziwo.info/patch-a-dependency-of-maven.html" rel="alternate"></link><published>2014-01-13T00:00:00+01:00</published><updated>2014-01-13T00:00:00+01:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2014-01-13:/patch-a-dependency-of-maven.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The other day, I was using a XWiki instance to make some crazy things (using
XWiki in a way that is not the default).  My point was to use the
functionalities of creating subwikis.  No specific configuration of XWiki after
that point: Apache Tomcat v7.0.47, &lt;span class="caps"&gt;HSQLDB&lt;/span&gt; (embedded …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The other day, I was using a XWiki instance to make some crazy things (using
XWiki in a way that is not the default).  My point was to use the
functionalities of creating subwikis.  No specific configuration of XWiki after
that point: Apache Tomcat v7.0.47, &lt;span class="caps"&gt;HSQLDB&lt;/span&gt; (embedded in the XWiki instance
downloadable on the website) and XWiki v5.3.  Is use Maven&amp;nbsp;v3.1.1.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In the project, I have no build of XWiki, only a Maven dependency to
&lt;code&gt;xwiki-enterprise-web&lt;/code&gt;.  My point is not to compile XWiki (which is a big
software to compile), but only depend on its &lt;span class="caps"&gt;JAR&lt;/span&gt;&amp;nbsp;files.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;However, if I found a bug in XWiki, how can I manage that without compiling the
entire XWiki software?  And that is what I will talk&amp;nbsp;about.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_the_problem"&gt;The&amp;nbsp;problem&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I have written some script to automatically call the &lt;code&gt;WikiManager.CreateWiki&lt;/code&gt;
page which will create a new subwiki based on a &lt;span class="caps"&gt;HTTP&lt;/span&gt; request with some
parameters.  Basically, I&amp;#8217;m calling the &lt;code&gt;WikiManager.CreateWiki&lt;/code&gt; with the &lt;span class="caps"&gt;URL&lt;/span&gt;
&lt;code&gt;/xwiki/bin/view/WikiManager/CreateWiki&lt;/code&gt; and the following&amp;nbsp;parameters:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;step=create&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;wikiname=mywiki&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;template=mytpl&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;wikiprettyname=My super wiki&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;ownerId=xwiki:XWiki.Admin&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;userScope=global_only&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;membershipType=open&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;However, when this page is called, it is not supposed that the subwiki already
exists.  First of all, it check is the subwiki already exists.  Then it will
also check that the subwiki is not in the process of creation; and this is where
things may go&amp;nbsp;wrong.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_checking_the_job_status_of_the_subwiki_creation"&gt;Checking the job status of the subwiki&amp;nbsp;creation&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To check the status of creation of a subwiki, we ask for the status of a job.
The status of the subwiki creation can be called with this Velocity&amp;nbsp;code.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;#set($jobId = ["wiki", "provisioning", "wikiprovisioning.template", "mywiki"])
#set($percent = $services.wiki.template.getWikiProvisioningJobStatus($jobId).progress.offset)&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;&lt;code&gt;$jobId&lt;/code&gt; is only a list of parameter where the last one is the identifiant of
our wiki being created (see &lt;code&gt;wikiname&lt;/code&gt; property above).  Then we call the
&lt;a href="https://github.com/xwiki/xwiki-platform/blob/stable-5.3.x/xwiki-platform-core/xwiki-platform-wiki/xwiki-platform-wiki-template/xwiki-platform-wiki-template-script/src/main/java/org/xwiki/wiki/template/script/WikiTemplateManagerScript.java#L223"&gt;&lt;code&gt;getWikiProvisioningJobStatus&lt;/code&gt;&lt;/a&gt; function from the script service
&lt;a href="https://github.com/xwiki/xwiki-platform/blob/stable-5.3.x/xwiki-platform-core/xwiki-platform-wiki/xwiki-platform-wiki-template/xwiki-platform-wiki-template-script/src/main/java/org/xwiki/wiki/template/script/WikiTemplateManagerScript.java"&gt;WikiTemplateManagerScript.java&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_getting_a_bug"&gt;Getting a&amp;nbsp;bug&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Getting a bug is usually the easy part!  The bug is here, right under your nose.
Look at the code of the script service.  This is the code you should look&amp;nbsp;for.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="java"&gt;	&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;JobStatus&lt;/span&gt; &lt;span class="nf"&gt;getWikiProvisioningJobStatus&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;jobId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="o"&gt;{&lt;/span&gt;
	    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
	        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wikiTemplateManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getWikiProvisioningJob&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jobId&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;getStatus&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
	    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;WikiTemplateManagerException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
	        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
	    &lt;span class="o"&gt;}&lt;/span&gt;
	&lt;span class="o"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;If the return of the &lt;code&gt;getWikiProvisioningJob&lt;/code&gt; function is &lt;code&gt;null&lt;/code&gt;, how can the
function &lt;code&gt;getWikiProvisioningJobStatus&lt;/code&gt; can return without exception?  Everybody
could have done this error, this is not the point.  And since this is open
source, the error as been reported in the &lt;span class="caps"&gt;JIRA&lt;/span&gt; of XWiki
(&lt;a href="http://jira.xwiki.org/browse/XWIKI-9861"&gt;&lt;span class="caps"&gt;XWIKI&lt;/span&gt;-9861&lt;/a&gt;) and fixed for the
next release with the following&amp;nbsp;code.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="java"&gt;	&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;JobStatus&lt;/span&gt; &lt;span class="nf"&gt;getWikiProvisioningJobStatus&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;jobId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="o"&gt;{&lt;/span&gt;
	    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
	        &lt;span class="nc"&gt;WikiProvisioningJob&lt;/span&gt; &lt;span class="n"&gt;wikiProvisioningJob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;wikiTemplateManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getWikiProvisioningJob&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jobId&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
	        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wikiProvisioningJob&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
	            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
	        &lt;span class="o"&gt;}&lt;/span&gt;
	        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wikiProvisioningJob&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getStatus&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
	    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;WikiTemplateManagerException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
	        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
	    &lt;span class="o"&gt;}&lt;/span&gt;
	&lt;span class="o"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_fix_the_bug_without_compiling_xwiki"&gt;Fix the bug without compiling&amp;nbsp;XWiki&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I cheat a little because we will not compile the entire XWiki software.
However, we still need to compile a small part of XWiki and replace it with the
bug&amp;nbsp;fix.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This is the general overview of what we will do to patch the&amp;nbsp;bug:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="olist arabic"&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;
&lt;p&gt;Unpack the source corresponding to the &lt;span class="caps"&gt;JAR&lt;/span&gt; we want to&amp;nbsp;modify&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Patch these&amp;nbsp;sources&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Compile the modified&amp;nbsp;source&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Unpack the &lt;span class="caps"&gt;JAR&lt;/span&gt; we want to modify in another&amp;nbsp;directory&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Move the freshly compiled classes into the unpacked &lt;span class="caps"&gt;JAR&lt;/span&gt;&amp;nbsp;directory&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Pack the &lt;span class="caps"&gt;JAR&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Exclude the bugged &lt;span class="caps"&gt;JAR&lt;/span&gt; from your main&amp;nbsp;project&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Include your patched &lt;span class="caps"&gt;JAR&lt;/span&gt; in the main&amp;nbsp;project&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_create_a_new_maven_module"&gt;Create a new Maven&amp;nbsp;module&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To begin, our patch &lt;span class="caps"&gt;JAR&lt;/span&gt; will be a new module of our project.  Into the root of
the project, we create a basic &lt;code&gt;pom.xml&lt;/code&gt; file with &lt;code&gt;mvn archetype:generate&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The bug come from the &lt;code&gt;xwiki-platform-wiki-template-script&lt;/code&gt; module (&lt;code&gt;artifactId&lt;/code&gt;
in Maven with the &lt;code&gt;groupId&lt;/code&gt; being &lt;code&gt;org.xwiki.platform&lt;/code&gt;).  We will named our new
module with  &lt;code&gt;xwiki-platform-wiki-template-script-patched&lt;/code&gt; as &lt;code&gt;artifactId&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;For the example, the &lt;code&gt;groupId&lt;/code&gt; of this module will be &lt;code&gt;com.myxwiki&lt;/code&gt;.  The main
project will be called &lt;code&gt;myxwiki&lt;/code&gt; in the same &lt;code&gt;groupId&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You should have something like this at the beginning of your &lt;code&gt;pom.xml&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="xml"&gt;	&lt;span class="nt"&gt;&amp;lt;parent&amp;gt;&lt;/span&gt;
		&lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.myxwiki&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
		&lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;myxwiki&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
		&lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.0-SNAPSHOT&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
	&lt;span class="nt"&gt;&amp;lt;/parent&amp;gt;&lt;/span&gt;
	&lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.myxwiki&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
	&lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;xwiki-platform-wiki-template-script-patched&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
	&lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.0-SNAPSHOT&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
	&lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;XWiki - Platform - Wiki - Template - Script - Patched&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_patch_the_sources"&gt;Patch the&amp;nbsp;sources&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To patch the source, we will create a dependency to the &lt;code&gt;java-source&lt;/code&gt; of the
module we are looking for then use the &lt;code&gt;maven-dependency-plugin&lt;/code&gt; (for unpacking)
combined with &lt;code&gt;maven-patch-plugin&lt;/code&gt; (for&amp;nbsp;patching).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;First of all, we will define directories where to unpack the&amp;nbsp;sources.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="xml"&gt;	...
	&lt;span class="nt"&gt;&amp;lt;properties&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;src.directory&amp;gt;&lt;/span&gt;${project.build.directory}/xwiki-platform-wiki-template-script-src&lt;span class="nt"&gt;&amp;lt;/src.directory&amp;gt;&lt;/span&gt;
	&lt;span class="nt"&gt;&amp;lt;/properties&amp;gt;&lt;/span&gt;
	...&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In the &lt;code&gt;build&lt;/code&gt; part, we need to define where is the source&amp;nbsp;directories.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="xml"&gt;	...
	&lt;span class="nt"&gt;&amp;lt;build&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;sourceDirectory&amp;gt;&lt;/span&gt;${src.directory}&lt;span class="nt"&gt;&amp;lt;/sourceDirectory&amp;gt;&lt;/span&gt;
	    ...
	&lt;span class="nt"&gt;&amp;lt;/build&amp;gt;&lt;/span&gt;
	...&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We will now use 2 plugins.  The first to unpack the sources and the second to
patch&amp;nbsp;them.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect3"&gt;
&lt;h4 id="_unpack_the_sources"&gt;Unpack the&amp;nbsp;sources&lt;/h4&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;First of all, we use the &lt;code&gt;maven-dependency-plugin&lt;/code&gt; to unpack the sources.  We
have already defined the &lt;code&gt;sourceDirectory&lt;/code&gt;.  We still need to give where are the&amp;nbsp;sources.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="xml"&gt;	&lt;span class="nt"&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.apache.maven.plugins&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;maven-dependency-plugin&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;executions&amp;gt;&lt;/span&gt;
	        &lt;span class="nt"&gt;&amp;lt;execution&amp;gt;&lt;/span&gt;
	            &lt;span class="nt"&gt;&amp;lt;id&amp;gt;&lt;/span&gt;unpack&lt;span class="nt"&gt;&amp;lt;/id&amp;gt;&lt;/span&gt;
	            &lt;span class="nt"&gt;&amp;lt;phase&amp;gt;&lt;/span&gt;generate-sources&lt;span class="nt"&gt;&amp;lt;/phase&amp;gt;&lt;/span&gt;
	            &lt;span class="nt"&gt;&amp;lt;goals&amp;gt;&lt;/span&gt;
	            &lt;span class="nt"&gt;&amp;lt;goal&amp;gt;&lt;/span&gt;unpack&lt;span class="nt"&gt;&amp;lt;/goal&amp;gt;&lt;/span&gt;
	            &lt;span class="nt"&gt;&amp;lt;/goals&amp;gt;&lt;/span&gt;
	            &lt;span class="nt"&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
	                &lt;span class="nt"&gt;&amp;lt;artifactItems&amp;gt;&lt;/span&gt;
	                    &lt;span class="nt"&gt;&amp;lt;artifactItem&amp;gt;&lt;/span&gt;
	                        &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.xwiki.platform&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
	                        &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;xwiki-platform-wiki-template-script&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
	                        &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;5.3&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
	                        &lt;span class="nt"&gt;&amp;lt;type&amp;gt;&lt;/span&gt;java-source&lt;span class="nt"&gt;&amp;lt;/type&amp;gt;&lt;/span&gt;
	                        &lt;span class="nt"&gt;&amp;lt;outputDirectory&amp;gt;&lt;/span&gt;${src.directory}&lt;span class="nt"&gt;&amp;lt;/outputDirectory&amp;gt;&lt;/span&gt;
	                    &lt;span class="nt"&gt;&amp;lt;/artifactItem&amp;gt;&lt;/span&gt;
	                &lt;span class="nt"&gt;&amp;lt;/artifactItems&amp;gt;&lt;/span&gt;
	            &lt;span class="nt"&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
	        &lt;span class="nt"&gt;&amp;lt;/execution&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;/executions&amp;gt;&lt;/span&gt;
	&lt;span class="nt"&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect3"&gt;
&lt;h4 id="_create_the_patch"&gt;Create the&amp;nbsp;patch&lt;/h4&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;First of all, we need to create the patch.  To create the patch, we first need
to clone &lt;a href="https://github.com/xwiki/xwiki-platform"&gt;&lt;code&gt;xwiki-platform&lt;/code&gt;&lt;/a&gt; (do not
forget that you should get the v5.3 tagged version because this bug has been
fixed in the master branch).  Then, we will modify the source we want
(&lt;code&gt;WikiTemplateManagerScript.java&lt;/code&gt;).  Once it is done, we can generate the patch
using the following command from the &lt;code&gt;java&lt;/code&gt; directory
(&lt;code&gt;xwiki-platform/xwiki-platform-core/xwiki-platform-wiki/xwiki-platform-wiki-template/xwiki-platform-wiki-template-script/src/main/java&lt;/code&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;git diff -p --src-prefix '' --dst-prefix '' --relative -- org/xwiki/wiki/template/script/WikiTemplateManagerScript.java&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You should get the following&amp;nbsp;file.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="diff"&gt;	diff --git org/xwiki/wiki/template/script/WikiTemplateManagerScript.java org/xwiki/wiki/template/script/WikiTemplateManagerScript.java
	index 74ca25f..8e49bf9 100644
	--- org/xwiki/wiki/template/script/WikiTemplateManagerScript.java
	+++ org/xwiki/wiki/template/script/WikiTemplateManagerScript.java
	@@ -40,6 +40,7 @@
	import org.xwiki.wiki.descriptor.WikiDescriptor;
	import org.xwiki.wiki.descriptor.WikiDescriptorManager;
	import org.xwiki.wiki.manager.WikiManagerException;
	+import org.xwiki.wiki.provisioning.WikiProvisioningJob;
	import org.xwiki.wiki.template.WikiTemplateManager;
	import org.xwiki.wiki.template.WikiTemplateManagerException;
	@@ -223,7 +224,11 @@ public Exception getLastException()
	    public JobStatus getWikiProvisioningJobStatus(List&amp;lt;String&amp;gt; jobId)
	    {
	        try {
	-            return wikiTemplateManager.getWikiProvisioningJob(jobId).getStatus();
	+            WikiProvisioningJob wikiProvisioningJob = wikiTemplateManager.getWikiProvisioningJob(jobId);
	+            if (wikiProvisioningJob == null) {
	+                return null;
	+            }
	+            return wikiProvisioningJob .getStatus();
	        } catch (WikiTemplateManagerException e) {
	            return null;
	        }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect3"&gt;
&lt;h4 id="_apply_the_patch_onto_the_sources"&gt;Apply the patch onto the&amp;nbsp;sources&lt;/h4&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In your new Maven module root, you now need to create the directory
&lt;code&gt;src/main/patches&lt;/code&gt; and put your patch (&lt;code&gt;WikiTemplateManagerScript.patch&lt;/code&gt;)&amp;nbsp;inside.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now, we can add the plugin which will patch our source with the file we have just&amp;nbsp;created.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="xml"&gt;	&lt;span class="nt"&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.apache.maven.plugins&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;maven-patch-plugin&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.1.1&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
	        &lt;span class="nt"&gt;&amp;lt;skipApplication&amp;gt;&lt;/span&gt;false&lt;span class="nt"&gt;&amp;lt;/skipApplication&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;executions&amp;gt;&lt;/span&gt;
	        &lt;span class="nt"&gt;&amp;lt;execution&amp;gt;&lt;/span&gt;
	            &lt;span class="nt"&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
	                &lt;span class="nt"&gt;&amp;lt;patchDirectory&amp;gt;&lt;/span&gt;src/main/patches/&lt;span class="nt"&gt;&amp;lt;/patchDirectory&amp;gt;&lt;/span&gt;
	                &lt;span class="nt"&gt;&amp;lt;targetDirectory&amp;gt;&lt;/span&gt;${src.directory}&lt;span class="nt"&gt;&amp;lt;/targetDirectory&amp;gt;&lt;/span&gt;
	                &lt;span class="nt"&gt;&amp;lt;patches&amp;gt;&lt;/span&gt;
	                    &lt;span class="nt"&gt;&amp;lt;patch&amp;gt;&lt;/span&gt;WikiTemplateManagerScript.patch&lt;span class="nt"&gt;&amp;lt;/patch&amp;gt;&lt;/span&gt;
	                &lt;span class="nt"&gt;&amp;lt;/patches&amp;gt;&lt;/span&gt;
	                &lt;span class="nt"&gt;&amp;lt;patchTrackingFile&amp;gt;&lt;/span&gt;${project.build.directory}/patch-log.txt&lt;span class="nt"&gt;&amp;lt;/patchTrackingFile&amp;gt;&lt;/span&gt;
	                &lt;span class="nt"&gt;&amp;lt;naturalOrderProcessing&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/naturalOrderProcessing&amp;gt;&lt;/span&gt;
	                &lt;span class="nt"&gt;&amp;lt;ignoreWhitespace&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/ignoreWhitespace&amp;gt;&lt;/span&gt;
	            &lt;span class="nt"&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
	            &lt;span class="nt"&gt;&amp;lt;phase&amp;gt;&lt;/span&gt;process-sources&lt;span class="nt"&gt;&amp;lt;/phase&amp;gt;&lt;/span&gt;
	            &lt;span class="nt"&gt;&amp;lt;goals&amp;gt;&lt;/span&gt;
	                &lt;span class="nt"&gt;&amp;lt;goal&amp;gt;&lt;/span&gt;apply&lt;span class="nt"&gt;&amp;lt;/goal&amp;gt;&lt;/span&gt;
	            &lt;span class="nt"&gt;&amp;lt;/goals&amp;gt;&lt;/span&gt;
	        &lt;span class="nt"&gt;&amp;lt;/execution&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;/executions&amp;gt;&lt;/span&gt;
	&lt;span class="nt"&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_create_the_jar"&gt;Create the &lt;span class="caps"&gt;JAR&lt;/span&gt;&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To create our modified version of the &lt;span class="caps"&gt;JAR&lt;/span&gt;, we need to unpack the original
version.  The point of doing this operation is to keep existing files that we
may not have in our sources (&lt;code&gt;components.txt&lt;/code&gt; for example).  First of all, we
will unpack the &lt;span class="caps"&gt;JAR&lt;/span&gt; with the same plugin than the one for the source: we will
add another &lt;code&gt;&amp;lt;artifactItem&amp;gt;&lt;/code&gt; &lt;span class="caps"&gt;XML&lt;/span&gt;&amp;nbsp;element.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="xml"&gt;	&lt;span class="nt"&gt;&amp;lt;artifactItem&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.xwiki.platform&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;xwiki-platform-wiki-template-script&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;5.3&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;type&amp;gt;&lt;/span&gt;jar&lt;span class="nt"&gt;&amp;lt;/type&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;outputDirectory&amp;gt;&lt;/span&gt;${bin.directory}&lt;span class="nt"&gt;&amp;lt;/outputDirectory&amp;gt;&lt;/span&gt;
	&lt;span class="nt"&gt;&amp;lt;/artifactItem&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You can note that the unpacked files will be in the binary directory, exactly
where the modified sources (that we patch), will be compiled.  So we do not need
anything else since the unpacking is done, then the compiling which will replace
the compiled files (&lt;code&gt;WikiTemplateManagerScript.class&lt;/code&gt; file is the only file).
However, we need to make the &lt;span class="caps"&gt;JAR&lt;/span&gt; original project a dependency of our&amp;nbsp;module.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="xml"&gt;	&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.xwiki.platform&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;xwiki-platform-wiki-template-script&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;5.3&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;type&amp;gt;&lt;/span&gt;jar&lt;span class="nt"&gt;&amp;lt;/type&amp;gt;&lt;/span&gt;
	&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_the_new_jar"&gt;The new &lt;span class="caps"&gt;JAR&lt;/span&gt;!&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now, you just need to &lt;code&gt;mvn clean install&lt;/code&gt; and see the result.  You should find
the &lt;span class="caps"&gt;JAR&lt;/span&gt; file &lt;code&gt;xwiki-platform-wiki-template-script-patched-1.0-SNAPSHOT.jar&lt;/code&gt; into
your &lt;code&gt;target&lt;/code&gt; directory.  Now, we need to use it in our main&amp;nbsp;project.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect3"&gt;
&lt;h4 id="_exclude_the_bugged_jar"&gt;Exclude the bugged &lt;span class="caps"&gt;JAR&lt;/span&gt;&lt;/h4&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To exclude the bugged file, we will use the &lt;code&gt;maven-war-plugin&lt;/code&gt; plugin.  In your
&lt;code&gt;pom.xml&lt;/code&gt;, you should have a dependency to XWiki somewhere.  Something like that
for&amp;nbsp;example.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="xml"&gt;	&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.xwiki.enterprise&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;xwiki-enterprise-web&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;5.3&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;type&amp;gt;&lt;/span&gt;war&lt;span class="nt"&gt;&amp;lt;/type&amp;gt;&lt;/span&gt;
	&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You can add the plugin which will exclude the
&lt;code&gt;xwiki-platform-wiki-template-script-5.3.jar&lt;/code&gt; &lt;span class="caps"&gt;JAR&lt;/span&gt;&amp;nbsp;file.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="xml"&gt;	&lt;span class="nt"&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.apache.maven.plugins&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;maven-war-plugin&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
	        &lt;span class="nt"&gt;&amp;lt;packagingExcludes&amp;gt;&lt;/span&gt;
	            WEB-INF/lib/xwiki-platform-wiki-template-script-5.3.jar
	        &lt;span class="nt"&gt;&amp;lt;/packagingExcludes&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
	&lt;span class="nt"&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Into the &lt;code&gt;&amp;lt;packagingExcludes&amp;gt;&lt;/code&gt; element, you may use wildcard pattern &lt;code&gt;*&lt;/code&gt; to find
more than one&amp;nbsp;file.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect3"&gt;
&lt;h4 id="_include_the_patched_jar"&gt;Include the patched &lt;span class="caps"&gt;JAR&lt;/span&gt;&lt;/h4&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To include you new patched &lt;span class="caps"&gt;JAR&lt;/span&gt;, you just need to add a dependency to&amp;nbsp;it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="xml"&gt;	&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.xwikisas&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;eesc-xwiki-platform-wiki-template-script&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
	    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.0-SNAPSHOT&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
	&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_references"&gt;References&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://maven.apache.org/plugins/maven-patch-plugin/"&gt;Maven patch plugin&amp;nbsp;documentation&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://maven.apache.org/plugins/maven-dependency-plugin/"&gt;Maven dependency
plugin&amp;nbsp;documentation&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://maven.apache.org/plugins/maven-war-plugin/"&gt;Maven &lt;span class="caps"&gt;WAR&lt;/span&gt; plugin&amp;nbsp;documentation&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Finally, the project I was working on to apply this patch is hosted by Github
and is called &lt;a href="https://github.com/fmancinelli/eesc-xwiki"&gt;&lt;span class="caps"&gt;EESC&lt;/span&gt; XWiki&lt;/a&gt;.  You
can find the patch module inside &lt;code&gt;eesc-xwiki-platform-wiki-template-script&lt;/code&gt; and
the main project for the &lt;span class="caps"&gt;WAR&lt;/span&gt; in &lt;code&gt;eesc-xwiki-web/eesc-xwiki-web-base&lt;/code&gt; (which is
not the root of our&amp;nbsp;project).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="maven"></category><category term="java"></category><category term="patch"></category></entry><entry><title>Get information from a XWiki database</title><link href="https://hole.tuziwo.info/get-information-from-a-xwiki-database.html" rel="alternate"></link><published>2013-12-12T00:00:00+01:00</published><updated>2013-12-12T00:00:00+01:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2013-12-12:/get-information-from-a-xwiki-database.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;It is really a problem when in a file you have characters displayed as something
like &lt;code&gt;^@&lt;/code&gt; or &lt;code&gt;&amp;lt;E5&amp;gt;&lt;/code&gt;.  Indeed, yesterday, my &lt;a href="http://www.xwiki.org"&gt;XWiki&lt;/a&gt;
(installed in local on my computer) has been crashed by a computer freeze.  I
hardly reboot my computer and never been able to start the wiki after …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;It is really a problem when in a file you have characters displayed as something
like &lt;code&gt;^@&lt;/code&gt; or &lt;code&gt;&amp;lt;E5&amp;gt;&lt;/code&gt;.  Indeed, yesterday, my &lt;a href="http://www.xwiki.org"&gt;XWiki&lt;/a&gt;
(installed in local on my computer) has been crashed by a computer freeze.  I
hardly reboot my computer and never been able to start the wiki after&amp;nbsp;that.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;On this wiki, I was developping some new Velocity scripts and if I was not able
to get them back, it would be a lot of lost work.  I used the default database
system for XWiki which is &lt;span class="caps"&gt;HSQLDB&lt;/span&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_step_1_backup_the_work"&gt;Step 1 - Backup the&amp;nbsp;work&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;My first action has been to backup all my work before deploying a new XWiki.  On
this step, I was lucky because all my work was store in a subdirectory.  All
stuff concerning the database was in a &lt;code&gt;xwiki.data&lt;/code&gt; directory and this is what
this directory&amp;nbsp;contains.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;xwiki.data
|--&amp;gt; database/
|--&amp;gt; extension/
|--&amp;gt; jobs/
|--&amp;gt; lucene/
|--&amp;gt; solr/&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_step_2_the_database"&gt;Step 2 - The&amp;nbsp;database&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_exporting_the_database"&gt;Exporting the&amp;nbsp;database&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The database file is inside de &lt;code&gt;database/xwiki_db.lobs&lt;/code&gt; file.  I copy it into a
new directory where I will be able to parse it and recover my&amp;nbsp;work.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;For example, you can do&amp;nbsp;this.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ cd ~/
$ mkdir restore-xwiki/
$ cd restore-xwiki/
$ cp &amp;lt;path-of-xwiki-database&amp;gt;/xwiki_db.lobs xwiki.db&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_whats_in_this_database_file"&gt;What&amp;#8217;s in this database&amp;nbsp;file?&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This file is almost a simple text file with not-valid &lt;span class="caps"&gt;XML&lt;/span&gt; in it.  &lt;em&gt;Almost&lt;/em&gt;
because there is a lot of &lt;code&gt;^@&lt;/code&gt; in it; indeed, between each readable character,
there is the &lt;code&gt;^@&lt;/code&gt; character.  &lt;em&gt;Not-valid&lt;/em&gt; &lt;span class="caps"&gt;XML&lt;/span&gt; file because it is in fact a
concatenation of multiple well-formed &lt;span class="caps"&gt;XML&lt;/span&gt; file (i.e. you have multiple &lt;code&gt;&amp;lt;?xml
&amp;#8230;&amp;#8203;?&amp;gt;&lt;/code&gt; elements in the&amp;nbsp;file).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_step_3_clean_the_file"&gt;Step 3 - Clean the&amp;nbsp;file&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Your file is now called &lt;code&gt;xwiki.db&lt;/code&gt;.  We will parse it to remove all the &lt;code&gt;^@&lt;/code&gt;
characters.  You may want to try with any file editor like &lt;code&gt;gedit&lt;/code&gt;, &lt;code&gt;emacs&lt;/code&gt; or
&lt;code&gt;vim&lt;/code&gt;.  However, the file is a database and in my case, was a more than &lt;span class="caps"&gt;300MB&lt;/span&gt;
file.  Opening a large file like this may be a problem (and parsing it to
replace characters and even bigger problem in this&amp;nbsp;case).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To parse this file, we will use the &lt;code&gt;tr&lt;/code&gt; command which is way more efficient.
The only thing to do before using &lt;code&gt;tr&lt;/code&gt; is to identify the &lt;span class="caps"&gt;ASCII&lt;/span&gt;/&lt;span class="caps"&gt;UTF&lt;/span&gt;-8/&lt;span class="caps"&gt;WHATEVER&lt;/span&gt;
code of this &lt;code&gt;^@&lt;/code&gt; character.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_identifying_the_character"&gt;Identifying the&amp;nbsp;character&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To identify this character, I used a tricky way which consist to take a small part of
this file, opening it with my favorite editor &lt;code&gt;vim&lt;/code&gt; and identifying the code
under&amp;nbsp;it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To create the small part of the database file, use the following then open with&amp;nbsp;vim.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ cat xwiki.db | head &amp;gt; temp.db
$ vim temp.db&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Once you&amp;#8217;re inside vim, you can see &lt;code&gt;^@&lt;/code&gt; characters.  Place your cursor on it
and type &lt;code&gt;ga&lt;/code&gt; on your keyboard (&lt;code&gt;ga&lt;/code&gt; is for &lt;em&gt;Get &lt;span class="caps"&gt;ASCII&lt;/span&gt;&lt;/em&gt;).  You should see at the
bottom of the window the code of the character we are looking for: this is the
one with the code&amp;nbsp;0.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_bonus_to_identify_the_character"&gt;Bonus to identify the&amp;nbsp;character&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We could have done a easier method to identify the character (but this method
may not work on other cases).  You can open &lt;code&gt;vim&lt;/code&gt; and typing the following:
&lt;code&gt;CTRL+v&lt;/code&gt; then &lt;code&gt;CTRL+@&lt;/code&gt;.  You should obtain the character we are looking for.
Then to identify it, you can still use the &lt;code&gt;ga&lt;/code&gt; shortcut.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_clean_the_file"&gt;Clean the&amp;nbsp;file&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now, we will use the &lt;code&gt;tr&lt;/code&gt; command which can replace each character of a file
with another (this functionality doesn&amp;#8217;t interests us) and also delete specific
characters from a file (this functionality seems more&amp;nbsp;interesting!).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;&lt;code&gt;tr&lt;/code&gt; take the standard input as an entry and we will save the output in the
&lt;code&gt;xwiki.xml&lt;/code&gt; file (which is not a real &lt;span class="caps"&gt;XML&lt;/span&gt;&amp;nbsp;file).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ tr -d '\000' &amp;lt; xwiki.db &amp;gt; xwiki.xml&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_step_4_find_the_xwiki_document"&gt;Step 4 - Find the XWiki&amp;nbsp;document&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Each page of the XWiki is stored in &lt;code&gt;xwiki.xml&lt;/code&gt; as an &lt;span class="caps"&gt;XML&lt;/span&gt; file which is
presented like&amp;nbsp;that.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;xwikidoc&amp;gt;
&amp;lt;web&amp;gt;Main&amp;lt;/web&amp;gt;
&amp;lt;name&amp;gt;WebHome&amp;lt;/name&amp;gt;
[...]
&amp;lt;contentUpdateDate&amp;gt;1383876486000&amp;lt;/contentUpdateDate&amp;gt;
[...]
&amp;lt;content&amp;gt;[...]&amp;lt;/content&amp;gt;
&amp;lt;/xwikidoc&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;xwikidoc&amp;gt;&lt;/code&gt; is the root element of these &lt;span class="caps"&gt;XML&lt;/span&gt; file.  After this element, the
&lt;code&gt;&amp;lt;web&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;name&amp;gt;&lt;/code&gt; elements respectively describes the space and name of your
XWiki page.  After &lt;code&gt;&amp;lt;name&amp;gt;&lt;/code&gt; element, there is a few header elements that
describes the page.  For example, you may find a few &lt;code&gt;&amp;lt;object&amp;gt;&lt;/code&gt; elements that
describes the objects stored in that page.  One element that is interesting for
us is the &lt;code&gt;&amp;lt;contentUpdateDate&amp;gt;&lt;/code&gt; which contains the update date of this page.
Finally, the &lt;code&gt;&amp;lt;content&amp;gt;&lt;/code&gt; element contains the content of our page (in my case,
the Velocity I am looking for, remember, I&amp;#8217;m trying to restore it because I lost
Velocity&amp;nbsp;work).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Given these informations, it seems pretty easy to find only the document we want
and copy/paste the content to save it.  However, XWiki store each saved version
of each page.  Though if I&amp;#8217;m looking for the page &lt;code&gt;Main.WebHome&lt;/code&gt;, I will find
multiple instances and that&amp;#8217;s where the &lt;code&gt;&amp;lt;contentUpdateDate&amp;gt;&lt;/code&gt; will help&amp;nbsp;us.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_step_4_1_search_a_multiline_pattern"&gt;Step 4.1 - Search a multiline&amp;nbsp;pattern&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The first thing we want to do is identifying the right page.  And because a page
is identified by it&amp;#8217;s name &lt;strong&gt;and&lt;/strong&gt; it&amp;#8217;s space, we need to look into the file for a
multiline pattern that contains &lt;code&gt;&amp;lt;web&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;name&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;For a multiline research, people says (see references) you should be able to use the &lt;code&gt;-P&lt;/code&gt; option
of &lt;code&gt;grep&lt;/code&gt;.  But for a mysterious reason, the &lt;code&gt;-P&lt;/code&gt; option doesn&amp;#8217;t works for me
and ends up with the following&amp;nbsp;message.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;[1]    2618 abort (core dumped)  /usr/bin/grep [...]&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;So I used another solution proposed in the same forum reference: &lt;code&gt;pcregrep&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ pcregrep -M -n -A 11 '&amp;lt;web&amp;gt;Main&amp;lt;\/web&amp;gt;[^&amp;lt;]*\n[^&amp;lt;]*&amp;lt;name&amp;gt;WebHome&amp;lt;\/name&amp;gt;' temp.xml&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I add also the &lt;code&gt;-n&lt;/code&gt; which numerotates each line: this will help us to find the
line number of what we are looking for.  And finally, I add the &lt;code&gt;-A 11&lt;/code&gt; option
in order to display 11 lines after each matching pattern.  Why I display 11
lines?  That&amp;#8217;s because 11 lines later, we can find the &lt;code&gt;&amp;lt;contentUpdateDate&amp;gt;&lt;/code&gt;
element which is the information we are interested&amp;nbsp;in.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_step_4_2_filter_the_contentupdatedate_elements"&gt;Step 4.2 - Filter the &lt;code&gt;&amp;lt;contentUpdateDate&amp;gt;&lt;/code&gt; elements&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;With the previous command, we have searched for documents with a particular name
and space.  We have also displayed each pattern with some extra lines wich
contains the following &lt;code&gt;&amp;lt;contentUpdateDate&amp;gt;&lt;/code&gt; element.  So each
&lt;code&gt;&amp;lt;contentUpdateDate&amp;gt;&lt;/code&gt; element that is displayed in this output is an potentially
interesting one.  Everything else in the output is of no interest&amp;nbsp;now.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ &amp;lt;output-4.1&amp;gt; | grep '&amp;lt;contentUpdateDate&amp;gt;'&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonitionblock note"&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td class="icon"&gt;
&lt;div class="title"&gt;Note&lt;/div&gt;
&lt;/td&gt;
&lt;td class="content"&gt;
&lt;div class="title"&gt;About the output&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In the following commands, I will use the &lt;code&gt;&amp;lt;output-4.?&amp;gt;&lt;/code&gt; notation to designate
the output of the previous step&amp;nbsp;command.&lt;/p&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_step_4_3_keep_the_numbers_we_want"&gt;Step 4.3 - Keep the numbers we&amp;nbsp;want&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In this step, I will remove the &lt;span class="caps"&gt;XML&lt;/span&gt; elements and keep only the line number and
the date (the data inside the &lt;code&gt;&amp;lt;contentUpdateDate&amp;gt;&lt;/code&gt; element).  I will also place
the date at the beginning of the line in order to be able to sort them in the
next&amp;nbsp;step.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ &amp;lt;output-4.2&amp;gt; | sed 's/^\([0-9]\+\).*&amp;lt;contentUpdateDate&amp;gt;\([0-9]\+\)&amp;lt;\/.*$/\2-\1/g'&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_step_4_4_sort_by_date_and_keep_the_last_one"&gt;Step 4.4 - Sort by date and keep the last&amp;nbsp;one&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This is pretty easy since the &lt;code&gt;sort&lt;/code&gt; command exists.  To keep only the last one,
we can use the &lt;code&gt;tail&lt;/code&gt; command.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ &amp;lt;output-4.3&amp;gt; | sort | tail -n 1&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_step_4_5_get_the_line_number"&gt;Step 4.5 - Get the line&amp;nbsp;number&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now, we just need to get the line number and save it in a variable.  We will use
the &lt;code&gt;awk&lt;/code&gt; command (we could also use the &lt;code&gt;sed&lt;/code&gt; command) to get the second field
of our line which should look like &lt;code&gt;1383876486000-2356&lt;/code&gt; (the first field is the
date and the second the line&amp;nbsp;number).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ LINE_NUMBER=`&amp;lt;output-4.4&amp;gt; | awk -F '-' '{print $2}'`&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_step_4_6_find_the_end_of_the_xwiki_document"&gt;Step 4.6 - Find the end of the XWiki&amp;nbsp;document&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now that we have the line number of the &lt;code&gt;&amp;lt;contentUpdateDate&amp;gt;&lt;/code&gt; of the document we
are looking for, we will parse the file from this element to find the first
&lt;code&gt;&amp;lt;/xwikidoc&amp;gt;&lt;/code&gt; element (which is the close element of the&amp;nbsp;document).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;First of all, we will use &lt;code&gt;grep -n ''&lt;/code&gt; in order to add the line numbers to our
input.  Then we will remove all the lines before our &lt;code&gt;LINE_NUMBER&lt;/code&gt; with &lt;code&gt;tail&lt;/code&gt;
because we want the first &lt;code&gt;&amp;lt;/xwikidoc&amp;gt;&lt;/code&gt; after this line number.  We will filter
all the &lt;code&gt;&amp;lt;/xwikidoc&amp;gt;&lt;/code&gt; elements with &lt;code&gt;grep&lt;/code&gt; and keep only the first with &lt;code&gt;head&lt;/code&gt;.
Finally, we will get the line number from this input with &lt;code&gt;awk&lt;/code&gt; and store it in
the &lt;code&gt;END_LINE&lt;/code&gt; variable.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;END_LINE=`cat xwiki.xml | grep -n '' | tail -n +$LINE | grep '&amp;lt;\/xwikidoc&amp;gt;' | head -n 1 | awk -F ':' '{print $1}'`&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_step_4_7_find_the_start_of_the_xwiki_document"&gt;Step 4.7 - Find the start of the XWiki&amp;nbsp;document&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The operation is nearly the same that for the step 4.6.  We will just revert
some of the sub-steps.  In this case, we will only keep the part of the document
that is before &lt;code&gt;LINE_NUMBER&lt;/code&gt; with &lt;code&gt;head&lt;/code&gt;.  Then we will look for &lt;code&gt;&amp;lt;?xml&lt;/code&gt;
pattern, keep the last found pattern and get then store the line number into the
&lt;code&gt;BEGIN_LINE&lt;/code&gt; variable.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ BEGIN_LINE=`cat xwiki.xml | grep -n '' | head -n $(($END_LINE - 1)) | grep '&amp;lt;?xml' | tail -n 1 | awk -F ':' '{print $1}'`&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_step_4_8_get_the_xwiki_document"&gt;Step 4.8 - Get the XWiki&amp;nbsp;document&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We now have &lt;code&gt;BEGIN_LINE&lt;/code&gt; and &lt;code&gt;END_LINE&lt;/code&gt;, we will be able to keep only this part
of the database with &lt;code&gt;head&lt;/code&gt; and &lt;code&gt;tail&lt;/code&gt; with a bit of &lt;code&gt;bash&lt;/code&gt; arithmetic.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ cat xwiki.xml | tail -n +$BEGIN_LINE | head -n $(($END_LINE - BEGIN_LINE + 1 )) &amp;gt; Main.WebHome.xml&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You can now get what&amp;#8217;s in the &lt;code&gt;&amp;lt;content&amp;gt;&lt;/code&gt; element.  It is also possible to get
the informations from the &lt;code&gt;&amp;lt;object&amp;gt;&lt;/code&gt; (where you may also have code and
configuration).  If you want, you probably can create a &lt;span class="caps"&gt;XAR&lt;/span&gt; file from this &lt;span class="caps"&gt;XML&lt;/span&gt;
file that you can import into your new&amp;nbsp;XWiki.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You still may need to be careful about the encoding of the file because I notice
that the encoding was &lt;code&gt;latin1&lt;/code&gt; in my case but a copy/paste of the content part
into a new XWiki page need some &lt;code&gt;utf-8&lt;/code&gt; encoding.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_references"&gt;References&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://vim.wikia.com/wiki/Showing_the_ASCII_value_of_the_current_character"&gt;Showing
the &lt;span class="caps"&gt;ASCII&lt;/span&gt; value of the current character on&amp;nbsp;Vim&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://stackoverflow.com/questions/152708/how-can-i-search-for-a-multiline-pattern-in-a-file-use-pcregrep"&gt;How
can I search for a multiline pattern in a&amp;nbsp;file?&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="xwiki"></category><category term="tr"></category><category term="grep"></category></entry><entry><title>Stress test XWiki for subwikis creations</title><link href="https://hole.tuziwo.info/stress-test-xwiki-for-subwikis-creation.html" rel="alternate"></link><published>2013-12-12T00:00:00+01:00</published><updated>2013-12-12T00:00:00+01:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2013-12-12:/stress-test-xwiki-for-subwikis-creation.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I need to know how many subwikis can XWiki support without freezing or crashing.
I prepared some kind of stress test (note that I&amp;#8217;m not familiar with these kind
of things) in order to &lt;em&gt;massively&lt;/em&gt; create subwikis into a XWiki instance.  By
&lt;em&gt;massively&lt;/em&gt;, I mean 1000 which seems …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I need to know how many subwikis can XWiki support without freezing or crashing.
I prepared some kind of stress test (note that I&amp;#8217;m not familiar with these kind
of things) in order to &lt;em&gt;massively&lt;/em&gt; create subwikis into a XWiki instance.  By
&lt;em&gt;massively&lt;/em&gt;, I mean 1000 which seems to be sufficient (you will see that in the&amp;nbsp;results).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;My XWiki instance (5.3-milestone-2) is a local instance, on the 8080 port,
runned on Jetty with &lt;span class="caps"&gt;HSQLDB&lt;/span&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Since my first method doesn&amp;#8217;t work pretty well, I tried a second way to do this
stress test but which may have a bias of&amp;nbsp;measure.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_first_method_velocity_script_called_by_a_curl_request"&gt;First method - Velocity script called by a &lt;code&gt;curl&lt;/code&gt; request&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The Velocity script is using the &lt;code&gt;wiki&lt;/code&gt; service which is new in the 5.3 version
of XWiki.  With this service, you can do a lot of interesting&amp;nbsp;things:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;exists(String)&lt;/code&gt; - Test the existence of&amp;nbsp;subwiki&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;getById(String)&lt;/code&gt; - To get the wiki&amp;nbsp;descriptor&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;createWiki(String, String, String, boolean)&lt;/code&gt; - Create a new&amp;nbsp;wiki&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This is the Velocity code I used and stored into
&lt;code&gt;WikiStressTestCode/FromRequest&lt;/code&gt;.  The page take a &lt;span class="caps"&gt;HTTP&lt;/span&gt; request in entry with
two parameters:
* &lt;code&gt;wikiname&lt;/code&gt; - the name of the created wiki
* &lt;code&gt;wikinumber&lt;/code&gt; - the number of the created wiki (useful for a stress&amp;nbsp;test)&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;{{velocity}}
#set($wikiName = $!request.getParameter('wikiname'))
#set($wikiNumber = $!request.getParameter('wikinumber'))
#set($wikiId = "$!wikiName$!wikiNumber")
#if($wikiId.isEmpty())
#set($wikiName = 'Null')
#set($wikiNumber = 0)
#set($wikiId = 'null')
#end
#if($services.wiki.exists($wikiId))
#set($wiki = $services.wiki.getById($wikiId))
#else
#set($wiki = $services.wiki.createWiki($wikiId, $wikiId, 'xwiki:XWiki.Admin', true))
#end
#if($wiki)
#set($wikiPrettyName = "Wiki $wikiName #$wikiNumber ")
#set($discard = $wiki.setPrettyName($wikiPrettyName))
#set($wikiDescription = "Wiki $wikiName #$wikiNumber created for the stress test")
#set($discard = $wiki.setDescription($wikiDescription))
#set($discard = $services.wiki.saveDescriptor($wiki))
#else
#set($discard = $response.sendError(404, 'Error in creating the wiki'))
#end
{{/velocity}}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;After this page has been created, you can call the page with a &lt;code&gt;curl&lt;/code&gt; request as&amp;nbsp;following;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="sh"&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nv"&gt;NUMBER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;span class="nv"&gt;NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;wiki
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$# &lt;/span&gt;&lt;span class="nt"&gt;-ge&lt;/span&gt; 1 &lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;then
	&lt;/span&gt;&lt;span class="nv"&gt;NUMBER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
&lt;span class="k"&gt;fi
if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$# &lt;/span&gt;&lt;span class="nt"&gt;-ge&lt;/span&gt; 2 &lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;then
	&lt;/span&gt;&lt;span class="nv"&gt;NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;
&lt;span class="k"&gt;fi

&lt;/span&gt;curl &lt;span class="se"&gt;\&lt;/span&gt;
	&lt;span class="nt"&gt;--silent&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
	&lt;span class="nt"&gt;--show-error&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
	&lt;span class="nt"&gt;--user&lt;/span&gt; Admin:admin &lt;span class="se"&gt;\&lt;/span&gt;
	&lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="s2"&gt;"wikiname="&lt;/span&gt;&lt;span class="nv"&gt;$NAME&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
	&lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="s2"&gt;"wikinumber="&lt;/span&gt;&lt;span class="nv"&gt;$NUMBER&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
	&lt;span class="nt"&gt;-o&lt;/span&gt; data/&lt;span class="nv"&gt;$NAME&lt;/span&gt;.html &lt;span class="se"&gt;\&lt;/span&gt;
	http://localhost:8080/xwiki/bin/view/WikiStressTestCode/FromRequest&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This file only create one request and take the number and the name as optional&amp;nbsp;parameters.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I call the &lt;code&gt;create-wiki.sh&lt;/code&gt; script into a loop from a second script file
&lt;code&gt;stress-test.sh&lt;/code&gt;.  This second script file will measure the time of each request
in order to observe the evolution of the time to create a new&amp;nbsp;subwiki.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="sh"&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nv"&gt;TEST_NUMBER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3
&lt;span class="nv"&gt;NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;test
&lt;/span&gt;&lt;span class="nv"&gt;LOG_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;stress-test-request.log
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nv"&gt;$LOG_FILE&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;then
	&lt;/span&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nv"&gt;$LOG_FILE&lt;/span&gt;
&lt;span class="k"&gt;fi
if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$# &lt;/span&gt;&lt;span class="nt"&gt;-ge&lt;/span&gt; 1 &lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;then
	&lt;/span&gt;&lt;span class="nv"&gt;TEST_NUMBER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
&lt;span class="k"&gt;fi

for &lt;/span&gt;num &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;seq &lt;/span&gt;1 &lt;span class="nv"&gt;$TEST_NUMBER&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;span class="k"&gt;do
	&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"Creating wiki "&lt;/span&gt;&lt;span class="nv"&gt;$Name&lt;/span&gt;&lt;span class="s2"&gt;" #&lt;/span&gt;&lt;span class="nv"&gt;$num&lt;/span&gt;&lt;span class="s2"&gt;..."&lt;/span&gt;
	/usr/bin/time &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;%e &lt;span class="nt"&gt;--output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$LOG_FILE&lt;/span&gt; &lt;span class="nt"&gt;--append&lt;/span&gt; ./create-wiki.sh &lt;span class="nv"&gt;$num&lt;/span&gt; &lt;span class="nv"&gt;$NAME&lt;/span&gt;
	&lt;span class="nv"&gt;TIME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 1 &lt;span class="nv"&gt;$LOG_FILE&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
	&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;" ("&lt;/span&gt;&lt;span class="nv"&gt;$TIME&lt;/span&gt;&lt;span class="s2"&gt;"s)"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;And now, this is the result of this first&amp;nbsp;method.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="images/stress-test-request.png" alt="Result of the Method 1" width="100%"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;As you can see, around 250 creations, XWiki seems to not respond.  And I can
check on XWiki that the first 250 subwikis have been created but not the others.
I suspect the indexation of either Lucene or Solr to be too much loaded and
freezing the whole&amp;nbsp;wiki.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_second_method_groovy_script"&gt;Second method - Groovy&amp;nbsp;script&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The Groovy script in &lt;code&gt;WikiStressTestCode.InsideGroovy&lt;/code&gt; is merely doing the same
as the Velocity script of the first method.  However, it is not responding to a
request but creating is own loop for the creation of the wikis.  The problem of
this method is that as long as the page is processing the iteration, the page is
loading and there is no possibility to know the state of the loop (like &amp;#8220;How
many iteration there&amp;nbsp;is?&amp;#8221;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This tricky part is done by writting the processing to a second page called
&lt;code&gt;WikiStressTestCode.InsideGroovyResults&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The second problem is to measure the time of execution.  This is done in Groovy
by using &lt;code&gt;System.currentTimeMillis()&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;{{groovy}}
String wikiName = "test";
int testNumber = 1000;
resultsPage = xwiki.getDocument("WikiStressTestCode", "InsideGroovyResults");
resultsPage.setContent("");
resultsPage.save();
int wikiNumber = 1;
while(wikiNumber &amp;lt;= testNumber) {
	begin = System.currentTimeMillis();
	String wikiId = String.format("%s%s", wikiName, wikiNumber);
	if(services.wiki.exists(wikiId)) {
	wiki = services.wiki.getById(wikiId);
	} else {
	wiki = services.wiki.createWiki(wikiId, wikiId, "xwiki:XWiki.Admin", true);
	}
	if(wiki) {
	String wikiPrettyName = String.format("Wiki %s #%s", wikiName, wikiNumber);
	wiki.setPrettyName(wikiPrettyName);
	String wikiDescription = String.format("Wiki %s #%s created for the stress test", wikiName, wikiNumber);
	wiki.setDescription(wikiDescription);
	services.wiki.saveDescriptor(wiki);
	}
	wikiNumber = wikiNumber + 1;
	end = System.currentTimeMillis();
	String time = String.format("%d", end-begin);
	resultsPageContent = resultsPage.getContent();
	resultsPage.setContent(String.format("%s\n%s", resultsPageContent, time));
	resultsPage.save();
}
{{/groovy}}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To create an image, I can now load the page
&lt;code&gt;WikiStressTestCode.InsideGroovyResults&lt;/code&gt; to get all measured&amp;nbsp;times.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;And now, this is the result of this second&amp;nbsp;method.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="images/stress-test-groovy.png" alt="Result of the Method 2" width="100%"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;As you can see, I was not able to create my 1000 wikis.  Almost 700 and crashed.
First of all, the evolution seems to be as an exponential law, which is a bad
news!  However, we could level this conclusion given the fact that all subwikis
are created in the same page: it is possible that the context of execution is
growing (in memory) with a consequence on the subwikis creation.  To simplify,
the exponential law may be the consequence of my stress test and not from XWiki
(or maybe&amp;nbsp;both!).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You can find the XWiki code that has been used and scripts&amp;nbsp;here:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="files/WikiStressTestCode.xar"&gt;WikiStressTestCode.xar&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="files/create-wiki.sh"&gt;create-wiki.sh&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="files/stress-test-request.sh"&gt;stress-test-request.sh&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;On a server, you will probably be able to create around 1000 subwikis but the
basic stress tests that I have made show that improvements should be done on
XWiki before going further.  Another method that I have not tested and would
probably be the best for stress testing is to use
&lt;a href="http://jmeter.apache.org/"&gt;JMeter&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="xwiki"></category><category term="velocity"></category><category term="groovy"></category></entry><entry><title>Using `sed` to add new lines</title><link href="https://hole.tuziwo.info/using-sed-to-add-new-lines.html" rel="alternate"></link><published>2013-11-30T00:00:00+01:00</published><updated>2013-11-30T00:00:00+01:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2013-11-30:/using-sed-to-add-new-lines.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;&lt;code&gt;sed&lt;/code&gt; is a powerful tool to edit files line by line.  However, when you try to
manipulate more than one line at a time, it becomes more difficult to create
&lt;code&gt;sed&lt;/code&gt; commands.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The point of this article is to find a pattern in a file and, when this pattern …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;&lt;code&gt;sed&lt;/code&gt; is a powerful tool to edit files line by line.  However, when you try to
manipulate more than one line at a time, it becomes more difficult to create
&lt;code&gt;sed&lt;/code&gt; commands.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The point of this article is to find a pattern in a file and, when this pattern
is found, add a new line just&amp;nbsp;below.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_the_use_case"&gt;The use&amp;nbsp;case&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Imagine that we have a lot of AsciiDoc documents.  These articles have metadata
at the beginning.  However, the language is not defined, in any article.  We
want to add a metadata to define the lang of all articles (we know they all are
in&amp;nbsp;english).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;For example, this is the metadata of this&amp;nbsp;article&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;= Using `sed` to add new lines
:author: woshilapin
:email: woshilapin@gmail.com
:date: 30-11-2013
:slug: using-sed-to-add-new-lines
:category: tech
:tags: sed&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We want to add the &lt;code&gt;:lang:&lt;/code&gt; metadata after the &lt;code&gt;:date:&lt;/code&gt; metadata.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_the_solution"&gt;The&amp;nbsp;solution&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;With the &lt;code&gt;sed&lt;/code&gt; command, we will use the &lt;code&gt;a\&lt;/code&gt; function to add a new line after
the pattern we are looking&amp;nbsp;for.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ sed '/:date:/ a\
	:lang: en\
	' on-fichier.asciidoc&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Notice that there is two new lines.  The first says &lt;code&gt;add a new line after the
pattern you&amp;#8217;re looking for'' and the second says &lt;/code&gt;add a new line at the end of
the line I&amp;#8217;m creating&amp;#8221;.  You may use the &lt;code&gt;-i&lt;/code&gt; option of &lt;code&gt;sed&lt;/code&gt; to replace in the
file (the default is to print on the standard&amp;nbsp;output).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_references"&gt;References&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://www.unix.com/showthread.php?t=15927"&gt;Add new line after finding&amp;nbsp;text&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="sed"></category></entry><entry><title>Problem with suspend on Linux</title><link href="https://hole.tuziwo.info/problem-with-suspend-on-linux.html" rel="alternate"></link><published>2013-11-22T00:00:00+01:00</published><updated>2013-11-22T00:00:00+01:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2013-11-22:/problem-with-suspend-on-linux.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The suspend can be achieved with the power button (default configuration on
&lt;span class="caps"&gt;GNOME&lt;/span&gt; 3) or with the &lt;code&gt;Fn+F1&lt;/code&gt; shortcut.  After a fresh installation of Arch
Linux, it worked but since few days, it does not resume&amp;nbsp;well.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The symptoms: the computer (&lt;span class="caps"&gt;ASUS&lt;/span&gt; &lt;span class="caps"&gt;N750JV&lt;/span&gt;) is suspend and when resume …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The suspend can be achieved with the power button (default configuration on
&lt;span class="caps"&gt;GNOME&lt;/span&gt; 3) or with the &lt;code&gt;Fn+F1&lt;/code&gt; shortcut.  After a fresh installation of Arch
Linux, it worked but since few days, it does not resume&amp;nbsp;well.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The symptoms: the computer (&lt;span class="caps"&gt;ASUS&lt;/span&gt; &lt;span class="caps"&gt;N750JV&lt;/span&gt;) is suspend and when resume, freeze with
a screen showing some information about resume.  Nothing to do except holding
the power button for a hard&amp;nbsp;shutdown.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_manage_the_problem"&gt;Manage the&amp;nbsp;problem&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;It seems that there is some hardware problems on resume.  The best way to manage
that is to blacklist these hardware.  When looking at the freezing screen, the
first problem is given by the the &lt;code&gt;nouveau&lt;/code&gt; driver.  In order to blacklist the
&lt;code&gt;nouveau&lt;/code&gt; driver,  we will add the following line into the
&lt;code&gt;/etc/modprobe.d/blacklist.conf&lt;/code&gt; file.  You can use any file into this
directory; as long as it its name ends with &lt;code&gt;.conf&lt;/code&gt;, it will be&amp;nbsp;parsed.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="txt"&gt;blacklist nouveau&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;After after a reboot, you should now be able to suspend your computer and resume
it without a&amp;nbsp;freeze!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="archlinux"></category><category term="graphic"></category></entry><entry><title>Fix a problem with fonts in web browser</title><link href="https://hole.tuziwo.info/fix-a-problem-with-fonts-in-web-browser.html" rel="alternate"></link><published>2013-10-29T00:00:00+01:00</published><updated>2013-10-29T00:00:00+01:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2013-10-29:/fix-a-problem-with-fonts-in-web-browser.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_the_problem"&gt;The&amp;nbsp;problem&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In your browser, you may have problems on some websites displaying strange
fonts.  For example, you may have seen the following fonts on&amp;nbsp;Github.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="images/font-problem.png" alt="Font problem in web browser" width="800"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This problem is due to bitmap&amp;nbsp;font.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_solution"&gt;Solution&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To deactivate bitmap fonts, you can use existing font configuration files you
can find into &lt;code&gt;/etc …&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_the_problem"&gt;The&amp;nbsp;problem&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In your browser, you may have problems on some websites displaying strange
fonts.  For example, you may have seen the following fonts on&amp;nbsp;Github.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="imageblock"&gt;
&lt;div class="content"&gt;
&lt;img src="images/font-problem.png" alt="Font problem in web browser" width="800"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This problem is due to bitmap&amp;nbsp;font.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_solution"&gt;Solution&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To deactivate bitmap fonts, you can use existing font configuration files you
can find into &lt;code&gt;/etc/fonts/conf.avail&lt;/code&gt;.  To avoid bitmap fonts, you just need to
link the &lt;code&gt;70-no-bitmaps.conf&lt;/code&gt; into &lt;code&gt;/etc/fonts/conf.d&lt;/code&gt; directory.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ cd /etc/fonts
$ ln -s conf.avail/70-no-bitmaps.conf conf.d/&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now, you can restart your X server for this new configuration taking&amp;nbsp;effect.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_references"&gt;References&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://wiki.archlinux.org/index.php/Font_Configuration#Disable_bitmap_fonts"&gt;Arch
font configuration (tip on bitmap&amp;nbsp;fonts)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="archlinux"></category><category term="web"></category><category term="font"></category></entry><entry><title>In the rabbit hole - Presentation</title><link href="https://hole.tuziwo.info/in-the-rabbit-hole-presentation.html" rel="alternate"></link><published>2013-10-21T00:00:00+02:00</published><updated>2013-10-21T00:00:00+02:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2013-10-21:/in-the-rabbit-hole-presentation.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This is the first post of a new blog.  This blog will mainly talk about computer
s and&amp;nbsp;programmation.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_the_blog"&gt;The&amp;nbsp;blog&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_which_system"&gt;Which&amp;nbsp;system?&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To run this blog, I used &lt;a href="http://docs.getpelican.com"&gt;Pelican&lt;/a&gt; which is very
simple to use.  With this blog system, I can write my articles in different
markdown syntaxes …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This is the first post of a new blog.  This blog will mainly talk about computer
s and&amp;nbsp;programmation.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_the_blog"&gt;The&amp;nbsp;blog&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_which_system"&gt;Which&amp;nbsp;system?&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To run this blog, I used &lt;a href="http://docs.getpelican.com"&gt;Pelican&lt;/a&gt; which is very
simple to use.  With this blog system, I can write my articles in different
markdown syntaxes (&lt;a href="http://en.wikipedia.org/wiki/Markdown"&gt;Markdown&lt;/a&gt;,
&lt;a href="http://en.wikipedia.org/wiki/ReStructuredText"&gt;reStructuredText&lt;/a&gt; or
&lt;a href="http://en.wikipedia.org/wiki/Asciidoc"&gt;AsciiDoc&lt;/a&gt;) and publish it as a static
website; indeed, it creates the &lt;span class="caps"&gt;HTML&lt;/span&gt; files and publish them on the server.  Easy
to install, easy to use, easy to backup and easy to begin&amp;nbsp;;-)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="pelican"></category></entry><entry><title>Installing printer on GNOME 3</title><link href="https://hole.tuziwo.info/installing-printer-on-gnome-3.html" rel="alternate"></link><published>2013-08-11T00:00:00+02:00</published><updated>2013-08-11T00:00:00+02:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2013-08-11:/installing-printer-on-gnome-3.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Installing a printer on an Arch Linux with &lt;span class="caps"&gt;GNOME&lt;/span&gt; 3 seems to be a little bugged.
The printer is a &lt;span class="caps"&gt;HP&lt;/span&gt; LaserJet M1536 on an intranet (not a direct&amp;nbsp;plugging).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_installing_the_service_for_printers"&gt;Installing the service for&amp;nbsp;printers&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;What else than &lt;span class="caps"&gt;CUPS&lt;/span&gt;?  You can install the &lt;code&gt;cups&lt;/code&gt; package which is the main …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Installing a printer on an Arch Linux with &lt;span class="caps"&gt;GNOME&lt;/span&gt; 3 seems to be a little bugged.
The printer is a &lt;span class="caps"&gt;HP&lt;/span&gt; LaserJet M1536 on an intranet (not a direct&amp;nbsp;plugging).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_installing_the_service_for_printers"&gt;Installing the service for&amp;nbsp;printers&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;What else than &lt;span class="caps"&gt;CUPS&lt;/span&gt;?  You can install the &lt;code&gt;cups&lt;/code&gt; package which is the main
reference about printing&amp;nbsp;service.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ pacman -S cups&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_installing_the_driver"&gt;Installing the&amp;nbsp;driver&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You may also install the driver for the printer.  In the case of a &lt;span class="caps"&gt;HP&lt;/span&gt; LaserJet
1536, the driver is installed with &lt;code&gt;hplip&lt;/code&gt; package.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ pacman -S hplip&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_starting_cups_service"&gt;Starting &lt;span class="caps"&gt;CUPS&lt;/span&gt;&amp;nbsp;service&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You can start the &lt;span class="caps"&gt;CUPS&lt;/span&gt; daemon with &lt;code&gt;systemd&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ systemctl start cupsd&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;However, this will only start the daemon for the current session.  In order to
start it at every boot, use the following&amp;nbsp;command.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ systemctl enable cups&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_adding_the_printer"&gt;Adding the&amp;nbsp;printer&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This is where the problem begins!  You may try to add the printer through the
&lt;span class="caps"&gt;GNOME&lt;/span&gt; interface.  Go in the preference menu, then the icon about printers.
Click on add a printer.  If the printer is on your intranet, you should see it
after a small time of loading.  Click on it to add the printer.  You may have an
error on this step.  Why this is not working? No&amp;nbsp;idea.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;However, the printer can also be added through the &lt;span class="caps"&gt;CUPS&lt;/span&gt; interface.  Open your
web browser and go to your local port 631
(&lt;a href="http://localhost:631/admin"&gt;localhost:631/admin&lt;/a&gt;).  You will be asked for a
login and a password.  These are the ones about the root account of your
computer.  Now, you can add the printer, it should&amp;nbsp;work.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_possible_errors"&gt;Possible&amp;nbsp;errors&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_the_printer_does_not_appear"&gt;The printer does not&amp;nbsp;appear&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;It seems that &lt;span class="caps"&gt;GNOME&lt;/span&gt; 3 has problems communicating with &lt;span class="caps"&gt;CUPS&lt;/span&gt;.  In fact, the
printers does not appear into the &lt;span class="caps"&gt;GNOME&lt;/span&gt; &lt;span class="caps"&gt;PDF&lt;/span&gt; viewer.  You may try with Evince,
which is a nice &lt;span class="caps"&gt;PDF&lt;/span&gt; viewer.  Evince had no problem about seeing the installed&amp;nbsp;printers.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_references"&gt;References&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://wiki.archlinux.org/index.php/Cups"&gt;&lt;span class="caps"&gt;CUPS&lt;/span&gt; on Arch&amp;nbsp;Linux&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://alien.slackbook.org/dokuwiki/doku.php?id=slackware%3acups"&gt;&lt;span class="caps"&gt;CUPS&lt;/span&gt;
local&amp;nbsp;port&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.linuxquestions.org/questions/linux-software-2/cups-username-and-password-156986/"&gt;&lt;span class="caps"&gt;CUPS&lt;/span&gt;
username and&amp;nbsp;password&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="archlinux"></category><category term="gnome"></category><category term="cups"></category></entry><entry><title>Installing Skype on Arch Linux 64 bits</title><link href="https://hole.tuziwo.info/installing-skype-on-arch-linux-64-bits.html" rel="alternate"></link><published>2013-08-11T00:00:00+02:00</published><updated>2013-08-11T00:00:00+02:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2013-08-11:/installing-skype-on-arch-linux-64-bits.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Skype is a mess since there is always problem using it on Linux.  However, it&amp;#8217;s
probably one of the best VoIP software and at least, one of the most used,
especially in business&amp;nbsp;communications.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The installation proposed in this article is to install Skype on a 64 bits …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Skype is a mess since there is always problem using it on Linux.  However, it&amp;#8217;s
probably one of the best VoIP software and at least, one of the most used,
especially in business&amp;nbsp;communications.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The installation proposed in this article is to install Skype on a 64 bits Arch
Linux.  One of the main problem, is the &amp;#8220;64 bits&amp;#8221; because Skype is still a 32
bits&amp;nbsp;software.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_installing_skype"&gt;Installing&amp;nbsp;Skype&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Because Skype is a 32 bits software, you need to configure &lt;code&gt;pacman&lt;/code&gt; to be able
to install 32 bits software through the &lt;code&gt;multilib&lt;/code&gt; repository.  To do that,
uncomment the following lines into &lt;code&gt;/etc/pacman.conf&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;[multilib]
Include = /etc/pacman.d/mirrorlist&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now, run some update of &lt;code&gt;pacman&lt;/code&gt; to be able to install&amp;nbsp;Skype.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ pacman -Syyu
$ pacman -S skype&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_the_problem"&gt;The&amp;nbsp;problem&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You should now be able to run Skype and connect to your account.  Moreover, you
should be able to chat with your contacts with no problem.  However, if you try
to call someone or test your audio configuration, it will just hang up.  Your
contact will never see this&amp;nbsp;call.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This problem is an audio&amp;nbsp;problem.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_installing_audio_stuff"&gt;Installing audio&amp;nbsp;stuff&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I will not enter in the details of &lt;span class="caps"&gt;ALSA&lt;/span&gt;, PulseAudio or other stuff because I
don&amp;#8217;t understanding a thing about these softwares.  However, you should be able
to make call with Skype installing two more 32 bits packages: &lt;code&gt;lib32-libpulse&lt;/code&gt;
and &lt;code&gt;lib32-alsa-plugins&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ pacman -S lib32-libpulse lib32-alsa-plugins&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now, you should be able to make your &amp;#8220;Echo / Sound Test Service&amp;#8221; or call your
best friend to tell hom this&amp;nbsp;story!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_possible_errors"&gt;Possible&amp;nbsp;errors&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_microphone_doesnt_work"&gt;Microphone doesn&amp;#8217;t&amp;nbsp;work&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Don&amp;#8217;t worry, it may be nothing.  Go to the &lt;span class="caps"&gt;GNOME&lt;/span&gt; preferences, inside &lt;code&gt;Sound''
configuration.  Now choose the &lt;/code&gt;Input&amp;#8221; tab.  You need to activate the
microphone by switching the &amp;#8220;On/Off&amp;#8221; button on the right.  You also may
increase the volume to your&amp;nbsp;convenience.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_references"&gt;References&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://wiki.archlinux.org/index.php/PulseAudio#Backend_Configuration"&gt;&lt;span class="caps"&gt;ALSA&lt;/span&gt;
Backend&amp;nbsp;configuration&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://bbs.archlinux.org/viewtopic.php?pid=1230842"&gt;audio problem with&amp;nbsp;Skype&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="archlinux"></category><category term="skype"></category></entry><entry><title>Install Eclipse on GNOME 3</title><link href="https://hole.tuziwo.info/install-eclipse-on-gnome-3.html" rel="alternate"></link><published>2013-05-11T00:00:00+02:00</published><updated>2013-05-11T00:00:00+02:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2013-05-11:/install-eclipse-on-gnome-3.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I will install Eclipse and add an entry to &lt;span class="caps"&gt;GNOME&lt;/span&gt; to make Eclipse an application.
I use the &amp;#8220;Eclipse &lt;span class="caps"&gt;IDE&lt;/span&gt; for Java &lt;span class="caps"&gt;EE&lt;/span&gt; Developpers&amp;#8221; version and I&amp;#8217;m currently
using &lt;span class="caps"&gt;GNOME&lt;/span&gt;&amp;nbsp;3.10.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_download_and_install_eclipse"&gt;Download and install&amp;nbsp;Eclipse&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To download Eclipse, you can go to &lt;a href="http://eclipse.org/downloads/" class="bare"&gt;http://eclipse.org/downloads/&lt;/a&gt;.  Once …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I will install Eclipse and add an entry to &lt;span class="caps"&gt;GNOME&lt;/span&gt; to make Eclipse an application.
I use the &amp;#8220;Eclipse &lt;span class="caps"&gt;IDE&lt;/span&gt; for Java &lt;span class="caps"&gt;EE&lt;/span&gt; Developpers&amp;#8221; version and I&amp;#8217;m currently
using &lt;span class="caps"&gt;GNOME&lt;/span&gt;&amp;nbsp;3.10.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_download_and_install_eclipse"&gt;Download and install&amp;nbsp;Eclipse&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To download Eclipse, you can go to &lt;a href="http://eclipse.org/downloads/" class="bare"&gt;http://eclipse.org/downloads/&lt;/a&gt;.  Once it&amp;#8217;s
downloaded, you can extract it to &lt;code&gt;/opt/&lt;/code&gt;.  You should have the binary of
Eclipse in &lt;code&gt;/opt/eclipse/eclipse&lt;/code&gt;.  You may extract Eclipse into
&lt;code&gt;/opt/eclipse-4.3.0&lt;/code&gt; and create a symbolic link; this way, you can easily install a new
version of eclipse by just modifying the&amp;nbsp;link.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ cd /opt
$ ln -s eclipse-4.3.0/ eclipse&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_download_a_svg_icon_for_eclipse"&gt;Download a &lt;span class="caps"&gt;SVG&lt;/span&gt; icon for&amp;nbsp;Eclipse&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In order to make a cute icon in the &lt;span class="caps"&gt;GNOME&lt;/span&gt; launcher, we can also download an icon
(in &lt;span class="caps"&gt;SVG&lt;/span&gt; format) for&amp;nbsp;Eclipse.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ cd /opt/eclipse/
$ curl -o /usr/share/pixmaps/eclipse.svg https://projects.archlinux.org/svntogit/packages.git/plain/trunk/eclipse.svg\?h\=packages/eclipse&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_create_the_launcher_for_gnome"&gt;Create the launcher for &lt;span class="caps"&gt;GNOME&lt;/span&gt;&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To create the launcher, you need to create the following file
&lt;code&gt;/usr/share/applications/eclipse.desktop&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="txt"&gt;[Desktop Entry]
Encoding=UTF-8
Version=4.3.0
Type=Application
NoDisplay=false
Exec=/opt/eclipse/eclipse
Name=Eclipse
Comment=Launcher for Eclipse
Icon=eclipse&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This is it.  You can now try&amp;nbsp;it!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_references"&gt;References&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://www.surlyjake.com/blog/2011/12/30/create-a-custom-application-launcher-in-gnome3/"&gt;Create
a Custom Application Launcher on &lt;span class="caps"&gt;GNOME3&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="archlinux"></category><category term="gnome"></category><category term="eclipse"></category></entry><entry><title>Install XWiki on Arch Linux</title><link href="https://hole.tuziwo.info/install-xwiki-on-arch.html" rel="alternate"></link><published>2013-05-11T00:00:00+02:00</published><updated>2013-05-11T00:00:00+02:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2013-05-11:/install-xwiki-on-arch.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In this article, I detail the installation of Java and XWiki on an freshly
installed Arch Linux.  I will use the open source implementation of Java,
OpenJDK and the generic installer of XWiki&amp;nbsp;5.2.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_install_java"&gt;Install&amp;nbsp;Java&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;On Arch Linux with OpenJDK, you need to install the &lt;code&gt;jre7-openjdk&lt;/code&gt; and …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In this article, I detail the installation of Java and XWiki on an freshly
installed Arch Linux.  I will use the open source implementation of Java,
OpenJDK and the generic installer of XWiki&amp;nbsp;5.2.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_install_java"&gt;Install&amp;nbsp;Java&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;On Arch Linux with OpenJDK, you need to install the &lt;code&gt;jre7-openjdk&lt;/code&gt; and
&lt;code&gt;jdk7-openjdk&lt;/code&gt; packages.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ pacman -S jre7-openjdk jdk7-openjdk&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_install_xwiki"&gt;Install&amp;nbsp;XWiki&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You first need to download the generic installed on
&lt;a href="http://enterprise.xwiki.org/xwiki/bin/view/Main/Download"&gt;xwiki.org&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Once it is done, you can launch the installer &lt;strong&gt;with root privileges&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ java -jar xwiki-enterprise-installer-generic-5.2-standard.jar&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You can now follow the instruction.  I choose to install XWiki into
&lt;code&gt;/opt/xwiki-5.2&lt;/code&gt;.  If it is your first installation, you should install the
&lt;strong&gt;Default Wiki&lt;/strong&gt; because it will create a bunch of useful wiki pages to&amp;nbsp;start.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;When installation is finished, the installer asks for icon creation.  I disable
all icon creation because we do not really need&amp;nbsp;them.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To finish this installation, I created a symbolic link on the directory of XWiki&amp;nbsp;installation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ cd /opt
$ ln -s xwiki-5.2/ xwiki&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_launch_xwiki"&gt;Launch&amp;nbsp;XWiki&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To launch XWiki, you have a start script into the freshly installed&amp;nbsp;directory.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ cd /opt/xwiki
$ sh start_xwiki.sh&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You should now be able to access your installed XWiki on &lt;a href="http://localhost:8080" class="bare"&gt;http://localhost:8080&lt;/a&gt;
and&amp;nbsp;enjoy!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_bonus"&gt;Bonus&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_log_in"&gt;Log&amp;nbsp;in&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To log in this newly installed XWiki, you may use the default&amp;nbsp;account:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;login:&amp;nbsp;&amp;#8220;Admin&amp;#8221;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;password:&amp;nbsp;&amp;#8220;admin&amp;#8221;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_applications_for_developers"&gt;Applications for&amp;nbsp;developers&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;If you want to develop some new applications for XWiki, you may install the
following&amp;nbsp;applications:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Collection Application: Makes easier the creation of a &lt;span class="caps"&gt;XAR&lt;/span&gt;&amp;nbsp;file&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Syntax Highlighting Application: Syntax highlighting for source, even for&amp;nbsp;Velocity&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;AutoCompletion Application: Autocompletion in Velocity&amp;nbsp;code&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To install them, you need to be logged in with the &lt;code&gt;Admin'' accound.  Then,
click on &lt;/code&gt;More applications&amp;#8221; in the panel on the right.  You will see
&amp;#8220;Install new applications&amp;#8221;; you can click on&amp;nbsp;it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Then search for each extension and click the &lt;code&gt;Install'' button on the right
then the &lt;/code&gt;Continue&amp;#8221;&amp;nbsp;button.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_reveal_hidden_pages"&gt;Reveal hidden&amp;nbsp;pages&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;By default, XWiki hide some pages, mainly pages that are for developers and
should not be displayed to a lambda user when using the search field (on the
top-right).  However, this could difficult to find some useful pages for a&amp;nbsp;developer.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To make these page visible, you need to be logged in with the &lt;code&gt;Admin'' account.
Then go in the &lt;/code&gt;Preferences&amp;#8221; in the profile (right in the top-bar).  Click on
the edit button (the little pen of the top right of the gray frame).  You will
have the possibility to change the property &lt;code&gt;DISPLAY HIDDEN DOCUMENTS'' to
&lt;/code&gt;Yes&amp;#8221;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You may also change the &lt;code&gt;DEFAULT EDITOR TO USE'' to &lt;/code&gt;Text&amp;#8221; if you do not want
&lt;span class="caps"&gt;WYSIWYG&lt;/span&gt; edition by&amp;nbsp;default.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_references"&gt;References&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://platform.xwiki.org/xwiki/bin/view/AdminGuide/InstallationStandalone"&gt;Installing
the Standalone&amp;nbsp;Distribution&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="archlinux"></category><category term="java"></category><category term="xwiki"></category></entry><entry><title>Configure X server</title><link href="https://hole.tuziwo.info/configure-x-server.html" rel="alternate"></link><published>2013-04-11T00:00:00+02:00</published><updated>2013-04-11T00:00:00+02:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2013-04-11:/configure-x-server.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To configure the X server on an fresh install of Arch Linux, you&amp;nbsp;need:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Install the graphic&amp;nbsp;driver&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Remove &lt;code&gt;nouveau&lt;/code&gt; or any &lt;code&gt;nvidia&lt;/code&gt; driver&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install a desktop environment (&lt;span class="caps"&gt;GNOME&lt;/span&gt; in this&amp;nbsp;case)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure the&amp;nbsp;trackpad&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_install_the_graphic_driver"&gt;Install the graphic&amp;nbsp;driver&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In this article, I will not detail the procedure to …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To configure the X server on an fresh install of Arch Linux, you&amp;nbsp;need:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Install the graphic&amp;nbsp;driver&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Remove &lt;code&gt;nouveau&lt;/code&gt; or any &lt;code&gt;nvidia&lt;/code&gt; driver&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install a desktop environment (&lt;span class="caps"&gt;GNOME&lt;/span&gt; in this&amp;nbsp;case)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure the&amp;nbsp;trackpad&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_install_the_graphic_driver"&gt;Install the graphic&amp;nbsp;driver&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In this article, I will not detail the procedure to install a graphic driver for
any &lt;span class="caps"&gt;ATI&lt;/span&gt; or NVidia graphic card.  I will only focus on the basic graphic card of
the motherboard which, in my case, is an Intel&amp;nbsp;one.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To install the basic graphic driver for this Intel graphic card, you need to
install the package &lt;code&gt;xf86-video-intel&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ pacman -S xf86-video-intel&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;And that&amp;#8217;s&amp;nbsp;it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_removing_other_graphic_drivers"&gt;Removing other graphic&amp;nbsp;drivers&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To make sure your Intel graphic driver will be chosen, remove all other graphic
driver that may have been installed during the default&amp;nbsp;installation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ pacman -R nvidia xf86-video-nouveau&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_install_the_desktop_environment"&gt;Install the desktop&amp;nbsp;environment&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To install the desktop environment (&lt;span class="caps"&gt;GNOME&lt;/span&gt; in this case), you just need to
install the &lt;code&gt;gnome&lt;/code&gt; package.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ pacman -S gnome&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;By default, it will also install &lt;span class="caps"&gt;GDM&lt;/span&gt;, the &lt;span class="caps"&gt;GNOME&lt;/span&gt; Display Manager.  In order to
start it, we need a little more configuration.  First, we activate &lt;span class="caps"&gt;GDM&lt;/span&gt; in the
&lt;code&gt;systemd&lt;/code&gt; system.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ systemctl enable gdm.service&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Secondly, you may have a non-&lt;span class="caps"&gt;US&lt;/span&gt; keyboard.  However, &lt;span class="caps"&gt;GDM&lt;/span&gt; will take a &lt;span class="caps"&gt;US&lt;/span&gt; keyboard
map by default.  To change this, you can edit a X11 configuration file.  For
example, you can edit &lt;code&gt;/etc/X11/xorg.conf.d/10-evdev.conf&lt;/code&gt; and change the
following&amp;nbsp;lines&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;Section "InputClass"
	Identifier "evdev keyboard catchall"
	MatchIsKeyboard "on"
	MatchDevicePath "/dev/input/event*"
	Driver "evdev"
EndSection&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;into&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;Section "InputClass"
	Identifier "evdev keyboard catchall"
	MatchIsKeyboard "on"
	MatchDevicePath "/dev/input/event*"
	Driver "evdev"
	Option "XkbLayout" "fr"
EndSection&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_configure_the_trackpad"&gt;Configure the&amp;nbsp;trackpad&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Your trackpad may not respond with the previous installation.  It is probably
because you miss the &lt;code&gt;xf86-input-synaptics&lt;/code&gt; package.  You can check if it is&amp;nbsp;installed.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ pacman -Qs xf86-input-synaptics&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;If it is not, you probably want to install&amp;nbsp;it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ pacman -S xf86-input-synaptics&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_possible_errors"&gt;Possible&amp;nbsp;errors&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_nouveau_is_still_ativated"&gt;&lt;code&gt;nouveau&lt;/code&gt; is still&amp;nbsp;ativated&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To check if &lt;code&gt;nouveau&lt;/code&gt; is activated, use the &lt;code&gt;lsmod&lt;/code&gt; command.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ lsmod | grep 'nouveau'&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;If you find &lt;code&gt;nouveau&lt;/code&gt; somewhere and that you&amp;#8217;re desktop environment still
doesn&amp;#8217;t start, you may try to put &lt;code&gt;nouveau&lt;/code&gt; on a&amp;nbsp;blacklist.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ echo 'blacklist nouveau' &amp;gt;&amp;gt; /etc/modprobe.d/blacklist.conf&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="archlinux"></category><category term="graphic"></category><category term="gnome"></category></entry><entry><title>Install Arch Linux on UEFI/GPT computer with BTRFS support</title><link href="https://hole.tuziwo.info/install-arch-linux-on-uefi-gpt-computer-with-btrfs-support.html" rel="alternate"></link><published>2013-02-11T00:00:00+01:00</published><updated>2013-02-11T00:00:00+01:00</updated><author><name>woshilapin</name></author><id>tag:hole.tuziwo.info,2013-02-11:/install-arch-linux-on-uefi-gpt-computer-with-btrfs-support.html</id><summary type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The goal of this article is to explain the installation of Linux
distribution with some&amp;nbsp;specificities:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The Linux distribution is an &lt;a href="http://www.archlinux.org"&gt;Arch&amp;nbsp;Linux&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The computer is &lt;span class="caps"&gt;UEFI&lt;/span&gt;&amp;nbsp;compatible&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The disk is a &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;span class="caps"&gt;BTRFS&lt;/span&gt; will be the file system&amp;nbsp;used&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use the &lt;span class="caps"&gt;BTRFS&lt;/span&gt; capabilities to split the &lt;code&gt;/&lt;/code&gt;, &lt;code&gt;/opt&lt;/code&gt;, &lt;code&gt;/home …&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="sect1"&gt;
&lt;h2 id="_introduction"&gt;Introduction&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The goal of this article is to explain the installation of Linux
distribution with some&amp;nbsp;specificities:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The Linux distribution is an &lt;a href="http://www.archlinux.org"&gt;Arch&amp;nbsp;Linux&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The computer is &lt;span class="caps"&gt;UEFI&lt;/span&gt;&amp;nbsp;compatible&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The disk is a &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;span class="caps"&gt;BTRFS&lt;/span&gt; will be the file system&amp;nbsp;used&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use the &lt;span class="caps"&gt;BTRFS&lt;/span&gt; capabilities to split the &lt;code&gt;/&lt;/code&gt;, &lt;code&gt;/opt&lt;/code&gt;, &lt;code&gt;/home&lt;/code&gt; and &lt;code&gt;/var&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The network is a wireless connection, configured with &lt;code&gt;netctl&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_run_the_arch_linux_installer"&gt;Run the Arch Linux&amp;nbsp;installer&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;First of all, you need to download the &lt;span class="caps"&gt;ISO&lt;/span&gt; (around 550Mb) from the Arch Linux
site
(&lt;a href="magnet:?xt=urn:btih:4343552155062db9a7a05a10904f5c68f98b1216&amp;amp;dn=archlinux-2013.10.01-dual.iso&amp;amp;tr=udp://tracker.archlinux.org:6969&amp;amp;tr=http://tracker.archlinux.org:6969/announce"&gt;magnet&lt;/a&gt;
or &lt;a href="https://www.archlinux.org/releng/releases/2013.10.01/torrent/)"&gt;torrent&lt;/a&gt;) and
copy it on a &lt;span class="caps"&gt;USB&lt;/span&gt; key or burn it on a &lt;span class="caps"&gt;CD&lt;/span&gt;.  To make a copy on a &lt;span class="caps"&gt;USB&lt;/span&gt; key, you can
use the &lt;code&gt;dd&lt;/code&gt; tool.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ dd if=archlinux-2013.10.01-dual.iso of=/dev/sdb&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;considering &lt;code&gt;/dev/sdb&lt;/code&gt; is the device&amp;#8217;s file for the &lt;span class="caps"&gt;USB&lt;/span&gt;&amp;nbsp;key.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;On Mac &lt;span class="caps"&gt;OS&lt;/span&gt; X, you will not have &lt;code&gt;/dev/sdb&lt;/code&gt; but something like &lt;code&gt;/dev/rdisk2&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You can now run your Arch Linux on the computer you want to&amp;nbsp;install.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_initializations"&gt;Initializations&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;First of all, you may want to change the keyboard layouts and the locales.  For
the keyboard layout, use the &lt;code&gt;loadkeys&lt;/code&gt; tool.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ loadkeys fr-pc&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;For the locales, edit the &lt;code&gt;/etc/locale.gen&lt;/code&gt; file and uncomment the locale your
want (you can uncomment more than one).  Then generate the new locales and
export your new default&amp;nbsp;locale.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ locale-gen
$ echo LANG=fr_FR.UTF-8 &amp;gt; /etc/locale.conf
$ export LANG=fr_FR.UTF-8&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You may change the terminal&amp;#8217;s font with the&amp;nbsp;following.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ setfont Lat2-Terminus16&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_partitionning"&gt;Partitionning&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Our installation will consider that the computer is &lt;span class="caps"&gt;UEFI&lt;/span&gt; compatible.  &lt;span class="caps"&gt;UEFI&lt;/span&gt; is
compatible with both &lt;span class="caps"&gt;MBR&lt;/span&gt; and &lt;span class="caps"&gt;GPT&lt;/span&gt; partitionning.  However, &lt;span class="caps"&gt;GPT&lt;/span&gt; is the standard
way to do it.  In order to partition the disk, we will use the &lt;span class="caps"&gt;GPT&lt;/span&gt; version of
&lt;code&gt;fdisk&lt;/code&gt;, which is &lt;code&gt;gdisk&lt;/code&gt;, on the main disk &lt;code&gt;/dev/sda&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ gdisk /dev/sda&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;&lt;code&gt;gdisk&lt;/code&gt; brings you to a new shell.  We will create 2&amp;nbsp;partitions:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The first partition will be the &lt;span class="caps"&gt;EFI&lt;/span&gt;&amp;nbsp;partition&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The second partition will be the partition for the Linux&amp;nbsp;system&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;These are the operations you should&amp;nbsp;do:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="olist arabic"&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;
&lt;p&gt;type &lt;code&gt;o&lt;/code&gt; and validate to create the &lt;span class="caps"&gt;GPT&lt;/span&gt;&amp;nbsp;partitionning&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;type &lt;code&gt;n&lt;/code&gt; and validate to create a new&amp;nbsp;partition&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;enter the partition number or just validate for the default (the default
should be&amp;nbsp;good)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;enter the first sector or just validate for the default (the default should
be&amp;nbsp;good)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;enter the last sector or the size of your volume; for &lt;span class="caps"&gt;EFI&lt;/span&gt;, enter &lt;code&gt;+512M&lt;/code&gt; and&amp;nbsp;validate&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;enter the type of the partition; for &lt;span class="caps"&gt;EFI&lt;/span&gt;, enter &lt;code&gt;EF00&lt;/code&gt; and&amp;nbsp;validate&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;type &lt;code&gt;n&lt;/code&gt; and validate to create a new&amp;nbsp;partition&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;enter the partition number or just validate for the default (the default
should be&amp;nbsp;good)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;enter the first sector or just validate for the default (the default should
be&amp;nbsp;good)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;enter the last sector or the size of your volume; for Linux system, validate
the default which is the last sector of the&amp;nbsp;disk&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;enter the type of the partition; for Linux system, enter &lt;code&gt;8300&lt;/code&gt; and&amp;nbsp;validate&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;type &lt;code&gt;w&lt;/code&gt; and validate to write all the modifications on the&amp;nbsp;disk.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_formatting"&gt;Formatting&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The formatting is pretty easy.  The &lt;span class="caps"&gt;EFI&lt;/span&gt; partition should be format in a &lt;span class="caps"&gt;FAT&lt;/span&gt;
filesystem (16 or 32).  The second partition will be format in &lt;span class="caps"&gt;BTRFS&lt;/span&gt; since it
one of the purpose of this&amp;nbsp;article.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ mkfs.vfat -F32 -n "EFI" /dev/sda1
$ mkfs.btrfs -L "Arch Linux" /dev/sda2&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_managing_the_btrfs_subvolumes"&gt;Managing the &lt;span class="caps"&gt;BTRFS&lt;/span&gt;&amp;nbsp;subvolumes&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_mounting_the_main_btrfs_volume"&gt;Mounting the main &lt;span class="caps"&gt;BTRFS&lt;/span&gt;&amp;nbsp;volume&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;First of all, we will mount the &lt;span class="caps"&gt;BTRFS&lt;/span&gt;&amp;nbsp;partition.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ mkdir -p /mnt/btrfs-root
$ mount -o defaults,relatime,ssd,discard,space_cache /dev/sda2 /mnt/btrfs-root&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;&lt;code&gt;discard&lt;/code&gt; and &lt;code&gt;ssd&lt;/code&gt; mount options are optimizations for &lt;span class="caps"&gt;SSD&lt;/span&gt; drives.  &lt;code&gt;discard&lt;/code&gt;
is to activate &lt;code&gt;`Discard/TRIM'' optimizations and `ssd&lt;/code&gt; is for specific &lt;span class="caps"&gt;BTRFS&lt;/span&gt;
optimization on &lt;span class="caps"&gt;SSD&lt;/span&gt;&amp;nbsp;drives.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_creating_and_mounting_the_btrfs_subvolumes"&gt;Creating and mounting the &lt;span class="caps"&gt;BTRFS&lt;/span&gt;&amp;nbsp;subvolumes&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Then we can create the subvolumes in the &lt;span class="caps"&gt;BTRFS&lt;/span&gt;&amp;nbsp;partition.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ mkdir -p /mnt/btrfs-root/__snapshot
$ mkdir -p /mnt/btrfs-root/__active
$ btrfs subvolume create /mnt/btrfs-root/__active/ROOT
$ btrfs subvolume create /mnt/btrfs-root/__active/home
$ btrfs subvolume create /mnt/btrfs-root/__active/opt
$ btrfs subvolume create /mnt/btrfs-root/__active/var&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We can now mount the subvolumes in the &lt;strong&gt;right order&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ mkdir -p /mnt/btrfs-active
$ mount -o \
	defaults,nodev,relatime,ssd,discard,space_cache,subvol=__active/ROOT \
	/dev/sda2 /mnt/btrfs-active&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We create the directories in this new-mounted subvolume and mount the other&amp;nbsp;subvolumes.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ mkdir -p /mnt/btrfs-active/home
$ mkdir -p /mnt/btrfs-active/opt
$ mkdir -p /mnt/btrfs-active/var/lib
$ mount -o \
	defaults,nosuid,nodev,relatime,ssd,discard,subvol=__active/home \
	/dev/sda2 /mnt/btrfs-active/home
$ mount -o \
	defaults,nosuid,nodev,relatime,ssd,discard,subvol=__active/opt \
	/dev/sda2 /mnt/btrfs-active/opt
$ mount -o \
	defaults,nosuid,nodev,noexec,relatime,ssd,discard,subvol=__active/var \
	/dev/sda2 /mnt/btrfs-active/var&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_tricky_part_for_the_varlib_directory"&gt;Tricky part for the &lt;code&gt;/var/lib&lt;/code&gt; directory&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;However, the &lt;code&gt;/var/lib&lt;/code&gt; is the directory in which some interesting files are
installed and we want to keep them in the &lt;code&gt;__active/ROOT&lt;/code&gt; subvolume to make
easier the snapshot procedure.  Remember, we create a directory in this
subvolume. So we will bind&amp;nbsp;it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ mkdir -p /mnt/btrfs-active/var/lib
$ mount --bind /mnt/btrfs-root/__active/ROOT/var/lib \
	/mnt/btrfs-active/var/lib&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_mount_the_efi_partition_into_the_main_directory_layout"&gt;Mount the &lt;span class="caps"&gt;EFI&lt;/span&gt; partition into the main directory&amp;nbsp;layout&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;At this point, we should mount the &lt;span class="caps"&gt;EFI&lt;/span&gt; partition as the &lt;code&gt;/boot&lt;/code&gt; directory.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ mkdir -p /mnt/btrfs-active/boot
$ mount -o \
	defaults,nosuid,nodev,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro,discard \
	/dev/sda1 /mnt/btrfs-active/boot&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_install_the_base_system"&gt;Install the base&amp;nbsp;system&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Before being able to install the base system, you need to configure a network
connection.  If you want a wireless connection, you can simply use &lt;code&gt;wifi-menu&lt;/code&gt;.
It will display you a menu where you can choose a wireless network and enter
your password (in&amp;nbsp;clear).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You may update the list of mirrors &lt;code&gt;/etc/pacman.d/mirrorlist&lt;/code&gt; before running the following&amp;nbsp;command.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The &lt;code&gt;base&lt;/code&gt; package will install a base system for your Arch Linux.  Because we
use a &lt;span class="caps"&gt;BTRFS&lt;/span&gt; system, we also install &lt;code&gt;btrfs-progs&lt;/code&gt; package (we could install it
later&amp;nbsp;too).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ pacstrap /mnt/btrfs-active base btrfs-progs&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We must now generate and configure the &lt;code&gt;fstab&lt;/code&gt; file with the help of &lt;code&gt;genfstab&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ genfstab -U -p /mnt/btrfs-active &amp;gt;&amp;gt; /mnt/btrfs-active/etc/fstab&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You should modify the &lt;code&gt;/etc/fstab&lt;/code&gt; file and make it looks like something like
the&amp;nbsp;following.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="txt"&gt;tmpfs					/tmp		tmpfs	rw,nodev,nosuid 0 0
tmpfs					/dev/shm	tmpfs	rw,nodev,nosuid,noexec 0 0

# /dev/sda1 LABEL=Arch\x20Linux
UUID=...				/		btrfs	rw,nodev,relatime,ssd,discard,space_cache,subvol=__active/ROOT 0 0
UUID=...				/home		btrfs	rw,nodev,nosuid,relatime,ssd,discard,space_cache,subvol=__active/home 0 0
UUID=...				/opt		btrfs	rw,nodev,nosuid,relatime,ssd,discard,space_cache,subvol=__active/opt 0 0
UUID=...				/var		btrfs	rw,nodev,nosuid,noexec,relatime,ssd,discard,space_cache,subvol=__active/var 0 0
UUID=...				/run/btrfs-root	btrfs	rw,nodev,nosuid,noexec,relatime,ssd,discard,space_cache 0 0
/run/btrfs-root/__active/ROOT/var/lib	/var/lib	none	bind 0 0

# /dev/sdb1 LABEL=EFI
UUID=...	/boot	vfat rw,nosuid,nodev,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro,discard 0 2&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Be careful about the configuration of &lt;code&gt;/var/lib&lt;/code&gt;.  In fact,
we need to mount the main &lt;span class="caps"&gt;BTRFS&lt;/span&gt; partition in order to access the directory that
should be binded.  Moreover, do not forget to check the line about the &lt;code&gt;/boot&lt;/code&gt;
partition.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We also need to create the directory where the root &lt;span class="caps"&gt;BTRFS&lt;/span&gt; partition will mount
(see in the &lt;code&gt;fstab&lt;/code&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ mkdir -p /mnt/btrfs-active/run/btrfs-root&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_configure_the_base_system"&gt;Configure the base&amp;nbsp;system&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You will now root from the newly installed base system with a &lt;code&gt;arch-chroot&lt;/code&gt;.
The configuration begins with mainly the same operations that we have done&amp;nbsp;before.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ echo "KEYMAP=fr-pc" &amp;gt; /etc/vconsole.conf
$ echo "FONT=Lat2-Terminus16" &amp;gt;&amp;gt; /etc/vconsole.conf
$ echo "fr_FR.UTF-8 UTF-8" &amp;gt; /etc/locale.gen
$ locale-gen
$ echo "LANG=fr_FR.UTF-8" &amp;gt; /etc/locale.conf
$ export LANG=fr_FR.UTF-8
$ ln -s /usr/share/zoneinfo/Europe/Paris /etc/localtime
$ hwclock --systohc --utc
$ echo "mypc" &amp;gt; /etc/hostname
$ passwd&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_configure_a_wireless_network_connection"&gt;Configure a wireless network&amp;nbsp;connection&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We will configure a default profile for a wireless connection with &lt;span class="caps"&gt;SSID&lt;/span&gt;
&lt;code&gt;mySSID&lt;/code&gt; and a &lt;span class="caps"&gt;WPA&lt;/span&gt; security.  Then we will make this connection automatic with
&lt;code&gt;wpa_actiond&lt;/code&gt;.  Begin to install &lt;code&gt;wpa_actiond&lt;/code&gt; with the base package &lt;code&gt;netctl&lt;/code&gt;.
The &lt;code&gt;dialog&lt;/code&gt; package allow us the use of &lt;code&gt;wifi-menu&lt;/code&gt; to generate &lt;code&gt;netctl&lt;/code&gt;
profiles.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ pacman -S netctl iw dialog wpa_actiond&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Then create a &lt;code&gt;netctl&lt;/code&gt; profile from an example file.  You can either
automatically generate a profile file with &lt;code&gt;wifi-menu&lt;/code&gt; or use the manual
configuration&amp;nbsp;below.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ cp /etc/netctl/examples/wireless-wpa-config /etc/netctl/profile&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You should modify &lt;code&gt;/etc/netctl/profile&lt;/code&gt; to make it look like the&amp;nbsp;following.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="listingblock"&gt;
&lt;div class="content"&gt;
&lt;pre class="rouge highlight"&gt;&lt;code data-lang="txt"&gt;Description='A wpa_supplicant configuration file based wireless connection'
Interface=wlp3s0
Connection=wireless
Security=wpa-config
WPAConfigFile='/etc/wpa_supplicant/wpa_supplicant.conf'
IP=dhcp&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Do not forget to change the path to the &lt;code&gt;wpa_supplicant.conf&lt;/code&gt; file which should
be &lt;code&gt;/etc/wpa_supplicant/wpa_supplicant.conf&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now, we can configure the &lt;span class="caps"&gt;WPA&lt;/span&gt; configuration of our &lt;code&gt;mySSID&lt;/code&gt; wifi network.  To
configure this network, we use &lt;code&gt;wpa_passphrase&lt;/code&gt;.  We first backup the default
configuration&amp;nbsp;file.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ cp /etc/wpa_supplicant/wpa_supplicant.conf /etc/wpa_supplicant/wpa_supplicant.conf.example
$ wpa_passphrase "mySSID" "mypassword" &amp;gt; /etc/wpa_supplicant/wpa_supplicant.conf&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Do not forget the double quotes, especially if the &lt;span class="caps"&gt;SSID&lt;/span&gt; contains spaces.  You may
edit the file and remove the password which appear in&amp;nbsp;clear.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You can now enable this&amp;nbsp;service.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ systemctl enable netctl-auto@wlp3s0.service&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_configure_the_initial_ramdisk_environment"&gt;Configure the initial ramdisk&amp;nbsp;environment&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To generate the initial ramdisk, because you run with &lt;span class="caps"&gt;BTRFS&lt;/span&gt; partitions, you
should modify some hooks in the &lt;code&gt;/etc/mkinitcpio.conf&lt;/code&gt;.  We will add a hook for
&lt;code&gt;btrfs&lt;/code&gt;.  For this new hook, we must install the package &lt;code&gt;btrfs-progs&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Secondly, &lt;span class="caps"&gt;BTRFS&lt;/span&gt; does not have a robust check file system so if we have the
&lt;code&gt;fsck&lt;/code&gt; hook, it will display an error.  We have 2&amp;nbsp;solutions:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;We erase the &lt;code&gt;fsck&lt;/code&gt; hook and there will not have file system check anymore,
even if other partitions are not &lt;span class="caps"&gt;BTRFS&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We can create a fake &lt;code&gt;fsck.btrfs&lt;/code&gt; command&lt;/p&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ ln -s /usr/bin/true /usr/bin/fsck.btrfs
$ sed 's/^\(HOOKS=.*fsck\)\(.*$\)/\1 btrfs\2/g' -i mkinitcpio.conf
$ mkinitcpio -p linux&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_install_and_configure_the_bootloader"&gt;Install and configure the&amp;nbsp;bootloader&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;I choose &lt;code&gt;gummiboot&lt;/code&gt; bootloader which is a simple bootloader for &lt;span class="caps"&gt;EFI&lt;/span&gt; systems.
First of all, you install it.  Before installing it, you may mount the
&lt;code&gt;efivarfs&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ mount -t efivarfs efivarfs /sys/firmware/efi/efivarfs
$ pacman -S gummiboot
$ gummiboot install&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Now, we can configure the bootloader following the specifications propose by
&lt;a href="http://www.freedesktop.org" class="bare"&gt;http://www.freedesktop.org&lt;/a&gt; (see the &lt;a href="#sec2-references"&gt;references&lt;/a&gt;).  Before configuring it, we will get the
following&amp;nbsp;variable:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ export MACHINE_ID=`cat /etc/machine-id`
$ export KERNEL_VERSION=`uname -r`
$ export OS_IDENTIFIER=`cat /etc/os-release | grep ID | awk -F '=' '{print $2}'`
$ export MACHINE_HARDWARE=`uname -m`
$ export OS_VERSION=`echo $KERNEL_VERSION.$OS_IDENTIFIER.$MACHINE_HARDWARE`
$ export PARTUUID=`ls -l /dev/disk/by-partuuid/ | grep sda2 | awk '{print $9}'`&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Create an entry in &lt;code&gt;/boot/loader/entries&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ vi /boot/loader/entries/$MACHINE_ID-$OS_VERSION.conf&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;title		Arch Linux
version		&amp;lt;value of $OS_VERSION&amp;gt;
machine-id	&amp;lt;value of $MACHINE_ID&amp;gt;
options		root=PARTUUID=&amp;lt;value of $PARTUUID&amp;gt; rootflags=subvol=__active/ROOT rw
linux		/&amp;lt;value of $MACHINE_ID&amp;gt;/&amp;lt;value of $OS_VERSION&amp;gt;/linux
initrd		/&amp;lt;value of $MACHINE_ID&amp;gt;/&amp;lt;value of $OS_VERSION&amp;gt;/initrd&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We may also configure the main configuration file &lt;code&gt;/boot/loader/loader.conf&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;timeout		3
default		&amp;lt;name of the entries conf file, without the '.conf'&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The default should be fine since it use any entry file which begin with the
machine &lt;span class="caps"&gt;ID&lt;/span&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You should now create the directories and copy the images into&amp;nbsp;them.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ mkdir -p /boot/$MACHINE_ID/$OS_VERSION
$ cp /boot/vmlinuz-linux /boot/$MACHINE_ID/$OS_VERSION/linux
$ cp /boot/initramfs-linux.img /boot/$MACHINE_ID/$OS_VERSION/initrd&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_rebooting_the_system"&gt;Rebooting the&amp;nbsp;system&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Before rebooting, you should define a root password, unmount all the mounted filesystems and quit the
&lt;code&gt;chroot&lt;/code&gt; environment.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ umount /sys/firmware/efi/efivarfs
$ exit
$ umount -R /mnt/btrfs-active
$ umount -R /mnt/btrfs-root
$ reboot&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_possible_errors"&gt;Possible&amp;nbsp;errors&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_make_the_ramdisk_environment"&gt;Make the ramdisk&amp;nbsp;environment&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You may have the following messages during the creation of the&amp;nbsp;ramdisk.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;==&amp;gt; WARNING: Possibly missing firmware for module: aic94xx
==&amp;gt; WARNING: Possibly missing firmware for module: bfa
==&amp;gt; WARNING: Possibly missing firmware for module: smsmdtv&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;It is probably some missing firmware you may install&amp;nbsp;later.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_gummiboot_installation"&gt;Gummiboot&amp;nbsp;installation&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;When installing &lt;code&gt;gummiboot&lt;/code&gt; with &lt;code&gt;pacman&lt;/code&gt;, you may have the following error&amp;nbsp;message.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ pacman -S gummiboot
...
Copied /usr/lib/gummiboot/gummibootx64.efi to /boot/EFI/gummiboot/gummibootx64.efi
Copied /usr/lib/gummiboot/gummibootx64.efi to /boot/EFI/Boot/BOOTX64.efi
Failed to create EFI Boot variable entry: No such file or directory&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;If this is the case, you may try the following before trying to reinstall
&lt;code&gt;gummiboot&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ mount -t efivarfs efivarfs /sys/firmware/efi/efivarfs
$ pacman -S gummiboot&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_when_rebooting_crash_into_ramfs"&gt;When rebooting, crash into&amp;nbsp;ramfs&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You may crash into the &lt;code&gt;ramfs&lt;/code&gt; when rebooting.  This is probably because you
forget to indicate to the kernel which &lt;span class="caps"&gt;BTRFS&lt;/span&gt; subvolume is the default one.  You
may choose one of the two following solutions (both are explained in the above&amp;nbsp;configuration):&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Give the right option to the kernel with &lt;code&gt;rootflags&lt;/code&gt; (see above for&amp;nbsp;details)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Make one of the &lt;span class="caps"&gt;BTRFS&lt;/span&gt; subvolume the default.  You can list the subvolume with the following&amp;nbsp;command.&lt;/p&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ btrfs subvolume list -atp /mnt/btrfs-root&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;You should have something like the&amp;nbsp;following&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;ID	gen	parent	top level	path
--	---	------	---------	----
256	18	5	5		__active/ROOT
257	7	5	5		__active/home
258	8	5	5		__active/opt
259	18	5	5		__active/var&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;We will now set the default subvolume which will be used by the kernel to launch
the system.  Keep the &lt;span class="caps"&gt;ID&lt;/span&gt; of the &lt;code&gt;__active/ROOT&lt;/code&gt; subvolume and use it in the following&amp;nbsp;command.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="literalblock"&gt;
&lt;div class="content"&gt;
&lt;pre&gt;$ btrfs subvolume set-default 256 /mnt/btrfs-root/__active/ROOT&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Be aware that this solution will fail to mount the root &lt;span class="caps"&gt;BTRFS&lt;/span&gt; system since it
will mount instead this default subvolume.  You may avoid it in the previous
configuration because the root &lt;span class="caps"&gt;BTRFS&lt;/span&gt; file system must be mount in order to bind
&lt;code&gt;/var/lib&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="sec2-references"&gt;References&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;For this article, there is two main references.  The first one is the
&lt;a href="https://wiki.archlinux.org/index.php/Beginners%27_Guide"&gt;Beginner&amp;#8217;s guide&lt;/a&gt; for
Arch Linux installation.  There is a lot of information on how to install an
Arch Linux distribution and a lot of links to explain the&amp;nbsp;details.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The second reference is mainly about the &lt;span class="caps"&gt;BTRFS&lt;/span&gt; configuration suggest by Fabio
Mancinelli in his
&lt;a href="http://blog.fabio.mancinelli.me/2012/12/28/Arch_Linux_on_BTRFS.html"&gt;article&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://btrfs.wiki.kernel.org/index.php/Mount_options"&gt;&lt;span class="caps"&gt;BTRFS&lt;/span&gt; mount&amp;nbsp;options&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://bbs.archlinux.org/viewtopic.php?id=157834"&gt;How to root from a
&lt;span class="caps"&gt;BTRFS&lt;/span&gt;&amp;nbsp;subvolume&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec/"&gt;Standard
proposition for the&amp;nbsp;bootloader&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><category term="tech"></category><category term="archlinux"></category><category term="uefi"></category><category term="btrfs"></category></entry></feed>