<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7003844608523781358</id><updated>2024-09-10T13:36:33.903-04:00</updated><category term="Vista"/><category term="rant"/><category term="NonTech"/><category term="windows"/><category term="emf"/><title type='text'>M-A&#39;s technology blog</title><subtitle type='html'>Various things that interest me; it may happen to interest others.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://m-a-tech.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://m-a-tech.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10266008552441372345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>53</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7003844608523781358.post-2369376354941183904</id><published>2013-02-13T11:16:00.001-05:00</published><updated>2013-02-13T13:26:14.914-05:00</updated><title type='text'>Exception handling and non-critical components</title><content type='html'>&lt;br /&gt;
Most software developers consider exception handling is different than error handling but should these be handled differently? Wikipedia has a &lt;a href=&quot;http://en.wikipedia.org/wiki/Exception_handling&quot;&gt;full page on exception handling&lt;/a&gt;.&lt;br /&gt;
&lt;h3&gt;
Exception handling in theory&lt;/h3&gt;
For example let&#39;s take memcached clients across various languages. Let&#39;s speculate that an error could be the fact that a key is not in memcache and an exception could be that the client failed to connect to the server. Note that it&#39;s the library that decides what is an exception or an error and different libraries disagree with each other. It becomes even more confusing in languages like C++ where there isn&#39;t a common idiom on where the separation line should lie.&lt;br /&gt;
&lt;h3&gt;
Exception handling in practice&lt;/h3&gt;
Let&#39;s use the 4 partial snippets below to describe the difference in practice. While I&#39;m referring to the AppEngine documentation, it&#39;s by pure laziness and this post has nothing to do specifically with AppEngine and has only little to do with memcache client libraries themselves.&lt;br /&gt;
&lt;br /&gt;
It&#39;s &lt;i&gt;all about exception and error handling idioms&lt;/i&gt; in each language:&lt;br /&gt;
&lt;h4&gt;
C (&lt;a href=&quot;http://docs.libmemcached.org/memcached_get.html#memcached_get&quot;&gt;ref&lt;/a&gt;)&lt;/h4&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;memcached_st* memc = memcached(...);&lt;br /&gt;size_t length = 0;&lt;br /&gt;uint32_t flags = 0;&lt;br /&gt;char* value = memcached_get(memc, &quot;item&quot;, 4, &amp;amp;length, &amp;amp;flags, &amp;amp;error);&lt;br /&gt;if (value == NULL) {&lt;br /&gt;&amp;nbsp; // Regen the value.&lt;br /&gt;}&lt;/span&gt;&lt;/blockquote&gt;
&lt;h4&gt;
Java (&lt;a href=&quot;https://developers.google.com/appengine/docs/java/javadoc/com/google/appengine/api/memcache/MemcacheService#get(java.lang.Object)&quot;&gt;ref&lt;/a&gt;)&lt;/h4&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;import com.google.appengine.api.memcache&lt;br /&gt;
MemcacheService syncCache = MemcacheServiceFactory.getMemcacheService();&lt;br /&gt;
byte[] value = syncCache.get(&quot;item&quot;);&lt;br /&gt;
if (value == null) {&lt;br /&gt;
&amp;nbsp; // Regen the value.&lt;br /&gt;
}&lt;/span&gt;&lt;/blockquote&gt;
&lt;h4&gt;
python (&lt;a href=&quot;https://developers.google.com/appengine/docs/python/memcache/functions#Client_get&quot;&gt;ref&lt;/a&gt;)&lt;/h4&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;from google.appengine.api import memcache&lt;br /&gt;
value = memcache.get(&quot;item&quot;)&lt;br /&gt;
if not value:&lt;br /&gt;
&amp;nbsp; # Regen the value.&lt;/span&gt;&lt;/blockquote&gt;
&lt;h4&gt;
Go (&lt;a href=&quot;https://developers.google.com/appengine/docs/go/memcache/reference#Get&quot;&gt;ref&lt;/a&gt;)&lt;/h4&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;import &quot;appengine/memcache&quot;&lt;br /&gt;
if item, err := memcache.Get(c, &quot;lyric&quot;); err != nil {&lt;br /&gt;
&amp;nbsp; // Regen the value.&lt;br /&gt;
}&lt;/span&gt;&lt;/blockquote&gt;
&lt;h3&gt;
Exception handling and components&lt;/h3&gt;
Can you spot the errors above? To help you, read this post about the chaos monkey&lt;br /&gt;
&lt;a href=&quot;http://techblog.netflix.com/2012/07/chaos-monkey-released-into-wild.html&quot;&gt;http://techblog.netflix.com/2012/07/chaos-monkey-released-into-wild.html&lt;/a&gt;&lt;br /&gt;
and figure out what would happen with each of the 4 clients above if a chaos monkey decided to take a memcached server down. In particular, spot the client library design error versus the necessary components to reply to an HTTP request.&lt;br /&gt;
&lt;br /&gt;
It&#39;s simple, memcache is not a &lt;i&gt;necessary component in a http request success&lt;/i&gt;. In practice, any request to the web server must always succeed in either of the languages above even if memcached is not available. But it won&#39;t in 2 out of 4 because they handle exceptions differently from errors. In particular, for an optional module, this turns an innocuous error into an HTTP 500! The fix is to rewrite these as the following:&lt;br /&gt;
&lt;h4&gt;
Java&lt;/h4&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;import com.google.appengine.api.memcache&lt;br /&gt;
byte[] value = null;&lt;br /&gt;
try {&lt;br /&gt;
&amp;nbsp; MemcacheService syncCache = MemcacheServiceFactory.getMemcacheService();&lt;br /&gt;
&amp;nbsp; value = syncCache.get(&quot;item&quot;);&lt;br /&gt;
} catch ( &amp;lt;Figure out which exception to catch&amp;gt; ) {&lt;br /&gt;
&amp;nbsp; // Nothing to do.&lt;br /&gt;
}&lt;br /&gt;
if (value == null) {&lt;br /&gt;
&amp;nbsp; // Regen the value.&lt;br /&gt;
}&lt;/span&gt;&lt;/blockquote&gt;
&lt;h4&gt;
python&lt;/h4&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;from google.appengine.api import memcache&lt;br /&gt;
value = None&lt;br /&gt;
try:&lt;br /&gt;
&amp;nbsp; value = memcache.get(&quot;item&quot;)&lt;br /&gt;
except &amp;lt;Figure out which exception to catch&amp;gt;:&lt;br /&gt;
&amp;nbsp; # Nothing to do.&lt;br /&gt;
&amp;nbsp; pass&lt;br /&gt;
if not value:&lt;br /&gt;
&amp;nbsp; # Regen the value.&lt;/span&gt;&lt;/blockquote&gt;
At first look, it turns the shortest snippets into horribly long sequences of code &lt;i&gt;for non-important code paths&lt;/i&gt;. But there&#39;s more issues in there.&lt;br /&gt;
&lt;h3&gt;
Handle a runtime exception, or not&lt;/h3&gt;
Let&#39;s focus on deciding which exception to catch. In particular, this has to be decided at each call site and it&#39;s very easy to catch different exceptions at different call site if one is not careful. To make things worse, &lt;b&gt;the exhaustive list of runtime exceptions that can be raised is not documented&lt;/b&gt;! In practice, one has to see the exception happening to be able to figure out which exception to handle. But is not always easy in practice to &quot;kill the memcached server and see what happens&quot;.&lt;br /&gt;
&lt;h3&gt;
Preemptive handling&lt;/h3&gt;
A junior developer would be quickly tempted to put a catch all handler like &quot;&lt;i&gt;} catch (Exception e) {&lt;/i&gt;&quot; or &quot;&lt;i&gt;except Exception:&lt;/i&gt;&quot;. It is &lt;b&gt;worse&lt;/b&gt; because then you&#39;d catch exceptions like DeadlineExceededException or DeadlineExceededError, which could make an HTTP that could have possibly returned into one that has no chance of completing. &lt;a href=&quot;https://developers.google.com/appengine/articles/deadlineexceedederrors&quot;&gt;https://developers.google.com/appengine/articles/deadlineexceedederrors&lt;/a&gt;&lt;br /&gt;
&lt;h3&gt;
Exception documentation&lt;/h3&gt;
Java tries to solve this problem with checked exception signature but the core problem with exception signature in Java is that it forces the developer to handle the exception he probably doesn&#39;t care about, the one explicitly listed, and simultaneously fails to document or help the developer handle the runtime exceptions, which is the one he cares about! It&#39;s even worse in&amp;nbsp;&lt;a href=&quot;http://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html&quot;&gt;Oracle&#39;s Unchecked Exceptions — The Controversy&lt;/a&gt;, the author uses the following falacy:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;i&gt;Runtime exceptions represent problems that are the result of a programming problem, and as such, the API client code cannot reasonably be expected to recover from them or to handle them in any way.&lt;/i&gt;&lt;/blockquote&gt;
While inside the memcache client library, a component, the fact that a network connection fails may be considered an exception. But this thinking assumes &lt;i&gt;all the components are necessary to&amp;nbsp;achieve&amp;nbsp;work item completion&lt;/i&gt; which, as demonstrated above, is not true, especially in distributed systems. Another example is dynamic content with static content fallback, which netflix also implements. So the hypothesis of linear control flow in the unchecked exception doesn&#39;t hold; in modern system, the control flow can adapt to &quot;exceptional&quot; runtime situations and more often than not, doesn&#39;t care if a value wasn&#39;t in the key store or if the whole db is&amp;nbsp;temporarily&amp;nbsp;unavailable.&lt;br /&gt;
&lt;h3&gt;
Throw or return null?&lt;/h3&gt;
So next time someone asks to be able to use exceptions in C++, just say no. If you are stuck with Java or python for web development, &lt;b&gt;assume unplanned downtime&lt;/b&gt;. If you are starting a new project, strongly consider a language not using exceptions like Golang or C or in the case of C++, with libraries not using exceptions. Personally, I&#39;m totally sold to Golang because exception safe code is &lt;i&gt;shorter&lt;/i&gt;.</content><link rel='replies' type='application/atom+xml' href='http://m-a-tech.blogspot.com/feeds/2369376354941183904/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7003844608523781358/2369376354941183904' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/2369376354941183904'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/2369376354941183904'/><link rel='alternate' type='text/html' href='http://m-a-tech.blogspot.com/2013/02/exception-handling-and-non-critical.html' title='Exception handling and non-critical components'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10266008552441372345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7003844608523781358.post-5735822208124007324</id><published>2012-11-15T10:09:00.002-05:00</published><updated>2012-11-15T10:09:36.900-05:00</updated><title type='text'>Unicode equivalence may not be handled as you think</title><content type='html'>Unicode normalization is not always happening how you would expect, especially w.r.t. file systems. First, I recommend you to read about it on the wikipedia page&amp;nbsp;&lt;a href=&quot;http://en.wikipedia.org/wiki/Unicode_equivalence&quot;&gt;http://en.wikipedia.org/wiki/Unicode_equivalence&lt;/a&gt;&amp;nbsp;that is fairly well written:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;i&gt;In general, the code points of truly identical characters (which can be rendered in the same way in Unicode fonts) are defined to be canonically equivalent.&lt;/i&gt;&lt;/blockquote&gt;
Unicode has 2 equivalence notions, with pre-composed or decomposed representing the same characters, and 2 normal forms, the canonical one (NF) and the &quot;compatible&quot; one (NFK).&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;i&gt;In order to compare or search Unicode strings, software can use either composed or decomposed forms; &lt;b&gt;this choice does not matter as long as it is the same for all strings involved in a search, comparison&lt;/b&gt;, etc. On the other hand, the choice of equivalence criteria can affect search results. For instance some typographic ligatures like U+FB03 (ﬃ), roman numerals like U+2168 (Ⅸ) and even subscripts and superscripts, e.g. U+2075 (⁵) have their own Unicode code points. Canonical normalization (NF) does not affect any of these, but compatibility normalization (NFK) will decompose the ffi ligature into the constituent letters, &lt;b&gt;so a search for U+0066 (f) as substring would succeed in an NFKC normalization of U+FB03 but not in NFC normalization of U+FB03&lt;/b&gt;. Likewise when searching for the Latin letter I (U+0049) in the precomposed Roman Numeral Ⅸ (U+2168). Similarly the superscript &quot;⁵&quot; (U+2075) is transformed to &quot;5&quot; (U+0035) by compatibility mapping.&lt;/i&gt;&lt;/blockquote&gt;
I found out while writing an universal file tracer for the Chromium project. [Spoiler alert]: The &lt;a href=&quot;http://git.chromium.org/gitweb/?p=chromium/tools/swarm_client.git;a=blob;f=trace_inputs.py;hb=HEAD&quot;&gt;gory details are buried in trace_inputs.py&lt;/a&gt;. Note that the code in trace_inputs.py also does &lt;i&gt;case normalization&lt;/i&gt;, which a subject in itself, maybe for another post.&lt;br /&gt;
&lt;br /&gt;
I wasn&#39;t sure about each OS&amp;nbsp;behaviour&amp;nbsp;with regard to file path handling so I wrote a small python script to figure out what is happening exactly. I pasted the script&#39;s code at the bottom of this post. I&#39;ll let you guess what happens on each of the following OS: OSX 10.8, Ubuntu 12.04 with&amp;nbsp;LANG=foo.UTF-8 and Windows 7. The analysis is under the eye of if NF or NFK is employed when trying to open a file. I&#39;m explicitly excluding &lt;i&gt;case normalization&lt;/i&gt; (a vs A) for this post.&lt;br /&gt;
&lt;h3&gt;
Ubuntu&lt;/h3&gt;
Let&#39;s start with Ubuntu, which behaved exactly as I imagined. Note that I&#39;m using LANG=foo.UTF-8:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;~/src/foo&amp;gt; ./unicode_is_hard.py&lt;br /&gt;e-acute-circumflex&lt;br /&gt;Found 2 different encodings for u&#39;\u1ebf&#39;&lt;br /&gt;&amp;nbsp; NFKC: u&#39;\u1ebf&#39;&lt;br /&gt;&amp;nbsp; &amp;nbsp;NFD: u&#39;e\u0302\u0301&#39;&lt;br /&gt;&amp;nbsp; &amp;nbsp;NFC: u&#39;\u1ebf&#39;&lt;br /&gt;&amp;nbsp; NFKD: u&#39;e\u0302\u0301&#39;&lt;br /&gt;&amp;nbsp; OS returned: u&#39;NFC\u1ebf&#39;, u&#39;NFDe\u0302\u0301&#39;, u&#39;NFKC\u1ebf&#39;, u&#39;NFKDe\u0302\u0301&#39;&lt;br /&gt;&lt;br /&gt;roman_numeral_one&lt;br /&gt;Found 2 different encodings for u&#39;\u2160&#39;&lt;br /&gt;&amp;nbsp; NFKC: u&#39;I&#39;&lt;br /&gt;&amp;nbsp; &amp;nbsp;NFD: u&#39;\u2160&#39;&lt;br /&gt;&amp;nbsp; &amp;nbsp;NFC: u&#39;\u2160&#39;&lt;br /&gt;&amp;nbsp; NFKD: u&#39;I&#39;&lt;br /&gt;&amp;nbsp; OS returned: u&#39;NFC\u2160&#39;, u&#39;NFD\u2160&#39;, u&#39;NFKCI&#39;, u&#39;NFKDI&#39;&lt;br /&gt;&lt;br /&gt;e-acute-circumflex + roman_numeral_one&lt;br /&gt;Found 4 different encodings for u&#39;\u1ebf\u2160&#39;&lt;br /&gt;&amp;nbsp; NFKC: u&#39;\u1ebfI&#39;&lt;br /&gt;&amp;nbsp; &amp;nbsp;NFD: u&#39;e\u0302\u0301\u2160&#39;&lt;br /&gt;&amp;nbsp; &amp;nbsp;NFC: u&#39;\u1ebf\u2160&#39;&lt;br /&gt;&amp;nbsp; NFKD: u&#39;e\u0302\u0301I&#39;&lt;br /&gt;&amp;nbsp; OS returned: u&#39;NFC\u1ebf\u2160&#39;, u&#39;NFDe\u0302\u0301\u2160&#39;, u&#39;NFKC\u1ebfI&#39;, u&#39;NFKDe\u0302\u0301I&#39;&lt;/span&gt;&lt;/blockquote&gt;
&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;float: right; margin-left: 1em; text-align: right;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTQvvIH4qYLqmx3BlfnKGmV0WxlzAbTCIR5HQJAyQ2RQAwDUutC2mKUIERlJp5U3dlHUh9BeuGJStaj1oD7uXX6TsItP6T1qteOwM-yhkYlQsYN7GH2GZKM4EpCOtvmmlWWoOi_jGzCTFs/s1600/unicode_is_hard_ubuntu.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTQvvIH4qYLqmx3BlfnKGmV0WxlzAbTCIR5HQJAyQ2RQAwDUutC2mKUIERlJp5U3dlHUh9BeuGJStaj1oD7uXX6TsItP6T1qteOwM-yhkYlQsYN7GH2GZKM4EpCOtvmmlWWoOi_jGzCTFs/s1600/unicode_is_hard_ubuntu.png&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;How Nautilus displays the files&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
As you can see, the file system is not processing the Unicode characters at all so what &lt;i&gt;you write is what you get&lt;/i&gt;. Now I&#39;ll let you guess what happens on OSX and Windows. Prepare your bets.&lt;br /&gt;
&lt;h3&gt;
Windows&lt;/h3&gt;
Windows is interesting because it didn&#39;t behave as I expected.&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;color: #660000; font-family: &#39;Courier New&#39;, Courier, monospace; font-size: x-small;&quot;&gt;D:\src&amp;gt;python unicode_is_hard.py&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;e-acute-circumflex&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;Found 2 different encodings for u&#39;\u1ebf&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; NFKC: u&#39;\u1ebf&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp;NFD: u&#39;e\u0302\u0301&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp;NFC: u&#39;\u1ebf&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; NFKD: u&#39;e\u0302\u0301&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; OS returned: u&#39;NFC\u1ebf&#39;, u&#39;NFDe\u0302\u0301&#39;, u&#39;NFKC\u1ebf&#39;, u&#39;NFKDe\u0302\u0301&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;roman_numeral_one&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;Found 2 different encodings for u&#39;\u2160&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; NFKC: u&#39;I&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp;NFD: u&#39;\u2160&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp;NFC: u&#39;\u2160&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; NFKD: u&#39;I&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; OS returned: u&#39;NFC\u2160&#39;, u&#39;NFD\u2160&#39;, u&#39;NFKCI&#39;, u&#39;NFKDI&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;e-acute-circumflex + roman_numeral_one&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;Found 4 different encodings for u&#39;\u1ebf\u2160&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; NFKC: u&#39;\u1ebfI&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp;NFD: u&#39;e\u0302\u0301\u2160&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp;NFC: u&#39;\u1ebf\u2160&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; NFKD: u&#39;e\u0302\u0301I&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; OS returned: u&#39;NFC\u1ebf\u2160&#39;, u&#39;NFDe\u0302\u0301\u2160&#39;, u&#39;NFKC\u1ebfI&#39;, u&#39;NFKDe\u0302\u0301I&#39;&lt;/span&gt;&lt;/blockquote&gt;
&lt;br /&gt;
&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;float: right; margin-left: 1em; text-align: right;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7ovLg99JVkxTyiSA8-mm9Od5xdgA0Tmhs4xNdvR3k0t8wLAsQ5BCqSdUnwVOb4pJ5pdiqPt9MeIS46oYx54k36tQBUgQZg1VTZb6bxdvaS6M3ziWsobK_SrZgCyKiYEZY28RCJzQSLHqn/s1600/filenames_on_windows.PNG&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7ovLg99JVkxTyiSA8-mm9Od5xdgA0Tmhs4xNdvR3k0t8wLAsQ5BCqSdUnwVOb4pJ5pdiqPt9MeIS46oYx54k36tQBUgQZg1VTZb6bxdvaS6M3ziWsobK_SrZgCyKiYEZY28RCJzQSLHqn/s1600/filenames_on_windows.PNG&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;How Windows Explorer displays the files&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
As you can see, and that was unexpected to me, Windows doesn&#39;t normalize the unicode code points to NFK so you will get whatever the program used like for Ubuntu. As a spoiler, cygwin is doing the same but I left its output for&amp;nbsp;brevity. Note how the rendering is significantly different for \u2160 (I) unlike Ubuntu&#39;s default rendering in Unity.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
OSX&lt;/h3&gt;
If you already played with unicode code point normalization and had to touch OSX, you problaby know why I kept it as the last one:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;~/src/foo&amp;gt; ./unicode_is_hard.py&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;e-acute-circumflex&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;Found 2 different encodings for u&#39;\u1ebf&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; NFKC: u&#39;\u1ebf&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp;NFD: u&#39;e\u0302\u0301&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp;NFC: u&#39;\u1ebf&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; NFKD: u&#39;e\u0302\u0301&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; OS returned: u&#39;NFCe\u0302\u0301&#39;, u&#39;NFDe\u0302\u0301&#39;, u&#39;NFKCe\u0302\u0301&#39;, u&#39;NFKDe\u0302\u0301&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;b&gt;&amp;nbsp; 2 are not matching.&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;b&gt;&amp;nbsp; For &amp;nbsp;NFC, expected &amp;nbsp;NFC, NFKC but could with &amp;nbsp;NFC, &amp;nbsp;NFD, NFKC, NFKD&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;b&gt;&amp;nbsp; For NFKC, expected &amp;nbsp;NFC, NFKC but could with &amp;nbsp;NFC, &amp;nbsp;NFD, NFKC, NFKD&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;b&gt;&amp;nbsp; For &amp;nbsp;NFD, expected &amp;nbsp;NFD, NFKD but could with &amp;nbsp;NFC, &amp;nbsp;NFD, NFKC, NFKD&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;b&gt;&amp;nbsp; For NFKD, expected &amp;nbsp;NFD, NFKD but could with &amp;nbsp;NFC, &amp;nbsp;NFD, NFKC, NFKD&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;roman_numeral_one&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;Found 2 different encodings for u&#39;\u2160&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; NFKC: u&#39;I&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp;NFD: u&#39;\u2160&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp;NFC: u&#39;\u2160&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; NFKD: u&#39;I&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; OS returned: u&#39;NFC\u2160&#39;, u&#39;NFD\u2160&#39;, u&#39;NFKCI&#39;, u&#39;NFKDI&#39;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;e-acute-circumflex + roman_numeral_one&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;Found 4 different encodings for u&#39;\u1ebf\u2160&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; NFKC: u&#39;\u1ebfI&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp;NFD: u&#39;e\u0302\u0301\u2160&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp;NFC: u&#39;\u1ebf\u2160&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; NFKD: u&#39;e\u0302\u0301I&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; OS returned: u&#39;NFCe\u0302\u0301\u2160&#39;, u&#39;NFDe\u0302\u0301\u2160&#39;, u&#39;NFKCe\u0302\u0301I&#39;, u&#39;NFKDe\u0302\u0301I&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;b&gt;&amp;nbsp; 2 are not matching.&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;b&gt;&amp;nbsp; For &amp;nbsp;NFC, expected &amp;nbsp;NFC but could with &amp;nbsp;NFC, &amp;nbsp;NFD&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;b&gt;&amp;nbsp; For NFKC, expected NFKC but could with NFKC, NFKD&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;b&gt;&amp;nbsp; For &amp;nbsp;NFD, expected &amp;nbsp;NFD but could with &amp;nbsp;NFC, &amp;nbsp;NFD&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #660000; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;b&gt;&amp;nbsp; For NFKD, expected NFKD but could with NFKC, NFKD&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;div&gt;
&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;float: right; margin-left: 1em; text-align: right;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPlDe16L48_Oj47CEwRkuYePOJ99as3-x6JvbcGNQqKpDuKW-NySR_Jae7PL_4BLe1fp0ko2QtVyEn3RH0DlxVI_4cYZksln8vSMmusdARu5T2jMBcRnLbhiwxc77WGozH-AMDTCGLhjBF/s1600/Screen+Shot+2012-11-15+at+9.35.46+AM.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPlDe16L48_Oj47CEwRkuYePOJ99as3-x6JvbcGNQqKpDuKW-NySR_Jae7PL_4BLe1fp0ko2QtVyEn3RH0DlxVI_4cYZksln8vSMmusdARu5T2jMBcRnLbhiwxc77WGozH-AMDTCGLhjBF/s1600/Screen+Shot+2012-11-15+at+9.35.46+AM.png&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;How Finder displays the files&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
As you can see, OSX is the only OS to normalize Unicode code points. But it is doing partial normalization, only for NFD vs NFC but not for NFKx vs NFx. &lt;b&gt;That&#39;s interesting as I&#39;d have expected NFK handling instead.&lt;/b&gt; So a file written in NFKx cannot be opened in NFx but NFC vs NFD is transparently converted.&lt;/div&gt;
&lt;h3&gt;
The code&lt;/h3&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;color: #274e13; font-family: &#39;Courier New&#39;, Courier, monospace; font-size: x-small;&quot;&gt;#!/usr/bin/env python&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;# Copyright (c) 2012 Marc-Antoine Ruel. All rights reserved.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&quot;&quot;&quot;This scripts create a subdirectory named unicode_is_hard which contains&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;various files in various encoding.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;See http://en.wikipedia.org/wiki/Unicode_equivalence for the various UTF&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;encodings.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;import os&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;import shutil&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;import sys&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;import unicodedata&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;BASE_DIR = os.path.dirname(os.path.abspath(__file__))&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;color: #274e13; font-family: &#39;Courier New&#39;, Courier, monospace; font-size: x-small;&quot;&gt;def try_with_string(work_dir, unicode_string):&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &quot;&quot;&quot;Encodes an unicode string with 4 different encodings and tries to open the&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; file with the other encodings.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &quot;&quot;&quot;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; # Delete the work directory if present.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; if os.path.isdir(work_dir):&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; shutil.rmtree(work_dir)&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; os.mkdir(work_dir)&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; encodings = (u&#39;NFC&#39;, u&#39;NFKC&#39;, u&#39;NFD&#39;, u&#39;NFKD&#39;)&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; encoded = dict(&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (key, unicodedata.normalize(key, unicode_string)) for key in encodings)&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; filenames = dict((key, key + value) for key, value in encoded.iteritems())&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; # This implicitly assumes python does the right thing here.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; different_encodings = len(set(encoded.itervalues()))&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; print(&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;Found %d different encodings for %r&#39; %&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (different_encodings, unicode_string))&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; for encoding, value in encoded.iteritems():&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; print(&#39; &amp;nbsp;%4s: %r&#39; % (encoding, value))&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; # Now for each type, create a file. See if the other encodings can open it.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; for filename in filenames.itervalues():&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; open(os.path.join(work_dir, filename), &#39;w&#39;).close()&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; files_found = sorted(os.listdir(work_dir))&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; print(&#39; &amp;nbsp;OS returned: %s&#39; % &#39;, &#39;.join(repr(i) for i in files_found))&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; not_matching = set(filenames.itervalues()).difference(files_found)&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; if not_matching:&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; print(&#39; &amp;nbsp;%d are not matching.&#39; % len(not_matching))&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; expected = {}&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; for encoding, value in encoded.iteritems():&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; # Assumes comparison in python is correctly done.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; for encoding_to_confirm, value_to_confirm in encoded.iteritems():&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; if value_to_confirm == value:&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; expected.setdefault(encoding, []).append(encoding_to_confirm)&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; # Now do the 16 combinations to try to open each files with the other&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; # encoding.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; actual = {}&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; for encoding, original_filename in filenames.iteritems():&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; for encoding_to_try, value_to_try in encoded.iteritems():&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; # Try to open the file with the other encoding.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; try:&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; open(os.path.join(work_dir, encoding + value_to_try)).close()&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; actual.setdefault(encoding, []).append(encoding_to_try)&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; except IOError:&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; pass&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; # Print if anything unexpected succeeded. This happens in the case&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; # encoded[encoding1] != encoded[encoding2] but they could open each other.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; for encoding in encodings:&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; if sorted(expected[encoding]) != sorted(actual[encoding]):&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; print(&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39; &amp;nbsp;For %4s, expected %s but could with %s&#39; % (&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; encoding,&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;, &#39;.join(&#39;%4s&#39; % i for i in sorted(expected[encoding])),&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;, &#39;.join(&#39;%4s&#39; % i for i in sorted(actual[encoding]))))&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;def main():&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; work_dir = os.path.join(unicode(BASE_DIR), u&#39;unicode_is_hard&#39;)&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; # Examples taken from the Wikipedia page and unicodedata python stdlib doc.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; # http://docs.python.org/2/library/unicodedata.html&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; e_acute_circumflex = u&#39;\u1ebf&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; roman_numeral_one = u&#39;\u2160&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; print(&#39;e-acute-circumflex&#39;)&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; try_with_string(work_dir, e_acute_circumflex)&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; print(&#39;\nroman_numeral_one&#39;)&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; try_with_string(work_dir, roman_numeral_one)&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; print(&#39;\ne-acute-circumflex + roman_numeral_one&#39;)&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; try_with_string(work_dir, e_acute_circumflex + roman_numeral_one)&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; return 0&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;if __name__ == &#39;__main__&#39;:&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #274e13; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; sys.exit(main())&lt;/span&gt;&lt;/blockquote&gt;
</content><link rel='replies' type='application/atom+xml' href='http://m-a-tech.blogspot.com/feeds/5735822208124007324/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7003844608523781358/5735822208124007324' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/5735822208124007324'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/5735822208124007324'/><link rel='alternate' type='text/html' href='http://m-a-tech.blogspot.com/2012/11/unicode-equivalence-may-not-be-handled.html' title='Unicode equivalence may not be handled as you think'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10266008552441372345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTQvvIH4qYLqmx3BlfnKGmV0WxlzAbTCIR5HQJAyQ2RQAwDUutC2mKUIERlJp5U3dlHUh9BeuGJStaj1oD7uXX6TsItP6T1qteOwM-yhkYlQsYN7GH2GZKM4EpCOtvmmlWWoOi_jGzCTFs/s72-c/unicode_is_hard_ubuntu.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7003844608523781358.post-3341887444656681374</id><published>2012-10-12T14:48:00.002-04:00</published><updated>2012-10-12T14:55:37.931-04:00</updated><title type='text'>Short 10 items work-efficiency recipe</title><content type='html'>Here&#39;s a repost of a message I wrote internally at Google. I had been asked about how to be more efficient, or put another way, &lt;i&gt;how to generate that much code&lt;/i&gt;. To get an idea, you can look at the data there;&lt;br /&gt;
&lt;a href=&quot;http://svnsearch.org/svnsearch/repos/CHROMIUM/search?view=plot&amp;amp;author=maruel%40chromium.org&quot;&gt;http://svnsearch.org/svnsearch/repos/CHROMIUM/search?view=plot&amp;amp;author=maruel%40chromium.org&lt;/a&gt;. In that time frame, I also contributed to &lt;a href=&quot;http://buildbot.net/&quot;&gt;buildbot&lt;/a&gt;, &lt;a href=&quot;http://code.google.com/p/rietveld/&quot;&gt;Rietveld&lt;/a&gt;, and worked on Google-internal projects.&lt;br /&gt;
&lt;br /&gt;
So here&#39;s my short 10 items work-efficiency recipe;&lt;br /&gt;
&lt;h4&gt;
1. Always keep the same work schedule as much as possible&lt;/h4&gt;
But &lt;i&gt;work when your brain is in flux state&lt;/i&gt;. If you wake up a noon and get to bed at 3am everyday, keep it always the same. When you&#39;re 25yr old it&#39;s fine to be less stable in your work schedule. You&#39;ll get old eventually, if you survive yourself, and eventually, your body will &lt;i&gt;hate what you do to it&lt;/i&gt;. Work on weekend if needed but keeping a stable schedule is important for maximal brain efficiency. Continue coding up to the exact moment as soon as you see yourself unsure of the design for your next line to write, stop coding at that point.&lt;br /&gt;
&lt;h4&gt;
2. Do small changes&lt;/h4&gt;
Other committers have probably larger diffstat than me but the CLs are more complicated so harder to read. I try to make small CLs because it&#39;s:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Easier to glance at to figure out what&#39;s it&#39;s doing.&lt;/li&gt;
&lt;li&gt;Much easier to review, reducing turn around time -&amp;gt; enable review over email -&amp;gt; improve your own efficiency.&lt;/li&gt;
&lt;li&gt;Easier to revert with less chance of merge error.&lt;/li&gt;
&lt;li&gt;When doing small changes, it&#39;s possible to TBR= the patches more often. TBR in this context means &lt;i&gt;to be reviewed&lt;/i&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
3. Learn to cope with review latency&lt;/h4&gt;
When doing small changes, you can pipeline them to reduce the effect of review latency. You can cheat sometimes with TBR but not abuse too much. Working on 2 projects concurrently helps &lt;b&gt;a lot&lt;/b&gt;. I often start with a large change then split it up into smaller CLs. This always improve the quality of the code.&lt;br /&gt;
&lt;h4&gt;
4. Take time to pay technical debt&lt;/h4&gt;
Probably worth keeping aside 20% of your coding time to technical debt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Adding tests. In spring 2011, I took 3 months writing unit tests for depot_tools. It was really depressing but it really helped afterward.&lt;/li&gt;
&lt;li&gt;Refactoring poor designs. It&#39;s good to accumulate technical debt since it&#39;s often after the fact that you can really see the best design. Do not try to design too much up front, unless you&#39;re designing an API!&lt;/li&gt;
&lt;/ul&gt;
Often people are afraid to refactor because of the cost of doing so. Planing is the key. Split in sub tasks;&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Identify consumers.&lt;/li&gt;
&lt;li&gt;Identify problem and how a new interface would fix the problem.&lt;/li&gt;
&lt;li&gt;Evaluate the cost/benefit of a refactor. Think about intangibles, would it reduce the learning curve of a potential new contributor?&lt;/li&gt;
&lt;li&gt;Create the new interface.&lt;/li&gt;
&lt;li&gt;Write tests for the new interface.&lt;/li&gt;
&lt;li&gt;Alert everyone.&lt;/li&gt;
&lt;li&gt;Switch consumer to new interface.&lt;/li&gt;
&lt;li&gt;Wait for propagation delay.&lt;/li&gt;
&lt;li&gt;Remove old interface.&lt;/li&gt;
&lt;/ol&gt;
It applies mostly everywhere. It requires being methodic. But sometimes, give up, the refactor is not worth it! A refactor for the fun of refactoring is skipping the &quot;Identify problem&quot; step. See next item.&lt;br /&gt;
&lt;h4&gt;
5. Focus on your user&#39;s benefit&lt;/h4&gt;
Do not focus code or just yet-another-feature. It&#39;s not the number of commits or the diffstat, it&#39;s stuff that works that count. Do not fix problems for old code, do not be afraid to deprecate cleanly. Work on complex problems! Fix a complex problem with many simple solutions by splitting the problem in parts so as much existing components can be reused. Work most of the time on non-visible grungy stuff but occasionally work on highly visible projects otherwise you&#39;ll get no recognition.&lt;br /&gt;
&lt;h4&gt;
6. Fix repetition with code&lt;/h4&gt;
Kill idle time with code. Take the time to automate anything you see yourself doing 3 times. Write one-liner scripts and put them in a SCM. Separate your public scripts from the private ones. For example, this permits putting the public one on github.&lt;br /&gt;
&lt;h4&gt;
7. Write the code to be refactorable in the first place&lt;/h4&gt;
This is in general overlooked by new grads but it is extremely important. Someone will be stuck with the code you wrote 4 years from now and will hate you and will wonder why you did it this way. So at least, make it easy for them to refactor it.&lt;br /&gt;
&lt;br /&gt;
That&#39;s why I always align the function call arguments at +4 on the following line, so that a single argument addition is a single-line diff that is very easy to revert or merge with other commits. Never align at &quot;(&quot;, otherwise at the moment you are renaming the function, you have to realign all the call sites!&lt;br /&gt;
&lt;br /&gt;
Another example is to use &lt;a href=&quot;http://golang.org/cmd/gofmt/&quot;&gt;style check&lt;/a&gt; or &lt;a href=&quot;http://www.logilab.org/857&quot;&gt;static analysis&lt;/a&gt;.&lt;br /&gt;
&lt;h4&gt;
8. Abuse to some extent the &quot;test on prod&quot; mentality&lt;/h4&gt;
To be able to achieve that, you have to:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Write code defensively. Especially with python, springle asserts generously.&lt;/li&gt;
&lt;li&gt;Plan for failure. If everything breaks, what is the cascading effect? Plan for cascading failure. For example, a gclient sync&amp;nbsp;[The chromium meta checkout tool]&amp;nbsp;breakage could DDoS the subversion server, then provision accordinly.&lt;/li&gt;
&lt;li&gt;Have breakage not be too important -&amp;gt; do many incremental changes instead of big ones.&lt;/li&gt;
&lt;li&gt;Make sure it&#39;s easy to revert fast (small CLs).&lt;/li&gt;
&lt;li&gt;Have some sort of monitoring. Devs yelling at you is a &lt;i&gt;form&lt;/i&gt; of monitoring. Otherwise, it&#39;s time to pay technical debt. I abuse &#39;devs monitoring&#39; a bit. Try to do without pissing off your colleagues too much.&lt;/li&gt;
&lt;li&gt;Unit tests are great. You need test. But you need integration (smoke) tests too. Are your mocks representative of the actual implementation? If the component you rely on working with &lt;i&gt;your&lt;/i&gt; use case?&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
9. Optimize your work environment&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Have your text editor be efficient. I personally use vim exclusively even if I do not consider myself a power-user. Spend an inordinate amount of time configuring it. Try a few before settling in.&lt;/li&gt;
&lt;li&gt;Use the CLI all the time.&lt;/li&gt;
&lt;li&gt;Try to never touch the mouse. But still use an high quality mouse.&lt;/li&gt;
&lt;li&gt;Use an high quality keyboard. Grab a keyboard where the F-keys are near the numbers row if you use F-keys. Millimeters count.&lt;/li&gt;
&lt;li&gt;Take time to learn how to use your SCM and review tool. As an example in Chromium-land, commands like &quot;git cl comments&quot; help boost your productivity.&lt;/li&gt;
&lt;li&gt;Not using GUI makes it easier to effectively use any wait time I may have; grab laptop, fire up an ssh window and screen -x exactly where I had left up. Setup ssh keys to reduce wait time. That&#39;s to help with #1.&lt;/li&gt;
&lt;li&gt;Do not be lazy. Use the best tools available. There are awesome engineers in the world produce new tools that could be of use for you, use their output. So the list of tools is different from last year&#39;s; be prepared for change. For example, &quot;If you are not using ninja to build Chromium, You are compiling it wrong(tm)&quot;. Do not accept status-quo for toolsets.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
10. Optimize your meta-work environment&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Do not get distracted. Social events are great. Visit other offices if you work in a multi-office environment. Meeting colleagues face to face is extremely important to build trust relationships. Otherwise, join meets-up to learn about how other companies solve common problems. But most of your time should be spent coding if you are a SWE.&lt;/li&gt;
&lt;li&gt;Communicate asynchronously as much as possible. But when it&#39;s time for coordination, communicate synchronously. VC/IM/F2F.&lt;/li&gt;
&lt;li&gt;Do not be shy. You are not paid to be shy. It doesn&#39;t mean to be a jerk, just not be afraid to ask questions. Be prepared to receive RTFM as answer.&lt;/li&gt;
&lt;li&gt;Do not meta-work. Gmail filter out as much as possible. Force yourself to use keyboard shortcuts in Gmail. Do not spend as much time on G+ as I do. :) Meetings are meta-work. &lt;b&gt;Meta-work is your #1 enemy&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;Reduce communication overhead as much as possible. Use broadcast instead of 1:1 to spread information. Use mailing lists instead of direct email addresses for easier searchability and archival.&lt;/li&gt;
&lt;li&gt;If you do not like working with someone, do not work with the person. Do not let management overhead kill your productivity.&lt;/li&gt;
&lt;/ul&gt;
</content><link rel='replies' type='application/atom+xml' href='http://m-a-tech.blogspot.com/feeds/3341887444656681374/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7003844608523781358/3341887444656681374' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/3341887444656681374'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/3341887444656681374'/><link rel='alternate' type='text/html' href='http://m-a-tech.blogspot.com/2012/10/short-10-items-work-efficiency-recipe.html' title='Short 10 items work-efficiency recipe'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10266008552441372345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7003844608523781358.post-3481338247568559380</id><published>2011-07-15T10:00:00.000-04:00</published><updated>2011-07-15T10:00:02.462-04:00</updated><title type='text'>Want to rent a movie tonight? Can you calculate how much it&#39;ll cost you?</title><content type='html'>&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: large;&quot;&gt;Or how many movies can you rent on iTunes in a month?&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
For demonstration purpose, let&#39;s say you love &quot;Funkytown&quot;, you are silly and you want to rent it multiple times within a month. Its HD version is 4.6gb at a price of 6.99$ on the iPad.&amp;nbsp;For consistency, I&#39;m taking ISP&#39;s cheapest package above 5mbps and assuming you have another service with the ISP to have reduced cost.&lt;br /&gt;
&lt;br /&gt;
&lt;table border=&quot;2&quot; cellpadding=&quot;4&quot;&gt;&lt;thead&gt;
&lt;tr&gt;&lt;td&gt;ISP&lt;/td&gt; &lt;td&gt;Province&lt;/td&gt; &lt;td&gt;Monthly price&lt;/td&gt; &lt;td&gt;Bandwidth&lt;/td&gt;&lt;td&gt;Allowance&lt;/td&gt;&lt;td&gt;Extra&lt;/td&gt;&lt;/tr&gt;
&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt; &lt;td&gt;Vidéotron&lt;/td&gt; &lt;td&gt;Québec&lt;/td&gt; &lt;td&gt;43,95$&lt;/td&gt;&lt;td&gt;8mbps&lt;/td&gt;&lt;td&gt;50gb&lt;/td&gt;&lt;td&gt;4.50$/gb max 50$&lt;/td&gt; &lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Rogers&lt;/td&gt;&lt;td&gt;Ontario&lt;/td&gt;&lt;td&gt;46,99$&lt;/td&gt;&lt;td&gt;10mbps&lt;/td&gt;&lt;td&gt;60gb&lt;/td&gt;&lt;td&gt;2.00$/gb max 50$&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt; &lt;td&gt;Bell&lt;/td&gt; &lt;td&gt;Québec&lt;/td&gt; &lt;td&gt;42,95$&lt;/td&gt;&lt;td&gt;7mbps&lt;/td&gt;&lt;td&gt;60gb&lt;/td&gt;&lt;td&gt;2.50$/gb unlimited cost?&lt;/td&gt; &lt;/tr&gt;
&lt;tr&gt; &lt;td&gt;Bell&lt;/td&gt; &lt;td&gt;Ontario&lt;/td&gt; &lt;td&gt;43,90$&lt;/td&gt;&lt;td&gt;6mbps&lt;/td&gt;&lt;td&gt;25gb&lt;/td&gt;&lt;td&gt;2.50$/gb unlimited cost?&lt;/td&gt; &lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;
With most ISP, you would be able to rent up to 13 movies in a month, &lt;b&gt;if&lt;/b&gt; you are not ever watching Youtube videos at 135mb/hour, going to&amp;nbsp;&lt;a href=&quot;http://tou.tv/&quot;&gt;tou.tv&lt;/a&gt;, doing Skype or&amp;nbsp;&lt;a href=&quot;http://plus.google.com/116805285176805120365/posts/D7zdEFJPKik&quot;&gt;Hangout on Google+ at 720mb/hour&lt;/a&gt;. And don&#39;t ever think about installing your latest operating system service pack, for each of your computers and laptops, which sometime weights near a gigabyte.&lt;br /&gt;
&lt;br /&gt;
If you have a family, think teenagers watching Bieber in a loop and blow up the monthly cap, you&#39;ll end up renting the 11th movie on Vidéotron at an effective cost of 6.99$+4.6gb*4.50$/gb = &lt;b&gt;27.69$&lt;/b&gt;. Yes, it&#39;s ridiculous.&lt;br /&gt;
&lt;br /&gt;
I do welcome the extra bandwidth cost bounding. I think it puts a fair balance between limiting heavy usage and extortion. But the extra bandwidth cost is usually &lt;b&gt;unbounded for business accounts&lt;/b&gt;, like mine. This puts &lt;b&gt;small businesses in an even weaker position&lt;/b&gt;, as they can&#39;t afford to not have internet access and usually have multiple concurrent users on a single connection. In fact, &lt;b&gt;small businesses are the ones that are losing the most of this situation.&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Now think about it, most independent ISP have caps around 200gb, which would permit you to rent 43 movies in a month, which makes more sense as an upper limit.&lt;br /&gt;
&lt;br /&gt;
Network bandwidth is not like water or electricity; an idle router and a congested router have both the exact same cost. As a counter point, a congested router will have lower throughput than a non-congested one so there is need to balance usage. It&#39;s fair, we don&#39;t want to have too many congested routers, causing slow connections. My point is that having unbounded extra cost,&amp;nbsp;especially above 1.00$/gb,&amp;nbsp;is nearing extortion and in particular for small businesses.&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: large;&quot;&gt;References&lt;/span&gt;&lt;br /&gt;
Vidéotron&lt;br /&gt;
&lt;a href=&quot;http://www.videotron.com/service/internet-services/internet-access/high-speed-internet&quot;&gt;http://www.videotron.com/service/internet-services/internet-access/high-speed-internet&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Rogers&lt;br /&gt;
(note how the details are hidden in a faq on a almost unbranded site)&lt;br /&gt;
&lt;a href=&quot;http://www.rogers.com/web/link/hispeedBrowseFlowDefaultPlans&quot;&gt;http://www.rogers.com/web/link/hispeedBrowseFlowDefaultPlans&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://www.keepingpace.ca/faq.html#9&quot;&gt;http://www.keepingpace.ca/faq.html#9&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Bell&lt;br /&gt;
&lt;a href=&quot;http://www.bell.ca/shopping/en_CA_QC.Performance/DSLTIPQCNewMassNCQPF06.details&quot;&gt;http://www.bell.ca/shopping/en_CA_QC.Performance/DSLTIPQCNewMassNCQPF06.details&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://www.bell.ca/shopping/en_CA_ON.Performance/DSLTIPONNewMassNCOPF10.details&quot;&gt;http://www.bell.ca/shopping/en_CA_ON.Performance/DSLTIPONNewMassNCOPF10.details&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: large;&quot;&gt;Disclaimer&lt;/span&gt;&lt;br /&gt;
I work for Google but I did this research on my own time. It doesn&#39;t represent the opinion on my employer. I &lt;b&gt;pay&lt;/b&gt; for my extra bandwidth.</content><link rel='replies' type='application/atom+xml' href='http://m-a-tech.blogspot.com/feeds/3481338247568559380/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7003844608523781358/3481338247568559380' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/3481338247568559380'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/3481338247568559380'/><link rel='alternate' type='text/html' href='http://m-a-tech.blogspot.com/2011/07/want-to-rent-movie-tonight-can-you.html' title='Want to rent a movie tonight? Can you calculate how much it&#39;ll cost you?'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10266008552441372345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7003844608523781358.post-6266359230608452318</id><published>2011-04-14T09:46:00.000-04:00</published><updated>2011-04-14T09:46:53.246-04:00</updated><title type='text'>Putty configuration</title><content type='html'>Saving my preference here since I always forget:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Session&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;Close window on exit: Always&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;Terminal&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;Bell&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;Taskbar/caption indication on bell: Steady&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;Features&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;Disable remote-controlled window title changing: True&lt;/li&gt;
&lt;/ul&gt;&lt;/ul&gt;&lt;li&gt;Window&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;Lines of scollback: 2000&lt;/li&gt;
&lt;li&gt;Behaviour&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;Window title: &amp;lt;session name&amp;gt;&lt;/li&gt;
&lt;li&gt;Separate window and icon titles: True&lt;/li&gt;
&lt;li&gt;Warn before closing window: False&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;Translation&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;UTF-8&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;Colours&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;ANSI Blue: 0, 0, 242&lt;/li&gt;
&lt;li&gt;ANSI Blue Bold: 132, 132, 255&lt;/li&gt;
&lt;/ul&gt;&lt;/ul&gt;&lt;li&gt;Connection&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;SSH&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;Remote commands: &quot;screen -x&quot;&lt;/li&gt;
&lt;li&gt;Preferred SSH protocol version: 2 only&lt;/li&gt;
&lt;li&gt;Encryption cipher selection policy: Move up &quot;--warn below here --&quot; to only leave &quot;AES (SSH-2 only) enabled.&lt;/li&gt;
&lt;li&gt;Tunnels&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&amp;lt;Set relevant tunnels&amp;gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;div&gt;Set as startup program: &quot;...\pageant.exe ...\&amp;lt;private key&amp;gt;.ppk&quot;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://m-a-tech.blogspot.com/feeds/6266359230608452318/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7003844608523781358/6266359230608452318' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/6266359230608452318'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/6266359230608452318'/><link rel='alternate' type='text/html' href='http://m-a-tech.blogspot.com/2011/04/putty-configuration.html' title='Putty configuration'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10266008552441372345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7003844608523781358.post-4412656505819641174</id><published>2011-03-11T10:14:00.000-05:00</published><updated>2011-03-11T10:14:01.395-05:00</updated><title type='text'>Generating passwords</title><content type='html'>Note to myself as I always forget. How to generate a (mostly) uncrackable password:&lt;br /&gt;
&lt;blockquote&gt;&lt;pre&gt;sudo apt-get install apg
apg -m 9 -MLNS -a0 -t&lt;/pre&gt;&lt;/blockquote&gt;This request: min 9 chars, must contain lowercase, &amp;nbsp;numeral, and symbol, be&amp;nbsp;pronounceable, and print the pronunciation.&lt;br /&gt;
&lt;br /&gt;
Then,&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Prepend /! for irc&amp;amp;bash safety.&lt;/li&gt;
&lt;li&gt;Append any accented letter in (non-exclusive) çÇ àÀ­áÁäÄâÂ éÉèÈëËêÊ íÍìÌïÏîÎ óÓòÒöÖôÔ úÚùÙüÜûÛ ýÝÿ ±£¢¤¬¦²³¼½¾¶§µ¯­­­. All these letters can be seamlessly typed from a FR-CA keyboard with AltGr or two keys combination.&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;You can simplify the apg complexity because of this one since it&#39;s adding many letters of entropy and each of these letters is ~3 bytes of utf-8, dramatically increasing the effective password length.&lt;/li&gt;
&lt;li&gt;If you are selecting your password on linux, don&#39;t forget that Windows won&#39;t accept certain combinations like&amp;nbsp;ȩȨ&amp;nbsp;ÝŸŷŶ. You may want to not use them if you ever plan to login from a windows workstation.&lt;/li&gt;
&lt;li&gt;«»° aren&#39;t accessible on all FR-CA keyboard so you need to memorize the Alt-Numlock combination.&lt;/li&gt;
&lt;li&gt;Similar alternatives for Spanish people:&amp;nbsp;¿¡&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;You now have a password that:&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;is mostly copy-paste safe&lt;/li&gt;
&lt;li&gt;is uncrackable by most rainbow tables. Who generates a utf8 rainbow table with ½ or µ with length of 12 characters?&lt;/li&gt;
&lt;li&gt;will probably not be accepted by most web sites since it&#39;s too secure. :(&lt;/li&gt;
&lt;/ul&gt;&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://m-a-tech.blogspot.com/feeds/4412656505819641174/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7003844608523781358/4412656505819641174' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/4412656505819641174'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/4412656505819641174'/><link rel='alternate' type='text/html' href='http://m-a-tech.blogspot.com/2011/03/generating-passwords.html' title='Generating passwords'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10266008552441372345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7003844608523781358.post-480884714439713153</id><published>2011-01-19T09:42:00.011-05:00</published><updated>2011-03-29T14:30:09.057-04:00</updated><title type='text'>1 kibioctet = 1023,937522 octets</title><content type='html'>Vous cherchez à propos de l&#39;affiche installé dans votre université? Je fais une présentation à propos de la corruption silencieuse de données le 27 janvier à l&#39;École Polytechnique de Montréal et le 28 janvier à l&#39;Université Laval à Québec.&lt;br /&gt;
&lt;br /&gt;
Mais en premier, trouvez la réponse à l&#39;énigme.&lt;br /&gt;
&lt;br /&gt;
Bonne Chance!&lt;br /&gt;
&lt;br /&gt;
Note: certains chercherons peut-être 1 kibioctet = 1023.937522 octets même si l&#39;affiche utilise une virgule.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Mise à jour #1&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Si vous avez de la difficulté à trouver la réponse, je vous conseille d&#39;appliquer:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Pour les finissants, &lt;a href=&quot;http://www.google.com/intl/en/jobs/students/us/technical/software-engineer-new-grad-north-america-locations/index.html&quot;&gt;http://www.google.com/intl/en/jobs/students/us/technical/software-engineer-new-grad-north-america-locations/index.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Pour un stage, &lt;a href=&quot;http://www.google.com/jobs/students/us/internships/eng/software-engineering-intern-summer-north-america-locations/index.html&quot;&gt;http://www.google.com/jobs/students/us/internships/eng/software-engineering-intern-summer-north-america-locations/index.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;b&gt;Mise à jour #2&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
L&#39;énigme n&#39;a rien à voir avec 1024&amp;nbsp;en particulier.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;&lt;b&gt;Mise à jour #3&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Monsieur Munroe a fait une coquille en écrivant ce nombre.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Mise à jour #4&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
En rapport avec l&#39;indice précédent, si vous donnez un url comme réponse, &quot;/394&quot; en fera partie.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;&lt;b&gt;Mise à jour #5&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Le tout a été causé par un manufacturier.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Mise à jour #6&lt;/b&gt;&lt;br /&gt;
&lt;i&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;(Mis à jour 2011-03-29)&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
Visitez &lt;a href=&quot;http://maruel.github.com/&quot;&gt;maruel.github.com&lt;/a&gt; pour voir la présentation.&lt;br /&gt;
&lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://m-a-tech.blogspot.com/feeds/480884714439713153/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7003844608523781358/480884714439713153' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/480884714439713153'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/480884714439713153'/><link rel='alternate' type='text/html' href='http://m-a-tech.blogspot.com/2011/01/1-kibioctet-1023937522-octets.html' title='1 kibioctet = 1023,937522 octets'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10266008552441372345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7003844608523781358.post-6372342526375438463</id><published>2010-09-06T15:57:00.001-04:00</published><updated>2012-11-06T14:25:02.866-05:00</updated><title type='text'>NovelQuest/MWELab Emperor 1510 review</title><content type='html'>&lt;div style=&quot;background-color: transparent; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;
Here&#39;s the only full length review of the &lt;a href=&quot;http://novelquest.com/emperor_1510.html&quot;&gt;NovelQuest&#39;s Emperor 1510 chair&lt;/a&gt; as far as I know. Most of 1510 buyers are enterprises or institutions but this chair is also useful for professionals and the review is focused on that point of view. I had the chance to be an early adopter. I got this chair in December 2009 so this review is done after extensive use of the Emperor 1510 for more than 8 months. The chair I&#39;m reviewing has these options:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;British Charcoal&lt;/li&gt;
&lt;li&gt;Recaro blue leather seat (&lt;i&gt;see note below&lt;/i&gt;)&lt;/li&gt;
&lt;li&gt;2.1 Bose sound system&lt;/li&gt;
&lt;li&gt;Custom monitor support, monitors weren&#39;t included&lt;/li&gt;
&lt;li&gt;USB hub under the armrest&lt;/li&gt;
&lt;li&gt;Blue LEDs package&lt;/li&gt;
&lt;li&gt;110 volts&lt;/li&gt;
&lt;/ul&gt;
&lt;b&gt;Delivery&lt;/b&gt;&lt;br /&gt;
This chair is heavy and high. You&#39;re not buying cheap plastic here. It is almost 6&#39; feet tall when &quot;boxed&quot;. Most parts are screwed so it can be split into smaller pieces to move it in more confined spaces, it just takes much more time to disassemble and reassemble. The seat itself is removable but there are more than 20 screws to remove first. With flaps and monitors removed, the chair is 27&quot; wide so it fits even smaller doors. It&#39;s on the heavy side, around 275lbs so you need to plan in advance for the move.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Weight and Size&lt;/b&gt;&lt;br /&gt;
Once unpacked, the chair fits low ceilings since it&#39;s &lt;i&gt;merely&lt;/i&gt; 6&#39;6&quot; high. The main concern I had when it was delivered was that the bottom didn&#39;t have polyester padding, the type of padding you often see on Ikea furniture. I was afraid the wood floor would be scratched by the direct metal contact coupled to the sheer weight of the structure. After many months of use, I can say this is not an issue. As with any furniture, dust tends to accumulate under the chair so it needs to be moved to clean the floor properly.&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEd6fyATbxFTtAmrC090oHJ72lvf6o91uRDknzR0qTBJZDbcy5diyPkKs4MnaSb7lQkRe3Q2LeO6PbRnIeJ4A89ECSPHiS3x5zMgIOikMvPVtvHVDN05Jpx7LQCAUhV3As5AvCSEgGCQMI/s1600/control_panel.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;81&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEd6fyATbxFTtAmrC090oHJ72lvf6o91uRDknzR0qTBJZDbcy5diyPkKs4MnaSb7lQkRe3Q2LeO6PbRnIeJ4A89ECSPHiS3x5zMgIOikMvPVtvHVDN05Jpx7LQCAUhV3As5AvCSEgGCQMI/s200/control_panel.jpg&quot; width=&quot;200&quot; /&gt;&lt;/a&gt;There is 2 electrical cylinders on the seat. One to raise the arm holding the monitors and the other to tilt the whole chair. The control panel is on the left arm rest. The fifth control is for the LEDs.&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaSbddYMf5xvvZfK6Wf4JDB9A9RjU_7Pc8NjolONJ_vrRhoSX7_1k-Emasp9qRJ7wz9JTm8vVu4g9DbezLf8YXELl1Q6c4apRkVfoPwreFt3UPU-yPtJkN6ZrPd831nITdJ4oP1ixBb9N1/s1600/monitors.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;240&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaSbddYMf5xvvZfK6Wf4JDB9A9RjU_7Pc8NjolONJ_vrRhoSX7_1k-Emasp9qRJ7wz9JTm8vVu4g9DbezLf8YXELl1Q6c4apRkVfoPwreFt3UPU-yPtJkN6ZrPd831nITdJ4oP1ixBb9N1/s320/monitors.jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;b&gt;Monitors&lt;/b&gt;&lt;br /&gt;
I have a custom configuration and was told it will be a unique item, so please don&#39;t try to order this configuration. The Emperor 1510 was replacing my desk of three 24&quot; Dell 2407wfp and one 17&quot; Dell 1707fp. I tried to have the old 17&quot; monitor above the right-most 24&quot; but that didn&#39;t work out so I just left the monitor on a table on the side of the chair. The main issue is weight asymmetry on the arm, causing it to oscillate significantly. So in the end, you want to have your monitor configuration to be symmetrical unlike mine. If you want to go with the &lt;a href=&quot;http://www.matrox.com/graphics/en/products/gxm/th2go/&quot;&gt;Matrox TripleHead2Go&lt;/a&gt; you will be limited to three 1680 * 1050 monitors. The default 19&quot; monitors setup is made of 1280*1024 monitors. Three HDMI -&amp;gt; DVI cables are now provided inside the tubes so you shouldn’t have to strap cables as I’ve done.&lt;br /&gt;
&lt;br /&gt;
Monitor weight is also an issue. Dell 2407wfp&#39;s aren&#39;t on the light side and putting 50lbs of monitors on it is apparent since the arm speed had to be slowed down. Everything is as new after 6 months of use. Cheaper monitors are usually lighter so that may be a saner choice. Mine have &lt;a href=&quot;http://en.wikipedia.org/wiki/Backlight&quot;&gt;CCLF backlight&lt;/a&gt;, newer LED backlight monitors may be lighter, check the specs first. If you can sustain the high dpi of a 30&quot; monitor, it&#39;s probably the way to go since you have more pixels than three 19&quot;.&lt;br /&gt;
&lt;br /&gt;
I own a nvidia Quadro NVS 450 but many options are available: use one of the triple output card from ATI, nvidia or Matrox or use two video cards. If you use a Matrox TripleHead2Go, the operating system thinks you have only one monitor so it has side effects like putting the taskbar across all monitors instead of only the one of your choice and you &lt;a href=&quot;http://www.matrox.com/graphics/en/products/gxm/dh2go/faq/#14&quot;&gt;cannot rotate them&lt;/a&gt;. At the same time, configuration is easier and you can use cheaper video card since you don&#39;t need 3 separate outputs.&lt;br /&gt;
&lt;br /&gt;
If you use your own monitor(s), be sure to have a VESA mount on them and to not have them be too deep. As a reference, a 2407wfp is the absolute maximum deepness you can have as I&#39;ve lost all possibility to do vertical orientation alignment. I highly recommend using 16:10 monitors and not 16:9 ones. If you can, 4:3 or even 5:4 monitors definitely make sense.&lt;/div&gt;
&lt;div style=&quot;background-color: transparent; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJAQYvttktXCkxmapzYR0_f6bQ9v8DcjnrbebHV8j9MSN2njwen1mzDqjj7o8X174N0stDbXMpAPfjH438ryoCAu7ftuwUizkviu9IgioB5etSiAX9179BZd0fDBbtXbz7dSfnievCZFnb/s1600/code_review.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;316&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJAQYvttktXCkxmapzYR0_f6bQ9v8DcjnrbebHV8j9MSN2njwen1mzDqjj7o8X174N0stDbXMpAPfjH438ryoCAu7ftuwUizkviu9IgioB5etSiAX9179BZd0fDBbtXbz7dSfnievCZFnb/s400/code_review.jpg&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;This setup is perfect for doing code reviews, coding, monitoring build status and chatting on irc all at once&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;Sound&lt;/b&gt;&lt;br /&gt;
I am impressed by the Bose 2.1 sound system. I had really low expectation about it as I dislike 2.1 sound system in general. I prefer old style extended range speakers with dual tweeters and one woofer per speaker box. Pop and techno music reproduction on the Bose system is really good and I assume it&#39;d be the same for gaming, you wouldn&#39;t want to have headphones on this chair. Since the subwoofer is confined under the chair, the bass level is really high. I had to reduce its level so I would be comfortable while working! Gamers may prefer the 5.1 to have better spacial reproduction to know where that grenade blast came from.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Gaming&lt;/b&gt;&lt;br /&gt;
If you have more than 4995$ to put in a chair, plus a powerful workstation and monitors, you probably have a professional life to pay these gadgets. This probably means you stopped gaming a long time ago as I did. I&#39;d personally prefer to have a high dpi monitor like a 30&quot; but some models tend to suffer input lag. If you want to have surround gaming, three 19&quot; is the way to go, at the cost of having less precise snipper shots since the center monitor doesn’t have that many pixels. The only thing you want to make sure is to not have a low end video card.&lt;br /&gt;
&lt;br /&gt;
For the video card, many options are available: &lt;a href=&quot;http://www.amd.com/us/products/technologies/ati-eyefinity-technology/Pages/eyefinity.aspx&quot;&gt;ATI with Eyefinity&lt;/a&gt;, &lt;a href=&quot;http://www.nvidia.com/object/3dv-system-requirements-surround-technology.html&quot;&gt;nvidia with 2D Surround&lt;/a&gt; or a &lt;a href=&quot;http://www.matrox.com/graphics/surroundgaming/en/home/&quot;&gt;Matrox TripleHead&lt;/a&gt;. You will want to use monitors that don&#39;t have &lt;a href=&quot;http://www.avforums.com/forums/lcd-led-lcd-tvs/612503-lcd-input-lag-video-delay-measurement-pc-console-games-responsiveness.html&quot;&gt;LCD panel&lt;/a&gt; &lt;a href=&quot;http://forums.anandtech.com/showthread.php?t=39226&quot;&gt;input&lt;/a&gt; &lt;a href=&quot;http://arstechnica.com/civis/viewtopic.php?f=6&amp;amp;t=138271&quot;&gt;delay&lt;/a&gt;, which means using the LCD in its native resolution when gaming or using the video card to do the scaling instead.&lt;/div&gt;
&lt;div style=&quot;background-color: transparent; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;
&lt;br /&gt;
I was tempted to try the new nvidia surround and ATI Eyefinity gaming support. I’d be running 3600x1920 if I were to rotate the third monitor in portrait as I don’t think there’s any way to put 3x 1920x1200 monitors in landscape on the Emperor 1510. The 3600x1920 setup only slightly wider than a 16:9 configuration so it’s not “surround” in its truest sense but you still get significantly more pixels than a 30” monitor and a wider view than a 1920x1080. Great for these sniper shots.&amp;nbsp;Both nvidia and ATI support portrait monitors. A (slightly crazy) colleague told me his ATI Radeon HD 5970 can drive three 30’ in most games fine enough so it should blast with three 24’. He now uses two HD 5970 &amp;nbsp;in CrossFireX so most games can be played at max settings.&lt;/div&gt;
&lt;div style=&quot;background-color: transparent; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;
&lt;br /&gt;
&lt;b&gt;Seat&lt;/b&gt;&lt;br /&gt;
Since the seat is different from what you&#39;ll get, I won&#39;t make a full review of it here. In short this is a real racing car seat so it has many settings but not all of them are relevant like sides hardening. The Recaro is also a very firm seat. It&#39;s comfortable even at very high temperature, tested at 35°C without A/C on. When raising the seat, it also advances so it is a bit harder to find the sweet spot. If you can attend one of the trade show that NovelQuest presents, I&#39;d recommend you to try the seat first to get an idea.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;USB hub option and wireless&lt;/b&gt;&lt;br /&gt;
The USB hub is now a powered type so you should be able to charge your cellphone on it. Keep in mind this chair is a lot of metal so it acts as an antenna with regard to wireless devices. There is no issue with Wifi but there is with Bluetooth and wireless mice and keyboards since their emission power is relatively low. This means you&#39;ll need to keep the USB receiver near the device to have it working at all. Cabled devices don&#39;t have any issue except that I tend to drop them on the floor, I already broke one keyboard. So putting the receiver on the USB hub just below the armrest makes sense here.&lt;br /&gt;
&lt;br /&gt;
&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;float: right; margin-left: 1em; text-align: right;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9IthtUoso3tBWxi2ZpLtvTPM2L9jXBvOsp1LTHk1gFCAgtU0ROUyn7Q2icmjkJH5tI4IakkBnAtbF3Ei1xsEuC8UIXf_k2qcGzh5lg1P2v9k52uou1KUdWfaGjk-Dp_XxAasU4MGfdvA7/s1600/leg_rest.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9IthtUoso3tBWxi2ZpLtvTPM2L9jXBvOsp1LTHk1gFCAgtU0ROUyn7Q2icmjkJH5tI4IakkBnAtbF3Ei1xsEuC8UIXf_k2qcGzh5lg1P2v9k52uou1KUdWfaGjk-Dp_XxAasU4MGfdvA7/s320/leg_rest.jpg&quot; width=&quot;204&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;The leg rest is now larger than this one&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;b&gt;Ergonomy&lt;/b&gt;&lt;br /&gt;
The seat itself has a fair number of adjustment but not much for the chair. I have long arms and I&#39;m the kind of guy to remove the armrest on all the chairs I&#39;ve been using as they were always too high. The armrests on the Emperor are soldered and the seat is screwed on the metal base. I am also farsighted. So in my case, the seat was too close to the monitors and the armrest too high. It took my a while to convince myself to bring on the drill and to put new holes on the base metal frame to move the seat backwards about 2&quot;. This worked great and the seat is comfortable now. As for the keyboard holder, I don&#39;t use it for the same reason but for &quot;normal&quot; people it should fits well. The whole chair can lean back which makes it quite comfortable but you are limited by how much friction your mouse has since it will start gliding by itself. Gaming-style mice are much more affected by that since they usually glide more. You&#39;ll also notice I removed the right side arm padding to remove an additional 1&quot; for my right arm, making mouse movement easier to reduce the likelihood of having &lt;a href=&quot;http://en.wikipedia.org/wiki/Carpal_tunnel_syndrome&quot;&gt;carpal tunnel syndrome&lt;/a&gt;. The chair also has a leg rest which is helpful, the newer model is slightly larger than the one I have. The seat is also extensible.&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGqhdD2VRehtP-W3AdgHln49EbfZ59Qdz7tZPLsqczRsFkKKa4tbhr0_Jo2fQyOchYBKEAADamquvRdZWPR-KJ79VD2eLBYp9zhAslAknQY6g4fr_MQOZ0yMzEKH74t2S1LgqTE01VOGZv/s1600/laptop.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGqhdD2VRehtP-W3AdgHln49EbfZ59Qdz7tZPLsqczRsFkKKa4tbhr0_Jo2fQyOchYBKEAADamquvRdZWPR-KJ79VD2eLBYp9zhAslAknQY6g4fr_MQOZ0yMzEKH74t2S1LgqTE01VOGZv/s320/laptop.jpg&quot; /&gt;&lt;/a&gt;Related to input devices, the USB hub’s placement is perfect for use with a Mac Pro’s keyboard. I’m specifically referring to the full length wired keyboard, not their small wireless one. I coupled this with a Logitech G3 “gaming mouse”. That’s what I’ve been using for a while and it gives me the best efficiency.&lt;br /&gt;
&lt;br /&gt;
If you are left-handed or ambidextrous, you are out of luck. I used to switch the mouse to reduce CTS but I can’t anymore. It is a small issue I can live with.&lt;br /&gt;
&lt;br /&gt;
Using a laptop in addition to the computer is slightly cumbersome. I do that occasionally but I try to not do that for extended period of time because of the awkward position. I use the keyboard holder to hold the laptop for light use.&lt;br /&gt;
&lt;br /&gt;
The whole chair tilt to the point where the keyboard will fall on the ground by itself. It&#39;s great to just sit back and watch a movie, depending on your monitor setup. The pictures below may not look like it tilts a lot but it sure does.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2-hdO1XDpkZ_C8Nc2glsbSkYYHaIaB4Igb57-sS2syiiVa2rlmZBAHa6XqsZKNfbXwYz6YayPF0HQfFniibF1Vj5Nx57S0W2Bnzn7yO2zwP536EAfrM9RPzZ6JY6KBitj9XLk0ASC6VQR/s1600/chaise_droite.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;200&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2-hdO1XDpkZ_C8Nc2glsbSkYYHaIaB4Igb57-sS2syiiVa2rlmZBAHa6XqsZKNfbXwYz6YayPF0HQfFniibF1Vj5Nx57S0W2Bnzn7yO2zwP536EAfrM9RPzZ6JY6KBitj9XLk0ASC6VQR/s200/chaise_droite.jpg&quot; width=&quot;184&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimMMjFgno61imwIgq9b8gaEqvyxVPN_jm7EI-oH4jiFHNuB-x1USf00tX7XkeYVzhCo5ExWBAGyZCGeIbpDAhPfKrjNPcKvuO8btcDX0VPgwkAnkXc0QNlW6GwW1qXGMRq1kiCFQWnPVB_/s1600/chaise_pench%C3%A9e.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;200&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimMMjFgno61imwIgq9b8gaEqvyxVPN_jm7EI-oH4jiFHNuB-x1USf00tX7XkeYVzhCo5ExWBAGyZCGeIbpDAhPfKrjNPcKvuO8btcDX0VPgwkAnkXc0QNlW6GwW1qXGMRq1kiCFQWnPVB_/s200/chaise_pench%C3%A9e.jpg&quot; width=&quot;178&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: right;&quot;&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;Cabling&lt;/b&gt;&lt;br /&gt;
I bought three cheap dual-link DVI 25&#39; cables at 30$ each plus USB cables. Look for 24 AWG cables if you choose this length, 28 AWG may not be of enough quality to push the signal at 1920x1200. Since my video card has display ports, I had to use the included passive DisplayPort -&amp;gt; single-link DVI adaptors which reduces the DVI signal strength. Having dual-link DVI cable still makes sense as it reduces internal &lt;a href=&quot;http://en.wikipedia.org/wiki/Electromagnetic_interference&quot;&gt;cross-wire EMI&lt;/a&gt;. I strapped the USB and DVI cables on the arms with velcros. If you plan to do this, be sure to use black cables with black metal coating since if you choose the red metal frame option, the cables will be hard to hide. In the end, that works out very well and there is no video signal loss. I use a USB cable to plug my own webcam since I&#39;m using a Logitech QuickCam Pro 9000. The one included by default wasn&#39;t high quality enough for videoconferencing. Note that now three video cables are passed inside the arm so it may be sufficient for you. It&#39;s also nicer to not have wires visible.&lt;br /&gt;
&lt;br /&gt;
The chair has a power cable for a computer if you want to keep it on one of the flap but I chose to keep the computer in the wardrobe, &lt;i&gt;literally&lt;/i&gt;. This explains the long cables since 15&#39; cables are long enough to connect anything from the monitors to a computer on the side. Keeping the computer in the wardrobe make the whole look much cleaner.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Working in a team environment&lt;/b&gt;&lt;br /&gt;
One issue with this chair is that &lt;a href=&quot;http://en.wikipedia.org/wiki/Pair_programming&quot;&gt;paired programming&lt;/a&gt; is not practical since the chair is designed for single person use and there isn&#39;t much place to let someone else look a the screens correctly. This is mainly because of the angle of each monitors. If only a single monitor is attached to the arm, the issue is much less important because there isn&#39;t monitor curvature.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Getting in and out&lt;/b&gt;&lt;br /&gt;
It is slower than a normal chair. It is even slower in my configuration because the arm had to be slowed down due to heavy monitor weight. At the beginning I was a little annoyed by that but I got used to this. The only complain I still have is that the arm&#39;s control still don&#39;t have an &#39;auto&#39; mode like electric car windows for full up/down movement.&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRcU5LApcmrZfUFO51idPQS3Tq0g96PeTXPX9hHoukoAmgIIOKhVzqLoDLKHFItFUeVHGwQV0GQnZDZX6iaIAv-6BJA6V0nOOqFf4nshKo94tzRcd5q6u1ri3jG1Vcj0WxeAaq2W80ZAhq/s1600/chaise_leds.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;198&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRcU5LApcmrZfUFO51idPQS3Tq0g96PeTXPX9hHoukoAmgIIOKhVzqLoDLKHFItFUeVHGwQV0GQnZDZX6iaIAv-6BJA6V0nOOqFf4nshKo94tzRcd5q6u1ri3jG1Vcj0WxeAaq2W80ZAhq/s200/chaise_leds.jpg&quot; width=&quot;200&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;b&gt;WOW factor and LED lighting&lt;/b&gt;&lt;br /&gt;
I have the base LED lighting with the LED packages. Once you&#39;ve got monitors, computer and sound hooked up, you&#39;ll see the wow factor and you have to see it to understand what I mean. That works out pretty well with friends. The LEDs are not strictly useful but it increases the &#39;wow&#39; effect significantly so it&#39;s a good option.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Conclusion&lt;/b&gt;&lt;br /&gt;
It is especially useful for home worker since it reduces the space your desk takes but it is not convenient for people managing even a small amount of paper. It&#39;s also smaller than a conventional cubicle so it&#39;s a space saver in offices. It definitely has the wow factor. If you put a large enough monitor, you don&#39;t need a personal cinema room. So in the end, if I have to buy it again, I&#39;ll do.&lt;br /&gt;
&lt;br /&gt;
Even though I work for Google, I bought the chair on my own. No, Google doesn&#39;t have these, yet.&lt;/div&gt;
&lt;div style=&quot;background-color: transparent; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: transparent; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;
&lt;br /&gt;
Copyright 2010 Marc-Antoine Ruel. All rights reserved. Reproduction can only be done with the consent of the author.&lt;/div&gt;
&lt;div style=&quot;background-color: transparent; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: transparent; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;background-color: transparent; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;
&lt;b&gt;&lt;i&gt;Edit 2012-11-06&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
I spent all my workdays in it for the past 2 years. The seating is really good and I can stay focused for many hours in a row. A setup of 3 monitors in portrait is hard to beat for a programmer, and the immersion is really good, I totally forget what&#39;s around me.&lt;br /&gt;
&lt;br /&gt;
Note that my chair has a standard Recaro Topline seat &lt;a href=&quot;http://www.recaro-automotive.com/us/product-areas-us/aftermarket-seats/product/retired-products/trend-trend-topline.html&quot;&gt;which is now discontinued&lt;/a&gt;. This is a car seat so that&#39;s why it looks a bit tick on the pictures, it is tick. I don&#39;t know which seat is used in the new revision. It seems a bit thinner but that shouldn&#39;t change anything comfort-wise, you are not in a car after all. If seating concerns you, I&#39;d recommend to inquire the company directly or better, visit one of the trade show where they present the chair so you can try it yourself.&amp;nbsp;The chair itself is now sold by MWE Lab (&lt;a href=&quot;http://mwelab.com/&quot;&gt;mwelab.com&lt;/a&gt;). They are nice guys and they list the trade shows where you can try it. That&#39;s how I made the first contact.&lt;br /&gt;
&lt;br /&gt;
The overall structure doesn&#39;t seem to have changed much and I can vouch for the solidity of the steel structure, even if using professional 24&quot; monitors is a tad on the heavy side of what it can support. Using consumer grade LED 24&quot; monitors should be fine. I replaced my Dell 2407wfp with Lenovo&amp;nbsp;4420MB2 (which feels like paperweight compared to the Dells) and it went fine even if the spacing are not exactly the same.&lt;br /&gt;
&lt;br /&gt;
The new revision of the chair now has a proper laptop holder which I do not have. So I use the keyboard holder as a laptop holder. It seems to have a fair number of small improvements like the sound knob and the power buttons are better placed. It now has a proper cup holder. And the overall look is a bit more polished too. So I think the new revision is worth trying out.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://m-a-tech.blogspot.com/feeds/6372342526375438463/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7003844608523781358/6372342526375438463' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/6372342526375438463'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/6372342526375438463'/><link rel='alternate' type='text/html' href='http://m-a-tech.blogspot.com/2010/09/novelquest-emperor-1510-review.html' title='NovelQuest/MWELab Emperor 1510 review'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10266008552441372345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEd6fyATbxFTtAmrC090oHJ72lvf6o91uRDknzR0qTBJZDbcy5diyPkKs4MnaSb7lQkRe3Q2LeO6PbRnIeJ4A89ECSPHiS3x5zMgIOikMvPVtvHVDN05Jpx7LQCAUhV3As5AvCSEgGCQMI/s72-c/control_panel.jpg" height="72" width="72"/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7003844608523781358.post-2220484294232562471</id><published>2010-06-30T12:10:00.002-04:00</published><updated>2010-08-17T16:38:22.602-04:00</updated><title type='text'>rdesktop from linux into Windows with a ca-fr keyboard layout</title><content type='html'>[note to myself]&lt;br /&gt;
&lt;br /&gt;
I am using the French Canadian keyboard layout on Ubuntu Lucid and was having a hard time typing &quot;\&quot;. Solution:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;With &quot;Terminal Server Client&quot; GUI and on the &quot;Local Resources&quot; tab, set the keyboard to &quot;ca-fr&quot;.&lt;/li&gt;

&lt;ul&gt;&lt;li&gt;Note it&#39;s &quot;ca-fr&quot; and &lt;b&gt;not&lt;/b&gt; &quot;fr-ca&quot; or &quot;fr_CA&quot; or whatever wrong values I could come up with..!&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;With rdesktop, it&#39;s &quot;rdesktop -k fr-ca &lt;i&gt;&amp;lt;hostip&amp;gt;&lt;/i&gt;&quot;.&lt;/li&gt;

&lt;ul&gt;&lt;li&gt;Note it&#39;s &quot;fr-ca&quot; there and &lt;b&gt;not&lt;/b&gt; &quot;ca-fr&quot; or &quot;fr_CA&quot;. +1 for consistency. Oh well...&lt;/li&gt;
&lt;/ul&gt;&lt;/ul&gt;&lt;div&gt;&lt;b&gt;Update&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Forget about tsclient and rdesktop, I never fully got them to work correctly. Remmina works much better for me. It is based on FreeRDP that uses sane keyboard input. Simply install its &lt;a href=&quot;http://remmina.sourceforge.net/downloads.shtml&quot;&gt;ppa&lt;/a&gt;&amp;nbsp;since Ubuntu Lucid&#39;s version is too old.&lt;/div&gt;&lt;ul&gt;&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://m-a-tech.blogspot.com/feeds/2220484294232562471/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7003844608523781358/2220484294232562471' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/2220484294232562471'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/2220484294232562471'/><link rel='alternate' type='text/html' href='http://m-a-tech.blogspot.com/2010/06/rdesktop-from-linux-into-windows-with.html' title='rdesktop from linux into Windows with a ca-fr keyboard layout'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10266008552441372345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7003844608523781358.post-759637650085210029</id><published>2010-06-14T12:18:00.004-04:00</published><updated>2010-06-14T12:26:34.807-04:00</updated><title type='text'>automatic git mergetool selection based on X availability</title><content type='html'>I usually edit code over ssh, when merging, &lt;a href=&quot;http://www.vim.org/&quot;&gt;vimdiff&lt;/a&gt; is sufficient to me most of the time but when the merge is too complex, &lt;a href=&quot;http://kdiff3.sourceforge.net/&quot;&gt;kdiff3&lt;/a&gt; does a better job so I &lt;a href=&quot;http://www.nomachine.com/&quot;&gt;NX&lt;/a&gt; into the box and start the merge from there. I got tired of using &lt;i&gt;git mergetool=kdiff3&lt;/i&gt; so I wrote this tool. Note that vimdiff is started in a different configuration that would be done in a normal &lt;i&gt;git config merge.tool = vimdiff&lt;/i&gt;; cursor is reset to line 0 and the viewport is modified in a more useful format, plus all the 4 buffers are loaded.&lt;br /&gt;
&lt;blockquote&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;#!/bin/sh&lt;br /&gt;
# Copyright (c) 2010 Marc-Antoine Ruel&lt;br /&gt;
# Automatically select the right merge tool based on X session availability.&lt;br /&gt;
&lt;br /&gt;
if [ ! &quot;$(git config --global --get mergetool.autodiff.cmd)&quot; ]; then&lt;br /&gt;
&amp;nbsp;&amp;nbsp;echo Setting git config --global merge.tool = autodiff&lt;br /&gt;
&amp;nbsp;&amp;nbsp;git config --global mergetool.autodiff.cmd &quot;`pwd`/autodiff.sh \$BASE \$LOCAL \$REMOTE \$MERGED&quot;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;git config --global merge.tool autodiff&lt;br /&gt;
&amp;nbsp;&amp;nbsp;echo Done.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;exit&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ -z &quot;$DISPLAY&quot; ]; then&lt;br /&gt;
&amp;nbsp;&amp;nbsp;# Start in diff mode, move the viewport down and move up to first line.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;vimdiff -c &quot;wincmd J&quot; -c &quot;0&quot; $4 $2 $1 $3&lt;br /&gt;
else&lt;br /&gt;
&amp;nbsp;&amp;nbsp;# Inside an X session, redirect stderr.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;kdiff3 --auto --L1 &quot;$4 (Base)&quot; --L2 &quot;$4 (Local)&quot; --L3 &quot;$4 (Remote)&quot; -o $4 $1 $2 $3 2&amp;gt; /dev/null&lt;br /&gt;
fi&lt;br /&gt;
&lt;/span&gt;&lt;/blockquote&gt;</content><link rel='replies' type='application/atom+xml' href='http://m-a-tech.blogspot.com/feeds/759637650085210029/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7003844608523781358/759637650085210029' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/759637650085210029'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/759637650085210029'/><link rel='alternate' type='text/html' href='http://m-a-tech.blogspot.com/2010/06/automatic-git-mergetool-selection-based.html' title='automatic git mergetool selection based on X availability'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10266008552441372345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7003844608523781358.post-4702525878417736709</id><published>2010-05-12T11:07:00.001-04:00</published><updated>2010-05-12T14:33:21.375-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="windows"/><title type='text'>Process ID reuse on Windows</title><content type='html'>Process IDs are reused on Windows after uptime has been long enough. Probably for compatibility with old applications, Windows tries to use 15 bits process ids for as long as it can&amp;nbsp;and they eventually grow to 31 bits values if you create enough processes simultaneously.&lt;br /&gt;
&lt;br /&gt;
I always though process ids weren&#39;t reused until it was unreferenced. I was wrong in &lt;i&gt;how&lt;/i&gt; it is referenced. I thought that having a process ID as a parent of another live process was enough but I was wrong, it needs to have a handle alive.&lt;br /&gt;
&lt;br /&gt;
Here&#39;s an example screenshot. This kind of behavior can be recreated by having a lot of orphan processes that no process keeps an handle to their parent:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYMIk7ElQETeL38JsA4gERBjaCanrzKzDrC9aU3Xfi6RwQJKLKxP7WM5nxFeSiEyPXw46cXp8kuXBeVBjZmeaEefR0P_cIrCfKgk6-WCzJofDYXb3fuKy4UAlnMSrmf3AM4jA__QO6MZL5/s1600/process_id_reuse.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;379&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYMIk7ElQETeL38JsA4gERBjaCanrzKzDrC9aU3Xfi6RwQJKLKxP7WM5nxFeSiEyPXw46cXp8kuXBeVBjZmeaEefR0P_cIrCfKgk6-WCzJofDYXb3fuKy4UAlnMSrmf3AM4jA__QO6MZL5/s640/process_id_reuse.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
I found this behavior while recreating a process tree tool. Naively checking the process ids is not sufficient. As you can see, Process Explorer already know about that fact and doesn&#39;t simply compare the process IDs. It uses another comparison else to discover the real parenthood. PROCESSENTRY32.th32ParentProcessID doesn&#39;t give enough data to discriminate. So the only good way is to use GetProcessTimes() and verify the process creation dates.</content><link rel='replies' type='application/atom+xml' href='http://m-a-tech.blogspot.com/feeds/4702525878417736709/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7003844608523781358/4702525878417736709' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/4702525878417736709'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/4702525878417736709'/><link rel='alternate' type='text/html' href='http://m-a-tech.blogspot.com/2010/05/process-id-reuse-on-windows.html' title='Process ID reuse on Windows'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10266008552441372345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYMIk7ElQETeL38JsA4gERBjaCanrzKzDrC9aU3Xfi6RwQJKLKxP7WM5nxFeSiEyPXw46cXp8kuXBeVBjZmeaEefR0P_cIrCfKgk6-WCzJofDYXb3fuKy4UAlnMSrmf3AM4jA__QO6MZL5/s72-c/process_id_reuse.png" height="72" width="72"/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7003844608523781358.post-4652088599416434836</id><published>2010-04-28T17:13:00.002-04:00</published><updated>2010-04-30T19:19:00.965-04:00</updated><title type='text'>MacOSX survival guide</title><content type='html'>Terminal preference;&lt;br /&gt;
1) Tab Startup, new window with settings: Pro&lt;br /&gt;
2) Tab Settings, Pro&lt;br /&gt;
&amp;nbsp; * Text, check everything except antialias text&lt;br /&gt;
&amp;nbsp; * Window, check only Active process name&lt;br /&gt;
&amp;nbsp; * Window, Background color, set alpha to &amp;gt;90%&lt;br /&gt;
&amp;nbsp; * Keyboard, check Use option as meta key&lt;br /&gt;
&amp;nbsp; * Keyboard, add end, page up, page down, home usage without shift modifier&lt;br /&gt;
&amp;nbsp; * Advanced, Delete sends Ctrl-H&lt;br /&gt;
(It&#39;s impressive how the terminal app is broken by default on Mac OS X)&lt;br /&gt;
&lt;br /&gt;
System Preferences;&lt;br /&gt;
1) Keyboard &amp;amp; Mouse&lt;br /&gt;
&amp;nbsp; * Keyboard, check Use all F1, F2, etc. keys as standard function keys &lt;br /&gt;
&amp;nbsp; * Keyboard Shortcuts, Uncheck Desktop (F11) and all the stupid shortcuts.&lt;br /&gt;
2) Trackpad&lt;br /&gt;
&amp;nbsp; * Enable Tap to Click and Dragging and Secondary Tap&lt;br /&gt;
&lt;br /&gt;
Enable lock icon:&lt;br /&gt;
1) /Applications / Utility/ Keychain Access&lt;br /&gt;
2) Preferences&lt;br /&gt;
3) check Show Status in Menu Bar&lt;br /&gt;
&lt;br /&gt;
French Canadian keyboard:&lt;br /&gt;
&lt;a href=&quot;http://matthieu.yiptong.ca/2009/09/09/canadian-french-keyboard-layout-for-mac-os-x/&quot;&gt;http://matthieu.yiptong.ca/2009/09/09/canadian-french-keyboard-layout-for-mac-os-x/&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://m-a-tech.blogspot.com/feeds/4652088599416434836/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7003844608523781358/4652088599416434836' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/4652088599416434836'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/4652088599416434836'/><link rel='alternate' type='text/html' href='http://m-a-tech.blogspot.com/2010/04/macosx-survival-guide.html' title='MacOSX survival guide'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10266008552441372345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7003844608523781358.post-6347703982256359830</id><published>2010-01-15T15:04:00.000-05:00</published><updated>2010-01-15T15:04:03.375-05:00</updated><title type='text'>Marketing email FAIL</title><content type='html'>You know you put too much junk in your marketing emails when you keep obsolete statements from more than &lt;b&gt;3 years &lt;/b&gt;ago:&lt;br /&gt;
&lt;br /&gt;
&quot;8. Microsoft requires that a PC have a modern processor and 512MB RAM to be included in the Windows Vista Capable PC program. Since the operating system and drivers are not final, Windows Vista has not been tested on all user configurations. (...)&quot;&lt;br /&gt;
&lt;br /&gt;
(From a Dell promo email in Canada received today)</content><link rel='replies' type='application/atom+xml' href='http://m-a-tech.blogspot.com/feeds/6347703982256359830/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7003844608523781358/6347703982256359830' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/6347703982256359830'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/6347703982256359830'/><link rel='alternate' type='text/html' href='http://m-a-tech.blogspot.com/2010/01/marketing-email-fail.html' title='Marketing email FAIL'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10266008552441372345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7003844608523781358.post-5183890188268824744</id><published>2009-10-09T10:03:00.001-04:00</published><updated>2010-02-04T11:21:11.154-05:00</updated><title type='text'>Windows, just another dumb terminal?</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizltYhPrrffVMIc3St8AHavmidRCLIWPd0fKkAFeF7FKiPBG9ru1XcMMh59rTFHse0E9PzySKl5aI8iMlvHk2YeHcblJ6vHCxkDWYoj8OccyHe8bJJOVTNnFlKmRhrh-7nEMNaAcWfCU2x/s1600-h/windows_is_an_excellent_dumb_terminal.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizltYhPrrffVMIc3St8AHavmidRCLIWPd0fKkAFeF7FKiPBG9ru1XcMMh59rTFHse0E9PzySKl5aI8iMlvHk2YeHcblJ6vHCxkDWYoj8OccyHe8bJJOVTNnFlKmRhrh-7nEMNaAcWfCU2x/s400/windows_is_an_excellent_dumb_terminal.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;The more I use ssh + screen, the more I realize Windows is an excellent dumb terminal mainly due to its support of awkward monitor setup support. This is four monitors, 1280, 1920 in portrait, 1920 in portrait, 1920 in landscape.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Update:&lt;/b&gt; Note that Windows&#39; 7 WinKey-Arrow and WinKey-Shift-Arrow shortcut makes it even better as a dumb terminal.</content><link rel='replies' type='application/atom+xml' href='http://m-a-tech.blogspot.com/feeds/5183890188268824744/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7003844608523781358/5183890188268824744' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/5183890188268824744'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/5183890188268824744'/><link rel='alternate' type='text/html' href='http://m-a-tech.blogspot.com/2009/10/windows-just-another-dumb-terminal.html' title='Windows, just another dumb terminal?'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10266008552441372345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizltYhPrrffVMIc3St8AHavmidRCLIWPd0fKkAFeF7FKiPBG9ru1XcMMh59rTFHse0E9PzySKl5aI8iMlvHk2YeHcblJ6vHCxkDWYoj8OccyHe8bJJOVTNnFlKmRhrh-7nEMNaAcWfCU2x/s72-c/windows_is_an_excellent_dumb_terminal.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7003844608523781358.post-4633621687065078829</id><published>2009-09-28T12:08:00.006-04:00</published><updated>2009-09-28T12:16:59.836-04:00</updated><title type='text'>Linker</title><content type='html'>&lt;span style=&quot;font-size: large;&quot;&gt;Do you know what you are linking?&lt;/span&gt;&lt;br /&gt;
I&#39;m surprised on how many people are confused about the linking process in general. This discussion will focus on MSVC in particular but this discussion stands for the gnu toolset too. First let&#39;s define:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;A compile unit as a single C++ (.cc) source file generating a single object (.obj) file.&lt;/li&gt;
&lt;li&gt; A &lt;a href=&quot;http://en.wikipedia.org/wiki/Portable_Executable&quot;&gt;PE&lt;/a&gt; is a single output unit from the linker.&lt;/li&gt;
&lt;li&gt; A symbol is a single named component globally visible, like a global function, class definition, member function, global variable, imported symbol with &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/3y1sfaz2.aspx&quot;&gt;dllimport&lt;/a&gt; or template instance; this list is obviously not exhaustive.&lt;/li&gt;
&lt;/ul&gt;&lt;span style=&quot;font-size: large;&quot;&gt;Compilation units&lt;/span&gt;&lt;br /&gt;
When linking, all inputs are linked together to extracts symbols and put them in the output file. This is important for the linker to have compilation units be easy to differentiate one to each other. The reason is that the compilation unit&#39;s name (the source file name) is used in the symbol mangling, especially for file static global variable. This is also important since often even if the source files are in various subdirectories, the output objects are in a single intermediary directory. This can cause problems when you have 2 sources files with the same name. For example, &lt;a href=&quot;http://code.google.com/p/libjingle/&quot;&gt;libjingle&lt;/a&gt;, up to revision 7, has 2 compile units with the same name: &lt;a href=&quot;http://code.google.com/p/libjingle/source/browse/trunk/talk/p2p/base/constants.cc&quot;&gt;constants.cc&lt;/a&gt; and &lt;a href=&quot;http://code.google.com/p/libjingle/source/browse/trunk/talk/xmpp/constants.cc&quot;&gt;constants.cc&lt;/a&gt;. If both arrive in the same output dir, you&#39;re in trouble. But how come it works in this specific case? Well, when the developer adds the second file in the Visual Studio IDE, the IDE will automatically set the ObjectFile attribute to to add a &#39;1&#39; postfix. See &lt;a href=&quot;http://code.google.com/p/libjingle/source/browse/trunk/talk/libjingle.vcproj#sl_svn2_432&quot;&gt;libjingle.vcproj&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;PE and incremental linking&lt;/span&gt;&lt;br /&gt;
Every output PE must have a unique name in a solution. This is something we are hitting in  the &lt;a href=&quot;http://code.google.com/p/chromium/&quot;&gt;Chromium&lt;/a&gt; project since we have chrome.exe and chrome.dll. The issue we face is that both generate chrome.ilk for incremental linking. This cause that incremntal linking fails every time. The workaround is to output one of the binaries in the intermediary output directory and hardlink it back at the right place. Lame but works.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;Every symbol is not on equal footing&lt;/span&gt;&lt;br /&gt;
When defining the same symbol multiple times into a PE, the linker will give errors on &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/xttf5w7w.aspx&quot;&gt;multiple defined symbols&lt;/a&gt;. To alleviate this problem, you can define the symbol as &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/5tkz6s71.aspx&quot;&gt;selectany&lt;/a&gt;, e.g. a weak symbol. But if the two symbol definitions are not exactly the same, you can get into real trouble since one is selected at random at link time.&lt;br /&gt;
&lt;br /&gt;
The interesting twist comes with static libraries. If a symbol is defined in one or multiple static libraries &lt;b&gt;and&lt;/b&gt; in an object file, the &lt;b&gt;symbol defined in the object file will be used&lt;/b&gt;. The best commonly used example is &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms682583.aspx&quot;&gt;DllMain&lt;/a&gt;. When creating a DLL, if it is defined in a .obj file, your definition will be used. If not defined in an object file, the definition provided in the CRT static library will be used.&lt;br /&gt;
&lt;blockquote&gt;So in short, the linker has different priorities when linking its inputs: &lt;i&gt;static libraries are second class citizens to object files&lt;/i&gt;.&lt;br /&gt;
&lt;/blockquote&gt;So if a symbol defined in a static library is not referenced by a symbol in a object file, it will not be linked in. That&#39;s why many people will use the &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/2s3hwbhs.aspx&quot;&gt;/INCLUDE&lt;/a&gt; parameter to force a symbol from a static library to be included. ATL is one doing that with &quot;#pragma comment(linker, &quot;/include:_forceAtlDllManifest&quot;)&quot; in atlbase.h.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;Scalability issue&lt;/span&gt;&lt;br /&gt;
But linking large static libraries takes time. For the Chromium project, some of our libraries are significantly large, browser.lib and webcore.lib being respectively 320 and 408 megs as revision 27335. One way to help speed up is to use &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/024awkd1.aspx&quot;&gt;Use Library Dependency Inputs&lt;/a&gt;. This permits skipping over the static library linking step. Why? Since static libraries cannot use &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/4khtbfyf.aspx&quot;&gt;incremental linking&lt;/a&gt;, they are much slower to link in debug than actual PE.&lt;br /&gt;
&lt;br /&gt;
But all the rules described above change with &lt;i&gt;Use Library Dependency Inputs&lt;/i&gt; since the final linker step links only object files and no static libraries. You see it coming, &lt;i&gt;every symbols are now on equal footing&lt;/i&gt;. Which mean a lot of fun and helps find a lot of problems.&lt;br /&gt;
&lt;br /&gt;
I saw unit tests including another compile unit. That results in duplicate symbols. I saw another project having 2 different main() functions. Same failure. I saw an installer including unit tests. Same failure. Why does that work without the ULDI flag? Because of different symbol priority between object file and static library. When a symbol exists in an object file, the  symbols defined in static libraries are silently discarded. If all the symbols defined in static libraries are now on higher priority, that breaks on every symbols that are ambiguous.&lt;br /&gt;
&lt;br /&gt;
That concludes my short explanation.</content><link rel='replies' type='application/atom+xml' href='http://m-a-tech.blogspot.com/feeds/4633621687065078829/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7003844608523781358/4633621687065078829' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/4633621687065078829'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/4633621687065078829'/><link rel='alternate' type='text/html' href='http://m-a-tech.blogspot.com/2009/09/linker.html' title='Linker'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10266008552441372345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7003844608523781358.post-2818215544825772145</id><published>2009-09-22T11:46:00.000-04:00</published><updated>2009-09-22T11:46:22.535-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="windows"/><title type='text'>usb key windows install</title><content type='html'>These days I install Windows 7 often but I can&#39;t help to remember the steps from Vista:&lt;br /&gt;
&lt;br /&gt;
Open an elevated command prompt:&lt;br /&gt;
&lt;blockquote&gt;&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;diskpart&lt;br /&gt;
list disk&lt;br /&gt;
select disk 2&amp;nbsp;&amp;nbsp; &amp;lt;- choose usb key!&lt;br /&gt;
clean&lt;br /&gt;
create partition primary&lt;br /&gt;
select partition 1&lt;br /&gt;
active&lt;br /&gt;
format fs=fat32 quick&lt;br /&gt;
assign&lt;br /&gt;
exit&lt;br /&gt;
xcopy /h /e /q path\to\uncompressed\iso e:\&amp;nbsp;&amp;nbsp; &amp;lt;- choose usb key!&lt;br /&gt;
&lt;/div&gt;&lt;/blockquote&gt;All this can be done through GUI with Computer Management / Disk Management. Choose an open source program in &lt;a href=&quot;http://en.wikipedia.org/wiki/List_of_ISO_image_software&quot;&gt;http://en.wikipedia.org/wiki/List_of_ISO_image_software&lt;/a&gt; for the iso extraction.</content><link rel='replies' type='application/atom+xml' href='http://m-a-tech.blogspot.com/feeds/2818215544825772145/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7003844608523781358/2818215544825772145' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/2818215544825772145'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/2818215544825772145'/><link rel='alternate' type='text/html' href='http://m-a-tech.blogspot.com/2009/09/usb-key-windows-install.html' title='usb key windows install'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10266008552441372345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7003844608523781358.post-3140317771898998948</id><published>2009-08-27T15:46:00.030-04:00</published><updated>2010-02-04T15:15:40.992-05:00</updated><title type='text'>git notes</title><content type='html'>This message is for me only. I don&#39;t not expect you learn anything from this or even think this is useful. This post represents a huge amount of fighting with blogspot editor.&lt;br /&gt;
&lt;br /&gt;
WORN: git is similar to perl: write-once, read-never. &lt;br /&gt;
&lt;br /&gt;
CONFIGURATION&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git config --global color.ui auto (1.6+)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git config --global user.email me@me.com&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git config --global user.name &quot;Mini Me&quot;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git config --global alias.st status&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git config --global alias.br branch&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;Basically everything at &lt;/span&gt;&lt;a href=&quot;http://git.wiki.kernel.org/index.php/Aliases#Shortcuts&quot;&gt;http://git.wiki.kernel.org/index.php/Aliases#Shortcuts&lt;/a&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;echo *.pyc&amp;gt;&amp;gt;.git/info/exclude&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;Edit these two in your ~/.gitconfig&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;[alias]&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;&amp;nbsp; ignored = &quot;!cd \&quot;$(git rev-parse --show-cdup)\&quot; &amp;amp;&amp;amp; git clean -n -d | cut -c 14- | sed -e \&quot;s/\\/$//\&quot;&quot;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;&amp;nbsp; ignoreall = &quot;!cd \&quot;$(git rev-parse --show-cdup)\&quot; &amp;amp;&amp;amp; git clean -n -d | cut -c 14- | sed -e \&quot;s/\\/$//\&quot; &amp;gt;&amp;gt; .git/info/exclude&quot;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;Use &lt;a href=&quot;http://github.com/lvv/git-prompt&quot;&gt;git-prompt&lt;/a&gt;! I use:&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;max_file_list_length=30&lt;/li&gt;
&lt;li&gt;default_user=me&lt;/li&gt;
&lt;li&gt;default_host=myhost&lt;/li&gt;
&lt;li&gt;default_domain=mydomain&lt;/li&gt;
&lt;li&gt;cwd_cmd=&#39;cwd_truncate 30&#39;&lt;/li&gt;
&lt;li&gt;and enable only the VCS I use. &lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;Use &lt;a href=&quot;http://git.kernel.org/?p=git/git.git;a=blob_plain;f=contrib/completion/git-completion.bash;hb=HEAD&quot;&gt;git-completion.bash&lt;/a&gt;!&lt;/li&gt;
&lt;/ul&gt;MODIFICATIONS&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git remote add origin2 user@host:path/to/repo.git&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git pull --rebase remote_name remote_branch&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git svn clone svn://host/repo --stdlayout&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git svn clone svn://host/repo -T sub/directory&lt;/span&gt;&lt;/li&gt;
&lt;ul style=&quot;font-family: inherit;&quot;&gt;&lt;li&gt;You may want to use --prefix=origin/ but I like to just type &quot;trunk&quot; instead of &quot;origin/trunk&quot; &lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git svn rebase&lt;/span&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;  &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git push remote_name remote_branch&lt;/span&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li style=&quot;font-family: inherit;&quot;&gt;remote_name and remote_branch are optional if branch.merge is set &lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git merge --squash --no-commit [other branch]&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git mergetool --tool=kdiff3&lt;/span&gt;&lt;/li&gt;
&lt;ul style=&quot;font-family: inherit;&quot;&gt;&lt;li&gt;when vimdiff is unsufficient and I&#39;m on X &lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git cherry-pick (hash) &lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li style=&quot;font-family: inherit;&quot;&gt;from the branch where you want to include your change&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git checkout -b new_branch trunk&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git checkout another_branch file_to_bring_here&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li style=&quot;font-family: inherit;&quot;&gt;another branch can be HEAD~1 for a past revision&lt;/li&gt;
&lt;li style=&quot;font-family: inherit;&quot;&gt;note the file is implicitly &quot;added&quot; so git diff will not display anything, use git diff HEAD&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git revert (hash) &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git add .&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git add -p&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li style=&quot;font-family: inherit;&quot;&gt;To index only some parts (hunks), useful to discard some changes by following with a commit and reset.&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git reset &quot;file&quot;&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li style=&quot;font-family: inherit;&quot;&gt;Really the reverse of git add &quot;file&quot; &lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git commit -a -m &quot;bleh&quot;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git commit --amend&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li style=&quot;font-family: inherit;&quot;&gt;Modify the last commit &lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git branch -D branch_to_delete&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git push origin :branch_to_delete&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git reflog&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li style=&quot;font-family: inherit;&quot;&gt;To find a deleted branch back&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git checkout -b new_branch HEAD@{1}&lt;/span&gt;&lt;/li&gt;
&lt;ul style=&quot;font-family: inherit;&quot;&gt;&lt;li&gt;To revive it &lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git rebase -i default~2^&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;To squash or amend previous commits, reappend to previous head. Warning, rewrites history! ^ means rewrite on the parent&lt;span style=&quot;font-family: courier new;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git rebase --continue&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;Never rebase after pushing something!! Only merge! &lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/ul&gt;&lt;br /&gt;
QUERIES&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git branch -a -v&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git diff old..new&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li style=&quot;font-family: inherit;&quot;&gt;Every commit you can reach by new not reachable by new &lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git diff master...HEAD&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li style=&quot;font-family: inherit;&quot;&gt;reachable by either but not both, XOR&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git diff master...&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li style=&quot;font-family: inherit;&quot;&gt;HEAD is implicit&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git diff `git merge-base HEAD master`&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li style=&quot;font-family: inherit;&quot;&gt;refer to 3 commits before&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git diff HEAD~3&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git diff HEAD^^^&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git diff HEAD^2&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li style=&quot;font-family: inherit;&quot;&gt;alternate parent&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git diff master~2^2&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li style=&quot;font-family: inherit;&quot;&gt;headache, really&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git log HEAD ^trunk&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li style=&quot;font-family: inherit;&quot;&gt;when trunk was updated, awesome&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git log -p HEAD ^git-svn&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li style=&quot;font-family: inherit;&quot;&gt;full diff per log &lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git log --pretty=oneline&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git log --pretty=format:&quot;%h %an %ar - %s&quot;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git log --pretty=format:&quot;%h %an %ar - %s&quot; --graph&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git status&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git clean -d -n -x&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li style=&quot;font-family: inherit;&quot;&gt;list currently ignored files &lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git blame -C1 file&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li style=&quot;font-family: inherit;&quot;&gt;search for renames &lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git diff --merge&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li style=&quot;font-family: inherit;&quot;&gt;for 3-way merge conflict&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;git show (hash)&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;&lt;li style=&quot;font-family: inherit;&quot;&gt;will show how a merge conflict was fixed &lt;/li&gt;
&lt;/ul&gt;&lt;/ul&gt;&lt;br /&gt;
Then read &lt;a href=&quot;http://www.kernel.org/pub/software/scm/git/docs/user-manual.html&quot;&gt;http://www.kernel.org/pub/software/scm/git/docs/user-manual.html&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://m-a-tech.blogspot.com/feeds/3140317771898998948/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7003844608523781358/3140317771898998948' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/3140317771898998948'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/3140317771898998948'/><link rel='alternate' type='text/html' href='http://m-a-tech.blogspot.com/2009/08/git-notes.html' title='git notes'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10266008552441372345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7003844608523781358.post-8845829216851285111</id><published>2009-08-27T15:40:00.006-04:00</published><updated>2010-04-19T10:40:27.265-04:00</updated><title type='text'>screen notes</title><content type='html'>This message is for me only. I don&#39;t not expect you learn anything from this or even think this is useful.&lt;br /&gt;
C-a means Ctrl-a&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Key&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; | Action&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; | Notes&lt;br /&gt;
C+a c&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; | new window&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; |&lt;br /&gt;
C+a n&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; | next window&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; | I bind F12 to this&lt;br /&gt;
C+a p&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; | previous window&amp;nbsp; | I bind F11 to this&lt;br /&gt;
C+a N &amp;nbsp; &amp;nbsp; &amp;nbsp; | go to window N &amp;nbsp; | &lt;br /&gt;
C+a &quot;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; | window list &amp;nbsp; &amp;nbsp;&amp;nbsp; | window list is in status line&lt;br /&gt;
C+a C+a&amp;nbsp; &amp;nbsp;&amp;nbsp; | previous window&amp;nbsp; |&lt;br /&gt;
C-a ? &amp;nbsp; &amp;nbsp; &amp;nbsp; | help&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; | unbound commands only&lt;br /&gt;
C+a :&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; | screen cmd prompt| up shows last commands &lt;br /&gt;
C+a Esc / [ | scrllbck/cpy mode| Enter start and end region&lt;br /&gt;
C+a ]&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; | paste buffer&amp;nbsp;&amp;nbsp; &amp;nbsp; | Supports pasting between windows&lt;br /&gt;
C-U / D&amp;nbsp;&amp;nbsp; &amp;nbsp; | page up/down&amp;nbsp;&amp;nbsp; &amp;nbsp; | While in copy mode&lt;/div&gt;&lt;br /&gt;
Efficient screen workflow:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;On 2 monitors, start 2 fullscreen ssh sessions&lt;/li&gt;
&lt;li&gt;Use screen -R -D on the first&lt;/li&gt;
&lt;li&gt;Use screen -x on the second&lt;/li&gt;
&lt;/ul&gt;You can now use screen as text based window manager. (awesome)&lt;br /&gt;
&lt;br /&gt;
To use screen on the ADP1/G1/N1, use &lt;a href=&quot;http://code.google.com/p/connectbot/&quot;&gt;ConnectBot&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Also useful:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;# Bind F11 and F12 (NOT F1 and F2) to previous and next screen window&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;bindkey -k F1 eval prev fit&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;bindkey -k F2 eval next fit&amp;nbsp;&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='http://m-a-tech.blogspot.com/feeds/8845829216851285111/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7003844608523781358/8845829216851285111' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/8845829216851285111'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/8845829216851285111'/><link rel='alternate' type='text/html' href='http://m-a-tech.blogspot.com/2009/08/screen-notes.html' title='screen notes'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10266008552441372345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7003844608523781358.post-7470488998587386478</id><published>2009-08-27T15:38:00.007-04:00</published><updated>2009-10-14T16:03:03.279-04:00</updated><title type='text'>vim / vimdiff notes</title><content type='html'>This message is for me only. I don&#39;t not expect you learn anything from this or even think this is useful.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;background-color: transparent; border-collapse: separate; color: black; font-family: &#39;Times New Roman&#39;; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;&quot;&gt;&lt;span style=&quot;color: #222222;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;table class=&quot;pixelbeat&quot; style=&quot;background-color: #ffffc0; border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px;&quot;&gt;&lt;tbody&gt;
&lt;tr class=&quot;pbtitle&quot; style=&quot;background-color: #b4dc64;&quot;&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;b&gt;Key&lt;/b&gt;&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;b&gt;Action&lt;/b&gt;&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;b&gt;Notes&lt;/b&gt;&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td nowrap=&quot;nowrap&quot; style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;ctrl+w, ctrl+w&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;switch windows&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td nowrap=&quot;nowrap&quot; style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;ctrl-w, &lt;span lang=&quot;fr-ca&quot;&gt;J&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;Move the window down&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td nowrap=&quot;nowrap&quot; style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;do&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;diff obtain&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;doesn&#39;t work in 3-way?&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td nowrap=&quot;nowrap&quot; style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;dp&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;diff put&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;doesn&#39;t work in 3-way?&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td nowrap=&quot;nowrap&quot; style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;[c&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;previous difference&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td nowrap=&quot;nowrap&quot; style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;]c&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;next difference&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td nowrap=&quot;nowrap&quot; style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;:diffupdate&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;diff update&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td nowrap=&quot;nowrap&quot; style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;:syntax off&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;syntax off&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td nowrap=&quot;nowrap&quot; style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;zo&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;open folded text&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td nowrap=&quot;nowrap&quot; style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;zc&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;close folded text&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td nowrap=&quot;nowrap&quot; style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;:set paste&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;span lang=&quot;fr-ca&quot;&gt;Disable auto-indent&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;span lang=&quot;fr-ca&quot;&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td nowrap=&quot;nowrap&quot; style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;span lang=&quot;fr-ca&quot;&gt;v&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;span lang=&quot;fr-ca&quot;&gt;select text&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td nowrap=&quot;nowrap&quot; style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;span lang=&quot;fr-ca&quot;&gt;V&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;span lang=&quot;fr-ca&quot;&gt;select lines&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td nowrap=&quot;nowrap&quot; style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;span lang=&quot;fr-ca&quot;&gt;Ctrl-V&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;span lang=&quot;fr-ca&quot;&gt;select vertical block&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td nowrap=&quot;nowrap&quot; style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;span lang=&quot;fr-ca&quot;&gt;d&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;span lang=&quot;fr-ca&quot;&gt;cut&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td nowrap=&quot;nowrap&quot; style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;span lang=&quot;fr-ca&quot;&gt;y&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;span lang=&quot;fr-ca&quot;&gt;yank (copy)&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td nowrap=&quot;nowrap&quot; style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;span lang=&quot;fr-ca&quot;&gt;p&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;span lang=&quot;fr-ca&quot;&gt;paste after the cursor&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td nowrap=&quot;nowrap&quot; style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;span lang=&quot;fr-ca&quot;&gt;P&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;span lang=&quot;fr-ca&quot;&gt;paste before the cursor&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td nowrap=&quot;nowrap&quot; style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;span lang=&quot;fr-ca&quot;&gt;lv&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;span lang=&quot;fr-ca&quot;&gt;selects an area equal to the yank buffer&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td nowrap=&quot;nowrap&quot; style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;span lang=&quot;fr-ca&quot;&gt;lvp&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;span lang=&quot;fr-ca&quot;&gt;replace paste&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td nowrap=&quot;nowrap&quot; style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;span lang=&quot;fr-ca&quot;&gt;lNNvp&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;span lang=&quot;fr-ca&quot;&gt;replace paste NN times&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td nowrap=&quot;nowrap&quot; style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;span lang=&quot;fr-ca&quot;&gt;*y&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;span lang=&quot;fr-ca&quot;&gt;yank to system clipboard&lt;/span&gt;&lt;br /&gt;
&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border: 2px ridge rgb(255, 255, 192); padding: 0px 0px 0px 2px;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;span style=&quot;background-color: transparent; border-collapse: separate; color: black; font-family: &#39;Times New Roman&#39;; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;&quot;&gt;&lt;span style=&quot;color: #222222;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
But this page is better: &lt;a href=&quot;http://www.tuxfiles.org/linuxhelp/vimcheat.html&quot;&gt;http://www.tuxfiles.org/linuxhelp/vimcheat.html&lt;/a&gt;&lt;br /&gt;
And the real reference: &lt;a href=&quot;http://www.vim.org/htmldoc/quickref.html#quickref&quot;&gt;http://www.vim.org/htmldoc/quickref.html#quickref&lt;/a&gt;, accessible from inline help.&lt;br /&gt;
This one is awesome: &lt;a href=&quot;http://jmcpherson.org/editing.html&quot;&gt;http://jmcpherson.org/editing.html&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://m-a-tech.blogspot.com/feeds/7470488998587386478/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7003844608523781358/7470488998587386478' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/7470488998587386478'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/7470488998587386478'/><link rel='alternate' type='text/html' href='http://m-a-tech.blogspot.com/2009/08/vim-vimdiff-notes.html' title='vim / vimdiff notes'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10266008552441372345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7003844608523781358.post-7784037210767995398</id><published>2009-06-12T19:21:00.002-04:00</published><updated>2009-06-12T20:25:45.872-04:00</updated><title type='text'></title><content type='html'>Boris Jabes (MS) told me that Visual Studio macros can be saved as UTF16 text file. I was shocked. How the hell I was ignoring that functionality, but it seems I&#39;m not alone by the sheer number of hits when searching for [vsmproj] on the web (e.g. less than 100 except on Yahoo)&lt;br /&gt;&lt;br /&gt;So here&#39;s how to convert your binary .vsmacros to utf16 .vsmproj project.&lt;br /&gt;&lt;br /&gt;1. Open Macro Explorer in Visual Studio&lt;br /&gt;2. Select a project or create a new one&lt;br /&gt;3. Open the Properties Window (Alt+Enter)&lt;br /&gt;4. In the properties, change the &quot;storage format&quot; from &quot;binary (.vsmacros)&quot; to &quot;text (unicode)&quot;&lt;br /&gt;&lt;br /&gt;That is much more useful for sharing macros in a source control.</content><link rel='replies' type='application/atom+xml' href='http://m-a-tech.blogspot.com/feeds/7784037210767995398/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7003844608523781358/7784037210767995398' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/7784037210767995398'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/7784037210767995398'/><link rel='alternate' type='text/html' href='http://m-a-tech.blogspot.com/2009/06/boris-jabes-ms-told-me-that-visual.html' title=''/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10266008552441372345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7003844608523781358.post-3225284118006295077</id><published>2009-06-12T19:15:00.002-04:00</published><updated>2009-06-12T19:20:32.724-04:00</updated><title type='text'>Archival price</title><content type='html'>I was considering buying a 50pk 4.5gig DVD spindle. It&#39;s ~15.40$ CAD for a good archival quality.&lt;br /&gt;On the other side, a 1.5TB HD is 150$.&lt;br /&gt;&lt;br /&gt;15.50$ / (50*4.5gb) = 6.9¢&lt;br /&gt;150$ / 1500gb = 10¢&lt;br /&gt;&lt;br /&gt;Taking in account that there&#39;s always lost space in DVD due to trying to fit it to its maximum space, the amount of time taken to format the data to fit in a DVD, the manual intervention of swaping the disks and the slow DVD write speed (compared to a SATA2 HD), I think it&#39;s not valuable to archive on DVD anymore, assuming you keep 2 copies of your data.</content><link rel='replies' type='application/atom+xml' href='http://m-a-tech.blogspot.com/feeds/3225284118006295077/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7003844608523781358/3225284118006295077' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/3225284118006295077'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/3225284118006295077'/><link rel='alternate' type='text/html' href='http://m-a-tech.blogspot.com/2009/06/archival-price.html' title='Archival price'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10266008552441372345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7003844608523781358.post-1927586070538070981</id><published>2009-06-03T06:12:00.010-04:00</published><updated>2009-07-16T16:20:57.692-04:00</updated><title type='text'>Dell mini 10v</title><content type='html'>&lt;span style=&quot;font-size:130%;&quot;&gt;Coolness&lt;/span&gt;&lt;br /&gt;1) With a 6 cells battery, this thing last a full day!&lt;br /&gt;2) Jaunty supports hibernation, faster boot and *way* faster wifi connection. Hardy was way too slow to connect back to the wifi network.&lt;br /&gt;3) If you take a colored top, you get the webcam for free. Mostly useless on a Atom processor anyway. :)&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-size:130%;&quot;&gt;Issues&lt;/span&gt;&lt;br /&gt;1) It took me a day to figure out how to page up/down key; kind of necessary when programming. Hint: FN key.&lt;br /&gt;2) No video acceleration for the 945GME / GMA 950 until Karmic Koala 9.10. This video card is too unstable with UXA to be usable. That&#39;s quite disapointing.&lt;br /&gt;3) The touchpad default configuration isn&#39;t great, I highly recommend a Logitech Nano VX.&lt;br /&gt;4) With the 6 cells battery, the laptop is not level, making it hard to look at the monitor while the laptop is on a table and you are straight up. This is due to the fact that the monitor doesn&#39;t bend backward enough.&lt;br /&gt;5) The dell ubuntu comes with Fluendo codecs and a custom shell launcher. My wife liked the launcher but the one in NBR is fine enough for her. TODO The codecs can be imported back into the new install if you install both OS side by side.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-size:130%;&quot;&gt;Survival kit&lt;/span&gt;&lt;br /&gt;1) Install Ubuntu Jaunty 9.04 netbook remix (NBR). This netbook has a SDHC card reader so you can put it on a memory card from the stock ubuntu install.&lt;br /&gt;2) Fix the palm check otherwise the mouse is constantly moving while typing on the keyboard.&lt;br /&gt;Temporary fix:&lt;br /&gt;&lt;blockquote&gt;DEVICE=&quot;SynPS/2 Synaptics TouchPad&quot;&lt;br /&gt;xinput list-props &quot;$DEVICE&quot;&lt;br /&gt;xinput --set-int-prop &quot;$DEVICE&quot; &quot;Synaptics Palm Detection&quot; 8 1&lt;br /&gt;xinput --set-int-prop &quot;$DEVICE&quot; &quot;Synaptics Palm Dimensions&quot; 32 10 10&lt;br /&gt;&lt;/blockquote&gt;First modify the file is /usr/share/hal/fdi/policy/20thirdparty/11-x11-synaptics.fdi as explained in:&lt;div&gt;http://ubuntu-snippets.blogspot.com/2009/03/multi-touch-for-anyall-synaptics.html&lt;/div&gt;&lt;br /&gt;You can then install&lt;br /&gt;&lt;div&gt;sudo apt-get install gsynaptics&lt;/div&gt;but it doesn&#39;t let you modify every settings..&lt;br /&gt;&lt;br /&gt;&lt;div&gt;3) If you kept the stock dell ubuntu 8.04 on a separate partition, fix the grub menu timeout to 1 second&lt;/div&gt;&lt;div&gt;sudo nano /boot/grub/menu.lst&lt;/div&gt;&lt;div&gt;Set the &quot;timeout&quot; line to 1.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;4) Install Google Chrome!&lt;div&gt;http://dev.chromium.org/getting-involved/dev-channel&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Update&lt;/b&gt;&lt;/div&gt;&lt;div&gt;- Better just turn off the touchpad after all, it&#39;s way too bad.&lt;/div&gt;&lt;div&gt;- Go in the bios and fix the Function keys as multimedia keys.&lt;/div&gt;&lt;div&gt;- I installed 2 gigs of RAM in it with the &lt;a href=&quot;http://www.youtube.com/watch?v=mXOZDNVRkZo&quot;&gt;videos&lt;/a&gt; &lt;a href=&quot;http://www.youtube.com/watch?v=-DGxwGUdOsw&quot;&gt;on&lt;/a&gt; &lt;a href=&quot;http://www.youtube.com/watch?v=qYo1Vbk-_5I&quot;&gt;youtube&lt;/a&gt;. &lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://m-a-tech.blogspot.com/feeds/1927586070538070981/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7003844608523781358/1927586070538070981' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/1927586070538070981'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/1927586070538070981'/><link rel='alternate' type='text/html' href='http://m-a-tech.blogspot.com/2009/06/dell-mini-10v.html' title='Dell mini 10v'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10266008552441372345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7003844608523781358.post-858577675243260999</id><published>2009-04-10T22:29:00.000-04:00</published><updated>2009-04-10T21:34:17.582-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="windows"/><title type='text'>Section synchronization</title><content type='html'>&lt;div&gt;I was looking at a cleaver way to use interprocess communication and we (chromium) use shared memory with CreateFileMapping(). The main issue is synchronization. I was looking at using the section as an inherent synchronization tool but it fails miserably. I finally found the answer: « File mapping objects do not support the SYNCHRONIZE standard access right. »[1]&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That would have been useful, even if it would have been limited to 4kb granularity or even just a global section lock. Sad. Going back to mutex. :(&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;[1]&lt;/div&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/aa366559.aspx&quot;&gt;http://msdn.microsoft.com/en-us/library/aa366559.aspx&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://m-a-tech.blogspot.com/feeds/858577675243260999/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7003844608523781358/858577675243260999' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/858577675243260999'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/858577675243260999'/><link rel='alternate' type='text/html' href='http://m-a-tech.blogspot.com/2008/06/section-synchronization.html' title='Section synchronization'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10266008552441372345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7003844608523781358.post-6476608772167520342</id><published>2009-04-10T22:24:00.000-04:00</published><updated>2009-04-10T22:24:01.131-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="emf"/><category scheme="http://www.blogger.com/atom/ns#" term="rant"/><category scheme="http://www.blogger.com/atom/ns#" term="windows"/><title type='text'>EMF buffer idiocracy</title><content type='html'>&lt;div&gt;On Windows XP, when creating an HDC from an EMF buffer with CreateEnhMetaFile():&lt;/div&gt;&lt;ul&gt;&lt;li&gt;SetDCBrushColor() and  SetDCPenColor() calls are not recorded. Too bad for you.&lt;/li&gt;&lt;li&gt;When using GetStockObject(), DC_BRUSH and DC_PEN are useless and will return a white pen and a black pen respectively. Just don&#39;t use them.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Expect no-op from ExtTextOut(..., ETO_GLYPH_INDEX, ...) if GDI32!GdiInitializeLanguagePack hasn&#39;t been called.&lt;/li&gt;&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://m-a-tech.blogspot.com/feeds/6476608772167520342/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7003844608523781358/6476608772167520342' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/6476608772167520342'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/6476608772167520342'/><link rel='alternate' type='text/html' href='http://m-a-tech.blogspot.com/2009/04/emf-buffer-idiocracy.html' title='EMF buffer idiocracy'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10266008552441372345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7003844608523781358.post-1044901726018756507</id><published>2008-01-17T20:53:00.000-05:00</published><updated>2008-01-18T10:10:54.603-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="rant"/><title type='text'>Understanding vsprops files</title><content type='html'>I&#39;ve began using .vsprops files (along side .vcproj files) on VS2005 SP1. I discovered that you can do something that looks like that:&lt;br /&gt;&lt;blockquote&gt;&lt; ?xml version=&quot;1.0&quot; encoding=&quot;Windows-1252&quot;? &gt;&lt;br /&gt;&lt; VisualStudioPropertySheet&lt;br /&gt; projecttype=&quot;Visual C++&quot;&lt;br /&gt;version=&quot;8.00&quot;&lt;br /&gt;name=&quot;whatever&quot; inheritedpropertysheets=&quot;.\randomprefix_$(RANDOM_ENVIRONMENT_VARIABLE).vsprops&quot;&gt;&lt;br /&gt;&lt; /VisualStudioPropertySheet &gt;&lt;br /&gt;&lt;/blockquote&gt;This is cool, you can modify which vsprops file will be inherited by an externally defined environment variable, before starting Visual Studio. Ok fine, then try further:&lt;br /&gt;&lt;blockquote&gt;&lt; ?xml version=&quot;1.0&quot; encoding=&quot;Windows-1252&quot;? &gt;&lt;br /&gt;&lt; VisualStudioPropertySheet&lt;br /&gt; projecttype=&quot;Visual C++&quot;&lt;br /&gt; version=&quot;8.00&quot;&lt;br /&gt; name=&quot;whatever&quot; inheritedpropertysheets=&quot;$(SolutionDir)..\randomdir\random_file.vsprops&quot;&gt;&lt;br /&gt;&lt; /VisualStudioPropertySheet &gt;&lt;br /&gt;&lt;/blockquote&gt;Cool again! I can use locally defined variable in Visual Studio. Ok, then let&#39;s try to do something useful:&lt;br /&gt;&lt;blockquote&gt;&lt; ?xml version=&quot;1.0&quot; encoding=&quot;Windows-1252&quot;? &gt;&lt;br /&gt;&lt; VisualStudioPropertySheet&lt;br /&gt; projecttype=&quot;Visual C++&quot; &lt;br /&gt;version=&quot;8.00&quot; &lt;br /&gt;name=&quot;whatever&quot; inheritedpropertysheets=&quot;randomprefix_$(ConfigurationName).vsprops&quot;&gt;&lt;br /&gt;&lt; /VisualStudioPropertySheet &gt;&lt;/blockquote&gt;It fails. :( &lt;span style=&quot;font-style: italic;&quot;&gt;That &lt;/span&gt;would have been useful: include a vsprops file named after the current configuration name (debug or release or whatever). Here a counter example:&lt;br /&gt;&lt;blockquote&gt;&lt; ?xml version=&quot;1.0&quot; encoding=&quot;Windows-1252&quot;? &gt;&lt;br /&gt;&lt; VisualStudioPropertySheet&lt;br /&gt; projecttype=&quot;Visual C++&quot; &lt;br /&gt;version=&quot;8.00&quot; &lt;br /&gt;name=&quot;whatever&quot; outputdirectory=&quot;$(SolutionDir)$(ConfigurationName)&quot; &gt;&lt;br /&gt;&lt; /VisualStudioPropertySheet &gt;&lt;/blockquote&gt;Yes, that actually works. In fact, you can even set « CharacterSet=&quot;1&quot; » in the vsprops even if the VS vsprops editor doesn&#39;t allow you to set this (the same applies to WholeProgramOptimization). So it seems like $(ConfigurationName) and $(SolutionDir) aren&#39;t defined at the same time, which is normal. The way VS looks at the project file looks like this:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Initial parsing&lt;/li&gt;&lt;li&gt;For each Configuration in Configurations&lt;br /&gt;&lt;/li&gt;&lt;ol&gt;&lt;li&gt;Load the InheritedPropertySheets attribute&lt;br /&gt;&lt;/li&gt;&lt;ol&gt;&lt;li&gt;Open &lt;span style=&quot;font-weight: bold;&quot;&gt;recursively&lt;/span&gt; the property sheets&lt;/li&gt;&lt;/ol&gt;&lt;li&gt;Load the Name attribute in Configuration in the vcproj&lt;/li&gt;&lt;li&gt;Process property sheets&lt;/li&gt;&lt;li&gt;Process the rest of the &lt;configuration&gt; attributes&lt;/configuration&gt;&lt;/li&gt;&lt;li&gt;Load the rest&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/ol&gt;The thing is that you &lt;span style=&quot;font-style: italic;&quot;&gt;can&lt;/span&gt; use $(ConfigurationName) in the OutputDirectory attribute but not in the InheritedPropertySheet. Too bad, what a missed opportunity. I somewhat tried playing with UserMacro but without any success.&lt;br /&gt;&lt;br /&gt;Disclaimer: I didn&#39;t try with VS2008.&lt;br /&gt;Disclaimer: I know the blogger&#39;s editor sucks and that I couldn&#39;t write real XML. In fact, they know it too. I just wished they &lt;span style=&quot;font-style: italic;&quot;&gt;cared&lt;/span&gt;. We&#39;re just all eager to have it actually &lt;span style=&quot;font-style: italic;&quot;&gt;fixed&lt;/span&gt;.</content><link rel='replies' type='application/atom+xml' href='http://m-a-tech.blogspot.com/feeds/1044901726018756507/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/7003844608523781358/1044901726018756507' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/1044901726018756507'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7003844608523781358/posts/default/1044901726018756507'/><link rel='alternate' type='text/html' href='http://m-a-tech.blogspot.com/2008/01/understanding-vsprops-files.html' title='Understanding vsprops files'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10266008552441372345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry></feed>