diff options
180 files changed, 0 insertions, 10496 deletions
diff --git a/build/.nojekyll b/build/.nojekyll deleted file mode 100644 index e69de29b..00000000 --- a/build/.nojekyll +++ /dev/null diff --git a/build/.well-known/keybase.txt b/build/.well-known/keybase.txt deleted file mode 100644 index 627c9a5d..00000000 --- a/build/.well-known/keybase.txt +++ /dev/null @@ -1,76 +0,0 @@ -================================================================== -https://keybase.io/zmwangx --------------------------------------------------------------------- - -I hereby claim: - - * I am an admin of https://zmwangx.github.io - * I am zmwangx (https://keybase.io/zmwangx) on keybase. - * I have a public key with fingerprint 9FDC DBAD 5608 97B4 5051 5B7A BBD3 1D4D 1100 44B8 - -To do so, I am signing this object: - -{ - "body": { - "client": { - "name": "keybase.io node.js client", - "version": "0.8.11" - }, - "key": { - "eldest_kid": "010143ade5970b5e797f0bb5235b11387f5892a198398f5ad96f06617070ab6f9a7d0a", - "fingerprint": "9fdcdbad560897b450515b7abbd31d4d110044b8", - "host": "keybase.io", - "key_id": "bbd31d4d110044b8", - "kid": "010143ade5970b5e797f0bb5235b11387f5892a198398f5ad96f06617070ab6f9a7d0a", - "uid": "ad8a2e7998a2a0c8847f8b3acf8cc200", - "username": "zmwangx" - }, - "service": { - "hostname": "zmwangx.github.io", - "protocol": "https:" - }, - "type": "web_service_binding", - "version": 1 - }, - "ctime": 1437606054, - "expire_in": 157680000, - "prev": "fe50050904a63ffb8cf04ee2dd8d80d378bd622777ea85d40f34cc6bbfa22f18", - "seqno": 11, - "tag": "signature" -} - -which yields the signature: - ------BEGIN PGP MESSAGE----- - -owGtkntMHEUcx4+DowW0PNTUkiMea1sqodfZu30SjbwMxti0l0BJxXLdx+zdUrg9 -bo/HQXlVe2gTqNcGLTEVYrTGVCnSQKRXqIW0tAhiSrEIFSwiTRMoSBspQcRdxJgm -/un8M5OZz+8739935r0nAzWhAf6hmN2RmrSvA769x2oyWwxnyhBW4j1IYhnC5YnQ -4VZXDiYfIonIIehhGRkaRcngkHhozJUN60wCUgRdsig5FAoYKSOKIuUJKq9Wwzwe -ym7rIZFXT1GAYmaGhzhNAhaHJE0KgGVxkxlnUdRMkQJO0SYGpSkzTQk4w9OEAAgC -JQEJGJYQaIbkAaNcKIgOG3Q5XaJqEaEFnuNZhscJQNEki+EAR3GWZFiWN6M8xqMo -ABjGUkqhXZLdjzWDrDm1rtn7D/5/9l24JsfwFGNSRGhlYgBHURgpUKyZ4QSK40wA -qKAMXevBl+YXMw5biZqpslkkclDNVW3kccBoE932QvbvnpwuyS1xUp5ybHe7nXKi -Wu72OFW+GLLWdSUrKzp4JUsk4fS/j4gqKOcWVW2la5IABMCxBASWOEUXtIoqgZME -BZShXgSLFE0B4gDggAYYQ5gFgaU4AWAQmnie4inAm0mK5QmTiSRJyFA4jwHBjHEc -wbICYzIJqBq1DAsckqKNKkYZm6IpizYH4y50QaT8Xa0+SBMQqgnWadVvqgkNifjn -76Yw4ctBz3sfrkrJhW/80p7hf/n66+k5N6/mTIdu7zi2PWNf61cPxr/AStPvekYv -lj3jbxmJOzjQUlo3uUEYenYEZplGGyaq/FvCkLdyNpLZuaMhjenH75xOWdB9GJhY -1+bVWG71BDoWr+yQNna/n7G/YLhnsF43OHahlxwbTo2OxaQPslenrnSdvXVqG4sF -HHZ4mw3LTn3lmV3ej3stjvGmutCR8OYqzRSwHIgcAm2zlt7lvXId/PLz5BN/hrUP -2TPb/khyamO/i36xvyGjYndKGvdmVP5tW4s46p0Nq9A96jhZuem+cdqnHT9g3vpO -MPaRgXlBFzW2Oaw/NtNvK5i/3hK1Ifc1eVtXfsxJs097u+vy77+dTWmPW6pveNS9 -aNtvWdnTlGdayt/0Wfl41o/RNeWt2q3dROdw2CXghg92RExfTU6Re8LLg/tuEjVx -YHWgKt6Qdbf2KX/UT8WNT8+VWBr1byd4vUmXzy2tzBTFdNXcOBEy/9LR5opTqaUr -kxpfRavuYFyqb69n/tfKbzK+76+qHwjqe6KmrkO/YKl9LrV6D0/MWX34z0J2X1Bw -/92IvjvJqYWfxB/drE9r0mli4wMmqiftFz/d1d2ZEzkzc//88sxC52DFzuofrr0y -Vwt8+sMXYmd3xh+ZOtJA981lem5Ik5ZX+8eFY0nnFy9d22c/95C/t2XiLw== -=VI5f ------END PGP MESSAGE----- - -And finally, I am proving ownership of this host by posting or -appending to this document. - -View my publicly-auditable identity here: https://keybase.io/zmwangx - -================================================================== diff --git a/build/CNAME b/build/CNAME deleted file mode 100644 index 1b8a9709..00000000 --- a/build/CNAME +++ /dev/null @@ -1 +0,0 @@ -archive.zhimingwang.org
\ No newline at end of file diff --git a/build/atom.xml b/build/atom.xml deleted file mode 100644 index 48758ee8..00000000 --- a/build/atom.xml +++ /dev/null @@ -1,567 +0,0 @@ -<feed xmlns="http://www.w3.org/2005/Atom"><title>dl? cmplnts?</title><subtitle>Zhiming Wang's personal blog</subtitle><link href="http://archive.zhimingwang.org/atom.xml" rel="self" type="application/atom+xml"/><link href="http://archive.zhimingwang.org/" rel="alternate" type="text/html"/><updated>2017-04-28T00:29:42+02:00</updated><id>http://archive.zhimingwang.org/</id><author><name>Zhiming Wang</name><uri>http://archive.zhimingwang.org/</uri><email>zmwangx@gmail.com</email></author><icon>http://archive.zhimingwang.org/img/icon-400.png</icon><generator uri="https://github.com/zmwangx/zmwangx.github.io">pyblog</generator><entry><title type="html">pyenv: compiling Python with SQLite in nonstandard location</title><link href="http://archive.zhimingwang.org/blog/2016-10-26-pyenv-compiling-python-with-sqlite-in-nonstandard-location.html"/><updated>2016-10-26T12:16:22-04:00</updated><id>http://archive.zhimingwang.org/blog/2016-10-26-pyenv-compiling-python-with-sqlite-in-nonstandard-location.html</id><author><name>Zhiming Wang</name><uri>http://archive.zhimingwang.org/</uri><email>zmwangx@gmail.com</email></author><content type="html"><![CDATA[ - -<p>This is a quick post sharing a workaround that I needed just now.</p> -<p>I was trying to compile Pythons with pyenv on a RHEL 6.8 cluster. Unfortunately <code>sqlite-devel</code> is not installed and I doubt I can convince my sysadmin to install a package for me. The lack of SQLite headers resulted in Pythons without <code>_sqlite3</code> which is essential for me. Hinting at SQLite headers from Linuxbrew with <code>CPATH</code> did not help either.</p> -<p>Digging into CPython source code, turns out that CPython only looks into <a href="https://github.com/python/cpython/blob/59fa72e34da71fb24f52251c1cc88ed3c3b14797/setup.py#L1132-L1138">a fixed set of paths</a>:</p> -<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python">sqlite_inc_paths <span class="op">=</span> [ <span class="st">'/usr/include'</span>, - <span class="st">'/usr/include/sqlite'</span>, - <span class="st">'/usr/include/sqlite3'</span>, - <span class="st">'/usr/local/include'</span>, - <span class="st">'/usr/local/include/sqlite'</span>, - <span class="st">'/usr/local/include/sqlite3'</span>, - ] -<span class="cf">if</span> cross_compiling: - sqlite_inc_paths <span class="op">=</span> []</code></pre></div> -<p>Well that's unfortunate. Luckily pyenv makes it really easy to patch Python source code; take a look at <a href="https://github.com/yyuu/pyenv/tree/master/plugins/python-build/share/python-build/patches"><code>plugins/python-build/share/python-build/patches</code></a> and you'll get the idea. Therefore, in the case of Linuxbrew'ed pyenv and SQLite, say we want to build Python 3.5.2 with SQLite support, we simply put the following patch at <code>~/.linuxbrew/opt/pyenv/plugins/python-build/share/python-build/patches/3.5.2/Python-3.5.2/linuxbrew-sqlite3.patch</code>:</p> -<div class="sourceCode"><pre class="sourceCode diff"><code class="sourceCode diff"><span class="kw">diff --git a/setup.py b/setup.py</span> -index 174ce72..774fd65 100644 -<span class="dt">--- a/setup.py</span> -+++ b/setup.py -@@ -1108,6 +1108,7 @@ class PyBuildExt(build_ext): - '/usr/local/include', - '/usr/local/include/sqlite', - '/usr/local/include/sqlite3', -+ os.path.expanduser('~/.linuxbrew/opt/sqlite/include/'), - ] - if cross_compiling: - sqlite_inc_paths = []</code></pre></div> -<p>That's it. Now</p> -<pre><code>$ pyenv install 3.5.2</code></pre> -<p>and enjoy.</p> -]]></content></entry><entry><title type="html">This blog is now behind CloudFlare</title><link href="http://archive.zhimingwang.org/blog/2016-09-01-this-blog-is-now-behind-cloudflare.html"/><updated>2016-09-01T20:11:00+08:00</updated><id>http://archive.zhimingwang.org/blog/2016-09-01-this-blog-is-now-behind-cloudflare.html</id><author><name>Zhiming Wang</name><uri>http://archive.zhimingwang.org/</uri><email>zmwangx@gmail.com</email></author><content type="html"><![CDATA[ - -<p>Back in July I registered the domain <a href="http://zhimingwang.org">zhimingwang.org</a> and pointed this GitHub Pages-powered blog at it. Since then I have lost the HTTPS badge due to GitHub Pages not supporting HTTPS on custom domains (see <a href="https://github.com/isaacs/github/issues/156">isaacs/github#156</a>).</p> -<p>There have been a lot of discussions on isaacs/github#156 (and stupid <a href="http://archive.zhimingwang.org/blog/2016-01-18-me-too-comments-on-github.html">+1's</a> too). Among the proposed solutions is putting the website behind CloudFlare. I carefully investigated <a href="https://blog.cloudflare.com/secure-and-fast-github-pages-with-cloudflare/">this option</a> and read almost all the arguments against it. I fully understand CloudFlare's SSL models (summarized in the image below), and I do realize most if not all of the limitations of CloudFlare, including CloudFlare being a huge MITM (which is inevitable for a CDN anyway), as well as most if not all of its annoyances, including CAPTCHAs which I myself would occasionally run into when I'm browsing with PIA VPN, and JavaScript-based browser checks.</p> -<div class="figure"> -<a href="http://archive.zhimingwang.org/img/20160901-cloudflare-ssl-modes.png" target="_blank"><img alt="CloudFlare's SSL modes. I use the Full SSL mode so that both ends of the connection are encrypted. Again, I know CloudFlare is a big MITM and could be a high profile target. Credit: CloudFlare." src="http://archive.zhimingwang.org/img/20160901-cloudflare-ssl-modes.png" width="500"/></a> -<p class="caption">CloudFlare's SSL modes. I use the Full SSL mode so that both ends of the connection are encrypted. Again, I know CloudFlare is a big MITM and could be a high profile target. Credit: <a href="https://blog.cloudflare.com/secure-and-fast-github-pages-with-cloudflare/">CloudFlare</a>.</p> -</div> -<p>After careful evaluation, I decided that CloudFlare's SSL model is good enough for me. After all, this is just a damn blog, with nothing sensitive. TLS is still nice because it guards against prying eyes and unethical ad-injecting ISPs or Wi-Fi hotspots, but other than that, it isn't necessary.</p> -<p>End result: this blog is now behind CloudFlare. Readers should now see that green HTTPS badge again (note that I'm enforcing HTTPS — without HSTS though). As for CAPTCHAs, I have adjusted the firewall settings on CloudFlare's dashboard — "Security Level" to "Essentially Off" and "Challenge Passage" to 1 year, so hopefully it won't be too annoying.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-09-01-this-blog-is-now-behind-cloudflare.html#fn1" id="fnref1"><sup>1</sup></a></p> -<p><strong>09/01/2016 Update.</strong> I just realized that <a href="https://support.cloudflare.com/hc/en-us/articles/203306930-Does-CloudFlare-block-Tor-">CloudFlare supports whitelisting Tor traffic</a>. Did that.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>I don't use Tor, and don't intend to raise Big Brother's suspicion by using it, so I have no idea of the actual Tor experience.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-09-01-this-blog-is-now-behind-cloudflare.html#fnref1">↩︎</a></p></li> -</ol> -</div> -]]></content></entry><entry><title type="html">It's 2016, and Microsoft is the only legit player who spams me without unsubscribe links</title><link href="http://archive.zhimingwang.org/blog/2016-06-24-its-2016-and-microsoft-is-the-only-legit-player-who-spams-me-without-unsubscribe-links.html"/><updated>2016-06-24T05:40:01+08:00</updated><id>http://archive.zhimingwang.org/blog/2016-06-24-its-2016-and-microsoft-is-the-only-legit-player-who-spams-me-without-unsubscribe-links.html</id><author><name>Zhiming Wang</name><uri>http://archive.zhimingwang.org/</uri><email>zmwangx@gmail.com</email></author><content type="html"><![CDATA[ - -<p>I'm so tired of Microsoft spam. Microsoft is known for being intrusive accross the board, and their newsletters are no different: I literally can't name one legit company in this day and age who doesn't put unsubscribe links in newsletters.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-06-24-its-2016-and-microsoft-is-the-only-legit-player-who-spams-me-without-unsubscribe-links.html#fn1" id="fnref1"><sup>1</sup></a> I get "Azure pricing and services updates" newsletters all the time, as well as "exciting news" from Windows Insider Program (which doesn't excite me at all) every once in a short while.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-06-24-its-2016-and-microsoft-is-the-only-legit-player-who-spams-me-without-unsubscribe-links.html#fn2" id="fnref2"><sup>2</sup></a> I still occasionally receive random Chinese language promotions of Windows, presumably because I used a Windows Phone as my secondary phone for three months back home in the summer of 2013 (which was a horrible experience). Why Microsoft hasn't been regulated for spam yet, I do not know.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>To be fair, Amazon used to force promotional email on student members, but (if memory serves) I haven't seen one in ages.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-06-24-its-2016-and-microsoft-is-the-only-legit-player-who-spams-me-without-unsubscribe-links.html#fnref1">↩︎</a></p></li> -<li id="fn2"><p>"If you wish to stop receiving Windows Insider Program emails, you will need to leave the program." I guess that's the price of downloading a couple of Windows 10 insider builds.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-06-24-its-2016-and-microsoft-is-the-only-legit-player-who-spams-me-without-unsubscribe-links.html#fnref2">↩︎</a></p></li> -</ol> -</div> -]]></content></entry><entry><title type="html">Chrome is screwing with our extensions... Again</title><link href="http://archive.zhimingwang.org/blog/2016-05-07-chrome-is-screwing-with-our-extensions-again.html"/><updated>2016-05-07T18:49:26-07:00</updated><id>http://archive.zhimingwang.org/blog/2016-05-07-chrome-is-screwing-with-our-extensions-again.html</id><author><name>Zhiming Wang</name><uri>http://archive.zhimingwang.org/</uri><email>zmwangx@gmail.com</email></author><content type="html"><![CDATA[ - -<p>Chrome is growing more and more hostile by the day. See <a href="http://archive.zhimingwang.org/blog/2016-03-06-google-chrome-keeps-getting-uglier.html">Google Chrome keeps getting uglier</a> for an earlier take. What I didn't report in the earlier post is that not only can't you show/hide extension buttons as easily as before, you can't even control which buttons appear in the toolbar anymore — they come and go as they wish.</p> -<p>As if screwing the app icon, extension buttons and the overall design is not enough, now they have upped their game again. I'm running Chrome 50.0.2661.94 from April 28, and I just rebooted my machine only to be greeted with a fleeting "unsupported extensions" (or something like that) message as I launched Chrome. I digged into the extensions page, and guess what, all sideloaded extensions (except unpacked ones) have been disabled.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-05-07-chrome-is-screwing-with-our-extensions-again.html#fn1" id="fnref1"><sup>1</sup></a> This in itself may not be too surprising (Google took away sideloaded extensions from non-developers last year), except that <strong>the "enable" button, which used to work at least in developer mode, doesn't function anymore.</strong> The message is very stupid:</p> -<blockquote> -<p>This extension is not listed in the Chrome Web Store and <strong>may</strong> have been added without your knowledge.</p> -</blockquote> -<p>Bold by me. Okay, so what if they have been added <strong>with my knowledge</strong>? No way to enable legit extensions (some written by none other than myself) just because of a "may"? Here's the <a href="https://support.google.com/chrome/answer/2811969">only migration path</a> they offer, by the way:</p> -<blockquote> -<p>If you need to use a disabled extension, you can contact the extension's developer and ask them to upload their extension to the Chrome Web Store.</p> -</blockquote> -<p>Seriously? Do they honestly think Chrome Web Store serves everyone's needs? First, they have every right to refuse or take down any extension in their store. This is dangerous. What if one day they conclude that Adblock Plus is hurting their ad revenue too much and decide to take it down? Secondly, people may not want to make every extension publicly available. For instance, I have some personal extensions that I have developed on my dev machine, packaged into .crx, and installed on other machines. Some of these are publicly available (on GitHub), and others are not. It's not hard to conclude that other people may have private extensions too, and there may be extensions that are only available in some private circles. Now, people have to load unpacked extensions, which is much easier to screw up for regular folks, or they're out of luck.</p> -<p>To add insult to injury, every time I launch Chrome now, I'm greeted by this "Disable Developer Mode Extensions" message:</p> -<blockquote> -<p>Extensions running in developer mode can harm your computer. If you're not a developer, you should disable these extensions running in developer mode to stay safe.</p> -</blockquote> -<p>As if there're not enough malicious extensions in the Chrome Web Store, let alone crap. May I tell Chrome that I <em>am</em> a developer and ask it to shut up? Apparently no.</p> -<p>With the current trend in Chrome, I might want to switch to Opera again.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-05-07-chrome-is-screwing-with-our-extensions-again.html#fn2" id="fnref2"><sup>2</sup></a> The only thing preventing me from doing so right now is their new <a href="https://i.imgur.com/F8Tc67m.png">horrendous-looking fat icon</a>. However, Chrome has also destroyed their icon and I need to <a href="https://github.com/zmwangx/fileicon">replace it</a> after every update anyway, so I might as well do the same thing for Opera. We'll see.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>I'm not sure why they weren't disabled upon first launch after the update, but given the randomness of extension buttons in my toolbar with hardly any action on my part, I won't be surprised if I were told that they had messed up the extension system completely.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-05-07-chrome-is-screwing-with-our-extensions-again.html#fnref1">↩︎</a></p></li> -<li id="fn2"><p>Modern day Safari is also pretty nice, and the team is showing great attitude lately, with Safari Technology Preview and tweets like <a href="https://twitter.com/webkit/status/725725657548738561">this one</a>, for instance. However, the lack of extensions is a big road block, and the fact that the used-to-be-free Safari Developer Program has been incorporated into the $99/yr Apple Developer Program certainly doesn't help. (I used to be a member. Now I've been kicked out.)</p> -<p>Note that Safari is more locked down in a sense compared to OS X and iOS. On OS X you can apparently run unsigned software; on iOS 9 and later you can create personal provisioning profiles with just an Apple ID. Neither is true for Safari extensions, which still require a signing key from developer program membership. I wonder if Apple will introduce free keys for personal use on Safari, too.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-05-07-chrome-is-screwing-with-our-extensions-again.html#fnref2">↩︎</a></p></li> -</ol> -</div> -]]></content></entry><entry><title type="html">Emacs's got a redesigned website!</title><link href="http://archive.zhimingwang.org/blog/2016-04-10-emacss-got-a-redesigned-website.html"/><updated>2016-04-10T03:04:19-07:00</updated><id>http://archive.zhimingwang.org/blog/2016-04-10-emacss-got-a-redesigned-website.html</id><author><name>Zhiming Wang</name><uri>http://archive.zhimingwang.org/</uri><email>zmwangx@gmail.com</email></author><content type="html"><![CDATA[ - -<p>I've been very busy lately, so I haven't posted anything for a month. As a result, I have many topic notes sitting in Notes.app — including the kik-left-pad-npm drama, the Text Expander outcry, and such — waiting to be organized and written up (I'll probably never write them up in the end, since these days it's very weird to write an opinion piece about an event whose attention span has already lapsed).</p> -<p>Anyway, this will be a short post about Emacs's <a href="https://gnu.org/software/emacs/">redesigned website</a>. See screenshot at the end. Apparently this was <a href="https://twitter.com/NicolasPetton/status/714854524108800000">last week's news</a>, but there's little interest in Emacs in general, so the news only reached me two days ago, sort of by chance.</p> -<p>According my impression, Emacs has been the underdog for quite some time. First, when you compare to vi/Vim, hard stats shed light on popularity: there are way more VimL repos than Elisp ones on GitHub.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-04-10-emacss-got-a-redesigned-website.html#fn1" id="fnref1"><sup>1</sup></a> Also, there are more exciting (or at least exciting-sounding or excitement-inducing) things happening in the Vim realm, e.g. Neovim, but not so much in the Emacs kingdom (excuse me if I missed something big). I'm actually very curious how Vim sold itself to so many people. I, for one, can't tolerate the Esc key at all (yes, I know basic editing in Vim, and I know the various workarounds to Esc, some of them reasonable and some not). I can't understand how people could laugh at Escape Meta Alt Control Shift — oh, I never used Esc in Emacs once, by the way — when the single most awkward Esc key serves a fundamental purpose by default in their own beloved editor. The Esc key is of course not my only gripe with Vim, nor the biggest; I'll however stop here to avoid turing this post into a complaint about Vim. Apart from Vim, Emacs is also being sidelined by more modern GUI-based text editors like Atom,<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-04-10-emacss-got-a-redesigned-website.html#fn2" id="fnref2"><sup>2</sup></a> or various IDEs. Atom <a href="http://blog.atom.io/2016/03/28/atom-reaches-1m-users.html">recently</a> reached one million monthly active users. I actually like certain parts of Atom a lot, e.g. the project navigation sidebar,<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-04-10-emacss-got-a-redesigned-website.html#fn3" id="fnref3"><sup>3</sup></a> but I simply can't give up my good ol' tty.</p> -<p>Personal preferences aside, I think Emacs does need a bit more publicity to draw a few more users. Whether redesigning the website will help at all I don't know; maybe the effect will be statistically indistinguishable from zero, but the bottom line is that people like pretty websites, so why not. The redesigned homepage is a bit more graphics-heavy, but it currently weighs a total of 521.33KB — within the tolerable range.</p> -<p>The most interesting thing I found on the redesigned homepage is the link to <a href="http://emacsrocks.com">emacsrocks.com</a>. I aimlessly clicked on the last episode — <a href="http://emacsrocks.com/e15.html">episode 15</a> — just to see what it was like, and ended up astonished. The episode is about <a href="https://github.com/pashky/restclient.el"><code>restclient.el</code></a>, which turned out to be wicked cool. In the real world it's probably a little bit too geeky to my liking, and I use the more mundane (and more powerful) <a href="https://luckymarmot.com/paw">Paw</a> as my REST client, but I can't stop admiring the beauty of <code>restclient-mode</code>. I'll definitely find time to watch all episodes of Emacs Rocks, and you probably should, too.</p> -<div class="figure"> -<a href="http://archive.zhimingwang.org/img/20160409-emacs-website-screenshot-half-size.png" target="_blank"><img alt="A scaled down screenshot of the redesigned gnu.org/software/emacs. Full screenshot on my 2880x1800 MBP is here. Actually I lied a bit — the screenshots were taken with pageres, so I could have specified any resolution." src="http://archive.zhimingwang.org/img/20160409-emacs-website-screenshot-half-size.png" width="720"/></a> -<p class="caption">A scaled down screenshot of the redesigned <a href="https://gnu.org/software/emacs/">gnu.org/software/emacs</a>. Full screenshot on my 2880x1800 MBP is <a href="http://archive.zhimingwang.org/img/20160409-emacs-website-screenshot.png">here</a>. Actually I lied a bit — the screenshots were taken with <a href="https://github.com/sindresorhus/pageres"><code>pageres</code></a>, so I could have specified any resolution.</p> -</div> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>According to <a href="http://githut.info/">GitHut</a>, in 2014 Q4, there were 22,450 VimL and 9,978 Elisp repositories on GitHub, respectively. And according to a real time search I did just now, the <a href="https://github.com/search?q=language%3AVimL">VimL number</a> has risen to 82,519 and the <a href="https://github.com/search?q=language%3AElisp">Elisp number</a> to 30,320. The ratio has risen from 2.25:1 to 2.72:1. To add insult to injury, on GitHub's <a href="https://github.com/search/advanced">advanced search page</a>, GitHub lists VimL in the "Popular" language section and Elisp in "Everything else". Hurt feelings anyone?<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-04-10-emacss-got-a-redesigned-website.html#fnref1">↩︎</a></p></li> -<li id="fn2"><p>Of course Emacs can operate in standalone GUI mode (or more precisely, window system mode), and more can be done in GUI mode (both in terms of customizability and functinality). However, in my early days with Emacs I found the GUI look like crap — the default always does, even to this day. I can never bring myself to use anything crappy-looking, unless I've got no choice, so I went with the TUI. Later I learned how to make the GUI habitable (still not as nice as the uniformity I find in tty, though), but by that time I'm already totally in love with tty mode and probably will never switch.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-04-10-emacss-got-a-redesigned-website.html#fnref2">↩︎</a></p></li> -<li id="fn3"><p>In Emacs I have ido, fiplr and sr-speedbar to help with navigation, but this is one area where a graphical sidebar really shines.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-04-10-emacss-got-a-redesigned-website.html#fnref3">↩︎</a></p></li> -</ol> -</div> -]]></content></entry><entry><title type="html">Google Chrome keeps getting uglier</title><link href="http://archive.zhimingwang.org/blog/2016-03-06-google-chrome-keeps-getting-uglier.html"/><updated>2016-03-06T14:59:45-08:00</updated><id>http://archive.zhimingwang.org/blog/2016-03-06-google-chrome-keeps-getting-uglier.html</id><author><name>Zhiming Wang</name><uri>http://archive.zhimingwang.org/</uri><email>zmwangx@gmail.com</email></author><content type="html"><![CDATA[ - -<p>I hate to say this, but the Google Chrome team keeps making poor design decisions to make it more and more ugly. I still remember the sad day when the kind of cool wrench button gave way to the utterly boring hamburger one. I also remember the sad day when the omnibox dropdown <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=276746">pointlessly went full width</a> (after more than two years, I still fail to see how it makes any sense, although my eyes have long grown used to it).<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-03-06-google-chrome-keeps-getting-uglier.html#fn1" id="fnref1"><sup>1</sup></a> And I'm sure there are other stupid changes that I can't name at the moment.</p> -<p>Unfortunately, they just won't stop. <a href="http://googlechromereleases.blogspot.com/2016/03/stable-channel-update.html">Four days ago</a> stable 49.0.2623.75 came out with a flurry of horrible visual changes.</p> -<ol style="list-style-type: decimal"> -<li><p>The icon. For whatever reason I have the impression that I might have seen this a while ago, but let's just pretend it's brand new. The new app icon is the most outrageously flat icon I've even seen. Compare it to that of 48.0.2564.103<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-03-06-google-chrome-keeps-getting-uglier.html#fn2" id="fnref2"><sup>2</sup></a>:</p> -<div class="figure"> -<a href="http://archive.zhimingwang.org/img/20160306-chrome-mac-48.0.2564.103-49.0.2623.75-icons-side-by-side.png" target="_blank"><img alt="Old and new app icons side by side. To the left, the 48.0.2564.103 icon; to the right, the 49.0.2623.75 icon." src="http://archive.zhimingwang.org/img/20160306-chrome-mac-48.0.2564.103-49.0.2623.75-icons-side-by-side.png" width="512"/></a> -<p class="caption">Old and new app icons side by side. To the left, <a href="http://archive.zhimingwang.org/img/20160306-chrome-mac-48.0.2564.103-icon.png">the 48.0.2564.103 icon</a>; to the right, <a href="http://archive.zhimingwang.org/img/20160306-chrome-mac-49.0.2623.75-icon.png">the 49.0.2623.75 icon</a>.</p> -</div> -<p>And let's see them in action:</p> -<div class="figure"> -<a href="http://archive.zhimingwang.org/img/20160306-chrome-mac-48.0.2564.103-49.0.2623.75-icons-side-by-side-in-dock.png" target="_blank"><img alt="Both icons in the dock, old one the left and new one on the right." src="http://archive.zhimingwang.org/img/20160306-chrome-mac-48.0.2564.103-49.0.2623.75-icons-side-by-side-in-dock.png" width="560"/></a> -<p class="caption">Both icons in the dock, old one the left and new one on the right.</p> -</div> -<p>Apart from flatness (lack of any gloss found in almost all Apple icons, however flattened they are), see how the new icon is notably larger than the old one, and any other circular icons for that matter. Apparently, consistency and guidelines mean nothing to them.</p> -<p>I wonder why they made this change. Maybe for material design? I certainly don't want to see my Mac infested by material design, thank you. And maybe to keep the icon in line with their new Google branding? Indeed, just like <a href="https://web.archive.org/web/20160306221914/https://g-design.storage.googleapis.com/production/v5/assets/g-logo.png">the new Google logo</a> which did away with serifs, this one has no depth at all and is very childish.</p> -<p>It's a shame I can't just throw this icon out of my dock. Looks like in addition to iTunes now I have yet another icon to replace following each update, except this one updates much more often, and almost silently.</p></li> -<li><p>Downloads. I almost thought I was hacked when I opened the Downloads tab and saw</p> -<div class="figure"> -<a href="http://archive.zhimingwang.org/img/20160306-chrome-mac-49.0.2623.75-downloads.png" target="_blank"><img alt="Downloads in 49.0.2623.75." src="http://archive.zhimingwang.org/img/20160306-chrome-mac-49.0.2623.75-downloads.png" width="848"/></a> -<p class="caption">Downloads in 49.0.2623.75.</p> -</div> -<p>instead of a nice and clean</p> -<div class="figure"> -<a href="http://archive.zhimingwang.org/img/20160306-chrome-mac-48.0.2564.103-downloads.png" target="_blank"><img alt="Downloads in 48.0.2564.103." src="http://archive.zhimingwang.org/img/20160306-chrome-mac-48.0.2564.103-downloads.png" width="728"/></a> -<p class="caption">Downloads in 48.0.2564.103.</p> -</div> -<p>Materail design infestation, apparently. Funny how they managed to convey less info in a LOT more space, and look horrible at the same time. At least they can choose a pleasant color palette if they want to use color (which is totally unnecessary as seen from the old design)? No, they can't.</p></li> -<li><p>Incognito mode. There's a reason why books are printed on light-colored paper, and there's a reason why the web is predominantly light-backgrounded, including user agent default style sheets. The old incognito follows the light background rule, plus a non-intrusive notice in the middle and a reasonably shaded tab bar to indicate incognito status:</p> -<div class="figure"> -<a href="http://archive.zhimingwang.org/img/20160306-chrome-mac-48.0.2564.103-incognito.png" target="_blank"><img alt="Incognito window in 48.0.2564.103." src="http://archive.zhimingwang.org/img/20160306-chrome-mac-48.0.2564.103-incognito.png" width="893"/></a> -<p class="caption">Incognito window in 48.0.2564.103.</p> -</div> -<p>But not anymore. Since those of you using Incognito mode must be conducting shady business, why not highlight that with a black background:</p> -<div class="figure"> -<a href="http://archive.zhimingwang.org/img/20160306-chrome-mac-49.0.2623.75-incognito.png" target="_blank"><img alt="Incognito window in 49.0.2623.75. Even more shocking if you maximize your browser windows." src="http://archive.zhimingwang.org/img/20160306-chrome-mac-49.0.2623.75-incognito.png" width="625"/></a> -<p class="caption">Incognito window in 49.0.2623.75. Even more shocking if you maximize your browser windows.</p> -</div> -<p>Oh. My. God. Now I hesitate whenever I want to press ⇧⌘N; it's just too great a cultural shock for me to handle.</p></li> -</ol> -<p>Those are just three changes I've discovered so far. Hopefully there are no more lurking surprises.</p> -<p>Conclusion? Sigh.</p> -<hr/> -<p><strong>03/09/2016 update</strong>. They also broke showing/hiding extension buttons (from toolbar) recently, probably in the same update. We used to be able to reshow a hidden button from <code>chrome://extensions</code>; that's no longer possible. Now we need to click on the hamburger (great), right click on one of the hidden buttons — which temporarily promotes the button to the toolbar and display the context menu, and while the context menu is still on, click on "Keep in Toolbar". So intuitive, your average computer users are definitely going to figure that out by themselves. Very nice.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>Dev left a <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=276746#c28">comment</a> when marking that issue as wont fix:</p> -<blockquote> -<p>... The current look is a precursor to a family of related work to make the Omnibox better, so expect to see more investment in this space to come. ...</p> -</blockquote> -<p>A family of related work? After 2.5 years the omnibox looks almost exactly the same as the screenshot in the issue. More to come my ass. Maybe I should be grateful, at least it didn't get worse.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-03-06-google-chrome-keeps-getting-uglier.html#fnref1">↩︎</a></p></li> -<li id="fn2"><p>I realized the last stable was 48.0.2564.109 instead of 48.0.2564.103 only after taking the screenshots. Doesn't matter anyway.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-03-06-google-chrome-keeps-getting-uglier.html#fnref2">↩︎</a></p></li> -</ol> -</div> -]]></content></entry><entry><title type="html">Dropbox, Noteworthy, and damned skeuomorphism</title><link href="http://archive.zhimingwang.org/blog/2016-01-26-dropbox-noteworthy-and-damned-skeuomorphism.html"/><updated>2016-01-26T12:18:36-08:00</updated><id>http://archive.zhimingwang.org/blog/2016-01-26-dropbox-noteworthy-and-damned-skeuomorphism.html</id><author><name>Zhiming Wang</name><uri>http://archive.zhimingwang.org/</uri><email>zmwangx@gmail.com</email></author><content type="html"><![CDATA[ - -<p>I just opened a note in a PDF within Dropbox's iOS app (never done that before), and instead of readable text what I saw was basically spaghetti:</p> -<div class="figure"> -<a href="http://archive.zhimingwang.org/img/20160126-dropbox-noteworthy.png" target="_blank"><img alt="A PDF note in Dropbox iOS. Noteworthy (scream). I know there's a typo, by the way." src="http://archive.zhimingwang.org/img/20160126-dropbox-noteworthy.png" width="300"/></a> -<p class="caption">A PDF note in Dropbox iOS. Noteworthy (scream). I know there's a typo, by the way.</p> -</div> -<p>That font is unmistakably Noteworthy, the default font in Apple's Notes app in Mountain Lion, when Apple was still practicing the damned skeuomorphism. (In case you can't recall how it looked like, let me point you to <a href="http://arstechnica.com/apple/2012/07/os-x-10-8/7/#notes">the John Siracusa review</a> for screenshots.) Just like your coworker's average handwritten notes, it is hardly legible and takes tremendous effort just to decode, especially when clustered in a paragraph rather than a short one-liner. Compare that to the same note, legibly rendered in Helvetica in PDF Expert:</p> -<div class="figure"> -<a href="http://archive.zhimingwang.org/img/20160126-pdf-expert-note.png" target="_blank"><img alt="The same note (typo corrected) in PDF Expert Mac." src="http://archive.zhimingwang.org/img/20160126-pdf-expert-note.png" width="258"/></a> -<p class="caption">The same note (typo corrected) in PDF Expert Mac.</p> -</div> -<p>This is an example of sacrificing usability for design aesthetics (an old-fashioned one for that matter, and an abonimable one if you ask for my opinion). Hard to believe we can still see it in 2016, from an otherwise great developer that is Dropbox.</p> -]]></content></entry><entry><title type="html">Antivirus app on MAS top chart?</title><link href="http://archive.zhimingwang.org/blog/2016-01-24-antivirus-app-on-mas-top-chart.html"/><updated>2016-01-24T18:43:28-08:00</updated><id>http://archive.zhimingwang.org/blog/2016-01-24-antivirus-app-on-mas-top-chart.html</id><author><name>Zhiming Wang</name><uri>http://archive.zhimingwang.org/</uri><email>zmwangx@gmail.com</email></author><content type="html"><![CDATA[ - -<p>Today for whatever reason I clicked on MAS's "Top Charts" page, and was immediately in for a surprise. Next to our great friend 1Password is an app called "AntiVirus Sentinel Pro", which sells for $9.99:</p> -<div class="figure"> -<a href="http://archive.zhimingwang.org/img/20160124-mas-top-paid.png" target="_blank"><img alt="AntiVirus Sentinel "Pro". These days many people like to end their apps' names with "Pro", even when there's nothing pro about them. This "Pro" app, for instance, comes from a developer whose three out of four apps matches the regex ^([A-Z](a-z)+ )+Pro$, and despite their names they are definitely geared towards uninformed newbies." src="http://archive.zhimingwang.org/img/20160124-mas-top-paid.png"/></a> -<p class="caption">AntiVirus Sentinel "Pro". These days many people like to end their apps' names with "Pro", even when there's nothing pro about them. This "Pro" app, for instance, comes from a developer whose three out of four apps matches the regex <code>^([A-Z](a-z)+ )+Pro$</code>, and despite their names they are definitely geared towards uninformed newbies.</p> -</div> -<p>The first rule of using MAS (or any kind of app store, for that matter) is that you research MAS apps outside the MAS. So let's Google "AntiVirus Sentinel Pro"... First result: <a href="https://discussions.apple.com/thread/6749331">Apple Support forum thread</a> from late 2014, "Is AntiVirus Sentinel Pro legit? If not, how can I delete it?" Good question about any AV product. However, you'll immediately find it hilarious when you read on:</p> -<blockquote> -<p>I have purchased and downloaded AntiVirus Sentinel Pro for Macintosh with Yosemite OS. I have a bad feeling this application is useless and maybe even harmful. Anyone knows if it is safe to use it?</p> -</blockquote> -<p>Okay, so why did you purchase it in the first place? I guess clueless users like this one are in every MAS developer's wet dreams.</p> -<p>Let's continue with the Google search results. Second one is the iTunes preview link. Third one is a <a href="http://www.securityfocus.eu/www/sentinel-pro.html">YouTube video</a> (also linked from MAS) which seems to be the only online documentation this app's got. Judging from the video the interface seems to be done in Java or something... Never mind that. Fourth result is a <a href="http://www.mac-forums.com/os-x-operating-system/327356-antivirus-sentinel-pro.html">rather recent thread</a> (August 2015) from Mac Forums. Not this again:</p> -<blockquote> -<p>I am a new Mac user. Can somebody answer these questions? Somehow it appears I have installed AntiVirus Sentinel Pro. What is this? Is it a real software? Should I keep it or try to uninstall it?</p> -</blockquote> -<p>The fifth and sixth results are general OS X AV product reviews that don't even mention this app. The next three results are from MAS aggregation sites. The last result on the first page is the app's product page on MacUpdate (now apparently abandoned), with a shiny 0.5/5 stars (note the zero point) badge.</p> -<p>Now that we've finished the first page (and the results are not a bit reassuring), the question comes: where the heck is this app's home page? It's also not on the second page, actually. There's something interesting on the third (still no home page), that is <a href="https://twitter.com/claud_xiao/status/681981763938197504">this tweet</a>:</p> -<blockquote> -<p>$10 "AntiVirus Sentinel Pro" got top2 in US Mac App Store and top1 in 48 countries--but it's just ClamAV+AdwareMedic signs+3 bullshit signs.</p> -</blockquote> -<p>Hmm. You might want to read Thomas Reed's (known for The Safe Mac) responses from that thread.</p> -<p>Anyway, we were sidetracked. Back to the home page, actually this app does have one, but it's just <a href="http://www.securityfocus.eu/www/sentinel-pro.html">a single page</a>, which simply states some marketing bullshit and directs to MAS (where the same bullshit is repeated). Seriously? That's the best you can do for your "pro" app, especially a security-related one?</p> -<p>Back to MAS, the reviews are kind of jokes, too:</p> -<div class="figure"> -<a href="http://archive.zhimingwang.org/img/20160124-antivirus-sentinel-pro-reviews.png" target="_blank"><img alt="Stupid reviews for stupid app." src="http://archive.zhimingwang.org/img/20160124-antivirus-sentinel-pro-reviews.png"/></a> -<p class="caption">Stupid reviews for stupid app.</p> -</div> -<p>The first one begins with</p> -<blockquote> -<p>Just switched to Apple from Windows ... and researched anti-virus software.</p> -</blockquote> -<p>Don't really need to read further.</p> -<p>Second one, speaking of customer service:</p> -<blockquote> -<p>... it only took one email to him explaining my problem... had a patch up and ready on the app store to download within hours.</p> -</blockquote> -<p>This review is from October 2015. Since when was MAS so efficient? Why do I (and everyone else keeping tabs on Apple stuff) keep hearing stories like <a href="http://mjtsai.com/blog/2015/12/01/sketch-leaving-the-mac-app-store/">bug fix updates waiting for review after 59 days</a>?</p> -<p>The pattern goes on. By the way, how does this app keep track of all disk and network activity when itself is running in a sandbox? No idea (maybe I'm misunderstanding sandboxing).</p> -<p>In summary, even as an AV product, this one seems untrustworthy. Not to mention AV products on the Mac are generally superfluous if not harmful.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-01-24-antivirus-app-on-mas-top-chart.html#fn1" id="fnref1"><sup>1</sup></a> What people really need to learn is to practice safe browsing habits and to properly use content blockers, which AV product vendors and (intrusive-)ad-supported websites (that is most, commercial websites today) won't tell you because they would go out of business if they do.</p> -<p>And how this app got onto the top charts, that is a real mystery.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>Disclaimer: I personally have used ClamXav and AdwareMedic (which has since been bought by Malwarebytes) before to help my social-engineered friend (tech support scam, in case you ask). Just to scan their documents though. It is my belief that once you're pwned (even slightly), clean system reinstall is the only way to go, despite what AV products might tell you. In addition, I don't use AV products myself (except Microsoft Security Essentials on Windows); as a programmer I've had enough bad experience with AV blocking <em>my</em> programs back in the Windows days.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-01-24-antivirus-app-on-mas-top-chart.html#fnref1">↩︎</a></p></li> -</ol> -</div> -]]></content></entry><entry><title type="html">Me-too comments on GitHub</title><link href="http://archive.zhimingwang.org/blog/2016-01-18-me-too-comments-on-github.html"/><updated>2016-01-18T16:36:40-08:00</updated><id>http://archive.zhimingwang.org/blog/2016-01-18-me-too-comments-on-github.html</id><author><name>Zhiming Wang</name><uri>http://archive.zhimingwang.org/</uri><email>zmwangx@gmail.com</email></author><content type="html"><![CDATA[ - -<p>I frequently subscribe to issues on GitHub, be it bugs I want to see fixed or features I would like to see implemented. Then every once in a short while I get an email notification about one of those obnoxious "me too" or "+1" comments, by which I mean terse comments with little to no content other than "me too" or "+1" or some other variant bearing the same meaning.</p> -<p>Me-too comments under bug reports are the most untolerable. If you have more details regarding the issue (e.g., a more reliable reproducer) or insights into what's really going on, then by any means post them. On the other hand, if you can't provide anything helpful, then just keep your mouth shut, and quietly press "subscribe" if you would like to be kept posted. Posting a me-too comment adds nothing to the discussion, does not expedite the resolution a tiny bit, and only serves to annoy all parties involved.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-01-18-me-too-comments-on-github.html#fn1" id="fnref1"><sup>1</sup></a> As always, submit a patch if you're dissatisfied with the progress. Keep in mind that no one is obligated to fix bugs for you in FOSS.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-01-18-me-too-comments-on-github.html#fn2" id="fnref2"><sup>2</sup></a></p> -<p>Me-too comments under feature requests are more understandable, though I genuinely doubt that two or three people requesting a feature instead of one would make a big difference. After all, the issue tracker is not a feature voting platform; most folks understand this and behave themselves, so "me-too demand" isn't even remotely accurate at reflecting demand.</p> -<p>Me-too folks: please stop being childish. If you have nothing to add, don't add anything (unless otherwise requested).</p> -<hr/> -<p><strong>01/20/2015 Update.</strong> I came accross <a href="https://github.com/dear-github/dear-github">dear-githuub/dear-github</a> just now, which was started a mere six days ago, and the <a href="https://github.com/dear-github/dear-github/blob/bc7a4f6bc78445905751061bf96f731edda14c25/README.md">open letter</a> of which also places +1 comments on its list of biggest problems on GitHub.</p> -<hr/> -<p><strong>03/10/2015 Update.</strong> GitHub is finally reacting. See <a href="https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments">Add Reactions to Pull Requests, Issues, and Comments</a>.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>There are exceptional cases.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-01-18-me-too-comments-on-github.html#fnref1">↩︎</a></p></li> -<li id="fn2"><p>Here we're talking about the subset of FOSS that is also free as in beer.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-01-18-me-too-comments-on-github.html#fnref2">↩︎</a></p></li> -</ol> -</div> -]]></content></entry><entry><title type="html">The dirtiest mistakes of OS X</title><link href="http://archive.zhimingwang.org/blog/2016-01-14-the-dirtiest-mistakes-of-os-x.html"/><updated>2016-01-14T01:02:52-08:00</updated><id>http://archive.zhimingwang.org/blog/2016-01-14-the-dirtiest-mistakes-of-os-x.html</id><author><name>Zhiming Wang</name><uri>http://archive.zhimingwang.org/</uri><email>zmwangx@gmail.com</email></author><content type="html"><![CDATA[ - -<p>I must have written about this elsewhere, but here are my top three:</p> -<ol style="list-style-type: decimal"> -<li><p><code>.DS_Store</code>. Finder litters faster than one could clean up.</p></li> -<li><p>HFS+ NFD*.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-01-14-the-dirtiest-mistakes-of-os-x.html#fn1" id="fnref1"><sup>1</sup></a> Heard of the cursed encoding <code>UTF8-MAC</code>? Pure Evil. Culprit of tons of garbled text issues (especially cross platform ones) and probably most length miscalculation issues. Even Apple's Terminal.app can't do NFD right. I wonder how Korean users navigate their filesystems in terminal.</p></li> -<li><p>Plist XML. It's XML, but even worse.</p></li> -</ol> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>NFD with an asterisk, i.e., not even NFD. According to Apple in <a href="https://developer.apple.com/library/mac/qa/qa1173/_index.html">an old Technical Q&A</a>,</p> -<blockquote> -<p>The terms used in this Q&A, precomposed and decomposed, roughly correspond to Unicode Normal Forms C and D, respectively. However, most volume formats do not follow the exact specification for these normal forms. For example, HFS Plus (Mac OS Extended) uses a variant of Normal Form D in which U+2000 through U+2FFF, U+F900 through U+FAFF, and U+2F800 through U+2FAFF are not decomposed (this avoids problems with round trip conversions from old Mac text encodings). It's likely that your volume format has similar oddities.</p> -</blockquote> -<p>They are conscious enough to call these oddities.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-01-14-the-dirtiest-mistakes-of-os-x.html#fnref1">↩︎</a></p></li> -</ol> -</div> -]]></content></entry><entry><title type="html">Virtualenvs for everyone</title><link href="http://archive.zhimingwang.org/blog/2016-01-01-virtualenvs-for-everyone.html"/><updated>2016-01-01T22:21:14-08:00</updated><id>http://archive.zhimingwang.org/blog/2016-01-01-virtualenvs-for-everyone.html</id><author><name>Zhiming Wang</name><uri>http://archive.zhimingwang.org/</uri><email>zmwangx@gmail.com</email></author><content type="html"><![CDATA[ - -<p>Python distutils for the most part is rather pleasant to work with. That is, pleasant until you've accumulated so many packages that you eventually run into a clash of namespace, or a dependency conflict (or dependency hell as most would affectionately call it).<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-01-01-virtualenvs-for-everyone.html#fn1" id="fnref1"><sup>1</sup></a> In contrast, npm's approach to dependencies shuts out dependency hell completely, but it is so paranoid and costs so much duplication that I find it hard to appreciate unless necessary. Somewhere in between there's the virtualenv approach which I find most appealing for smallish projects — keep a single copy of each package in the dependency tree in a contained environment specific to the project at hand. This is how we debug Python projects, and it certainly also should be <em>the</em> way we run command line tools written in Python.</p> -<p>There's another reason I like virtualenvs. There are tons of problems associated with choosing between Python 2 and 3 — some projects are Python 2 only, some are instead Python 3, some claim to be compatible with both but actually present subtle problems when you use one instead of the other. However, without virtualenvs, there's only one <code>bin</code> — <code>/usr/local/bin</code> — and everything's competing for it. Most programs (especially ones with a typical <code>setup.py</code>) don't install a soft/hardlink with a helpful <code>2</code> or <code>3</code> suffix when installing executables, let alone detailed suffixes like <code>2.7</code> or <code>3.5</code>, so without probing into the shebangs you're never sure which version of Python you're running your program with, and as a result Python 2/3 (or even a point release)-specific bugs occur randomly. Virtualenvs solve the problem by allowing you to have as many bins (and includes, and libs) as you like.</p> -<p>Hence the title "virtualenvs for everyone". I would like to install each command line program written in Python into a separate virtualenv. The only issue is that apparently I don't want too many bins in my <code>$PATH</code>; to solve this issue, the executable bits of each project should be linked to a central place, for which I choose <code>$HOME/bin</code>. There could be as many symlinks as we like, so now we can have multiple links with increasing detailed version suffixes, e.g., <code>3</code>, <code>3.5</code>, <code>3.5.1</code>. Very nice.</p> -<p>This task could clearly be automated; the only slightly tricky bit is to programmatically figure out which scripts a project installs to <code>bin</code>. Luckily, for projects using <code>setuptools.setup</code>, we can simply spoof that function. Here's my <code>setuptools/__init__.py</code>:</p> -<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="co">#!/usr/bin/env python3</span> - -<span class="co">"""setuptools stubs.</span> - -<span class="co">Here we only stubbed the symbols in setuptools.__all__. Hopefully that's</span> -<span class="co">enough (actually I can't remember seeing any setup.py using more than</span> -<span class="co">setup and find_packages).</span> - -<span class="co">setup has been spoofed to print the names of scripts, console_scripts</span> -<span class="co">and gui_scripts defined in the arguments to setup. Some user-friendly</span> -<span class="co">messages are also printed to stderr.</span> - -<span class="co">"""</span> - -<span class="im">from</span> __future__ <span class="im">import</span> print_function - -<span class="im">import</span> re -<span class="im">import</span> sys -<span class="im">import</span> os - -__all__ <span class="op">=</span> [ - <span class="st">'setup'</span>, <span class="st">'Distribution'</span>, <span class="st">'Feature'</span>, <span class="st">'Command'</span>, <span class="st">'Extension'</span>, <span class="st">'Require'</span>, - <span class="st">'find_packages'</span> -] - -<span class="kw">def</span> setup(<span class="op">**</span>kwargs): - scripts <span class="op">=</span> [os.path.basename(script_path) - <span class="cf">for</span> script_path <span class="kw">in</span> kwargs.pop(<span class="st">'scripts'</span>, [])] - <span class="cf">if</span> scripts: - <span class="bu">print</span>(<span class="st">'scripts:</span><span class="ch">\n</span><span class="st"> - </span><span class="sc">%s</span><span class="st">'</span> <span class="op">%</span> <span class="st">'</span><span class="ch">\n</span><span class="st"> - '</span>.join(scripts), <span class="bu">file</span><span class="op">=</span>sys.stderr) - entry_points <span class="op">=</span> kwargs.pop(<span class="st">'entry_points'</span>, {}) - <span class="cf">for</span> entry_point <span class="kw">in</span> [<span class="st">'console_scripts'</span>, <span class="st">'gui_scripts'</span>]: - extra_scripts <span class="op">=</span> [re.split(<span class="st">'(\s|=)'</span>, spec.strip())[<span class="dv">0</span>] - <span class="cf">for</span> spec <span class="kw">in</span> entry_points.pop(entry_point, [])] - <span class="cf">if</span> extra_scripts: - <span class="bu">print</span>(<span class="st">'</span><span class="sc">%s</span><span class="st">:</span><span class="ch">\n</span><span class="st"> - </span><span class="sc">%s</span><span class="st">'</span> <span class="op">%</span> (entry_point, <span class="st">'</span><span class="ch">\n</span><span class="st"> - '</span>.join(extra_scripts)), - <span class="bu">file</span><span class="op">=</span>sys.stderr) - scripts.extend(extra_scripts) - <span class="bu">print</span>(<span class="st">'</span><span class="ch">\n</span><span class="st">'</span>.join(<span class="bu">sorted</span>(scripts))) - -<span class="kw">class</span> Distribution(<span class="bu">object</span>): <span class="cf">pass</span> -<span class="kw">class</span> Feature(<span class="bu">object</span>): <span class="cf">pass</span> -<span class="kw">class</span> Command(<span class="bu">object</span>): <span class="cf">pass</span> -<span class="kw">class</span> Extension(<span class="bu">object</span>): <span class="cf">pass</span> -<span class="kw">class</span> Require(<span class="bu">object</span>): <span class="cf">pass</span> -<span class="kw">def</span> find_packages(<span class="op">**</span>kwargs): <span class="cf">pass</span></code></pre></div> -<p>Now, let <code>$HERE</code> be the directory containing our fake <code>setuptools/</code>, and <code>$PROJECT_ROOT</code> be the project root directory containing <code>setup.py</code>. Run</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh"><span class="ot">PYTHONPATH=$HERE</span>:<span class="ot">$PYTHONPATH</span> python <span class="ot">$PROJECT_ROOT</span>/setup.py</code></pre></div> -<p>and bam! We get the names of all scripts on stdout.</p> -<p>My full automation scripts, including the Zsh main function <code>virtual-install</code>, can be found in <a href="https://github.com/zmwangx/prezto/tree/master/modules/python/functions"><code>modules/python/functions</code> in zmwangx/prezto</a>. I'm not including it here because it uses some custom helper, and it's just too long (200+ lines, but not very sophisticated). Happy virtualenving!</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>In rare cases, even installing a single package could land you in trouble. The classical example is installing the <code>readme</code> package on a case-insensitive filesystem (e.g., the default mode of HFS+). "Unfortunately" <a href="https://bugs.python.org/issue24633">this</a> has been fixed.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-01-01-virtualenvs-for-everyone.html#fnref1">↩︎</a></p></li> -</ol> -</div> -]]></content></entry><entry><title type="html">Catches when installing Windows 7 with Boot Camp</title><link href="http://archive.zhimingwang.org/blog/2015-12-29-catches-when-installing-windows-7-with-boot-camp.html"/><updated>2015-12-29T15:09:16-08:00</updated><id>http://archive.zhimingwang.org/blog/2015-12-29-catches-when-installing-windows-7-with-boot-camp.html</id><author><name>Zhiming Wang</name><uri>http://archive.zhimingwang.org/</uri><email>zmwangx@gmail.com</email></author><content type="html"><![CDATA[ - -<p>I was looking for a use for my retired Mid-2012 Non-Retina MacBook Pro 13''<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-12-29-catches-when-installing-windows-7-with-boot-camp.html#fn1" id="fnref1"><sup>1</sup></a>, and unsurprisingly I figured that I would turn it into a OS X-Windows dual boot for some occasional gaming. I'm a CnC fan (not hardcore, but still), mainly for RA2/YR and TW/KW, and playing these inside Fusion is really a subsubpar experience. Due to the age of these games and their compatibility problems on Windows 8 and higher<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-12-29-catches-when-installing-windows-7-with-boot-camp.html#fn2" id="fnref2"><sup>2</sup></a>, I chose to shoot for a Windows 7 install.</p> -<p>Apple has a pretty thorough walkthrough in the support article <a href="https://support.apple.com/en-us/HT205016">Install Windows 7 and earlier on your Mac using Boot Camp</a>. There are, however, some catches that I would like to collect and share in this post.</p> -<ol style="list-style-type: decimal"> -<li><p>Win 7 ISO isn't available for download in the appropriate language (given your product key). This one sounds incredibly stupid... But it is a real problem at least for me and several others (just Google). I have a valid Win 7 Ultimate license from my institution, so I went to <a class="uri" href="https://www.microsoft.com/en-us/software-download/windows7">https://www.microsoft.com/en-us/software-download/windows7</a> to grab my ISO (just for fun; I already have the image). However, after verifying my product key, here's the list of languages that I'm asked to choose from, where English is apparently missing (!!!):</p> -<div class="figure"> -<a href="http://archive.zhimingwang.org/img/20151229-win7-iso-language-choice.png" target="_blank"><img alt="da !@#$?" src="http://archive.zhimingwang.org/img/20151229-win7-iso-language-choice.png" width="394"/></a> -<p class="caption">da !@#$?</p> -</div> -<p>I don't know the solution to this problem. In my case I've archived English Win 7 Ultimate SP1 images (both x86 and x64) before, so I just proceeded with my old image.</p></li> -<li><p>FileVault. It is my belief that FileVault needs to turned off before partitioning the drive with Boot Camp.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-12-29-catches-when-installing-windows-7-with-boot-camp.html#fn3" id="fnref3"><sup>3</sup></a></p></li> -<li><p><em>An error occured while partitioning the disk.</em> That's the unhelpful message from Boot Camp. If you try to manually partition the drive with Disk Utility, you'll probably get a much more helpful message like <em>Partition failed with the error: couldn't modify partition map because file system verification failed</em>. Now the problem is obvious, and the solution is simple. Boot to single user mode and repair the filesystem with <code>/sbin/fsck -fy</code>, or safer, <code>/sbin/fsck -f</code> which might require interaction.</p></li> -<li><p>During Windows installation you'll obviously be prompted to choose a system partition at some point, and due to Boot Camp only formatting to FAT32, you'll get the message <em>Windows cannot be installed to this hard disk space. Windows must be installed to a partition formatted as NTFS.</em> This one is easy, just click "Drive options (advanced)" then "Format", which automatically formats the partition to NTFS. This is actually documented in Apple's walkthrough, but mortals do panic in face of error messages, so let's also note it here.</p></li> -<li><p>Even after formatting the Boot Camp partition, it is still possible to get the error <em>Setup was unable to create a new system partition or locate an existing system partition</em>. It this happens, check if you have any USB drives (other than the installation media) plugged in. In my case my Time Capsule was plugged in, and rebooting with it unplugged fixed the problem. The exact cause of the problem is unclear to me. Some say it's due to Master Boot Record limiting the number of partitions to four, but why the heck is my external drive counted towards that limitation? I'd go for Win 7 installer is just confused. Anyway, just unplug anything that's not needed during Windows installation.</p></li> -</ol> -<p>Hopefully you're good after solving the aforementioned problems. If you followed Apple's walkthrough correctly, Boot Camp's setup.exe will be invoked automatically immediately after Windows finishes installation, and after a certain number of reboots your drivers will be up and running. Now you're ready to take control of your Windows. Install Chrome<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-12-29-catches-when-installing-windows-7-with-boot-camp.html#fn4" id="fnref4"><sup>4</sup></a> and Microsoft Security Essentials immediately, then hop right into the Windows Update hell to patch your four-year-old system. Of course, Windows Update being Windows Update won't be smooth — servers will be crowded as ever and just checking for updates will likely take forever, let alone downloads. After a semi-infinite amount of time you'll get your estimates (I got 212 updates). Click update and let Windows Update grind for hours. And wish yourself a good luck (that no update errors will occur — luckily I didn't get any).</p> -<p>By the way, the otherwise great Apple trackpad is almost unusable on Boot Camp Windows under any setting. I'm forced to use a mouse.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>2.9 GHz i7 + Intel HD Graphics 4000 + 16 GB RAM + frigging slow 750 GB 5400-rpm spinning disk I've yet to replace.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-12-29-catches-when-installing-windows-7-with-boot-camp.html#fnref1">↩︎</a></p></li> -<li id="fn2"><p>RA2/YR used to have problems even on Windows 7, at least inside Fusion, so I used to play them in XP SP3 VMs; I've yet to try them with Windows 7 running on bare metal.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-12-29-catches-when-installing-windows-7-with-boot-camp.html#fnref2">↩︎</a></p></li> -<li id="fn3"><p>I'm not completely sure that this is necessary. I was greeted with partitioning errors initially which I thought was due to FileVault, so I switched it off (the actual process is much longer than "switching it off", since the whole disk has to be decrypted and rewritten), but as you'll see later, the partitioning errors were at least partly due to a slightly corrupt filesystem.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-12-29-catches-when-installing-windows-7-with-boot-camp.html#fnref3">↩︎</a></p></li> -<li id="fn4"><p>You can't even browse Microsoft's own websites with stock IE8. And IE11 is locked behind a hell lot of Windows Updates (even then it is crap). Doing Windows Update is like building up a tech tree.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-12-29-catches-when-installing-windows-7-with-boot-camp.html#fnref4">↩︎</a></p></li> -</ol> -</div> -]]></content></entry><entry><title type="html">Why I want lossless music on iTunes Music Store</title><link href="http://archive.zhimingwang.org/blog/2015-12-28-why-i-want-lossless-music-on-itunes-music-store.html"/><updated>2015-12-28T03:15:45-08:00</updated><id>http://archive.zhimingwang.org/blog/2015-12-28-why-i-want-lossless-music-on-itunes-music-store.html</id><author><name>Zhiming Wang</name><uri>http://archive.zhimingwang.org/</uri><email>zmwangx@gmail.com</email></author><content type="html"><![CDATA[ - -<p>This is an impulse post after reading <a href="https://marco.org/2015/12/27/apple-hd-audio-again">"Apple again rumored to be working on high-resolution audio"</a>.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-12-28-why-i-want-lossless-music-on-itunes-music-store.html#fn1" id="fnref1"><sup>1</sup></a></p> -<p>To be clear, I'm no audiophile. I can't tell the difference between 256kbps AAC and lossless (maybe not even the difference between 128k and 256k), and my midrange to lower midrange equipments probably won't let me tell anyway. I'm certainly not a consumer of snake oil.</p> -<p>However, I still prefer to get everything in lossless, simply because <strong>"good enough" today is almost never good enough tomorrow</strong>. Fifty years later I'm most likely still wandering this planet, I and my music collection. I would be extremely regretful if I didn't archive the highest quality versions of my favorite tracks today, only to find them inferior-sounding fifty years later, which is a pretty realistic possibility given how fast technology advances.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-12-28-why-i-want-lossless-music-on-itunes-music-store.html#fn2" id="fnref2"><sup>2</sup></a> Even today's lossless could be inferior-sounding in the future, but there would be no regret.</p> -<p>To be extra clear, I'm talking about lossless for archival purposes, so what I want to see is a lossless download option in ITMS.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-12-28-why-i-want-lossless-music-on-itunes-music-store.html#fn3" id="fnref3"><sup>3</sup></a> Streaming can be done in whatever good enough® sampling frequency and bitrate that's currently in use, since it's a one-off thing with no effects on tomorrow (and I don't give a shit about streaming and subscription anyway). Offering lossless downloads likely won't put much burden on Apple's infrastructure, since they already deliver much more bandwidth-demanding movies on the same channel. Moreover, albums on ITMS aren't much cheaper than physical CDs, while the cost is apparently lower than CD production, the audience apparently wider, and the chances of impulse purchases (especially of single tracks) much higher, so I would suppose such a move (delivering lossless on ITMS) won't considerably hurt record labels' profits either. After all, if they don't make it easy for consumers, many consumers will just pirate — it's way too easy to pirate music.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>And I did see the <a href="http://www.macrumors.com/2015/12/20/apple-high-resolution-audio/">MacRumors article</a> a week ago. I even registered a MacRumors account, which I never bothered to do, just to comment on that article... It just didn't occur to me to write a blog post at that time.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-12-28-why-i-want-lossless-music-on-itunes-music-store.html#fnref1">↩︎</a></p></li> -<li id="fn2"><p>You might be skeptical of my hearing when I'm in my seventies... But I could well be showing my favorites to someone with perfect hearing, say my grandchildren.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-12-28-why-i-want-lossless-music-on-itunes-music-store.html#fnref2">↩︎</a></p></li> -<li id="fn3"><p>I know there are many online music stores that sell lossless music, but ITMS has the largest catalog in the world, and for many titles I care about, ITMS is still the only place in this country where I can make legal digital purchases.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-12-28-why-i-want-lossless-music-on-itunes-music-store.html#fnref3">↩︎</a></p></li> -</ol> -</div> -]]></content></entry><entry><title type="html">Lesson on magic method access of Python new-style classes (from my failed Python3 port of Tomorrow)</title><link href="http://archive.zhimingwang.org/blog/2015-12-27-lesson-on-magic-method-access-of-python-new-style-classes-from-my-failed-python3-port-of-tomorrow.html"/><updated>2015-12-27T16:47:05-08:00</updated><id>http://archive.zhimingwang.org/blog/2015-12-27-lesson-on-magic-method-access-of-python-new-style-classes-from-my-failed-python3-port-of-tomorrow.html</id><author><name>Zhiming Wang</name><uri>http://archive.zhimingwang.org/</uri><email>zmwangx@gmail.com</email></author><content type="html"><![CDATA[ - -<p>I know the title is formidably long, but I can't find something more accurate (and my homegrown mini CMS doesn't support subtitle), so please bear with me.</p> -<p>So, I have <a href="https://github.com/madisonmay/Tomorrow">madisonmay/Tomorrow</a> — "magic decorator syntax for asynchronous code in Python 2.7" — bookmarked for a long time<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-12-27-lesson-on-magic-method-access-of-python-new-style-classes-from-my-failed-python3-port-of-tomorrow.html#fn1" id="fnref1"><sup>1</sup></a> without ever trying it, because I simply don't write Python 2 code any more (except when I try to maintain compatibililty). I felt kind of strange that a ~50-line project with ~1000 stars on GitHub hasn't been ported to Python 3 already, so I gave it a shot just now.</p> -<p>I thought it would be easy:</p> -<ol style="list-style-type: decimal"> -<li>Modernize the old-style class <code>Tomorrow</code>;</li> -<li>Replace <code>__getattr__</code> with <code>__getattribute__</code> for unconditional attribute routing, then make a few exceptions to prevent infinite recursion;</li> -<li><code>2to3</code> test cases;</li> -<li>Make meta changes, like removing the <code>futures</code> dependency.</li> -</ol> -<p>However, after doing 1–3, I ran the tests, and out of the five test cases, three failed and one errored. I tried to isolate the problem, and ended up with the following piece of proof-of-concept:</p> -<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="kw">class</span> PassThrough(<span class="bu">object</span>): - - <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>, obj): - <span class="va">self</span>._obj <span class="op">=</span> obj - - <span class="kw">def</span> <span class="fu">__getattribute__</span>(<span class="va">self</span>, name): - <span class="cf">if</span> name <span class="op">==</span> <span class="st">"_obj"</span>: - <span class="cf">return</span> <span class="bu">object</span>.<span class="fu">__getattribute__</span>(<span class="va">self</span>, name) - <span class="bu">print</span>(<span class="st">"Accessing '</span><span class="sc">%s</span><span class="st">'"</span> <span class="op">%</span> name) - <span class="cf">return</span> <span class="va">self</span>._obj.<span class="fu">__getattribute__</span>(name)</code></pre></div> -<p>This snippet is valid in both Python 2.7 and Python 3, but here's the surprise:</p> -<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="op">>>></span> g <span class="op">=</span> PassThrough(<span class="dv">0</span>) -<span class="op">>>></span> <span class="bu">print</span>(g) -<span class="op"><</span>__main__.PassThrough <span class="bu">object</span> at <span class="bn">0x10c662e48</span><span class="op">></span> -<span class="op">>>></span> <span class="bu">str</span>(g) -<span class="co">'<__main__.PassThrough object at 0x10c662e48>'</span> -<span class="op">>>></span> <span class="bu">hasattr</span>(g, <span class="st">'__str__'</span>) -Accessing <span class="st">'__str__'</span> -<span class="va">True</span> -<span class="op">>>></span> g.<span class="fu">__str__</span>() -Accessing <span class="st">'__str__'</span> -<span class="co">'0'</span></code></pre></div> -<p>In addition, here's what happens if you try to "pass through" a function:</p> -<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="op">>>></span> <span class="kw">def</span> f(): <span class="cf">return</span> <span class="va">True</span> -<span class="op">>>></span> g <span class="op">=</span> PassThrough(f) -<span class="op">>>></span> g() -Accessing <span class="st">'__class__'</span> -Accessing <span class="st">'__class__'</span> -Traceback (most recent call last): - File <span class="st">"<ipython-input-6-d65ffd94a45c>"</span>, line <span class="dv">1</span>, <span class="kw">in</span> <span class="op"><</span>module<span class="op">></span> - g() -<span class="pp">TypeError</span>: <span class="st">'PassThrough'</span> <span class="bu">object</span> <span class="kw">is</span> <span class="kw">not</span> <span class="bu">callable</span> - -<span class="op">>>></span> <span class="bu">callable</span>(g) -<span class="va">False</span> -<span class="op">>>></span> <span class="bu">hasattr</span>(g, <span class="st">'__call__'</span>) -Accessing <span class="st">'__call__'</span> -<span class="va">True</span> -<span class="op">>>></span> g.<span class="fu">__call__</span>() -Accessing <span class="st">'__call__'</span> -<span class="va">True</span></code></pre></div> -<p>As you can tell, although <code>__str__</code> or <code>__call__</code> may have been implemented through <code>__getattribute__</code>, and <code>hasattr</code> (which in turn depends on <code>getattr</code>) has no trouble finding them, they are not picked up by <code>str</code> or function call <code>(...)</code>. At this point, one would suspect that this is due to <code>str</code> or function call only looking at the class instance's <code>__dict__</code>. Compare this to the behavior of an old-style class:</p> -<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="kw">class</span> PassThrough(): - - <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>, obj): - <span class="va">self</span>._obj <span class="op">=</span> obj - - <span class="kw">def</span> <span class="fu">__getattr__</span>(<span class="va">self</span>, name): - <span class="bu">print</span>(<span class="st">"Acessing '</span><span class="sc">%s</span><span class="st">'"</span> <span class="op">%</span> name) - <span class="cf">return</span> <span class="va">self</span>._obj.<span class="fu">__getattribute__</span>(name)</code></pre></div> -<p>Now:</p> -<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="op">>>></span> g <span class="op">=</span> PassThrough(<span class="dv">0</span>) -<span class="op">>>></span> <span class="bu">print</span>(g) -Acessing <span class="st">'__str__'</span> -<span class="dv">0</span> -<span class="op">>>></span> <span class="kw">def</span> f(): <span class="cf">return</span> <span class="va">True</span> -<span class="op">>>></span> g <span class="op">=</span> PassThrough(f) -<span class="op">>>></span> g() -Acessing <span class="st">'__call__'</span> -<span class="va">True</span></code></pre></div> -<p>Note that magic method access is always routed through <code>__getattr__</code>.</p> -<p>After some digging, my suspicion was confirmed: indeed, for new-style classes, rather than invoking <code>__getattribute__</code>, the Python interpreter only looks for magic methods in <code>__dict__</code>. But is there a workaround for implementing something like the <code>PassThrough</code> class above? There's a <a href="http://stackoverflow.com/a/9059858/">nice answer</a> on StackOverflow that uses a metaclass to "automatically add proxies for magic methods at the time of class creation", to quote the author. However, the thing about Tomorrow is that <em>we don't have the result and don't know whatever magic methods it might have at class creation</em> — after all, Python isn't a statically typed language. It is possible for programmers to offer hints, but then Tomorrow won't be as elegant and magical anymore. Therefore, unfortunately enough, Tomorrow isn't portable to Python 3 — at least not without a substantial hack that's beyond my knowledge, or a complete overhaul of its logic (haven't thought about that).</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>Pretty much since the beginning, I believe (the <a href="https://github.com/madisonmay/Tomorrow/commit/22a53dfbcf9b516ecd1770eeca9fcf1720271240">initial commit</a> was from July 24 of this year). I don't remember how I came accross it though.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-12-27-lesson-on-magic-method-access-of-python-new-style-classes-from-my-failed-python3-port-of-tomorrow.html#fnref1">↩︎</a></p></li> -</ol> -</div> -]]></content></entry><entry><title type="html">autoenv with auto cleanup</title><link href="http://archive.zhimingwang.org/blog/2015-12-26-autoenv-with-auto-cleanup.html"/><updated>2015-12-26T00:15:48-08:00</updated><id>http://archive.zhimingwang.org/blog/2015-12-26-autoenv-with-auto-cleanup.html</id><author><name>Zhiming Wang</name><uri>http://archive.zhimingwang.org/</uri><email>zmwangx@gmail.com</email></author><content type="html"><![CDATA[ - -<p>I heard about <a href="https://github.com/kennethreitz/autoenv">kennethreitz/autoenv</a> a long time ago. The idea of autoloading project-specific environment modifications is nice, but no auto cleanup after leaving a project was a showstopper for me.</p> -<p>Today, I took matters into my own hands and wrote a fresh Zsh implementation<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-12-26-autoenv-with-auto-cleanup.html#fn1" id="fnref1"><sup>1</sup></a> with auto cleanup support. Check it out: <a class="uri" href="https://github.com/zmwangx/prezto/tree/master/modules/autoenv">https://github.com/zmwangx/prezto/tree/master/modules/autoenv</a>.</p> -<p>As a quick promotion, let me show you two common examples.</p> -<p>First, inserting some local bin directory into the search path. This is easily done by a one-line <code>.env</code>, say,</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh">autoenv-insert-paths bin libexec</code></pre></div> -<p>This way <code>$PWD/bin</code> and <code>$PWD/libexec</code> are inserted to the beginning of the search path, which will persist until you leave the directory tree. That is to say, the inserted paths will still be available when you descend into subdirectories (and more specific <code>.env</code>'s can even be stacked as you descend), but they will be purged as soon as you leave the tree. Clever, isn't it?</p> -<p>Secondly, exporting project-specific environment variables. The <code>.env</code> would look like</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh"><span class="kw">export</span> <span class="ot">HOMEBREW_DEVELOPER=</span>not-for-the-faint-hearted - -<span class="fu">autoenv-purge ()</span> <span class="kw">unset</span> HOMEBREW_DEVELOPER</code></pre></div> -<p>where the body of <code>autoenv-purge</code> will be executed when you leave the directory tree. No more junk floating around.</p> -<p>Again, for more info, including detailed usage and customization instructions, please visit <a href="https://github.com/zmwangx/prezto/tree/master/modules/autoenv"><code>modules/autoenv</code></a> in zmwangx/prezto.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>This is not a re-implementation in the common sense. My little Zsh module is inspired by kennethreitz/autoenv and reminiscent of that older project, but I took nothing from there (in fact I didn't even read their source code). I also don't claim to support their entire feature set. For instance, kennethreitz/autoenv claims to be Foreman compatible, which includes turning on <code>ALL_EXPORT</code>. However, I don't think <code>ALL_EXPORT</code> by default is a good idea, so with my <code>autoenv</code>, if you want <code>ALL_EXPORT</code> you have to set it explicitly.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-12-26-autoenv-with-auto-cleanup.html#fnref1">↩︎</a></p></li> -</ol> -</div> -]]></content></entry><entry><title type="html">Regex flavor hell</title><link href="http://archive.zhimingwang.org/blog/2015-12-20-regex-flavor-hell.html"/><updated>2015-12-20T16:03:03-08:00</updated><id>http://archive.zhimingwang.org/blog/2015-12-20-regex-flavor-hell.html</id><author><name>Zhiming Wang</name><uri>http://archive.zhimingwang.org/</uri><email>zmwangx@gmail.com</email></author><content type="html"><![CDATA[ - -<p>I write a lot of shell scripts, which means dealing with common *ix utilities a lot. I typically want my scripts to work on both OS X and Linux (or OS X + GNU utilities, which is my personal setup), which means writing commands that are understood in both GNU/Linux and BSD worlds. Unfortunately that's not so simple, because to do that I usually have to give up readily available functionalities (especially the vast collection of useful options typical of GNU utilities) and am constantly thrown back to the stone age that is POSIX, or a little bit more than POSIX.</p> -<p>Working with regular expressions is especially painful. Almost every implementation of every utility (with regex support) has its own flavor of regex. Most notably the big three: <code>grep</code>, <code>sed</code> and <code>awk</code>. GNU utilities of course come with GNU extensions, but they are nothing when aiming for compatibility. Ignoring GNU extensions, there's a way to turn on standard POSIX extensions (ERE) on <code>sed</code>, but unfortunately GNU and BSD use different flags: <code>-r</code> for GNU sed and <code>-E</code> for BSD sed. The two implementations of <code>grep</code> thankfully use the same flag <code>-E</code> to turn on ERE, but GNU grep, being a GNU utility and having to distinguish itself from its mundane counterpart, further implements <code>-P,--perl-regexp</code> — regexers' dream. It's there but I can't use it, except in an interactive shell. <code>awk</code> has more than two implementations and will be left out of this discussion.</p> -<p>Anyway, despite all these flavor issues, I can usually get away with BRE, although it's verbose and unreadable as hell (quantifiers in particular) and doesn't support alternation. I would be thankful if BRE is the end of the story, but it is not. There are more tools lurking around trying to sabotage scripters. <code>find</code> is a perfect example. BSD <code>find</code>, unsurprisingly, uses BRE by default with <code>-regex</code> and <code>-iregex</code>, and ERE may be turned on with the <code>-E</code> flag. GNU findutils <code>find</code>, however, tries to be helpful and future-proof by having a <code>-regextype</code> option:</p> -<blockquote> -<p>Changes the regular expression syntax understood by <code>-regex</code> and <code>-iregex</code> tests which occur later on the command line. Currently-implemented types are <code>emacs</code> (this is the default), <code>posix-awk</code>, <code>posix-basic</code>, <code>posix-egrep</code> and <code>posix-extended</code>.</p> -</blockquote> -<p>The Emacs flavor? You mean Elisp regexp? Okay fine, <a href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html">BRE</a> — with few features other than grouping (<code>\(...\)</code>), quantifiers (<code>*</code> or <code>\{n,m\}</code>), bracket expressions and character classes — should still be pretty much compatible with Elisp regexp. However, the "Emacs flavor" isn't even the Elisp flavor. It's a <a href="https://www.gnu.org/software/findutils/manual/html_node/find_html/emacs-regular-expression-syntax.html">stripped version</a> specifically for findutils. In particular, there are <code>*</code>, <code>+</code> and <code>?</code> but no curly braces quantifiers, so gone is the dream of writing even just mildly complex regexps that are compatible with both BSD <code>find</code> and GNU findutils <code>find</code>. By the way, in case you wonder, the <a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/find.html">POSIX <code>find</code></a> doesn't even have a <code>-regex</code> primary/operator...</p> -<p>What a cruelly realistic world we live in.</p> -]]></content></entry><entry><title type="html">Spoiled by Retina, in less than a day</title><link href="http://archive.zhimingwang.org/blog/2015-12-16-spoiled-by-retina-in-less-than-a-day.html"/><updated>2015-12-16T21:10:08-08:00</updated><id>http://archive.zhimingwang.org/blog/2015-12-16-spoiled-by-retina-in-less-than-a-day.html</id><author><name>Zhiming Wang</name><uri>http://archive.zhimingwang.org/</uri><email>zmwangx@gmail.com</email></author><content type="html"><![CDATA[ - -<p>I finally got a 15'' Retina MacBook Pro this morning to replace my 13'' mid-2012 non-Retina MacBook Pro, whose spinning disk has been getting increasingly slower (or so I felt).<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-12-16-spoiled-by-retina-in-less-than-a-day.html#fn1" id="fnref1"><sup>1</sup></a> Apparently this is a pretty significant landmark in my personal computing history, since I'm saying goodbye to both spinning disk and non-Retina display on my primary computing device.</p> -<p>The transition was initially smooth except for a few things. First, as a tap-to-click wizard I immediately turned on tap-to-click, but I had a hard time dragging things because it was too easy to trigger a force touch instead on the medium setting, and under the firm setting I could hardly force touch at all; in the end I just turned off force touch altogether, and haven't had any problem since. By the way, I was initially worried about the keyboard too but it worked surprisingly well for me, so no complaints there. Secondly, <a href="http://archive.zhimingwang.org/blog/2015-08-31-after-all-these-years-10pt-non-anti-aliased-monaco-is-still-the-best.html">10pt non-anti-aliased Monaco</a> looks weird on Retina since it's no longer the beloved bitmap version. I turned on antialiasing and now it's no longer weird, but it felt totally different and I'm not sure if I like it (definitely not as much as the 10pt bitmap Monaco anyway). It's okay right now but I'll probably need to spend some time trying out different fonts. Obviously there are <a href="https://news.ycombinator.com/item?id=10140728">like-minded folks</a> out there. Sad story.</p> -<p>So much for first impressions. Apart from Monaco, everything felt great, until I returned home (I was doing setup away from home to get a less shitty connection) and connected my 27'' external monitor. Holy crap, I couldn't believe my eyes. The dock icons — the first things I saw before launching anything — looked <em>so blurry I couldn't stare at them for more than a few seconds</em>. That was after staring at the Retina display for less than five hours. Not to mention PDFs; they look ultra crisp on the Retina display and ultra crappy on non-Retina — especially in Preview, which is a problem I've been aware of since Yosemite.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-12-16-spoiled-by-retina-in-less-than-a-day.html#fn2" id="fnref2"><sup>2</sup></a> Moreover, the terminal font is more problematic than initially estimated — <em>now I have a retina display and a non-retina one side-by-side, yet I can only set one font for my default profile, which will never satisfy both</em>!<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-12-16-spoiled-by-retina-in-less-than-a-day.html#fn3" id="fnref3"><sup>3</sup></a> This is so awkward I can't think of a solution. One obvious approach is to ditch the blurry 27'' and only work from the Retina 15'', but should I really let the large canvas sit idle? No idea. Or should I get a 4K external display? First, a 4K display at 27'' still can't rival the pixel density of 2880x1800 at 15.4'' (Apple ships 5K at 27'' for a reason). Secondly and more importantly, I don't have the budget for such a thing after throwing money at an expensive 15'' rMBP (with 512 GB SSD)...</p> -<p>Transition periods are always awkward, I guess.</p> -<hr/> -<p><strong>12/17/2015 Update.</strong> After more than a full day's use, I actually quite love 10pt Monaco on a Retina display. I tried various fonts, including Menlo, Consolas and so on, but none of them has that whimsical feeling of Monaco. Hopefully the font is stuck now.</p> -<hr/> -<p><strong>12/28/2015 Update.</strong> A dozen days later, I can hardly look at 10pt Monaco on a non-Retina screen anymore, antialiased or not, especially not in bold. Mind blown.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>I haven't got the nerve to replace the hard drive myself, since it looks so much more complicated than upgrading the memory.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-12-16-spoiled-by-retina-in-less-than-a-day.html#fnref1">↩︎</a></p></li> -<li id="fn2"><p>PDFs looked so horrible in Preview (and TeXShop, my LaTeX previewer, which only serves a niche) that I often viewed them in browsers (!!), where text at least looks reasonable (on par with slightly blurry text elsewhere). PDF Expert came along and kind of made the situation better for non-Retina.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-12-16-spoiled-by-retina-in-less-than-a-day.html#fnref2">↩︎</a></p></li> -<li id="fn3"><p>Provided that I'll religiously stick to 10pt non-anti-aliased Monaco on non-Retina.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-12-16-spoiled-by-retina-in-less-than-a-day.html#fnref3">↩︎</a></p></li> -</ol> -</div> -]]></content></entry><entry><title type="html">Safeguarding git repos against accidental rm</title><link href="http://archive.zhimingwang.org/blog/2015-12-08-safeguarding-git-repos-against-accidental-rm.html"/><updated>2015-12-08T00:17:39-08:00</updated><id>http://archive.zhimingwang.org/blog/2015-12-08-safeguarding-git-repos-against-accidental-rm.html</id><author><name>Zhiming Wang</name><uri>http://archive.zhimingwang.org/</uri><email>zmwangx@gmail.com</email></author><content type="html"><![CDATA[ - -<p>Everyone who has spent a sizable portion of their life in terminals has experienced that "oh shit" moment: you realize what you've done immediately after you've hit enter, but it's already too late. And needlessly to say, many of those are associated to accidental <code>rm</code>s.</p> -<p>I just had one of those moments. I was going to delete a subdirectory of <code>~/.config</code>, but hit return prematurely, and the command line ended up being <code>rm -r ~/.config</code>. Imagine the horror one second later. Fortunately I was saved by the read-only objects in <code>.git</code>, which triggered prompts; however, damage was already done, to some extent. I had to reinit the repo and do a hard reset, and a corrupted submodule was in my way (it blocked my attempt of <code>git reset --hard</code>) which I eventually had to completely remove and re-add. In the end everything was recovered (hopefully) and back to normal, but this episode was definitely not great for heart health, which led me to rethink <code>rm</code>.</p> -<p>I've tried several safer <code>rm</code> solutions before. The first and obvious is to alias <code>rm</code> to <code>rm -i</code>, but having to answer dozens of prompts a day (or more) is agonizing and unproductive. I've also tried trashing, but a nonempty trash can makes me sick, so not for me either. I also used <code>safe-rm</code> for a couple of months, but without supplying my own blacklist (I have none to be blacklisted), I've never hit the default blacklist; apparently I'm not stupid enough to mess in system locations, so this won't really help much. Fortunately though, this time I might have found a very good solution for myself.</p> -<p>The idea is to protect all git repos. Git repos<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-12-08-safeguarding-git-repos-against-accidental-rm.html#fn1" id="fnref1"><sup>1</sup></a> are among the most valuable assets of programmers, and they have the nice property of not being completely removable without <code>-f</code> or <code>--force</code> (the work tree of a submodule, where <code>.git</code> is a regular file containing the relative path of the git dir, can be removed without <code>--force</code>, but we don't want to damage submodules anyway, so let's not single them out). It's unlikely that we would intend to remove a repo directory without specifying <code>-f</code> or <code>--force</code>, so let's just reject all such <code>rm</code> calls.</p> -<p>The wrapper is very easy to write. Here's one implementation for Zsh with support for both GNU coreutils and BSD <code>rm</code>.</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh"><span class="kw">rm</span> <span class="kw">()</span> <span class="kw">{</span> - <span class="kw">setopt</span> localoptions noshwordsplit noksharrays - <span class="kw">local</span> <span class="ot">args_backup</span> <span class="ot">force</span> <span class="ot">node</span> - <span class="kw">set</span> -A args_backup <span class="ot">$@</span> - <span class="kw">while</span> <span class="kw">:</span>; <span class="kw">do</span> - <span class="kw">case</span> <span class="ot">$1</span><span class="kw"> in</span> - --force<span class="kw">|</span>-*f*<span class="kw">)</span> <span class="ot">force=</span>1 <span class="kw">&&</span> <span class="kw">shift;;</span> - --<span class="kw">)</span> <span class="kw">shift</span> <span class="kw">&&</span> <span class="kw">break;;</span> - -*<span class="kw">)</span> <span class="kw">shift;;</span> - *<span class="kw">)</span> <span class="kw">break;;</span> - <span class="kw">esac</span> - <span class="kw">done</span> - <span class="kw">for</span> node; <span class="kw">do</span> - <span class="co"># -f, --force hasn't been specified && node is a git repo</span> - [[ -z <span class="ot">$force</span> <span class="kw">&&</span> -e <span class="ot">$node</span>/.git ]] <span class="kw">&&</span> <span class="kw">{</span> - <span class="kw">printf</span> <span class="st">"\e[31m'%s' is a git repo -- won't remove without the -f or --force option\e[0m\n"</span> <span class="ot">$node</span> - <span class="kw">return</span> 1 - <span class="kw">}</span> - <span class="kw">done</span> - <span class="kw">command</span> <span class="kw">rm</span> <span class="ot">$args_backup</span> -<span class="kw">}</span></code></pre></div> -<p>Personally, I stick it into a <a href="https://github.com/zmwangx/prezto/tree/master/modules/rm_guard">Prezto module</a> available from my fork. Hopefully it will serve me well this time round.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>In this article, "repo" stands for the work tree of a repo, unless otherwise noted; the actual repo with git objects is referred to as "git dir".<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-12-08-safeguarding-git-repos-against-accidental-rm.html#fnref1">↩︎</a></p></li> -</ol> -</div> -]]></content></entry><entry><title type="html">Bash function exporting fiasco</title><link href="http://archive.zhimingwang.org/blog/2015-11-25-bash-function-exporting-fiasco.html"/><updated>2015-11-25T15:38:13-08:00</updated><id>http://archive.zhimingwang.org/blog/2015-11-25-bash-function-exporting-fiasco.html</id><author><name>Zhiming Wang</name><uri>http://archive.zhimingwang.org/</uri><email>zmwangx@gmail.com</email></author><content type="html"><![CDATA[ - -<p>Bash is the only major shell (and the only shell that I know of) that implements function exporting. By now everyone should have heard of this feature, I suppose, after the publicity of Shellshock last year. I was personally introduced to it while writing parallel processing scripts <a href="https://www.gnu.org/software/parallel/parallel_tutorial.html#Transfer-environment-variables-and-functions">with GNU Parallel</a> (long before Shellshock), and it seemed useful and clever at that time. Back then I often wondered why it didn't make its way into Z shell. However, now that I'm much more seasoned in shell scripting, I can see why and how this feature is troubled and of debatable value.</p> -<p>Two problems lie at the heart of function exporting:</p> -<ol style="list-style-type: decimal"> -<li>As always, everything clever comes at a cost;</li> -<li>Code execution from untrusted source.</li> -</ol> -<p>Regarding the first problem, the cost of function exporting is to mess with the environment, in a very hackish way. The environment was designed to hold data, not code, and we're not in the utopia of Lisp; but bash forced its way through. Pre-shellshock, exported <code>func</code> was stored as <code>func=() {...</code> in env; post-shellshock, it was first <code>BASH_FUNC_func()=() {...</code> (which didn't entirely fix the issue), and then <code>BASH_FUNC_func%%=() {...</code>.</p> -<p>The second problem doesn't need much explanation — <em>shellshock it was</em>. It has been extensively documented elsewhere, so I'll just succinctly comment that to load exported functions into a subshell, function definitions have to be retrieved from the environment and executed (again because we're not in the utopia of Lisp<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-11-25-bash-function-exporting-fiasco.html#fn1" id="fnref1"><sup>1</sup></a>), and loading is done passively from the subshell user's point of view, hence the code execution bug(s). The bug(s) has(have) allegedly been fixed, but code execution (presumably with the appropriate safeguards now) still can't be avoided altogether, so just like a sanitized <code>eval</code>, it would still wake you up at night.</p> -<p>Well, if that's all I have to say, I wouldn't have started this post today. The thing that's bugging me is another issue I've found recently that's entirely avoidable, yet upon which we'll probably never see light ever after due to a combination of factors.</p> -<p>It started with <a href="http://stackoverflow.com/q/33819243/19447840">this question on SO</a>. While troubleshooting I quickly noticed that a Bash-emulated <code>sh</code> imports those <code>BASH_FUNC</code>s from the environment:</p> -<pre><code>> bash -c 'func () { echo "exported function loaded"; } && export -f func && ln -sf /bin/bash sh && ./sh -c func' -exported function loaded</code></pre> -<p>It gets worse when the function isn't Bourne shell compatible (e.g., when it uses process substitution):</p> -<pre><code>> bash -c 'func () { cat <(echo hello); } && export -f func && ln -sf /bin/bash sh && ./sh -c func' -cat: <(echo hello): No such file or directory</code></pre> -<p>That's surprising but not scary enough, because if you're not a fool you won't call <code>func</code> in <code>sh</code> anyway. However, if you're unfortunate enough to be dealing with <code>/bin/sh</code> on OS X (bash 3.2 under the hood, modified by Apple or not I'm not sure), then all hell break loose:</p> -<pre><code>> bash -c 'func () { cat <(echo hello); } && export -f func && /bin/sh -c :' # OS X only -/bin/sh: func: line 0: syntax error near unexpected token `(' -/bin/sh: func: line 0: `func () { cat <(echo hello)' -/bin/sh: error importing function definition for `func'</code></pre> -<p>Note that we're actively doing nothing in <code>sh</code>, yet we get all these syntax errors from loading <code>func</code>. This happens to every invocation of <code>sh</code>, and as you might expect, there are no shortage of programs that are either <code>sh</code> scripts (e.g., fasd) or have internal <code>sh</code> calls (e.g., GNU Parallel<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-11-25-bash-function-exporting-fiasco.html#fn2" id="fnref2"><sup>2</sup></a>). A single export of a Bourn shell incompatible function will haunt you through the entire session. Oops.</p> -<p>As I said, I don't know if the displayed error messages are due to Apple's modifications (anyone willing to look at the <a href="https://opensource.apple.com/source/bash/bash-97/">source code</a>?), since a symlink named <code>sh</code> to <code>/bin/bash</code> doesn't print error messages, but instead load the wrong function, which is almost as bad but less annoying to innocent users. At any rate, it's not even worth reporting, either to GNU or Apple, because we're stuck with bash 3.2 for <code>/bin/sh</code> forever (thank you GPLv3), and it takes a hell of a vulnerability like shellshock to get a small update out of Apple's hands. We can install newer shells to <code>/usr/local</code> as much as we'd like to, but <code>/bin/sh</code> is simply the final word for many tasks involving the shell. Yet it's stained by this troubled bash-specific feature, and it's not going anywhere. So sad.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>I'm not commenting on the security of Lisp.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-11-25-bash-function-exporting-fiasco.html#fnref1">↩︎</a></p></li> -<li id="fn2"><p><strong>04/14/2015 Update.</strong> GNU Parallel is no longer haunted by this issue since <a href="http://git.savannah.gnu.org/cgit/parallel.git/commit/?id=3d919c6cd427e9615f56f260eb959a44d5d32c18"><code>3d919c6</code></a>.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-11-25-bash-function-exporting-fiasco.html#fnref2">↩︎</a></p></li> -</ol> -</div> -]]></content></entry><entry><title type="html">We need a programming keyboard on iOS</title><link href="http://archive.zhimingwang.org/blog/2015-11-15-we-need-a-programming-keyboard-on-ios.html"/><updated>2015-11-15T02:17:05-08:00</updated><id>http://archive.zhimingwang.org/blog/2015-11-15-we-need-a-programming-keyboard-on-ios.html</id><author><name>Zhiming Wang</name><uri>http://archive.zhimingwang.org/</uri><email>zmwangx@gmail.com</email></author><content type="html"><![CDATA[ - -<p>We do. If you ever tried to say something on GitHub (web) or StackOverflow (web or app) on iOS, you'll probably agree with me. The stock keyboard (or any third party keyboard that I've heard of) is simply awful at this. Typing on iOS software keyboard is unpleasant enough to begin with, but behold:</p> -<ul> -<li>Auto"correct" messes up everything as fast as you can type, which isn't really fast anyway; might as well call it autorot.</li> -<li>The backtick is a click plus a loooong click (on the single quote key) plus another click away. Good luck typing code in Markdown,<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-11-15-we-need-a-programming-keyboard-on-ios.html#fn1" id="fnref1"><sup>1</sup></a> especially if you use GFM fenced code block like all of us do.</li> -<li>Brackets, curly braces, the underscore, the pound, etc. are all three clicks away.</li> -</ul> -<p>The solution is pretty obvious actually. I don't know about smaller phones, but the software keyboard on a landscape iPhone 6 Plus has four rows, which takes up about 40% of vertical screen estate, and it has fourteen keys in the top row. With a little bit of effort it can be made into a five-row, full-sized keyboard (without arrow keys perhaps) without taking up a ridiculous amount of space. Since the horizontal 6 Plus could handle it, any iPad should be able to handle it too; definitely shouldn't be an iPad Pro-only luxury. Turn off autocorrect on top of that, and you get a decent programming (or better put, programmer-oriented) keyboard.</p> -<p>This is merely a rant, but it would awesome if anyone sets out to make one.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>To be fair, typing BBCode is even worse. Unfortunately that's what Ars Technica use, and I've given up on commenting there.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-11-15-we-need-a-programming-keyboard-on-ios.html#fnref1">↩︎</a></p></li> -</ol> -</div> -]]></content></entry></feed> diff --git a/build/blog/2014-10-20-hello-octopress.html b/build/blog/2014-10-20-hello-octopress.html deleted file mode 100644 index 888c7b6a..00000000 --- a/build/blog/2014-10-20-hello-octopress.html +++ /dev/null @@ -1,59 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-10-20T16:53:00-0700" name="date"/> -<title>Hello, Octopress!</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/highlight.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Hello, Octopress!</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-10-20T16:53:00-0700">October 20, 2014</time> -</div> -</header> -<p>This post marks my transition from Tumblr to Octopress & GitHub Pages.</p> -<p>I've been microblogging for a while at <a href="http://zshello3.tumblr.com">zshello3.tumblr.com</a> and I liked it. Not because of readers, which I suspect I have none; but there are certainly a huge amount of information I want to dump off my mind. Back in the days I <em>loved</em> my handwritten journals, and I really poured a lot into them. Peers were usually amazed when they saw my journals. These days typing seems to be a more robust solution to keeping my thoughts, especially when the thoughts are mostly technical.</p> -<p>Tumblr is awesome. Compared to WordPress (.com for pedantic people), it is both lightweight and beautiful (you get all the customization for free), so you quickly get to the writing. However, it is not designed for geeks, so</p> -<ul> -<li>Customization is capped at some point;</li> -<li>I had the impression that the Markdown parser is herrendous;</li> -<li>Email publishing is a mightmare, by the way;</li> -<li>Code rendering always falls short — unless I spend a lot of time customizing (I'm pretty bad at HTML, CSS, and JS stuff).</li> -</ul> -<p>Speaking of the last point, I've always been envious of the beautiful code blocks found on Octopress blogs. So here I come!</p> -<p>(Let me give it a try first.)</p> -<div class="sourceCode"><pre class="sourceCode c"><code class="sourceCode c"><span class="pp">#include </span><span class="im"><stdio.h></span> - -<span class="dt">int</span> main(<span class="dt">int</span> argc, <span class="dt">char</span> **argv) { - printf(<span class="st">"Hello, Octopress!</span><span class="sc">\n</span><span class="st">"</span>) -}</code></pre></div> -<p>Gorgeous. I'll get to the theme customization later. I'm actually busy as crazy this week.</p> -<p>Before I close this post, let me also try to embed a random gist I authored yesterday (for brewing):</p> -<pre><code>{% gist 828fd00bdecd6611cf40 brew.sh %}</code></pre> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-10-20-help-mou-hit-1-dot-0.html b/build/blog/2014-10-20-help-mou-hit-1-dot-0.html deleted file mode 100644 index 076f18d5..00000000 --- a/build/blog/2014-10-20-help-mou-hit-1-dot-0.html +++ /dev/null @@ -1,42 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-10-20T17:37:45-0700" name="date"/> -<title>Help Mou hit 1.0</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Help Mou hit 1.0</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-10-20T17:37:45-0700">October 20, 2014</time> -</div> -</header> -<p>Quick call for <a href="https://www.indiegogo.com/projects/mou-1-0-markdown-editor-on-os-x-for-you">Mou 1.0 fundraiser</a> on Indiegogo. At the time of writing, it has raised $6,178/$20,000, and has 39 days to go (with 21 already passed).</p> -<p>I'm actually writing this post in Mou right now. It's far less powerful than Emacs, but when I want preview-on-the-fly, Mou is the Markdown editor to go. Right now it's far from perfect; for instance, GFM fenced blocks (now included in <a href="http://commonmark.org">CommonMark</a>) are not supported, so you get nonsense preview when your code block is fenced rather than indented. (Of course, Mou is even less suitable for editing an Octopress post due to the yaml metadata upfront, but that's not a big deal.)</p> -<p>Let's hope for Mou hitting the 1.0 mark.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-10-21-get-rolling.html b/build/blog/2014-10-21-get-rolling.html deleted file mode 100644 index 0b86713c..00000000 --- a/build/blog/2014-10-21-get-rolling.html +++ /dev/null @@ -1,59 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-10-21T11:40:14-0700" name="date"/> -<title>Get rolling</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Get rolling</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-10-21T11:40:14-0700">October 21, 2014</time> -</div> -</header> -<p>Yesterday, on an internet forum, I saw someone’s signature, which translates to</p> -<blockquote> -<p>Don’t even get started if you know you can't know from the beginning that you won't make it to the very end.</p> -</blockquote> -<p>This seems justified — persistence is the key to success; why even bother if you know you’ll fail? However, I have to profoundly disagree with this, and even dedicate a blog post to discussing this problem.</p> -<p>The problem here is, the real world is much more complicated than the idealized world found in various quotes about persistence. Most of the time you have absolutely no clue where which road is leading, unless you embark on the journey, clueless. As for me, fortunately I knew I was gonna be a mathematician/physicist ever since elementary school, so the roadmap is sorta clear on the grand scale. Still, all those tiny building blocks for the ultimate goal are confusing, and even more so for things hardly related to the ultimate goal, for instance, coding, which is just a hobby and a way to simplify life — it has simplified my life in some sense, but has itself complicated my life in other ways (your life inevitably becomes more complicated when you know more and want to find out even more).</p> -<p>And sometimes you are bound to fail — I know my code is shitty, for instance, but if I don’t get rolling, I won’t even have a working (albeit shitty) version that barely meets my needs. As another example, I was looking for a way to share and archive some photos. I started with <a href="http://apinkarchive.wordpress.com/">WordPress</a>, which turned out to be more formal and tiring than I’d thought. Then I ran a <a href="http://chorongmemories.tumblr.com/">Tumblr microblog</a>, which was great, but has certain limitations that in the end prevents it from being damn useful for myself, so in the end I went onto “indefinite hiatus.” In both cases I never declared that the thing was permanent — I was careful to say that the blogs were experimental, and I moved on when I found something better, or when they were no longer helping me. Yesterday I started yet another experiment, a <a href="http://apinkpcr.tistory.com">Tistory blog</a>. It is a random move triggered by something unexpected; the South Korean blogging platform is not that great, but at least it provides acceptable API access, and more importantly, I’ve got complete infrastructure built around the API to scrape photos, so it’s easy to build on top of that to automate things. It is also experimental. Again I’m not sure I long I can keep it up, but at least I’m happy with it for the time being. Being happy at the time being is the most important goal for hobbies.</p> -<p>Choices are hard. Especially in today’s world, tools in every discipline are constantly improving, be it math, physics, programming, photography, blogging, or whatever. If you research over and over until you find “the perfect tool”, or “the perfect platform” (hint: the rank is constantly changing), you’re stuck on the first step to anywhere. In fact, reading other people’s blogs, for example, are not enough to learn what is the best — you need to at least have some working knowledge to even decide which tool or platform is more suitable for you. Therefore, the most sensible thing to do is to do a little bit of research (combined with your gut feeling), pick up something that makes you feel good at the moment, and immediately get rolling. Well, of course you need some research, otherwise you’re just kidding yourself; doing <code>>>> import this</code> in python tells you:</p> -<blockquote> -<p>Now is better than never.<br/> Although never is often better than <em>right</em> now.</p> -</blockquote> -<p>Then, when you have more experience and know what’s wrong with your original choice, correct it or trash it. There’s nothing wrong with abandoning dated crap, hopping bandwagons, or whatever; that’s the nature of change and improvement, and the most sensible thing for someone as busy as you are.</p> -<p>Up till now I've been talking about tools and platforms, so maybe it seems that I'm attacking the straw man — you may argue that the original quote is not about what tools or platforms you use, but rather, what you try to accomplish with the tools or platforms. Okay, what about the grander things in life, like mathematical research, like <em>the final theory</em>? Well, similar. I’ll quote Ravi here,</p> -<blockquote> -<p>…mathematics is so rich and infinite that it is impossible to learn it systematically, and if you wait to master one topic before moving on to the next, you’ll never get anywhere. Instead, you’ll have tendrils of knowledge extending far from your comfort zone. Then you can later backfill from these tendrils, and extend your comfort zone; this is much easier to do than learning “forwards”.</p> -</blockquote> -<p>Ravi is always hinting at “you should get started with actual research rather than ‘prepare’ yourself”! I can’t reckon that since I’ve yet to follow Ravi’s advice, but the thinking here is crystal clear. <strong>You shouldn’t be afraid of failure; you shouldn’t be afraid of being “not prepared enough”; you shouldn’t be afraid of getting started.</strong> Speaking of a final theory, I’m pretty sure I’m bound to fail, I’m pretty sure I won’t see a satisfactory one in my lifetime — the inconvenient truth is that, I have the gut feeling that the ultimate explanation is unfortunately intertwined with consciousness, and we are still far from having the right tools to understand consciousness. According to Feynman, <strong>really knowing something is hard</strong>. It’s hard, so failure is not shameful at all. Those who won’t even get started due to fear of failing or making the wrong choice won’t fail again, since they’ve already failed at the very beginning. So, get rolling.</p> -<p>Yesterday I read <a href="http://www.joelonsoftware.com/articles/fog0000000339.html">Fire and Motion</a> on <em>Joel on Software</em>. Joel’s metaphor is really nice, but he’s essentially conveying very similar ideas.</p> -<hr/> -<p>By the way, I wrote this post in Emacs. I don’t know why but I seem to type much faster in Emacs than in Mou. (For Markdown editing <code>markdown-mode</code>, and <code>typo-mode</code>, a minor mode I found today which is useful for inserting smart quotes and smart dashes seamlessly into md articles).</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-10-23-ripping-copy-protected-dvd-with-mpv.html b/build/blog/2014-10-23-ripping-copy-protected-dvd-with-mpv.html deleted file mode 100644 index db6664f0..00000000 --- a/build/blog/2014-10-23-ripping-copy-protected-dvd-with-mpv.html +++ /dev/null @@ -1,57 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-10-23T20:03:22-0700" name="date"/> -<title>Ripping copy-protected DVD with mpv</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Ripping copy-protected DVD with mpv</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-10-23T20:03:22-0700">October 23, 2014</time> -</div> -</header> -<p><strong><em>11/02/2014 update:</em></strong></p> -<p>See <a href="/blog/2014-11-02-vobcopy-dvdbackup-etc.html">this post</a> for issues, explanations, and more.</p> -<hr/> -<p><strong><em>10/25/2014 update:</em></strong></p> -<p>I'm such an idiot. <code>vobcopy</code> is the real, hassel-free way to go.</p> -<pre><code>brew install vobcopy</code></pre> -<p>Then, with the DVD mounted,</p> -<blockquote> -<p><strong>vobcopy</strong> without any options will copy the title with the most chapters into files of 2GB size into the current working directory.</p> -</blockquote> -<p>Of course there are a ton of options, but I generally hate to browse through options unless I have to, so I'm happy with calling without argument.</p> -<hr/> -<p>Yesterday I was trying to rip a music video off a newly released DVD from Japan. I knew very little about how DRM (in this case, CSS) actually works and how to break it. I tried to operate directly on the VOB file with <code>ffmpeg</code> or <code>mpv</code> but both failed with a lot of header errors — I suppose more files than the VOB are required for authentication? Whatever, maybe I’ll learn the details in the future, but I don’t see the need since DVD is an outdated technology anyway.</p> -<p>So, can we proceed from here? Most certainly. I noticed that although <code>mpv</code> won’t let me play a single VOB, I can simply hand it the DVD mount point, and it will play the whole DVD seamlessly. <strong>Caution:</strong> <code>mpv</code> needs to be compiled with <code>libdvdnav</code> and <code>libdvdread</code>! With brew you just do</p> -<pre><code>brew install mpv --with-libdvdnav --with-libdvdread</code></pre> -<p>For better performance and backup, I first cloned the DVD into a <code>.cdr</code> image (DVD/CD-R Master Image) using Disk Utility (I've never tried creating/cloning image with <code>diskutil</code> CLI, so nothing to report on that). Then I mount the image, say the mount point is <code>/Volumes/UPBX_80165</code>. As said I can hand that mount point to <code>mpv</code> and it simply works, but how about extracting the MPEG-2 video stream? The <code>--stream-capture=<filename></code> option is there just for you. In principle <code>--stream-dump=<filename></code> should also work, but without monitoring the output and controlling where to end, I’m not sure if it will ever terminate itself when reading from a DVD (when I stream captured the DVD it just kept repeating itself until I explicitly quit with <code>q</code>). So that's it:</p> -<pre><code>mpv --stream-capture=dump.mpg /Volumes/UPBX_80165</code></pre> -<p>Then you can torture the <code>dump.mpg</code> with <code>ffmpeg</code> however you want. The most obvious thing is to cut out the music video part, and put into a new container like MPEG-TS. Or transcode it to H.264 for your iPhone. The nice thing about <code>dump.mpg</code> is that, unless I got it wrong, there's no quality loss here — the only thing you got rid of is that goddamn DRM.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-10-24-charles-munger-donated-$65m-to-kitp.html b/build/blog/2014-10-24-charles-munger-donated-$65m-to-kitp.html deleted file mode 100644 index d4d0e5ea..00000000 --- a/build/blog/2014-10-24-charles-munger-donated-$65m-to-kitp.html +++ /dev/null @@ -1,53 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-10-24T16:41:36-0700" name="date"/> -<title>Charles Munger donated $65M to KITP</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Charles Munger donated $65M to KITP</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-10-24T16:41:36-0700">October 24, 2014</time> -</div> -</header> -<p>Today's news has it that Charles Munger made a $65 million donation to KITP at UCSB. See for instance <a href="http://nyti.ms/1D4zg24">this article</a> on NYT. Of course I didn't learn it from NYT (I'm generally sick of any news other than math, physics, or IT-related ones). I learned it from <a href="http://www.math.columbia.edu/~woit/wordpress/?p=7247">Not Even Wrong</a> instead (of course I don't agree with Woit, but some of his links are nice).</p> -<p>I have no interest whatsoever in the business world, so I have no idea about Warren Buffett's business partners (although I'm still worldly enough to know Warren Buffett). However, the name Charles Munger sounded surprisingly familiar. After reading the sentence</p> -<blockquote> -<p>Mr. Munger has frequently donated big sums to schools like Stanford and the Harvard-Westlake School.</p> -</blockquote> -<p>from the NYT article linked above, it finally hit me that Mr. Munger is the donor of the Munger Graduate Residence here at Stanford. Munger is really nice, much better than our undergrad residences AFAIK (location-wise Roble is still unbeatable for mathematicians and physicists, although Munger still kicks EV's ass).</p> -<p>I'm glad to see more and more entrepreneurs funding physics, especially theoretical physics, whether they understand it or not. (<strong>Aside:</strong> Even for laypeople theoretical physics is cool isn't it, like the coolest kid in class. I won't comment on whether math is cooler, but breakthrough mathematical work certainly go largely unnoticed in the public, since theoretical physics is the last thing that laypeople can "vaguely understand". Do some name searches on Google to see how math and physics play out in the limelight — hint:</p> -<ul> -<li>Gauss — 4,130,000 results;</li> -<li>Euler — 855,000 results;</li> -<li>Newton — 13,200,000 results;</li> -<li>Einstein — 6,330,000 results.</li> -</ul> -<p>End of aside.) Engaging in physics is plain better than engaging in some questionable philanthropy. (Have you heard that Gates Foundation invested in G4S, the largest private military and security company in the world? I’m not sure about the details — I once read that off a bathroom flyer — but that’s definitely interesting philanthropy.)</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-10-25-os-x-package-receipts.html b/build/blog/2014-10-25-os-x-package-receipts.html deleted file mode 100644 index 863156ab..00000000 --- a/build/blog/2014-10-25-os-x-package-receipts.html +++ /dev/null @@ -1,48 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-10-25T13:26:02-0700" name="date"/> -<title>OS X package receipts</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">OS X package receipts</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-10-25T13:26:02-0700">October 25, 2014</time> -</div> -</header> -<p>I just learned something new. Whenever you install a <code>pkg</code> on OS X, OS X stores a receipt of what was installed in <code>/var/db/receipts</code> (I'm running OS X 10.9.5 at the time of writing), called a <strong>bom</strong> — bill of materials (I’d rather call it a manifest, whatever). This feature was introduced in NeXTSTEP. From <code>man 5 bom</code>:</p> -<blockquote> -<p>The Mac OS X Installer uses a file system "bill of materials" to determine which files to install, remove, or upgrade. A bill of materials, <strong>bom</strong>, contains all the files within a directory, along with some information about each file. File information includes: the file's UNIX permissions, its owner and group, its size, its time of last modification, and so on. Also included are a checksum of each file and information about hard links.</p> -</blockquote> -<p><code>man 5 bom</code> is actually badly maintained, as it says "The bill of materials for installed packages are found within the package receipts located in /Library/Receipts," whereas those have been migrated to <code>/var/db/receipts</code> a long time ago.</p> -<p><code>.bom</code> files are binary, but you can access the contents via <code>lsbom</code>. For instance, to list the files installed,</p> -<pre><code>lsbom -f /var/db/receipts/org.macports.MacPorts.bom</code></pre> -<p>Note that the paths printed are always relative to <code>/</code>. See <code>man 1 lsbom</code> for detailed option listing.</p> -<p>(Beware when you try to clean up unwanted packages using the <code>lsbom</code> listing. Packages might overwrite files, so make sure you review the listing first and know what you are doing. "Knowing what you are doing" is the prerequisite for using <code>sudo</code> anyway.)</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-10-26-audio-cd-slash-dvd-to-iso-image-on-os-x.html b/build/blog/2014-10-26-audio-cd-slash-dvd-to-iso-image-on-os-x.html deleted file mode 100644 index 310368c2..00000000 --- a/build/blog/2014-10-26-audio-cd-slash-dvd-to-iso-image-on-os-x.html +++ /dev/null @@ -1,51 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-10-26T23:29:47-0700" name="date"/> -<title>Convert Audio CD/DVD to ISO image on OS X</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Convert Audio CD/DVD to ISO image on OS X</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-10-26T23:29:47-0700">October 26, 2014</time> -</div> -</header> -<p><strong><em>11/02/2014 update:</em></strong></p> -<p>See <a href="/blog/2014-11-02-vobcopy-dvdbackup-etc.html">this post</a> for issues, explanations, and more.</p> -<hr/> -<p>Today it occurred to me that I should make clones of my audio CDs (as stand-alone ISO images, I mean, not just rsyncing the AIFFs to subdirectories in <code>~/aud/lossless</code>). One can never have too many backups.</p> -<p>Of course I could simply pack the aforementioned directories with AIFFs into ISOs — that’s not impressive. The end result might actually be the same, but I want to make the clones directly from the original CDs. It turns out that this is not so simple with the Disk Utility GUI — unlike DVDs, the “New Image” option is grayed out for Audio CDs. I’m not sure why, but maybe they want you to just use iTunes to deal with Audio CDs (which works well for all practical purposes — but theoretical curiosity never ends).</p> -<p>So there comes <code>hdiutil</code>. <code>hdiutil</code> and <code>diskutil</code> are the utilities underlying Disk Utility. Unfortunately, so far I know little about them except for simplest things like <code>diskutil list</code>, <code>diskutil mount</code>, <code>hdiutil attach -stdinpass</code>, etc. (I'm so ignorant about anything filesystem related!) The <code>hdiutil</code> verb that makes cross-platform CD or DVD is <code>makehybrid</code>, which supports the following filesystem options: <code>-hfs</code> (holy crap, no HFS+ please! Apple ought to replace this thirty-year-old filesystem — ZFS or something better please!), <code>-iso</code>, <code>-joliet</code>, and <code>-udf</code>. For Audio CDs you use <code>-iso</code> and with <code>-joliet</code> extension:</p> -<pre><code>hdiutil makehybrid -iso -joliet -o AUDIO_CD_NAME.iso SOURCE</code></pre> -<p>where <code>SOURCE</code> can be the mount point, the disk device file, etc. Similarly, although you can create <code>.cdr</code> images from DVDs via the Disk Utility GUI, you can also do it with <code>hdiutil</code> (which is potentially more portable — I’ve never heard a definitive answer of whether renaming <code>.cdr</code> to <code>.iso</code> really cross-platform):</p> -<pre><code>hdiutil makehybrid -udf -o DVD_NAME.iso SOURCE</code></pre> -<p>This way CSS keys <em>seem</em> to be cloned as well, since I was able to authenticate such a CSS-protected DVD with <code>libdvdread</code>.</p> -<hr/> -<p>P.S. I sincerely hope that one day lossless music tracks are no longer distributed through CD-ROMs. So painful — even my Internet speed is more than ten times faster than the <a href="https://en.wikipedia.org/wiki/CD-ROM#Transfer_rates">highest transfer rate</a> available from any CD-ROM. (I’ve heard about some websites distributing lossless music digitally, but that won’t happen to the music I care about in the near future.) I still like physical albums though — a real sense of possession. Maybe they should contain the physical goodies and some sort of access codes?</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-10-26-disk-visualizer-daisydisk.html b/build/blog/2014-10-26-disk-visualizer-daisydisk.html deleted file mode 100644 index 65700f36..00000000 --- a/build/blog/2014-10-26-disk-visualizer-daisydisk.html +++ /dev/null @@ -1,48 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-10-26T00:02:22-0700" name="date"/> -<title>Disk visualizer: DaisyDisk</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Disk visualizer: DaisyDisk</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-10-26T00:02:22-0700">October 26, 2014</time> -</div> -</header> -<p>DaisyDisk is a pretty famous name. I’ve heard a lot that DaisyDisk is beautiful, but as a “power user” I always feel ashamed about using a disk analyzer or visualizer (although no one really cares). I’m pretty comfortable with doing most filesystem operations right in the shell, and for other tasks too tedious for the shell (like renaming a bunch of files with no obvious pattern), Finder (equipped with TotalFinder) works just fine.</p> -<p>Today I was trying clean up my drive a bit, as there were only 22GB left. I knew where the main problem lied: a huge number of highres videos lying in <code>~/vid/staging</code>, awaiting renaming and migration to my external drive. Anyway, it would be nice to have some visualization of a detailed breakdown of my disk usage, preferably on any level I want without multiple passes of <code>du</code>. The name DaisyDisk popped up from the cache in my brain, so I headed over to their website to download it.</p> -<p>The result is not disappointing at all. Look at this:</p> -<div class="figure"> -<a href="https://i.imgur.com/vyIwSNQ.png" target="_blank"><img alt="DaisyDisk screen shot" src="https://i.imgur.com/vyIwSNQ.png"/></a> -<p class="caption">DaisyDisk screen shot</p> -</div> -<p>Beautiful. Moreover, functional. It indeed gives me a detailed breakdown on any level, within any directory (given enough priviledge). I can also collect items I don’t want and let DaisyDisk clean up for me at once (not surprising for a disk analyzer); this feature isn’t that useful for me since I know exactly where my queues of unorganized items are — <code>~/Downloads</code>, <code>~/aud/staging</code>, <code>~/img/staging</code>, and <code>~/vid/staging</code>.</p> -<p>By the way, DaisyDisk seems to be WinRAR-free. (Rest assured; I’m a good guy and I <em>will</em> purchase a license — these days whether to purchase the website or the MAS version is a headache, though.)</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-10-27-onedrive-goes-unlimited.html b/build/blog/2014-10-27-onedrive-goes-unlimited.html deleted file mode 100644 index def63ae4..00000000 --- a/build/blog/2014-10-27-onedrive-goes-unlimited.html +++ /dev/null @@ -1,50 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-10-27T09:44:51-0700" name="date"/> -<title>OneDrive goes unlimited</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">OneDrive goes unlimited</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-10-27T09:44:51-0700">October 27, 2014</time> -</div> -</header> -<p><strong>10/28/2014 Update:</strong></p> -<p>Yesterday Microsoft pushed an update to OneDrive.app to MAS. After uninstalling, reinstalling, and wiping the 10 GB folder I'd like to sync (that's for photos; I upload videos via the web interface) on both client and server sides, it actually began to work. The speed was around 1 MB/s during my last sync of 10 GB worth of data. Not fast, but I will be fairly satisfied if it can keep up with that speed. Time will tell.</p> -<hr/> -<p>The OneDrive team just <a href="https://blog.onedrive.com/office-365-onedrive-unlimited-storage/">announced on their blog</a> that</p> -<blockquote> -<p>Today, storage limits just became a thing of the past with Office 365. Moving forward, all Office 365 customers will get unlimited OneDrive storage at no additional cost.</p> -</blockquote> -<p>Hell, I hate Microsoft, but <strong>I have to say that this is big</strong>. OneDrive might not be the first to offer unlimited cloud storage (not sure), but it is certainly the first one to roll it out on such a grand scale. Remember, Office 365 is just $99.99 a year. OneDrive might not be the best cloud storage service, especially for OS X customers, but unlimited is unlimited — in comparison, I pay Google $9.99 a month for 1 TB.</p> -<p>Microsoft products are indeed pure crap on a Mac. Office for Mac 2011 is horrible (speed and bloat aside, some features are simply not implemented — try to import a UTF-8 CSV into Excel, all non-ASCII characters become underscores; Microsoft’s response was that Unicode import was not implemented yet). OneDrive.app is slow like crawl, and it never finishes syncing — always stuck on the last few megabytes, eating up 100% CPU. Thank god I only use it for backups. The web interface is okay, although Google Drive is faster — blazing fast, I can easily upload with 20+MB/s. But again, <strong>unlimited is unlimited.</strong></p> -<p>Microsoft is opening a new chapter of cloud storage. In today’s world, we have so many huge video files, so storage limit should indeed be something of the past. This is a smart move for Microsoft — when you have, say, 100 TB up there (which seems very far at this moment, but what if all contents go 4K), and if competitors don’t offer comparable plans, then you are stuck with Microsoft. And Office. Oh my god, Microsoft Office must die.</p> -<p>Of course I don’t want to be stuck with Microsoft, so I’m looking at how Google and Apple will handle this. Google ought to offer more affordable plans, preferably also unlimited. (My 1Password still has it that I purchased Office for Mac University 2011 on Nov 12, 2012 for $99.99. That turned into a free 4-year Office 365 subscription, which contains 60 world minutes of Skype per month, 1 TB of OneDrive — oh, now it’s about to go unlimited. All for $99.99. In comparison, Google charges me $119.88 per year.) Apple wants you to save everything to iCloud, and it introduced iCloud Drive and Cloud Kit this year — but plans still start at 5 GB and tops out at 1 TB, seriously? Dude, you sell top notch hardware with huge profits; why don’t you pay your customers back by offering better cloud storage — that’s also better for iCloud.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-10-28-google-drive-no-selective-subfolder-sync.html b/build/blog/2014-10-28-google-drive-no-selective-subfolder-sync.html deleted file mode 100644 index bec8ebd5..00000000 --- a/build/blog/2014-10-28-google-drive-no-selective-subfolder-sync.html +++ /dev/null @@ -1,63 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-10-28T20:49:24-0700" name="date"/> -<title>Google Drive — no selective subfolder sync?</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Google Drive — no selective subfolder sync?</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-10-28T20:49:24-0700">October 28, 2014</time> -</div> -</header> -<p>Up to this point I've been using Google Drive as an online backup service, and uploads files mostly manually, although I do sync <code>~/img</code> with the client.</p> -<p><strong>Aside.</strong> Google Drive, OneDrive, etc. don't work with symlinks. Wanna keep your stuff free and duplicate-free yet still synced to the servers? Use <code>rsync</code> to automatically reproduce your folder structure with hard links:</p> -<pre><code>rsync -avzP --delete --link-dest=SOURCE/ SOURCE DESTINATION</code></pre> -<p>e.g.,</p> -<pre><code>rsync -avzP --delete --link-dest=~/img/ ~/img/ ~/sync/GoogleDrive/img/</code></pre> -<p>automatically reproduces my <code>~/img</code> in the <code>img</code> directory under Google Drive's root, yet every file in the <code>~/img</code> tree is replaced by hard links to the original file, so the new structure within Google Drive takes little additional space — for the directories only.</p> -<p>That doesn't solve every problem though, as you will see shortly. <em>End of aside.</em></p> -<p>So, up to this point I’ve mostly used Google Drive as an online backup service by manually uploading (huge) stuff. But at some point I’m gonna automate parts of the uploading. As it turns out, I can keep some smaller video files on my hard drive; other bigger monsters (like movies, TV shows, etc., especially a lot of 1080i Transport Streams directly from TV broadcasts) are uploaded and then moved to external drives. Some of the smaller files, including things downloaded from YouTube, live in <code>~/vid/etc</code>, and I want to sync this folder to Google Drive. What's shocking is that this is not possible with the Google Drive client — it only allows selective syncing of the top level folders. Let me repeat this:</p> -<p><strong>The Google Drive client only allows selective syncing of the <em>top level folders</em>.</strong></p> -<p>This is <em>insane</em>. It’s almost 2015. Everyone supports this — Dropbox, Microsoft, Box, even Baidu. Google Drive launched on April 24, 2012, that’s 2.5 years ago. <a href="https://productforums.google.com/forum/#!topic/drive/Gs2w1BL-B9U">This thread</a> on Google Drive Forum, “Ability to sync only selected sub folders”, was posted on August 27, 2012, and has garnered 139 replies. They are ignored by the developers, and the accepted “answer” is to utilize Google Drive’s assign-one-file/folder-to-multiple-folders feature to create a special “sync” directory. Okay, that’s a stupid hard link solution on the server side. Okay, if that works… <em>No</em>. “Hard links on the server side” cannot bear different names; so what if I want to sync, say, both <code>vid/etc</code> and <code>aud/etc</code>? Whoops. So I also have to do all sorts of ugly renaming. NO, GOOGLE, NO, I won't accept that much trouble.</p> -<p>This kind of insanity makes me wander:</p> -<p><strong>Do the Google Drive developers use Google Drive themselves?</strong></p> -<p>For now I'm moving <code>vid/etc</code> to <code>vid_etc</code>. Sigh.</p> -<hr/> -<p>There are other problems that I encountered with Google Drive sync today. For one thing, it rejects what I already have and insists on starting from scratch. I mean, say I have uploaded a folder via the web interface, and later wants to keep it in sync (of course that's only possible if it's top level), so I put what I already have there. Nope, Google Drive reports that as a conflict and insists on downloading all the stuff again. Apart from wasted traffic, that also ruins my hard links, so I have to either wipe everything clean on the server side and reupload, or redownload everything and redo all the hard-linking after the download finishes. Either way, very annoying. I opted for the first one. (I later empirically confirmed that OneDrive could handle this situation.)</p> -<p>There are other problems that don't pop right off my mind. Anyway, the gist is,</p> -<p><strong>Google Drive is not yet sync-ready for power users (maybe even laymen).</strong></p> -<hr/> -<p>Then, is OneDrive perfect? No. I know it recently went unlimited, but there’s one major annoyance: the speed. Stanford’s Ethernet speed is almost 1 Gbps UL/DL, but the OneDrive client tops out at about 2 MBps. The web interface isn’t much better. Google Drive is a lot faster than that, which makes it a good backup service for manual uploading. Anyway, maybe OneDrive will improve over time; yesterday they delivered an update to OneDrive.app, and at least it finally works.</p> -<p>OneDrive also boasts no file status indicators on OS X, which everyone else in the industry has. That’s not a show-stopper though, if you just use it as a backup service.</p> -<hr/> -<p>What about Dropbox? Dropbox is a truly awesome sync-ready service, but it is at the same time pretty expensive compared to others. Also, since I use Dropbox as a sync service, it must be up at all times and constantly indexing, so I’m really cautious with what I put there to avoid unnecessary cycles and startup time.</p> -<hr/> -<p>Everything is broken in one way or another. Sigh. Let's hope that OneDrive improves a lot in the coming months; if it's stable enough and the speed gets some boost, I'll cancel my Google Drive subscription. I am a Google supporter and Microsoft hater, but a service that <em>works</em> is more important than ideology.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-10-28-mou-1-dot-0-fundraiser-goal-reached.html b/build/blog/2014-10-28-mou-1-dot-0-fundraiser-goal-reached.html deleted file mode 100644 index 4c9f2bce..00000000 --- a/build/blog/2014-10-28-mou-1-dot-0-fundraiser-goal-reached.html +++ /dev/null @@ -1,50 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-10-28T01:57:06-0700" name="date"/> -<title>Mou 1.0 fundraiser: goal reached</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Mou 1.0 fundraiser: goal reached</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-10-28T01:57:06-0700">October 28, 2014</time> -</div> -</header> -<p>A week ago I wrote a post <a href="/blog/2014-10-20-help-mou-hit-1-dot-0.html"><em>Help Mou hit 1.0</em></a>. Today, I'm delighted to find out that Mou has reached its goal, $20,000, half way into the fundraiser.</p> -<div class="figure"> -<a href="https://i.imgur.com/vM298t5.png" target="_blank"><img alt="Mou hit its goal on Indiegogo" src="https://i.imgur.com/vM298t5.png"/></a> -<p class="caption">Mou hit its goal on Indiegogo</p> -</div> -<p>So what do I expect from 1.0? Most importantly,</p> -<ul> -<li>CommonMark support, especially GFM fenced code block and saner nested structures;</li> -<li>Custom Markdown engine (I would like to call <a href="https://github.com/jgm/CommonMark"><code>stmd</code></a>).</li> -</ul> -<p>Whatever the case, Emacs is still my best friend.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-10-29-fun.html b/build/blog/2014-10-29-fun.html deleted file mode 100644 index 308ce9e9..00000000 --- a/build/blog/2014-10-29-fun.html +++ /dev/null @@ -1,44 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-10-29T11:26:29-0700" name="date"/> -<title>Fun</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Fun</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-10-29T11:26:29-0700">October 29, 2014</time> -</div> -</header> -<p>This happened in yesterday's Math 210A lecture.</p> -<blockquote> -<p>Ravi: I won't be here next Thursday.<br/> Someone: Will there be a lecture?<br/> Ravi: Yeah, Brian Conrad will give a lecture. Don't tell him, he don't know this yet.</p> -</blockquote> -<p>...</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-11-02-vobcopy-dvdbackup-etc.html b/build/blog/2014-11-02-vobcopy-dvdbackup-etc.html deleted file mode 100644 index 52a973e0..00000000 --- a/build/blog/2014-11-02-vobcopy-dvdbackup-etc.html +++ /dev/null @@ -1,92 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-11-02T15:06:07-0800" name="date"/> -<title>vobcopy, dvdbackup, etc.</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">vobcopy, dvdbackup, etc.</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-11-02T15:06:07-0800">November 2, 2014</time> -</div> -</header> -<p>A few days ago, I was cloning my entire Audio CD and DVD collection, and reported some of the findings in <a href="/blog/2014-10-26-audio-cd-slash-dvd-to-iso-image-on-os-x.html">this post</a>. As said, the most important commands are</p> -<pre><code>hdiutil makehybrid -iso -joliet -o AUDIO_CD_NAME.iso SOURCE</code></pre> -<p>for Audio CDs and</p> -<pre><code>hdiutil makehybrid -udf -o DVD_NAME.iso SOURCE</code></pre> -<p>for DVDs.</p> -<p>Those alone don't finish the story. I also tried other things and unfortunately encountered problems. I was too busy to report back then, but now I'll summarize some of the findings.</p> -<hr/> -<p>For one thing, <code>hdiutil makehybrid</code> might fail, issuing an "Operation not permitted" for no obvious reason. This could even happen when you work with the Disk Utility GUI (for which I once got a "Permission denied"). Even <code>sudo</code> didn't help in my case. However, I was able to <strong>circumvent the problem with the root shell</strong> (I won't tell you how to enter the root shell — you need to at least have that amount of knowledge about the root shell before you are given the key). Not sure why. Just keep in mind that the root shell might help (that's also a general, albeit dangerous, advice for life).</p> -<hr/> -<p>Next onto grabbing the raw VOB.</p> -<p><code>vobcopy</code> is pretty sweet, but at least for me it had one huge problem. When I tried to copy a single title, say title #2 with</p> -<pre><code>vobcopy --title-number TITLE_NUMBER -i SOURCE</code></pre> -<p>other titles got copied, too. I didn't have enough samples to test out, but presumably it's because the problematic DVD has a structure like this:</p> -<div class="figure"> -<a href="https://i.imgur.com/HTgmwQL.png" target="_blank"><img alt="problematic DVD title structure" src="https://i.imgur.com/HTgmwQL.png"/></a> -<p class="caption">problematic DVD title structure</p> -</div> -<p>Anyway, no matter I <code>vobcopy</code> title 01, 02, or 03, the result was the same — the whole thing. That's pretty stupid. I don't know if it counts as a bug or unfinished feature. Definitely not cool.</p> -<p>(One cool thing about <code>vobcopy</code>: as long as you complied with <code>libdvdread</code>, you can create a fully decrypted version of the DVD with</p> -<pre><code>vobcopy --mirror -i SOURCE</code></pre> -<p>Of course, to get an iso image out of the decrypted mirror, you run the <code>hdiutil makehybrid -udf</code> command given above.)</p> -<hr/> -<p>So <code>vobcopy</code> is dead (for copying specific titles in unfortunate DVDs). What's next?</p> -<p>There's <code>dvdbackup</code>. The man page is good, and <a href="https://wiki.archlinux.org/index.php/dvdbackup#A_single_title">ArchWiki</a> is even better (<em>ArchWiki is awesome!</em>), providing you cookbook solutions of combining the power of <code>dvdbackup</code> and <code>dvdauthor</code> (cookbooks are nice when dealing with unexciting technologies like DVD). In fact, <code>dvdbackup</code> alone is enough for extracting the VOBs of relatively small titles (< 1GiB):</p> -<pre><code>dvdbackup -i SOURCE -o VOB_TARGET_DIR -t TITLE_NUMBER -n TITLE_NAME</code></pre> -<p>then grab your title-specific VOB in <code>VOB_TARGET_DIR/TITLE_NAME/VIDEO_TS</code>. Unlike <code>vobcopy</code>'s <code>-n/--title-number</code> option, <code>dvdbackup</code>'s <code>-t/--title</code> option does it right, trimming everything else. However, there's a problem when the title is larger than 1 GiB — then <code>dvdbackup</code> will split the VOB into several 1 GiB max pieces, and there's no way to disable this (since <code>dvdbackup</code> is targeting a DVD player — ancient technology — rather than <code>mpv</code> or whatever). What's sadder is that I can't seem to combine the split VOBs with FFmpeg stream copy — <code>pcm_dvd</code> audio always gets converted to <code>mp2</code> and fails when I use <code>-c copy</code>. I'm not a codec expert, but I suppose this is due to the fact that <code>pcm_dvd</code> isn't a supported encoding codec of FFmpeg (at least not my FFmpeg):</p> -<pre><code>> ffmpeg -codecs | grep pcm_dvd -D.A..S pcm_dvd PCM signed 20|24-bit big-endian</code></pre> -<p><code>D</code> is for "Decoding supported", <code>A</code> is for "Audio codec", <code>S</code> is for "Lossless compression" — no encoding support. By the way, my FFmpeg is <code>brew</code>ed with the options <code>--with-fdk-aac</code>, <code>--with-ffplay</code>, <code>--with-freetype</code>, <code>--with-libass</code>, <code>--with-libbluray</code>, <code>--with-openjpeg</code>, <code>--with-openssl</code>, <code>--with-x265</code>:</p> -<pre><code>> \ffmpeg -version -ffmpeg version 2.4.2 Copyright (c) 2000-2014 the FFmpeg developers -built on Oct 19 2014 14:09:36 with Apple LLVM version 6.0 (clang-600.0.51) (based on LLVM 3.5svn) -configuration: --prefix=/usr/local/Cellar/ffmpeg/2.4.2 --enable-shared --enable-pthreads --enable-gpl --enable-version3 --enable-nonfree --enable-hardcoded-tables --enable-avresample --enable-vda --cc=clang --host-cflags= --host-ldflags= --enable-libx264 --enable-libfaac --enable-libmp3lame --enable-libxvid --enable-libfreetype --enable-libass --enable-ffplay --enable-libfdk-aac --enable-openssl --enable-libx265 --enable-libopenjpeg --disable-decoder=jpeg2000 --extra-cflags='-I/usr/local/Cellar/openjpeg/1.5.1_1/include/openjpeg-1.5 ' -libavutil 54. 7.100 / 54. 7.100 -libavcodec 56. 1.100 / 56. 1.100 -libavformat 56. 4.101 / 56. 4.101 -libavdevice 56. 0.100 / 56. 0.100 -libavfilter 5. 1.100 / 5. 1.100 -libavresample 2. 1. 0 / 2. 1. 0 -libswscale 3. 0.100 / 3. 0.100 -libswresample 1. 1.100 / 1. 1.100 -libpostproc 53. 0.100 / 53. 0.100</code></pre> -<p>Maybe I missed some <code>--enable</code>.</p> -<p>Sorry for the digression. So, it's not possible to stream-copy-concat the VOBs with FFmpeg. (In fact, since audio quality is not that important — you won't be able to tell 256k AAC from lossless anyway, especially when you are focusing on the video, so you can always transcode <code>pcm_dvd</code> into 256k AAC with <code>-c:a libfdk_aac -b:a 256k</code>. <code>mpeg2video</code> is an encoding supported codec so stream copy works fine. Or you may also use <code>flac</code> or whatever encoding-supported lossless codec.) However, if you insist on getting the original <code>pcm_dvd</code>, there is a way, an ugly way. You've gotta be creative here. <a href="https://wiki.archlinux.org/index.php/dvdbackup#A_single_title">ArchWiki</a> already provides a cookbook solution on how to use <code>dvdbackup</code> and <code>dvdauthor</code> to create a DVD with a selected title. And <code>vobcopy</code> can copy the entire thing just fine, without the 1 GiB limit (make sure to use the <code>-l/--large-file</code> option if the size is greater than 2 GiB). Therefore, you can create a DVD with selected title from the original DVD, then <code>vobcopy</code> from the new DVD. This is insane, but it works, I've tested that. <strong>Note, however, that timestamps might be wrong with <code>vobcopy</code>, so the VOB runs just fine linearly but might run into problems when you seek.</strong> Therefore, FFmpeg is still the way to go. Or maybe you can do it right with one click using some closed source software ☹ — I've heard about success stories with the long ceased DVD Decrypter Windows project. In reality, I guess only people with theoretical interest or OCD will ever do this — FLAC or AAC should serve everyone just fine. It should have worked with <code>vobcopy</code> alone, but it doesn't. Hence the workaround.</p> -<hr/> -<p>For future reference, I'll translate the ArchWiki cookbook solution here (it's too cookbook itself, specifying paths like <code>~/movie_name</code> and using unnecessary <code>cd</code>) about creating a title-specific DVD from a multi-title DVD (replace <code>SOURCE</code>, <code>VOB_TARGET_DIR</code>, <code>DVD_TARGET_DIR</code>, <code>TITLE_NUMBER</code>, and <code>TITLE_NAME</code> with sane values):</p> -<pre><code>dvdbackup -i SOURCE -o VOB_TARGET_DIR -t TITLE_NUMBER -n TITLE_NAME -dvdauthor -t -o DVD_TARGET_DIR VOB_TARGET_DIR/TITLE_NAME/VIDEO_TS/*.VOB -export VIDEO_FORMAT=NTSC -cd DVD_TARGET_DIR/VIDEO_TS && dvdauthor -T -o DVD_TARGET_DIR</code></pre> -<p><code>export VIDEO_FORMAT=NTSC</code> is to avoid the <code>dvdauthor</code> error of "no default video format, must explicitly specify NTSC or PAL" (I'm not sure about the difference between NTSC and PAL, but I saw NTSC printed on my DVD, so I used it). And there you go, a shiny new DVD filesystem located in <code>DVD_TARGET_DIR</code>. (Note that unlike <code>vobcopy</code>, <code>dvdbackup</code> doesn't feature a nice progress bar even when <code>-v/--verbose</code> and <code>-p/--progress</code> are specified.) Then you can</p> -<pre><code>vobcopy -l DVD_TARGET_DIR</code></pre> -<p>if you'd like to. Recall that timestamps might be wrong, sadly.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-11-05-apple-is-pushing-yosemite-hard.html b/build/blog/2014-11-05-apple-is-pushing-yosemite-hard.html deleted file mode 100644 index e547c812..00000000 --- a/build/blog/2014-11-05-apple-is-pushing-yosemite-hard.html +++ /dev/null @@ -1,61 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-11-05T22:17:01-0800" name="date"/> -<title>Apple is pushing Yosemite hard</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Apple is pushing Yosemite hard</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-11-05T22:17:01-0800">November 5, 2014</time> -</div> -</header> -<p>Apple is pushing Yosemite hard and secretly Yosemitizing things. iTunes was updated to its shiny new look on Mavericks, day one upon Yosemite launch. I liked it. The only problems I had with the new iTunes are:</p> -<ul> -<li><p>It's no longer possible to go to the Artists view and Music Videos view with one click. Artists is now a drop-down menu option in My Music view; Music Videos is now a sidebar tab in Playlists view.</p></li> -<li><p>The red icon doesn't look as good as the previous blue one, and it doesn't harmonize too well alongside the blue Finder and Mail. Maybe they will look better together in Yosemite.</p></li> -</ul> -<p>Just now I found that the Mac App Store in Mavericks is also Yosemitized:</p> -<div class="figure"> -<a href="https://i.imgur.com/T7KIo6s.png" target="_blank"><img alt="Yosemitized Mac App Store" src="https://i.imgur.com/T7KIo6s.png"/></a> -<p class="caption">Yosemitized Mac App Store</p> -</div> -<p>The chromeless UI certainly looks a bit weird, and the font seems a bit too small. However, I'm sure I'll quickly get over these shortcomings, and might even grow to appreciate them. Even more so when I finally upgrade to Yosemite (I'll wait for Thanksgiving break or 10.10.1 this year, whichever comes first — looks like the former will come first, considering the first 10.10.1 developer beta was out <a href="http://www.macrumors.com/2014/11/03/first-yosemite-10-10-1-beta-now-available/">merely two days ago</a>, <a href="https://i.imgur.com/IVFV7E2.png">reportedly</a> focusing on WiFi, etc.).</p> -<p>On the font side, unfortunately the small font size in the new Mac App Store does make text fuzzy on my non-Retina display. I didn't notice the fuzziness in the new iTunes. Anyway, everything is optimized for Retina — Apple is also secretly pushing Retina hard. In the Apple ecosystem, apparently you always want to stay at the top of the line. Due to Apple's nature, the degree of hardware-software integration is simply unparalleled, so only the latest hardware enjoys all the new features and love. Unfortunately, the typical lifespan of a Mac is much longer than the hardware/software release cycle.</p> -<p>The truth is, we (or at least I) adapt to things much quicker and easier than we'd imagined (or otherwise would be willing to admit). When iOS 7 was demo'ed on WWDC 2013, I was like "no way! What's with those stupid flat crap?" But when the update came, I hopped on and was happy ever since. (I reserve my opinion on the icon design.) Later when I installed an app that was not updated for the new UI, I was like "OMG, what's with this clumsy UI?" I guess legibility issues, WiFi issues (with Yosemite) and responsiveness issue (with iOS 8 on iPhone 4S — <em>AT&T, where's my preordered 6 Plus?</em>) are harder to impossible to adapt to, but they will eventually be fixed, or support-dropped, or hardware-upgraded (with $$). So in the end (almost) everyone will be happy. And one day when we face the old thing again by chance, we'll flee as fast as we can: "what's with that..." (I did exaggerate. Also, I know, many people just don't care about design, or have ill tastes, or can't find the buttons after a minimal number of UI tweaks — I'm not including them in the "we" here.) Those who claim that "I won't upgrade until..." are just kidding themselves, and certainly no one will wait for them or make their "until..." come true. Most of those "won't upgrade" folks will eventually upgrade and be happy. Those that really don't upgrade (like those still running Snow Leopard) either can't afford the new hardware, or suffer from senility (seen from the deep hostility towards new things). Or they have some important legacy software that would break with an upgrade; poor dudes.</p> -<p>Same goes for newer, shinier, seemingly unnecessary deluxe hardware. I'm still stuck on a Mid-2012 MBP 13" Non-Retina. Retina seems highly useless for me since I do most of my work on the 27" external display — the 13" internal LCD hosts a single maximized Activity Monitor window most of the time (and sometimes also a Transmission window). I expect my opinion about Retina to change after I upgrade to a Retina model next year. (It will be a pretty major purchase though — i7, 16 GB memory, and 512 GB SSD are musts, and there are like a million peripherals to buy — Thunderbolt to Ethernet, Super Drive, etc., etc.) This shift of opinion after upgrading to something unnecessarily good (and ending up not being able to tolerate anything inferior) is best described as "<strong>sadly converted</strong>". Some folks are already sadly converted by the Retina iMac. See, for example, <a href="http://arstechnica.com/apple/2014/11/yes-the-5k-retina-imacs-screen-runs-at-60hz-at-5k-resolution/#p11">this article</a> on Ars Technica:</p> -<blockquote> -<p>Prior to getting the Retina iMac on my desk, I would have said that "retina" isn’t necessarily something we need on the desktop. Most people don’t notice pixels on the desktop at a normal seating distance. However, after getting to A/B compare the Retina iMac with the standard one over the course of a week, I’m sadly converted. I just don’t know if my wallet can take the abuse.</p> -</blockquote> -<p>And others are bitterly desiring one (me included — sadly two Macs are too much for a university dorm). See, for example, <a href="http://arstechnica.com/apple/2014/11/yes-the-5k-retina-imacs-screen-runs-at-60hz-at-5k-resolution/?comments=1&post=27896871">this comment</a> on the aforementioned article:</p> -<blockquote> -<p>I WISH APPLE TECHNICA WOULD STOP WITH ALL THESE ARTICLES ABOUT THE IMAC.</p> -<p>It really makes me want one unjustifiably.</p> -</blockquote> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-11-05-list-youtube-playlist-with-youtube-dl.html b/build/blog/2014-11-05-list-youtube-playlist-with-youtube-dl.html deleted file mode 100644 index 28cd21f5..00000000 --- a/build/blog/2014-11-05-list-youtube-playlist-with-youtube-dl.html +++ /dev/null @@ -1,84 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-11-05T10:37:58-0800" name="date"/> -<title>List YouTube playlist with youtube-dl</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/highlight.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">List YouTube playlist with youtube-dl</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-11-05T10:37:58-0800">November 5, 2014</time> -</div> -</header> -<p>Of course you are always welcome to use the <a href="https://developers.google.com/api-client-library/python/">Google APIs Client Library for Python</a> to wrestle with YouTube, which is usually pretty simple. (As an added bonus, YouTube has some <a href="https://developers.google.com/youtube/v3/code_samples/">nice runnable sample scripts</a> to get you started.) With the client library, listing videos in a YouTube playlist is a breeze.</p> -<p>However, if you don't feel like writing code yourself (I usually don't feel like writing code myself until I use something often enough and existing solutions are suboptimal), <code>youtube-dl</code> recently added the functionality to list videos in a playlist with the <code>--flat-playlist</code> option.</p> -<p><a href="https://github.com/rg3/youtube-dl/issues/4003#issuecomment-60322630">According to one of the project collaborators</a>, currently <code>--flat-playlist</code> is only helpful with the <code>-j</code> option for dumping JSON (so I suppose this feature is subject to change). For instance, <code>--flat-playlist</code> alone would emit something like this:</p> -<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="op">></span> <span class="ex">youtube-dl</span> --flat-playlist <span class="st">'https://www.youtube.com/watch?v=gdOwwI0ngqQ&list=PLPpZI8R1zUfrkDbmJMOBhEbJ9Td9vbV-F'</span> -[<span class="ex">youtube</span>:playlist] Downloading playlist PLPpZI8R1zUfrkDbmJMOBhEbJ9Td9vbV-F - add --no-playlist to just download video gdOwwI0ngqQ -[<span class="ex">youtube</span>:playlist] PLPpZI8R1zUfrkDbmJMOBhEbJ9Td9vbV-F: Downloading webpage -[<span class="ex">youtube</span>:playlist] PLPpZI8R1zUfrkDbmJMOBhEbJ9Td9vbV-F: Downloading page <span class="co">#1</span> -[<span class="ex">download</span>] Downloading playlist: Cam By apinknomfan -[<span class="ex">youtube</span>:playlist] playlist Cam By apinknomfan: Collected 119 video ids (downloading 119 of them) -[<span class="ex">download</span>] Downloading video <span class="co">#1 of 119</span> -[<span class="ex">download</span>] Downloading video <span class="co">#2 of 119</span> -[<span class="ex">download</span>] Downloading video <span class="co">#3 of 119</span> -[<span class="ex">download</span>] Downloading video <span class="co">#4 of 119</span> -<span class="ex">...</span></code></pre></div> -<p>which doesn't really make sense — it tells you that it collected 119 video ids, and no more. Once you have <code>-j</code> on, you get JSON data that you can parse with anything:</p> -<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="op">></span> <span class="ex">youtube-dl</span> -j --flat-playlist <span class="st">'https://www.youtube.com/watch?v=gdOwwI0ngqQ&list=PLPpZI8R1zUfrkDbmJMOBhEbJ9Td9vbV-F'</span> -{<span class="st">"url"</span>: <span class="st">"gdOwwI0ngqQ"</span>, <span class="st">"_type"</span>: <span class="st">"url"</span>, <span class="st">"ie_key"</span>: <span class="st">"Youtube"</span>, <span class="st">"id"</span>: <span class="st">"gdOwwI0ngqQ"</span>} -{<span class="st">"url"</span>: <span class="st">"j9l5nchv1Z8"</span>, <span class="st">"_type"</span>: <span class="st">"url"</span>, <span class="st">"ie_key"</span>: <span class="st">"Youtube"</span>, <span class="st">"id"</span>: <span class="st">"j9l5nchv1Z8"</span>} -{<span class="st">"url"</span>: <span class="st">"znW5ALwWNQw"</span>, <span class="st">"_type"</span>: <span class="st">"url"</span>, <span class="st">"ie_key"</span>: <span class="st">"Youtube"</span>, <span class="st">"id"</span>: <span class="st">"znW5ALwWNQw"</span>} -{<span class="st">"url"</span>: <span class="st">"qyE7-auTIcc"</span>, <span class="st">"_type"</span>: <span class="st">"url"</span>, <span class="st">"ie_key"</span>: <span class="st">"Youtube"</span>, <span class="st">"id"</span>: <span class="st">"qyE7-auTIcc"</span>} -<span class="ex">...</span></code></pre></div> -<p>The most straightforward way to parse this is to use a command line JSON parser, the best one being <a href="https://github.com/stedolan/jq">jq</a>:</p> -<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="op">></span> <span class="ex">youtube-dl</span> -j --flat-playlist <span class="st">'https://www.youtube.com/watch?v=gdOwwI0ngqQ&list=PLPpZI8R1zUfrkDbmJMOBhEbJ9Td9vbV-F'</span> <span class="kw">|</span> <span class="ex">jq</span> -r <span class="st">'.id'</span> <span class="kw">|</span> <span class="fu">sed</span> <span class="st">'s_^_https://youtube.com/v/_'</span> -<span class="ex">https</span>://youtube.com/v/gdOwwI0ngqQ -<span class="ex">https</span>://youtube.com/v/j9l5nchv1Z8 -<span class="ex">https</span>://youtube.com/v/znW5ALwWNQw -<span class="ex">https</span>://youtube.com/v/qyE7-auTIcc -<span class="ex">...</span></code></pre></div> -<p>There you go, a list of URIs you can use. Of course you can put this in a script to save some typing:</p> -<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="co">#!/usr/bin/env bash</span> -<span class="co"># Takes a YouTube URI to a playlist (fairly liberal, it's fine as long</span> -<span class="co"># as the playlist id can be extracted), and prints a list of URIs in a</span> -<span class="co"># YouTube playlist.</span> -<span class="co">#</span> -<span class="co"># Requires youtube-dl 2014.10.24, tested on youtube-dl</span> -<span class="co"># 2014.11.02.1. Feature subject to change.</span> -<span class="ex">youtube-dl</span> -j --flat-playlist <span class="st">"</span><span class="va">$1</span><span class="st">"</span> <span class="kw">|</span> <span class="ex">jq</span> -r <span class="st">'.id'</span> <span class="kw">|</span> <span class="fu">sed</span> <span class="st">'s_^_https://youtube.com/v/_'</span></code></pre></div> -<p><strong><em>Aside:</em></strong> I first embedded the gist here, but <a href="https://i.imgur.com/m3cr0Im.png">it looked a bit off</a>. See <a href="https://github.com/imathis/octopress/issues/1392">imathis/octopress#1392</a>.</p> -<blockquote> -<p>In the next version of the Gist tag plugin we are just downloading the gists and embedding them upon generation so we don't have to worry about GitHub going down and breaking all your gists, or changing the HTML and breaking all the styles.</p> -<p>For the time being I suggest embedding your code snippets directly if you want them to look good.</p> -</blockquote> -<p>Okay. End of aside.</p> -<p>By the way, <code>youtube-dl</code> supports playlist bulk download natively. The reason I need a list of video ids or URIs, however, is that among other things, <code>youtube-dl</code> doesn't download highest resolution DASH video by default, so I have to rely on something like <code>youtube-dl-dash</code> (<a href="https://github.com/zmwangx/sh/blob/master/youtube-dl-dash">link</a>) to download the best version.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-11-06-2014-nobel-prize-in-physics-led-lights-seriously.html b/build/blog/2014-11-06-2014-nobel-prize-in-physics-led-lights-seriously.html deleted file mode 100644 index 62cf03bc..00000000 --- a/build/blog/2014-11-06-2014-nobel-prize-in-physics-led-lights-seriously.html +++ /dev/null @@ -1,47 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-11-06T11:08:45-0800" name="date"/> -<title>2014 Nobel Prize in Physics — LED lights, seriously?</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">2014 Nobel Prize in Physics — LED lights, seriously?</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-11-06T11:08:45-0800">November 6, 2014</time> -</div> -</header> -<p>For some reason, I only learned about this year’s laureates today, through <a href="http://motls.blogspot.com/2014/11/ex-employer-wont-meet-blue-led-nobel.html">the reference frame</a>. The prize goes to the inventors of the LED. Not exciting at all, so I don’t care if I’m ever informed. (Lubos has a good point on why applied physics — well, let’s even widen the concept of applied physics a bit — should not surprise anyone when they appear in a Nobel Prize announcement: “After all, Alfred Nobel might have very well considered his dynamite to be a discovery in physics, too.”)</p> -<p>The Nobel Prize Physics Awards has been rather amusing in recent years. Partly due to controversy on the theoretical front and no breakthrough on the experimental front, I guess. (The discovery of Higgs was a breakthrough to some extent, but it was totally expected; little physics beyond SM at LHC before LS1 is sad. Since it was totally expected, the award went to theorists — some experimentalists might not be too thrilled.) Just look at the recent list: 2010, graphene (shouldn’t that be chemistry? if material science can be part of physics, then chemistry must surely encompass it, too); 2009, CCD sensor (whatever that means, maybe that’s important); 2008, fibers (okay, I love fast Internet connections). The list actually goes all the way down to early 20th century, but it’s much denser in recent decades. Now one more: 2014, LED.</p> -<blockquote> -<p>“for the invention of efficient blue light-emitting diodes which has enabled bright and energy-saving white light sources”</p> -</blockquote> -<p>Wow, energy-saving. I guess next year’s prize will go to the inventors of high efficiency urinals, for being resource-saving. <strong>I mean, LEDs are great, but not great as physics, much less a physics breakthrough.</strong></p> -<p>Let’s compare the applied folks to other laureates: Lorentz, J. J. Thomson, Planck, Einstein, Bohr, Heisenberg, Schrödinger, Dirac, Fermi, Pauli, Born, Lee, Yang, Landau, Feynman, Schwinger, Gell-Mann, Weinberg, ’t Hooft, etc. Not on the same level.</p> -<p>It’s good to see that a growing body of physicists are (or at least as it seems to me) increasingly reserved about the Nobel Prize, and prizes in general. Same goes for math, with the Nobel Prize replaced by something else. (Employers still love the big titles, I suppose — good to have some star faculty on board.)</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-11-07-interstellar.html b/build/blog/2014-11-07-interstellar.html deleted file mode 100644 index 48372d93..00000000 --- a/build/blog/2014-11-07-interstellar.html +++ /dev/null @@ -1,44 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-11-07T23:56:31-0800" name="date"/> -<title>Interstellar</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Interstellar</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-11-07T23:56:31-0800">November 7, 2014</time> -</div> -</header> -<p>Today (I mean November 7, 2014 — it’s technically November 8 at the time of writing) I saw <a href="https://en.wikipedia.org/wiki/Interstellar_%28film%29"><em>Interstellar</em></a> (IMAX digital) at AMC Mercado 20. I rarely go to movie theaters, less on the release day (film formats of <em>Interstellar</em> were released on November 5, and digital formats followed on November 7). However, reviews of it were positive (from the physics community), and I really need a way to release stress these days — I wasn’t in the right condition for months. So I figured I’d just spend an afternoon in front of the big screen.</p> -<p>I’ve heard good things about IMAX 70mm film, like no trailers, among other things. But I didn’t bother the extra seven miles’ drive to Hackworth IMAX Dome, so I landed on IMAX digital. Still a pretty stunning experience, although I ended up watching forty minutes worth of trailers before the real thing (arrived fifteen minutes early). In hindsight maybe I’d be better off spending some extra time on the road.</p> -<p>Speaking of the movie itself, they tried to make it as plausible as possible from a physics viewpoint, by involving <a href="https://en.wikipedia.org/wiki/Kip_Thorne">Kip Thorne</a> of Caltech. (There’s even a book out, <em>The Science of Interstellar</em>.) For instance, the wormhole isn’t portrayed as a hole (I mean, imagine a ring in empty space, as you would picture in your mind when you hear the word “hole” out of nothing; that’s not how it looks like here, and there’s a nice explanation). Some of the physics still doesn’t work out quite well, though, like Cooper’s not crushed at the singularity… Also there are communications from within the horizon and breakdown of causality, explained in the movie as happening in four dimension slices of some five dimensional spacetime where time could be a physical dimension. Obviously these are needed to get the sci-fi story going, so no one should be blamed.</p> -<p>I was there for the sci-fi and physics, but a nice surprise was that I was also touched by the humanity elements of story, I mean, family and stuff.</p> -<p>The downside: Cooper’s accent was a bit hard on me ☹</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-11-10-average-phone-plan-in-the-u-dot-s-costs-ten-time-as-much-as-that-in-the-u-dot-k.html b/build/blog/2014-11-10-average-phone-plan-in-the-u-dot-s-costs-ten-time-as-much-as-that-in-the-u-dot-k.html deleted file mode 100644 index d7485616..00000000 --- a/build/blog/2014-11-10-average-phone-plan-in-the-u-dot-s-costs-ten-time-as-much-as-that-in-the-u-dot-k.html +++ /dev/null @@ -1,44 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-11-10T11:11:46-0800" name="date"/> -<title>Average phone plan in the U.S. costs ten time as much as that in the U.K.</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Average phone plan in the U.S. costs ten time as much as that in the U.K.</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-11-10T11:11:46-0800">November 10, 2014</time> -</div> -</header> -<p>To quote <a href="http://blogs.opera.com/news/2014/11/mobile-data-anyway/">Opera News</a>,</p> -<blockquote> -<p>According to research by the International Telecommunication Union, the average phone plan with 500MB of data costs $85 in the United States, compared to $24.10 in China and $8.80 in the United Kingdom.</p> -</blockquote> -<p>Holy shit!</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-11-11-re-encoding-everything-for-iphone-6-plus.html b/build/blog/2014-11-11-re-encoding-everything-for-iphone-6-plus.html deleted file mode 100644 index 8cb9d9e6..00000000 --- a/build/blog/2014-11-11-re-encoding-everything-for-iphone-6-plus.html +++ /dev/null @@ -1,40 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-11-11T13:31:25-0800" name="date"/> -<title>Re-encoding everything for iPhone 6 Plus</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Re-encoding everything for iPhone 6 Plus</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-11-11T13:31:25-0800">November 11, 2014</time> -</div> -</header> -<p>AT&T finally delivered my iPhone 6 Plus (silver, 64 GB) after about fifty days since preorder… The 1080p Retina display is simply stunning. However, it turns out that my old videos don’t work so well on 6 Plus’s giant screen. My old mobile video collection was optimized for my 16 GB 4S, targeting the small screen and highly limited storage — you guessed it, they were resized to 960x540, and they looked great. But they’re not up to the task any more. 960x540 videos aren’t at all sharp on the stunning screen of 6 Plus, which is more than capable of handling 4x pixels. Therefore, I have no choice but to feed it more pixels. I’m left in a weird situation, where my 1080p desktop (or even HDTV) quality videos should fit the screen just fine, but H.264 profile stands in the way. iPhone 6 and 6 Plus are only capable of High Profile level 4.2, so anything encoded in level 5.1, for instance, needs to be re-encoded. Also there are still MPEG-2 and MPEG-4 videos out there (MPEG-4 should be obsolete by now, I assume, but some people still use it; and MPEG-2 is de facto in TV broadcasts), which have to be transcoded. Okay, it’s a daunting task to re-encode a fairly big collection, but I have to do it sooner or later. Presumably this weekend. I’ll also report whether 720p videos look sharp on the screen later.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-11-19-convolution-of-irreducible-characters.html b/build/blog/2014-11-19-convolution-of-irreducible-characters.html deleted file mode 100644 index 5b1a90f3..00000000 --- a/build/blog/2014-11-19-convolution-of-irreducible-characters.html +++ /dev/null @@ -1,44 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-11-19T20:40:37-0800" name="date"/> -<title>Convolution of irreducible characters</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Convolution of irreducible characters</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-11-19T20:40:37-0800">November 19, 2014</time> -</div> -</header> -<p><strong><em>TL; DR:</em> The actual PDF write-up is <a href="https://dl.bintray.com/zmwangx/generic/20141119-convolution-of-irreducible-characters.pdf">here</a>.</strong></p> -<hr/> -<p>Yesterday I was trying to establish the formula for orthogonal primitive central idempotents of a group ring. It is possible to establish the result through the convolution of irreducible characters. However, I stuck quite a while on trying to work out the convolutions themselves. For a formidable and unenlightening proof using "matrix entry functions" (i.e., fix a basis, induce a matrix representation, and explicitly expand everything in matrix elements), see <a href="http://drexel28.wordpress.com/2011/03/02/representation-theory-using-orthogonality-relations-to-compute-convolutions-of-characters-and-matrix-entry-functions/">this post</a> (in fact, this is just one in a series of posts that lead up to the result). That's a really sad proof.</p> -<p>It turns out that I really should have been working the other way round — first establish the orthogonal idempotents (the proof of which is really simple and elegant, I was just trapped in a single thread of thought), then use that to compute the convolution of irreducible characters.</p> -<p>I feel like this is worth presenting (as the only proof I saw online is the really sad one above), so I TeX'ed it up. I tried to convert to MathJax HTML but eventually gave up (that's the story for another post). So, the write-up is in good ol' PDF, available <a href="https://dl.bintray.com/zmwangx/generic/20141119-convolution-of-irreducible-characters.pdf">here</a>.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-11-20-dropbot-for-geeks(r).html b/build/blog/2014-11-20-dropbot-for-geeks(r).html deleted file mode 100644 index 713ec711..00000000 --- a/build/blog/2014-11-20-dropbot-for-geeks(r).html +++ /dev/null @@ -1,51 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-11-20T09:48:15-0800" name="date"/> -<title>Dropbot for Geeks®</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Dropbot for Geeks®</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-11-20T09:48:15-0800">November 20, 2014</time> -</div> -</header> -<p>I propose the following cloud storage and syncing service model of the future. I call it <strong>Dropbot for Geeks®</strong>, and it totally rules. It's designed for geeks who are tired of the highly limited, miserably unproductive traditional services (based on clicking around). It has the following features:</p> -<ul> -<li>Standard Unix file system commands exposed as an API, e.g., <code>cat</code>, <code>cd</code>, <code>cp</code>, <code>du</code>, <code>df</code>, <code>file</code>, <code>find</code>, <code>head</code>, <code>ln</code>, <code>ls</code>, <code>mkdir</code>, <code>mv</code>, <code>pwd</code>, <code>rm</code>, <code>rmdir</code>, <code>tail</code>, <code>touch</code>, etc.</li> -<li>A rudimentary shell emulator through the web interface exposing the commands above.</li> -<li>Secure shell access to the file system, also exposing the commands above. Provide two-factor auth for SSH. Clearly, <code>scp</code> should also be supported.</li> -<li>Checksums. Expose, for instance, <code>md5sum</code> or <code>sha1sum</code>, in the API. Provide checksums on download pages, probably on demand.</li> -<li>Programmable selective syncing, down to per file level.</li> -<li>Scriptability. Allow clients to run custom scheduled jobs or daemons with the API above. To prevent the service from becoming full-featured IaaS, though, clients might be limited in CPU time, memory, or command selection. This bullet point is arguable.</li> -</ul> -<hr/> -<p>With the level of command line integration illustrated above, we'll finally get rid of clicking around and not being able to automate chores. Navgating the remote file system will be a breeze — click, click, click, click, click (sometimes click should be replaced by double click, which is even more painful) just to navigate to a directory will be made a thing of the past. <code>ln</code>, in particular, saves disk space for duplicates — Dropbot for Geeks does <em>not</em> want to charge you extra for multiple copies of the same file in different directories. (To facilitate syncing hardlinks, clients should be able to specify hardlinked files in a config file. Or maybe some better mechanism. This might be hard.) At last, checksums are a must. I’ve had traumatic experiences like having downloaded an eight-part RAR, 1 GiB each, only to find that it wouldn’t unRAR. Without checksums, it was impossible to find which part was corrupted. As a result, I had to re-download everything — a nightmare. I never want to experience similar problems again. Hence the precious checksums.</p> -<p>Dropbot for Geeks looks like a pretty good (well, not really, but at least pretty cool®) model. Maybe I should patent it before anyone else? Then if some similar service surfaces in the future, I can <a href="http://arstechnica.com/tech-policy/2014/11/jury-apple-must-pay-23-6m-for-old-pager-patents/">sue their ass off and enjoy some hot cash</a>.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-11-24-iphone-photography-frustration.html b/build/blog/2014-11-24-iphone-photography-frustration.html deleted file mode 100644 index 34fad830..00000000 --- a/build/blog/2014-11-24-iphone-photography-frustration.html +++ /dev/null @@ -1,58 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-11-24T12:42:25-0800" name="date"/> -<title>iPhone photography frustration</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">iPhone photography frustration</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-11-24T12:42:25-0800">November 24, 2014</time> -</div> -</header> -<p><strong>TL; DR:</strong> Jump to the paragraph “In the end…”</p> -<hr/> -<p>I'm not a photo-savvy guy. I've never taken a single selfie in my life, and my iPhone Photos app witnesses about twenty photos a year — fifteen of which are accidental screenshots. Okay, a little bit of exaggeration. The iPhone, aka iCamera, especially the 6 Plus model, is sort of a waste in my possession. However, my grandparents came to visit me on campus yesterday, and my grandma <em>loves</em> photos. So I took one with them, using my phone (which is obviously better than my grandma’s digital camera). The lighting was wrong, but I was able to fix that in five seconds — clicked “Edit”, clicked on the little sun icon (whatever it is called), clicked on “Light”, slided the slidebar all the way to the right, and all of a sudden it looked perfect. (This is the first time I ever clicked those, but I got it nicely done in five seconds — very intuitive, deeply impressed.) From a layman’s perspective, the builtin edit feature of the Photos app is really smart. Later I tried to reproduce the same edit with iPhoto, but I had to manually wrestle with exposure, highlights, shadows, brightness, contrast, etc., and I just never got it right. Call me a moron if you feel like it, but I’ve already given you the context at the beginning of this article, so you can’t blame me. (For your reference, I do ’shop some images for fun and profit from time to time, but I never deal with actual unedited photos, so I never have to worry about exposure and stuff.)</p> -<p>So far so good. The frustation began when I try to import the photo to my Mac. I’m certainly not a mobile guy who keeps everything on his phone or the cloud. I have the photo import feature of Dropbox turned on, so as I plugged in my phone the photo already appearred in the Camera Upload folder. Wait what, two copies? Two copies that looked exactly the same, albeit one is about 0.1 MB larger than the other? Not cool. Pulled up Image Capture; Apple’s own software should do the trick, I guess. Nope, same thing. Googled, found this article on support.apple.com: <a href="http://support.apple.com/en-us/HT203612"><em>iOS: Edited photos show original photo after import or in other apps</em></a>. Okay sure, they know this. Let's listen to what they have to say.</p> -<blockquote> -<p>Apple uses Extensible Metadata Platform (XMP), a standard created by Adobe, for nondestructive photo editing. XMP allows you to undo edits and to revert back to an original photo without the loss of quality. Displaying the edited photo requires OS X v10.9 or later and software that can read XMP. The following applications support XMP:</p> -<ul> -<li>iPhoto 9.5 or later</li> -<li>iPhoto for iOS</li> -<li>Aperture 3 or later</li> -<li>Adobe Lightroom</li> -<li>Adobe Photoshop Elements</li> -</ul> -<p>Other photo-management applications and some iOS apps may also display XMP.</p> -</blockquote> -<p>Adobe Lightroom, oh well. I don’t yet have Adobe CC installed — Photoshop is certainly a powerhouse (plus Illustrator, InDesign, etc. are nice to have at times), but Pixelmator works fine for me most of the time, and I’m happy to go to a library iMac or Mac Pro when I do need the power; $29.99/$19.99 is just too much if I use it twice a month. I theorize that I can indefinitely extend the free trial by running CC in a VM, reverting to a clean snapshot and regenerating the MAC address from time to time, but that’s only a theory — I haven’t got the incentive to test it out. As for iPhoto, I know it’s pretty lame from past experience, and I was very much baffled by the ugly and unintuitive UI, so normally I don’t even want to waste disk space on it; but since it’s only official solution other than expensive Adobe products and Aperture, I decided to install it. 1.7 GB gone. <em>So does the wasted 1.7 GB do the trick? Sadly, no.</em> Still the same thing in iPhoto 9.6, which is clearly “iPhoto 9.5 or later”. Totally baffled.</p> -<p>In the end, I came up with an ugly solution. Just email or iMessage the photo to yourself from the phone. If you use email though, be sure to use the builtin Mail, or you would likely lose Exif data (I sent from Mailbox and lost Exif; I then sent from Mail and didn’t). This is really annoying since setting up accounts in the builtin Mail app is not fun — Google 2FA is not supported, and I have to generate an app-specific password. Compare to Mailbox, where <em>I signed into Dropbox on the new phone and within five seconds all of my ten email accounts are ready to use</em>. The loss of Exif data is probably related to <a href="http://stackoverflow.com/questions/20763814">this thread on SO</a>, but I didn’t delve into it since I’m not a Cocoa Touch dev. What’s more confusing, sending the photo via different applications result in different filesizes. The one sent from Mail (I chose original size when I sent it) was a 2 MB JPEG; the one sent from Mailbox was a 4.5 MB JPEG (without the right Exif); and the one sent via iMessage and later opened from the Messages app on Yosemite could be saved as a 10 MB lossless PNG (Exif was there). I went with the 2 MB one in the end.</p> -<p>I don’t know if iCloud Photo Library will solve the problem in the end. From my perspective, <em>Apple should train Preview and QuickLook to recognize their XMP technology.</em> Seriously, they talk about continuity, and I expect to enjoy my enhanced photos on my Mac without going through all the hessle and confusion. Photo enhancing is already such a breeze, thank you; now make sharing and archiving easy, at least within the Apple ecosystem. (Although I’m not familiar with photography and image editing in general, considering how tech-savvy I am, I bet most users can’t even figure out one annoying solution.)</p> -<p>By the way, Continuity and Handoff only work intermittently for me, and AirDrop between my iPhone (6 Plus) and MacBook Pro (mid-2012, model 9,2) doesn’t work at all. Continuity and Handoff sometimes turn up when they are unexpected (and serve as kinda nice surprises), but when I try to nail them, they remain elusive. Not a big deal for me, but certainly not the most pleasant thing ever. I bet these have to do with the fact that my Mac is connected to Ethernet and sharing the Ethernet connection to my iPhone; these days they expect everyone to be on Wi-Fi (and ironically they messed up big in Yosemite), but Wi-Fi simply can’t beat the speed and stability of Ethernet. I didn’t bother to test whether the features work when my devices are connected to the same Wi-Fi network; even if they do, that’s not my production setup, so they’re still useless to me.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-11-24-why-i-abandoned-mathjax-and-fell-back-to-pdf.html b/build/blog/2014-11-24-why-i-abandoned-mathjax-and-fell-back-to-pdf.html deleted file mode 100644 index c83c63a0..00000000 --- a/build/blog/2014-11-24-why-i-abandoned-mathjax-and-fell-back-to-pdf.html +++ /dev/null @@ -1,42 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-11-24T20:54:36-0800" name="date"/> -<title>Why I abandoned MathJax and fell back to PDF</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Why I abandoned MathJax and fell back to PDF</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-11-24T20:54:36-0800">November 24, 2014</time> -</div> -</header> -<p>Recently I wrote an expository article, <a href="https://dl.bintray.com/zmwangx/generic/20141119-convolution-of-irreducible-characters.pdf"><em>Convolution of irreducible characters</em></a>, and posted it <a href="/blog/2014-11-19-convolution-of-irreducible-characters.html">here</a>. At first I intended to use MathJax, but in the end I fell back to good ol' PDF. Here's why.</p> -<p>In short, I'm a mathematician. I write math <em>articles</em>, not just standalone expressions or formulas. I use AMSLaTeX to its fullest (not really, but at least I use numbering and the <code>amsthm</code> package to its fullest). HTML simply wasn't designed for this. Here are two influential markup languages designed for totally different use cases, and bridging them is painful. I tried to use <code>pandoc</code>, but it doesn't support <code>\input</code>, doesn't support <code>\def</code>, and swallows <code>\begin{theorem} \end{theorem}</code>, among other things. I tried to use <code>htlatex</code>; even the MathML output is suboptimal, with many math symbols translated to non-math (apart from totally human-unreadable), and it uses its custom CSS files that don't play well with everything else. I tried other things. In the end I gave up. Maybe I don't know enough about MathJax, but I certainly don't want to write a translator myself. Leave LaTeX alone. Distribute as PDF. MathJax may be great for Wikis (like Wikipedia) and for math lite blogs, but it's no replacement for real, beefy LaTeX. It's not for mathematicians who want to distribute real articles.</p> -<p>By the way, Terry Tao and others use <a href="http://lucatrevisan.wordpress.com/latex-to-wordpress/">Luca's LaTeX to WordPress, aka LaTeX2WP</a> for math blogging. From Terry's experience it works fairly well. I don't know if <code>amsthm</code> and <code>\def</code> are in the feature set, though. Anyway, since WordPress handles LaTeX as pre-compiled images (which is also the default on Wikipedia, and which looks poor in general and plays horribly with scaling), LaTeX2WP won't help MathJax users the slightest.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-11-25-i-got-16-gigs-of-ram.html b/build/blog/2014-11-25-i-got-16-gigs-of-ram.html deleted file mode 100644 index fa6c7e39..00000000 --- a/build/blog/2014-11-25-i-got-16-gigs-of-ram.html +++ /dev/null @@ -1,52 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-11-25T16:28:30-0800" name="date"/> -<title>I got 16 gigs of RAM</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">I got 16 gigs of RAM</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-11-25T16:28:30-0800">November 25, 2014</time> -</div> -</header> -<p>Today I upgraded the RAM of my MacBook Pro mid-2012 to 2x8GB. I purchased the <a href="http://smile.amazon.com/dp/B008LTBJFW">Crucial 16GB Kit (8GBx2) DDR3/DDR3L 1600 MHz (PC3-12800) CL11 SODIMM 204-Pin 1.35V/1.5V Memory for Mac CT2K8G3S160BM</a> from Amazon, which cost me $146.64 after tax. I followed the <a href="http://support.apple.com/en-us/HT201165">official guide</a> as well as the <a href="https://www.ifixit.com/Guide/MacBook+Pro+13-Inch+Unibody+Mid+2012+RAM+Replacement/10374">iFixit guide</a>. To finish the job I needed a Phillips #00 screwdriver and a spudger, so I purchased the <a href="https://www.ifixit.com/Store/Tools/Spudger/IF145-002">spudger</a> and the <a href="https://www.ifixit.com/Store/Tools/54-Bit-Driver-Kit/IF145-022-1">54 bit driver kit</a> from iFixit.</p> -<p>The actual process was pretty simple. I had a little bit of hard time pulling out the bottom module and pushing in the top module, but overall it was smooth. The only stupid thing I did was that I forgot to push the battery connector back in before I closed the case; I only realized this when I was screwing in the eighth screw (that was a close one!), and had to unscrew everything again.</p> -<p>After I replaced the RAM modules, booting was just normal. And now I've got 16 gigs of RAM!</p> -<div class="figure"> -<a href="https://i.imgur.com/PGhdEGr.png" target="_blank"><img alt="About This Mac->Memory" src="https://i.imgur.com/PGhdEGr.png"/></a> -<p class="caption">About This Mac->Memory</p> -</div> -<p>Want to run multiple memory hoggers <em>along with a Windows VM</em> (with 4GB of RAM)? No problem.</p> -<div class="figure"> -<a href="https://i.imgur.com/czDcVaK.png" target="_blank"><img alt="Activity Monitor->Memory" src="https://i.imgur.com/czDcVaK.png"/></a> -<p class="caption">Activity Monitor->Memory</p> -</div> -<p>By the way, Yosemite is indeed really aggressive at RAM usage. I reserve my opinion on whether there's a memory leak. But so far the performance has been fine, even with 8GB of RAM.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-11-26-original-images-in-day-one-journal.html b/build/blog/2014-11-26-original-images-in-day-one-journal.html deleted file mode 100644 index f800f626..00000000 --- a/build/blog/2014-11-26-original-images-in-day-one-journal.html +++ /dev/null @@ -1,64 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-11-26T00:22:16-0800" name="date"/> -<title>Original images in Day One journal</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Original images in Day One journal</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-11-26T00:22:16-0800">November 26, 2014</time> -</div> -</header> -<p><strong>TL; DR:</strong> Jump to the paragraph beginning with “workaround”.</p> -<hr/> -<p>I started a Day One journal two days ago. I've heard good things about Day One, but after using it for a dozen entries, I'm not that satisfied. For one thing, the editor is pretty horrible — keybindings aside, I can’t even find and replace?! And the overview doesn’t look very pretty if you are a heavy Markdown user (i.e., you have a lot of markups, e.g., italics and inline links) — the markups are displayed as is. Moreover, I can’t even <code>#</code> my title: it kills the bold font rendering in the bird’s-eye view. What a let down. Anyway, it’s better than nothing, and I hope it will help me keep on track. (I used to manage a Markdown journal in an encrypted sparse bundle, and it was a pain in the ass — mentally. Maybe some GUI sugar is necessary, although Day One is certainly not as pretty as advertised.) Also a private journal means more privacy — I certainly don’t want to publish everything I write on this public blog.</p> -<p>Too much irrelevant talking. Onto one of the most annoying “features”, and the subject of this post. Images are automatically JPEG-compressed when imported into Day One. See <a href="https://dayone.zendesk.com/hc/en-us/articles/200145875-Are-photos-resized-when-imported-into-Day-One-">this support article</a>, which says:</p> -<blockquote> -<p>Every photo imported into Day One is converted to JPEG format and resized to a maximum resolution of 2100 x 2100 pixels. The aspect ratio is maintained. We resize photos for more efficient sync and storage. At this size the average photo is about 700KB which means you can store: * Dropbox: 2,500+ photos using the free 2GB account * iCloud: 6,000+ photos using the free 5GB account</p> -</blockquote> -<p>What the heck. Dude, who cares about storage these days? And transfer rate? I have a gigabit Ethernet. I certainly have much more than 2GB in my Dropbox. Even for those underpriviledged folks with only 2GB, remember, Day One allows <em>only one photo per entry</em>. That’s 2,500+ entries. At any rate, this should be an opt-in rather than an uncustomizable “feature”. I’m about to submit a ticket, but I doubt the outcome (I’m sure many people have submitted tickets about the plain text format even when password-protected, but so far, no response).</p> -<p>With photos, most of the time JPEG compression works pretty well (but people surely want to keep photos in highest quality). However, I’m a techie guy, and my images are often screenshots or precision images, where JPEG compression totally ruins the sharpness.</p> -<p>Workaround? Simple (yet a bit annoying). Day One lets you show the photo in Finder. So just go ahead and replace that compressed image with the original using <code>cp</code> or <code>mv</code>. I shouldn’t have needed to do this, but every piece of software comes with some annoyances. Overall Day One’s pretty good — at least it does what it was designed for, albeit not perfectly.</p> -<hr/> -<p>By the way, here is my support ticket:</p> -<blockquote> -<p>I understand that Day One does JPEG compression to every imported photo, as written in the support article “Are photos resized when imported into Day One?” http://goo.gl/Rzi017 . Yet I beg an option. The reason is that the benefits outlined in the support article are virtually non-existent:</p> -<ul> -<li><p>“More efficient sync and storage”: these days transfer rates are really high with SSDs and gigabit Ethernet, so reducing a few hundred KBs won’t help me the slightest;</p></li> -<li><p>“Dropbox: 2,500+ photos using the free 2GB account”: I have much more than 2GB in my Dropbox; even if I only have 2GB, Day One allows only one photo per entry, and that means 2,500+ entries with photos, which is more than enough for most users, I suppose. By the way, Dropbox storage shouldn’t be your concern; people will buy more when they need more.</p></li> -</ul> -<p>And some of the bad things about JPEG compression:</p> -<ul> -<li><p>JPEG compression usually works pretty well with photos, but when I import high precision images, the sharpness is totally ruined;</p></li> -<li><p>People want to keep their photos in highest quality, which is defeated by forced compression.</p></li> -</ul> -<p>I know an ugly workaround, which is simply replace the compressed image with the original in the filesystem. But I would love to see an option to import images as originals (in fact, compression should be an opt-in). Really, transfer rates and storage grow so rapidly that they are not people’s primary concerns anymore. (For your information, OneDrive recently rolled out truly unlimited storage to Office 365 subscribers. Online storage is that cheap.) Thanks.</p> -</blockquote> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-11-28-given-infinite-time.html b/build/blog/2014-11-28-given-infinite-time.html deleted file mode 100644 index 0d7fc4e4..00000000 --- a/build/blog/2014-11-28-given-infinite-time.html +++ /dev/null @@ -1,40 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-11-28T00:18:19-0800" name="date"/> -<title>Given infinite time</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Given infinite time</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-11-28T00:18:19-0800">November 28, 2014</time> -</div> -</header> -<p>Given infinite time. There's so much I can do <em>given infinite time</em>. I don't think I'll ever be bored. But sadly the time assigned to each human being is finite. Actually it's epsilon, epsilon approaching zero. Sadly.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-11-28-going-diceware.html b/build/blog/2014-11-28-going-diceware.html deleted file mode 100644 index 271b46e0..00000000 --- a/build/blog/2014-11-28-going-diceware.html +++ /dev/null @@ -1,42 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-11-28T19:05:59-0800" name="date"/> -<title>Going Diceware</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Going Diceware</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-11-28T19:05:59-0800">November 28, 2014</time> -</div> -</header> -<p>Today I'm officially going <a href="http://world.std.com/~reinhold/diceware.html">Diceware</a>. I published my simple C implementation of diceware on <a href="https://github.com/zmwangx/diceware">GitHub</a>.</p> -<p>I've been using 1Password for a couple years now, and I've always been a bit worried about my master password. It's a ~30 byte monster with uppercase, lowercase letters, numbers, and special symbols. By any measure it is very safe. The problem is there are (extremely) personal things in there. I assembled several unrelated things that I (secretly) hold dearest to my heart, obfuscated them with rules not found in best64, and mixed with semi-gibberish. My daily login password is a combo similar in nature, with less obfuscation to facilitate typing. People who dig really deep into my identity might be able to compromise it (or not); I'm afraid that I'm more predictable than I thought I was. I know, the worry is pretty much unwarranted, as I’m not likely the target of a focused attack — I’m neither rich nor equipped with sensitive information or power, and for wide-range exploits, 99.9% of people are lower-hanging fruits. Even for a targeted attack, <a href="http://xkcd.com/538/">xkcd 538: Security</a> broke a crypto nerd’s imagination with a $5 wrench. However, a geek is a geek, you can’t block a geek’s imagination.</p> -<p>Therefore, after worrying for so long, today I’m going Diceware. Eight diceware words give you at least 100 bits of true entropy. Unfortunately I don’t have a die, and don’t bother to get one. (Amazon Prime: get it Monday? No. Target, six miles away? No.) So I read my random bits from <code>/dev/urandom</code>. The C implementation is <a href="https://github.com/zmwangx/diceware">here</a>. By publishing this I’m announcing to the world that I’m using diceware. But I’m not afraid, since I’m now protected by true entropy that’s not compromised by publishing the scheme.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-11-30-opera-style-advanced-keyboard-shortcuts-in-safari.html b/build/blog/2014-11-30-opera-style-advanced-keyboard-shortcuts-in-safari.html deleted file mode 100644 index c6b44b26..00000000 --- a/build/blog/2014-11-30-opera-style-advanced-keyboard-shortcuts-in-safari.html +++ /dev/null @@ -1,68 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-11-30T17:20:20-0800" name="date"/> -<title>Opera-style advanced keyboard shortcuts in Safari</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/highlight.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Opera-style advanced keyboard shortcuts in Safari</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-11-30T17:20:20-0800">November 30, 2014</time> -</div> -</header> -<p>I've been using the Chromuim Opera for a long time, after Chrome's design went unbearably ugly around v32 (IIRC Opera stable channel was on v19 when I switched, which was released on January 28, 2014). From then on, Opera's <a href="http://help.opera.com/opera/Mac/1583/en/fasterBrowsing.html#advanced">advanced keyboard shortcuts</a> has become an integral part of my browsing habit. In particular, the following are especially handy for me:</p> -<ul> -<li><code>1</code>: Cycle left through tabs;</li> -<li><code>2</code>: Cycle right through tabs;</li> -<li><code>/</code>: Find on page;</li> -<li><code>Z</code>: Go back one page;</li> -<li><code>X</code>: Go forward one page;</li> -<li><code>0</code>: Zoom in;</li> -<li><code>9</code>: Zoom out;</li> -<li><code>6</code>: Reset zoom to 100%.</li> -</ul> -<p>Lately, with the Yosemite release, Safari has become a much more competitive browser. I won't say why, and I admit that it has major missing features that still prevents it from becoming my default — but I have to say I’m gradually moving more of more of my browsing, especially reading, to Safari. It would be nice if I could carry my power user shortcuts with me. Fortunately, this is possible. Just modify the plist in the following way:</p> -<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="co">#!/usr/bin/env bash</span> -<span class="ex">defaults</span> write com.apple.Safari NSUserKeyEquivalents <span class="st">'{</span> -<span class="st">"Actual Size"="6";</span> -<span class="st">"Back"="z";</span> -<span class="st">"Find..."="/";</span> -<span class="st">"Forward"="x";</span> -<span class="st">"Show Previous Tab"="1";</span> -<span class="st">"Show Next Tab"="2";</span> -<span class="st">"Zoom In"="0";</span> -<span class="st">"Zoom Out"="9";</span> -<span class="st">}'</span></code></pre></div> -<p>Relaunch Safari. You are all set! Enjoy the ultrafast single key navigating experience. To reset,</p> -<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">defaults</span> delete com.apple.Safari NSUserKeyEquivalents</code></pre></div> -<hr/> -<p><strong><em>2014/12/22 Update:</em></strong></p> -<p>There's one caveat to this approach — unlike in Opera, where the default layman shortcuts (e.g., ⌘F) are still available when advanced keyboard shorts are enabled, in Safari they are simply overwritten. This is annoying when the web page or web app binds certain keys, especially <code>/</code> to its own search bar (a notable example being google.com). In that case I have to admit defeat and click on the menu bar item, which takes a hundred times as long as a single <code>/</code> keystroke.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-12-05-distraction-free-writing.html b/build/blog/2014-12-05-distraction-free-writing.html deleted file mode 100644 index 1e30ddd0..00000000 --- a/build/blog/2014-12-05-distraction-free-writing.html +++ /dev/null @@ -1,65 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-12-05T21:09:10-0800" name="date"/> -<title>Distraction free writing</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Distraction free writing</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-12-05T21:09:10-0800">December 5, 2014</time> -</div> -</header> -<p>This is not the first time that a distraction free writing app is featured on the Mac App Store. This time the candidate is <a href="https://itunes.apple.com/us/app/desk/id915839505?mt=12">Desk</a>. The official website is <a href="http://desk.pm">here</a>, but licensing is MAS-exclusive. The icon looks like this:</p> -<div class="figure"> -<a href="https://i.imgur.com/OprXSEU.png" target="_blank"><img alt="The icon of Desk" src="https://i.imgur.com/OprXSEU.png"/></a> -<p class="caption">The icon of Desk</p> -</div> -<p>Skeuomorphism, oh man. And this is the only screenshot I can find on the official website:</p> -<div class="figure"> -<a href="https://i.imgur.com/WBaYzho.png" target="_blank"><img alt="Screenshot of editing in Desk" src="https://i.imgur.com/WBaYzho.png"/></a> -<p class="caption">Screenshot of editing in Desk</p> -</div> -<p>I can find a few other screenshots on MAS, but you know how shitty MAS screenshots are, plus the screenshots of this app only focus on specific UI elements. The official website also features an intro video (which provides no information at all) and a brief feature list with no further details, all on one page. The MAS description is somewhat more comprehensive, but again, "WordPress integration" and the like are not so informative. So, after a certain amount of research, I have to say I know little about this app. To do the app justice, there's an <a href="http://blog.desk.pm">accompanying blog</a>, with all kinds of noise though — like what a good blog should be, no complaint about that. So I guess anyone who wants to know more about this app should go digging there. Not me, so I didn't read.</p> -<p>Strangely enough, reception is great, although the price tag is currently set at $30 — definitely a premium price. John Gruber <a href="http://daringfireball.net/linked/2014/11/22/desk">has a piece</a>, but I think "My thanks to Johb Saddington for sponsoring this weeks' DF RSS feed to promote Desk, his blogging app for the Mac" kind of defeats credability. MAS featuring is also a good sign (although not always). Out of the 55 MAS ratings at the time of writing (9:42 PM, Friday, December 5, 2014), 45 are five stars.</p> -<p>That brings home my curiosity about "distraction free writing apps" in general. <em>Why would anyone pay $30 for a "distraction free writing app" (which basically justifies any lack of feature — "we deliberately give you no choice for anything so you can focus on writing!"), <strong>without even a trial</strong>?</em> MAS is such a bad model for utility and productivity software since you can't just look at five screenshots (seriously?) and decide "this is for me!" Yet I have the impression that more developers prefer this model nowadays, especially in this focused-writing business, another example being IA Writer. Sure it makes licensing and combating piracy simple, but again, I need to feel it to decide if it's the right tool for me, especially for a feature-deprived focused-writing app. (This is a general thought — in this case I don't need to feel it to tell that it's not for me.)</p> -<p>More specifically, let's think about distraction free writing. What does IA Writer, or Desk, or other apps offer that's not already available to you with your OS? They support Markdown syntax highlighting, or even WYSYWYG (but only the very simple kind of WYSYWYG limited by the Markdown feature set), sure. They support some select-and-click type of formatting (by the way, Desk's formatting tools look a lot like those found on medium.com), which is good for some who are not competent enough to type simple markups, I guess. Desk supports drag-and-drop of media (although I'm sure it's limited to certain platforms and not portable at all — I always upload images to Imgur and embed the Imgur links, which is super simple for me since I have several homemade scripts to take care of that). So are these features essential? Not at all. For the general public, plain Markdown without rendering should be more than enough, since Markdown was designed to be human-readable as plain text in the first place. Markdown only gets ugly when you have a lot of inline hyperlinks, or worse still, plain HTML tags, but that's not what I would expect from the general public. The technical population who do probably need the rendering, on the other hand, aren't the target audience of these apps; certain needs of the technical folks are hardly ever addressed by these feature-deprived focused-writing apps — e.g., where are my keybindings (full-featured, not just C-k, C-y, C-p, C-n, C-b, C-f, M-del, etc.; in particular, what about M-d, M-b, etc.)? What about custom Markdown engine? What about Jekyll integration (no need for that, actually — I'm happy with tty)? So, to sum up, for the target audience, realtime rendering isn't necessary, although I guess people with technophobia hate to see markups like <code>**</code> so no rendering will kill them. Second point, select-and-click type of formatting, is already dismissed. Third point, drag-and-drop of media might be useful for some people, but not all. After all, Desk uses a typewriter as its icon, and there's no way you could throw photos into your typewriter. It's about writing, and most of the time writing is enough.</p> -<p>I have dismissed the "additional features" of focused-writing apps as non-essential. And I can argue that they are actually sources of distraction — as soon as you have WYSYWYG and formatting and mouse, you could, in principle, begin to fiddle. But when I say "additional features", you might ask, "additional" compared to what? Okay here's the magic. The magic is designed by Apple in California®, and it's present on every single Mac running OS X. It's called TextEdit.app. Distraction free? How can you be more distraction free than this:</p> -<div class="figure"> -<a href="https://i.imgur.com/z3LEu0U.png" target="_blank"><img alt="TextEdit: The most distraction free writing experience on the Mac. Designed by Apple in California." src="https://i.imgur.com/z3LEu0U.png"/></a> -<p class="caption">TextEdit: The most distraction free writing experience on the Mac. Designed by Apple in California.</p> -</div> -<p>It's either text or blank. Nothing else. It's more than capable of handling plain text, our best friend (and computer's best friend — the universal interface). You can customize the font once and for all, or you can even live with the factory setting. That's better than having a font you don't like forced upon you, as many of those focused-writing apps do. You can even auto save to iCloud if you'd like to. Of course there's no one click publishing or timeline management or whatever, but you could leave that to a publishing app (like Desk, when used as a publishing app). Better yet, you can use Jekyll or Octopress or whatever command line solution, where everything is at your fingertip, a few keystrokes away. No limitation whatsoever. But that's out of question for most people. (The easy-to-use command line interface, and not needing to worry about hosting myself, are two of the primary reasons that brought me to Octopress on GitHub Pages, rather than wordpress.com or self-hosted wordpress.org).</p> -<p>Of course I'm not saying TextEdit is good enough as a text editor (it is good enough for most people, though), or it is my text editor of choice. My text editor has always been Emacs, which can be distraction free when I need it to be (I've hidden everything I feel like to hide), and which can be an almost feature-complete operating system when I need it to be. Apart from a slightly frustrating loading time, there's no such bullshit as "we deliberately left no feature and no choice to you so you won't fiddle." Mostly importantly, it is extensible — I can start writing Elisp right away, and every single line of code I write can potentially save me thousands of keystrokes in the future; I don't need to submit a feature request to the developer and wait forever (usually power users' feature requests are ignored, unless the software was built for power users to begin with or mainly popular within power users). Plus Emacs is free (both as in beer and in speech), rather than being proprietary and costing $30. At any rate, when I'm writing in Emacs, most of the time I'm just furiously typing away — no distraction whatsoever. That's the ideal state of writing, and I feel really good at those moments. That's the main charm of writing, at least to me.</p> -<div class="figure"> -<a href="https://i.imgur.com/2Jx9Mpv.png" target="_blank"><img alt="Editing in iTerm2 + Emacs + Solarized Dark. Paradise." src="https://i.imgur.com/2Jx9Mpv.png"/></a> -<p class="caption">Editing in iTerm2 + Emacs + Solarized Dark. Paradise.</p> -</div> -<p>The whole command line experience is awesome (most of what I do with the computer are either done in the browser or in iTerm2 — well, plus some time spent with PDF in Preview.app and some with emails in Mail.app). And most of my tools either ship with the operating system (OS X is a great operating system), or are FOSS. Things that hardly ever die. Of course the command line experience is infeasible for laymen, but my argument is, <strong>most of the time the things you need are already there, e.g., TextEdit.</strong> I feel bad about those folks who are constantly on the lookout for distraction-free writing apps, and pay a ridiculous amount for them — only to distract themselves. Just open TextEdit and type away (or if you're capable of it, Emacs or Vim or SublimeText or TextMate or BBEdit or whatever). That's the most productive thing to do. <strong>Publishing is not the top priority; writing is, and it's really simple.</strong></p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-12-10-omnifocus-change-sync-behavior-mac-and-ios.html b/build/blog/2014-12-10-omnifocus-change-sync-behavior-mac-and-ios.html deleted file mode 100644 index 4f5edfec..00000000 --- a/build/blog/2014-12-10-omnifocus-change-sync-behavior-mac-and-ios.html +++ /dev/null @@ -1,51 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-12-10T22:45:34-0800" name="date"/> -<title>OmniFocus: change sync behavior, Mac and iOS</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">OmniFocus: change sync behavior, Mac and iOS</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-12-10T22:45:34-0800">December 10, 2014</time> -</div> -</header> -<p>On OS X, the following URIs are relevant:</p> -<ul> -<li><a href="omnifocus:///change-preference?MaximumTimeBetweenSync=30">omnifocus:///change-preference?MaximumTimeBetweenSync=30</a></li> -<li><a href="omnifocus:///change-preference?TimeFromFirstEditToSync=2">omnifocus:///change-preference?TimeFromFirstEditToSync=2</a></li> -</ul> -<p>What they do are self-evident.</p> -<p>On iOS, use the following URIs instead:</p> -<ul> -<li><a href="x-omnifocus-debug:set-default:MaximumTimeBetweenSync:60">x-omnifocus-debug:set-default:MaximumTimeBetweenSync:60</a></li> -<li><a href="x-omnifocus-debug:set-default:TimeFromFirstEditToSync:2">x-omnifocus-debug:set-default:TimeFromFirstEditToSync:2</a></li> -</ul> -<p>Source: <a href="http://www.macstories.net/links/change-default-sync-times-of-omnifocus-for-mac-and-ios/">Change Default Sync Times of OmniFocus For Mac and iOS</a>.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-12-13-the-mac-like-evernote.html b/build/blog/2014-12-13-the-mac-like-evernote.html deleted file mode 100644 index cf92fdd7..00000000 --- a/build/blog/2014-12-13-the-mac-like-evernote.html +++ /dev/null @@ -1,43 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-12-13T21:47:31-0800" name="date"/> -<title>The Mac-like Evernote</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">The Mac-like Evernote</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-12-13T21:47:31-0800">December 13, 2014</time> -</div> -</header> -<p>Once in a while (maybe a year, maybe several months — not set in stone), I give big name free services not in use a chance to convince me. Evernote is one such service. The interface used to look very cheap and cluttered. I hated it. However, this time I'm sold. Now everything Evernote, from its Mac app to its iOS app to its web design to its physical products, looks distinctively Mac-like. (I use Mac-like to refer to Apple's design philosophy, including iOS. Well, I guess the Android and Windows apps aren't Mac-like.) I mean, just look at the screenshots:</p> -<p><a href="https://i.imgur.com/AZelofm.png" target="_blank"><img alt="Web UI, beta" src="https://i.imgur.com/AZelofm.png"/></a> <a href="https://i.imgur.com/tZuWBlY.png" target="_blank"><img alt="Evernote Market, Pfeiffer Collection" src="https://i.imgur.com/tZuWBlY.png"/></a> <a href="https://i.imgur.com/R4QF8OM.png" target="_blank"><img alt="Mac app" src="https://i.imgur.com/R4QF8OM.png"/></a></p> -<p>Bright, simplistic, elegant, clutter-free. Mac-like. The Mac app takes advantage of the translucent material of Yosemite, and it looks gorgeous. The iOS app also feels great on a full HD Retina screen; I didn't bother to take a screenshot. Now it's much likely that I'll put it into good use — cluttered and cheap-looking interfaces give me nightmares and actually hinders my productivity, and now they are gone.</p> -<p>No one can argue that Apple products make great screenshots. They are also much more intuitive, functional, and productive than most Windows folks are willing to believe. I hope our world is more Mac-like.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-12-14-speeding-up-emacs-with-emacsclient.html b/build/blog/2014-12-14-speeding-up-emacs-with-emacsclient.html deleted file mode 100644 index 55ce35c9..00000000 --- a/build/blog/2014-12-14-speeding-up-emacs-with-emacsclient.html +++ /dev/null @@ -1,63 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-12-14T10:06:02-0800" name="date"/> -<title>Speeding up Emacs with emacsclient</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/highlight.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Speeding up Emacs with emacsclient</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-12-14T10:06:02-0800">December 14, 2014</time> -</div> -</header> -<p>Emacs is notorious for its loading time. For me, this is especially annoying when I'm editing LaTeX files — AUCTeX takes about five seconds to load, and once I exit Emacs (especially after a quick edit), all that work is wasted, and next time I want to do some quick editing with that same LaTeX file — sorry, another five seconds.</p> -<p>This problem can be solved by "using that same Emacs", i.e., running Emacs in server mode, then connecting to the server via <code>emacsclient</code>. Below is my script, which I call <code>emc</code>, to make <code>emacsclient</code> more user-friendly. <code>emc</code> opens a file (given as <code>$1</code>) on the server, launching one on its way if none is detected. Note that I used <code>-cqta=</code> for <code>emacsclient</code>. The <code>-c</code> option is <code>--create-frame</code>, i.e., create a new frame (in the current tty, for instance) instead of using the existing frame (in another tty, for instance); this allows for multiple frames accross different ttys. The <code>-q</code> option is for <code>--quiet</code>, suppressing messages like "Waiting for Emacs..." The <code>-t</code> option is for <code>--tty</code>, or equivalently, the familiar <code>-nw</code> option of <code>emacs</code>. The <code>-a=</code> options is <code>--alternate-editor=</code>; according to the manpage, <code>-a, --alternate-editor=EDITOR</code> has the following effect:</p> -<blockquote> -<p>if the Emacs server is not running, run the specified editor instead. This can also be specified via the `ALTERNATE_EDITOR' environment variable. If the value of EDITOR is the empty string, run `emacs --daemon' to start Emacs in daemon mode, and try to connect to it.</p> -</blockquote> -<p>Note that <code>emacsclient</code> requires a filename, so my script prompts for one if <code>$1</code> is empty.</p> -<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="co">#!/usr/bin/env bash</span> -<span class="kw">if [[</span> <span class="ot">-n</span> <span class="va">$1</span><span class="kw"> ]]</span>; <span class="kw">then</span> - <span class="va">file=$1</span> -<span class="kw">else</span> - <span class="kw">while [[</span> <span class="ot">-z</span> <span class="va">${file}</span><span class="kw"> ]]</span>; <span class="kw">do</span> - <span class="bu">read</span> -p <span class="st">'filename: '</span> <span class="va">file</span> - <span class="kw">done</span> -<span class="kw">fi</span> -<span class="ex">emacsclient</span> -cqta= <span class="st">"</span><span class="va">${file}</span><span class="st">"</span></code></pre></div> -<p>Note that using <code>emacsclient</code> has the additional benefit that the same buffer is simultaneously updated accross different ttys (See screenshot, where I opened the current post in two different ttys). This way, you won't face the nasty "file changed on disk" problem when you accidentally edited the same file in another tty session.</p> -<div class="figure"> -<a href="https://i.imgur.com/9KxEWKq.png" target="_blank"><img alt="screen shot of multiple copies of the same buffer" src="https://i.imgur.com/9KxEWKq.png"/></a> -<p class="caption">screen shot of multiple copies of the same buffer</p> -</div> -<p>By the way, remember to re-configure your other programs that uses an external editor. For instance, change <code>$EDITOR</code> to <code>emacsclient -cqta=</code> in your <code>env</code>, and <code>core.editor</code> to <code>emacsclient -cqta=</code> in your <code>~/.gitconfig</code>.</p> -<p><em>Note</em>: if you use <code>emacsclient</code> to edit git commit messages in Git Commit Mode, remember to use <code>C-c C-c</code> (<code>git-commit-commit</code>) to save the commit message rather than using <code>server-edit</code> or <code>C-x C-c</code> to exit Emacs. Otherwise, the <code>COMMIT_EDITMSG</code> buffer will persist in the Emacs server, and you'll be prompted to revert buffer the next time you edit another commit message, which is pretty annoying.</p> -<p>I just started using <code>emacsclient</code>, so the above script might be buggy in certain edge cases. I'll report when I run into issues.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-12-14-the-google-chrome-comic-a-classic.html b/build/blog/2014-12-14-the-google-chrome-comic-a-classic.html deleted file mode 100644 index 09fa98f2..00000000 --- a/build/blog/2014-12-14-the-google-chrome-comic-a-classic.html +++ /dev/null @@ -1,49 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-12-14T17:42:55-0800" name="date"/> -<title>The Google Chrome Comic — A classic</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">The Google Chrome Comic — A classic</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-12-14T17:42:55-0800">December 14, 2014</time> -</div> -</header> -<p>I was cleaning up my Opera bookmarks just now — I'm semi-officially leaving Opera for Safari. Of course, Safari still can't handle everything (e.g., Adblock Plus is still not so good on Safari, YouTubeCenter lags behind and I don't bother to compile myself — yes, I have a certificate, and some power user features simply don't exist), so I'm still going to Opera/Opera beta/Chrome/Firefox for certain tasks. But Safari is very nice. For the first time.</p> -<p>I started out as a Chrome user (well, don't want to recall the IE days), branched out to the Chromium Opera, and now ended up in Safari. Not sure about the future. When I look back, something nostalgic pops up in mind — <a href="http://www.google.com/googlebooks/chrome/">the Google Chrome Comic</a>. I enjoyed it more than once, but I never seemed to have archived it. So here it is, combined into <a href="https://dl.bintray.com/zmwangx/generic/2008-chrome-comic.pdf">one PDF</a>. In fact, you can create the PDF yourself:</p> -<pre><code>seq 0 39 | parallel wget -q http://www.google.com/googlebooks/chrome/images/big/{}.jpg -convert $(ls -v *.jpg) 2008-chrome-comic.pdf</code></pre> -<p>Here I was a bit lazy and used a GNU <code>ls</code> feature: <code>-v</code> for natural sorting of numbers (doesn't work for BSD <code>ls</code>).</p> -<p>And here's page 1 of the comic as a teaser:</p> -<div class="figure"> -<a href="https://i.imgur.com/W5pJTjl.jpg" target="_blank"><img alt="Google Chrome — Behind the Open Source Browser Project" src="https://i.imgur.com/W5pJTjl.jpg"/></a> -<p class="caption">Google Chrome — Behind the Open Source Browser Project</p> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-12-19-app-suggestion-dropzone-3.html b/build/blog/2014-12-19-app-suggestion-dropzone-3.html deleted file mode 100644 index 7973d85f..00000000 --- a/build/blog/2014-12-19-app-suggestion-dropzone-3.html +++ /dev/null @@ -1,42 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-12-19T14:08:57-0800" name="date"/> -<title>App suggestion: Dropzone 3</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">App suggestion: Dropzone 3</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-12-19T14:08:57-0800">December 19, 2014</time> -</div> -</header> -<p>I recently tried and purchased <a href="https://aptonic.com/dropzone3/">Dropzone 3</a>. See a list of features on the linked official website. In short, Dropzone 3 provides an intermediate zone for drag-n-drop. You can use it as a stash (called "Drop Bar" — stacking is available), use it as a shortcut by putting frequently used folders and applications there, or trigger actions by dropping. There are a dozen builtin actions and <a href="https://aptonic.com/dropzone3/actions/">an additional list of readily available actions</a>, covering common web drives, SNS and file sharing sites. <strong>Better yet, you can develop your custom actions with the easy-to-use <a href="https://github.com/aptonic/dropzone3-actions/blob/master/README.md#dzalerttitle-message">Ruby API</a>.</strong> For instance, I wrote a simple Google Translate action, <code>Google Translate.dzbundle</code> (<a href="https://gist.github.com/zmwangx/b27f106a8ba47468a43d">link</a>), based on <a href="https://github.com/soimort/translate-shell">translate-shell</a>. (You know, it's Ruby, so calling external commands and concatenating strings feel at home, as if you are coding in Perl or directly in shell; unlike Python, where you at least need to <code>import subprocess</code> then <code>subprocess.check_output</code> to get the output of an external command, and have to use a bunch of stupid <code>+</code>'s to get your goddamn message to print.)</p> -<p>Although I use the terminal for most tasks, drag-n-drop is still useful and convenient at times, not to mention the custom actions. (And the stock drag-n-drop is kinda hit-and-miss, especially for people like me who are mostly working with windows maximized — except terminal windows.) After using Dropzone 3 for a while, I found it well worth $4.99.</p> -<p>Wait, I didn't mention the pricing? Dropzone 3 is only <a href="https://itunes.apple.com/us/app/dropzone-3/id695406827?ls=1&mt=12">$4.99 on MAS</a>, so get it while supplies last. (Somehow the license is $10 on the developer's online store, so definitely buy from MAS and change to the <a href="https://aptonic.com/dropzone3/sandboxing.php">unsandboxed version</a> later — de-sandboxing is free.) There's also a 15-day free trial.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-12-22-10k-images-on-imgur.html b/build/blog/2014-12-22-10k-images-on-imgur.html deleted file mode 100644 index 89340ccc..00000000 --- a/build/blog/2014-12-22-10k-images-on-imgur.html +++ /dev/null @@ -1,40 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-12-22T12:42:16-0800" name="date"/> -<title>10k images on imgur</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">10k images on imgur</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-12-22T12:42:16-0800">December 22, 2014</time> -</div> -</header> -<p>I happened to check my imgur account just now (haven't been to the web interface for ages), and you know what, I have uploaded 10,744 images since I created the account in February this year! (I've been using imgur for longer than that; previously I uploaded images anonymously.) Most of the 10k images were uploaded via scripts using the API. This again demonstrates the importance of a good API — without the imgur API I wouldn't have been able to upload hundreds of images with a few keystrokes all in a snap, and getting links would be a huge pain in the ass. There are myriad image hosting services out there, but imgur rules 'em all, thanks to its decent API (and also its good CDN and direct image links, of course).</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2014-12-23-mpv-launcher.html b/build/blog/2014-12-23-mpv-launcher.html deleted file mode 100644 index d941073d..00000000 --- a/build/blog/2014-12-23-mpv-launcher.html +++ /dev/null @@ -1,50 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2014-12-23T00:51:05-0800" name="date"/> -<title>mpv launcher</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/highlight.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">mpv launcher</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2014-12-23T00:51:05-0800">December 23, 2014</time> -</div> -</header> -<p><strong><em>04/06/2015 update:</em></strong></p> -<p>I just noticed that <code>daemonize</code> doesn't play too well with the OS; in particular, when you use dark menu bar on OS X Yosemite, apps launched with <code>daemonize</code> won't conform to that. So a native shell solution would be using <code>/bin/zsh</code> and run</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh">mpv <span class="ot">$@</span> <span class="kw">&></span>/dev/null <span class="kw"><</span>/dev/null <span class="kw">&</span>!</code></pre></div> -<p>instead.</p> -<hr/> -<p><a href="http://mpv.io"><code>mpv</code></a> is a nice simplistic video player (fork of MPlayer and mplayer2). The CLI is flawless (and you can run as many instances as you want), but when it comes to the OS X application bundle, there's one major annoyance. Each app bundle could only have one running instance (unless <code>open -n</code>’ed, which is not how sane people use app bundles), and one instance of <code>mpv</code> only supports one video. So, say I'm playing one video with the app bundle, and unsuspectingly opens another in Finder (which is associated to <code>mpv.app</code> by default), then the latter video immediately takes over, and the position in the first video is lost. That happens <em>a lot</em>.</p> -<p>Today I finally gave this issue some serious thought (I've been on a bug report/enhancement request spree these days so it's natural for me to start thinking about enhancements). Turns out that there's a pretty simple workaround. I created an automator app <code>mpv-launcher.app</code> that does one thing: "Run Shell Script" (pass input as arguments)</p> -<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">daemonize</span> /usr/local/bin/mpv <span class="st">"</span><span class="va">$@</span><span class="st">"</span></code></pre></div> -<p>in the shell of your choice (for me the shell of choice is <code>zsh</code> since the env would be readily available from my <code>zshenv</code>). <code>daemonize</code>, as the name suggests, daemonizes the process so that the process doesn't block; this way, <code>mpv-launcher.app</code> immediately quits after launching, making multiple "instances" possible. (<code>daemonize</code> can be installed via <code>brew install daemonize</code>; note that you need to specify the full path of the command to daemonize, which in my case is <code>/usr/local/bin/mpv</code>). And there you go. Associate your video files to <code>mpv-launcher.app</code>. Launch as many instances as you want. Enjoy.</p> -<p>By the way, I also filed an <a href="https://github.com/mpv-player/mpv/issues/1377">enhancement request</a> with <code>mpv-player/mpv</code>. We'll see what the developers can do. Hopefully the app bundle will support multiple videos out of box in the future.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-01-01-os-x-system-ruby-encoding-annoyance.html b/build/blog/2015-01-01-os-x-system-ruby-encoding-annoyance.html deleted file mode 100644 index 89f18c5d..00000000 --- a/build/blog/2015-01-01-os-x-system-ruby-encoding-annoyance.html +++ /dev/null @@ -1,62 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-01-01T22:49:39-0800" name="date"/> -<title>OS X system ruby encoding annoyance</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/highlight.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">OS X system ruby encoding annoyance</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-01-01T22:49:39-0800">January 1, 2015</time> -</div> -</header> -<p>I've been using RVM (with fairly up-to-date Rubies) and pry since my day one with Ruby (well, almost), so it actually surprises me today when I found out by chance how poorly the system Ruby behaves when it comes to encoding.</p> -<p>The major annoyance with the current system Ruby (2.0.0p481) is that it can't convert <code>UTF8-MAC</code> to <code>UTF-8</code> (namely, NFD to NFC, as far as I can tell), at least not with Korean characters. Consider the following script:</p> -<div class="sourceCode"><pre class="sourceCode ruby"><code class="sourceCode ruby"><span class="co"># coding: utf-8</span> -require <span class="st">'hex_string'</span> -str = <span class="st">"에이핑크"</span> -puts str.to_hex_string -puts str.encode(<span class="st">"UTF-8"</span>, <span class="st">"UTF8-MAC"</span>).to_hex_string</code></pre></div> -<p>Here are what I get with the system Ruby and the latested brewed Ruby:</p> -<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="op">></span> <span class="ex">/usr/bin/ruby</span> --version -<span class="ex">ruby</span> 2.0.0p481 (2014-05-08 revision 45883) [<span class="ex">universal.x86_64-darwin14</span>] -<span class="op">></span> <span class="ex">/usr/local/bin/ruby</span> --version -<span class="ex">ruby</span> 2.2.0p0 (2014-12-25 revision 49005) [<span class="ex">x86_64-darwin14</span>] -<span class="op">></span> <span class="ex">/usr/bin/ruby</span> utf8-mac.rb -<span class="ex">e1</span> 84 8b e1 85 a6 e1 84 8b e1 85 b5 e1 84 91 e1 85 b5 e1 86 bc e1 84 8f e1 85 b3 -<span class="ex">e1</span> 84 8b e1 85 a6 e1 84 8b e1 85 b5 e1 84 91 e1 85 b5 e1 86 bc e1 84 8f e1 85 b3 -<span class="op">></span> <span class="ex">/usr/local/bin/ruby</span> utf8-mac.rb -<span class="ex">e1</span> 84 8b e1 85 a6 e1 84 8b e1 85 b5 e1 84 91 e1 85 b5 e1 86 bc e1 84 8f e1 85 b3 -<span class="ex">ec</span> 97 90 ec 9d b4 ed 95 91 ed 81 ac</code></pre></div> -<p>As you can see, in the case of the system Ruby, NFD is left untouched. This leads to problems with, for instance, Google Translate. One obvious solution is to outsource the task to <code>iconv</code>, but I have the impression that outsourcing language features to shell commands is a generally despised practice.</p> -<p>There's one more surprise. While <code>pry</code> with latest Rubies tend to handle Unicode very well (unlike <code>irb</code>), I tried <code>pry</code> with the current system Ruby, and it doesn't work; due to this annoying limitation, I couldn't even test the above problem interactively, and had to resort to a script. Maybe the problem can be resolved by compiling Ruby with <code>readline</code> or whatever; I didn't bother. The bottom line is, the system Ruby is not very pleasant for men in the 21st century — good Unicode support ought to be a must. (By the way, NFD in HFS+ is maddening. It breaks Terminal, iTerm, Google Translate, scp with Linux hosts, and the list goes on.)</p> -<p>P.S. In Dropzone 3 custom actions you can select a custom Ruby with the <code>RubyPath</code> meta field, e.g.,</p> -<div class="sourceCode"><pre class="sourceCode ruby"><code class="sourceCode ruby"><span class="co"># RubyPath: /usr/local/bin/ruby</span></code></pre></div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-01-10-fonts-why-chinese-web-design-is-hard.html b/build/blog/2015-01-10-fonts-why-chinese-web-design-is-hard.html deleted file mode 100644 index df6b0dab..00000000 --- a/build/blog/2015-01-10-fonts-why-chinese-web-design-is-hard.html +++ /dev/null @@ -1,50 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-01-10T09:30:02-0800" name="date"/> -<title>Fonts: why Chinese web design is hard</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Fonts: why Chinese web design is hard</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-01-10T09:30:02-0800">January 10, 2015</time> -</div> -</header> -<p>For years I've been complaining about Chinese websites' horrendous designs. Yesterday I tried to translate one of my simple project websites to Chinese, and finally realized that web design for the Chinese language is no simple task — much harder than for English. The problem is fonts. This might not be the only problem (and cannot take blame for all the horrendous designs), but it certainly seems to be a roadblock.</p> -<p>The problem with fonts boils down to the fact that the Chinese writing system has too many glyphs. I still remember learning things about the GB 2312 charset when I was twelve — there are 3755 Level 1 characters (more commonly seen), 3008 Level 2 characters, and other symbols and foreign glyphs. Designing more than six thousand Chinese characters is so much harder than designing 26 letters. I'm not sure if many glyphs are auto-generated from parts, but that would certainly degrade the quality. The result? Availability of digital fonts suffers. There are simply not so many choices of Chinese fonts. Chinese writing is beautiful, but I've yet to see a font for screens (let alone the web) that conveys that beauty. This might be subjective, but I have the impression that fonts generally look worse on screen than in print, and more so for Chinese fonts (Retina doesn't help much). For the record, I checked Apple's font usage at the moment, and they are using a tailored font named "PingHei" ("平黑", I guess; see screenshot at the end); I'm not at all impressed. Compare that to the English counterpart (also at the end) — not on the same level. (I won't talk about Microsoft since it doesn't feature a design department, or that department is brain dead. Well, I'm a little opinionated.)</p> -<p>Another problem triggered by the vast number of glyphs is that font files are large. I looked at a dozen OTF fonts with SC or TC glyphs, and none seems to be below 10 MB. That's clearly a no go on the web — not until everyone has a gigabit connection, I suppose. I tried to Google for Chinese webfonts and had little success, so I'm not sure if woff helps. I've heard that Apple is able to pack a reduced set of PingHei glyphs into woffs less than 1 MB (keep in mind that PingHei being sans serif is simpler than serif fonts like Songti); that's pretty remarkable. I don't know much about font technologies so I can't comment more on this matter, but from my observation all Chinese websites (with the exception of apple.com/cn, I guess) rely on locally installed fonts, and most don't even have a list of fallbacks, i.e., typefaces simply aren't part of their designs. Even if they do have a list of fallbacks, they won't be able to guarantee uniform experience across the board (as far as I know, the lowest common denominator of Chinese fonts across all platforms seem to be zero). Apple has taught us that design must be integrated and perfected (well, Apple wasn't the first to do design, but they did bring it to the digital world and to the masses). Any fragmented design is doomed to fail.</p> -<div class="figure"> -<a href="https://i.imgur.com/MPmtSJI.png" target="_blank"><img alt="A section of apple.com/cn/iphone-6." src="https://i.imgur.com/MPmtSJI.png"/></a> -<p class="caption">A section of <a href="https://www.apple.com/cn/iphone-6/">apple.com/cn/iphone-6</a>.</p> -</div> -<div class="figure"> -<a href="https://i.imgur.com/hBpdv0B.png" target="_blank"><img alt="The English equivalent." src="https://i.imgur.com/hBpdv0B.png"/></a> -<p class="caption">The English equivalent.</p> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-01-21-web-design-microsoft-vs-apple.html b/build/blog/2015-01-21-web-design-microsoft-vs-apple.html deleted file mode 100644 index 66719464..00000000 --- a/build/blog/2015-01-21-web-design-microsoft-vs-apple.html +++ /dev/null @@ -1,52 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-01-21T16:30:51-0800" name="date"/> -<title>Web design: Microsoft vs Apple</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Web design: Microsoft vs Apple</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-01-21T16:30:51-0800">January 21, 2015</time> -</div> -</header> -<p>I just had a look at Ars's live blog on today's Windows 10 Event to acquire a sense of where Windows is heading. There's not much to report. Safari rip-off (Microsoft's new Spartan — wait, is this name also inspired by Safari? — features reading mode and offline reading list, Safari's killer features) aside, the focus seems to be virtual assistant, PC-tablet-phone integration, and gaming, none of which I'm interested in. The hologram thing does look cool, but putting the hype aside, I doubt if it will be really useful for the masses (except probably in gaming, one of my most despised applications of computing). I'm not a visionary so maybe I'm underestimating this.</p> -<p>(Another interesting development is "Windows as a Service" — WaaS? Microsoft isn't communiating it effectively. If it means paid subscription, am I ever going to subscribe to an OS? No. If it instead means free system updates for the lifetime of a device, then this WaaS thing is just a vacuous buzz phrase — Apple has already been doing it for two years. Longer if you count the cheap upgrades. However, if free system updates is indeed the case, then what about VMs? Not sure.)</p> -<p>The only thing I would like to see Apple copy from Microsoft is the unlimited OneDrive — come on, we already paid enough for our hardware, why can't we have unlimited cloud storage? I would even pay $10 per month for that — Microsoft is offering Office 365 along with unlimited cloud storage, all for just $10, so it certainly won't hurt Apple. The current iCloud pricing is ridiculous.</p> -<p>All the discussions above are not the main point of this post though. The point is, I went to the Windows website to learn more about Windows 10, and just can't believe my eyes in how awful it is designed. Just look at the font and the layout of <a href="http://windows.microsoft.com/en-us/windows-10/about">windows.microsoft.com/en-us/windows-10/about</a> (full web page screenshot courtesy of <a href="http://web-capture.net">web-capture.net</a>). And compare that to <a href="http://www.apple.com/osx/">www.apple.com/osx/</a> (scroll past the Windows screenshot). Holy crap, I even booted my Windows 8.1 VM just to make sure I'm not lacking the necessary fonts available on Windows.</p> -<p>Why Microsoft's web design is so shitty is always beyond my grasp. For OS X, a potential customer would be eager to set his hands on it just by looking at its beautifully-crafted homepage and a few screenshots there. For Windows it's exactly the opposite. I mean, apart from metro apps (worst and ugliest desktop experience ever), modern Windows actually looks pretty good. But their shitty advertising totally ruins it. I guess it doesn't matter much for Microsoft, for all design-savvy folks who are not stuck on Windows are already using OS X, and most of their customers just need a commodity OS.</p> -<div class="figure"> -<a href="https://i.imgur.com/0eIt4SR.png" target="_blank"><img alt="Full height screenshot of windows.microsoft.com/en-us/windows-10/about." src="https://i.imgur.com/0eIt4SR.png"/></a> -<p class="caption">Full height screenshot of <a href="http://windows.microsoft.com/en-us/windows-10/about">windows.microsoft.com/en-us/windows-10/about</a>.</p> -</div> -<div class="figure"> -<a href="https://i.imgur.com/piUO0xY.png" target="_blank"><img alt="Full height screenshot of www.apple.com/osx/." src="https://i.imgur.com/piUO0xY.png"/></a> -<p class="caption">Full height screenshot of <a href="http://www.apple.com/osx/">www.apple.com/osx/</a>.</p> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-02-10-monitor-progress-of-your-unix-pipes-with-pv.html b/build/blog/2015-02-10-monitor-progress-of-your-unix-pipes-with-pv.html deleted file mode 100644 index 474518f5..00000000 --- a/build/blog/2015-02-10-monitor-progress-of-your-unix-pipes-with-pv.html +++ /dev/null @@ -1,85 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-02-10T02:18:30-0800" name="date"/> -<title>Monitor progress of your Unix pipes with pv</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/highlight.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Monitor progress of your Unix pipes with pv</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-02-10T02:18:30-0800">February 10, 2015</time> -</div> -</header> -<p>Recently I found a very useful utility called <code>pv</code> (for "pipe viewer"). <a href="http://www.ivarch.com/programs/pv.shtml">Here</a> is its home page, and it can be easily installed with <code>brew</code>. According to its man page,</p> -<blockquote> -<p><code>pv</code> shows the progress of data through a pipeline by giving information such as time elapsed, percentage completed (with progress bar), current throughput rate, total data transferred, and ETA.</p> -</blockquote> -<p>For more info, see its home page (linked above) and <a href="http://linux.die.net/man/1/pv">man page</a>.</p> -<p>Why is it useful? Well, pretty obvious if you are in the right audience. For me, one particularly important use case is with <code>openssl sha1</code>. I deal with videos on a daily basis, and back up all of them to OneDrive (ever since OneDrive went unlimited). To ensure integrity of transfer (in future downloads), I append the first seven digits of each video to its filename. This should be more than enough to reveal any error in transfer except for active attacks. One additional advantage is that I can now have multiple versions of a same show, event, or whatever and don't have to worry about naming conflicts (and don't have to artificially say <code>-ver1</code>, <code>-ver2</code>, etc.). This little merit turns out to be huge and saves me a lot of trouble, since naming things is intrinsically hard:</p> -<blockquote> -<p>There are only three hard things concurrency, in computer science: cache invalidation, naming things, and off-by-one errors.</p> -</blockquote> -<p>(I learned this beefed up version of two hard things only recently.) Well, too much digression. So SHA-1 sum is useful. (By the way, I learned in my crypto class that SHA-1 is broken as a collision-resistant hash function — not HMAC, which doesn't assume collision-resistance — and SHA-256 should be used instead. However, I'm not protecting against active attacks — I won't be able to without a shared secret key anyway — so the faster SHA-1 is good for my purpose.) But at the same time, SHA-1 is slow. Maybe what's actually slow is my HDD. Whatever the bottleneck, generating a SHA-1 digest for a 10 GB video file isn't fun at all; it's even more of a torture when there's no progress bar and ETA. But hopelessly waiting has become a thing of the past with the advent (well, discovery in my case) of <code>pv</code>. Now I have nice and informative progress bars, which reduces the anxiety of waiting by an order of magnitude.</p> -<p>For the record, here's the current version of my ruby script that attaches the first seven digits of the SHA-1 digests of the given files to their filenames:</p> -<div class="sourceCode"><pre class="sourceCode ruby"><code class="sourceCode ruby"><span class="kw">#!/usr/bin/env ruby</span> - -require <span class="st">'fileutils'</span> - -<span class="kw">def</span> rename(items) - num_items = items.length - num_done = <span class="dv">0</span> - items.each {|path| - printf(<span class="dt">$stderr</span>, <span class="st">"%d/%d: %s\n"</span>, num_done + <span class="dv">1</span>, num_items, <span class="dt">File</span>.basename(path)) - - <span class="kw">if</span> ! <span class="dt">File</span>.directory?(path) - extname = <span class="dt">File</span>.extname(path) - basename = <span class="dt">File</span>.basename(path, extname) - dirname = <span class="dt">File</span>.dirname(path) - sha1sum = <span class="st">`pv '</span><span class="ot">#{</span>path<span class="ot">}</span><span class="st">' | openssl sha1`</span> - new_basename = basename + <span class="st">"__"</span> + sha1sum[<span class="dv">0</span>,<span class="dv">7</span>] - new_path = <span class="dt">File</span>.join(dirname, new_basename + extname) - <span class="dt">FileUtils</span>.mv(path, new_path) - <span class="kw">else</span> - <span class="dt">STDERR</span>.puts(<span class="st">"</span><span class="ot">#{</span>path<span class="ot">}</span><span class="st">: directory ignored"</span>) - <span class="kw">end</span> - - num_done += <span class="dv">1</span> - } -<span class="kw">end</span> - -rename(<span class="dt">ARGV</span>)</code></pre></div> -<p>You might ask why I used ruby (littered with bash) when it's obviously a job for bash or perl. Well, the reason is that I first wrote this thing in ruby as a <a href="https://gist.github.com/zmwangx/d6406fb8bf51ac768770">Dropzone 3 action</a>. I'm lazy, so I just borrowed that script and modified its printout for shell use.</p> -<hr/> -<p>By the way, I also found a project called <code>cv</code> (Coreutils Viewer), which is <a href="https://github.com/Xfennec/cv">officially described as</a></p> -<blockquote> -<p>... a Tiny, Dirty, Linux-Only C command that looks for coreutils basic commands (cp, mv, dd, tar, gzip/gunzip, cat, etc.) currently running on your system and displays the percentage of copied data.</p> -</blockquote> -<p>I'll look into it when I have time, but it from its description, it seems to be limited to coreutils, and OS X support might not be too awesome (at this point).</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-02-17-microsoft-is-getting-cool-but-not-its-website.html b/build/blog/2015-02-17-microsoft-is-getting-cool-but-not-its-website.html deleted file mode 100644 index b8f48620..00000000 --- a/build/blog/2015-02-17-microsoft-is-getting-cool-but-not-its-website.html +++ /dev/null @@ -1,56 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-02-17T18:57:19-0800" name="date"/> -<title>Microsoft is getting cool (but not its website)</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Microsoft is getting cool (but not its website)</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-02-17T18:57:19-0800">February 17, 2015</time> -</div> -</header> -<p>Microsoft is getting kind of cool. For instance, open sourcing .NET last year caused quite a buzz. Ars has a good piece about this: <a href="http://arstechnica.com/information-technology/2015/02/microsofts-continuing-efforts-to-be-cool/">Microsoft’s continuing efforts to be cool</a>.</p> -<p>Three weeks ago Microsoft made another minor but totally unexpected move: they integrated AgileBits' <code>onepassword-app-extension</code> (<a href="https://github.com/AgileBits/onepassword-app-extension">GitHub</a>) into the 5.0 release of the OneDrive iOS app. I didn't realize this until I read <a href="https://blog.onedrive.com/onedrive_secure_password/">yesterday's blog post on the OneDrive Blog</a>. This is really amazing when you put it in context: I mean, take a look at <a href="https://blog.agilebits.com/1password-apps/">Apps that love 1Password</a>, i.e., apps that have integrated that extension. Out of the ninety apps listed to date, there are only a dozen apps that I've heard of, and the only brands bigger than 1Password are Microsoft, Tumblr, Uber (infamous), and Walmart (what?). Microsoft embracing third party is surely an interesting phenomenon.</p> -<p>Meanwhile,</p> -<ul> -<li>Microsoft still won't let us use our password managers to its fullest (of course we can't blame it on the OneDrive folks): 16 characters max in this day and age (screenshot taken today)? Hmm. And I remember Microsoft recently said password length isn't the main source of vulnerability of its customers. WTF. Who cares about <em>your</em> stupid customers. I just want to protect <em>my own</em> data, and make sure that in case of a breach on <em>your</em> side, I won't face the same loss as your technologically illiterate customers. But that's not currently possible with Microsoft.</li> -</ul> -<div class="figure"> -<a href="https://i.imgur.com/CNv76zw.png" target="_blank"><img alt="It's 2015, yet "your password can't be longer than 16 characters"." src="https://i.imgur.com/CNv76zw.png"/></a> -<p class="caption">It's 2015, yet "your password can't be longer than 16 characters".</p> -</div> -<ul> -<li>Microsoft's UI design is still shit, <a href="/blog/2015-01-21-web-design-microsoft-vs-apple.html">as well as their website</a>; I mean, seriously:</li> -</ul> -<div class="figure"> -<a href="https://i.imgur.com/wu66zZc.png" target="_blank"><img alt="What the heck are those blue blocks?" src="https://i.imgur.com/wu66zZc.png"/></a> -<p class="caption">What the heck are those blue blocks?</p> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-02-20-my-dock-and-updated-omnifocus.html b/build/blog/2015-02-20-my-dock-and-updated-omnifocus.html deleted file mode 100644 index 9642afab..00000000 --- a/build/blog/2015-02-20-my-dock-and-updated-omnifocus.html +++ /dev/null @@ -1,57 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-02-20T16:16:10-0800" name="date"/> -<title>My dock and updated OmniFocus</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">My dock and updated OmniFocus</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-02-20T16:16:10-0800">February 20, 2015</time> -</div> -</header> -<blockquote> -<p>Simplicity is the ultimate sophistication.</p> -</blockquote> -<p>Here's a screenshot of my dock at the moment.</p> -<div class="figure"> -<a href="https://i.imgur.com/EhaJw57.png" target="_blank"><img alt="My dock" src="https://i.imgur.com/EhaJw57.png" title="My current dock. Left to right: Finder (TotalFinder), Mail, Safari, Chrome, iTunes, OmniFocus, iTerm2, Activity Monitor, and mpv. Everything except mpv is persistent."/></a> -<p class="caption">My dock</p> -</div> -<p>Left to right: Finder (TotalFinder), Mail, Safari, Chrome, iTunes, OmniFocus, iTerm2, Activity Monitor, and mpv. Everything except mpv is persistent; mpv is there because I happen to be looping a piece of music with mpv that I don't plan to add to the iTunes library. The point is that it never looked this good, mainly due to the updated OmniFocus icon. Finally they put some serious thought into graphics design! Just compare <a href="https://dl.bintray.com/zmwangx/generic/omnifocus-v2.1.icns">the v2.1 icon</a> to <a href="https://dl.bintray.com/zmwangx/generic/omnifocus-v2.0.icns">the v2.0 version</a>.</p> -<div class="figure"> -<a href="https://i.imgur.com/KeTz5wK.png" target="_blank"><img alt="OmniFocus Mac app icon, v2.0 vs v2.1" src="https://i.imgur.com/KeTz5wK.png"/></a> -<p class="caption">OmniFocus Mac app icon, v2.0 vs v2.1</p> -</div> -<p>Obviously the overpolished (and honestly, badly polished) 2.0 one belongs to the past. It "stood out" even among Mavericks dock icons (in terms of color), not to mention among the flattened-down Yosemite ones. Today, it finally becomes a native member of the dock. (Well, actually not today — I've been using the beta for a while, so the new icon didn't come as a surprise.) In fact, this time the Omni Group seems to be on a graphics design streak these days, and today they have a really impressive App Store feature banner:</p> -<div class="figure"> -<a href="https://i.imgur.com/tILmveQ.png" target="_blank"><img alt="OmniFocus's MAS feature banner" src="https://i.imgur.com/tILmveQ.png"/></a> -<p class="caption">OmniFocus's MAS feature banner</p> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-02-21-all-is-not-lost.html b/build/blog/2015-02-21-all-is-not-lost.html deleted file mode 100644 index ece5525f..00000000 --- a/build/blog/2015-02-21-all-is-not-lost.html +++ /dev/null @@ -1,46 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-02-21T17:12:32-0800" name="date"/> -<title>All is not lost</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">All is not lost</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-02-21T17:12:32-0800">February 21, 2015</time> -</div> -</header> -<p>Lubos Motl always attacks the Many-Worlds Interpretation as if it is on the same level as anti-scientific claims. He even went on to attack Hugh Everett (the guy who first formulated this interpretation) personally; <em>ad hominem</em> is of course typical Motl shit, and I don't bother to find those posts. Anyway, here's yet another one: <a href="http://motls.blogspot.com/2015/02/many-worlds-rozali-carroll-exchange.html">Many worlds: a Rozali-Carroll exchange</a>.</p> -<p>Disclaimer: I'm not really a proponent of Many-Worlds, at least not of the part of it that says history really <em>branches</em> into <em>many</em> worlds. Well, Lubos is at least right about one thing: "many worlds", taken literally, can't even be well-defined. However, I do believe that the world is can be described by a "universal wavefunction" (I prefer to call it the "universal state vector") in some gargantuan Hilbert space. And the universal state vector has to evolve deterministically. The reason is simple: <strong><em>all information is not lost</em></strong>. This principle is fundamental to physics and it's simply not on the same level as falsifiability, which is little more than a philosopher's toy and a nice thing to have. In quantum mechanics' terms, <em>unitarity must be respected</em>; this is why the Copenhagen Interpretation, or at least the wavefunction-collapsing part of it, cannot hold up to serious scrutiny — no operator can ever collapse the wavefunction and break unitarity. Those who hold the Copenhagen Interpretation are confusing <em>their</em> lack of knowledge (albeit a fundamental one, as they were entangled into the system when they make an observation) with the fundamental loss of information (which is not possible).</p> -<p>One may question that if the universal state vector is <em>real</em>, then where's all the unavailable information stored (why is there a <em>fundamental</em> lack of knowledge)? Well, who told you that all information in this universe can be observed or written down? Everything outside our event horizon is also unavailable to us, yet modern physics knows for sure that some of those <em>do</em> exist. Of course we have a hierarchy of belief in the existence of different things, with the universal state vector being hard to believe (and very hard to not believe) or make sense of. But there's no hard cut, and we might some day be able to reason about it.</p> -<p>I don't know how exactly the observed universe is the way it is (i.e., how exactly it fell — or "collapsed", which is a convenient word for communication — into the eigenstate that we observed). I'm not even sure if the observed universe is the way it is in the objective (ontological) sense — if there were no observers, would it just be an "uncollapsed" state vector? I suspect that this problem has something to do with consciousness, and I suspect that we are at least hundreds of years from understanding consciousness. (Of course this kind of predictions are all nonsense — no one can look thirty years into the future). At the very least, we may eliminate some possibilities when we know more about consciousness. At any rate, this is an interesting problem that might be outside the capability of human reason, or might not. One may hate it and refuse to talk about it, but one cannot dismiss it as unphysical.</p> -<p>When Lubos dismisses <em>ontology</em> as "exactly the same thing" as classical physics, he's dismissing the problem above, and making a hard compromise. He's basically saying that we cannot and should not reason about anything outside of what we can observe (this is also a crude classification because obviously he reasons beyond black hole horizons every day). This compromise is very dangerous for physics — sometimes one has to reason beyond one's horizon to formulate a complete and consistent answer. Black holes are one good example of getting of the limit. If we can extend spacetime beyond our event horizon, then why can't we accept <strong><em>the possibility of existence</em></strong> outside our "existence horizon", i.e., outside our perceived existence of the universal (and the first hand experience of our own existence inside it)? It's a wild and not well-defined idea, but all new physics starts out not well-defined.</p> -<p>I still remember the last lecture of my first quantum mechanics course in my freshman year, taught by Prof. Michael Peskin. He discussed the interpretations of quantum mechanics. I forgot the exact arguments, but after rejecting other interpretations (including Copenhagen and hidden variable), he resorted to Many-Worlds, citing "Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth." I was not particularly satisfied. To me, once you eliminate the impossible, if whatever remains is still improbable, then maybe your imagination is not wild enough. I also remember the second time I took QM I, this time the graduate version, taught by Prof. Lenny Susskind. He stressed unitarity so much and showed us how wavefunction-collapsing is unnecessary (it was never well-defined anyway, unless you impose it). Unitarity is so important that triggered his "black hole war".</p> -<p>The point of mentioning my two professors is that the interpretation problem of quantum mechanics has never been settled, and people who hold opinions contrary to Copenhagen should be respected. Lubos, on the other hand, tries to convince people that this problem has been settled, and actually settled for ninety years. He is either lying or delusional himself.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-02-24-the-new-onedrive-api.html b/build/blog/2015-02-24-the-new-onedrive-api.html deleted file mode 100644 index cb67b3f5..00000000 --- a/build/blog/2015-02-24-the-new-onedrive-api.html +++ /dev/null @@ -1,41 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-02-24T18:31:19-0800" name="date"/> -<title>The new OneDrive API</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">The new OneDrive API</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-02-24T18:31:19-0800">February 24, 2015</time> -</div> -</header> -<p>Microsoft released the new OneDrive API today. See the blog post announcement <a href="https://blog.onedrive.com/the-new-onedrive-api/">here</a>. One highlight is that <a href="http://onedrive.github.io/items/upload_large_files.htm">large file upload</a> is now officially supported. Previously, large file upload was handled with a semi-official API using the BITS protocol; the only documentation was a <a href="https://gist.github.com/rgregg/37ba8929768a62131e85">gist</a>. Now it is handled through standard HTTP <code>POST</code>. With this major release, there's likely a lot of work to be done with <a href="https://github.com/mk-fg/python-onedrive">python-onedrive</a>. I have opened an issue: <a href="https://github.com/mk-fg/python-onedrive/issues/52">mk-fg/python-onedrive#52 — New OneDrive API support</a>.</p> -<p>Interestingly, the new OneDrive API doc is hosted on GitHub Pages — <a href="http://onedrive.github.io">onedrive.github.io</a>, rather than MSDN. Exactly a week ago I wrote a piece, "<a href="/blog/2015-02-17-microsoft-is-getting-cool-but-not-its-website.html">Microsoft is getting cool (but not its website)</a>". Looks like they are doing something about their website (or better put, their online identity), too.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-03-22-back-up-os-x-app-icons.html b/build/blog/2015-03-22-back-up-os-x-app-icons.html deleted file mode 100644 index e243c42f..00000000 --- a/build/blog/2015-03-22-back-up-os-x-app-icons.html +++ /dev/null @@ -1,74 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-03-22T16:58:50-0700" name="date"/> -<title>Back up OS X app icons</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/highlight.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Back up OS X app icons</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-03-22T16:58:50-0700">March 22, 2015</time> -</div> -</header> -<p>OS X application icons are valuable assets, and it's interesting to see how they evolve over time. This is especially the case when we upgraded to OS X 10.10 Yosemite, when Apple and many design-aware third party developers overhauled (mainly flattened) their icons.</p> -<p>However, we lose all the old icons when we do a major OS upgrade. Technically they still live in Time Machine backups, but those are a pain to pull out. Therefore, I wrote a script just now to back up app icons of all applications living in <code>/Applications</code> (including those symlinked to <code>/Applications</code>, e.g., apps installed through <code>brew cask</code>) and its level-one subdirectories, and <code>/System/Library/CoreServices</code> (for <code>Finder.app</code> and such). Here's the script:</p> -<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="co">#!/usr/bin/env bash</span> -<span class="kw">function</span><span class="fu"> app_version</span> -<span class="kw">{</span> - <span class="co"># $1 is the path to the app</span> - <span class="ex">/usr/libexec/PlistBuddy</span> -c <span class="st">"print CFBundleShortVersionString"</span> <span class="st">"</span><span class="va">$1</span><span class="st">"</span>/Contents/Info.plist <span class="op">2></span>/dev/null <span class="kw">||</span> <span class="fu">date</span> +%Y%m%d -<span class="kw">}</span> - -<span class="kw">function</span><span class="fu"> app_icon_path</span> -<span class="kw">{</span> - <span class="co"># $1 is the path to the app</span> - <span class="va">filename=$(</span><span class="ex">/usr/libexec/PlistBuddy</span> -c <span class="st">"print CFBundleIconFile"</span> <span class="st">"</span><span class="va">$1</span><span class="st">"</span>/Contents/Info.plist <span class="op">2></span>/dev/null<span class="va">)</span> - [[ <span class="ex">-n</span> <span class="va">${filename}</span> ]] <span class="kw">||</span> <span class="bu">return</span> - <span class="va">filename=$(</span><span class="fu">basename</span> <span class="st">"</span><span class="va">${filename}</span><span class="st">"</span> .icns<span class="va">)</span> - <span class="bu">echo</span> <span class="st">"</span><span class="va">$1</span><span class="st">/Contents/Resources/</span><span class="va">${filename}</span><span class="st">.icns"</span> -<span class="kw">}</span> - -<span class="kw">function</span><span class="fu"> process_app</span> -<span class="kw">{</span> - <span class="co"># $1 is the path to the app</span> - <span class="va">name=$(</span><span class="fu">basename</span> <span class="st">"</span><span class="va">$1</span><span class="st">"</span> .app <span class="kw">|</span> <span class="fu">tr</span> -d <span class="st">' '</span><span class="va">)</span> - <span class="va">path=$(</span><span class="ex">realpath</span> -e <span class="st">"</span><span class="va">$1</span><span class="st">"</span><span class="va">)</span> <span class="kw">||</span> <span class="kw">{</span> <span class="bu">echo</span> <span class="st">"</span><span class="va">${RED}</span><span class="st">error: broken link '</span><span class="va">${path}</span><span class="st">'</span><span class="va">${RESET}</span><span class="st">"</span> <span class="op">>&2</span><span class="kw">;</span> <span class="bu">return</span> 1<span class="kw">;</span> <span class="kw">}</span> - <span class="va">version=$(</span><span class="ex">app_version</span> <span class="st">"</span><span class="va">${path}</span><span class="st">"</span><span class="va">)</span> - <span class="va">icon_path=$(</span><span class="ex">app_icon_path</span> <span class="st">"</span><span class="va">${path}</span><span class="st">"</span><span class="va">)</span> - [[ <span class="ex">-n</span> <span class="va">${icon_path}</span> ]] <span class="kw">||</span> <span class="kw">{</span> <span class="bu">echo</span> <span class="st">"</span><span class="va">${YELLOW}</span><span class="st">warning: '</span><span class="va">$1</span><span class="st">' has no app icon</span><span class="va">${RESET}</span><span class="st">"</span><span class="kw">;</span> <span class="bu">return</span> 1<span class="kw">;</span> <span class="kw">}</span> - [[ <span class="ex">-f</span> <span class="va">${icon_path}</span> ]] <span class="kw">||</span> <span class="kw">{</span> <span class="bu">echo</span> <span class="st">"</span><span class="va">${RED}</span><span class="st">error: '</span><span class="va">${icon_path}</span><span class="st">' does not exist</span><span class="va">${RESET}</span><span class="st">"</span> <span class="op">>&2</span><span class="kw">;</span> <span class="bu">return</span> 1<span class="kw">;</span> <span class="kw">}</span> - <span class="fu">cp</span> <span class="st">"</span><span class="va">${icon_path}</span><span class="st">"</span> <span class="st">"</span><span class="va">${name}</span><span class="st">-</span><span class="va">${version}</span><span class="st">.icns"</span> - <span class="bu">echo</span> <span class="st">"</span><span class="va">${name}</span><span class="st">-</span><span class="va">${version}</span><span class="st">.icns"</span> -<span class="kw">}</span> - -<span class="fu">find</span> /Applications -maxdepth 2 -name <span class="st">'*.app'</span> <span class="kw">|</span> <span class="kw">while</span> <span class="bu">read</span> <span class="va">app</span>; <span class="kw">do</span> <span class="ex">process_app</span> <span class="st">"</span><span class="va">${app}</span><span class="st">"</span><span class="kw">;</span> <span class="kw">done</span> -<span class="fu">find</span> /System/Library/CoreServices -maxdepth 1 -name <span class="st">'*.app'</span> <span class="kw">|</span> <span class="kw">while</span> <span class="bu">read</span> <span class="va">app</span>; <span class="kw">do</span> <span class="ex">process_app</span> <span class="st">"</span><span class="va">${app}</span><span class="st">"</span><span class="kw">;</span> <span class="kw">done</span></code></pre></div> -<p>The script is also available as a <a href="https://gist.github.com/zmwangx/fad97e085045a21ebc1d">gist</a>.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-04-26-using-python-3-with-emacs-jedi.html b/build/blog/2015-04-26-using-python-3-with-emacs-jedi.html deleted file mode 100644 index 7f12a065..00000000 --- a/build/blog/2015-04-26-using-python-3-with-emacs-jedi.html +++ /dev/null @@ -1,53 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-04-26T21:19:14-0700" name="date"/> -<title>Using Python 3 with Emacs Jedi</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/highlight.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Using Python 3 with Emacs Jedi</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-04-26T21:19:14-0700">April 26, 2015</time> -</div> -</header> -<p>Recently I'm working on <a href="https://github.com/zmwangx/storyboard">a hobby project in Python</a>, which means editing Python source files a lot. I've been using <a href="https://github.com/tkf/emacs-jedi">Emacs Jedi</a> for almost as long as I've been writing Python, and it has been pretty helpful at completing away long names.</p> -<p>However, Jedi uses <code>python</code> by default, which means <code>python2</code> on most of our systems at this point. Occasionally I'm writing Python 3 specific code but Jedi completes to Python 2 or refuses to complete; for the record, I enjoy writing and debugging Python 3.3+ much better than 2.7 (I realized this after trying to create a code base that is backward compatible with 2.7, which means reinventing the wheel or introducing annoying branches from time to time). So naturally I'm looking into using Python 3 in Jedi.</p> -<p>The <a href="https://tkf.github.io/emacs-jedi/latest/#how-to-use-python-3-or-any-other-specific-version-of-python">official docs</a> has been confusing and unhelpful at least for me, since it insists on setting up the virtualenv from within Emacs, and it failed for me. Why can't I set up the virtualenv myself? Turns out I can, and it's incredibly simple. The commands below assume that you have installed Jedi and friends (well, dependencies) using <code>package.el</code>.</p> -<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="fu">mkdir</span> -p ~/.emacs.d/.python-environments -<span class="ex">virtualenv</span> -p /usr/local/bin/python3 ~/.emacs.d/.python-environments/jedi # or whatever your python3 path is -<span class="co"># If you feel like installing the server with 'M-x jedi:install-server', also do the following</span> -<span class="ex">~/.emacs.d/.python-environments/jedi/bin/pip</span> install --upgrade ~/.emacs.d/elpa/jedi-20150109.2230/ # you might need to change the version number</code></pre></div> -<p>And that's it. Put the following in your <code>~/.emacs</code>:</p> -<div class="sourceCode"><pre class="sourceCode commonlisp"><code class="sourceCode commonlisp">(add-hook 'python-mode-hook 'jedi:setup) -(<span class="kw">setq</span> jedi:complete-on-dot <span class="kw">t</span>) -(<span class="kw">setq</span> jedi:environment-root <span class="st">"jedi"</span>)</code></pre></div> -<p>where the first two lines should be there whether you want to use Python 3 or not — so only the third line is new, and its meaning is obvious.</p> -<p>At last, start Emacs and do <code>M-x jedi:install-server</code> if you haven't run the <code>pip</code> command above yet. Restart Emacs (if necessary). That's it. Enjoy your Jedi with Python 3. (Type <code>import conf</code>, for instance, to be convinced that you're really autocompleting Python 3).</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-05-03-why-oh-my-zsh-is-completely-broken.html b/build/blog/2015-05-03-why-oh-my-zsh-is-completely-broken.html deleted file mode 100644 index bcddc5d1..00000000 --- a/build/blog/2015-05-03-why-oh-my-zsh-is-completely-broken.html +++ /dev/null @@ -1,155 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-05-03T17:15:49-0700" name="date"/> -<title>Why Oh My Zsh is completely broken</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/highlight.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Why Oh My Zsh is completely broken</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-05-03T17:15:49-0700">May 3, 2015</time> -</div> -</header> -<p>Today I moved from <a href="https://github.com/robbyrussell/oh-my-zsh">Oh My Zsh</a> to <a href="https://github.com/sorin-ionescu/prezto">Prezto</a>, after using Oh My Zsh for about three years since 2012. I'll try to shed some light on the reasons in this post.</p> -<p>Zsh is a rather complicated shell (compared to Bash), with a hell lot of builtins and a complex completion system. The complexity makes it powerful, but also makes it intimidating to mortals; moreover, it doesn't look as sweet as it could be out of box. Most mortals, me included, want an interactive shell that's sweet and "just works", so we need wizards to guide us in configuring this beast. Oh My Zsh and Prezto are just two of such configuration frameworks. Oh My Zsh is somewhat older: the first commit of Oh My Zsh dates back to <a href="https://github.com/robbyrussell/oh-my-zsh/commit/e20401e04e057a39c228dbb99dda68ec7fa4235a">August 2009</a>, while Prezto was forked from Oh My Zsh in <a href="https://github.com/sorin-ionescu/prezto/commit/8d487d4f6c2d38cb108d7c8c0c2de9f0385da402">February 2011</a>, and has since been completely rewritten. <code>robbyrussell/oh-my-zsh</code> as of today has 23,610 stars on GitHub, while <code>sorin-ionescu/prezto</code> has 4,069. This doesn't imply Oh My Zsh is any better — I guess the fancy name of Oh My Zsh earned it a lot more undeserved stars; you'll see why soon.</p> -<p>I was hardly involved in Oh My Zsh development, and I haven't even carefully inspected Oh My Zsh's source code until yesterday, so my soon-to-come complaints about Oh My Zsh might not be completely true. But here it is: <strong>Oh My Zsh brings the worst of community-driven development, where the "community" knows not of what it is doing, and just wants to get things done in the sloppiest way possible.</strong> Let's look at some examples. All discussions are based on <a href="https://github.com/robbyrussell/oh-my-zsh/commit/140034605edd0f72c548685d39e49687a44c1b23"><code>1400346</code></a>, the latest commit at the time of writing.</p> -<h2 id="the-core-lib-hodgepodge">The core lib hodgepodge</h2> -<p>First, look at Oh My Zsh's core <a href="https://github.com/robbyrussell/oh-my-zsh/tree/140034605edd0f72c548685d39e49687a44c1b23/lib">lib</a>:</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh"><span class="kw">></span> <span class="kw">ls</span> lib -bzr.zsh directories.zsh grep.zsh misc.zsh spectrum.zsh -completion.zsh functions.zsh history.zsh nvm.zsh termsupport.zsh -correction.zsh git.zsh key-bindings.zsh prompt_info_functions.zsh theme-and-appearance.zsh</code></pre></div> -<p>Wait, why do I see <code>bzr.zsh</code>, <code>git.zsh</code>, and even <code>nvm.zsh</code> in the core lib? Why are all of these mandatory (all files in <code>lib</code> are sourced from <code>oh-my-zsh.sh</code>)? Why should I load <code>bzr.sh</code> and <code>nvm.zsh</code> when I don't use Bazaar or NVM at all?<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> Moreover, since we already have <code>bzr.sh</code>, <code>git.zsh</code> and <code>nvm.zsh</code> in the core library, why don't we also have <code>hg.zsh</code>, <code>rvm.zsh</code>, <code>svn.zsh</code> and <code>virtualenv.zsh</code>, just to name a few?</p> -<p>I suppose these marginal scripts are in the core because they define functions (<code>bzr_prompt_info</code>, <code>git_prompt_info</code>, <code>nvm_prompt_info</code>, etc.) that are called from many themes; well, at least this is the case for <code>git.zsh</code>. But that doesn't answer any of the questions above. <strong>The underlying question is: why aren't they simply plugins?</strong><a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a> Loading a plugin in Oh My Zsh isn't sophiscated at all (compared to Prezto; see discussion below), just annoying to type in full, which <a href="https://github.com/robbyrussell/oh-my-zsh/blob/140034605edd0f72c548685d39e49687a44c1b23/oh-my-zsh.sh#L68-L72">boils down to</a>:</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh"><span class="kw">if [</span> <span class="ot">-f</span> <span class="ot">$ZSH_CUSTOM</span>/plugins/<span class="ot">$plugin</span>/<span class="ot">$plugin</span>.plugin.zsh<span class="kw"> ]</span>; <span class="kw">then</span> - <span class="kw">source</span> <span class="ot">$ZSH_CUSTOM</span>/plugins/<span class="ot">$plugin</span>/<span class="ot">$plugin</span>.plugin.zsh -<span class="kw">elif [</span> <span class="ot">-f</span> <span class="ot">$ZSH</span>/plugins/<span class="ot">$plugin</span>/<span class="ot">$plugin</span>.plugin.zsh<span class="kw"> ]</span>; <span class="kw">then</span> - <span class="kw">source</span> <span class="ot">$ZSH</span>/plugins/<span class="ot">$plugin</span>/<span class="ot">$plugin</span>.plugin.zsh -<span class="kw">fi</span></code></pre></div> -<p>where <code>$plugin</code> is the name of the plugin. They can easily wrap this in a function and let theme authors painlessly load plugins,<a class="footnoteRef" href="#fn3" id="fnref3"><sup>3</sup></a> but they just don't. Also, the consistency issue (think of my question about <code>hg</code>, <code>rvm</code>, <code>svn</code> and <code>virtualenv</code>) is beyond my grasp. The only way I could make sense of this situation is that all the mess was created by clueless community contributions that didn't think about the code base as a whole (the code base is small!), and maintainers didn't care either.</p> -<p>Meanwhile, Prezto does it right. Prezto is highly modular, with the <code>pmodload</code> function defined in <a href="https://github.com/sorin-ionescu/prezto/blob/08676a273eba1781ddcb63c4f89cfff9bd62eac4/init.zsh"><code>init.zsh</code></a> to load modules (doing things like sourcing module init scripts and marking module functions for autoloading). That's about the entirety of Prezto's core; everything else are in optional <a href="https://github.com/sorin-ionescu/prezto/blob/08676a273eba1781ddcb63c4f89cfff9bd62eac4/modules">modules</a>, including essential configs like <code>editor</code> (ZLE configs), <code>completion</code>, and <code>prompt</code>. Note that module loading order matters in some cases, but still, working with Prezto's modular structure is a joy. Apart from <code>init.zsh</code> and the <code>modules</code> directory, the Prezto repo does contain one other <a href="https://github.com/sorin-ionescu/prezto/tree/08676a273eba1781ddcb63c4f89cfff9bd62eac4/runcoms"><code>runcoms</code></a> directory with rc files, but those are just recommendations that one may safely ignore. In fact, there are a total of eight lines related to Prezto in my <code>.zshrc</code>, and nowhere else (note that I only switched to Prezto today, so this freshly baked <code>.zshrc</code> is subject to change):</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh"><span class="co"># prezto</span> -<span class="kw">zstyle</span> <span class="st">':prezto:*:*'</span> color <span class="st">'yes'</span> -<span class="kw">zstyle</span> <span class="st">':prezto:environment:termcap'</span> color <span class="st">'no'</span> <span class="co"># disable coloring of less, which looks horrible</span> -<span class="kw">zstyle</span> <span class="st">':prezto:load'</span> pmodule environment editor <span class="kw">history</span> directory utility colors spectrum git completion prompt ruby -<span class="kw">zstyle</span> <span class="st">':prezto:module:editor'</span> key-bindings <span class="st">'emacs'</span> -<span class="kw">zstyle</span> <span class="st">':prezto:module:prompt'</span> theme <span class="st">'zmwangx'</span> -<span class="kw">[[</span> <span class="st">"</span><span class="ot">$OSTYPE</span><span class="st">"</span> <span class="ot">==</span> darwin*<span class="kw"> ]]</span> <span class="kw">&&</span> <span class="kw">export</span> <span class="ot">BROWSER=</span><span class="st">'open'</span> -<span class="kw">source</span> ~/.zprezto/init.zsh</code></pre></div> -<p>Here <code>zmwangx</code> is my <a href="https://github.com/zmwangx/prezto/blob/master/modules/prompt/functions/prompt_zmwangx_setup">personal theme</a> that looks like <a href="https://i.imgur.com/nCBK8ZB.png">this</a>.</p> -<h2 id="incredibly-poor-code-quality">Incredibly poor code quality</h2> -<p>Oh My Zsh's code quality is incredibly poor. Even within the core library. Pick any file from <code>lib/</code>, and you'll be amazed by the hot mess in front of your eyes. There's no coding standard whatsoever:</p> -<ul> -<li>You can find four-space indents and two-space indents mixed <a href="https://github.com/robbyrussell/oh-my-zsh/blob/140034605edd0f72c548685d39e49687a44c1b23/lib/functions.zsh">in the same file</a>;</li> -<li>You can find function definitions with the <code>function</code> keyword and without <a href="https://github.com/robbyrussell/oh-my-zsh/blob/140034605edd0f72c548685d39e49687a44c1b23/lib/git.zsh">in the same file</a>;</li> -<li>You can find <a href="https://github.com/robbyrussell/oh-my-zsh/blob/140034605edd0f72c548685d39e49687a44c1b23/lib/functions.zsh#L2">167-character-long lines</a> mixed with early-broken lines (yes, sometimes <a href="https://github.com/robbyrussell/oh-my-zsh/blob/140034605edd0f72c548685d39e49687a44c1b23/lib/git.zsh#L69">in the same file</a>);</li> -<li>You can find completely commented out blocks of code <a href="https://github.com/robbyrussell/oh-my-zsh/blob/140034605edd0f72c548685d39e49687a44c1b23/lib/key-bindings.zsh#L70-L87">in the core lib</a>, where the average user is not supposed to touch;</li> -</ul> -<p>I guess the list could go on; I didn't spend more time inspecting this crap.</p> -<p>We were discussing styles, but obviously style isn't the only problem with this code base. Next onto a case study of how Oh My Zsh does something in the most inefficient way possible. Let's have a look at <a href="https://github.com/robbyrussell/oh-my-zsh/blob/140034605edd0f72c548685d39e49687a44c1b23/lib/git.zsh"><code>git.zsh</code></a>. It suffers from almost all problems we have talked about so far, but let's focus specifically on <a href="https://github.com/robbyrussell/oh-my-zsh/blob/140034605edd0f72c548685d39e49687a44c1b23/lib/git.zsh#L78-L122">the <code>git_prompt_status</code> function</a>:</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh"><span class="fu">git_prompt_status()</span> <span class="kw">{</span> - <span class="ot">INDEX=$(</span><span class="kw">command</span> git status --porcelain -b <span class="kw">2></span> /dev/null<span class="ot">)</span> - <span class="ot">STATUS=</span><span class="st">""</span> - <span class="kw">if</span> <span class="ot">$(</span><span class="kw">echo</span> <span class="st">"</span><span class="ot">$INDEX</span><span class="st">"</span> <span class="kw">|</span> <span class="kw">command</span> <span class="kw">grep</span> -E <span class="st">'^\?\? '</span> <span class="kw">&></span> /dev/null<span class="ot">)</span>; <span class="kw">then</span> - <span class="ot">STATUS=</span><span class="st">"</span><span class="ot">$ZSH_THEME_GIT_PROMPT_UNTRACKED$STATUS</span><span class="st">"</span> - <span class="kw">fi</span> - <span class="kw">if</span> <span class="ot">$(</span><span class="kw">echo</span> <span class="st">"</span><span class="ot">$INDEX</span><span class="st">"</span> <span class="kw">|</span> <span class="kw">grep</span> <span class="st">'^A '</span> <span class="kw">&></span> /dev/null<span class="ot">)</span>; <span class="kw">then</span> - <span class="ot">STATUS=</span><span class="st">"</span><span class="ot">$ZSH_THEME_GIT_PROMPT_ADDED$STATUS</span><span class="st">"</span> - <span class="kw">elif</span> <span class="ot">$(</span><span class="kw">echo</span> <span class="st">"</span><span class="ot">$INDEX</span><span class="st">"</span> <span class="kw">|</span> <span class="kw">grep</span> <span class="st">'^M '</span> <span class="kw">&></span> /dev/null<span class="ot">)</span>; <span class="kw">then</span> - <span class="ot">STATUS=</span><span class="st">"</span><span class="ot">$ZSH_THEME_GIT_PROMPT_ADDED$STATUS</span><span class="st">"</span> - <span class="kw">fi</span> - <span class="kw">if</span> <span class="ot">$(</span><span class="kw">echo</span> <span class="st">"</span><span class="ot">$INDEX</span><span class="st">"</span> <span class="kw">|</span> <span class="kw">grep</span> <span class="st">'^ M '</span> <span class="kw">&></span> /dev/null<span class="ot">)</span>; <span class="kw">then</span> - <span class="ot">STATUS=</span><span class="st">"</span><span class="ot">$ZSH_THEME_GIT_PROMPT_MODIFIED$STATUS</span><span class="st">"</span> - <span class="kw">elif</span> <span class="ot">$(</span><span class="kw">echo</span> <span class="st">"</span><span class="ot">$INDEX</span><span class="st">"</span> <span class="kw">|</span> <span class="kw">grep</span> <span class="st">'^AM '</span> <span class="kw">&></span> /dev/null<span class="ot">)</span>; <span class="kw">then</span> - <span class="ot">STATUS=</span><span class="st">"</span><span class="ot">$ZSH_THEME_GIT_PROMPT_MODIFIED$STATUS</span><span class="st">"</span> - <span class="kw">elif</span> <span class="ot">$(</span><span class="kw">echo</span> <span class="st">"</span><span class="ot">$INDEX</span><span class="st">"</span> <span class="kw">|</span> <span class="kw">grep</span> <span class="st">'^ T '</span> <span class="kw">&></span> /dev/null<span class="ot">)</span>; <span class="kw">then</span> - <span class="ot">STATUS=</span><span class="st">"</span><span class="ot">$ZSH_THEME_GIT_PROMPT_MODIFIED$STATUS</span><span class="st">"</span> - <span class="kw">fi</span> - <span class="kw">if</span> <span class="ot">$(</span><span class="kw">echo</span> <span class="st">"</span><span class="ot">$INDEX</span><span class="st">"</span> <span class="kw">|</span> <span class="kw">grep</span> <span class="st">'^R '</span> <span class="kw">&></span> /dev/null<span class="ot">)</span>; <span class="kw">then</span> - <span class="ot">STATUS=</span><span class="st">"</span><span class="ot">$ZSH_THEME_GIT_PROMPT_RENAMED$STATUS</span><span class="st">"</span> - <span class="kw">fi</span> - <span class="kw">if</span> <span class="ot">$(</span><span class="kw">echo</span> <span class="st">"</span><span class="ot">$INDEX</span><span class="st">"</span> <span class="kw">|</span> <span class="kw">grep</span> <span class="st">'^ D '</span> <span class="kw">&></span> /dev/null<span class="ot">)</span>; <span class="kw">then</span> - <span class="ot">STATUS=</span><span class="st">"</span><span class="ot">$ZSH_THEME_GIT_PROMPT_DELETED$STATUS</span><span class="st">"</span> - <span class="kw">elif</span> <span class="ot">$(</span><span class="kw">echo</span> <span class="st">"</span><span class="ot">$INDEX</span><span class="st">"</span> <span class="kw">|</span> <span class="kw">grep</span> <span class="st">'^D '</span> <span class="kw">&></span> /dev/null<span class="ot">)</span>; <span class="kw">then</span> - <span class="ot">STATUS=</span><span class="st">"</span><span class="ot">$ZSH_THEME_GIT_PROMPT_DELETED$STATUS</span><span class="st">"</span> - <span class="kw">elif</span> <span class="ot">$(</span><span class="kw">echo</span> <span class="st">"</span><span class="ot">$INDEX</span><span class="st">"</span> <span class="kw">|</span> <span class="kw">grep</span> <span class="st">'^AD '</span> <span class="kw">&></span> /dev/null<span class="ot">)</span>; <span class="kw">then</span> - <span class="ot">STATUS=</span><span class="st">"</span><span class="ot">$ZSH_THEME_GIT_PROMPT_DELETED$STATUS</span><span class="st">"</span> - <span class="kw">fi</span> - <span class="kw">if</span> <span class="ot">$(</span><span class="kw">command</span> git rev-parse --verify refs/stash <span class="kw">></span>/dev/null <span class="kw">2>&1</span><span class="ot">)</span>; <span class="kw">then</span> - <span class="ot">STATUS=</span><span class="st">"</span><span class="ot">$ZSH_THEME_GIT_PROMPT_STASHED$STATUS</span><span class="st">"</span> - <span class="kw">fi</span> - <span class="kw">if</span> <span class="ot">$(</span><span class="kw">echo</span> <span class="st">"</span><span class="ot">$INDEX</span><span class="st">"</span> <span class="kw">|</span> <span class="kw">grep</span> <span class="st">'^UU '</span> <span class="kw">&></span> /dev/null<span class="ot">)</span>; <span class="kw">then</span> - <span class="ot">STATUS=</span><span class="st">"</span><span class="ot">$ZSH_THEME_GIT_PROMPT_UNMERGED$STATUS</span><span class="st">"</span> - <span class="kw">fi</span> - <span class="kw">if</span> <span class="ot">$(</span><span class="kw">echo</span> <span class="st">"</span><span class="ot">$INDEX</span><span class="st">"</span> <span class="kw">|</span> <span class="kw">grep</span> <span class="st">'^## .*ahead'</span> <span class="kw">&></span> /dev/null<span class="ot">)</span>; <span class="kw">then</span> - <span class="ot">STATUS=</span><span class="st">"</span><span class="ot">$ZSH_THEME_GIT_PROMPT_AHEAD$STATUS</span><span class="st">"</span> - <span class="kw">fi</span> - <span class="kw">if</span> <span class="ot">$(</span><span class="kw">echo</span> <span class="st">"</span><span class="ot">$INDEX</span><span class="st">"</span> <span class="kw">|</span> <span class="kw">grep</span> <span class="st">'^## .*behind'</span> <span class="kw">&></span> /dev/null<span class="ot">)</span>; <span class="kw">then</span> - <span class="ot">STATUS=</span><span class="st">"</span><span class="ot">$ZSH_THEME_GIT_PROMPT_BEHIND$STATUS</span><span class="st">"</span> - <span class="kw">fi</span> - <span class="kw">if</span> <span class="ot">$(</span><span class="kw">echo</span> <span class="st">"</span><span class="ot">$INDEX</span><span class="st">"</span> <span class="kw">|</span> <span class="kw">grep</span> <span class="st">'^## .*diverged'</span> <span class="kw">&></span> /dev/null<span class="ot">)</span>; <span class="kw">then</span> - <span class="ot">STATUS=</span><span class="st">"</span><span class="ot">$ZSH_THEME_GIT_PROMPT_DIVERGED$STATUS</span><span class="st">"</span> - <span class="kw">fi</span> - <span class="kw">echo</span> <span class="ot">$STATUS</span> -<span class="kw">}</span></code></pre></div> -<p><strong>This one single function intended to be invoked from a precmd hook (basically executed every time the prompt is printed), calls <code>grep</code> a staggering 14 times inside command substitutions, forking the process 28 times — while all the greps can be replaced with pattern/regex matching right within the shell.</strong> (Keep in mind that forking is the most expensive operation of the shell.) For instance,</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh"><span class="ot">$(</span><span class="kw">echo</span> <span class="st">"</span><span class="ot">$INDEX</span><span class="st">"</span> <span class="kw">|</span> <span class="kw">grep</span> <span class="st">'^A '</span> <span class="kw">&></span> /dev/null<span class="ot">)</span></code></pre></div> -<p>may well be replaced with</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh"><span class="kw">[[</span> <span class="ot">$INDEX</span> <span class="ot">==</span> *<span class="st">$'</span><span class="dt">\n</span><span class="st">A '</span>*<span class="kw"> ]]</span></code></pre></div> -<p>or</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh"><span class="kw">[[</span> <span class="ot">$INDEX</span> =~ <span class="st">$'</span><span class="dt">\n</span><span class="st">A '</span><span class="kw"> ]]</span></code></pre></div> -<p>(Note that the <code>git status --porcelain -b</code> call always prints the branch info such as <code>## master...origin/master</code> in the first line, so "<code>A </code>", if present at the beginning of any line, must be preceded by a newline; that's why the above works.) All other grep calls can be similarly replaced with pattern/regex matching. No forking.</p> -<p>By the way, whoever wrote this function seems to be unaware of the <code>-q,--quite,--silent</code> switch of <code>grep</code> (which should be available in all implementations), and every call is littered with <code>&> /dev/null</code>. In fact, using the <code>-q</code> switch is even (slightly) faster: a reasonable implementation of <code>-q</code> exits immediately when a match is found, while what is written here waits until all input is processed.</p> -<p>I haven't exhausted the problems with this function just yet. As a bonus: despite being awfully inefficient, <strong>this function <em>can't even be used</em> in many cases for which it is designed.</strong> You might have noticed that the order of different status bits is completely fixed by whoever wrote this function (by the way, all those <code>$ZSH_THEME_GIT_PROMPT_*</code> variables are documented nowhere, so one who wants to write a theme has to dig into the source — only to find the function useless except for polluting the namespace). If one wants to use a different order, or put some of the bits in <code>RPROMPT</code>, one has to roll his own (or good luck parsing the output of <code>git_prompt_status</code>). In fact, even a <a href="https://github.com/robbyrussell/oh-my-zsh/blob/140034605edd0f72c548685d39e49687a44c1b23/lib/git.zsh#L2-L8">dumbed down function <code>git_prompt_info</code></a>, which only prints the branch name and whether it's dirty, is similarly uncustomizable; <a href="https://github.com/robbyrussell/oh-my-zsh/blob/140034605edd0f72c548685d39e49687a44c1b23/themes/gallois.zsh-theme">the <code>gallois</code> theme</a>, my first theme and on which I later based my own theme, needs to define a <code>git_custom_status</code> function to achieve what it needs — otherwise something as simple as adding a pair of brackets around the branch name is super painful.</p> -<p>One might wonder how Prezto solves the same problem. The answer is in <a href="https://github.com/sorin-ionescu/prezto/blob/08676a273eba1781ddcb63c4f89cfff9bd62eac4/modules/git/functions/git-info"><code>modules/git/functions/git-info</code></a>. The <code>git-info</code> function does more, and again in a highly modular way (without grep calls, for God's sake): status bits or their combinations are <a href="https://github.com/sorin-ionescu/prezto/blob/08676a273eba1781ddcb63c4f89cfff9bd62eac4/modules/git/functions/git-info#L393-L416">formatted on demand with <code>zformat</code> and stored in an associative array <code>git_info</code></a>, where users specify format strings via <code>zstyle</code> with <a href="https://github.com/sorin-ionescu/prezto/tree/08676a273eba1781ddcb63c4f89cfff9bd62eac4/modules/git#theming">thoroughly documented escape sequences</a>. Very beautiful solution.</p> -<h2 id="the-completely-broken-community-contribution-process">The completely broken community contribution process</h2> -<p>I'm not sure if the project maintainers are Zsh wizards (I'm afraid not). I'll just assume that most of the code with incredibly poor quality came from community contribution. Okay, community. But even the community contribution process is completely broken.</p> -<p>At the time of writing there are 159 open issues and 446 open pull requests in <code>robbyrussell/oh-my-zsh</code> (the stats are 13/35 in <code>sorin-ionescu/prezto</code> — not proportional to the number of stars or forks). There's even <a href="https://github.com/robbyrussell/oh-my-zsh/pull/3809">a PR called "Easy-to-Merge"</a> that is said to collect PRs that are either extremely simple fixes or have been discussed–tested–and–signed-off (wait, then why aren't they already merged?). This makes it almost impossible to open new, substantial PRs (such as a complete rewrite of the <code>git_prompt_status</code> criticized above) — God knows whether other people have already proposed the same fix, or a different fix for the same problem, whether it's been discussed–tested–and–signed-off, and how much discussion will be needed for a new PR.</p> -<p>You might infer from the above that the actually merged PRs are discussed–tested–and–signed-off. Well, of course not (think about the code quality), and here's one more case study.</p> -<p>The only time I <a href="https://github.com/robbyrussell/oh-my-zsh/pull/3591">submitted a PR</a> is when <a href="https://github.com/robbyrussell/oh-my-zsh/pull/3564">a previous PR</a> broke aliases of the <code>ls</code> family, which most of us run tens to hundreds of times every day. The <code>-h</code> option was stripped from all aliases but one (which was ridiculous since the option seemed to be lost during copy/paste), and anyone who used the affected aliases regularly and lived with the PR for ten minutes should notice. Apparently nobody looked at the diffs before merging, or nobody cared (before I and one other guy jumped in). My PR was merged three days later; the delay was okay.</p> -<p><a href="https://github.com/robbyrussell/oh-my-zsh/pull/3341">In another instance</a>, the delay was totally unbearable. <a href="https://savannah.gnu.org/forum/forum.php?forum_id=8152">grep 2.21</a> was released on November 23, 2014, and it deprecated <code>GREP_OPTIONS</code>. Oh My Zsh was using <code>GREP_OPTIONS</code> back then, so anyone who upgraded to grep 2.21 and used grep regularly was getting a lot of deprecation warnings (oh, before you ask, <code>grep.zsh</code> is in the core lib). Core lib stuff spitting deprecation warnings on all platforms all the time is a pretty big thing, right? There were multiple ways to fix this problem, all of them trivial to the reasonably trained eyes; and they won't break user scripts, unless someone was doing something insane in the first place (like relying on exported <code>GREP_OPTIONS</code> for certain behaviors in a script). However, there were quite a bit of discussion spanning multiple issues and PRs (most notably <a href="https://github.com/robbyrussell/oh-my-zsh/pull/3341">this one</a>), and despite all the discussions, not a single maintainer or collaborator joined or showed any interest. <a href="https://github.com/robbyrussell/oh-my-zsh/pull/3403">A fix was merged not until December 14, 2014</a>. Of course there were temporary fixes (remember, the issue was trivial to begin with), but the problem must have been confusing to the less-proficient Zsh users during the twenty day window.</p> -<h2 id="easter-egg">Easter egg</h2> -<p>One more thing, among countless other problems: the recommended way to install Oh My Zsh is either</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh">curl -L https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh <span class="kw">|</span> <span class="kw">sh</span></code></pre></div> -<p>or</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh"><span class="kw">wget</span> https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh -O <span class="kw">-</span> <span class="kw">|</span> <span class="kw">sh</span></code></pre></div> -<p>Cool, huh? How many of you have the <code>--no-check-certificate</code> option of <code>wget</code> automatically turned on? Thankfully there's no <code>sudo</code> in front.</p> -<h2 id="summary">Summary</h2> -<p>Oh My Zsh was a great idea when it took off. Over the years however, through low-quality community contributions from people who barely understand Zsh (and shell scripting idioms and best practices in general), it evolved into a beast that no one except the maintainers could fix or seriously contribute to; yet the maintainers seem to be pretty satisfied with it.</p> -<p>Therefore, I'm moving to Prezto, the project with far better modularity and code quality. In fact, this rant all began from yesterday, when I was about to embark on a stripped down Zsh configuration system for myself. I was thinking about borrowing code from both Oh My Zsh and Prezto; but after reading some code from both projects, I soon realized that Oh My Zsh is totally crap and Prezto can be taken almost unmodified. I hope that more people will take a look at Prezto, realize how awesome it is (especially in comparison to the famed Oh My Zsh), fork it, and possibly submit patches.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>This is not entirely true. I use <a href="https://github.com/felipec/git-remote-bzr">git-remote-bzr</a> when I have to clone a Bazaar repo for some reason.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>Note that outside the core, there are additional plugins for <code>git</code> and <code>nvm</code>. Oh well.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -<li id="fn3"><p>Whether aliases defined in a plugin (e.g. for <code>git</code>) should be loaded can be easily controlled via a switch.<a class="footnotes-backlink" href="#fnref3">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-05-05-graceful-handling-of-sigint-when-using-pythons-multiprocessingprocess.html b/build/blog/2015-05-05-graceful-handling-of-sigint-when-using-pythons-multiprocessingprocess.html deleted file mode 100644 index f5e2a076..00000000 --- a/build/blog/2015-05-05-graceful-handling-of-sigint-when-using-pythons-multiprocessingprocess.html +++ /dev/null @@ -1,106 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-05-05T22:03:39-07:00" name="date"/> -<title>Graceful handling of SIGINT when using Python's multiprocessing.Process</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/highlight.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Graceful handling of <code>SIGINT</code> when using Python's <code>multiprocessing.Process</code></h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-05-05T22:03:39-07:00">May 5, 2015</time> -</div> -</header> -<p>Today I learned something about Python's (at least CPython's) multiprocessing and signal handling, and I would like to share it here. Basically my situation was such (when developing <a href="https://github.com/zmwangx/zmwangx.github.io/blob/source/pyblog"><code>pydoc</code></a> that powers this blog):</p> -<ul> -<li>I would like to serve the blog with an HTTP server while auto-regenerating for changes;</li> -<li>The auto-regeneration is handled in the main process with a while loop, whereas the HTTP server (requiring little human intervention) is put in a <code>multiprocessing.Process</code> and launched with <code>http.server.HTTPServer.serve_forever()</code>;</li> -<li>Upon sending <code>SIGINT</code>, both processes need to clean up and quit; in particular, the server needs to exit its <code>serve_forever()</code> loop (which can be done via <code>shutdown()</code>, but how to invoke the method is a problem, since <code>serve_forever()</code> blocks);</li> -<li>Handling of <code>SIGINT</code> must be graceful in the main process — there might be an ongoing build that must not be interrupted until finishing.</li> -</ul> -<p>Given this context, I learned the following two critical concepts (at least true in the current version of CPython) through trial and error:</p> -<ol style="list-style-type: decimal"> -<li><strong>A user-triggered <code>SIGINT</code> is sent to both processes</strong> — the main process and the <code>multiprocessing.Process</code> instance;</li> -<li><strong>Except for the defined interfaces, a <code>multiprocessing.Process</code> instance is almost completely separated from the main process, sharing as little resources as possible</strong>; by "defined interfaces" I mean the defined attributes and methods of a <code>Process</code> instance, as well as defined communication channels like <code>multiprocessing.Pipe</code> or <code>multiprocessing.Queue</code>. And to expand on resource sharing: yes, the two processes have their own copies of global variables, so using global variables as state registers is a no-go.</li> -</ol> -<p>Both concepts can be used to one's benefit or detriment. Below is how I solved my problem, using the two concepts. Observe that without a custom handler, Python translates a <code>SIGINT</code> to a <code>KeyboardInterrupt</code> exception; therefore, I use the default <code>KeyboardInterrupt</code> to interrupt the HTTP server in its own process (through handling the exception and calling <code>shutdown()</code>), but instead install a custom <code>SIGINT</code> handler in the main process that translates <code>SIGINT</code> to setting a <code>sigint_raised</code> flag that can be picked up by the while loop once the current build (if any) is finished. The proof of concept script is as follows (the production code is <a href="https://github.com/zmwangx/zmwangx.github.io/blob/a7a0b2073f30b1d0214c3152998d95e40a39b438/pyblog#L567-L635">here</a>):</p> -<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="co">#!/usr/bin/env python3</span> - -<span class="im">import</span> http.server -<span class="im">import</span> multiprocessing -<span class="im">import</span> signal -<span class="im">import</span> sys -<span class="im">import</span> time - -<span class="kw">class</span> HTTPServerProcess(multiprocessing.Process): - <span class="kw">def</span> run(<span class="va">self</span>): - httpd <span class="op">=</span> http.server.HTTPServer( - (<span class="st">""</span>, <span class="dv">8000</span>), http.server.SimpleHTTPRequestHandler) - <span class="cf">try</span>: - httpd.serve_forever() - <span class="cf">except</span> <span class="pp">KeyboardInterrupt</span>: - httpd.shutdown() - -<span class="kw">def</span> do_things(): - <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">10</span>): - sys.stderr.write(<span class="st">"."</span>) - sys.stderr.flush() - time.sleep(<span class="dv">1</span>) - sys.stderr.write(<span class="st">"</span><span class="ch">\n</span><span class="st">"</span>) - -<span class="kw">def</span> main(): - server_process <span class="op">=</span> HTTPServerProcess() - server_process.start() - - <span class="co"># define and install custom SIGINT handler</span> - sigint_raised <span class="op">=</span> <span class="va">False</span> - - <span class="kw">def</span> sigint_mitigator(signum, frame): - <span class="kw">nonlocal</span> sigint_raised - sigint_raised <span class="op">=</span> <span class="va">True</span> - - signal.signal(signal.SIGINT, sigint_mitigator) - - <span class="cf">while</span> <span class="kw">not</span> sigint_raised: - do_things() - - server_process.join() - -<span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">"__main__"</span>: - main()</code></pre></div> -<p>Beware that with this solution, if there are external programs or OS level operations happening in the main process, then the operation at the time of <code>SIGINT</code> will still be interrupted<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> (for example, in the script above, the <code>time.sleep(1)</code> at the exact point of <code>SIGINT</code> is still interrupted, but otherwise <code>do_things</code> is carried on to its completion). I'm not sure how to explain this — maybe the handler isn't capturing the signal fast enough?<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a> Anyway, one single early interruption is at least more acceptable than a completely corrupted build<a class="footnoteRef" href="#fn3" id="fnref3"><sup>3</sup></a>, and certainly more graceful.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p><a href="https://hg.python.org/cpython/file/1320ec1b24af/Modules/_multiprocessing">CPython's <code>multiprocessing</code> is written in C</a>, so the behavior might depend on the OS. I'm talking about OS X here. I haven't inspected and won't inspect the C source code.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>That's awfully naive and layman-sounding, I know, but I <em>am</em> almost a layman when it comes to system-level programming.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -<li id="fn3"><p>That's assuming your build isn't interdependent in which any single failure corrupts everything. In that case, what can we do? I honestly see no way of injecting signal handling in <code>subprocess.Popen</code>.<a class="footnotes-backlink" href="#fnref3">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-05-05-new-blog-new-start.html b/build/blog/2015-05-05-new-blog-new-start.html deleted file mode 100644 index 1524757e..00000000 --- a/build/blog/2015-05-05-new-blog-new-start.html +++ /dev/null @@ -1,74 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-05-05T02:42:44-07:00" name="date"/> -<title>New blog, new start</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">New blog, new start</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-05-05T02:42:44-07:00">May 5, 2015</time> -</div> -</header> -<p>Octopress has been serving me for the past six months, during which even Octopress itself underwent major changes — in fact, <a href="https://github.com/octopress/octopress/releases/tag/v3.0.0">Octopress 3.0.0</a> was only released 3 days ago, which I never got to try. Anyway, Octopress's heavily colored interface grew old on me fairly quickly. I'm especially unhappy with the inline <code><code></code> tag, which is always wrapped in a white box and stands out too much (worse still, there's no visual difference when such a <code><code></code> tag is placed inside an <code><a></code> tag). Since I use inline code/verbatim a lot, many of my articles were littered with arbitrary boxes everywhere.</p> -<div class="figure"> -<a href="https://i.imgur.com/hxfSnOk.png" target="_blank"><img alt="Farewell, Octopress." src="https://i.imgur.com/hxfSnOk.png"/></a> -<p class="caption">Farewell, Octopress.</p> -</div> -<p>Apparently I need something simpler. Because</p> -<blockquote> -<p>Simplicity is the ultimate sophistication.</p> -</blockquote> -<p>But how? Simiplicity 101: get rid of the "platform". There's no reason why I need a blogging platform like Jekyll (let alone the WordPress monster). When I initially switched to Octopress, I thought code highlighting was something fancy that I need heavy machinery to achieve, but it turned out that Pandoc is battery-included when it comes to syntax highting,<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> so all I need is to specify a highlight style, e.g., Pygments:</p> -<pre><code>pandoc input.md --highlight-style=pygments --template template.html --output output.html</code></pre> -<p>That's it. Write the Markdown, compile with Pandoc, instantly awesome. So the HTML posts are there (assuming the HTML template is written, which is not hard to kick off).</p> -<p>The rest of the job is to design the stylesheets and compile the posts into a coherent blog — basically, generate an index. I was able to realize both in several hours. For the former task, I borrowed a lot from <a href="http://mort.ninja/">mort.ninja</a> by <a href="https://github.com/soimort">Mort Yao</a>. Interestingly, we were born in the same city (Nanjing, China), and I benefit from at least two of his open source projects: <a href="https://github.com/soimort/you-get">you-get</a> and <a href="https://github.com/soimort/translate-shell">translate-shell</a>. The latter task is more interesting but also not hard. I'm rolling my own toolchain in Python, which you can find in <a href="https://github.com/zmwangx/zmwangx.github.io/blob/source/pyblog"><code>pyblog</code></a>. In fact, the complete source of this blog (down to how image assets are generated) are in the <a href="https://github.com/zmwangx/zmwangx.github.io/tree/source"><code>source</code> branch</a> of my GitHub Pages repo, so you may take a look if you're interested. <code>pyblog</code> is highly specialized<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a> and is still a work in progress at the time of writing, but it's already well capable of generating the blog — currently missing are auto gen-deploy and preview (with auto-update), which will also come soon.</p> -<p>By the way, the most annoying thing in the development process was working with XML and generating <a href="/atom.xml">the Atom feed</a>. Standard library <code>xml.etree.ElementTree</code> doesn't support the <code>![CDATA[</code> tag, and in the end I had to hack <a href="https://github.com/zmwangx/zmwangx.github.io/blob/source/pyblog#L34-L54">library internals</a>, which is likely to break in future versions. Remember the quotes?</p> -<blockquote> -<p>XML is a classic political compromise: it balances the needs of man and machine by being equally unreadable to both.</p> -</blockquote> -<blockquote> -<p>XML combines the efficiency of text files with the readability of binary files.</p> -</blockquote> -<p>Sigh.</p> -<p>Anyway, here is my new shiny blog.</p> -<div class="figure"> -<a href="https://i.imgur.com/VS5f9eJ.png" target="_blank"><img alt="Welcome to the completely revamped dl? cmplnts?" src="https://i.imgur.com/VS5f9eJ.png"/></a> -<p class="caption">Welcome to the completely revamped dl? cmplnts?</p> -</div> -<p>It looks ten times better than Octopress, and ever builds much faster than Octopress<a class="footnoteRef" href="#fn3" id="fnref3"><sup>3</sup></a>. As a bonus, the codebase is so small that it's super trivial to hack (no, not <em>that</em> hack).</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>Well, Pandoc is heavy-machinery, but it's both generic and self-contained, unlike a specialized blogging platform.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>Which is fine since I don't expect anyone else to use it, anyway.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -<li id="fn3"><p>I have the impression that a complete build of all posts (about fifty of them) with <code>pyblog</code> is faster than regenerating for a single modified post in Octopress. That's in the context of absolutely no categories; when you have a dozen or more categories, Octopress slows down to a halt.<a class="footnotes-backlink" href="#fnref3">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-05-06-searchable-settings-are-one-honking-great-idea-lets-do-more-of-those.html b/build/blog/2015-05-06-searchable-settings-are-one-honking-great-idea-lets-do-more-of-those.html deleted file mode 100644 index d4301846..00000000 --- a/build/blog/2015-05-06-searchable-settings-are-one-honking-great-idea-lets-do-more-of-those.html +++ /dev/null @@ -1,80 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-05-06T19:29:46-07:00" name="date"/> -<title>Searchable settings are one honking great idea — let's do more of those!</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Searchable settings are one honking great idea — let's do more of those!</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-05-06T19:29:46-07:00">May 6, 2015</time> -</div> -</header> -<p>I had to tweak some iOS settings just now, which wasn't a delightful experience. Since I just renovated my blog inside out and am still in the hype mode, I'll write a post on the interface design of settings or preferences.</p> -<p>The Zen of Python says,</p> -<blockquote> -<p>Namespaces are one honking great idea -- let's do more of those!</p> -</blockquote> -<p>Namespaces are in general great stuff for sure, and I love them a lot.<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> But they are not so great when badly designed. One problem is that sometimes things belong to the unexpected namespace. There are already examples in Python's STL, e.g., <code>os.remove</code> and <code>shutil.rmtree</code> — for Unix guys they're just <code>rm</code> and <code>rm -r</code>, but in Python they live in two separate <del>universes</del> namespaces. The other problem is that if one takes namespaces too far and design several levels of nested namespaces, then either the names are super long and annoying to use, or one needs to leave out part of the hierarchy with <code>from .. import ..</code>, defeating the security of namespaces and making code harder to understand locally.</p> -<p>When designing an interface for settings or preferences, there are also "namespaces", or sections (and subsections), although sections are more about grouping preferences by kind than about avoiding name clashes. However, section structures more often than not suffer from the same problems as badly designed namespace structures. Take iOS Settings for example. There are both unintuitive groupings and very deep nestings.</p> -<p>Regarding unintuitive groupings, there's this top-level section named "General" (among other unintuitive things), which contains many subsections: "About", "Software Update", "Siri", "Spotlight Search", "Handoff & Suggested App" "Accessibility", "Usage", "Background App Refresh"... And others I'm too tired to list. But what does "General" even mean? How are other top level sections like "Notifications", "Control Center", "Display & Brightness", etc. less general than the subsections found in "General"? No clue. I think Apple just wants to put (what they perceive as) the most used sections in the top-level, but sometimes it's hard to remember what's in "General" and what's not without going through both lists one by one (and missing what you are looking for in the first three tries).</p> -<p>Regarding deep nestings, try to find "Frequent Locations". It's "Privacy->Location Services->System Services->Frequent Locations", or if you locked down Location Services with Restrictions,<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a> "General->Restrictions->Location Services->System Services->Frequent Locations". Of course it's rarely used, but it still makes me gasp.<a class="footnoteRef" href="#fn3" id="fnref3"><sup>3</sup></a></p> -<p>I think in general <strong>one should be really careful with subsections (i.e., two or more levels of nesting)</strong>, especially in designing a settings interface. There's a reason why most INI files have no hierarchy, just sections. I believe the reason is that <strong>our text processing capability is inherently linear.</strong> Hypertext and jumping interfaces disrupt the linear workflow, but even when faced with a network of stuff, we still process them one at a time, linearly. Linearity is even more important in designing a settings interface since unlike reading articles, one is typically looking for a specific item. <strong>Finding one item linearly in a list of irrelevant distractions is already annoying enough, and you certainly don't want to make it quadratic or even cubic, which is simply unbearable when coupled with unexpected groupings.</strong></p> -<p>I can understand why designing a settings interface for a system as complicated as iOS (yet somehow has to keep all settings in a central place) is hard — there are too many atomic items, and often items do not fall nicely into categories. But I think it still important to try to reduce nesting. Maybe having long lists, but putting the most commonly used items on top is a good idea. Or maybe... Bypass the linear searching experience altogether?</p> -<h2 id="searchable-settings">Searchable settings</h2> -<p>I'm not sure who invented searchable setting pages, but I first noticed their great efficiency in Google Chrome many years ago, when one had to look for setting items tab after tab in all other major browsers. In fact, even to this day, the Chromium Opera (i.e., Opera 15+) is the only major browser other than Chrome that has adopted searchable settings. (I remember arguing with someone over whether this was a change for the good on <a href="http://blogs.opera.com/desktop/">blogs.opera.com/desktop</a>.) Searchable settings is also available in OS X's System Preferences, which is a joy to use. See screenshots below about how Google and Apple implement a searchable interface. Windows Control Panel is also searchable, and the search feature is capable of turning up deeply buried settings (e.g., "Control Panel->System and Security->System->Advanced system settings->Environment Variables"), so one point for them also.</p> -<p>As I said above, looking for an item in a list of irrelevant stuff is really annoying. Searchable settings completely bypass this issue by bringing users right to the desired item. This way, unintuitive groupings or deep nestings are no longer that problematic. Just like Google will tell me whether <code>rmtree</code> is in <code>os</code> or <code>shutil</code><a class="footnoteRef" href="#fn4" id="fnref4"><sup>4</sup></a>, System Preferences' search will tell me whether "Dark menu bar or Dock" is in "General" or somewhere else.</p> -<p>In fact, it is somewhat surprising to me that searchable settings are only available in a handful of applications. Seriously, these days we can search for almost anything on our computers and anything on the grand grand Internet, but we can't search the pool of available settings? If we have an INI, Plist XML, JSON, YAML, or whatever text configuration/preference file, then we can search it. Why not in GUI applications?</p> -<p>Of course, designing clear structures (with the principles and pitfalls discussed in the first half of this post) pays. But searchable settings are one honking great idea, and they are just long due in most applications. Come on, let's do more of them.</p> -<div class="figure"> -<a href="https://i.imgur.com/NazieEk.png" target="_blank"><img alt="How Google designed their award-winning searchable settings." src="https://i.imgur.com/NazieEk.png"/></a> -<p class="caption">How Google designed their award-winning searchable settings.</p> -</div> -<div class="figure"> -<a href="https://i.imgur.com/aKgW29W.png" target="_blank"><img alt="Apple." src="https://i.imgur.com/aKgW29W.png"/></a> -<p class="caption">Apple.</p> -</div> -<div class="figure"> -<a href="https://i.imgur.com/7zJxr8P.png" target="_blank"><img alt="Microsoft." src="https://i.imgur.com/7zJxr8P.png"/></a> -<p class="caption">Microsoft.</p> -</div> -<hr/> -<p><strong>May 16, 2015 update:</strong> Ars Technica <a href="http://arstechnica.com/apple/2015/05/what-wed-like-to-see-in-ios-9-at-wwdc-next-month/">published an article today</a> listing "what we'd like to see in iOS 9 at WWDC next month", and "Settings page overhaul" is listed as the third item. Apparently I'm not the only one who's concerned about the iOS Settings maze. In addition, their proposed solution is similar to mine;<a class="footnoteRef" href="#fn5" id="fnref5"><sup>5</sup></a> the key, of course, is search.</p> -<p><strong>June 27, 2015 update:</strong> <a href="/blog/2015-06-26-ios-9-searchable-settings.html">Wish granted in iOS 9</a>.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>Thinking about <a href="http://nshipster.com/namespacing/"><code>NSHell</code></a> and the like kinda creeps me out, although there are quite some reasonable pro-class prefix arguments.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>Which you should: what's the point of Find My iPhone when the thief can disable it in Location Services?<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -<li id="fn3"><p>This brings another problem of the interface design of iOS Settings. When restricted, one cannot make modifications to "Privacy->Location Services", and instead has to go to "General->Restrictions->Location Services". What's the point? "Restrictions" is about <em>setting restrictions</em>, not about <em>editing restricted items or sections in a central place exclusively"</em>. Ideally one should be able to tap on a lock icon in "Privacy->Location Services" and enter the restrictions passcode to unlock it, like what we find in OS X's System Preferences.<a class="footnotes-backlink" href="#fnref3">↩︎</a></p></li> -<li id="fn4"><p>This is of course just a metaphor; I'm not dumb enough to be unable to remember <code>shutil.rmtree</code>.<a class="footnotes-backlink" href="#fnref4">↩︎</a></p></li> -<li id="fn5"><p>Which is not at all surprising, since Apple's very own OS X has already set an example.<a class="footnotes-backlink" href="#fnref5">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-05-09-storyboard-reached-01.html b/build/blog/2015-05-09-storyboard-reached-01.html deleted file mode 100644 index dfb0c953..00000000 --- a/build/blog/2015-05-09-storyboard-reached-01.html +++ /dev/null @@ -1,113 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-05-09T00:32:28-07:00" name="date"/> -<title>storyboard reached 0.1</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title"><code>storyboard</code> reached 0.1</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-05-09T00:32:28-07:00">May 9, 2015</time> -</div> -</header> -<p>For quite some time I've been working on a Python project called <a href="https://github.com/zmwangx/storyboard"><code>storyboard</code></a>, and today I finally released the 0.1 stable (or you can think of it as 1.0).</p> -<p>As described on <a href="https://storyboard.readthedocs.org/en/0.1/index.html">the index page</a>,</p> -<blockquote> -<p><code>storyboard</code> is a FFmpeg-based customizable video storyboard generator with metadata reporting directly embedded in the generated images. Reported metadata fields include, but are not limited to, title, filename, file size, SHA-1 digest, container format, duration, pixel dimension, display aspect ratio (DAR), scan type (progressive, interlaced, or telecined), frame rate, and per-stream metadata (type, codec, profile, dimensions, bitrate, etc.).</p> -</blockquote> -<p>And the motivation was</p> -<blockquote> -<p><code>storyboard</code> was inspired by the storyboards I frequently encounter on video-sharing Internet forums, mostly generated by proprietary video players. Those storyboards often come with video/file metadata bundled, which I see as a great all-in-one solution for video sharing, saving one the labor of typing multiple console commands, copying and pasting output, and worrying about the forum’s crappy formatting. However, I, for one, dislike proprietary players. Also, those storyboards are usually ugly and uninformative, using stupid fonts and lacking crucial information that hackers look for (e.g., hash). Therefore, I developed this customizable storyboard generator for hackers.</p> -</blockquote> -<p>The project itself isn't very important, and I don't see any possibility of it gaining recognition; but its educational value to me was pretty huge. This is the first full package I ever developed, in the sense that it's complete with documentation, test suites, continuous integration and tested portability, as well as distributed to a package index (<a href="https://pypi.python.org/pypi/storyboard">PyPI</a> in this case). Here's what I observed and learned:</p> -<ol style="list-style-type: decimal"> -<li><p>It's just really different from casual hacking, where I would try to achieve what I need in the shortest amount of programmer time possible, drop hard-coded values (even OAuth tokens) in scripts, leave things undocumented, etc. I'm a perfectionist so my casual code is usually not so bad, but <code>storyboard</code> is just different — to ensure quality of API and CLI, I wrote more documentation than actual code. Through this project I realized how hard real-world coding (or idealized real-world coding) is: the initial 10% is excitement, and the rest is just chores (compare that to casual hacking, where at least 30% is excitement).</p></li> -<li><p>Write once, debug everywhere. Not really, but ensuring portability is really difficult. Trying to debug something on a platform which I can't lay my hands upon is insanely frustrating. This afternoon I spent a long time trying to pin down a weird hanging bug on AppVeyor; the complete process is documented in <a href="https://github.com/zmwangx/storyboard/commit/e8a28e5a92f744157fedd03893fa8fe5a5e7d445">this squashed commit</a>. In the end the bug wasn't in my program, but in that specific version of FFmpeg (which I wouldn't believe since FFmpeg is really stable from my experience), or that specific version of FFmpeg combined with AppVeyor, or that specific version of FFmpeg combined with AppVeyor combined with Azure, or... who knows. The only thing I could say is it was not in my program, because I could reproduce the infinite loop in <code>ffprobe</code> even before I launched my program... Anyway, in this case I can lay my hands on the platform, just indirectly and painful. What about real world development where developers need to handle bug reports from users who could have broken everything? I don't want to imagine.</p></li> -<li><p>The project was a clear manifestation of Hofstadter's law:</p> -<blockquote> -<p>It always takes longer than you expect, even when you take into account Hofstadter's Law.</p> -</blockquote> -<p>Enough said; so true. In fact, towards the end of the development cycle I got pretty bogged down<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> and stopped for a while to work on renovating this blog (60% excitement!). Meanwhile, I was too busy with other parts of life, so I rushed towards the stable 0.1 release in the past two days, dropping several ideas I wanted to implement (for completeness). Although I "rushed", it still took at least four times as long as I expected.</p></li> -</ol> -<p>Anyway, here it is, the <a href="https://github.com/zmwangx/storyboard/releases/tag/0.1">0.1</a> <a href="https://pypi.python.org/pypi/storyboard/0.1">release</a>. The badges certainly weren't bad:</p> -<div class="figure"> -<a href="https://i.imgur.com/miOoX5Y.png" target="_blank"><img alt="storyboard's got quite a few badges of honor" src="https://i.imgur.com/miOoX5Y.png"/></a> -<p class="caption"><code>storyboard</code>'s got quite a few badges of honor</p> -</div> -<p>I created <a href="https://asciinema.org/a/19782">an asciinema recording</a> to commemorate the release (the original asciicast is <a href="https://dl.bintray.com/zmwangx/generic/storyboard-0.1-walkthrough-asciicast.json">here</a>):<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a></p> -<div style="width: 672px; text-align: center; margin: auto;"> -<script async="" id="asciicast-19782" src="https://asciinema.org/a/19782.js" type="text/javascript"></script> -<noscript> -Javascript disabled. Check out the cast <a href="https://asciinema.org/a/19782">here</a>. -</noscript> -</div> -<p>And, just to demonstrate <code>storyboard</code>, I re-screen-recorded the asciinema screencast with QuickTime, saved to <a href="https://dl.bintray.com/zmwangx/generic/storyboard-0.1-walkthrough.mov">an MOV file</a>, and ran it through my <code>metadata</code> and <code>storyboard</code>:</p> -<pre><code>> metadata storyboard-0.1-walkthrough.mov -Filename: storyboard-0.1-walkthrough.mov -File size: 60418244 (57.7MiB) -Container format: QuickTime movie -Duration: 00:06:36.30 -Pixel dimensions: 672x846 -Display aspect ratio: 112:141 -Scan type: Progressive scan -Frame rate: 60 fps -Streams: - #0: Video, H.264 (Main Profile level 3.2), 672x846 (DAR 112:141), 60 fps, 1213 kb/s - -> storyboard storyboard-0.1-walkthrough.mov -Processing storyboard-0.1-walkthrough.mov -Crunching metadata... -Trying to determine scan type... -Inspecting frame 40/40... -Generating main storyboard... -Extracting frame 16/16... -Generating thumbnail 16/16... -Tiling thumbnails... -Generating metadata sheet... -Computing SHA-1 digest... -57.7MiB 0:00:00 [ 571MiB/s] [=================================================================================>] 100% -Generating promotional banner... -Assembling pieces... - -storyboard saved to: /tmp/storyboard-se3fbiif.jpg -</code></pre> -<p>Here's the actual image:</p> -<div class="figure"> -<a href="https://i.imgur.com/c3E3M8R.jpg" target="_blank"><img alt="storyboard of storyboard-0.1-walkthrough.mov (1964x2694), generated with the default settings by storyboard 0.1" src="https://i.imgur.com/c3E3M8R.jpg"/></a> -<p class="caption">storyboard of <code>storyboard-0.1-walkthrough.mov</code> (1964x2694), generated with the default settings by <code>storyboard 0.1</code></p> -</div> -<p>Credit to <code>lolcat</code> for making my storyboard colorful.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>I was implementing stuff that I wouldn't ever need myself — for completeness, and that was not rewarding in the slightest.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>The screencast's color scheme is actually off in some places, since in my iTerm2 bold font is displayed as bold, not bright.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-05-19-bash-the-special-slash-character-in-filename-expansion.html b/build/blog/2015-05-19-bash-the-special-slash-character-in-filename-expansion.html deleted file mode 100644 index 580272ae..00000000 --- a/build/blog/2015-05-19-bash-the-special-slash-character-in-filename-expansion.html +++ /dev/null @@ -1,69 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-05-19T18:33:51-07:00" name="date"/> -<title>Bash: the special slash character in filename expansion</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/highlight.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Bash: the special slash character in filename expansion</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-05-19T18:33:51-07:00">May 19, 2015</time> -</div> -</header> -<p>It is well-known and common sense that the slash character (<code>/</code>) serves a special role in Bash filename expansion. For instance, the asterisk <code>*</code> certainly won't match <code>/</code> or <code>.</code> when used in filename expansion; otherwise, a standalone <code>*</code> would match everything in the filesystem.</p> -<p>However, it is less clear how a literal slash character<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> is treated in extended glob patterns. Naively one would expect it to just match a literal slash, but the real situtation is more complicated than that. Consider the following examples:</p> -<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">bash-4.3</span>$ shopt -s extglob nullglob -<span class="ex">bash-4.3</span>$ echo /usr/@(bin<span class="kw">|</span><span class="ex">lib</span>) -<span class="ex">/usr/bin</span> /usr/lib -<span class="ex">bash-4.3</span>$ echo /usr@(/bin<span class="kw">|</span><span class="ex">/lib</span>) - -<span class="ex">bash-4.3</span>$ [[ /usr/bin == /usr@(/bin<span class="kw">|</span><span class="ex">/lib</span>) ]] <span class="kw">&&</span> <span class="bu">echo</span> matching -<span class="ex">matching</span></code></pre></div> -<p>As seen from this example, patterns with slash simply doesn't work (in filename expansion) when placed in an extended glob pattern list, and there's no error whatsoever. I looked up the <a href="https://www.gnu.org/software/bash/manual/html_node/Pattern-Matching.html#Pattern-Matching">Bash Reference Manual</a> and the <a href="http://mywiki.wooledge.org/BashGuide/Patterns">Bash Guide</a> but neither mentioned this behavior. One might need to delve into the source code to say for sure what exactly is going on.</p> -<p>In comparison, Zsh and its <a href="http://zsh.sourceforge.net/Doc/Release/Expansion.html#Filename-Generation">docs</a> are much more up front about this issue:</p> -<blockquote> -<p>Note that grouping cannot extend over multiple directories: it is an error to have a ‘/’ within a group (this only applies for patterns used in filename generation). ...</p> -</blockquote> -<p>And when we run equivalent code in Zsh:</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh">zsh-5.0.5$ <span class="kw">setopt</span> NULL_GLOB -zsh-5.0.5$ <span class="kw">echo</span> /usr/<span class="kw">(</span>bin<span class="kw">|</span>lib<span class="kw">)</span> -/usr/bin /usr/lib -zsh-5.0.5$ <span class="kw">echo</span> /usr<span class="kw">(</span>/bin<span class="kw">|</span>/lib<span class="kw">)</span> -zsh: bad pattern: /usr<span class="kw">(</span>/bin<span class="kw">|</span>/lib<span class="kw">)</span> -zsh-5.0.5$<span class="kw"> [[</span> /usr/bin <span class="ot">==</span> /usr(/bin|/lib)<span class="kw"> ]]</span> <span class="kw">&&</span> <span class="kw">echo</span> matching -matching</code></pre></div> -<p>The lesson? Be careful not to use a pattern like <code>@(path1|path2|path3)</code> in Bash when the paths are absolute, or relative but contain the slash. Unlike Zsh, Bash just silently fails on a pattern like this, which is rather dangerous in scripts.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>Here, "a literal slash character" also applies to one that comes from tilde expansion, parameter expansion or command substitution, since they are performed before filename expansion in Bash.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-05-22-using-a-command-table-as-wallpaper.html b/build/blog/2015-05-22-using-a-command-table-as-wallpaper.html deleted file mode 100644 index 64821bb9..00000000 --- a/build/blog/2015-05-22-using-a-command-table-as-wallpaper.html +++ /dev/null @@ -1,194 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-05-22T00:48:19-07:00" name="date"/> -<title>Using a command table as wallpaper</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/highlight.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Using a command table as wallpaper</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-05-22T00:48:19-07:00">May 22, 2015</time> -</div> -</header> -<p>Recently I cleaned up my source code directory, removed a lot of rarely-used, dated scripts, and grouped the remaining standalone scripts into a central place (<code>~/dev/scripts</code>)<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a>. One thing I learned in this process is that I tend to write a reusable script but rarely actually reuse it (even if it sits on <code>PATH</code>), sometimes implementing the same functionality twice or typing a long command line over and over again.</p> -<p>To remind myself of which scripts are at my fingertip, I decided to use a command table as wallpaper on my secondary display. So I wrote a shitty Python script<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a> (depending on XeLaTeX and ImageMagick) to automate the generation of such a wallpaper. It's pretty customizable, and anyone may grab it and do whatever they want to with it (also <a href="https://gist.github.com/zmwangx/b06aa923abf061b33fc9">available as a gist</a>):</p> -<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="co">#!/usr/bin/env python3</span> - -<span class="co">"""Generate command table."""</span> - -<span class="im">import</span> argparse -<span class="im">import</span> os -<span class="im">import</span> shlex -<span class="im">import</span> subprocess -<span class="im">import</span> sys -<span class="im">import</span> tempfile - -<span class="co"># pylint: disable=wildcard-import,unused-wildcard-import</span> - -<span class="im">from</span> zmwangx.colorout <span class="im">import</span> <span class="op">*</span> - -DEFAULT_COLUMN_WIDTH <span class="op">=</span> <span class="dv">120</span> -DEFAULT_FOREGROUND_COLOR <span class="op">=</span> <span class="st">"white"</span> -DEFAULT_BACKGROUND_COLOR <span class="op">=</span> <span class="st">"black"</span> -DEFAULT_FONT <span class="op">=</span> <span class="st">"Consolas"</span> -DEFAULT_BORDER <span class="op">=</span> <span class="dv">20</span> -DEFAULT_DENSITY <span class="op">=</span> <span class="dv">300</span> -DEFAULT_SIZE <span class="op">=</span> <span class="st">"1280x800"</span> - -HERE <span class="op">=</span> os.path.dirname(os.path.realpath(sys.argv[<span class="dv">0</span>])) -XELATEX_PROGRAM <span class="op">=</span> (<span class="vs">r"""</span> -<span class="vs">\documentclass[varwidth=\maxdimen,border=</span><span class="sc">{border}</span><span class="vs">pt]</span><span class="sc">{{</span><span class="vs">standalone</span><span class="sc">}}</span> -<span class="vs">\usepackage</span><span class="sc">{{</span><span class="vs">color</span><span class="sc">}}</span> -<span class="vs">\pagecolor</span><span class="sc">{{{background}}}</span> -<span class="vs">\color</span><span class="sc">{{{foreground}}}</span> -<span class="vs">\usepackage</span><span class="sc">{{</span><span class="vs">fontspec</span><span class="sc">}}</span> -<span class="vs">\setmonofont</span><span class="sc">{{{font}}}</span> - -<span class="vs">\begin</span><span class="sc">{{</span><span class="vs">document</span><span class="sc">}}</span> -<span class="vs">\begin</span><span class="sc">{{</span><span class="vs">verbatim</span><span class="sc">}}</span> -<span class="sc">{table}</span> -<span class="vs">\end</span><span class="sc">{{</span><span class="vs">verbatim</span><span class="sc">}}</span> -<span class="vs">\end</span><span class="sc">{{</span><span class="vs">document</span><span class="sc">}}</span> -<span class="vs">"""</span>) - -<span class="kw">def</span> text_table(<span class="op">**</span>kwargs): - <span class="co">"""Generate the text version of the table."""</span> - width <span class="op">=</span> kwargs[<span class="st">"width"</span>] <span class="cf">if</span> <span class="st">"width"</span> <span class="kw">in</span> kwargs <span class="cf">else</span> DEFAULT_COLUMN_WIDTH - directory <span class="op">=</span> kwargs[<span class="st">"directory"</span>] <span class="cf">if</span> <span class="st">"directory"</span> <span class="kw">in</span> kwargs <span class="cf">else</span> HERE - command_line <span class="op">=</span> (<span class="vs">r"find </span><span class="sc">{directory}</span><span class="vs"> -maxdepth 1 -type f -perm -u=x -exec basename </span><span class="sc">{{}}</span><span class="vs"> \; "</span> - <span class="st">"| column -c </span><span class="sc">{width}</span><span class="st"> | expand"</span>.<span class="bu">format</span>( - directory<span class="op">=</span>shlex.quote(directory), width<span class="op">=</span>width)) - ccommand(command_line) - <span class="cf">return</span> subprocess.check_output(command_line, shell<span class="op">=</span><span class="va">True</span>).decode(<span class="st">"utf-8"</span>) - -<span class="kw">def</span> pdf_table(<span class="op">**</span>kwargs): - <span class="co">"""Generate the PDF version of the table.</span> - -<span class="co"> Returns 0 on success or 1 on failure. Generated PDF is "table.pdf"</span> -<span class="co"> in the current working directory.</span> - -<span class="co"> """</span> - border <span class="op">=</span> kwargs[<span class="st">"border"</span>] <span class="cf">if</span> <span class="st">"border"</span> <span class="kw">in</span> kwargs <span class="cf">else</span> DEFAULT_BORDER - foreground <span class="op">=</span> kwargs[<span class="st">"foreground"</span>] <span class="cf">if</span> <span class="st">"foreground"</span> <span class="kw">in</span> kwargs <span class="cf">else</span> DEFAULT_FOREGROUND_COLOR - background <span class="op">=</span> kwargs[<span class="st">"background"</span>] <span class="cf">if</span> <span class="st">"background"</span> <span class="kw">in</span> kwargs <span class="cf">else</span> DEFAULT_BACKGROUND_COLOR - font <span class="op">=</span> kwargs[<span class="st">"font"</span>] <span class="cf">if</span> <span class="st">"font"</span> <span class="kw">in</span> kwargs <span class="cf">else</span> DEFAULT_FONT - program <span class="op">=</span> XELATEX_PROGRAM.<span class="bu">format</span>(table<span class="op">=</span>text_table(<span class="op">**</span>kwargs).strip(), - font<span class="op">=</span>font, border<span class="op">=</span>border, - foreground<span class="op">=</span>foreground, background<span class="op">=</span>background) - <span class="cf">with</span> <span class="bu">open</span>(<span class="st">"table.tex"</span>, <span class="st">"w"</span>) <span class="im">as</span> texfileobj: - texfileobj.write(program) - <span class="cf">try</span>: - ccommand(<span class="st">"xelatex table.tex"</span>) - subprocess.check_call([<span class="st">"xelatex"</span>, <span class="st">"table.tex"</span>], - stdout<span class="op">=</span>subprocess.DEVNULL, stderr<span class="op">=</span>subprocess.DEVNULL) - <span class="cf">return</span> <span class="dv">0</span> - <span class="cf">except</span> subprocess.CalledProcessError: - cerror(<span class="st">"xelatex failed on the following program:"</span>) - cerrnewline() - cerrwrite(<span class="st">"default"</span>, program) - <span class="cf">return</span> <span class="dv">1</span> - -<span class="kw">def</span> png_table(<span class="op">**</span>kwargs): - <span class="co">"""Generate the PNG version of the table.</span> - -<span class="co"> Returns 0 on success or 1 on failure. Generated PNG is "table.png"</span> -<span class="co"> in the current working directory.</span> - -<span class="co"> """</span> - <span class="cf">if</span> pdf_table(<span class="op">**</span>kwargs) <span class="op">==</span> <span class="dv">1</span>: - <span class="cf">return</span> <span class="dv">1</span> - density <span class="op">=</span> kwargs[<span class="st">"density"</span>] <span class="cf">if</span> <span class="st">"density"</span> <span class="kw">in</span> kwargs <span class="cf">else</span> DEFAULT_DENSITY - size <span class="op">=</span> kwargs[<span class="st">"size"</span>] <span class="cf">if</span> <span class="st">"size"</span> <span class="kw">in</span> kwargs <span class="cf">else</span> DEFAULT_SIZE - background <span class="op">=</span> kwargs[<span class="st">"background"</span>] <span class="cf">if</span> <span class="st">"background"</span> <span class="kw">in</span> kwargs <span class="cf">else</span> DEFAULT_BACKGROUND_COLOR - command_line <span class="op">=</span> (<span class="st">"convert -density </span><span class="sc">{density}</span><span class="st"> table.pdf -resize </span><span class="sc">{size}</span><span class="st"> -size </span><span class="sc">{size}</span><span class="st"> "</span> - <span class="st">"xc:</span><span class="sc">{background}</span><span class="st"> +swap -gravity center -composite table.png"</span>.<span class="bu">format</span>( - density<span class="op">=</span>density, size<span class="op">=</span>size, background<span class="op">=</span>background)) - <span class="cf">try</span>: - ccommand(command_line) - subprocess.check_call(shlex.split(command_line)) - <span class="cf">return</span> <span class="dv">0</span> - <span class="cf">except</span> subprocess.CalledProcessError: - cerror(<span class="st">"the following ImageMagick command failed:"</span>) - cerrprint(<span class="st">"default"</span>, command_line) - <span class="cf">return</span> <span class="dv">1</span> - -<span class="kw">def</span> main(): - <span class="co">"""CLI."""</span> - description <span class="op">=</span> <span class="st">"Generate a PNG table of all executable commands in a directory."</span> - parser <span class="op">=</span> argparse.ArgumentParser(description<span class="op">=</span>description) - parser.add_argument(<span class="st">"--width"</span>, <span class="bu">type</span><span class="op">=</span><span class="bu">int</span>, default<span class="op">=</span>DEFAULT_COLUMN_WIDTH, - <span class="bu">help</span><span class="op">=</span><span class="st">"""line width, default is 120"""</span>) - parser.add_argument(<span class="st">"--directory"</span>, - <span class="bu">help</span><span class="op">=</span><span class="st">"""directory containing executables, default is</span> -<span class="st"> the directory containing this command"""</span>) - parser.add_argument(<span class="st">"--border"</span>, <span class="bu">type</span><span class="op">=</span><span class="bu">int</span>, default<span class="op">=</span>DEFAULT_BORDER, - <span class="bu">help</span><span class="op">=</span><span class="st">"""default is 20pt"""</span>) - parser.add_argument(<span class="st">"--foreground"</span>, default<span class="op">=</span>DEFAULT_FOREGROUND_COLOR, - <span class="bu">help</span><span class="op">=</span><span class="st">"""foreground color, default is white"""</span>) - parser.add_argument(<span class="st">"--background"</span>, default<span class="op">=</span>DEFAULT_BACKGROUND_COLOR, - <span class="bu">help</span><span class="op">=</span><span class="st">"""background color, default is black"""</span>) - parser.add_argument(<span class="st">"--font"</span>, default<span class="op">=</span>DEFAULT_FONT, - <span class="bu">help</span><span class="op">=</span><span class="st">"""default is Consolas"""</span>) - parser.add_argument(<span class="st">"--density"</span>, default<span class="op">=</span>DEFAULT_DENSITY, - <span class="bu">help</span><span class="op">=</span><span class="st">"""used for the -density argument of convert,</span> -<span class="st"> default is 300"""</span>) - parser.add_argument(<span class="st">"--size"</span>, default<span class="op">=</span>DEFAULT_SIZE, - <span class="bu">help</span><span class="op">=</span><span class="st">"""size of image, default is 1280x800"""</span>) - args <span class="op">=</span> parser.parse_args() - kwargs <span class="op">=</span> {k: v <span class="cf">for</span> (k, v) <span class="kw">in</span> args.__dict__.items() <span class="cf">if</span> v <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>} - - fd, tmpfilepath <span class="op">=</span> tempfile.mkstemp(suffix<span class="op">=</span><span class="st">".png"</span>, prefix<span class="op">=</span><span class="st">"table-"</span>) - os.close(fd) - <span class="cf">with</span> tempfile.TemporaryDirectory(prefix<span class="op">=</span><span class="st">"table-"</span>) <span class="im">as</span> working_directory: - os.chdir(working_directory) - <span class="cf">if</span> png_table(<span class="op">**</span>kwargs) <span class="op">==</span> <span class="dv">1</span>: - cerror(<span class="st">"execution failed"</span>) - os.remove(tmpfilepath) - <span class="cf">else</span>: - os.rename(<span class="st">"table.png"</span>, tmpfilepath) - cprogress(<span class="st">"saved to:"</span>) - <span class="bu">print</span>(tmpfilepath) - -<span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">"__main__"</span>: - main()</code></pre></div> -<p>By the way, the <code>zmwangx.colorout</code> module is <a href="https://github.com/zmwangx/pyzmwangx/blob/41b0bffaad9439888d68097a85c7aed594240283/zmwangx/colorout.py">here</a>, just to ease the printing of progress and errors to tty. You may safely remove all the <code>ccommand</code>, <code>cerr*</code> and <code>cprogress</code> calls.</p> -<p>Here is an example wallpaper reflecting my current <code>~/dev/scripts</code>:</p> -<div class="figure"> -<a href="https://i.imgur.com/mccQu1e.png" target="_blank"><img alt="Command table wallpaper for my secondary display (MBP 13'' builtin display)." src="https://i.imgur.com/mccQu1e.png"/></a> -<p class="caption">Command table wallpaper for my secondary display (MBP 13'' builtin display).</p> -</div> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>The <code>~/dev</code> directory stands for development, and contains all my source code and almost all local builds. The point is by having a <code>~/dev</code> directory, I no longer need to have <code>bin</code>, <code>include</code>, <code>lib</code>, and <code>share</code> in my <code>HOME</code>, thus saving a few slots. Backing up and restoring is also slightly easier.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>Yeah, I know it's a shitty script, so don't nitpick on style problems.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-05-29-apples-customer-service-is-still-the-best-plus-an-authy-horror-story.html b/build/blog/2015-05-29-apples-customer-service-is-still-the-best-plus-an-authy-horror-story.html deleted file mode 100644 index b086e57d..00000000 --- a/build/blog/2015-05-29-apples-customer-service-is-still-the-best-plus-an-authy-horror-story.html +++ /dev/null @@ -1,54 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-05-29T20:40:05-07:00" name="date"/> -<title>Apple's customer service is still the best (plus an Authy horror story)</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Apple's customer service is still the best (plus an Authy horror story)</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-05-29T20:40:05-07:00">May 29, 2015</time> -</div> -</header> -<p>Recently the mute switch (officially known as the Ring/Silent switch) on my little-more-than-half-a-year-old iPhone 6 Plus stopped working. It almost always bounced back to ON (ring) position upon turning, and even if I could keep it at the OFF position for five seconds, it would most likely bounce back when I thrust it into my pocket. I got bitten a few times — almost got heart attacks when the phone dinged loudly in class. Minor yet annoying problem.</p> -<p>So I took my phone to the Genius Bar today, prepared to have it sent to a repair center<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> and get a loan in the mean time — basically, I was prepared for all sorts of trouble. But nope. I demoed the problem for three seconds, my agent explained to me in five seconds that the switch alone was hard to replace and took fifteen seconds to verify my warranty status (I suppose), then off he went to retrieve a brand new replacement for me. No questions asked about the little dent on my old phone or whatever. <em>So I ended up with a brand new phone in less than five minutes.</em> (Of course, redoing setup and restoring backup took much longer than that.)</p> -<p>This is <em>the</em> customer service we should receive everywhere. Unfortunately, Apple seems to be one of the very few tech giants (or the only one?) that take customers seriously. Yeah, Apple sells products at a premium; but hey, they also live up to what one would expect from a premium product.</p> -<hr/> -<p>By the way, my only gripe during the process wasn't with Apple; it's about setting up Authy on the new phone. I verified my phone number via SMS and signed into Authy. I entered my backup password, which must be correct since it came straight off 1Password. My Authenticator accounts were displayed (I didn't verify if they would produce TOTPs) but a weird error message along the line of "data is corrupted" was shown to me, asking me to verify my phone for a second time. Unsuspecting, I asked Authy to send me another SMS, and entered the code I got. Then boom! All of a sudden <em>all my Authenticator accounts were gone</em>, leaving me with merely an Authy dev and a Coinbase account, which were the only ones that use Authy's native auth system. My heart almost sank for a second; I could almost foresee hours going down the drain, recovering (dozens of) accounts and regenerating new keys for two-factor auth.</p> -<p>That was before I immediately realized that all my secret keys were safe and sound in 1Password's database. In the past few months, AgileBits implemented TOTP support in both the iOS and OS X versions of 1Password. The day <a href="https://blog.agilebits.com/2015/04/06/1password-5-3-for-mac-the-bionic-edition-is-out/">OS X support came into stable 5.3</a>, I exported all my Authenticator secret keys from Authy to 1Password (with help from <a href="https://www.pommepause.com/2014/10/how-to-extract-your-totp-secrets-from-authy/">this blog post</a><a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a>). At that time I didn't expect 1Password would save my day later. Overall, the $50 (OS X) plus $17 (iOS) I spent on 1Password was my most worthwhile spend on software, ever.</p> -<p>The lesson to learn from my Authy horror story is that one should export and backup Authenticator secret keys from Authy before it's too late. Moreover, this one shitty experience with Authy is enough to keep me away from it for the ages to come, except for services that are Authy-specific, e.g., Coinbase<a class="footnoteRef" href="#fn3" id="fnref3"><sup>3</sup></a>. 1Password is the way to go, and with the addition of TOTP, it is one more step towards a truly one password experience. If you don't own 1Password yet, you should really get it, now.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>As I see no obvious way to replace the switch in store. My intuition was later confirmed.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>The first comment below that post is mine.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -<li id="fn3"><p>I have a Coinbase account and probably around 0.01 BTC in my wallet, but I don't really use bitcoins. At the time I signed up for two-factor auth on Coinbase, Authy seemed to be only supported system; however, I just signed in again and it seems that Coinbase is now supporting Authenticator also. Whatever the case, Authy is practically dead for me.<a class="footnotes-backlink" href="#fnref3">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-05-30-using-a-personal-helper-package-in-everyday-scripting.html b/build/blog/2015-05-30-using-a-personal-helper-package-in-everyday-scripting.html deleted file mode 100644 index 0839d2b3..00000000 --- a/build/blog/2015-05-30-using-a-personal-helper-package-in-everyday-scripting.html +++ /dev/null @@ -1,64 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-05-30T22:48:57-07:00" name="date"/> -<title>Using a personal helper package in everyday scripting</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Using a personal helper package in everyday scripting</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-05-30T22:48:57-07:00">May 30, 2015</time> -</div> -</header> -<p>Recently I've been scripting (mostly in Python) quite a bit, and noticed that some functionalities get copied over or reimplemented over and over again. Examples include reading configuration files (mostly JSON, INI, and YAML), printing progress information to tty in color, displaying progress bar, and so on.</p> -<p>In light of this, I came up with the idea of keeping a pool of helper modules in a personal helper package. I'm unimaginative at naming things, so I just named my package <code>zmwangx</code>. It is <a href="https://github.com/zmwangx/pyzmwangx">published on GitHub</a>, and the API docs are published on <a href="https://pyzmwangx.readthedocs.org">Read the Docs</a> for easy reference during scripting.<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> At the time of writing the following helper modules are available in the package:</p> -<ul> -<li><code>colorout -</code> colorized output to stdout and stderr, and much more.</li> -<li><code>config -</code> read and write config files of various common formats.</li> -<li><code>hash -</code> hash files in a memory-efficient manner.</li> -<li><code>humansize -</code> convert size in bytes to human readable string (IEC or SI).</li> -<li><code>humantime -</code> convert duration in seconds to human readable string.</li> -<li><code>infrastructure -</code> testing infrastructure.</li> -<li><code>pbar -</code> display progress bar for the progress of processing a file or stream.</li> -<li><code>urlgrep -</code> parse and match URLs from HTML documents.</li> -</ul> -<p>With a personalized helper package, scripting has never been more enjoyable. Here are just some of the benefits:</p> -<ul> -<li>Stating the obvious: write once, use everywhere (without copy/paste);</li> -<li>As always, factoring out small functional units make code more readable and easier to debug; and having a dedicated pool just for helper modules encourages one to think about factoring, <em>early</em>;</li> -<li>Bug fixes and enhancements in the helper package are instantly effective accross the board.</li> -</ul> -<p>Of course, one cannot depend on such a package in a formally published package (say, one published to PyPI), so things like <code>tools.py</code> or whatever are still necessary from time to time. But for day-to-day scripting, having a personal helper package that is used accross the board is definitely a good idea.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>I'm pretty paranoid about documenting things.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-06-07-stackoverflow-review-system-is-completely-bs.html b/build/blog/2015-06-07-stackoverflow-review-system-is-completely-bs.html deleted file mode 100644 index 1effbcc0..00000000 --- a/build/blog/2015-06-07-stackoverflow-review-system-is-completely-bs.html +++ /dev/null @@ -1,82 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-06-07T18:58:57-07:00" name="date"/> -<title>StackOverflow review system is completely BS</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/highlight.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">StackOverflow review system is completely BS</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-06-07T18:58:57-07:00">June 7, 2015</time> -</div> -</header> -<p>I just answered an interesting question about ZLE <a href="http://stackoverflow.com/q/30699242/1944784">on StackOverflow</a>, and in the process I also improved my own toolchain. For the record, the OP asked for tab completion to present working directory items (executable files and directories) on an empty command line, which led to the following widget:</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh"><span class="co"># This widget inserts "./" to the buffer and list possible completions</span> -<span class="co"># (executable files and directories in the present working directory) if the</span> -<span class="co"># buffer is empty or only contains whitespace.</span> -<span class="kw">function</span><span class="fu"> complete_pwd_items_on_empty_buffer</span> -<span class="kw">{</span> - <span class="kw">if [[</span> <span class="ot">$BUFFER</span> =~ ^[[:space:]]*$<span class="kw"> ]]</span>; <span class="kw">then</span> - <span class="ot">BUFFER+=</span><span class="st">"./"</span> - <span class="ot">CURSOR+=</span>2 - <span class="kw">zle</span> list-choices - <span class="kw">else</span> - <span class="kw">zle</span> expand-or-complete - <span class="kw">fi</span> -<span class="kw">}</span> - -<span class="kw">zle</span> -N complete_pwd_items_on_empty_buffer</code></pre></div> -<p>This is all good stuff.</p> -<p>However, at some point a <a href="https://stackoverflow.com/users/608639/jww">security architect and mobile security engineer</a> jumped in and made <a href="https://stackoverflow.com/questions/30699242/first-tab-completion-enhancement#comment49457640_30699242">the following comment</a>:</p> -<blockquote> -<p>Stack Overflow is a site for programming and development questions. This question appears to be off-topic because it is not about programming or development. See <a href="https://stackoverflow.com/help/on-topic">What topics can I ask about here</a> in the Help Center. Perhaps Super User or Unix & Linux Stack Exchange would be a better place to ask. Also see <a href="http://meta.stackexchange.com/q/134306">Where do I post questions about Dev Ops</a>?</p> -</blockquote> -<p>Then the question was put on hold by several not-so-high-rep users as off-topic, and the reason given is</p> -<blockquote> -<p>Questions about general computing hardware and software are off-topic for Stack Overflow unless they directly involve tools used primarily for programming. You may be able to get help on Super User.</p> -</blockquote> -<p>WTF. First, <em>programming ZLE widgets is programming.</em> Hell, I even gave chunks of Zsh code in the answer (and they saw that, because the stupid comment and its upvotes came after my answer was put up). If writing an interactive Android crapp in Java for your Samsung counts as programming, why is writing an interactive widget for my Z shell any inferior? Second, even if you want to follow what the Help Center says, this question clearly falls under</p> -<blockquote> -<p>software tools commonly used by programmers.</p> -</blockquote> -<p>Maybe Zsh isn't used by those specific voters (I guess most of them are Windows lusers), but it has a very vibrant community, and it clearly rules. Maybe the specific voters don't realize that Zsh is a programming language; that alone shows how ignorant they are.</p> -<p>However, these are just specific lusers. Why do I generalize and insist that "StackOverflow review system is completely BS"? Well, just look at the voters' stats; I searched for their involvement in the <code>zsh</code> tag, and here are the results: <a href="https://stackoverflow.com/search?q=user:2422776+%5Bzsh%5D">1</a>, <a href="https://stackoverflow.com/search?q=user:683218+%5Bzsh%5D">2</a>, <a href="https://stackoverflow.com/search?q=user:608639+%5Bzsh%5D">3</a>, <a href="https://stackoverflow.com/search?q=user:3836229+%5Bzsh%5D">4</a>, <a href="https://stackoverflow.com/search?q=user:2772643+%5Bzsh%5D">5</a>. Unsurprisingly, nothing, except one guy has answered a question about ASCII art, which shouldn't be placed under <code>zsh</code> in the first place. While someone knowlegeable of Zsh doesn't necessarily need to ask or answer questions about Zsh on SO, this quick search does reveal that these voters, rather than following the <code>zsh</code> tag, just popped out of nowhere, probably from the review queues. In this case it's pretty obvious that they're going after a new user (the OP just registered). And that is one of the main problems with SO's review system that makes it highly questionable in many cases:</p> -<p><strong>The review tasks are handed to people who have no knowledge of the topics,<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> and these people just operate under assumptions (e.g., new users will ask off-topic questions.)<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a></strong></p> -<p>The solution? I'm afraid <em>there's no solution as long as the system is in place</em>. Ideally one should skip questions from topics that they don't understand, but in reality people just do as they damned well please, whether because they are working toward a badge, or because they <em>think</em> they understand the topic but really don't, or because they are outright jerks. Also, there are tons of totally fucked-up questions lying in every corner of SO (like questions displaying such profound ignorance<a class="footnoteRef" href="#fn3" id="fnref3"><sup>3</sup></a> that no one would answer due to embarrassment, or those despicable "I can has code" questions) that no one cares about cleaning up, but instead they chose to target this well-meaning question that generated a pretty useful answer. By the way, this is the kind of thing I see all the time.</p> -<p>I hope SO could abandon this questionable "review queue" practice altoghether. Let people who actually follow the tags do the reviewing and voting. Honestly, no one really cares about dangling low-quality questions anyway.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>This problem isn't limited to reviews; it also applies to, for instance, approved edits. My <em>tag edits</em> (with explanations) got rejected quite a few times because the reviewers clearly didn't understand the topic — e.g., some morons assume that command line problems equal Bash problems.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>This is actually a good assumption, because this is the case at least 50% of the time from my limited experience. But one shouldn't operate under this assumption, especially if one doesn't understand the topic.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -<li id="fn3"><p>I think I asked quite a few stupid questions back in the days, and now I'm totally ashamed of them. Insterestingly, some of those questions are my highest voted ones and got me quite some reps (compared to my total rep — I'm by no means a high rep user). See <a href="http://michael.richter.name/blogs/why-i-no-longer-contribute-to-stackoverflow"><em>Why I no longer contribute to StackOverflow</em></a> for a thorough discussion of the broken rep system and its disastrous effects.<a class="footnotes-backlink" href="#fnref3">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-06-08-apple-turns-its-homepage-into-a-wwdc-liveblog.html b/build/blog/2015-06-08-apple-turns-its-homepage-into-a-wwdc-liveblog.html deleted file mode 100644 index 69c99a15..00000000 --- a/build/blog/2015-06-08-apple-turns-its-homepage-into-a-wwdc-liveblog.html +++ /dev/null @@ -1,98 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-06-08T14:42:50-07:00" name="date"/> -<title>Apple turns its homepage into a WWDC liveblog</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/highlight.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Apple turns its homepage into a WWDC liveblog</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-06-08T14:42:50-07:00">June 8, 2015</time> -</div> -</header> -<p>WWDC is Apple's biggest event every year, and WWDC keynote always attracts tons of hype. Apple knows that. In the past years folks who can't (at work, in class, etc.) or don't want to watch the crappy live stream would follow the various WWDC liveblogs presented by tech sites like Gizmodo, TechCrunch, Ars Technica, etc. But this year the landscape has changed: Apple rolled its own card-based liveblog at <a href="http://www.apple.com/live/2015-june-event/">www.apple.com/live/2015-june-event</a>.<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> Not only that; during the keynote, Apple redirected its homepage to the liveblog page, so it effectively turned its homepage into a liveblog:</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh"><span class="kw">></span> curl -sSIL http://www.apple.com -HTTP/1.1 302 Moved Temporarily -Location: http://www.apple.com/live/ -Content-Length: 210 -Content-Type: text/html; <span class="ot">charset=</span>iso-8859-1 -Expires: Mon, 08 Jun 2015 19:16:41 GMT -Cache-Control: max-age=0, no-cache, no-store -Pragma: no-cache -Date: Mon, 08 Jun 2015 19:16:41 GMT -Connection: keep-alive -Server: Apache - -HTTP/1.1 301 Moved Permanently -Content-Length: 0 -Date: Mon, 08 Jun 2015 19:16:41 GMT -Connection: keep-alive -Server: Apache -Location: http://www.apple.com/live/2015-june-event/ - -HTTP/1.1 200 OK -Last-Modified: Mon, 08 Jun 2015 15:45:30 GMT -ETag: <span class="st">"0b7bcbfbd14c411e64e728ae4d644de7"</span> -Content-Type: text/html -Cache-Control: max-age=298 -Date: Mon, 08 Jun 2015 19:16:41 GMT -Connection: keep-alive -Server: Apache</code></pre></div> -<p>Of course, you miss a few jokes and random shots of Tim or Craig from the official liveblog, but hey, who don't like that official feel?<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a></p> -<p>Here are a few screenshots of today's liveblog. Unfortunately I only know some entry level JS, so I wasn't able to capture the entire page, which uses dynamic DOM based on one's position in the page.</p> -<div class="figure"> -<a href="/img/20150608-wwdc-2015-banner.png" target="_blank"><img alt="The banner on Chrome." src="/img/20150608-wwdc-2015-banner.png"/></a> -<p class="caption">The banner on Chrome.</p> -</div> -<div class="figure"> -<a href="/img/20150608-wwdc-2015-liveblog-960x981.png" target="_blank"><img alt="Introducing OS X El Capitan, 960x981." src="/img/20150608-wwdc-2015-liveblog-960x981.png"/></a> -<p class="caption">Introducing OS X El Capitan, 960x981.</p> -</div> -<div class="figure"> -<a href="/img/20150608-wwdc-2015-liveblog-1920x1080.png" target="_blank"><img alt="A fuller experience: 1920x1080." src="/img/20150608-wwdc-2015-liveblog-1920x1080.png"/></a> -<p class="caption">A fuller experience: 1920x1080.</p> -</div> -<p>By the way, here are the full-page screenshots of <a href="http://www.apple.com/osx/elcapitan-preview/">OS X 10.11 El Capitan</a> and <a href="http://www.apple.com/ios/ios9-preview/">iOS 9</a> previews. <code>pageres</code> recently <a href="https://github.com/sindresorhus/pageres/issues/174">cannot render web fonts</a>, which is rather annoying, so I used <a href="https://github.com/mrcoles/full-page-screen-capture-chrome-extension">Full Page Screen Capture</a> to capture the shots. I then resized to 50% to reduce filesizes a bit.</p> -<div class="figure"> -<a href="/img/20150608-osx-el-capitan-preview-1920x1080-50%25.png" target="_blank"><img alt="OS X El Capitan" src="/img/20150608-osx-el-capitan-preview-1920x1080-50%25.png"/></a> -<p class="caption"><a href="http://www.apple.com/osx/elcapitan-preview/">OS X El Capitan</a></p> -</div> -<div class="figure"> -<a href="/img/20150608-ios-9-preview-1920x1080-50%25.png" target="_blank"><img alt="iOS 9" src="/img/20150608-ios-9-preview-1920x1080-50%25.png"/></a> -<p class="caption"><a href="http://www.apple.com/ios/ios9-preview/">iOS 9</a></p> -</div> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>The crappy live stream is still there, but thankfully you wouldn't see it if you're on a browser other than Safari. Just look the screenshot of the banner.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>Yeah, I know some people don't; but those people are not likely to be Apple fans either.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-06-10-chrome-disappointment-the-shabby-and-boring-old-bookmark-system-from-stone-age-strikes-back.html b/build/blog/2015-06-10-chrome-disappointment-the-shabby-and-boring-old-bookmark-system-from-stone-age-strikes-back.html deleted file mode 100644 index b39f282d..00000000 --- a/build/blog/2015-06-10-chrome-disappointment-the-shabby-and-boring-old-bookmark-system-from-stone-age-strikes-back.html +++ /dev/null @@ -1,80 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-06-10T23:17:05-07:00" name="date"/> -<title>Chrome disappointment: the shabby and boring old bookmark system from Stone Age strikes back</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Chrome disappointment: the shabby and boring old bookmark system from Stone Age strikes back</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-06-10T23:17:05-07:00">June 10, 2015</time> -</div> -</header> -<p>I just restarted my machine (in the process of planning a fresh OS re-install), and something in Chrome's UI immediately felt wrong. After a few moments I realized it was the star button (bookmark button) in the far right of the omnibox giving me the uneasy feeling — the old bookmark system is back. Broadcasting from stable channel, build 43.0.2357.124 on OS X.</p> -<div class="figure"> -<a href="/img/20150610-omnibox-with-aged-star.png" target="_blank"><img alt="What caught my immediate attention." src="/img/20150610-omnibox-with-aged-star.png"/></a> -<p class="caption">What caught my immediate attention.</p> -</div> -<div class="figure"> -<a href="/img/20150610-old-bookmark-manager.png" target="_blank"><img alt="The heart sinking feeling when I saw this again." src="/img/20150610-old-bookmark-manager.png"/></a> -<p class="caption">The heart sinking feeling when I saw this again.</p> -</div> -<p>I went to flags and made sure "Enable the new bookmark app system" wasn't tempered with. It wasn't. Anyway, I changed it to "Enabled" and restarted Chrome. No go, still the old crap. So I Googled my way to <a href="https://productforums.google.com/forum/#!topic/chrome/mhIX5LB23As">the announcement</a>:</p> -<blockquote> -<p>Hi Everyone,</p> -<p>Our team is committed to improving Chrome’s bookmarks experience, but for the time being, we’ve decided to bring back the previous version. Our team will continue to explore other ways to improve the bookmarks experience. You’ll see the previous version of the bookmarks manager return to your Chrome browser shortly.</p> -<p>For those of you who enjoyed using the new bookmarks manager, you can still keep the new experience by downloading the Bookmarks Manager extension from the Chrome Web Store.</p> -<p>We appreciate hearing all of your thoughtful feedback. Feel free to leave us with any additional comments here in this thread.</p> -<p>Best,<br/> The Chrome team</p> -</blockquote> -<p>This is just very disappointing. My default browser changes a lot, but I've been tagging along with Opera for <a href="/blog/2014-12-14-the-google-chrome-comic-a-classic.html">almost the entirety of 2014</a>, so I've long been used to visual bookmarks. And honestly, it never felt weird or anything; I saw it as an improvement the first time I was introduced to the concept.</p> -<p>I know, there's always a demographic that would fiercely resist any change; they would reject anything new at a glance (or after using for a second) and start moaning right away, disregarding all the new benefits here and there. There's also another demographic who not only have no taste in design at all, but would also actively seek to tear down any visual enhancement — 90s visual is enough for them for life, any more is unsolicited and insulting. When these two demographics meet<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> and somehow make the developers retreat, the outcome is simple and sad: <em>we can never have nice things.</em></p> -<p>I'm not saying I'm 100% satisfied with Chrome's visual bookmarks. In fact far from that. For one thing, Google is really pretty bad at visual design.<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a> Also, not being able to adjust tile size or toggle a list view is rather lame. However, whatever problems there are, the new system is at least 200% better than the old one (just look that the screenshots!).<a class="footnoteRef" href="#fn3" id="fnref3"><sup>3</sup></a> <em>The team should focus on making the new system better,</em> such as implementing the features I mentioned above, rather than throw it into the trash can and resurrect the old system from Stone Age.</p> -<p>I know, throwing things away is part of Google's philosophy. They usually toy with a wide range of ideas and discard the ones that people don't buy into. Not that I whole-heartedly agree with strategy, but to advance technology there has to be some Brownian motion out there, and Google usually listens to the market, which is fine. In this case, however, there's really nothing innovative about visual bookmarks, and I can't see how the new system could harm market share or anything either. In fact, it could only help, since except the anti-design demographic, who would choose the aged and boring layout from the old system?<a class="footnoteRef" href="#fn4" id="fnref4"><sup>4</sup></a> Moreover, people tend to ignore the fact that the new system is also functionally superior — it offers to</p> -<ul> -<li>Learn and suggest folder for a new bookmark (which is often accurate);</li> -<li>Create auto folders based on site or keyword;</li> -<li>Allow arbitrary text data to be stored with each entry (e.g., a page-specific non-sensitive access code);</li> -<li>One tap pop from assigned folder;</li> -</ul> -<p>and more. Those that resist everything new are simply blind. The team claim that they are listening to "thoughtful feedback"; well, can they tell "thoughtful feedback" from blind suspicion and denial about everything? And they do realize that feedback is heavily biased, as someone with positive experience (unless he is a hardcore fan) is unlikely to leave them a thank you message? I think it's pretty clear that the majority of users won't care either way<a class="footnoteRef" href="#fn5" id="fnref5"><sup>5</sup></a>; the majority of the rest was happy with the change; and the rest, comprising only a diminishingly small percentage, is what kept us from having nice things.</p> -<p>Even if one agrees with nothing from the last paragraph, one has to realize that randomly dropping a big change this way is just irresponsible.<a class="footnoteRef" href="#fn6" id="fnref6"><sup>6</sup></a> There were hurt feelings when the change was first introduced (not that I care about them), so don't change mind again three weeks later, hurting yet another camp. Whether it was a change for the good or the bad, admit it was done (admit you screwed up if you did) and focus on improving it.</p> -<p>End of rant, off to install the <a href="https://chrome.google.com/webstore/detail/bookmark-manager/gmlllbghnfkpflemihljekbapjopfjik">Bookmark Manager extension</a>.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>There's actually a pretty big overlap between these two demographics.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>The giant blue search bar at the top is especially ridiculous.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -<li id="fn3"><p>I didn't bother to switch to an earlier build just to take a screenshot of the visual system, so unfortunately there's no comparison here. But anyone who's been there knows what I'm saying.<a class="footnotes-backlink" href="#fnref3">↩︎</a></p></li> -<li id="fn4"><p>Unless one has hundreds of bookmarks in a single folder (which probably means some cleanup or refactoring is long overdue), the old layout is unlikely to be easier on the eyes or anything.<a class="footnotes-backlink" href="#fnref4">↩︎</a></p></li> -<li id="fn5"><p>Well, grandmas have one more thing to learn, I guess...<a class="footnotes-backlink" href="#fnref5">↩︎</a></p></li> -<li id="fn6"><p>In other news, Google dropped YouTube collections two weeks ago (<a href="https://support.google.com/youtube/answer/6233832?hl=en">May 26, 2015</a>), causing another round of agony. Also, subscriptions were all over the place once more, just like Google's project landscape.<a class="footnotes-backlink" href="#fnref6">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-06-12-the-tip-of-the-iceberg.html b/build/blog/2015-06-12-the-tip-of-the-iceberg.html deleted file mode 100644 index eefb79ec..00000000 --- a/build/blog/2015-06-12-the-tip-of-the-iceberg.html +++ /dev/null @@ -1,54 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-06-12T14:24:18-07:00" name="date"/> -<title>The tip of the iceberg</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">The tip of the iceberg</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-06-12T14:24:18-07:00">June 12, 2015</time> -</div> -</header> -<p><em><strong>Disclaimer</strong>: While this post might have been triggered by a <a href="https://twitter.com/search?q=%23distractinglysexy">specific</a><a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> campaign, I'm certainly not addressing any specific concern or siding with any party. I never bothered to learn enough about a specific campaign to form a judgement that I would stand by,<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a> since I simply don't care. I'm writing this post because I'm just too tired to see them popping up in my feeds every once in a while.</em></p> -<p><em>By the way, I'm not sure if I'm going to stand by this post when I wake up tomorrow morning. It will stay either way, though.</em></p> -<hr/> -<p>I have the impression that these days there's at least one public shaming campaign going on every week, justified by political correctness, and serving as a great outlet for school or workplace frustration accumulated during the week. And every now and then, a woman or man<a class="footnoteRef" href="#fn3" id="fnref3"><sup>3</sup></a> is destroyed by such a campaign, although all she or he did was to make a somewhat flippant yet universally true,<a class="footnoteRef" href="#fn4" id="fnref4"><sup>4</sup></a> almost universally true, or at the very least, not-meant-to-be-offensive, remark.</p> -<p>On the face of it (e.g., retweet counts), you might be convinced that the world is seriously supportive of such campaigns. However, you have to realize that <em>the tens or even hundreds of thousands of campaigners are still just one tip of the iceberg called the society</em>. Behind every campaigner there are probably ten people holding opposite views, and one thousand who simply don't care either way<a class="footnoteRef" href="#fn5" id="fnref5"><sup>5</sup></a>. Since political correctness is involved, how many people would you expect to be outspoken about their true opinions? Most likely people are muted by the fear of being politically wrong and being pursued and destroyed, just like the poor guy at the center of the storm. Moreover, I'm afraid that some (if not most) campaigners are not really offended, but just joining what they see as a hilarious ride — they don't mind if a woman or man is destroyed along the way. You know, humans can be unintentionally cruel to people not worth being cruel to. This statement also applies to some of the shaming campaign targets, but <em>being unintentionally cruel doesn't automatically make them worth being cruel to</em>.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>In this case the campaign is too civilized to be called a shaming campaign.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>And I question if most shamers did.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -<li id="fn3"><p>Note how I have to be distracted from writing to consider the wording that should have been subconscious, and eventually write in this style.<a class="footnotes-backlink" href="#fnref3">↩︎</a></p></li> -<li id="fn4"><p>Sometimes a certain group of people seek to redefine certain concepts or terms so that truths stated with older concepts or terms in mind are no longer true. That's fine. But before you label someone as an asshole, you have to realize that while you are free to embrace <em>your</em> modernity, some (if not most) people are just not as radical or as concerned about your topic, and they are just holding on to the truths and values they were taught.<a class="footnotes-backlink" href="#fnref4">↩︎</a></p></li> -<li id="fn5"><p>Yes, I'm among the one thousand.<a class="footnotes-backlink" href="#fnref5">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-06-23-all-problems-solved.html b/build/blog/2015-06-23-all-problems-solved.html deleted file mode 100644 index 003b2655..00000000 --- a/build/blog/2015-06-23-all-problems-solved.html +++ /dev/null @@ -1,56 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-06-23T21:47:07-07:00" name="date"/> -<title>All problems solved!?</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">All problems solved!?</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-06-23T21:47:07-07:00">June 23, 2015</time> -</div> -</header> -<p>The project I've been working on intermittently over the past month, <a href="https://github.com/zmwangx/pyonedrive"><code>pyonedrive</code></a>, a OneDrive API v1.0 API/CLI client, is now quite satisfactory in terms of its feature set<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a>, so today I'm thinking about what I should work on next. Of course there's <a href="https://github.com/zmwangx/pyonedrive/labels/enhancement">a lot more I can do</a>, but what is done already encapsulates 95%+ of my daily usage; moreover, as everyone knows, refining an existing project is not as exciting as starting a new one and making something happen that is previously tedious or impossible.</p> -<p>To my surprise, <em>I can't think of anything</em>. I now realized that I don't have many peculiar computing needs. I needed a storyboard generator which I couldn't find anywhere, <a href="https://github.com/zmwangx/storyboard">so I wrote one</a>, and got an <a href="https://storyboard.readthedocs.org/en/latest/metadata-cli.html">elegant FFprobe wrapper</a> for free. I hated the crappy CLI shipped with <a href="https://github.com/mk-fg/python-onedrive"><code>python-onedrive</code></a><a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a> that constantly fails and dumps, so I <a href="https://github.com/zmwangx/pyonedrive">rolled my own</a> around the new API. In the process of coding up these two things, I learned quite a bit of Python — the kind of things I would never learn by reading tutorials or references alone. Other than these two, I need to interact with a few Web services and scrape a few Web sites, which are easily taken care of in bash/zsh/python (node might better serve some, but they ain't broke, so why rewrite). I also need some other CLI tools but those have been solved by existing projects, probably started by people with similar needs. Some of them need some clean-up and feature boost, e.g., <a href="https://github.com/soimort/you-get"><code>you-get</code></a>, but I'm not inclined to refactor or submit substantial PRs to other people's projects, so I usually just write my own wrappers to bypass their limitations.<a class="footnoteRef" href="#fn3" id="fnref3"><sup>3</sup></a> What else? Basically nothing.</p> -<p>So I'm in a strange situation that I feel like writing software for fun and profit, but don't have anything exciting to lay my hands upon (other than improving existing things). Of course I could learn my next language, but language learning without real world usage is likely to be futile. For instance, I would like to learn some Go or Rust, but why do I need a compiled, C/C++ replacement these days, when scripting takes care of all my personal needs? Not clear. Maybe it's a good time to concentrate on the real important things in my career.</p> -<hr/> -<p>Update: Whilst writing this post, I came up with a project after all. I always had the idea of keeping an encrypted journal — real encryption, not the fake "password protection" of DayOne.<a class="footnoteRef" href="#fn4" id="fnref4"><sup>4</sup></a> The journal should be decrypted — probably only into memory — upon entry (after securely typing in password), and each text/image object should be encrypted separately to ease syncing (so using an encrypted sparseimage won't work).</p> -<p>In principle an Emacs package should be able to do this, but going forward Elisp is a pretty horrible choice of language for anything substantial (think of, for example, threading, which there is none). Therefore, I'm inclined to write this in ObjC/Swift with Cocoa. This will be my first attempt at Cocoa programming, and my first serious involvement with Xcode (other than CLT, of course) after quite a few years<a class="footnoteRef" href="#fn5" id="fnref5"><sup>5</sup></a>. Actually I've always been looking for an excuse to learn some Swift.</p> -<p>Oops, am I falling into <a href="https://sivers.org/zipit">prematurely announcing my plans</a>? Hopefully not.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>In fact it already exceeded my original expectations — <code>pyonedrive</code> started out as a <a href="https://github.com/zmwangx/pyonedrive/blob/4d21308545ec1462c3892b9ca25300042f1ccb81/README.rst">bare bones batch uploader</a>.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>I never bothered to look at the API.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -<li id="fn3"><p>E.g., for <code>you-get</code>, I wrote a wrapper with concurrency support and much more surrounding <code>you-get</code>'s <code>--url</code> option. (But honestly, for whatever reason, links provided by <code>flvcd.com</code> for Chinese video streaming sites are much better than those parsed by <code>you-get</code> in terms of download speed, so these days I almost use <code>flvcd.com</code>'s <code>BigRats</code> exclusively, except when it similarly can't pick up a reasonable speed, in which case I would grind with my <code>you-get</code> wrapper, which was designed exactly for grinding.)<a class="footnotes-backlink" href="#fnref3">↩︎</a></p></li> -<li id="fn4"><p>And DayOne's Markdown engine sucks, among other limitations, like the ridiculous one-image-per-entry.<a class="footnotes-backlink" href="#fnref4">↩︎</a></p></li> -<li id="fn5"><p>I used to use Xcode as a C++ IDE before I was introduced to the brave new world of command line wizardry.<a class="footnotes-backlink" href="#fnref5">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-06-26-ios-9-searchable-settings.html b/build/blog/2015-06-26-ios-9-searchable-settings.html deleted file mode 100644 index f9db7364..00000000 --- a/build/blog/2015-06-26-ios-9-searchable-settings.html +++ /dev/null @@ -1,48 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-06-26T23:59:28-07:00" name="date"/> -<title>iOS 9: searchable Settings</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">iOS 9: searchable Settings</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-06-26T23:59:28-07:00">June 26, 2015</time> -</div> -</header> -<p>Finally it's here. According to <a href="http://www.macrumors.com/2015/06/26/hidden-features-in-ios-9-and-os-x-el-capitan/">MacRumors</a>:</p> -<blockquote> -<p>Apple's introduced a wide range of feature additions and minor tweaks in iOS 9 that make some very useful improvements to iOS. For example, there's now a Notification Center widget that displays the battery life of connected devices like the Apple Watch, and <strong>there's a search bar in the Settings app that lets you find a specific setting very quickly.</strong></p> -</blockquote> -<p>Good to see <a href="/blog/2015-05-06-searchable-settings-are-one-honking-great-idea-lets-do-more-of-those.html">my wish</a> granted.</p> -<div class="figure"> -<a href="/img/20150627-macrumors-demo-ios9-searchable-settings.png" target="_blank"><img alt="A screenshot of iOS 9 Settings in action." src="/img/20150627-macrumors-demo-ios9-searchable-settings.png"/></a> -<p class="caption">A screenshot of iOS 9 Settings in action.</p> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-06-27-automatically-clean-up-previous-mobile-applications.html b/build/blog/2015-06-27-automatically-clean-up-previous-mobile-applications.html deleted file mode 100644 index 29faf9ca..00000000 --- a/build/blog/2015-06-27-automatically-clean-up-previous-mobile-applications.html +++ /dev/null @@ -1,157 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-06-27T21:19:59-07:00" name="date"/> -<title>Automatically clean up "Previous Mobile Applications"</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/highlight.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Automatically clean up "Previous Mobile Applications"</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-06-27T21:19:59-07:00">June 27, 2015</time> -</div> -</header> -<p>iTunes keeps a "Previous Mobile Applications" folder of questionable value, which always annoys me. It eats into disk space and wastes syncing/backup cycles and bandwidth; you can easily find horror stories online about <a href="http://forums.macrumors.com/threads/5-years-of-deleted-iphone-apps-accumulated-in-my-itunes-library.1781676/#post-19749496">100GB+ PMA folders</a>. The value? You might be able to roll back to an earlier version, or restore an app pulled from the App Store. Really? I never had that need in my life<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a>; have you? Worst of all, there should be a periodic clean up option — just like how deleted mail are automatically purged after one month, but the option is missing.</p> -<p>Therefore, I wrote a trivial Python script to do the periodic cleanup. Feel free to grab my script below (also available at <a class="uri" href="http://git.io/previous-mobile-applications">http://git.io/previous-mobile-applications</a>) to save a few minutes of hacking. It should be plugged into a daily or weekly or monthly cron job (or the equivalent), and it writes data to <code>~/.local/share/itunes/previous-mobile-applications.json</code> by default. To customize, just modify the global constants.</p> -<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="co">#!/usr/bin/env python3</span> - -<span class="co">"""Periodically clean up "Previous Mobile Applications" of iTunes."""</span> - -<span class="im">import</span> arrow -<span class="im">import</span> datetime -<span class="im">import</span> json -<span class="im">import</span> os -<span class="im">import</span> sys - -OFFENDING_DIR <span class="op">=</span> os.path.expanduser(<span class="st">"~/Music/iTunes/iTunes Media/Mobile Applications/Previous Mobile Applications"</span>) -STORAGE_DIR <span class="op">=</span> os.path.expanduser(<span class="st">"~/.local/share/itunes"</span>) -STORAGE_FILE <span class="op">=</span> os.path.join(STORAGE_DIR, <span class="st">"previous-mobile-applications.json"</span>) - -DELETE_AFTER <span class="op">=</span> datetime.timedelta(days<span class="op">=</span><span class="dv">7</span>) - -<span class="kw">def</span> load_storage(): - <span class="co">"""Load stored dictionary of seen apps from STORAGE_FILE.</span> - -<span class="co"> Returns</span> -<span class="co"> -------</span> -<span class="co"> seen_app_dict : dict</span> -<span class="co"> Dictionary of (app_filename, first_seen_date) key-value pairs,</span> -<span class="co"> where app_filename is str, and last_seen_date is datetime.date.</span> - -<span class="co"> """</span> - os.makedirs(STORAGE_DIR, mode<span class="op">=</span><span class="bn">0o700</span>, exist_ok<span class="op">=</span><span class="va">True</span>) - <span class="cf">try</span>: - <span class="cf">with</span> <span class="bu">open</span>(STORAGE_FILE, encoding<span class="op">=</span><span class="st">"utf-8"</span>) <span class="im">as</span> fp: - serializable_seen_app_dict <span class="op">=</span> json.load(fp) - <span class="cf">return</span> {app_filename: arrow.get(serialized_first_seen_date).date() - <span class="cf">for</span> app_filename, serialized_first_seen_date <span class="kw">in</span> serializable_seen_app_dict.items()} - <span class="cf">except</span> <span class="pp">OSError</span>: - <span class="cf">return</span> {} - -<span class="kw">def</span> write_storage(seen_app_dict): - <span class="co">"""Write the dictionary of seen apps to STORAGE_FILE.</span> - -<span class="co"> Parameters</span> -<span class="co"> ----------</span> -<span class="co"> seen_app_dict : dict</span> -<span class="co"> See the return format of load_storage().</span> - -<span class="co"> Returns</span> -<span class="co"> -------</span> -<span class="co"> 0 or 1</span> -<span class="co"> Return code indicating success or failure.</span> - -<span class="co"> """</span> - <span class="co"># convert datetime.time to str (ISO 8601)</span> - serializable_seen_app_dict <span class="op">=</span> {app_filename: first_seen_date.isoformat() - <span class="cf">for</span> app_filename, first_seen_date <span class="kw">in</span> seen_app_dict.items()} - os.makedirs(STORAGE_DIR, mode<span class="op">=</span><span class="bn">0o700</span>, exist_ok<span class="op">=</span><span class="va">True</span>) - <span class="cf">try</span>: - <span class="cf">with</span> <span class="bu">open</span>(STORAGE_FILE, mode<span class="op">=</span><span class="st">"w"</span>, encoding<span class="op">=</span><span class="st">"utf-8"</span>) <span class="im">as</span> fp: - json.dump(serializable_seen_app_dict, fp, indent<span class="op">=</span><span class="dv">2</span>, sort_keys<span class="op">=</span><span class="va">True</span>) - <span class="cf">return</span> <span class="dv">0</span> - <span class="cf">except</span> <span class="pp">OSError</span> <span class="im">as</span> err: - sys.stderr.write(<span class="st">"error: failed to write to '</span><span class="sc">%s</span><span class="st">': </span><span class="sc">%s</span><span class="st">"</span> <span class="op">%</span> (STORAGE_FILE, <span class="bu">str</span>(err))) - <span class="cf">return</span> <span class="dv">1</span> - -<span class="kw">def</span> main(): - <span class="co">"""Main.</span> - -<span class="co"> Returns</span> -<span class="co"> -------</span> -<span class="co"> 0 or 1</span> -<span class="co"> Return code indicating success or failure.</span> - -<span class="co"> """</span> - <span class="cf">if</span> <span class="kw">not</span> os.path.isdir(OFFENDING_DIR): - <span class="co"># good, you don't have that junk</span> - <span class="cf">return</span> <span class="dv">0</span> - - today <span class="op">=</span> datetime.date.today() - seen_app_dict <span class="op">=</span> load_storage() - current_app_list <span class="op">=</span> os.listdir(OFFENDING_DIR) - - <span class="co"># boot already disappeared apps</span> - <span class="cf">for</span> app <span class="kw">in</span> [app <span class="cf">for</span> app <span class="kw">in</span> seen_app_dict <span class="cf">if</span> app <span class="kw">not</span> <span class="kw">in</span> current_app_list]: - seen_app_dict.pop(app) - - <span class="co"># add newly appeared apps</span> - <span class="cf">for</span> app <span class="kw">in</span> [app <span class="cf">for</span> app <span class="kw">in</span> current_app_list <span class="cf">if</span> app <span class="kw">not</span> <span class="kw">in</span> seen_app_dict]: - seen_app_dict[app] <span class="op">=</span> today - - <span class="co"># delete expired apps</span> - returncode <span class="op">=</span> <span class="dv">0</span> - newly_deleted_apps <span class="op">=</span> [] - <span class="cf">for</span> app <span class="kw">in</span> seen_app_dict: - <span class="cf">if</span> today <span class="op">>=</span> seen_app_dict[app] <span class="op">+</span> DELETE_AFTER: - app_path <span class="op">=</span> os.path.join(OFFENDING_DIR, app) - <span class="cf">try</span>: - os.remove(app_path) - newly_deleted_apps.append(app) - <span class="cf">except</span> <span class="pp">OSError</span> <span class="im">as</span> err: - sys.stderr.write(<span class="st">"error: failed to remove '</span><span class="sc">%s</span><span class="st">': </span><span class="sc">%s</span><span class="st">"</span> <span class="op">%</span> (app_path, <span class="bu">str</span>(err))) - returncode <span class="op">=</span> <span class="dv">1</span> - - <span class="cf">for</span> app <span class="kw">in</span> newly_deleted_apps: - seen_app_dict.pop(app) - - <span class="co"># write data to disk</span> - returncode <span class="op">|=</span> write_storage(seen_app_dict) - - <span class="cf">return</span> returncode - -<span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">"__main__"</span>: - exit(main())</code></pre></div> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>Full disclosure: unlike many people, I'm not very obsessed with my phone, and I only have about two dozen third-party apps.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-06-29-dl-cmplnts-in-apple-news.html b/build/blog/2015-06-29-dl-cmplnts-in-apple-news.html deleted file mode 100644 index 2fac2055..00000000 --- a/build/blog/2015-06-29-dl-cmplnts-in-apple-news.html +++ /dev/null @@ -1,63 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-06-29T23:14:42-07:00" name="date"/> -<title>dl? cmplnts? in Apple News</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">dl? cmplnts? in Apple News</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-06-29T23:14:42-07:00">June 29, 2015</time> -</div> -</header> -<p>I submitted this blog to Apple via <a href="https://developer.apple.com/news-publisher/">News Publisher</a> a few days after the WWDC keynote, just to get a feel for the submission process. It was easy; basically I just needed to provide an <a href="/atom.xml">Atom 1.0</a> or <a href="/rss.xml">RSS 2.0</a> feed, both of which I already have anyway.<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> I was told at the end of the submission process that my submission would be reviewed.</p> -<p>Just now, quite surprisingly, I got the acceptance email from News Publisher:</p> -<div class="figure"> -<a href="/img/20150629-news-publisher-acceptance-email.png" target="_blank"><img alt="Acceptance email from News Publisher." src="/img/20150629-news-publisher-acceptance-email.png"/></a> -<p class="caption">Acceptance email from News Publisher.</p> -</div> -<p>The link to my channel appears to be</p> -<blockquote> -<p><a class="uri" href="https://news.apple.com/TdEf82WUNSQeNOsvYyyu48Q">https://news.apple.com/TdEf82WUNSQeNOsvYyyu48Q</a></p> -</blockquote> -<p>But at the time of writing, trying to open this page just turns up a "sorry, this item isn't available in Apple News". Not sure if the page hasn't been updated, or if I really need an iOS 9 device to access. My current guess is the former — there's no reason Apple won't provide a channel preview in good ol' HTML.<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a> I don't have an iOS 9 device yet, so I don't know how well my content, especially preformatted code blocks, will fare in News. Either way I won't adjust my content, but it would be fun to see the capabilities of Apple's official "RSS reader".</p> -<hr/> -<p><em>June 30, 2015 update:</em> The page has been updated, and now the message makes much more sense:</p> -<div class="figure"> -<a href="/img/20150630-dl-cmplnts-on-apple-news.png" target="_blank"><img alt="Apple News is coming soon. This channel or topic is only available in Apple News." src="/img/20150630-dl-cmplnts-on-apple-news.png"/></a> -<p class="caption">Apple News is coming soon. This channel or topic is only available in Apple News.</p> -</div> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>Of course my content isn't really optimized for the Apple News format, but why would I care.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>Or maybe they will only open up regular browser traffic after iOS 9 stable is released.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-07-15-zsh-save-stdout-stderr-and-return-value-of-command-to-different-variables-without-temp-file.html b/build/blog/2015-07-15-zsh-save-stdout-stderr-and-return-value-of-command-to-different-variables-without-temp-file.html deleted file mode 100644 index 1aa21bf0..00000000 --- a/build/blog/2015-07-15-zsh-save-stdout-stderr-and-return-value-of-command-to-different-variables-without-temp-file.html +++ /dev/null @@ -1,68 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-07-15T09:21:47-07:00" name="date"/> -<title>Zsh: save stdout, stderr, and return value of command to different variables (without temp file)</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/highlight.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Zsh: save stdout, stderr, and return value of command to different variables (without temp file)</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-07-15T09:21:47-07:00">July 15, 2015</time> -</div> -</header> -<p>This is something worth sharing. The idea was based on <a href="http://stackoverflow.com/a/18086548/1944784">this SO answer</a>, and I cooked up this particular implementation to remove potential race conditions, with input from Mathias Fredriksson<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a>. See <a href="https://github.com/mafredri/zsh-async/issues/1">mafredri/zsh-async#1</a>, and in particular <a href="https://github.com/mafredri/zsh-async/issues/1#issuecomment-121468958">this comment</a> for explanation.</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh"><span class="co"># The following construct evaluates "$@" and saves output on stdout in the</span> -<span class="co"># parameter stdout, output on stderr in the parameter stderr, and return value</span> -<span class="co"># in the parameter return.</span> -<span class="co">#</span> -<span class="co"># The idea was based on http://stackoverflow.com/a/18086548/1944784, but this</span> -<span class="co"># implementation is completely race-condition-free. The implementation was</span> -<span class="co"># refined during my exchange with Mathias Fredriksson @mafredri, in</span> -<span class="co"># https://github.com/mafredri/zsh-async/issues/1. See mainly</span> -<span class="co"># https://github.com/mafredri/zsh-async/issues/1#issuecomment-121468958, where</span> -<span class="co"># the advantage of this implementation is explained.</span> - -<span class="kw">unset</span> stdout stderr ret -<span class="kw">eval</span> <span class="st">"</span> -<span class="ot">$(</span> - <span class="kw">{</span> - <span class="ot">stdout=$(</span><span class="kw">eval</span> <span class="st">"</span><span class="ot">$@</span><span class="st">"</span><span class="ot">)</span> - <span class="ot">ret=$?</span> - <span class="kw">typeset</span> -p <span class="ot">stdout</span> <span class="ot">ret</span> - <span class="kw">}</span> <span class="kw">2></span> <span class="kw">>(</span><span class="ot">stderr=$(</span><span class="kw">cat</span><span class="ot">)</span>; <span class="kw">typeset</span> -p <span class="ot">stderr</span><span class="kw">)</span> -<span class="ot">)</span><span class="st">"</span></code></pre></div> -<p>Also available as <a href="https://gist.github.com/zmwangx/efababea6258cedea07a">a gist</a>.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>Mathias (<a href="https://github.com/mafredri">@mafredri</a>) is the author of the lovely <a href="https://github.com/mafredri/zsh-async">zsh-async</a> library, and a maintainer of <a href="https://github.com/sindresorhus/pure">sindresorhus/pure</a>. He forever revolutionalized <a href="https://github.com/zmwangx/prezto/blob/master/modules/prompt/functions/prompt_zmwangx_setup">my prompt</a>.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-07-19-github-experimental-attachment-formats-pdf-docx-and-pptx.html b/build/blog/2015-07-19-github-experimental-attachment-formats-pdf-docx-and-pptx.html deleted file mode 100644 index 5ddbf4a4..00000000 --- a/build/blog/2015-07-19-github-experimental-attachment-formats-pdf-docx-and-pptx.html +++ /dev/null @@ -1,104 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-07-19T21:58:01-07:00" name="date"/> -<title>GitHub experimental attachment formats: PDF, DOCX and PPTX!?!</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">GitHub experimental attachment formats: PDF, DOCX and PPTX!?!</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-07-19T21:58:01-07:00">July 19, 2015</time> -</div> -</header> -<p>I was browsing <a href="https://github.com/github/hub">github/hub</a>, and noticed something funny in the issue tracker:</p> -<blockquote> -<p>Attach more than just images: Now you can attach PDF, <strong>Word</strong>, and <strong>PowerPoint</strong> files to your comments on Issues and Pull Requests. This experimental feature is only available to some repositories.<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a></p> -</blockquote> -<div class="figure"> -<a href="/img/20150719-github-attachment-new-formats.png" target="_blank"><img alt='"Attach more than just images: Now you can attach PDF, Word, and PowerPoint files to your comments on Issues and Pull Requests." WOW, JUST WOW.' src="/img/20150719-github-attachment-new-formats.png"/></a> -<p class="caption">"Attach more than just images: Now you can attach PDF, Word, and PowerPoint files to your comments on Issues and Pull Requests." WOW, JUST WOW.</p> -</div> -<p>For a moment I wondered if today's April Fools', but apparently it isn't. Which makes me wonder: is GitHub expanding its customer base to grandparents? Or is this a heavily demanded feature on GitHub Enterprise by nontechnical managers and sales personnel? Attaching PDF to issues and PRs is already laughable enough; I just can't imagine any developer asking for Microsoft Office support. I mean, what should we do with those? Download those crap, wait ten minutes for Microsoft applications to launch, just to read a few pages of text? I know GitHub is expanding to designers by rolling out features like PSD diffing<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a> and Large File Storage (<a href="https://git-lfs.github.com/"><code>git-lfs</code></a>) for assets, so is this feature also targeting nontechnical designers? Not sure. <strong>At any rate, this "feature" is simply ridiculous.</strong></p> -<p>GitHub has long been lacking good attachment support. Granted, one can dump files to gists and then link to them from issues, but that's a pain for most people (and not all people are aware of that). The lack of attachment support (other than images) is keeping some projects from hosting their issue trackers on GitHub, whose issue tracking system is otherwise extraodinary.<a class="footnoteRef" href="#fn3" id="fnref3"><sup>3</sup></a> One notable example that I care about is <a href="https://gitlab.com/gnachman/iterm2/issues">iTerm2</a>, which asks users to attach the user preference plist and a gzipped debug log when opening a new bug. <strong>Therefore, GitHub should improve their attachment support by accepting plain text files<a class="footnoteRef" href="#fn4" id="fnref4"><sup>4</sup></a>, small gzips, common binary config file formats like binary Plist XML and so on that developers care about. But instead, they are working on... Microsoft Office???</strong></p> -<p>My attitude towards Microsoft Office (mostly Word) is best described in a gist/tutorial that I wrote more than a year ago: <a href="https://gist.github.com/zmwangx/9987772"><em>Markdown, LaTeX, etc.</em></a>. The <a href="https://gist.github.com/zmwangx/9987772#tips-for-microsoft-office-users">"Tips for Microsoft Office users"</a> section is quoted out in full at the end of this post. My feelings toward Microsoft, and by extension, Office, has softened quite a bit since I wrote that tutorial (in particular, unlimited OneDrive storage for Office 365 subscribers was a pretty good bribe), but every word in that section still applies to Microsoft Word. <strong>It is just sad that so many people all around the globe are still stuck in this Microsoft hell, not knowing that they have been liberated, and that they could have been free all along. And this move by GitHub is definitely not helping.</strong></p> -<hr/> -<p><strong>Appendix.</strong> From my tutorial <a href="https://gist.github.com/zmwangx/9987772"><em>Markdown, LaTeX, etc.</em></a>:</p> -<blockquote> -<h2 id="tips-for-microsoft-office-users">Tips for Microsoft Office users</h2> -<ol style="list-style-type: decimal"> -<li>Stop using Microsoft Office, <strong>RIGHT NOW</strong>;</li> -<li>Do 1;</li> -<li>Do 2;</li> -<li>......</li> -</ol> -<h3> -Why I hate Microsoft Office -</h3> -<ol style="list-style-type: decimal"> -<li><p>Microsoft Office is non-free, free both as in "free speech" and "free beer."</p></li> -<li><p>Microsoft Office is not only non-free, but also expensive.</p></li> -<li><p><code>.docx</code> is proprietary format. Microsoft has full control over it (correct me if I'm wrong). Hopefully they at least released it as a standard, so vendor lock-in won't happen. However, Microsoft could change mind any time.</p></li> -<li><p>Most Microsoft Word documents are text documents. But they are not readable and editable at all with text editors (in principle you could read and edit XML, but seriously, who would bother to do that). <strong>So why Microsoft Office when plain text is nice, elegant, efficient, fast, and free?</strong> Even when you need some formatting, there are Markdown and other plain text, human readble, and open source formats. I really hate it when people send me docx or ask me to send docx. Why assume I have the crap proprietary software installed? You could at least save as PDF before sending to me.</p> -<p>(PDF is another story. It started as proprietary, but was released free of charge a long time ago, and has since been made an open standard. There are a good number of great open source PDF generators, PDFLaTeX being one notable example. And after all, PDF and PostScript are intended for printers — they are not so easily made human readable without an interpreter, so using a proprietary format in this setting is reasonable.)</p> -<p>You might argue that docx can be edited with LibreOffice, OpenOffice, etc. However, first of all, documents created by Microsoft Office are not always (always not) rendered the same in these Offices; 100% compatibility has never been achieved. If you choose to work with Microsoft Office documents, you either be cheap and worry about lock-out/lock-in/damage/permanent damage (people who love Microsoft Office are often not competent enough to do back-up right), or throw your money at Microsoft. And point is: <strong>plain text is both free and reliable in the first place.</strong></p></li> -<li><p>Microsoft could change their pricing model at any time, just as Adobe did to their Creative Suite. They've already been exploring the subscription model via Office 365 for a while, which is $99.99 a year (home). In the future, Office might turn to subscription only, meaning that you would never have a full copy of your (already crappy) software that is guaranteed to work regardless of time, and that they could raise the subcription price at any time and drive you nuts instantly. (Microsoft recently released Office on iPad, which is already subscription only. Watch out for the trend.)</p></li> -<li><p>Forgot to highlight one major annoyance. As you already know, I hate Microsoft Office; however, as mentioned in 4, I'm forced to keep the crap installed and occasionally launch it (which takes something around ten minutes just to launch) thanks to other people who insist on Microsoft Office. Every single launch deepens the hatred.</p></li> -<li><p>(<em>05/04/2014</em> update) Apart from storage, transmission, and distribution, Microsoft Office — and word processors in general — are also bad for <em>writing</em>. To quote the <a href="http://asciidoctor.org/docs/what-is-asciidoc/">AsciiDoc official introduction</a>, the "Word processors, the real writer’s block" section,</p> -<blockquote> -<p>When you are in the writing (i.e., <a href="http://blog.stoyanstefanov.com/writing-vs-typing/">typing</a>) phase, you want the words to flow onto the screen with minimal distractions and interruptions. Flow, not just time, is essential.</p> -<p>Most word processor excel at distracting you from writing. The result: <em>you write less</em> (ironic, huh?).</p> -<p>In a word processor, before you can type the first word on a blank screen, you're forced to think about what font family you want, what font size you want, what lines spacing you want and so on. Once you do get going, auto-correct, spelling and grammar suggestions entice you to backtrack and lose your next thought. "Smart" quotes and auto-linking messes with the text as fast as you can enter it. If you paste text, it likely gets added to the document with a different font family, size and even color.</p> -<p><strong>Undo. Undo. Undo!</strong></p> -<p>Let's not even talk about inserting source code. The designers of word processors clearly did not.</p> -<p><strong>Format. Format. Format!</strong></p> -<p>After burning time fighting with its interface, you rightfully conclude that the word processor is trying to <em>sabotage</em> your writing process.</p> -<p><strong>We <em>need</em> an easier way to write!</strong></p> -<p>But how?</p> -</blockquote> -<p>It's kind of ironic to quote AsciiDoc in a document promoting Markdown, but at the very least, we are all against Word. This section is so well written that I can't resist the temptation to quote it out in full. Moreover, I actually typed it in myself to enjoy it to the fullest.</p></li> -<li><p>(<em>05/04/2014</em> update) By the way, there is more to quote against docx (and XML in general), this time from Linus Torvalds, in a <a href="https://plus.google.com/+LinusTorvalds/posts/X2XVf9Q7MfV">Google+ comment</a>:</p> -<blockquote> -<p>no [sic], XML isn't even good for document markup.</p> -<p>Use 'asciidoc' for document markup. Really. It's actually <strong>readable</strong> by humans, and easier to parse and way more flexible than XML.</p> -<p>XML is crap. Really. There are no excuses. XML is nasty to parse for humans, and it's a disaster to parse even for computers. There's just no reason for that horrible crap to exist.</p> -</blockquote> -<p>If you don't believe in me, you certainly believe in Linus don't you, who is much better at this art than you and me. If you don't even believe in Linus, you are not my reader in mind anyway.</p></li> -<li><p>There are infinitely many other reasons to hate Microsoft Office, <strong>which grabs money from the most basic workflow — text editing</strong>. The reasons to hate Microsoft Office occur infinitely often in the decimal expansion of π.</p></li> -</ol> -</blockquote> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>Bold by me.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>That's not even new; PSD viewing and diffing support has been around <a href="https://github.com/blog/1845-psd-viewing-diffing">for a year</a>.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -<li id="fn3"><p>At least compared to Bugzilla, Trac, (the user-facing part of) Jira and FogBugz, SourceForge, Google Code (now closed), BitBucket, Savannah, GitLab, etc.<a class="footnotes-backlink" href="#fnref3">↩︎</a></p></li> -<li id="fn4"><p>Whether a file is plain text or binary is usually easy to check. Just look for the <code>NUL</code> character (<code>\000</code>).<a class="footnotes-backlink" href="#fnref4">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-07-25-dl-cmplntss-web-doesnt-suck.html b/build/blog/2015-07-25-dl-cmplntss-web-doesnt-suck.html deleted file mode 100644 index b63e5921..00000000 --- a/build/blog/2015-07-25-dl-cmplntss-web-doesnt-suck.html +++ /dev/null @@ -1,58 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-07-25T11:31:54-07:00" name="date"/> -<title>dl? cmplnts?'s web doesn't suck</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">dl? cmplnts?'s web doesn't suck</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-07-25T11:31:54-07:00">July 25, 2015</time> -</div> -</header> -<p>I was reading <a href="http://blog.lmorchard.com/2015/07/22/the-verge-web-sucks/">Les Orchard's <em>The Verge's web sucks</em></a> just now, and inspired by his dignostics of his various daily reads, I also ran the performance meter on my very own blog. Fortunately, it doesn't suck<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a>:</p> -<blockquote> -<p>13 requests, 77.88 KB, 0.84s.</p> -</blockquote> -<p>Moreover, apart from a Google Analytics snippet and the occasional embedding with a <code><script></code> tag, this site is entirely static.</p> -<div class="figure"> -<a href="/img/20150725-performance-of-my-blog-requests.png" target="_blank"><img alt="HTTP requests upon visiting https://zmwangx.github.io/ (commit 3af1eaf)." src="/img/20150725-performance-of-my-blog-requests.png"/></a> -<p class="caption">HTTP requests upon visiting <a class="uri" href="https://zmwangx.github.io/">https://zmwangx.github.io/</a> (commit <a href="https://github.com/zmwangx/zmwangx.github.io/tree/3af1eafde5afa9fbb4255135191d6d232cf81cee">3af1eaf</a>).</p> -</div> -<div class="figure"> -<a href="/img/20150725-performance-of-my-blog-breakdown.png" target="_blank"><img alt="The breakdown." src="/img/20150725-performance-of-my-blog-breakdown.png"/></a> -<p class="caption">The breakdown.</p> -</div> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>Diagnostics generated on Firefox Developer Edition 41.0a2.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-07-30-the-sad-state-of-finder-on-el-capitan.html b/build/blog/2015-07-30-the-sad-state-of-finder-on-el-capitan.html deleted file mode 100644 index ff7cf504..00000000 --- a/build/blog/2015-07-30-the-sad-state-of-finder-on-el-capitan.html +++ /dev/null @@ -1,70 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-07-30T23:59:09-07:00" name="date"/> -<title>The sad state of Finder on El Capitan</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">The sad state of Finder on El Capitan</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-07-30T23:59:09-07:00">July 30, 2015</time> -</div> -</header> -<p>I was listening to <a href="http://atp.fm/episodes/128">Accidental Tech Podcast E128</a> today, which discussed the implications of Rootless (i.e. System Integrity Protection) at quite some length.<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> Which stirred up my old worries about the Finder — I was briefly concerned about TotalFinder immediately after Rootless was announced in WWDC, but was quickly reassured and forgot that concern after learning that Homebrew (i.e. <code>/usr/local</code>) isn't affected, which attracted more of my attention.</p> -<p>Unfortunately, the concern is real. TotalFinder is dead on El Capitan: it has been monkey patching Finder.app all along, and that strategy apparently is killed by Rootless. BinaryAge has <a href="http://blog.binaryage.com/el-capitan-update/">announced</a> that TotalFinder won't be ported to El Capitan. It's a done deal.</p> -<p>This is actually not the first time I felt threatened as a TotalFinder fan<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a>. Back in 2013, when Finder tabs was announced for Mavericks, there were <a href="http://discuss.binaryage.com/t/call-for-ideas-what-should-be-the-next-binaryage-product/243">hints from BinaryAge</a> that TotalFinder might be discontinued one day, because apparently Finder tabs is a "serious hit for our [BinaryAge's] business". However, it still survived all the way up till Yosemite. I had the hope that TotalFinder could die a peaceful, glorious death when Apple finally improved the stock Finder to a certain point; I didn't quite expect TotalFinder to die an abrupt death like this.</p> -<p>Now that I think about it, my expectations for Finder isn't very high. Just provide the following and I'll be pretty happy:</p> -<ol style="list-style-type: decimal"> -<li>Auto-resize each column (one can already "Right Size All Columns Individually" through the right-click context menu from the column dividers — is it that hard or unreasonable to make that automatic?);</li> -<li>A way to quickly show and hide hidden files without leaving Finder;</li> -<li>Folders on top (when not sorting by kind) is a nice addition, but not a must;</li> -<li>Chrome-styled tab (instead of Safari-styled) would be a plus.</li> -</ol> -<p>Pretty simple, aren't they (except point 4, which won't happen in stock Finder for the forseeable future)? Especially point 1, which should be desirable for all users, power users and dummies alike. If TotalFinder (and the free alternative XtraFinder, for that matter) can do these just by monkey patching, then Apple with all the control and infinite resources definitely could do these.</p> -<p>Anyway, complaints aren't going to get me anywhere. What's next?</p> -<p>TotalFinder is dead.</p> -<p>XtraFinder<a class="footnoteRef" href="#fn3" id="fnref3"><sup>3</sup></a> similarly monkey patches Finder, so it also won't work with Rootless enabled. The developer has no plan to drop its support though, and I've confirmed that so far the lastest version works well on El Capitan PB3 without Rootless, save for the auto-resize columns feature, which somehow has no effect. Hopefully it will be fixed.</p> -<p>The only other well-known Finder alternative is probably Path Finder, but being a standalone program<a class="footnoteRef" href="#fn4" id="fnref4"><sup>4</sup></a> priced at $39.95, it seems both too full-blown and too expensive. Also, the "Path Finder 7" and "Upgrade — $19.95" on <a href="http://www.cocoatech.com/pathfinder/">the project's home page</a> aren't reassuring; it's probably a $20 per year program.<a class="footnoteRef" href="#fn5" id="fnref5"><sup>5</sup></a> Moreover, even if I end up paying the money, I'm not even sure if it is going to be able to fully replace the experience around Finder. For instance, does the <code>open</code> command open directories in PathFinder? I highly doubt that. Not to mention my AppleScripts surrounding Finder. Heck, I just want a nicer Finder; why am I forced to a full (and probably not fully integrated) replacement.</p> -<p>Besides, Path Finder's roadmap is pretty ridiculous. A guy asked "<a href="http://support.cocoatech.com/discussions/problems/33611-will-path-finder-work-with-el-capitan">Will Path Finder work with El Capitan?</a>" on the support forum, and the reply was</p> -<blockquote> -<p>Unfortunately, I cannot provide you with any information regarding this at the moment. We will let you know once there will be an official release of Mac OS X El Capitan.</p> -</blockquote> -<p>Seriously? That sounds so last decade. Which developer is so tight-lipped today? And who waits for the final OS release only to announce the support schedule? If they can't keep up with the schedule (or haven't evaluated the situation yet), at least they can communicate honestly with customers. This kind of uncertainty will only drive people away. Hard to believe this is the support you get for $40 plus upgrade fees.</p> -<p>I don't know what I'll do in the end. Path Finder is probably not what I'm looking for, but maybe I'll give it a spin if they release an El Capitan ready version in time. Most likely though, I'll stick to stock Finder for a while, and if it turns out too painful, I'll just disable Rootless and sport a copy of XtraFinder. I don't think Rootless will be that useful for me anyway; I still believe it's game over once malware sneaks into my system, whatever privilege it claims. Whether Apple will further lock down the system in a future version is another story.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>It's interesting to listen to John Siracusa's take on the issue, by the way. I completely agree with him.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>Well this time we're not really threatened; TotalFinder is just plain dead. Those "I run Snow Leopard and I won't upgrade" dudes are delusional, as I've pointed out more than once.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -<li id="fn3"><p><a href="http://www.trankynam.com/xtrafinder/">XtraFinder</a> is free, and it comes from the developer of <a href="https://www.trankynam.com/atext/">aText</a>, so I have good feelings about it. However, its annoucements and discussions take place on <a href="https://www.facebook.com/XtraFinder">Facebook</a>, which makes it awfully unprofessional...<a class="footnotes-backlink" href="#fnref3">↩︎</a></p></li> -<li id="fn4"><p>From what I've heard.<a class="footnotes-backlink" href="#fnref4">↩︎</a></p></li> -<li id="fn5"><p>Mind you, TotalFinder charges nothing except the initial $18 investment, despite a lot of rewrite for each major version of OS X.<a class="footnotes-backlink" href="#fnref5">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-08-02-sync-chrome-bookmarks-with-safari-on-os-x.html b/build/blog/2015-08-02-sync-chrome-bookmarks-with-safari-on-os-x.html deleted file mode 100644 index b46f8e78..00000000 --- a/build/blog/2015-08-02-sync-chrome-bookmarks-with-safari-on-os-x.html +++ /dev/null @@ -1,95 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-08-02T22:11:56-07:00" name="date"/> -<title>Sync Chrome bookmarks with Safari on OS X</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Sync Chrome bookmarks with Safari on OS X</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-08-02T22:11:56-07:00">August 2, 2015</time> -</div> -</header> -<p><strong>08/11/2015 Update:</strong> I have taken down the project from GitHub since it's way too flaky. Guess I'll stick with manually clicking around then...</p> -<hr/> -<p><strong>TL;DR</strong>: <a href="https://github.com/zmwangx/safari-sync-chrome-bookmarks">zmwangx/safari-sync-chrome-bookmarks</a> (now defunct; see update above).</p> -<hr/> -<p>I've been reading quite a bit of stuff on my iPhone 6 Plus these days, especially since I got my Apple Watch (not quite sure why these two things are correlated, but they are). I used to read subscribed content in Feedly, but abandoned that a while ago since Feedly does an unbearably bad job at updating my one-subscriber feeds,<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> e.g., Ars Premier feed, GitHub release feeds, etc. Ever since then, I've been rocking a local Leaf engine on my Mac but lost access on my phone,<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a> and had to rely on bookmarks.</p> -<p>However, as a Chrome user on the desktop and only on the desktop (iOS Chrome sucks), I have trouble getting my Chrome bookmarks into mobile Safari. Apple developed an <a href="https://chrome.google.com/webstore/detail/icloud-bookmarks/fkepacicchenbjecpbpbclokcabebhah?hl=en">iCloud Bookmarks</a> extension for Chrome that allegedly syncs your bookmarks to iCloud<a class="footnoteRef" href="#fn3" id="fnref3"><sup>3</sup></a>, but upon installing the extension for Mac Chrome, an error message pops up:</p> -<blockquote> -<p>The extension you are trying to install is designed to run on Windows 7 or 8. If you are using a Mac, your Safari bookmarks will automatically sync with your iPhone, iPad, and Mac when you sign in to iCloud on all your devices.</p> -</blockquote> -<p>The message is pretty clear: you have access to our browser, so you either use our browser or go fuck yourself.</p> -<p>So, what's next? Fortunately, recent versions of Safari (I'm currently running 8.0.7) has an import feature that comes in handy and does a pretty good job: "File -> Import From -> Google Chrome..." which lets you import either history or bookmarks or both. Once they are imported into desktop Safari, iCloud is pretty good at pushing it to mobile. I have no problem importing both, but the idea that I'll have to launch Safari and click click click click just to sync my bookmarks is beyond horrible.</p> -<p>Okay, remember we have another nightmare called AppleScript? And remember we have another nightmare within nightmare called GUI scripting? Yes, here's what we could do:</p> -<pre class="applescript"><code>#!/usr/bin/osascript -tell application "Safari" to activate -delay 1 -tell application "System Events" - tell process "Safari" - tell menu bar 1 - tell menu bar item "File" - tell menu "File" - tell menu item "Import From" - tell menu "Import From" - click menu item "Google Chrome…" - delay 1 - keystroke return - end tell - end tell - end tell - end tell - end tell - end tell -end tell -delay 1 -tell application "Safari" to quit</code></pre> -<p>Holy crap, look at that cascade.<a class="footnoteRef" href="#fn4" id="fnref4"><sup>4</sup></a> Anyway, in principle, this piece of crap works. In reality, well, it <em>sometimes</em> works. Because you know the nightmare called "assistive access", among other unreliabilities of poking around with system events:</p> -<div class="figure"> -<a href="/img/20150802-assistive-access-nightmare.png" target="_blank"><img alt="Familiar?" src="/img/20150802-assistive-access-nightmare.png"/></a> -<p class="caption">Familiar?</p> -</div> -<p>On Yosemite at least, the pane to grant assistive access in System Preferences is three levels deep ("Security & Privacy -> Privacy -> Accessibility"), behind an admin password, and most unfortunately, there's no way to grant access to individual executables through that pane, unless you are explicitly prompted about one, which may not happen when it should.<a class="footnoteRef" href="#fn5" id="fnref5"><sup>5</sup></a> <a class="footnoteRef" href="#fn6" id="fnref6"><sup>6</sup></a> There's nothing I could do apart from granting access to both Terminal.app and iTerm.app and hope for the best. Not so surprisingly, just as demonstrated in my past encounters with GUI scripting, with access granted to the terminals, whether I'll get an "assitive access" error when running the script is completely hit-or-miss. This time it works, the next time it just stalls, and yet another time it emits the error... Oh god.</p> -<p>In order to raise the rate of success, there's one other trick we could try: package the script into an Automator app. This way we can grant access to the standalone app, and that helps a bit. That's what I did in <a href="https://github.com/zmwangx/safari-sync-chrome-bookmarks">zmwangx/safari-sync-chrome-bookmarks</a>. It still occasionally get stuck, probably because I have a freaking slow spinning HDD and Safari would sometimes take forever to launch; but the accessibility problem does seem to go away (provided that you re-grant access every time you make the tiniest modification to the app).</p> -<p>Now I can throw that into my crontab (launching Safari beforehand to avoid freezing up):</p> -<pre class="crontab"><code>55 04 * * * open -g -a safari && sleep 30 && open -g -a safari-sync-chrome-bookmarks</code></pre> -<p>or invoke on demand.</p> -<p>Horrible solution, yes. Anything better? I would love to hear about it, but I highly doubt there's any, unless we directly work with <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code> and <code>~/Library/Safari/Bookmarks.plist</code>. Probably a good problem to tackle though, provided that someone would sit down and understand the formats of the two files.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>I can understand that to reduce server load, they can't refresh the one-subscriber feeds at a rate, say, once per minute, but not being able to manually update, especially when you have a so-called "refresh" feature? Not cool. (What the manual "refresh" seems to do is to fetch Feedly's cached content.) Anyway, it's a freemium service with me running the free tier, so I can't really blame them.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>Which RSS reader/service I'll use next on iOS is a question; I haven't got time to compare the various options yet. So many readers, so many aggregation services!<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -<li id="fn3"><p>And also one for Firefox, it seems<a class="footnotes-backlink" href="#fnref3">↩︎</a></p></li> -<li id="fn4"><p>There's another annoyance: <code>"Google Chrome…"</code> cannot be replaced with <code>"Google Chrome..."</code>, or you won't ever find that menu item.<a class="footnotes-backlink" href="#fnref4">↩︎</a></p></li> -<li id="fn5"><p>There might be a way round through poking with the system accessibility database as root; see <a href="https://github.com/jacobsalmela/tccutil">jacobsalmela/tccutil</a>. However, until I have time to carefully evaluate the code, I'll have to stay with System Preferences.<a class="footnotes-backlink" href="#fnref5">↩︎</a></p></li> -<li id="fn6"><p>Yes, I can understand the security concerns, but having to jump through so many hoops just to get some damned GUI scripting to work is awfully frustrating — and that's when you assume that the damned thing would just work after you jump through the hoops.<a class="footnotes-backlink" href="#fnref6">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-08-05-should-apple-split-up-itunes-on-os-x.html b/build/blog/2015-08-05-should-apple-split-up-itunes-on-os-x.html deleted file mode 100644 index 17a3b7de..00000000 --- a/build/blog/2015-08-05-should-apple-split-up-itunes-on-os-x.html +++ /dev/null @@ -1,63 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-08-05T14:09:51-07:00" name="date"/> -<title>Should Apple split up iTunes on OS X?</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Should Apple split up iTunes on OS X?</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-08-05T14:09:51-07:00">August 5, 2015</time> -</div> -</header> -<p>These days everyone seems to be talking about how complicated iTunes is and how Apple should give it a clean-sheet rewrite. This is not new, but the argument has certainly intensified ever since the introduction of iCloud Photo Library and Apple Music. For one recent example, see <a href="http://www.marco.org/2015/07/26/dont-order-the-fish">Don't order the fish</a> by Marco Arment. I was listening to John Gruber's <a href="https://daringfireball.net/thetalkshow/2015/07/29/ep-127">The Talk Show episode 127</a> earlier today (a little bit late to the game, yeah), and the complexity argument was brought up yet again.</p> -<p>I just can't buy that argument. (Disclaimer: in this post I'm talking about UI/UX, not the backend.) Granted, there are many tabs in iTunes. There's one for music, one for movies, one for TV shows, one for podcasts, one for iOS apps, one for each iOS device currently connected via USB, and so on. You can hide some of them if you don't use them. And for each of these tabs there are probably subtabs, and occasionally a sidebar. This might sound rather intimidating to the faint-hearted, but if you really dive into iTunes, you'll find that 99% of the functionalities you'll ever need to find or organize your stuff are under four clicks away<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a>, and editing metadata (including batch editing) is pretty easy too. All in all, iTunes as it currently stands is both powerful (too many things on the plate, in some people's words) and not badly complicated, in the sense that you can certainly find your way around if you try. Some would argue that some of iTunes' features get shuffled into different places from version to version; yeah that's annoying, but in reality it usually takes less than five minutes to find all I need in a new version.</p> -<p>For people who just buy their content from iTunes Store<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a> and never organize again, there are probably too many unnecessary subtabs and sidebars, but hey, do they need to touch these controls at all? There's a search bar that works reasonably well accross the entire content library<a class="footnoteRef" href="#fn3" id="fnref3"><sup>3</sup></a>. For people who do organize their stuff, or do routinely import music and videos from outside, or do sync their devices via USB, most of those controls are great and necessary.</p> -<p>One disclaimer, by the way: maybe Apple Music made things more confusing. I don't know because I didn't even sign up for the free trial.</p> -<p>Now think about splitting up iTunes. As on iOS, you get a Music app, a Videos app, a Podcast app, an iTunes U app, and a separate iTunes Store app. Probably yet another one for managing your iOS devices, since that belongs to none of the above. So, what do you save by having all those apps? You save one click when you switch focus to another area? Well, not even that at times: now you need to switch apps. Moreover, what if I use several of those routinely (I do)? Do I have to keep all of them on my dock? Even if I don't keep them in Dock, as long as they're open they'll show up anyway, and that would be beyond horrible for people who care about their docks. This is my current dock:</p> -<div class="figure"> -<a href="/img/20150805-my-current-dock.png" target="_blank"><img alt="My current Dock. Note that I have the old red iTunes icon from 12.1, because I really can't stand the white one from 12.2. I know that's the future in El Capitan and iOS 9 (it looks reasonable on iOS 9 by the way, I've been using public betas since day one), but I'll just be stubborn this time, without much real cost." src="/img/20150805-my-current-dock.png"/></a> -<p class="caption">My current Dock. Note that I have the old red iTunes icon from 12.1, because I really can't stand the white one from 12.2. I know that's the future in El Capitan and iOS 9 (it looks reasonable on iOS 9 by the way, I've been using public betas since day one), but I'll just be stubborn this time, without much real cost.</p> -</div> -<p>iTunes, where I playback music and manage my entire content library<a class="footnoteRef" href="#fn4" id="fnref4"><sup>4</sup></a>, nicely takes up only one slot, which is the most reasonable thing to have. On iOS where apps can't have too many tabs or subtabs, it certainly makes sense to split the functionalities; on OS X where you do have space to host those tabs or subtabs, I fail to see how complexity warrants refactoring, especially when refactoring would introduce other problems.<a class="footnoteRef" href="#fn5" id="fnref5"><sup>5</sup></a> <a class="footnoteRef" href="#fn6" id="fnref6"><sup>6</sup></a></p> -<p>Speaking of complexity, iTunes isn't even remotely as complex as, say, Microsoft Word or Adobe Photoshop. Those are of course nightmares to most people, but the point is that iTunes isn't a nightmare — it's pretty manageable, especially to power users and developers, who are the ones complaining most loudly. Also, nothing can beat the complexity of the web browser. We browse all kinds of web pages and use all kinds of web apps everyday, all inside the browser, which can hold arbitrarily many tabs with completely different UIs. We don't complain about the browser. Then why do we complain about iTunes, which is a consistent mix of essential functionalities across different areas of our multimedia experience?</p> -<p>It's true that everyone has their iTunes pet peeves. For instance, I hate the stupid new icon and the useless Apple Music related tabs that I can't turn off in 12.2. The biggest gripe I have with 12.2 is probably the small, hardly noticeable rotating circle at the far upper-right corner of the window,<a class="footnoteRef" href="#fn7" id="fnref7"><sup>7</sup></a> which now hosts the progress indicators of certain IO operations such as downloads and copying files to devices. To me it's a step backwards. Previously downloads was in a separate popup window and file copying had a place in the central area, visible whichever app you are in, but now I have to look for the visual indicator and all of a sudden remember that oh, it has been moved to that remote corner; even then I have to keep focus on iTunes, or the progress indicator dropdown would disappear. It seems all random that the progress of device syncing (and any copy operations initiated as part of the sync) should be front and center, while manually copying files to apps should retreat to the corner. Nevertheless, these minor or not-so-minor annoyances (honestly annoyances exist in almost every app) doesn't justify an iOS-like approach, which has its own drawbacks. I would be really mad if one day I need to run multiple apps just to manage the stuff on my phone.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>Just a rough estimate off the top of my head; please don't challenge me or hold me responsible.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>I'm actually increasingly inclined to this approach. Having lossless music shipped on CDs (sometimes with extra goodies) is nice, but having age-old CDs and goodies lying around, taking up space and gathering dust is less enjoyable.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -<li id="fn3"><p>"Reasonably well" at least on my not-so-large content library.<a class="footnotes-backlink" href="#fnref3">↩︎</a></p></li> -<li id="fn4"><p>I should probably say "my entire content library visible to iOS" instead, since my non-ITMS, DRM-free videos are mostly not in iTunes. It certainly can't keep my Matroska videos anyway.<a class="footnotes-backlink" href="#fnref4">↩︎</a></p></li> -<li id="fn5"><p>For instance, where should music videos live?<a class="footnotes-backlink" href="#fnref5">↩︎</a></p></li> -<li id="fn6"><p>By the way, Microsoft seems to have a split experience in Windows 10. Do people like it? The answer seems to be no.<a class="footnotes-backlink" href="#fnref6">↩︎</a></p></li> -<li id="fn7"><p>Previously what would appear in that corner is the downloads icon, but anyone who has experienced both versions would tell you that the downloads icon is at least much more visible than the new rotating circle. The downloads icon was a dark gray blob, whereas the new thing is a few thin arcs.<a class="footnotes-backlink" href="#fnref7">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-08-05-switching-to-capitalized-commit-messages.html b/build/blog/2015-08-05-switching-to-capitalized-commit-messages.html deleted file mode 100644 index 01e19b48..00000000 --- a/build/blog/2015-08-05-switching-to-capitalized-commit-messages.html +++ /dev/null @@ -1,44 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-08-05T19:38:37-07:00" name="date"/> -<title>Switching to capitalized commit messages</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Switching to capitalized commit messages</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-08-05T19:38:37-07:00">August 5, 2015</time> -</div> -</header> -<p>This post is a note to self.</p> -<p>As a long time git user, I've always used lowercase commit messages (in the subject line). I never quite liked the idea of capitalized commit messages, which are seldom complete sentences (and they are never period-terminated). Similarly, I avoid capilatization like hell in comments, unless when I write complete sentences. By the way, there's a technical advantage of writing lowercase commit messages: I can easily tell my human-made commits from auto commits like merge and revert commits, because they always begin with a capitalized "Merge", "Revert", etc.</p> -<p>However, most of the projects I've contributed to seem to prefer capitalized commit messages, and by following my own habit, quite often I would go through the "oh crap I messed up the contribution guidelines" realization and had to amend my commits after the fact. Also, when I open a single-commit pull request on GitHub, the subject line of the commit message automatically becomes the subject line of the pull request, and I want my pull requests to have capitalized subject lines. Perhaps I come off as self-contradictory here: lowercase commit message, but capitalized PR subject? I don't know. Maybe a PR subject is more like a real "title". Also, I blame the font: lowercase subject lines don't look remotely as good in, say, Helvetica (which GitHub currently uses for PR and commit message subject lines), as in a good fixed width font, which is what I get when I run any <code>git-log</code> variant in a terminal.</p> -<p>Anyway, lowercase commit messages isn't a particularly strong preference of mine, so I'm happy to change my habit from this day onward. Anyone can feel free to tease me if they see me write a lowercase commit message again (unless its in the format <code>component: changes</code>). In light of this, I've already <a href="https://github.com/zmwangx/zmwangx.github.io/commit/297225f2ab8a6db4fe75643f511f52499b052aa7">changed the message format</a> of <code>pyblog</code>'s auto commits, which is how I generate this blog.</p> -<p>P.S. To be fair to me, <em>Pro Git</em>, the official git tutorial, <a href="https://github.com/progit/progit2/blob/6d9867ff2394cb8a08fa3e013b082a7ae547b8af/book/02-git-basics/sections/viewing-history.asc#viewing-the-commit-history">uses lowercase commit messages</a> (I guess that's just the personal preference of Scott Chacon — not mandated by anyone). To be fair to the other side, <a href="https://github.com/git/git/commit/e83c5163316f89bfbde7d9ab23ca2e25604af290"><code>git.git</code> mostly uses capitalized commit messages</a>.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-08-13-other-peoples-___.html b/build/blog/2015-08-13-other-peoples-___.html deleted file mode 100644 index a5f481fa..00000000 --- a/build/blog/2015-08-13-other-peoples-___.html +++ /dev/null @@ -1,40 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-08-13T02:00:24-07:00" name="date"/> -<title>Other people's ___</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Other people's ___</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-08-13T02:00:24-07:00">August 13, 2015</time> -</div> -</header> -<p>Often enough we look at other people's ___ (fill in the blank here) and say wow, but more often than not when we actually get to lay our hands on it, we find it less than impressive or even super annoying, and end up having nothing to say but meh. For Zsh geeks, examples include other people's Zsh prompts<a href="https://github.com/chauncey-garrett/zsh-prompt-garrett" style="text-decoration: none">,</a> zsh-syntax-highlighting, and zsh-autosuggestions.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-08-14-laymen.html b/build/blog/2015-08-14-laymen.html deleted file mode 100644 index 09522513..00000000 --- a/build/blog/2015-08-14-laymen.html +++ /dev/null @@ -1,42 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-08-14T18:32:13-07:00" name="date"/> -<title>Laymen</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Laymen</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-08-14T18:32:13-07:00">August 14, 2015</time> -</div> -</header> -<p>I always cringe when I see laymen discussing physics in comments sections of news websites. A typical situation: one commentator put together a sentence with all physics-sounding (kind of) terms he's ever heard of; the next commentator "agrees" with the previous one, adding something that sounds more reasonable (to folks who've never taken high school physics) but unfortunately violates the first law of thermodynamics; then yet another guy comes along and corrects both of the above in a pedagogic tone, with an argument that violates the second law of thermodymics...</p> -<p>I cringe even more when laymen discuss mathematics, but that's much rarer compared to physics.</p> -<p>Granted, mathematics (theoretical computer science included) and theoretical physics are probably the most abstract knowledge known to human beings, but I'm beginning to wonder if there are other professionals who would also cringe when I myself is discussing something outside my domain of expertise. Or when a better mathematician or physicist listens in on my baby talks with someone on the roughly same level.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-08-20-i-installed-blockparty-and-the-only-thing-i-can-say-is-wow.html b/build/blog/2015-08-20-i-installed-blockparty-and-the-only-thing-i-can-say-is-wow.html deleted file mode 100644 index 15606b67..00000000 --- a/build/blog/2015-08-20-i-installed-blockparty-and-the-only-thing-i-can-say-is-wow.html +++ /dev/null @@ -1,54 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-08-20T20:58:55-07:00" name="date"/> -<title>I installed BlockParty, and the only thing I can say is WOW</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">I installed BlockParty, and the only thing I can say is WOW</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-08-20T20:58:55-07:00">August 20, 2015</time> -</div> -</header> -<p><strong>09/18/2015 update.</strong> Okay, <a href="http://www.marco.org/2015/09/18/just-doesnt-feel-good">Peace has been pulled</a>. Guess I'll keep using it for a while, though.</p> -<hr/> -<p><strong>09/17/2015 update.</strong> I'm now running <a href="http://www.marco.org/2015/09/16/peace-content-blocker">Marco Arment's</a> <a href="https://itunes.apple.com/us/app/peace-block-ads-trackers-powered/id1031035630?mt=8">Peace</a>, powered by Ghostery.</p> -<hr/> -<p>I just let out <a href="/blog/2015-08-20-ios-9-turn-off-wi-fi-assist.html">a load of complaints about iOS 9 beta</a> last night, but apparently forgot about one nice thing: <a href="https://developer.apple.com/videos/wwdc/2015/?id=511">Safari content blocking</a>.</p> -<p>In this day and age, not being iOS/OS X developers ourselves won't stop the rest of us from obtaining ObjC/Swift source code.<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> I simply typed "Safari content blocker" into GitHub's search box, and there it popped, the most starred repo relevant to my search, <a href="https://github.com/krishkumar/BlockParty">krishkumar/BlockParty</a>. Thanks to Apple's new sideloading policy in Xcode 7, I was able to immediately test it out on my phone.</p> -<p>The effect is just amazing. In my few minutes of browsing, I did not seem to encounter a single ad (on various consistently ad-laden news sites). You should definitely give it a shot. What's even more amazing is that BlockParty's <a href="https://github.com/krishkumar/BlockParty/blob/master/RediffBlock/blockerList.json"><code>blockList.json</code></a>, at the time of writing, is only 1578 lines long — a JSON array with 197 objects. <strong>Only 197 rules, blocking 197 domains.</strong> Compare that to <a href="https://easylist-downloads.adblockplus.org/easylist.txt">EasyList</a>, which at the moment is a <strong>48820 line monster</strong>. Of course, EasyList is much more fine-grained (<a href="https://adblockplus.org/blog/content-blocking-in-safari-9-and-ios-9-good-news-or-the-death-knell-of-ad-blocking-on-safari">as are AdBlockPlus's filtering mechanisms</a>); with BlockParty I can actually see some blank boxes that used to host ads. But still, very impressive. Many thanks to <a href="https://github.com/krishkumar">@krishkumar</a> for publishing BlockParty, and to <a href="https://medium.com/@searls/installing-a-content-blocker-on-ios-9-public-beta-a25b2b83848f">Justin Searls</a> for publishing a detailed tutorial.<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a></p> -<p>197 domains made our online lives so miserable. Hmm.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>Actually developing a Safari content blocker extension is as easy as writing a JSON blocker list, but I'm not sure if you need an app with a UI to support the extension. Anyway, there are professional iOS developers out there ready to share the code, so I'll just happily join for a ride.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>Without which I would have been scratching my head, not knowing that I had to go to Settings->General->Profiles to trust my personal profile.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-08-20-ios-9-turn-off-wi-fi-assist.html b/build/blog/2015-08-20-ios-9-turn-off-wi-fi-assist.html deleted file mode 100644 index db9f72cc..00000000 --- a/build/blog/2015-08-20-ios-9-turn-off-wi-fi-assist.html +++ /dev/null @@ -1,63 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-08-20T01:01:57-07:00" name="date"/> -<title>iOS 9: turn off Wi-Fi Assist!</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">iOS 9: turn off Wi-Fi Assist!</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-08-20T01:01:57-07:00">August 20, 2015</time> -</div> -</header> -<p>Seriously. Go to Settings->Cellular, and scroll all the way down to reveal the "Wi-Fi Assist" switch. See screenshot at the end of the post. You'll see a description:</p> -<blockquote> -<p>Automatically use cellular data when Wi-Fi connectivity is poor.</p> -</blockquote> -<p>Switch that off, if you occasionally have shitty Wi-Fi (that kinda works anyway) and at all care about your cellular data usage.</p> -<p>I'll tell my horror story now. Background info: I have unlimited voice and text plus 300 MB data per month, since I've got Wi-Fi almost everywhere I go. Granted, school Wi-Fi (especially dorm) is shitty and drops all the time, but I'm not a streaming-music-on-mobile person, so the Wi-Fi is mostly fine for checking emails, browsing the Web (yes, even <a href="http://murphyapps.co/blog/2015/6/24/an-hour-with-safari-content-blocker-in-ios-9">iMore</a> or <a href="http://blog.lmorchard.com/2015/07/22/the-verge-web-sucks/">The Verge</a> kind of Web), getting push notifications, or even downloading a few podcasts on the go. I usually end up using less than 200 MB of cellular data per month.</p> -<p>However, at the beginning of August (on iOS 9 Public Beta 2 at that time), I somehow managed to burn through 200 MB in four or five days, with consistent daily stats, <em>while I did nothing special, at least not actively</em>. The timing overlaps with when I got my Apple Watch; I don't know if that's a coincidence. Anyway, more than 90% of that usage was under System Services->Documents & Sync, which I could do nothing about. I had to turn off cellular data until almost the end of my billing cycle, when I stumbled upon the "Wi-Fi Assist" setting. Since then, I only used 4.8 MB — with 1.5 MB for System Services — in four days. Hardly a coincidence, I'd say.</p> -<p>In fact, I was pretty delighted when I heard about the ability to auto fallback to LTE when one's on the fringe of Wi-Fi in <a href="https://developer.apple.com/videos/wwdc/2015/?id=719">WWDC '15 Session 719</a> ("Your App and the Next Generation Networks"). However, without another likely suspect, I guess what happened in reality was that when I was sitting in the center of a shitty Wi-Fi, with the system trying to do some background job involving a network connection, it just kept trying to connect via LTE, which probably beat the shitty Wi-Fi consistently. It would be nice if one day our phones would be aware of our data plans (realize that not every one is on a $100/mo 15 GB plan) and throttle its usage wisely.</p> -<p>Anyway, I simply can't understand why the "Wi-Fi Assist" switch, a general system-wide option, appears at the end of Cellular settings, after all the per-app nickel-and-dime settings and statistics. It's nearly impossible to find. Generic settings should be at the top, period.</p> -<p>By the way, I have a lot of gripes about iOS 9 Beta. Maybe I shouldn't whine about beta software — I never used another iOS beta before so maybe they were even worse — but I can't help it because this was supposed to be a stability release. Several things immediately jumped to my mind (all present in the latest Public Beta 3), without even trying:</p> -<ul> -<li><p><a href="/blog/2015-06-26-ios-9-searchable-settings.html">Searchable settings</a> is a scam. Many items can't be found. For instance, good luck searching for "Wi-Fi Assist". I wonder if the search index is hand-crafted. Also, you can't pull down to search from any screen; you have to go back, back, back, back to the main settings screen, and even then it begins with your last search, even if you're done with it. Ewww.</p></li> -<li><p>Scrolling and switching screens feels janky (system-wide) even on iPhone 6 Plus, supposedly a powerhouse.</p></li> -<li><p>The Music app is indeed totally screwed up (this actually dates back to iOS 8.4). It's so much harder than previous versions.</p> -<p>Dude, give me my old UI with selectable categories on the bottom bar if I've turned off Apple Music, okay? Do I have to put up with the Radio and Connect tabs, completely useless for me? Switching categories — by which I mean artists, albums, songs genres, etc. — is infinitely harder now, because you have to scroll all the way up to the top of a category in order to reveal the category selector, which has a dropdown arrow outside but isn't really a dropdown.</p> -<p>And may I go straight to the artwork and playback control screen when I tap to play a song? Damn, when I select and play a song of course I want see the song front and center; don't treat me like an indecisive guy.</p> -<p>And may I kindly request that the artwork does not protrude to the status bar — you do realize some artworks have white or light backgrounds, rendering the status bar unreadable?</p> -<p>Recently I also noticed that all my old iTunes purchases are showing up and screwing my library. There used to be a switch in System Preferences, the right place for this kind of settings on iOS, but it's since be removed in favor of Apple Music stuff (not sure why they are mutually exclusive), and strangely put in the category switcher. Hell, this abomination is even documented in <a href="https://support.apple.com/en-us/HT204951">"Using the new Music app"</a>; here's <a href="https://i.imgur.com/RJKLqPo.jpg">Apple's official screenshot</a> showing off the stupid category switcher. For me without Apple Music, the switch says "Show iTunes Purchases" instead of "Show Music Available Offline". Pretty clear, huh, not bad. But don't bother, it does absolutely nothing for me.</p></li> -</ul> -<p>I could go on and on and on, but I don't want to waste more time on this crap. The gist is that I'm not impressed by iOS 9 at all at the moment (oh, one thing positive: San Francisco is nice). Hopefully the final release would be in much better shape; but I don't see any hope for the Music mess — it's not likely to be cleaned up any time soon. I mourn for the old Music app, which is likely gone forever.</p> -<div class="figure"> -<a href="/img/20150819-ios9-wifi-assist.png" target="_blank"><img alt='The "Wi-Fi Assist" switch, hidden below per-app settings.' src="/img/20150819-ios9-wifi-assist.png"/></a> -<p class="caption">The "Wi-Fi Assist" switch, hidden below per-app settings.</p> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-08-25-automated-os-x-provisioning.html b/build/blog/2015-08-25-automated-os-x-provisioning.html deleted file mode 100644 index cc0881db..00000000 --- a/build/blog/2015-08-25-automated-os-x-provisioning.html +++ /dev/null @@ -1,52 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-08-25T08:16:44-07:00" name="date"/> -<title>Automated OS X provisioning</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Automated OS X provisioning</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-08-25T08:16:44-07:00">August 25, 2015</time> -</div> -</header> -<p>After quite a bit of work, I finally have a decent OS X provisioning system, capable of provisioning a blank OS X install (with Xcode and CLT) for development and everyday life.</p> -<p>Here it is: <a href="https://github.com/zmwangx/dotfiles/blob/master/provision"><code>zmwangx/dotfiles/provision</code></a>. In case the path changes in the future and invalidates the aforementioned URL, <a href="https://github.com/zmwangx/dotfiles/blob/d8e20b731583d69b380d422c8788f61cd4a4e211/provision">here</a> is the archived provisioning script at the current master. Of course the provisioning system is not a single script; it reads and executes modules from a <a href="https://github.com/zmwangx/dotfiles/tree/master/provision.d"><code>provision.d</code></a> directory, which in turn links into other specialized parts of the system.</p> -<p>Selling points:</p> -<ul> -<li><p>Highly modular due to the <code>provision.d</code> structure. New provisioning scripts for specialized tools can be added at any time without complicating the rest of the system.</p></li> -<li><p>Graceful failure and easy error recovery. For most failures, running the provision once more fixes the issues. This is especially helpful when GitHub get DDoS'ed and loads of downloads fail, e.g., <a href="https://web.archive.org/web/20150825150044/https://status.github.com/messages">last night</a>, when I was sleeping with the provisioning system hard at work.</p></li> -<li><p>Very nice, colored console messages. Of course you'd expect that when half of the code is devoted to messaging...</p></li> -</ul> -<p>Thus far tested on OS X 10.10 and 10.11. Works pretty well. Of course OS X provisioning (with so many impossible-to-automate tasks) is still a hell lot harder than Linux provisioning, but hopefully this system will safe me a considerable amount of time and trouble during my at-least-twice-a-year clean OS installation and beta testing in VMs.</p> -<div class="figure"> -<a href="/img/20150825-osx-provisioning-system.png" target="_blank"><img alt="provision at work. Provisioning a blank machine is probably the only time I need Terminal.app." src="/img/20150825-osx-provisioning-system.png"/></a> -<p class="caption"><code>provision</code> at work. Provisioning a blank machine is probably the only time I need Terminal.app.</p> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-08-31-after-all-these-years-10pt-non-anti-aliased-monaco-is-still-the-best.html b/build/blog/2015-08-31-after-all-these-years-10pt-non-anti-aliased-monaco-is-still-the-best.html deleted file mode 100644 index 99766672..00000000 --- a/build/blog/2015-08-31-after-all-these-years-10pt-non-anti-aliased-monaco-is-still-the-best.html +++ /dev/null @@ -1,55 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-08-31T06:31:03+08:00" name="date"/> -<title>After all these years, 10pt non-anti-aliased Monaco is still the best</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">After all these years, 10pt non-anti-aliased Monaco is still the best</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-08-31T06:31:03+08:00">August 31, 2015</time> -</div> -</header> -<p>Ars Technica <a href="http://arstechnica.com/information-technology/2015/08/open-source-typeface-hack-brings-design-to-source-code/">just ran a piece</a> on the open source programming font <a href="https://github.com/chrissimpkins/Hack">Hack</a>. Now I don't really know why this is news-worthy (open source programming fonts aren't a new thing), but I thought I'd give it a try.</p> -<p>The result is unsurprising. I've loved my 10pt non-anti-aliased Monaco for years, beginning with the Pro profile of Terminal.app. In fact, I initially refused to use iTerm2 precisely because I can't reproduce my beloved typeface in it, until I found out the non anti-aliasing trick. This time again, Hack simply can't compete with my favorite font; see the screenshots below. Among other things, it is way too thick for my liking — the same problem that haunts a whole range of programming fonts. Note that Hack is <a href="https://github.com/chrissimpkins/Hack#about">supposed to</a> look good at 8px–12px according to its README, but I tested it at 9pt–12pt in iTerm2 (I know, pt is supposed to be larger than px, but I seriously doubt that anyone would want 8px or 6pt as their daily font size — and for that matter iTerm2 doesn't even allow me to go below 9pt, a pretty reasonable restriction, I'd say).</p> -<p>By the way, it is worth pointing out that the very same Monaco looks horrible at 9pt or 11pt, anti-aliased or not (same goes for 10pt anti-aliased). 10pt non-anti-aliased Monaco is simply a miracle.</p> -<p><strong>09/01/2015 update:</strong> Looks like I was quite confused about pt and px, and they are to be used interchangeably in the current context. I suggest that anyone interested in this subject also read John Gruber's two very informative pieces from 2003, <a href="http://daringfireball.net/2003/03/antialiasing.html"><em>Anti-Aliasing</em></a> and <a href="https://daringfireball.net/2003/03/anti-anti-aliasing"><em>Anti-Anti-Aliasing</em></a>.</p> -<div class="figure"> -<a href="/img/20150831-terminal-app-pro-profile.png" target="_blank"><img alt="Pro profile in Apple's Terminal.app, with 10pt non-anti-aliased Monaco. That says something about the font's quality, especially on a dark background." src="/img/20150831-terminal-app-pro-profile.png"/></a> -<p class="caption">Pro profile in Apple's Terminal.app, with 10pt non-anti-aliased Monaco. That says something about the font's quality, especially on a dark background.</p> -</div> -<div class="figure"> -<a href="/img/20150831-monaco-10pt-non-antialiased.png" target="_blank"><img alt="10pt non-anti-aliased Monaco is life." src="/img/20150831-monaco-10pt-non-antialiased.png"/></a> -<p class="caption">10pt non-anti-aliased Monaco is life.</p> -</div> -<div class="figure"> -<a href="/img/20150831-hack-8,9,10,11pt-antialiased-combined.png" target="_blank"><img alt="Hack, anti-aliased, at 9pt, 10pt, 11pt and 12pt, respectively. Click to enlarge." src="/img/20150831-hack-8,9,10,11pt-antialiased-combined.png"/></a> -<p class="caption">Hack, anti-aliased, at 9pt, 10pt, 11pt and 12pt, respectively. Click to enlarge.</p> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-09-21-zsh-51-and-bracketed-paste.html b/build/blog/2015-09-21-zsh-51-and-bracketed-paste.html deleted file mode 100644 index 52a7b006..00000000 --- a/build/blog/2015-09-21-zsh-51-and-bracketed-paste.html +++ /dev/null @@ -1,79 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-09-21T14:40:36-07:00" name="date"/> -<title>Zsh 5.1 and bracketed paste</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/highlight.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Zsh 5.1 and bracketed paste</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-09-21T14:40:36-07:00">September 21, 2015</time> -</div> -</header> -<p><strong>TL;DR.</strong> Jump to <a href="#code">code</a>.</p> -<hr/> -<p>In short, Zsh 5.1 introduced bracketed paste mode<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> and turned it on by default (as it seems to me<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a>). It is nice in certain ways — I appreciate the change, yet I was bitten nevertheless. In at least two ways:</p> -<ol style="list-style-type: decimal"> -<li><p>Most annoyingly, <code>url-quote-magic</code> doesn't work anymore when pasting URLs, so for example if I paste</p> -<pre><code>https://www.google.com/search?q=zsh</code></pre> -<p>without typing in a single or double quote first, the <code>?</code> and <code>=</code> won't be backslash-quoted by default, which causes an error when passed unnoticed (out of habit).</p></li> -<li><p>The Emacs shell<a class="footnoteRef" href="#fn3" id="fnref3"><sup>3</sup></a> is littered with <code>^[[?2004h</code> and <code>^[[?2004l</code> around every prompt.</p></li> -</ol> -<p>The solution? Zsh now also ships with <a href="https://github.com/zsh-users/zsh/blob/master/Functions/Zle/bracketed-paste-magic"><code>bracketed-paste-magic</code></a> that resolves exactly breakage #1 (and a bit more); to quote comments from the linked source file:</p> -<blockquote> -<p>Starting with zsh-5.1, ZLE began to recognize the "bracketed paste" capability of terminal emulators, that is, the sequences <code>$'\e[200~'</code> to start a paste and <code>$'\e[201~'</code> to indicate the end of the pasted text. Pastes are handled by the bracketed-paste widget and insert literally into the editor buffer rather than being interpreted as keystrokes.</p> -<p>This disables some common usages where the self-insert widget has been replaced in order to accomplish some extra processing. An example is the contributed url-quote-magic widget. The bracketed-paste-magic widget replaces bracketed-paste with a wrapper that re-enables these self-insert actions, and other actions as selected by the zstyles described below.</p> -</blockquote> -<p>And to resolve breakage #2, just disable bracketed paste altogether for dumb terms.</p> -<p id="code"> -Putting it together: -</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh"><span class="co"># turn off ZLE bracketed paste in dumb term</span> -<span class="co"># otherwise turn on ZLE bracketed-paste-magic</span> -<span class="kw">if [[</span> <span class="ot">$TERM</span> <span class="ot">==</span> dumb<span class="kw"> ]]</span>; <span class="kw">then</span> - <span class="kw">unset</span> zle_bracketed_paste -<span class="kw">else</span> - <span class="kw">autoload</span> -Uz bracketed-paste-magic - <span class="kw">zle</span> -N bracketed-paste bracketed-paste-magic -<span class="kw">fi</span></code></pre></div> -<hr/> -<p><span id="update"><strong>09/22/2015 update.</strong></span> I only read <code>NEWS</code> and not <code>README</code>, so I missed out on a very clear announcement of the <a href="https://github.com/zsh-users/zsh/blob/68405f31a043bdd5bf338eb06688ed3e1f740937/README#L38-L45">bracketed paste incompatibitilies (between 5.0.8 and 5.1)</a>:</p> -<blockquote> -<p>The default behaviour when text is pasted into an X Windows terminal has changed significantly (unless you are using a very old terminal emulator that doesn't support this mode). Now, the new "bracketed paste mode" treats all the pasted text as literal characters. This means, in particular, that a newline is simply inserted as a visible newline; you need to hit Return on the keyboard to execute the pasted text in one go. See the description of <code>zle_bracketed_paste</code> in the <code>zshparams</code> manual for more. "<code>unset zle_bracketed_paste</code>" restores the previous behaviour.</p> -</blockquote> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>Bracketed paste mode is a safeguard against inadvertent interpretation of pasted text, e.g., newline being treated at <code>accept-line</code> in Zsh. You may read more about it <a href="https://cirw.in/blog/bracketed-paste">in this blog post</a>, which is somewhat outdated yet still informational.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>Indeed it is. See <a href="#update">update</a> with more accurate info from official source.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -<li id="fn3"><p>I seldom use this dumb (literally) thing, but when I do I expect it to work ungarbled, naturally.<a class="footnotes-backlink" href="#fnref3">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-09-24-apple-watch-digital-crown-tightness-issue.html b/build/blog/2015-09-24-apple-watch-digital-crown-tightness-issue.html deleted file mode 100644 index 623bb917..00000000 --- a/build/blog/2015-09-24-apple-watch-digital-crown-tightness-issue.html +++ /dev/null @@ -1,47 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-09-24T10:55:38-07:00" name="date"/> -<title>Apple Watch: Digital Crown tightness issue</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Apple Watch: Digital Crown tightness issue</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-09-24T10:55:38-07:00">September 24, 2015</time> -</div> -</header> -<p>Quick tip: if the Digital Crown on your Apple Watch <em>all of a sudden</em><a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> feels too tight and doesn't turn smoothly, probably it was somehow over-turned (and probably because you played with watchOS 2 Time Travel, as I did). I don't know how that happened because it's clearly not supposed to happen, but turning it in the easy-to-turn direction for a few rounds fixed the tightness issue for me.</p> -<p>There's also an <a href="https://support.apple.com/en-us/HT204639">Apple Support document</a> on troubleshooting and cleaning the Digital Crown, if the above doesn't help.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>Especially after upgrading to watchOS 2. Why in the hell could upgrading the software screw up the hardware? You'll see a possible cause if you read on.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-09-25-removing-google-analytics-from-this-blog.html b/build/blog/2015-09-25-removing-google-analytics-from-this-blog.html deleted file mode 100644 index 95641010..00000000 --- a/build/blog/2015-09-25-removing-google-analytics-from-this-blog.html +++ /dev/null @@ -1,49 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-09-25T12:30:25-07:00" name="date"/> -<title>Removing Google Analytics from this blog</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Removing Google Analytics from this blog</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-09-25T12:30:25-07:00">September 25, 2015</time> -</div> -</header> -<p>There was a lengthy discussion about Peace and ad-blocking in <a href="http://atp.fm/episodes/136">Accidental Tech Podcast Episode 136</a>. There were many lessons to learn from the story; as a side effect, it also made me reconsider Google Analytics on this blog.</p> -<p>I've been a user of ad-blocking for years and have little to no moral burden.<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a><a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a> I do hate being tracked online, even by Google (to whom I entrust so much of my personal information), although it's certainly better (I believe) than the host of shadier ad networks out there. Given this, why should I force something even I hate down my visitors' throats? Google Analytics is nice at telling me how many page views I got and where they came from, and I don't earn any money from it so I shouldn't feel guilty, but (1) it does install a tracker, and (2) I care very little about traffic anyway.</p> -<p>At this point the decision is pretty clear. I'm simply removing Google Analytics from this blog. This makes the blog entirely cookie-free and JS-free (except for the very occasional JS embed).</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>I do try to support websites I frequent, e.g., through <a href="https://arstechnica.com/subscriptions/">Ars Premier</a>.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>Although it's easy to be a user of ad-blocking, I fully understand the moral (or even legal) burden of being the developer of an ad-blocker, let alone being the "face" of the ad-blocking industry; therefore, I understand and respect Marco's decision of pulling Peace.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-10-01-auto-hidden-menu-bar-dock-maximized-window-is-the-new-full-screen-mode.html b/build/blog/2015-10-01-auto-hidden-menu-bar-dock-maximized-window-is-the-new-full-screen-mode.html deleted file mode 100644 index f50f4a14..00000000 --- a/build/blog/2015-10-01-auto-hidden-menu-bar-dock-maximized-window-is-the-new-full-screen-mode.html +++ /dev/null @@ -1,47 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-10-01T15:48:59-07:00" name="date"/> -<title>Auto hidden menu bar & dock + maximized window is the new full screen mode</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Auto hidden menu bar & dock + maximized window is the new full screen mode</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-10-01T15:48:59-07:00">October 1, 2015</time> -</div> -</header> -<p>One nice feature of OS X El Capitan is that the menu bar can be auto hidden. Combined an auto hidden dock, we can now emulate the full screen experience with a maximized window while still enjoying overlayed windows, e.g., transparent terminal windows or "Picture in Picture" style small floating player. To see how closely a full screen experience is emulated this way, see the side-by-side screenshots below.</p> -<div class="figure"> -<a href="/img/20151001-maximized-window-vs-full-screen.png" target="_blank"><img alt="Maximized and full screen windows of Google Chrome side by side. Can you tell any difference apart from the color of the title bar and a bit of black bottom margin on the left?" src="/img/20151001-maximized-window-vs-full-screen.png"/></a> -<p class="caption">Maximized and full screen windows of Google Chrome side by side. Can you tell any difference apart from the color of the title bar and a bit of black bottom margin on the left?</p> -</div> -<p>I've always liked maximized windows much better than full screen windows. (Maybe this is part of the legacy from my early Windows days? Anyway, to Microsoft's credit, Windows <em>is</em> better in certain aspects, e.g., File Explorer. You see, I'm still fighting Finder to this day. Window maximization is also something that Windows does better, although I do like OS X's universal menu bar and hate the Windows menus that could appear in all kinds of surprising places.) There are legit reasons to perfer maximized windows over full screen. One obvious advantage is persistent window stacking, which has already been mentioned. Moreover, sometimes I need to temporarily bring up another app for a quick task, which is to say I need something like iOS 9's Slide Over — but on the desktop slide-over already comes for free with window overlay. In full screen mode, however, the second app will be opened in another desktop space with lavish animation of switching, and when I'm done I need to swipe back to the original space, again with lavish animation, instead of just ⌘H to hide. Do it several times in quick succession and it's a pretty nauseous experience (of course I'm exaggerating, but it's certainly neither comfortable nor productive).</p> -<p>In short, maximized windows have always been great, and now they are getting even better.</p> -<p>P.S. I personally don't have many informational moving parts in the menu bar. There's date time down to seconds, but I have an Apple Watch on my wrist, and I don't mind raising my wrist for a few seconds when I need the time. There's a battery icon which I certainly won't look at constantly — my MBP is plugged in most of the time. There's a Dropbox icon that would animate when it is syncing, which I don't care. Other than that, all icons are still. Therefore, I can totally do away with the menu bar until I really need it.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-10-01-upgrading-to-el-capitan.html b/build/blog/2015-10-01-upgrading-to-el-capitan.html deleted file mode 100644 index 15168bc3..00000000 --- a/build/blog/2015-10-01-upgrading-to-el-capitan.html +++ /dev/null @@ -1,66 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-10-01T11:46:44-07:00" name="date"/> -<title>Upgrading to El Capitan</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Upgrading to El Capitan</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-10-01T11:46:44-07:00">October 1, 2015</time> -</div> -</header> -<p>I upgraded to El Capitan last night, and the experience is pretty painless. To be accurate, I'm not really upgrading in place — I always perform a clean install for each major OS upgrade to avoid subtle breakage later on. Therefore, what I did instead was to <code>rsync</code> out all my valuable data and state information<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> to an external drive, wipe the internal drive clean, install new OS from scratch, then <code>rsync</code> everything back in. <code>rsync</code> is really good at this stuff (I affectionately alias <code>rsync -avP</code> to <code>r</code> during transfers in and out), and it is simply amazing at dropping the right stuff at the right place, including data deep down <code>~/Library/Containers</code>, without interfering with the existing structures<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a>. With data and state info ready, reinstalling programs is also easy, thanks to my recently finished <a href="/blog/2015-08-25-automated-os-x-provisioning.html">automated provisioning system</a>. It was the first time I used it outside a VM to provision an OS from almost scratch, and I'm really happy with it.</p> -<p>Thus far, most of my programs and applications seem to work just fine on El Capitan. I needed to <code>brew reinstall pyenv --HEAD</code> because an OpenSSL fix for El Capitan hasn't made into a release yet. Some of XtraFinder's features<a class="footnoteRef" href="#fn3" id="fnref3"><sup>3</sup></a>, including my most needed auto resizing columns, don't seem to work on El Capitan yet, and I'll have to contact the developer soon. The only distratrous incompatibility I've seen lies with Mathematica 9; <code>codesign -vvvv Mathematica.app</code> on the v9.0.1 app bundle says <code>resource envelope is obsolete (version 1 signature)</code>, and OS X downright refused to open the app, offering me no option other than trashing the app, even when I temporarily set Gatekeeper to "Any". Anyway, I quickly paid to upgrade to v10.2.0 (cost of free OS upgrade, geez), and it ran happily afterwards. Those were basically all I had to deal with. I haven't set up my mail accounts<a class="footnoteRef" href="#fn4" id="fnref4"><sup>4</sup></a> and printer yet, but hopefully they will work, and just hopefully Apple Mail finally got it right this time™ and won't ask me to reauthenticate with Gmail all the time.</p> -<p>Overall it was pretty good experience. Nevertheless, I was caught by surprise at least twice, due to subtle user-facing changes in the OS. Actually these surprises motivated me to write this post.</p> -<p>First, <u>the OS seems to default to using the iCloud password (i.e., the Apple ID password) as the local account password now.</u> Maybe I missed a checkbox during setup (unlikely), and maybe it was nothing new (I don't think so), but I only realized this when I needed to <code>sudo</code> on the new OS for the first time. I typed my usual local password thrice, no luck. Did I accidentally gave my 1Password master password? Thrice, no luck. Did I accidentally used Vagrant's default password (i.e., <code>vagrant</code>, however unlikely)? This one is short enough and I didn't need to type it thrice to realize it was wrong — I knew that all along anyway. Did I... No, I couldn't have used anything else (literally ten minutes ago) without remembering it. I was completely horror-struck at that point, but speaking of remembering, I didn't even remember giving a password hint! So could it be... Yes, I typed in my 32 character long iCloud password, and this time it was right. I quickly realized after the fact that this setting could be toggled in the standard System Preferences -> Users & Groups -> Change Password... (see screenshot below), so if you are in this situation, don't panic. I don't like this move though. Hopefully Apple won't degrade to Microsoft's level at some future point, where you either sign in with a Microsoft account (and have to type your Microsoft password to log in) or miss out on cloud features with a local account.</p> -<div class="figure"> -<a href="/img/20151001-osx-el-capitan-icloud-password-to-log-in.png" target="_blank"><img alt="Screenshot taken after I've changed to a local password. After initial setup, it would be the reverse." src="/img/20151001-osx-el-capitan-icloud-password-to-log-in.png"/></a> -<p class="caption">Screenshot taken after I've changed to a local password. After initial setup, it would be the reverse.</p> -</div> -<p>Secondly, <u>three finger drag, a multitouch gesture that I use all the time to move windows on screen, is now mysteriously gone from System Preferences -> Trackpad</u> (it used to be in "Touch & Click"):</p> -<div class="figure"> -<a href="/img/20151001-osx-el-capitan-wheres-my-three-finger-drag.png" target="_blank"><img alt="Where's my beloved three finger drag? By the way, since it is shown in this screenshot, I'll officially declare here that I'm a tap-to-click wizard." src="/img/20151001-osx-el-capitan-wheres-my-three-finger-drag.png"/></a> -<p class="caption">Where's my beloved three finger drag? By the way, since it is shown in this screenshot, I'll officially declare here that I'm a tap-to-click wizard.</p> -</div> -<p>Maybe Apple found it somewhat confusing with the three finger tap/click, which is clearly a different gesture. I found the solution in an Apple Support document, <a href="https://support.apple.com/en-us/HT204609">Turn on "three finger drag" for your Force Touch trackpad</a>, while my trackpad is clearly not Force Touch (the document was written for Yosemite, so clearly the reorganized settings started out on the MacBook One and newer Retina MacBook Pros in Yosemite and spreaded to all Macs in El Capitan). Anyway, the gesture could be turned on in System Preferences -> Accessibility -> Mouse & Trackpad Options... -> Enable dragging. That was godawful, no one could possibly find it, but hopefully it's hidden there because of the confusion rather than Apple intentionally phasing it out.</p> -<div class="figure"> -<a href="/img/20151001-osx-el-capitan-three-finger-drag-there-it-is.png" target="_blank"><img alt="Oh, there it is!" src="/img/20151001-osx-el-capitan-three-finger-drag-there-it-is.png"/></a> -<p class="caption">Oh, there it is!</p> -</div> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>State information includes <code>~/.config</code> and <code>~/.local</code>, Google Chrome and Firefox profiles, Messages archive, Mathematica customizations, Unclutter notes, VMware Fusion inventory, various important plists, and so on and so forth.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>Unless you are stupid enough to specify the <code>--delete</code> flag when you transfer in.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -<li id="fn3"><p>As mentioned in <a href="/blog/2015-07-30-the-sad-state-of-finder-on-el-capitan.html">The sad state of Finder on El Capitan</a>, I've disabled SIP and am running XtraFinder. I simply can't live with the stock Finder, that is, without code injection.<a class="footnotes-backlink" href="#fnref3">↩︎</a></p></li> -<li id="fn4"><p>Setting up mail accounts is the most painful thing in the world, especially if you have a dozen of them for different tasks.<a class="footnotes-backlink" href="#fnref4">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-10-03-we-need-an-os-x-security-white-paper.html b/build/blog/2015-10-03-we-need-an-os-x-security-white-paper.html deleted file mode 100644 index f97c795d..00000000 --- a/build/blog/2015-10-03-we-need-an-os-x-security-white-paper.html +++ /dev/null @@ -1,54 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-10-03T03:34:24-07:00" name="date"/> -<title>We need an OS X security white paper</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">We need an OS X security white paper</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-10-03T03:34:24-07:00">October 3, 2015</time> -</div> -</header> -<p>Apple has been offering an excellent <a href="https://www.apple.com/privacy/docs/iOS_Security_Guide.pdf">iOS Security White Paper</a> since at least 2012, and it's very informative. I highly encourage everyone to read it. It even explains some annoyances of iOS; for instance, <a href="http://www.relay.fm/upgrade/56">this week's Upgrade episode</a> discussed, <a href="https://daringfireball.net/linked/2015/10/01/upgrade-56">in Gruber's words</a>, "the lousy, painstaking, and at times downright confusing experience of migrating to a new iOS device", and once you read the white paper you'll realize that many things just can't be migrated due to iOS's hardware security model — basically, certain classes of data are encrypted with crypto keys baked into the silicon (see the section "Hardware security features"). I'm not saying the migration experience should be this painful (I would love to see it fixed or improved), but at least there's an explanation.<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a></p> -<p>But I digress. This post is about OS X. I've been hunting for an OS X equivalent for a while now, but I don't think it exists. And recently people are talking about Apple's <a href="https://www.apple.com/privacy/">updated Privacy website</a><a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a>, so I went there with a glimmer of hope. End result: no luck. In fact, Apple links to its iOS Security White Paper at the bottom of "<a href="https://www.apple.com/privacy/approach-to-privacy">Our Approach to Privacy</a>":</p> -<div class="figure"> -<a href="/img/20151003-ios-security-white-paper-but-no-osx.png" target="_blank"><img alt="iOS Security White Paper linked, but no OS X." src="/img/20151003-ios-security-white-paper-but-no-osx.png"/></a> -<p class="caption">iOS Security White Paper linked, but no OS X.</p> -</div> -<p>But there's little to no mention of OS X (the words "Mac" and "OS X" each appears only once on the page). This is not surprising; OS X as the second class citizen is nothing new, and iPhones and Apple Watches are arguably more intimate, and hence more private devices — at least for most people. It is somewhat disappointing though.</p> -<p>I forgot to mention why I would like to see an OS X security white paper. The reason is simple: a lot of security features are under-explained. For instance, I might want to learn more about FileVault: why am I given the choice of decrypting my drive with iCloud — I believe it's not the case on iOS? How does iCloud handle my disk encryption key, if I allow it access (I don't)? Or I might want to learn more about System Integrity Protection: does it auto revert (or repair, in their eyes) some permissions (e.g., that of <code>/usr/local</code>), as I heard people talking about? Or maybe more about code signing and the inner workings of Gatekeeper: there's <a href="http://arstechnica.com/security/2015/09/drop-dead-simple-exploit-completely-bypasses-macs-malware-gatekeeper/">recent news</a> of Gatekeeper workarounds. I guess some of these stuff can be found in Apple's support documents or developer documentation if you look hard enough, but it would be nice if the major security features and their implementations are presented coherently in a single document. Maybe the OS X security model is too complex and diverse to fit into a single document? I don't know. Anyway, I'll keep waiting.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>Loss of certain classes of protected data (due to hardward crypto keys) during migration should in principle only apply to migration by "restoration". What about providing a direct phone-to-phone migration, where data could be decrypted and transferred on the fly? But that would at least require a lightning male to lightning male cable (or you would have to entrust your most sensitive data, which shouldn't even leave the phone under normal conditions, to your Wi-Fi, something Apple probably wouldn't do), and having to use a different, and actually unheard-of cable isn't very realistic, so it won't be happening any time soon.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>I haven't read through everything, but the idea of a <a href="https://www.apple.com/privacy/privacy-policy/">non-law-practicing-human readable privacy policy</a> is great.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-10-10-printing-long-80-character-per-line-plain-text-document-in-two-columns.html b/build/blog/2015-10-10-printing-long-80-character-per-line-plain-text-document-in-two-columns.html deleted file mode 100644 index 7e1752bd..00000000 --- a/build/blog/2015-10-10-printing-long-80-character-per-line-plain-text-document-in-two-columns.html +++ /dev/null @@ -1,56 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-10-10T22:35:15-07:00" name="date"/> -<title>Printing long, 80-character-per-line plain text document in two columns</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/highlight.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Printing long, 80-character-per-line plain text document in two columns</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-10-10T22:35:15-07:00">October 10, 2015</time> -</div> -</header> -<p><strong>TL; DR</strong>. Jump to <a href="#code">code</a>.</p> -<hr/> -<p>Printing is hard. Everyone who has ever tried to set up a printer (especially a multifunction unit) will probably agree with me. There are also a million ways to be sabotaged by your printer, e.g., connection failure (over Wi-Fi), toner running low, manual duplex eating two sheets at once when printing the second side. (Do you believe I encountered all three tonight?) Anyway, let's just assume that you have a perfectly connected, perfectly functional printer, and talk about something even harder.</p> -<p>We nerds read 80-character-per-line (or 72, but it's safer to assume longer) plain text documents all the time, or at least occasionally if we exclude source code. A plain text document is extremely versatile; it looks awesome in a text editor or in a browser window — with monospace typeface of your choice and infinite scrolling or arbitrary pagination. However, the problem is, sometimes we want to put things into print for easier reference, and we do <em>not</em> have infinite scrolling or arbitrary pagination in print. We want to divide things up into pieces that fit nicely onto 8.5'' by 11'' sheets, without ruining the original formatting of the plain text document. Therefore, some program has to decide the page layout and translate the plain text document into something a printer understands, e.g., PostScript. But since plain text is so versatile, there are a million ways to lay it out on paper.</p> -<p>You would assume that this is a solved problem, since the digital publishing industry has been around for 40 years; and you would assume that this should be easy on a Mac because it is a great platform for "creative professionals". And indeed it's not hard if you just want to print one column of 80 characters. You can even do that in TextEdit, where you pick a plain text font and font size so that lines don't wrap, and there you go. If you are using a more capable GUI text editor like TextWrangler (I use Emacs all the time but I don't know about printing from Emacs), you are given more customization options like header and line numbers. However, 80 character lines look awful on a 8.5'' wide page. Characters are HUGE (to me anyway). Note that monospaced fonts usually look better when they are smaller (I'm a <a href="/blog/2015-08-31-after-all-these-years-10pt-non-anti-aliased-monaco-is-still-the-best.html">10pt bitmap Monaco fan</a>), and do keep in mind that we are usually farther away from a computer screen than a piece of paper held in hand, so even "10pt" could look pretty big in print. Moreover, you most likely get the outlined version of your font in print rather than the bitmap version, which depending on your font of choice might not be a good thing, and the difference is amplified when characters are big. And above all, you waste a lot of paper this way, and create stapling problems for yourself when the document is long. In short, I don't find it a good solution.</p> -<p>It would be much nicer if we could print in two columns. The characters will be pretty small so it's probably not very good for older people (or they could try two columns in landscape), but I'm still pretty young and have fairly good eyesight, so I like this idea. But turns out this is nontrivial with existing GUI programs, at least the ones that I know of. You could emulate the two-column layout by having four pages on one sheet, but it's really awkward because you get a page divider in each single column (waste of space), and page numbering would be all messed up. Other than that there's little you could do. I guess there's just not enough market for this particular need. Luckily we have a large selection of modular command line utilities that we can stitch together for great results. I'll cut the bullshit here and just show you the <span id="code">code</span> (for US letter):</p> -<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">curl</span> https://www.gnu.org/software/bash/manual/bash.txt \ - <span class="kw">|</span> <span class="fu">pr</span> --columns=2 --width=168 --length=120 --form-feed --date-format=%Y-%m-%d --header=<span class="st">"Bash Reference Manual"</span> - \ - <span class="kw">|</span> <span class="ex">enscript</span> --media=Letter --header= --font=Courier5.5 --margins=18:18:0:18 --output - \ - <span class="kw">|</span> <span class="fu">ps2pdf</span> - bash-print.pdf</code></pre></div> -<p>Here, as an example, I'm printing the ASCII text version of the Bash Reference Manual. <code>pr</code> ships with <code>coreutils</code> (OS X also ships with the BSD version of <code>pr</code>, but geez, I'm a <code>coreutils</code> fan), so if you just <code>brew install coreutils</code> then you should use <code>gpr</code> instead. <code>enscript</code> here is <a href="https://www.gnu.org/software/enscript/">GNU Enscript</a>, which could be installed with <code>brew install enscript</code> (credit to <a href="https://askubuntu.com/questions/27097/">Ask Ubuntu</a> for pointing me to this utility). <code>ps2pdf</code> ships with GhostScript, so you could do <code>brew install gs</code>, but you should already have it if you've got the MacTeX or TeXLive distribution installed. The options I'm using should be pretty self-explanatory and tweakable, but in case you don't understand something, just RTFM (that way you could also find more options). Anyway, a page of <code>bash-print.pdf</code> from the above looks like this (this one happen to be a 72-char-per-line document, whereas my numbers are tailored for 80; the image is at 300 ppi):</p> -<div class="figure"> -<a href="/img/20151010-bash-print-sample-page.png" target="_blank"><img alt="Sample page from bash-print.pdf generated above. I drew a black, one-pixel border so you could tell the page from the background." src="/img/20151010-bash-print-sample-page.png"/></a> -<p class="caption">Sample page from <code>bash-print.pdf</code> generated above. I drew a black, one-pixel border so you could tell the page from the background.</p> -</div> -<p>P.S. Preview.app on El Capitan just caught me by surprise. If memory serves, exporting PDF to PNG in Preview.app used to produce only one image for the current page, but now apparently you get a single, gigantic <a href="https://en.wikipedia.org/wiki/APNG">APNG</a> with each page in a frame. It's not very useful at 10 fps, though. Also, exporting to JPEG doesn't give you an MJPEG.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-10-12-the-importance-of-dated-detailed-release-notes.html b/build/blog/2015-10-12-the-importance-of-dated-detailed-release-notes.html deleted file mode 100644 index 9dbfc28c..00000000 --- a/build/blog/2015-10-12-the-importance-of-dated-detailed-release-notes.html +++ /dev/null @@ -1,57 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-10-12T14:29:42-07:00" name="date"/> -<title>The importance of dated, detailed release notes</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">The importance of dated, detailed release notes</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-10-12T14:29:42-07:00">October 12, 2015</time> -</div> -</header> -<p>I can't stress how much I value release notes, especially for closed source, commercial software. None of us want to invest on a piece of abandonware (unless it is ageless, which is quite unlikely for anything with a GUI), or a piece of software that is not completely abandoned, but takes a full year to adapt to the latest OS, campatibility-wise or UI-wise; and release notes, especially with dates, serve as almost the single metric for gauging developer commitment. In fact, whenever I try to learn about a piece of software that I heard about, one of the first things I do, usually after browsing through features and screenshots and before I even download the software to try out, is to look for its release notes and skim through it if available, and the outcome largely determines whether I'll even bother to download the installer.<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> A prominent, dedicated page with dated, detailed release notes immediately leaves a good impression on me.</p> -<p>Unfortunately, many developers or publishers don't value release notes as much as I do. Several problems, in ascending order of seriousness:</p> -<ul> -<li><p>Most release notes are not linked to from the home page or at least the download page, which kind of makes sense when the audience is generally non-technical, but there's little excuse when the software's targeted audience are pro-level or power users. This is not a big problem now because Google is very good at turning up release notes as long as they exist.</p></li> -<li><p>Quite some release notes are not dated, which I can't understand — it's so easy to date each entry, and it adds so much context, especially for gauging commitment (I guess developers who are less commited might not want to insert dates precisely for this reason).</p></li> -<li><p>For some software, releases notes are downright nonexistent, at least not on the web. Interestingly, occasionally they are available from an in-app menu or distributed document; the publishers just don't bother to put it on a web page. Not surprisingly, I might as well not bother to download this kind of software.<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a></p></li> -</ul> -<p>If I were ever to publish closed source software, I'll definitely have dated, detailed release notes, linked to from the home page.</p> -<hr/> -<p>P.S. Speaking of release notes, it's hard not to complain about MAS, as if there are not enough complaints about this horrible platform. You can only view the most recent release with its release notes (and some publishers stack "bug fixes" notes of minor/patch releases on top of the real notes of the last major release, making it ever more confusing), whereas in the iOS App Store you have the "Version History" page that shows you a dated list of releases with release notes — what I would expect from everywhere. Basically, Apple has all this data and they can show it to you in a satisfactory way it they want to, but they blew it by not bothering to implement it. Note that I'm much more likely to care about the release notes of an OS X application than an iOS app, and I daresay most power users will agree with me.</p> -<p>Of course there are much more serious problems with MAS like the lack of trials, so the release notes problem is nothing but an insult over injury. In short, MAS is not a good distribution channel; it's only a lazy one, a compromise for small publishers.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>Nowadays, with homebrew-cask, I'm much more likely to give things a spin, but still, I take an especially defensive stance against anything that doesn't have release notes.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>Yes, I won't deny that downloaded some of them nevertheless — that's how I found out.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-10-14-follow-up-the-sad-state-of-finder-on-el-capitan.html b/build/blog/2015-10-14-follow-up-the-sad-state-of-finder-on-el-capitan.html deleted file mode 100644 index 811f8c2d..00000000 --- a/build/blog/2015-10-14-follow-up-the-sad-state-of-finder-on-el-capitan.html +++ /dev/null @@ -1,70 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-10-14T12:30:32-07:00" name="date"/> -<title>Follow-up: The sad state of Finder on El Capitan</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Follow-up: The sad state of Finder on El Capitan</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-10-14T12:30:32-07:00">October 14, 2015</time> -</div> -</header> -<p><strong>10/14/2015 update</strong> (updated even before I published the article). Just as I was finishing this post, an update to TotalFinder came. <a href="http://totalfinder.binaryage.com/beta-changes">1.7.8</a>. And holy cow, it fixed automatic column resizing! The fix isn't perfect — there's actually a visible delay before resizing, but I'm happy again. Long live TotalFinder!</p> -<hr/> -<p>As expected, it's hard to get Finder to work the way I want it to on El Capitan. The unexpected part is that even after disabling the Debugging Restrictions part of SIP (<code>csrutil enable --without debug</code>), XtraFinder and TotalFinder<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> both can't auto resize columns. Seems that a hole they are both utilizing has been closed. Just like <code>QLEnableTextSelection</code> in <code>com.apple.finder</code>, I guess. Apple gives, Apple takes. XtraFinder has additional problems like folder-on-top not working, window config occasionally forgotten, and the long-standing issue of shitty Chrome-style tab implementation (basically stacking a separate layer on top of each window) that shows a visible white divider, so I'm running TotalFinder right now, not sure about whether it would be abandoned completely next year. Anyway, even after running TotalFinder, it's still that damn old stupid Finder, the columns of which I have to manually resize all the time; just a little bit nicer.</p> -<p>So I went out to look for full Finder replacements. I tried everything listed in the <a href="http://discuss.binaryage.com/t/totalfinder-alternatives/4124">TotalFinder alternatives</a> post on TotalFinder forums. None worked for me. Here's a very brief (batch) review.</p> -<ul> -<li><p><a href="http://likemac.ru/english/">Disk Order</a>, <a href="http://mac.eltima.com/file-manager.html">Commander </a><a href="http://mac.eltima.com/totalfinder-promo.html">One</a>, <a href="http://www.devstorm-apps.com/dc/">DCommander</a>, and <a href="http://crax.soft4u2.com/">CRAX Commander</a>: No column view. All of them are dual-pane though. What's the advantage of being dual-pane? I can't fathom. Easier to copy/cut and paste? What a joke — how often do you do that to justify having two panes in your face at all times? Might as well spend the time to do a column view. Column view enables fast navigation and provides a full picture of a directory tree, which is one of the two reasons I use Finder (i.e., a file manager), the other being Quick Look. If I just want to stay in a single directory, and painstakingly navigate in and out, I'll just do everything in the terminal, thank you. By the way, Command One and DCommander are suprisingly similar, both appearance-wise and functionality-wise. Not sure if one rips off the other (looks like DCommander is older). Also, why do most of them call themselves commanders? Another thing that I can't fathom.<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a></p></li> -<li><p><a href="http://www.binarynights.com/forklift/">ForkLift</a>: Again, dual-pane, and doesn't seem to offer a single-pane mode, but you can drag the pane divider all the way to the right to hide the second one (including the divider). It has a column view, but doesn't seem to offer column auto resizing. Also, it doesn't hide items with the <code>hidden</code> flag, which is kind of insane. Even more shockingly, it offers no option to show file extensions! Tell me again that this is a power user tool. (Yeah, I know its myriad power user features, but I need the basic ones, and I don't see them. More discussions about "features" at the end.)</p></li> -<li><p><a href="http://www.cocoatech.com/pathfinder/">Path Finder</a>. It actually kind of works. It offers column auto resizing, hidden in the view options of the column view (accessible via ⌘J). Even "<code>open ~</code>" could open in Path Finder, if you let it be the default file manager; that was a nice surprise, and I'm not sure about the mechanism (maybe <a href="https://apple.stackexchange.com/questions/73529/how-to-change-the-default-file-manager-for-osx">this</a>? Doesn't sound right though). However, it has a horrible default appearance, and even after substantial customizations, it still looks kind of crappy. Also, the auto resizing implementation is incomplete, in that it doesn't offer min and max column size settings, so when auto resizing is enabled, many columns look awfully narrow. I'm also suspicious about its tech support. When I was investigating some issues about it on Google, I found some relevant tickets on its <a href="http://support.cocoatech.com/">support site</a>, but <em>none</em> of the tickets have any replies. I didn't bother to look around, but that was definitely a bad impression.</p> -<p>By the way, I mentioned concerns about Path Finder's pricing in the <a href="/blog/2015-07-30-the-sad-state-of-finder-on-el-capitan.html">sad state</a> post. At $40 it's definitely not cheap, but judging from the <a href="http://support.cocoatech.com/kb/installation-and-compatibility/path-finder-version-history">release history</a>, it's more like pay-to-upgrade every other year, rather than every year.</p> -<p>Conclusion: not impressed.</p></li> -</ul> -<p>Finally, a few words about "pro features". Many of these file managers offer a huge bundle of pro features, but quite of a few of them are completely useless. Useless features include builtin text editor, hex editor, terminal, archiver and unarchiver, blah blah blah. Why would anyone use those watered-down builtins? I use the right tool, the dedicated tool, for the right job. (To give one example, Commander One includes a command line that you can type commands to execute — without command or filename completion, naturally; and it also ships with a builtin terminal accessible via ⌃O. Apart from horrendous typography, the builtin terminal is also barely better than a dumb term, incapable of handling my prompt theme. Meanwhile, iTerm2 is accessible via a system-wide shortcut ⌥Space to me — extremely convenient.) Support for other filesystems, including remote filesystems and in-place archive browsing, could be welcome though, although I seldom need them.</p> -<hr/> -<p>P.S. Here are the version numbers, at the time of writing, of the mentioned software packages (apparently, things might change in later versions):</p> -<ul> -<li>TotalFinder 1.7.6 (beta);</li> -<li>XtraFinder 0.25.5;</li> -<li>Disk Order 3.2.5;</li> -<li>Commander One 1.1.1346;</li> -<li>DCommander 2.7.2;</li> -<li>CRAX Commander 1.10.4 (demo);</li> -<li>ForkLift 2.6.6;</li> -<li>Path Finder 7.2.</li> -</ul> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>TotalFinder 1.7.8+ now supports column auto resizing on El Cap. See update at the top.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>If you Google <a href="https://www.google.com/search?q=file+manager+commander">"file manager commander"</a>, you'll find a hell lot of "commanders". Reminds me of C&C... Oh well.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-10-14-sip-for-the-greater-good.html b/build/blog/2015-10-14-sip-for-the-greater-good.html deleted file mode 100644 index 18894bcf..00000000 --- a/build/blog/2015-10-14-sip-for-the-greater-good.html +++ /dev/null @@ -1,43 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-10-14T17:07:24-07:00" name="date"/> -<title>SIP — For the Greater Good</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">SIP — For the Greater Good</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-10-14T17:07:24-07:00">October 14, 2015</time> -</div> -</header> -<p>In recent months I wrote a few thousand words lamenting Finder and <a href="https://en.wikipedia.org/wiki/System_Integrity_Protection">SIP</a> on El Capitan. See <a href="/blog/2015-07-30-the-sad-state-of-finder-on-el-capitan.html">The sad state of Finder on El Capitan</a> and <a href="/blog/2015-10-14-follow-up-the-sad-state-of-finder-on-el-capitan.html">its follow-up</a>.</p> -<p>For the record, I'm not blaming SIP. It does deal a serious blow to people who in-memory patch stock applications (and there's a good discussion about the creativity aspect on <a href="http://atp.fm/episodes/128">ATP episode 128</a>), but the general public — at least more than 95% of users — should not be negatively affected, at least not in the short term. And I can understand why SIP protection comes at this time. Macs used to be safe, but in recent years we are seeing real world exploits increasingly more often. History has shown that technically-challenged users simply can't be entrusted with admin accounts, they are too willing to give their passwords to shady software downloaded from shady corners of the web (and sometimes even renowned corners get hacked). But they are given admin accounts anyway (there has to be someone knowing the admin password), so Apple has to come up with ways to protect them. SIP is a pretty good response.</p> -<p>SIP is also good for new tinkerers. When I first started to tinker with the command line, I wasn't aware of package managers and I wasn't messing inside virtual machines, so I would download packages from official websites, then manually compile and install them to my daily system. Some packages didn't respect the <code>/usr/local/bin</code> (and <code>include</code>, <code>lib</code>, <code>libexec</code>, <code>share</code>, etc.) convention and insisted on <code>/usr/bin</code>; some others used funny locations like a standalone subdirectory of <code>/usr/local</code>; and when things don't work (e.g., can't find libraries when building — at that time I'm not familiar with <code>CFLAGS=-I</code> yet), I would explictly change <code>PREFIX</code> (probably to <code>/usr</code>) and try again. That way, over a period of a few months, I ended up with a genuinely messed up <code>/usr</code>, with all kinds of stuff everywhere. I probably overwrote quite some binaries shipped with the system. The configuration kind of worked but was pretty fragile. In the end I reinstalled the system, and started to (loosely) follow FHS (<a href="http://www.pathname.com/fhs/">Filesystem Hierarchy Standard</a>) and use package managers (first MacPorts, then Homebrew). Good times. If I were to start tinkering today, I would certainly meet some barriers early on, but I would probably also learn the good practices earlier.</p> -<p>SIP is clearly the future, and I don't blame it. I just hope we don't see a vulnerability in the implementation soon.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-10-26-att-to-pure-talkusa-one-month-later.html b/build/blog/2015-10-26-att-to-pure-talkusa-one-month-later.html deleted file mode 100644 index c5b39344..00000000 --- a/build/blog/2015-10-26-att-to-pure-talkusa-one-month-later.html +++ /dev/null @@ -1,86 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-10-26T00:00:30-07:00" name="date"/> -<title>AT&T to Pure TalkUSA, one month later</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">AT&T to Pure TalkUSA, one month later</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-10-26T00:00:30-07:00">October 26, 2015</time> -</div> -</header> -<p><strong>TL;DR</strong>: If you have questions about Pure TalkUSA unanswered by the <a href="https://www.puretalkusa.com/cell-phones-sim-cards.php">official FAQ</a>, I have some information for you starting from the section "<a href="#migration-experience">migration experience</a>".</p> -<hr/> -<p>I became an AT&T customer days after arriving in the U.S., and stayed one for three years. The service was okay (I'm not a picky customer), but the pricing was ridiculous. I was paying somewhere between $50 and $60 per month for an AT&T Next plan, with unlimited talk and text and a mere 300 MB of data, phone installments <em>not</em> included (which I was paying the full price anyway). That's actually below average; see <a href="https://zmwangx.github.io/blog/2014-11-10-average-phone-plan-in-the-u-dot-s-costs-ten-time-as-much-as-that-in-the-u-dot-k.html">average phone plan in the U.S. costs ten time as much as that in the U.K.</a>. I could save a bit by joining a family plan (or more precisely, "data share plan"), but then I would lose control over my line and account, which have proven to be very annoying when I needed to upgrade, or otherwise be serviced.</p> -<p>The biggest concern was that I didn't really need unlimited talk and text, so I wasn't using what I was paying for. These days we have too many channels of communications, most of them free. My monthly talk usage was usually around a hundred minutes or less, so I was basically paying a few <em>dimes</em> per minute. Which was like being robbed.</p> -<p>Then I heard about <a href="https://www.puretalkusa.com/">Pure TalkUSA</a> — an AT&T <a href="https://en.wikipedia.org/wiki/Mobile_virtual_network_operator">MVNO</a> — from one of my friends. Pure Talk offers <a href="https://www.puretalkusa.com/cell-plans.php">cheap limited plans</a><a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> that looked appealing to me. It uses AT&T's network, so for me, the only thing I would lose by switching was part of my monthly expenses, to which I wouldn't object. So I switched last month. Now that I've been on Pure Talk's network for a month, I'll try to talk about the good and bad, as well as some migration caveats, since information is sparse on the Internet. Note: I'm not comparing Pure TalkUSA to other AT&T MVNOs, since I know nothing about any of them.</p> -<p><em>Disclaimer before I start: I can't guarantee that information provided here is accurate (I only speak from the experience of a single customer, that is myself, although I'll try not to make unfounded claims), and I didn't consult Pure TalkUSA before publishing this post, so please don't hold me accountable for anything.</em></p> -<h2 id="migration-experience"> -Migration experience -</h2> -<p>A few tips about migration from AT&T:</p> -<ul> -<li><p>About unlocking: After allegedly unlocking your AT&T phone, naturally you would want to make sure it is actually unlocked before ordering a Pure Talk SIM. And you'll find a lot of guides when you google "check if iPhone is unlocked". I'll just tell you this: don't trust those guides. iOS is constantly changing, and the only guaranteed check is to plug in your new SIM. To this day my General->About->Carrier shows AT&T, although I'm happily using Pure Talk's network.</p></li> -<li><p>Pure Talk ships your SIM card using USPS (they don't have physical stores), which is slow and expensive. However, I got my SIM much earlier than the estimated delivery date. Not sure if it's a coincidence. Probably location-dependent.</p></li> -<li><p>Porting number: You can choose to port your number during activation, whether you're calling or doing it online (filling out a few webforms). Beware that you must not have cancelled your AT&T service at the time of porting. The porting system was actually down for two days (customer support was very polite and kept apologizing although I said it didn't matter), and on the third day I used the webform but got an error in the end due to the wrong AT&T account number (there's an account number associated to each account — different from the phone number — that I've never heard of or used, and I had to call AT&T to extract that info). After acquiring the account number, I called Pure again and the porting process finished almost in an instant. I swapped in the new SIM card (the phone has been unlocked) and was able to make calls after a few seconds.</p></li> -<li><p>About AT&T cancellation: Porting the number will automatically cancel your service with AT&T, so you don't need to call them for cancellation.</p> -<p>An anecdote here: I initially feared the usual customer retention bullshit when I tried to cancel my AT&T service through online chat (I didn't know about automatic cancellation at that time), but there was none. Representative was very polite, and I only got a "sorry to see you go" at the end. So kudos to them.</p></li> -</ul> -<h2 id="pros-and-cons"> -Pros and cons -</h2> -<p>Here is a short list of pros and cons of Pure Talk compared to AT&T, in my opinion:</p> -<p>Good:</p> -<ul> -<li><p>Cheap. Obviously. I am currently paying $22.90 ($12.95 + $9.95) for 500 minutes and 400 MB of data, and I'm switching to 250 minutes next month, which would make it $19.95. Note that as advertised, there are no taxes and hidden fees. I always hated the before-tax price tags in the U.S. Just tell me how much I need to pay!</p></li> -<li><p>Network quality (both talk and LTE) is good. Switching from AT&T, I didn't notice a difference. I don't know if this is true nationwide (I live in the Bay Area), but they say it's true on their FAQ.</p> -<p>By the way, shortly after activating the service, I got a text message pointing me to download a profile to my phone in order to use LTE. It's titled "PureLTE" by "Giesecke and Devrient AB Nordic", and I verified with customer support that it is legit.</p></li> -<li><p>You may change your plan at any time with a few clicks, and only need to make up for the price difference. Note that downgrading doesn't grant you a refund.</p></li> -<li><p>Customer service (U.S. based) is mostly very polite and helpful (I did encounter a guy who sounded very tired with his job though), and wait time is generally very short.</p> -<p>Tip: For customer support, <em>call 611 from a Pure Talk line</em> (instead of the usual ten digit customer service number listed on their website) to avoid being charged.</p></li> -</ul> -<p>Bad:</p> -<ul> -<li><p>There's no visual voicemail, only old-schooled voicemail which you need to dial a number to listen to, in the order they were received; moreover, dialing and listening to voicemail counts toward your minute balance. I hardly missed that. I never grew accustomed to voicemail anyway; now I have an excuse to forget about it completely.</p></li> -<li><p>All incoming phone calls and text messages count towards your minute balance (I don't know about what's most common in the U.S., but as far as I know this is rarely the case in China — you usually only pay for active usage, although you do need an active service to receive calls and messages). Calling toll free numbers counts, too, so now you'll be even more angry when you're put on hold for an hour.</p></li> -<li><p>For iPhone users, or Android users who otherwise bring in their own phones: since they don't sell you your iPhone, they also don't offer insurance plans. So be extra careful with your phone! Paying $100 for a replacement (from AT&T's insurance program) is no more.</p></li> -</ul> -<p>That's basically all I want to say. Hope this post helps someone who's researching Pure Talk.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>Pure Talk also offers an unlimited talk & text plan for $24, excluding data. According to <a href="https://www.puretalkusa.com/mobile-unlimited-plan.php">the "unlimited plus plan" page</a>:</p> -<blockquote> -<p>Compare our Unlimited Plus plans to similar unlimited cell phone plans on the market and you'll see the savings you can receive! While others may pad their higher priced plans with "free" international minutes, we're focused on giving you the best rate for unlimited talk and text, plus data used within the United States.</p> -</blockquote> -<p>I honestly don't know which competitions they are referring to here. If it's AT&T, I'll share an anecdote about international roaming: I went back to China, and got a text message from AT&T saying that I could use data for TWENTY DOLLARS PER MEGABYTE. I would have had to pay $200 to visit The Verge once on 4G.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-11-06-microsoft-drops-unlimited-onedrive-storage-after-people-use-it-for-unlimited-storage.html b/build/blog/2015-11-06-microsoft-drops-unlimited-onedrive-storage-after-people-use-it-for-unlimited-storage.html deleted file mode 100644 index bd67f486..00000000 --- a/build/blog/2015-11-06-microsoft-drops-unlimited-onedrive-storage-after-people-use-it-for-unlimited-storage.html +++ /dev/null @@ -1,53 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-11-06T10:49:51-08:00" name="date"/> -<title>Microsoft drops unlimited OneDrive storage after people use it for unlimited storage</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Microsoft drops unlimited OneDrive storage after people use it for unlimited storage</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-11-06T10:49:51-08:00">November 6, 2015</time> -</div> -</header> -<p><a href="http://arstechnica.com/information-technology/2015/11/microsoft-drops-unlimited-onedrive-storage-after-people-use-it-for-unlimited-storage/">Story on Ars Technica</a>. <a href="https://blog.onedrive.com/onedrive_changes/">Official announcement</a>. I was playing catch up on this week's RSS when this one punched in my face.</p> -<p>I currently have 5 TB of data in OneDrive. I was once worried about lock-in when I eventually have 20 or 100 TB there, but now that they have shown their true colors, the worries are all gone. They are not even offering anything past 1 TB. We have seen this too many times — shit happens when people actually use unlimited for unlimited. Usually unlimited quickly becomes qualified, but in this case, unlimited simply becomes limited. What irony when one looks back at their announcement from <a href="/blog/2014-10-27-onedrive-goes-unlimited.html">a year ago</a>:</p> -<blockquote> -<p>Today, storage limits just became a thing of the past with Office 365.</p> -</blockquote> -<p>Why even promise when they can't keep it for more than a year.</p> -<p>Okay, Microsoft just reclaimed the top spot of my most-hated-companies list, and my <a href="https://github.com/zmwangx/pyonedrive">ongoing efforts on making a usable OneDrive CLI</a> have been wasted. I just pushed the final commit and closed all issues. Maybe it's a blessing that I'll no longer need to deal with that slow and glitchy API; I'll see after experimenting with APIs of other cloud storage providers.</p> -<p>Guess my next stop is either Amazon Cloud Drive or S3, probably the former so that I don't need to calculate.<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> And a quick search yields an actively-maintained CLI client <a href="https://github.com/yadayada/acd_cli">yadavada/acd_cli</a>, so I may not need to roll my own this time (it depends on usability).</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>Yeah I'm a mathematician, but I hate most calculations that involve $$. 😂<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-11-15-we-need-a-programming-keyboard-on-ios.html b/build/blog/2015-11-15-we-need-a-programming-keyboard-on-ios.html deleted file mode 100644 index 74dd0397..00000000 --- a/build/blog/2015-11-15-we-need-a-programming-keyboard-on-ios.html +++ /dev/null @@ -1,53 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-11-15T02:17:05-08:00" name="date"/> -<title>We need a programming keyboard on iOS</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">We need a programming keyboard on iOS</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-11-15T02:17:05-08:00">November 15, 2015</time> -</div> -</header> -<p>We do. If you ever tried to say something on GitHub (web) or StackOverflow (web or app) on iOS, you'll probably agree with me. The stock keyboard (or any third party keyboard that I've heard of) is simply awful at this. Typing on iOS software keyboard is unpleasant enough to begin with, but behold:</p> -<ul> -<li>Auto"correct" messes up everything as fast as you can type, which isn't really fast anyway; might as well call it autorot.</li> -<li>The backtick is a click plus a loooong click (on the single quote key) plus another click away. Good luck typing code in Markdown,<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> especially if you use GFM fenced code block like all of us do.</li> -<li>Brackets, curly braces, the underscore, the pound, etc. are all three clicks away.</li> -</ul> -<p>The solution is pretty obvious actually. I don't know about smaller phones, but the software keyboard on a landscape iPhone 6 Plus has four rows, which takes up about 40% of vertical screen estate, and it has fourteen keys in the top row. With a little bit of effort it can be made into a five-row, full-sized keyboard (without arrow keys perhaps) without taking up a ridiculous amount of space. Since the horizontal 6 Plus could handle it, any iPad should be able to handle it too; definitely shouldn't be an iPad Pro-only luxury. Turn off autocorrect on top of that, and you get a decent programming (or better put, programmer-oriented) keyboard.</p> -<p>This is merely a rant, but it would awesome if anyone sets out to make one.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>To be fair, typing BBCode is even worse. Unfortunately that's what Ars Technica use, and I've given up on commenting there.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-11-25-bash-function-exporting-fiasco.html b/build/blog/2015-11-25-bash-function-exporting-fiasco.html deleted file mode 100644 index 351f2a57..00000000 --- a/build/blog/2015-11-25-bash-function-exporting-fiasco.html +++ /dev/null @@ -1,68 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-11-25T15:38:13-08:00" name="date"/> -<title>Bash function exporting fiasco</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Bash function exporting fiasco</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-11-25T15:38:13-08:00">November 25, 2015</time> -</div> -</header> -<p>Bash is the only major shell (and the only shell that I know of) that implements function exporting. By now everyone should have heard of this feature, I suppose, after the publicity of Shellshock last year. I was personally introduced to it while writing parallel processing scripts <a href="https://www.gnu.org/software/parallel/parallel_tutorial.html#Transfer-environment-variables-and-functions">with GNU Parallel</a> (long before Shellshock), and it seemed useful and clever at that time. Back then I often wondered why it didn't make its way into Z shell. However, now that I'm much more seasoned in shell scripting, I can see why and how this feature is troubled and of debatable value.</p> -<p>Two problems lie at the heart of function exporting:</p> -<ol style="list-style-type: decimal"> -<li>As always, everything clever comes at a cost;</li> -<li>Code execution from untrusted source.</li> -</ol> -<p>Regarding the first problem, the cost of function exporting is to mess with the environment, in a very hackish way. The environment was designed to hold data, not code, and we're not in the utopia of Lisp; but bash forced its way through. Pre-shellshock, exported <code>func</code> was stored as <code>func=() {...</code> in env; post-shellshock, it was first <code>BASH_FUNC_func()=() {...</code> (which didn't entirely fix the issue), and then <code>BASH_FUNC_func%%=() {...</code>.</p> -<p>The second problem doesn't need much explanation — <em>shellshock it was</em>. It has been extensively documented elsewhere, so I'll just succinctly comment that to load exported functions into a subshell, function definitions have to be retrieved from the environment and executed (again because we're not in the utopia of Lisp<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a>), and loading is done passively from the subshell user's point of view, hence the code execution bug(s). The bug(s) has(have) allegedly been fixed, but code execution (presumably with the appropriate safeguards now) still can't be avoided altogether, so just like a sanitized <code>eval</code>, it would still wake you up at night.</p> -<p>Well, if that's all I have to say, I wouldn't have started this post today. The thing that's bugging me is another issue I've found recently that's entirely avoidable, yet upon which we'll probably never see light ever after due to a combination of factors.</p> -<p>It started with <a href="http://stackoverflow.com/q/33819243/19447840">this question on SO</a>. While troubleshooting I quickly noticed that a Bash-emulated <code>sh</code> imports those <code>BASH_FUNC</code>s from the environment:</p> -<pre><code>> bash -c 'func () { echo "exported function loaded"; } && export -f func && ln -sf /bin/bash sh && ./sh -c func' -exported function loaded</code></pre> -<p>It gets worse when the function isn't Bourne shell compatible (e.g., when it uses process substitution):</p> -<pre><code>> bash -c 'func () { cat <(echo hello); } && export -f func && ln -sf /bin/bash sh && ./sh -c func' -cat: <(echo hello): No such file or directory</code></pre> -<p>That's surprising but not scary enough, because if you're not a fool you won't call <code>func</code> in <code>sh</code> anyway. However, if you're unfortunate enough to be dealing with <code>/bin/sh</code> on OS X (bash 3.2 under the hood, modified by Apple or not I'm not sure), then all hell break loose:</p> -<pre><code>> bash -c 'func () { cat <(echo hello); } && export -f func && /bin/sh -c :' # OS X only -/bin/sh: func: line 0: syntax error near unexpected token `(' -/bin/sh: func: line 0: `func () { cat <(echo hello)' -/bin/sh: error importing function definition for `func'</code></pre> -<p>Note that we're actively doing nothing in <code>sh</code>, yet we get all these syntax errors from loading <code>func</code>. This happens to every invocation of <code>sh</code>, and as you might expect, there are no shortage of programs that are either <code>sh</code> scripts (e.g., fasd) or have internal <code>sh</code> calls (e.g., GNU Parallel<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a>). A single export of a Bourn shell incompatible function will haunt you through the entire session. Oops.</p> -<p>As I said, I don't know if the displayed error messages are due to Apple's modifications (anyone willing to look at the <a href="https://opensource.apple.com/source/bash/bash-97/">source code</a>?), since a symlink named <code>sh</code> to <code>/bin/bash</code> doesn't print error messages, but instead load the wrong function, which is almost as bad but less annoying to innocent users. At any rate, it's not even worth reporting, either to GNU or Apple, because we're stuck with bash 3.2 for <code>/bin/sh</code> forever (thank you GPLv3), and it takes a hell of a vulnerability like shellshock to get a small update out of Apple's hands. We can install newer shells to <code>/usr/local</code> as much as we'd like to, but <code>/bin/sh</code> is simply the final word for many tasks involving the shell. Yet it's stained by this troubled bash-specific feature, and it's not going anywhere. So sad.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>I'm not commenting on the security of Lisp.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p><strong>04/14/2015 Update.</strong> GNU Parallel is no longer haunted by this issue since <a href="http://git.savannah.gnu.org/cgit/parallel.git/commit/?id=3d919c6cd427e9615f56f260eb959a44d5d32c18"><code>3d919c6</code></a>.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-12-08-safeguarding-git-repos-against-accidental-rm.html b/build/blog/2015-12-08-safeguarding-git-repos-against-accidental-rm.html deleted file mode 100644 index 88ab872a..00000000 --- a/build/blog/2015-12-08-safeguarding-git-repos-against-accidental-rm.html +++ /dev/null @@ -1,73 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-12-08T00:17:39-08:00" name="date"/> -<title>Safeguarding git repos against accidental rm</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/highlight.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Safeguarding git repos against accidental rm</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-12-08T00:17:39-08:00">December 8, 2015</time> -</div> -</header> -<p>Everyone who has spent a sizable portion of their life in terminals has experienced that "oh shit" moment: you realize what you've done immediately after you've hit enter, but it's already too late. And needlessly to say, many of those are associated to accidental <code>rm</code>s.</p> -<p>I just had one of those moments. I was going to delete a subdirectory of <code>~/.config</code>, but hit return prematurely, and the command line ended up being <code>rm -r ~/.config</code>. Imagine the horror one second later. Fortunately I was saved by the read-only objects in <code>.git</code>, which triggered prompts; however, damage was already done, to some extent. I had to reinit the repo and do a hard reset, and a corrupted submodule was in my way (it blocked my attempt of <code>git reset --hard</code>) which I eventually had to completely remove and re-add. In the end everything was recovered (hopefully) and back to normal, but this episode was definitely not great for heart health, which led me to rethink <code>rm</code>.</p> -<p>I've tried several safer <code>rm</code> solutions before. The first and obvious is to alias <code>rm</code> to <code>rm -i</code>, but having to answer dozens of prompts a day (or more) is agonizing and unproductive. I've also tried trashing, but a nonempty trash can makes me sick, so not for me either. I also used <code>safe-rm</code> for a couple of months, but without supplying my own blacklist (I have none to be blacklisted), I've never hit the default blacklist; apparently I'm not stupid enough to mess in system locations, so this won't really help much. Fortunately though, this time I might have found a very good solution for myself.</p> -<p>The idea is to protect all git repos. Git repos<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> are among the most valuable assets of programmers, and they have the nice property of not being completely removable without <code>-f</code> or <code>--force</code> (the work tree of a submodule, where <code>.git</code> is a regular file containing the relative path of the git dir, can be removed without <code>--force</code>, but we don't want to damage submodules anyway, so let's not single them out). It's unlikely that we would intend to remove a repo directory without specifying <code>-f</code> or <code>--force</code>, so let's just reject all such <code>rm</code> calls.</p> -<p>The wrapper is very easy to write. Here's one implementation for Zsh with support for both GNU coreutils and BSD <code>rm</code>.</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh"><span class="kw">rm</span> <span class="kw">()</span> <span class="kw">{</span> - <span class="kw">setopt</span> localoptions noshwordsplit noksharrays - <span class="kw">local</span> <span class="ot">args_backup</span> <span class="ot">force</span> <span class="ot">node</span> - <span class="kw">set</span> -A args_backup <span class="ot">$@</span> - <span class="kw">while</span> <span class="kw">:</span>; <span class="kw">do</span> - <span class="kw">case</span> <span class="ot">$1</span><span class="kw"> in</span> - --force<span class="kw">|</span>-*f*<span class="kw">)</span> <span class="ot">force=</span>1 <span class="kw">&&</span> <span class="kw">shift;;</span> - --<span class="kw">)</span> <span class="kw">shift</span> <span class="kw">&&</span> <span class="kw">break;;</span> - -*<span class="kw">)</span> <span class="kw">shift;;</span> - *<span class="kw">)</span> <span class="kw">break;;</span> - <span class="kw">esac</span> - <span class="kw">done</span> - <span class="kw">for</span> node; <span class="kw">do</span> - <span class="co"># -f, --force hasn't been specified && node is a git repo</span> - [[ -z <span class="ot">$force</span> <span class="kw">&&</span> -e <span class="ot">$node</span>/.git ]] <span class="kw">&&</span> <span class="kw">{</span> - <span class="kw">printf</span> <span class="st">"\e[31m'%s' is a git repo -- won't remove without the -f or --force option\e[0m\n"</span> <span class="ot">$node</span> - <span class="kw">return</span> 1 - <span class="kw">}</span> - <span class="kw">done</span> - <span class="kw">command</span> <span class="kw">rm</span> <span class="ot">$args_backup</span> -<span class="kw">}</span></code></pre></div> -<p>Personally, I stick it into a <a href="https://github.com/zmwangx/prezto/tree/master/modules/rm_guard">Prezto module</a> available from my fork. Hopefully it will serve me well this time round.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>In this article, "repo" stands for the work tree of a repo, unless otherwise noted; the actual repo with git objects is referred to as "git dir".<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-12-16-spoiled-by-retina-in-less-than-a-day.html b/build/blog/2015-12-16-spoiled-by-retina-in-less-than-a-day.html deleted file mode 100644 index 61a17a94..00000000 --- a/build/blog/2015-12-16-spoiled-by-retina-in-less-than-a-day.html +++ /dev/null @@ -1,55 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-12-16T21:10:08-08:00" name="date"/> -<title>Spoiled by Retina, in less than a day</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Spoiled by Retina, in less than a day</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-12-16T21:10:08-08:00">December 16, 2015</time> -</div> -</header> -<p>I finally got a 15'' Retina MacBook Pro this morning to replace my 13'' mid-2012 non-Retina MacBook Pro, whose spinning disk has been getting increasingly slower (or so I felt).<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> Apparently this is a pretty significant landmark in my personal computing history, since I'm saying goodbye to both spinning disk and non-Retina display on my primary computing device.</p> -<p>The transition was initially smooth except for a few things. First, as a tap-to-click wizard I immediately turned on tap-to-click, but I had a hard time dragging things because it was too easy to trigger a force touch instead on the medium setting, and under the firm setting I could hardly force touch at all; in the end I just turned off force touch altogether, and haven't had any problem since. By the way, I was initially worried about the keyboard too but it worked surprisingly well for me, so no complaints there. Secondly, <a href="/blog/2015-08-31-after-all-these-years-10pt-non-anti-aliased-monaco-is-still-the-best.html">10pt non-anti-aliased Monaco</a> looks weird on Retina since it's no longer the beloved bitmap version. I turned on antialiasing and now it's no longer weird, but it felt totally different and I'm not sure if I like it (definitely not as much as the 10pt bitmap Monaco anyway). It's okay right now but I'll probably need to spend some time trying out different fonts. Obviously there are <a href="https://news.ycombinator.com/item?id=10140728">like-minded folks</a> out there. Sad story.</p> -<p>So much for first impressions. Apart from Monaco, everything felt great, until I returned home (I was doing setup away from home to get a less shitty connection) and connected my 27'' external monitor. Holy crap, I couldn't believe my eyes. The dock icons — the first things I saw before launching anything — looked <em>so blurry I couldn't stare at them for more than a few seconds</em>. That was after staring at the Retina display for less than five hours. Not to mention PDFs; they look ultra crisp on the Retina display and ultra crappy on non-Retina — especially in Preview, which is a problem I've been aware of since Yosemite.<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a> Moreover, the terminal font is more problematic than initially estimated — <em>now I have a retina display and a non-retina one side-by-side, yet I can only set one font for my default profile, which will never satisfy both</em>!<a class="footnoteRef" href="#fn3" id="fnref3"><sup>3</sup></a> This is so awkward I can't think of a solution. One obvious approach is to ditch the blurry 27'' and only work from the Retina 15'', but should I really let the large canvas sit idle? No idea. Or should I get a 4K external display? First, a 4K display at 27'' still can't rival the pixel density of 2880x1800 at 15.4'' (Apple ships 5K at 27'' for a reason). Secondly and more importantly, I don't have the budget for such a thing after throwing money at an expensive 15'' rMBP (with 512 GB SSD)...</p> -<p>Transition periods are always awkward, I guess.</p> -<hr/> -<p><strong>12/17/2015 Update.</strong> After more than a full day's use, I actually quite love 10pt Monaco on a Retina display. I tried various fonts, including Menlo, Consolas and so on, but none of them has that whimsical feeling of Monaco. Hopefully the font is stuck now.</p> -<hr/> -<p><strong>12/28/2015 Update.</strong> A dozen days later, I can hardly look at 10pt Monaco on a non-Retina screen anymore, antialiased or not, especially not in bold. Mind blown.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>I haven't got the nerve to replace the hard drive myself, since it looks so much more complicated than upgrading the memory.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>PDFs looked so horrible in Preview (and TeXShop, my LaTeX previewer, which only serves a niche) that I often viewed them in browsers (!!), where text at least looks reasonable (on par with slightly blurry text elsewhere). PDF Expert came along and kind of made the situation better for non-Retina.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -<li id="fn3"><p>Provided that I'll religiously stick to 10pt non-anti-aliased Monaco on non-Retina.<a class="footnotes-backlink" href="#fnref3">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-12-20-regex-flavor-hell.html b/build/blog/2015-12-20-regex-flavor-hell.html deleted file mode 100644 index 6528aed4..00000000 --- a/build/blog/2015-12-20-regex-flavor-hell.html +++ /dev/null @@ -1,47 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-12-20T16:03:03-08:00" name="date"/> -<title>Regex flavor hell</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Regex flavor hell</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-12-20T16:03:03-08:00">December 20, 2015</time> -</div> -</header> -<p>I write a lot of shell scripts, which means dealing with common *ix utilities a lot. I typically want my scripts to work on both OS X and Linux (or OS X + GNU utilities, which is my personal setup), which means writing commands that are understood in both GNU/Linux and BSD worlds. Unfortunately that's not so simple, because to do that I usually have to give up readily available functionalities (especially the vast collection of useful options typical of GNU utilities) and am constantly thrown back to the stone age that is POSIX, or a little bit more than POSIX.</p> -<p>Working with regular expressions is especially painful. Almost every implementation of every utility (with regex support) has its own flavor of regex. Most notably the big three: <code>grep</code>, <code>sed</code> and <code>awk</code>. GNU utilities of course come with GNU extensions, but they are nothing when aiming for compatibility. Ignoring GNU extensions, there's a way to turn on standard POSIX extensions (ERE) on <code>sed</code>, but unfortunately GNU and BSD use different flags: <code>-r</code> for GNU sed and <code>-E</code> for BSD sed. The two implementations of <code>grep</code> thankfully use the same flag <code>-E</code> to turn on ERE, but GNU grep, being a GNU utility and having to distinguish itself from its mundane counterpart, further implements <code>-P,--perl-regexp</code> — regexers' dream. It's there but I can't use it, except in an interactive shell. <code>awk</code> has more than two implementations and will be left out of this discussion.</p> -<p>Anyway, despite all these flavor issues, I can usually get away with BRE, although it's verbose and unreadable as hell (quantifiers in particular) and doesn't support alternation. I would be thankful if BRE is the end of the story, but it is not. There are more tools lurking around trying to sabotage scripters. <code>find</code> is a perfect example. BSD <code>find</code>, unsurprisingly, uses BRE by default with <code>-regex</code> and <code>-iregex</code>, and ERE may be turned on with the <code>-E</code> flag. GNU findutils <code>find</code>, however, tries to be helpful and future-proof by having a <code>-regextype</code> option:</p> -<blockquote> -<p>Changes the regular expression syntax understood by <code>-regex</code> and <code>-iregex</code> tests which occur later on the command line. Currently-implemented types are <code>emacs</code> (this is the default), <code>posix-awk</code>, <code>posix-basic</code>, <code>posix-egrep</code> and <code>posix-extended</code>.</p> -</blockquote> -<p>The Emacs flavor? You mean Elisp regexp? Okay fine, <a href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html">BRE</a> — with few features other than grouping (<code>\(...\)</code>), quantifiers (<code>*</code> or <code>\{n,m\}</code>), bracket expressions and character classes — should still be pretty much compatible with Elisp regexp. However, the "Emacs flavor" isn't even the Elisp flavor. It's a <a href="https://www.gnu.org/software/findutils/manual/html_node/find_html/emacs-regular-expression-syntax.html">stripped version</a> specifically for findutils. In particular, there are <code>*</code>, <code>+</code> and <code>?</code> but no curly braces quantifiers, so gone is the dream of writing even just mildly complex regexps that are compatible with both BSD <code>find</code> and GNU findutils <code>find</code>. By the way, in case you wonder, the <a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/find.html">POSIX <code>find</code></a> doesn't even have a <code>-regex</code> primary/operator...</p> -<p>What a cruelly realistic world we live in.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-12-26-autoenv-with-auto-cleanup.html b/build/blog/2015-12-26-autoenv-with-auto-cleanup.html deleted file mode 100644 index 544154e4..00000000 --- a/build/blog/2015-12-26-autoenv-with-auto-cleanup.html +++ /dev/null @@ -1,58 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-12-26T00:15:48-08:00" name="date"/> -<title>autoenv with auto cleanup</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/highlight.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">autoenv with auto cleanup</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-12-26T00:15:48-08:00">December 26, 2015</time> -</div> -</header> -<p>I heard about <a href="https://github.com/kennethreitz/autoenv">kennethreitz/autoenv</a> a long time ago. The idea of autoloading project-specific environment modifications is nice, but no auto cleanup after leaving a project was a showstopper for me.</p> -<p>Today, I took matters into my own hands and wrote a fresh Zsh implementation<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> with auto cleanup support. Check it out: <a class="uri" href="https://github.com/zmwangx/prezto/tree/master/modules/autoenv">https://github.com/zmwangx/prezto/tree/master/modules/autoenv</a>.</p> -<p>As a quick promotion, let me show you two common examples.</p> -<p>First, inserting some local bin directory into the search path. This is easily done by a one-line <code>.env</code>, say,</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh">autoenv-insert-paths bin libexec</code></pre></div> -<p>This way <code>$PWD/bin</code> and <code>$PWD/libexec</code> are inserted to the beginning of the search path, which will persist until you leave the directory tree. That is to say, the inserted paths will still be available when you descend into subdirectories (and more specific <code>.env</code>'s can even be stacked as you descend), but they will be purged as soon as you leave the tree. Clever, isn't it?</p> -<p>Secondly, exporting project-specific environment variables. The <code>.env</code> would look like</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh"><span class="kw">export</span> <span class="ot">HOMEBREW_DEVELOPER=</span>not-for-the-faint-hearted - -<span class="fu">autoenv-purge ()</span> <span class="kw">unset</span> HOMEBREW_DEVELOPER</code></pre></div> -<p>where the body of <code>autoenv-purge</code> will be executed when you leave the directory tree. No more junk floating around.</p> -<p>Again, for more info, including detailed usage and customization instructions, please visit <a href="https://github.com/zmwangx/prezto/tree/master/modules/autoenv"><code>modules/autoenv</code></a> in zmwangx/prezto.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>This is not a re-implementation in the common sense. My little Zsh module is inspired by kennethreitz/autoenv and reminiscent of that older project, but I took nothing from there (in fact I didn't even read their source code). I also don't claim to support their entire feature set. For instance, kennethreitz/autoenv claims to be Foreman compatible, which includes turning on <code>ALL_EXPORT</code>. However, I don't think <code>ALL_EXPORT</code> by default is a good idea, so with my <code>autoenv</code>, if you want <code>ALL_EXPORT</code> you have to set it explicitly.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-12-27-lesson-on-magic-method-access-of-python-new-style-classes-from-my-failed-python3-port-of-tomorrow.html b/build/blog/2015-12-27-lesson-on-magic-method-access-of-python-new-style-classes-from-my-failed-python3-port-of-tomorrow.html deleted file mode 100644 index 839ce5d5..00000000 --- a/build/blog/2015-12-27-lesson-on-magic-method-access-of-python-new-style-classes-from-my-failed-python3-port-of-tomorrow.html +++ /dev/null @@ -1,118 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-12-27T16:47:05-08:00" name="date"/> -<title>Lesson on magic method access of Python new-style classes (from my failed Python3 port of Tomorrow)</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/highlight.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Lesson on magic method access of Python new-style classes (from my failed Python3 port of Tomorrow)</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-12-27T16:47:05-08:00">December 27, 2015</time> -</div> -</header> -<p>I know the title is formidably long, but I can't find something more accurate (and my homegrown mini CMS doesn't support subtitle), so please bear with me.</p> -<p>So, I have <a href="https://github.com/madisonmay/Tomorrow">madisonmay/Tomorrow</a> — "magic decorator syntax for asynchronous code in Python 2.7" — bookmarked for a long time<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> without ever trying it, because I simply don't write Python 2 code any more (except when I try to maintain compatibililty). I felt kind of strange that a ~50-line project with ~1000 stars on GitHub hasn't been ported to Python 3 already, so I gave it a shot just now.</p> -<p>I thought it would be easy:</p> -<ol style="list-style-type: decimal"> -<li>Modernize the old-style class <code>Tomorrow</code>;</li> -<li>Replace <code>__getattr__</code> with <code>__getattribute__</code> for unconditional attribute routing, then make a few exceptions to prevent infinite recursion;</li> -<li><code>2to3</code> test cases;</li> -<li>Make meta changes, like removing the <code>futures</code> dependency.</li> -</ol> -<p>However, after doing 1–3, I ran the tests, and out of the five test cases, three failed and one errored. I tried to isolate the problem, and ended up with the following piece of proof-of-concept:</p> -<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="kw">class</span> PassThrough(<span class="bu">object</span>): - - <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>, obj): - <span class="va">self</span>._obj <span class="op">=</span> obj - - <span class="kw">def</span> <span class="fu">__getattribute__</span>(<span class="va">self</span>, name): - <span class="cf">if</span> name <span class="op">==</span> <span class="st">"_obj"</span>: - <span class="cf">return</span> <span class="bu">object</span>.<span class="fu">__getattribute__</span>(<span class="va">self</span>, name) - <span class="bu">print</span>(<span class="st">"Accessing '</span><span class="sc">%s</span><span class="st">'"</span> <span class="op">%</span> name) - <span class="cf">return</span> <span class="va">self</span>._obj.<span class="fu">__getattribute__</span>(name)</code></pre></div> -<p>This snippet is valid in both Python 2.7 and Python 3, but here's the surprise:</p> -<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="op">>>></span> g <span class="op">=</span> PassThrough(<span class="dv">0</span>) -<span class="op">>>></span> <span class="bu">print</span>(g) -<span class="op"><</span>__main__.PassThrough <span class="bu">object</span> at <span class="bn">0x10c662e48</span><span class="op">></span> -<span class="op">>>></span> <span class="bu">str</span>(g) -<span class="co">'<__main__.PassThrough object at 0x10c662e48>'</span> -<span class="op">>>></span> <span class="bu">hasattr</span>(g, <span class="st">'__str__'</span>) -Accessing <span class="st">'__str__'</span> -<span class="va">True</span> -<span class="op">>>></span> g.<span class="fu">__str__</span>() -Accessing <span class="st">'__str__'</span> -<span class="co">'0'</span></code></pre></div> -<p>In addition, here's what happens if you try to "pass through" a function:</p> -<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="op">>>></span> <span class="kw">def</span> f(): <span class="cf">return</span> <span class="va">True</span> -<span class="op">>>></span> g <span class="op">=</span> PassThrough(f) -<span class="op">>>></span> g() -Accessing <span class="st">'__class__'</span> -Accessing <span class="st">'__class__'</span> -Traceback (most recent call last): - File <span class="st">"<ipython-input-6-d65ffd94a45c>"</span>, line <span class="dv">1</span>, <span class="kw">in</span> <span class="op"><</span>module<span class="op">></span> - g() -<span class="pp">TypeError</span>: <span class="st">'PassThrough'</span> <span class="bu">object</span> <span class="kw">is</span> <span class="kw">not</span> <span class="bu">callable</span> - -<span class="op">>>></span> <span class="bu">callable</span>(g) -<span class="va">False</span> -<span class="op">>>></span> <span class="bu">hasattr</span>(g, <span class="st">'__call__'</span>) -Accessing <span class="st">'__call__'</span> -<span class="va">True</span> -<span class="op">>>></span> g.<span class="fu">__call__</span>() -Accessing <span class="st">'__call__'</span> -<span class="va">True</span></code></pre></div> -<p>As you can tell, although <code>__str__</code> or <code>__call__</code> may have been implemented through <code>__getattribute__</code>, and <code>hasattr</code> (which in turn depends on <code>getattr</code>) has no trouble finding them, they are not picked up by <code>str</code> or function call <code>(...)</code>. At this point, one would suspect that this is due to <code>str</code> or function call only looking at the class instance's <code>__dict__</code>. Compare this to the behavior of an old-style class:</p> -<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="kw">class</span> PassThrough(): - - <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>, obj): - <span class="va">self</span>._obj <span class="op">=</span> obj - - <span class="kw">def</span> <span class="fu">__getattr__</span>(<span class="va">self</span>, name): - <span class="bu">print</span>(<span class="st">"Acessing '</span><span class="sc">%s</span><span class="st">'"</span> <span class="op">%</span> name) - <span class="cf">return</span> <span class="va">self</span>._obj.<span class="fu">__getattribute__</span>(name)</code></pre></div> -<p>Now:</p> -<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="op">>>></span> g <span class="op">=</span> PassThrough(<span class="dv">0</span>) -<span class="op">>>></span> <span class="bu">print</span>(g) -Acessing <span class="st">'__str__'</span> -<span class="dv">0</span> -<span class="op">>>></span> <span class="kw">def</span> f(): <span class="cf">return</span> <span class="va">True</span> -<span class="op">>>></span> g <span class="op">=</span> PassThrough(f) -<span class="op">>>></span> g() -Acessing <span class="st">'__call__'</span> -<span class="va">True</span></code></pre></div> -<p>Note that magic method access is always routed through <code>__getattr__</code>.</p> -<p>After some digging, my suspicion was confirmed: indeed, for new-style classes, rather than invoking <code>__getattribute__</code>, the Python interpreter only looks for magic methods in <code>__dict__</code>. But is there a workaround for implementing something like the <code>PassThrough</code> class above? There's a <a href="http://stackoverflow.com/a/9059858/">nice answer</a> on StackOverflow that uses a metaclass to "automatically add proxies for magic methods at the time of class creation", to quote the author. However, the thing about Tomorrow is that <em>we don't have the result and don't know whatever magic methods it might have at class creation</em> — after all, Python isn't a statically typed language. It is possible for programmers to offer hints, but then Tomorrow won't be as elegant and magical anymore. Therefore, unfortunately enough, Tomorrow isn't portable to Python 3 — at least not without a substantial hack that's beyond my knowledge, or a complete overhaul of its logic (haven't thought about that).</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>Pretty much since the beginning, I believe (the <a href="https://github.com/madisonmay/Tomorrow/commit/22a53dfbcf9b516ecd1770eeca9fcf1720271240">initial commit</a> was from July 24 of this year). I don't remember how I came accross it though.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-12-28-why-i-want-lossless-music-on-itunes-music-store.html b/build/blog/2015-12-28-why-i-want-lossless-music-on-itunes-music-store.html deleted file mode 100644 index 0428f884..00000000 --- a/build/blog/2015-12-28-why-i-want-lossless-music-on-itunes-music-store.html +++ /dev/null @@ -1,51 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-12-28T03:15:45-08:00" name="date"/> -<title>Why I want lossless music on iTunes Music Store</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Why I want lossless music on iTunes Music Store</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-12-28T03:15:45-08:00">December 28, 2015</time> -</div> -</header> -<p>This is an impulse post after reading <a href="https://marco.org/2015/12/27/apple-hd-audio-again">"Apple again rumored to be working on high-resolution audio"</a>.<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a></p> -<p>To be clear, I'm no audiophile. I can't tell the difference between 256kbps AAC and lossless (maybe not even the difference between 128k and 256k), and my midrange to lower midrange equipments probably won't let me tell anyway. I'm certainly not a consumer of snake oil.</p> -<p>However, I still prefer to get everything in lossless, simply because <strong>"good enough" today is almost never good enough tomorrow</strong>. Fifty years later I'm most likely still wandering this planet, I and my music collection. I would be extremely regretful if I didn't archive the highest quality versions of my favorite tracks today, only to find them inferior-sounding fifty years later, which is a pretty realistic possibility given how fast technology advances.<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a> Even today's lossless could be inferior-sounding in the future, but there would be no regret.</p> -<p>To be extra clear, I'm talking about lossless for archival purposes, so what I want to see is a lossless download option in ITMS.<a class="footnoteRef" href="#fn3" id="fnref3"><sup>3</sup></a> Streaming can be done in whatever good enough® sampling frequency and bitrate that's currently in use, since it's a one-off thing with no effects on tomorrow (and I don't give a shit about streaming and subscription anyway). Offering lossless downloads likely won't put much burden on Apple's infrastructure, since they already deliver much more bandwidth-demanding movies on the same channel. Moreover, albums on ITMS aren't much cheaper than physical CDs, while the cost is apparently lower than CD production, the audience apparently wider, and the chances of impulse purchases (especially of single tracks) much higher, so I would suppose such a move (delivering lossless on ITMS) won't considerably hurt record labels' profits either. After all, if they don't make it easy for consumers, many consumers will just pirate — it's way too easy to pirate music.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>And I did see the <a href="http://www.macrumors.com/2015/12/20/apple-high-resolution-audio/">MacRumors article</a> a week ago. I even registered a MacRumors account, which I never bothered to do, just to comment on that article... It just didn't occur to me to write a blog post at that time.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>You might be skeptical of my hearing when I'm in my seventies... But I could well be showing my favorites to someone with perfect hearing, say my grandchildren.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -<li id="fn3"><p>I know there are many online music stores that sell lossless music, but ITMS has the largest catalog in the world, and for many titles I care about, ITMS is still the only place in this country where I can make legal digital purchases.<a class="footnotes-backlink" href="#fnref3">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2015-12-29-catches-when-installing-windows-7-with-boot-camp.html b/build/blog/2015-12-29-catches-when-installing-windows-7-with-boot-camp.html deleted file mode 100644 index 90071dc0..00000000 --- a/build/blog/2015-12-29-catches-when-installing-windows-7-with-boot-camp.html +++ /dev/null @@ -1,64 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-12-29T15:09:16-08:00" name="date"/> -<title>Catches when installing Windows 7 with Boot Camp</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Catches when installing Windows 7 with Boot Camp</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2015-12-29T15:09:16-08:00">December 29, 2015</time> -</div> -</header> -<p>I was looking for a use for my retired Mid-2012 Non-Retina MacBook Pro 13''<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a>, and unsurprisingly I figured that I would turn it into a OS X-Windows dual boot for some occasional gaming. I'm a CnC fan (not hardcore, but still), mainly for RA2/YR and TW/KW, and playing these inside Fusion is really a subsubpar experience. Due to the age of these games and their compatibility problems on Windows 8 and higher<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a>, I chose to shoot for a Windows 7 install.</p> -<p>Apple has a pretty thorough walkthrough in the support article <a href="https://support.apple.com/en-us/HT205016">Install Windows 7 and earlier on your Mac using Boot Camp</a>. There are, however, some catches that I would like to collect and share in this post.</p> -<ol style="list-style-type: decimal"> -<li><p>Win 7 ISO isn't available for download in the appropriate language (given your product key). This one sounds incredibly stupid... But it is a real problem at least for me and several others (just Google). I have a valid Win 7 Ultimate license from my institution, so I went to <a class="uri" href="https://www.microsoft.com/en-us/software-download/windows7">https://www.microsoft.com/en-us/software-download/windows7</a> to grab my ISO (just for fun; I already have the image). However, after verifying my product key, here's the list of languages that I'm asked to choose from, where English is apparently missing (!!!):</p> -<div class="figure"> -<a href="/img/20151229-win7-iso-language-choice.png" target="_blank"><img alt="da !@#$?" src="/img/20151229-win7-iso-language-choice.png" width="394"/></a> -<p class="caption">da !@#$?</p> -</div> -<p>I don't know the solution to this problem. In my case I've archived English Win 7 Ultimate SP1 images (both x86 and x64) before, so I just proceeded with my old image.</p></li> -<li><p>FileVault. It is my belief that FileVault needs to turned off before partitioning the drive with Boot Camp.<a class="footnoteRef" href="#fn3" id="fnref3"><sup>3</sup></a></p></li> -<li><p><em>An error occured while partitioning the disk.</em> That's the unhelpful message from Boot Camp. If you try to manually partition the drive with Disk Utility, you'll probably get a much more helpful message like <em>Partition failed with the error: couldn't modify partition map because file system verification failed</em>. Now the problem is obvious, and the solution is simple. Boot to single user mode and repair the filesystem with <code>/sbin/fsck -fy</code>, or safer, <code>/sbin/fsck -f</code> which might require interaction.</p></li> -<li><p>During Windows installation you'll obviously be prompted to choose a system partition at some point, and due to Boot Camp only formatting to FAT32, you'll get the message <em>Windows cannot be installed to this hard disk space. Windows must be installed to a partition formatted as NTFS.</em> This one is easy, just click "Drive options (advanced)" then "Format", which automatically formats the partition to NTFS. This is actually documented in Apple's walkthrough, but mortals do panic in face of error messages, so let's also note it here.</p></li> -<li><p>Even after formatting the Boot Camp partition, it is still possible to get the error <em>Setup was unable to create a new system partition or locate an existing system partition</em>. It this happens, check if you have any USB drives (other than the installation media) plugged in. In my case my Time Capsule was plugged in, and rebooting with it unplugged fixed the problem. The exact cause of the problem is unclear to me. Some say it's due to Master Boot Record limiting the number of partitions to four, but why the heck is my external drive counted towards that limitation? I'd go for Win 7 installer is just confused. Anyway, just unplug anything that's not needed during Windows installation.</p></li> -</ol> -<p>Hopefully you're good after solving the aforementioned problems. If you followed Apple's walkthrough correctly, Boot Camp's setup.exe will be invoked automatically immediately after Windows finishes installation, and after a certain number of reboots your drivers will be up and running. Now you're ready to take control of your Windows. Install Chrome<a class="footnoteRef" href="#fn4" id="fnref4"><sup>4</sup></a> and Microsoft Security Essentials immediately, then hop right into the Windows Update hell to patch your four-year-old system. Of course, Windows Update being Windows Update won't be smooth — servers will be crowded as ever and just checking for updates will likely take forever, let alone downloads. After a semi-infinite amount of time you'll get your estimates (I got 212 updates). Click update and let Windows Update grind for hours. And wish yourself a good luck (that no update errors will occur — luckily I didn't get any).</p> -<p>By the way, the otherwise great Apple trackpad is almost unusable on Boot Camp Windows under any setting. I'm forced to use a mouse.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>2.9 GHz i7 + Intel HD Graphics 4000 + 16 GB RAM + frigging slow 750 GB 5400-rpm spinning disk I've yet to replace.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>RA2/YR used to have problems even on Windows 7, at least inside Fusion, so I used to play them in XP SP3 VMs; I've yet to try them with Windows 7 running on bare metal.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -<li id="fn3"><p>I'm not completely sure that this is necessary. I was greeted with partitioning errors initially which I thought was due to FileVault, so I switched it off (the actual process is much longer than "switching it off", since the whole disk has to be decrypted and rewritten), but as you'll see later, the partitioning errors were at least partly due to a slightly corrupt filesystem.<a class="footnotes-backlink" href="#fnref3">↩︎</a></p></li> -<li id="fn4"><p>You can't even browse Microsoft's own websites with stock IE8. And IE11 is locked behind a hell lot of Windows Updates (even then it is crap). Doing Windows Update is like building up a tech tree.<a class="footnotes-backlink" href="#fnref4">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2016-01-01-virtualenvs-for-everyone.html b/build/blog/2016-01-01-virtualenvs-for-everyone.html deleted file mode 100644 index c1a32d75..00000000 --- a/build/blog/2016-01-01-virtualenvs-for-everyone.html +++ /dev/null @@ -1,100 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2016-01-01T22:21:14-08:00" name="date"/> -<title>Virtualenvs for everyone</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/highlight.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Virtualenvs for everyone</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2016-01-01T22:21:14-08:00">January 1, 2016</time> -</div> -</header> -<p>Python distutils for the most part is rather pleasant to work with. That is, pleasant until you've accumulated so many packages that you eventually run into a clash of namespace, or a dependency conflict (or dependency hell as most would affectionately call it).<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> In contrast, npm's approach to dependencies shuts out dependency hell completely, but it is so paranoid and costs so much duplication that I find it hard to appreciate unless necessary. Somewhere in between there's the virtualenv approach which I find most appealing for smallish projects — keep a single copy of each package in the dependency tree in a contained environment specific to the project at hand. This is how we debug Python projects, and it certainly also should be <em>the</em> way we run command line tools written in Python.</p> -<p>There's another reason I like virtualenvs. There are tons of problems associated with choosing between Python 2 and 3 — some projects are Python 2 only, some are instead Python 3, some claim to be compatible with both but actually present subtle problems when you use one instead of the other. However, without virtualenvs, there's only one <code>bin</code> — <code>/usr/local/bin</code> — and everything's competing for it. Most programs (especially ones with a typical <code>setup.py</code>) don't install a soft/hardlink with a helpful <code>2</code> or <code>3</code> suffix when installing executables, let alone detailed suffixes like <code>2.7</code> or <code>3.5</code>, so without probing into the shebangs you're never sure which version of Python you're running your program with, and as a result Python 2/3 (or even a point release)-specific bugs occur randomly. Virtualenvs solve the problem by allowing you to have as many bins (and includes, and libs) as you like.</p> -<p>Hence the title "virtualenvs for everyone". I would like to install each command line program written in Python into a separate virtualenv. The only issue is that apparently I don't want too many bins in my <code>$PATH</code>; to solve this issue, the executable bits of each project should be linked to a central place, for which I choose <code>$HOME/bin</code>. There could be as many symlinks as we like, so now we can have multiple links with increasing detailed version suffixes, e.g., <code>3</code>, <code>3.5</code>, <code>3.5.1</code>. Very nice.</p> -<p>This task could clearly be automated; the only slightly tricky bit is to programmatically figure out which scripts a project installs to <code>bin</code>. Luckily, for projects using <code>setuptools.setup</code>, we can simply spoof that function. Here's my <code>setuptools/__init__.py</code>:</p> -<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="co">#!/usr/bin/env python3</span> - -<span class="co">"""setuptools stubs.</span> - -<span class="co">Here we only stubbed the symbols in setuptools.__all__. Hopefully that's</span> -<span class="co">enough (actually I can't remember seeing any setup.py using more than</span> -<span class="co">setup and find_packages).</span> - -<span class="co">setup has been spoofed to print the names of scripts, console_scripts</span> -<span class="co">and gui_scripts defined in the arguments to setup. Some user-friendly</span> -<span class="co">messages are also printed to stderr.</span> - -<span class="co">"""</span> - -<span class="im">from</span> __future__ <span class="im">import</span> print_function - -<span class="im">import</span> re -<span class="im">import</span> sys -<span class="im">import</span> os - -__all__ <span class="op">=</span> [ - <span class="st">'setup'</span>, <span class="st">'Distribution'</span>, <span class="st">'Feature'</span>, <span class="st">'Command'</span>, <span class="st">'Extension'</span>, <span class="st">'Require'</span>, - <span class="st">'find_packages'</span> -] - -<span class="kw">def</span> setup(<span class="op">**</span>kwargs): - scripts <span class="op">=</span> [os.path.basename(script_path) - <span class="cf">for</span> script_path <span class="kw">in</span> kwargs.pop(<span class="st">'scripts'</span>, [])] - <span class="cf">if</span> scripts: - <span class="bu">print</span>(<span class="st">'scripts:</span><span class="ch">\n</span><span class="st"> - </span><span class="sc">%s</span><span class="st">'</span> <span class="op">%</span> <span class="st">'</span><span class="ch">\n</span><span class="st"> - '</span>.join(scripts), <span class="bu">file</span><span class="op">=</span>sys.stderr) - entry_points <span class="op">=</span> kwargs.pop(<span class="st">'entry_points'</span>, {}) - <span class="cf">for</span> entry_point <span class="kw">in</span> [<span class="st">'console_scripts'</span>, <span class="st">'gui_scripts'</span>]: - extra_scripts <span class="op">=</span> [re.split(<span class="st">'(\s|=)'</span>, spec.strip())[<span class="dv">0</span>] - <span class="cf">for</span> spec <span class="kw">in</span> entry_points.pop(entry_point, [])] - <span class="cf">if</span> extra_scripts: - <span class="bu">print</span>(<span class="st">'</span><span class="sc">%s</span><span class="st">:</span><span class="ch">\n</span><span class="st"> - </span><span class="sc">%s</span><span class="st">'</span> <span class="op">%</span> (entry_point, <span class="st">'</span><span class="ch">\n</span><span class="st"> - '</span>.join(extra_scripts)), - <span class="bu">file</span><span class="op">=</span>sys.stderr) - scripts.extend(extra_scripts) - <span class="bu">print</span>(<span class="st">'</span><span class="ch">\n</span><span class="st">'</span>.join(<span class="bu">sorted</span>(scripts))) - -<span class="kw">class</span> Distribution(<span class="bu">object</span>): <span class="cf">pass</span> -<span class="kw">class</span> Feature(<span class="bu">object</span>): <span class="cf">pass</span> -<span class="kw">class</span> Command(<span class="bu">object</span>): <span class="cf">pass</span> -<span class="kw">class</span> Extension(<span class="bu">object</span>): <span class="cf">pass</span> -<span class="kw">class</span> Require(<span class="bu">object</span>): <span class="cf">pass</span> -<span class="kw">def</span> find_packages(<span class="op">**</span>kwargs): <span class="cf">pass</span></code></pre></div> -<p>Now, let <code>$HERE</code> be the directory containing our fake <code>setuptools/</code>, and <code>$PROJECT_ROOT</code> be the project root directory containing <code>setup.py</code>. Run</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh"><span class="ot">PYTHONPATH=$HERE</span>:<span class="ot">$PYTHONPATH</span> python <span class="ot">$PROJECT_ROOT</span>/setup.py</code></pre></div> -<p>and bam! We get the names of all scripts on stdout.</p> -<p>My full automation scripts, including the Zsh main function <code>virtual-install</code>, can be found in <a href="https://github.com/zmwangx/prezto/tree/master/modules/python/functions"><code>modules/python/functions</code> in zmwangx/prezto</a>. I'm not including it here because it uses some custom helper, and it's just too long (200+ lines, but not very sophisticated). Happy virtualenving!</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>In rare cases, even installing a single package could land you in trouble. The classical example is installing the <code>readme</code> package on a case-insensitive filesystem (e.g., the default mode of HFS+). "Unfortunately" <a href="https://bugs.python.org/issue24633">this</a> has been fixed.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2016-01-14-the-dirtiest-mistakes-of-os-x.html b/build/blog/2016-01-14-the-dirtiest-mistakes-of-os-x.html deleted file mode 100644 index 4738d43c..00000000 --- a/build/blog/2016-01-14-the-dirtiest-mistakes-of-os-x.html +++ /dev/null @@ -1,55 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2016-01-14T01:02:52-08:00" name="date"/> -<title>The dirtiest mistakes of OS X</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">The dirtiest mistakes of OS X</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2016-01-14T01:02:52-08:00">January 14, 2016</time> -</div> -</header> -<p>I must have written about this elsewhere, but here are my top three:</p> -<ol style="list-style-type: decimal"> -<li><p><code>.DS_Store</code>. Finder litters faster than one could clean up.</p></li> -<li><p>HFS+ NFD*.<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> Heard of the cursed encoding <code>UTF8-MAC</code>? Pure Evil. Culprit of tons of garbled text issues (especially cross platform ones) and probably most length miscalculation issues. Even Apple's Terminal.app can't do NFD right. I wonder how Korean users navigate their filesystems in terminal.</p></li> -<li><p>Plist XML. It's XML, but even worse.</p></li> -</ol> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>NFD with an asterisk, i.e., not even NFD. According to Apple in <a href="https://developer.apple.com/library/mac/qa/qa1173/_index.html">an old Technical Q&A</a>,</p> -<blockquote> -<p>The terms used in this Q&A, precomposed and decomposed, roughly correspond to Unicode Normal Forms C and D, respectively. However, most volume formats do not follow the exact specification for these normal forms. For example, HFS Plus (Mac OS Extended) uses a variant of Normal Form D in which U+2000 through U+2FFF, U+F900 through U+FAFF, and U+2F800 through U+2FAFF are not decomposed (this avoids problems with round trip conversions from old Mac text encodings). It's likely that your volume format has similar oddities.</p> -</blockquote> -<p>They are conscious enough to call these oddities.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2016-01-18-me-too-comments-on-github.html b/build/blog/2016-01-18-me-too-comments-on-github.html deleted file mode 100644 index 09610702..00000000 --- a/build/blog/2016-01-18-me-too-comments-on-github.html +++ /dev/null @@ -1,54 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2016-01-18T16:36:40-08:00" name="date"/> -<title>Me-too comments on GitHub</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Me-too comments on GitHub</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2016-01-18T16:36:40-08:00">January 18, 2016</time> -</div> -</header> -<p>I frequently subscribe to issues on GitHub, be it bugs I want to see fixed or features I would like to see implemented. Then every once in a short while I get an email notification about one of those obnoxious "me too" or "+1" comments, by which I mean terse comments with little to no content other than "me too" or "+1" or some other variant bearing the same meaning.</p> -<p>Me-too comments under bug reports are the most untolerable. If you have more details regarding the issue (e.g., a more reliable reproducer) or insights into what's really going on, then by any means post them. On the other hand, if you can't provide anything helpful, then just keep your mouth shut, and quietly press "subscribe" if you would like to be kept posted. Posting a me-too comment adds nothing to the discussion, does not expedite the resolution a tiny bit, and only serves to annoy all parties involved.<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> As always, submit a patch if you're dissatisfied with the progress. Keep in mind that no one is obligated to fix bugs for you in FOSS.<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a></p> -<p>Me-too comments under feature requests are more understandable, though I genuinely doubt that two or three people requesting a feature instead of one would make a big difference. After all, the issue tracker is not a feature voting platform; most folks understand this and behave themselves, so "me-too demand" isn't even remotely accurate at reflecting demand.</p> -<p>Me-too folks: please stop being childish. If you have nothing to add, don't add anything (unless otherwise requested).</p> -<hr/> -<p><strong>01/20/2015 Update.</strong> I came accross <a href="https://github.com/dear-github/dear-github">dear-githuub/dear-github</a> just now, which was started a mere six days ago, and the <a href="https://github.com/dear-github/dear-github/blob/bc7a4f6bc78445905751061bf96f731edda14c25/README.md">open letter</a> of which also places +1 comments on its list of biggest problems on GitHub.</p> -<hr/> -<p><strong>03/10/2015 Update.</strong> GitHub is finally reacting. See <a href="https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments">Add Reactions to Pull Requests, Issues, and Comments</a>.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>There are exceptional cases.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>Here we're talking about the subset of FOSS that is also free as in beer.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2016-01-24-antivirus-app-on-mas-top-chart.html b/build/blog/2016-01-24-antivirus-app-on-mas-top-chart.html deleted file mode 100644 index 8ecb8101..00000000 --- a/build/blog/2016-01-24-antivirus-app-on-mas-top-chart.html +++ /dev/null @@ -1,84 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2016-01-24T18:43:28-08:00" name="date"/> -<title>Antivirus app on MAS top chart?</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Antivirus app on MAS top chart?</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2016-01-24T18:43:28-08:00">January 24, 2016</time> -</div> -</header> -<p>Today for whatever reason I clicked on MAS's "Top Charts" page, and was immediately in for a surprise. Next to our great friend 1Password is an app called "AntiVirus Sentinel Pro", which sells for $9.99:</p> -<div class="figure"> -<a href="/img/20160124-mas-top-paid.png" target="_blank"><img alt="AntiVirus Sentinel "Pro". These days many people like to end their apps' names with "Pro", even when there's nothing pro about them. This "Pro" app, for instance, comes from a developer whose three out of four apps matches the regex ^([A-Z](a-z)+ )+Pro$, and despite their names they are definitely geared towards uninformed newbies." src="/img/20160124-mas-top-paid.png"/></a> -<p class="caption">AntiVirus Sentinel "Pro". These days many people like to end their apps' names with "Pro", even when there's nothing pro about them. This "Pro" app, for instance, comes from a developer whose three out of four apps matches the regex <code>^([A-Z](a-z)+ )+Pro$</code>, and despite their names they are definitely geared towards uninformed newbies.</p> -</div> -<p>The first rule of using MAS (or any kind of app store, for that matter) is that you research MAS apps outside the MAS. So let's Google "AntiVirus Sentinel Pro"... First result: <a href="https://discussions.apple.com/thread/6749331">Apple Support forum thread</a> from late 2014, "Is AntiVirus Sentinel Pro legit? If not, how can I delete it?" Good question about any AV product. However, you'll immediately find it hilarious when you read on:</p> -<blockquote> -<p>I have purchased and downloaded AntiVirus Sentinel Pro for Macintosh with Yosemite OS. I have a bad feeling this application is useless and maybe even harmful. Anyone knows if it is safe to use it?</p> -</blockquote> -<p>Okay, so why did you purchase it in the first place? I guess clueless users like this one are in every MAS developer's wet dreams.</p> -<p>Let's continue with the Google search results. Second one is the iTunes preview link. Third one is a <a href="http://www.securityfocus.eu/www/sentinel-pro.html">YouTube video</a> (also linked from MAS) which seems to be the only online documentation this app's got. Judging from the video the interface seems to be done in Java or something... Never mind that. Fourth result is a <a href="http://www.mac-forums.com/os-x-operating-system/327356-antivirus-sentinel-pro.html">rather recent thread</a> (August 2015) from Mac Forums. Not this again:</p> -<blockquote> -<p>I am a new Mac user. Can somebody answer these questions? Somehow it appears I have installed AntiVirus Sentinel Pro. What is this? Is it a real software? Should I keep it or try to uninstall it?</p> -</blockquote> -<p>The fifth and sixth results are general OS X AV product reviews that don't even mention this app. The next three results are from MAS aggregation sites. The last result on the first page is the app's product page on MacUpdate (now apparently abandoned), with a shiny 0.5/5 stars (note the zero point) badge.</p> -<p>Now that we've finished the first page (and the results are not a bit reassuring), the question comes: where the heck is this app's home page? It's also not on the second page, actually. There's something interesting on the third (still no home page), that is <a href="https://twitter.com/claud_xiao/status/681981763938197504">this tweet</a>:</p> -<blockquote> -<p>$10 "AntiVirus Sentinel Pro" got top2 in US Mac App Store and top1 in 48 countries--but it's just ClamAV+AdwareMedic signs+3 bullshit signs.</p> -</blockquote> -<p>Hmm. You might want to read Thomas Reed's (known for The Safe Mac) responses from that thread.</p> -<p>Anyway, we were sidetracked. Back to the home page, actually this app does have one, but it's just <a href="http://www.securityfocus.eu/www/sentinel-pro.html">a single page</a>, which simply states some marketing bullshit and directs to MAS (where the same bullshit is repeated). Seriously? That's the best you can do for your "pro" app, especially a security-related one?</p> -<p>Back to MAS, the reviews are kind of jokes, too:</p> -<div class="figure"> -<a href="/img/20160124-antivirus-sentinel-pro-reviews.png" target="_blank"><img alt="Stupid reviews for stupid app." src="/img/20160124-antivirus-sentinel-pro-reviews.png"/></a> -<p class="caption">Stupid reviews for stupid app.</p> -</div> -<p>The first one begins with</p> -<blockquote> -<p>Just switched to Apple from Windows ... and researched anti-virus software.</p> -</blockquote> -<p>Don't really need to read further.</p> -<p>Second one, speaking of customer service:</p> -<blockquote> -<p>... it only took one email to him explaining my problem... had a patch up and ready on the app store to download within hours.</p> -</blockquote> -<p>This review is from October 2015. Since when was MAS so efficient? Why do I (and everyone else keeping tabs on Apple stuff) keep hearing stories like <a href="http://mjtsai.com/blog/2015/12/01/sketch-leaving-the-mac-app-store/">bug fix updates waiting for review after 59 days</a>?</p> -<p>The pattern goes on. By the way, how does this app keep track of all disk and network activity when itself is running in a sandbox? No idea (maybe I'm misunderstanding sandboxing).</p> -<p>In summary, even as an AV product, this one seems untrustworthy. Not to mention AV products on the Mac are generally superfluous if not harmful.<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> What people really need to learn is to practice safe browsing habits and to properly use content blockers, which AV product vendors and (intrusive-)ad-supported websites (that is most, commercial websites today) won't tell you because they would go out of business if they do.</p> -<p>And how this app got onto the top charts, that is a real mystery.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>Disclaimer: I personally have used ClamXav and AdwareMedic (which has since been bought by Malwarebytes) before to help my social-engineered friend (tech support scam, in case you ask). Just to scan their documents though. It is my belief that once you're pwned (even slightly), clean system reinstall is the only way to go, despite what AV products might tell you. In addition, I don't use AV products myself (except Microsoft Security Essentials on Windows); as a programmer I've had enough bad experience with AV blocking <em>my</em> programs back in the Windows days.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2016-01-26-dropbox-noteworthy-and-damned-skeuomorphism.html b/build/blog/2016-01-26-dropbox-noteworthy-and-damned-skeuomorphism.html deleted file mode 100644 index e630af98..00000000 --- a/build/blog/2016-01-26-dropbox-noteworthy-and-damned-skeuomorphism.html +++ /dev/null @@ -1,50 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2016-01-26T12:18:36-08:00" name="date"/> -<title>Dropbox, Noteworthy, and damned skeuomorphism</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Dropbox, Noteworthy, and damned skeuomorphism</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2016-01-26T12:18:36-08:00">January 26, 2016</time> -</div> -</header> -<p>I just opened a note in a PDF within Dropbox's iOS app (never done that before), and instead of readable text what I saw was basically spaghetti:</p> -<div class="figure"> -<a href="/img/20160126-dropbox-noteworthy.png" target="_blank"><img alt="A PDF note in Dropbox iOS. Noteworthy (scream). I know there's a typo, by the way." src="/img/20160126-dropbox-noteworthy.png" width="300"/></a> -<p class="caption">A PDF note in Dropbox iOS. Noteworthy (scream). I know there's a typo, by the way.</p> -</div> -<p>That font is unmistakably Noteworthy, the default font in Apple's Notes app in Mountain Lion, when Apple was still practicing the damned skeuomorphism. (In case you can't recall how it looked like, let me point you to <a href="http://arstechnica.com/apple/2012/07/os-x-10-8/7/#notes">the John Siracusa review</a> for screenshots.) Just like your coworker's average handwritten notes, it is hardly legible and takes tremendous effort just to decode, especially when clustered in a paragraph rather than a short one-liner. Compare that to the same note, legibly rendered in Helvetica in PDF Expert:</p> -<div class="figure"> -<a href="/img/20160126-pdf-expert-note.png" target="_blank"><img alt="The same note (typo corrected) in PDF Expert Mac." src="/img/20160126-pdf-expert-note.png" width="258"/></a> -<p class="caption">The same note (typo corrected) in PDF Expert Mac.</p> -</div> -<p>This is an example of sacrificing usability for design aesthetics (an old-fashioned one for that matter, and an abonimable one if you ask for my opinion). Hard to believe we can still see it in 2016, from an otherwise great developer that is Dropbox.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2016-03-06-google-chrome-keeps-getting-uglier.html b/build/blog/2016-03-06-google-chrome-keeps-getting-uglier.html deleted file mode 100644 index 81033a62..00000000 --- a/build/blog/2016-03-06-google-chrome-keeps-getting-uglier.html +++ /dev/null @@ -1,93 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2016-03-06T14:59:45-08:00" name="date"/> -<title>Google Chrome keeps getting uglier</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Google Chrome keeps getting uglier</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2016-03-06T14:59:45-08:00">March 6, 2016</time> -</div> -</header> -<p>I hate to say this, but the Google Chrome team keeps making poor design decisions to make it more and more ugly. I still remember the sad day when the kind of cool wrench button gave way to the utterly boring hamburger one. I also remember the sad day when the omnibox dropdown <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=276746">pointlessly went full width</a> (after more than two years, I still fail to see how it makes any sense, although my eyes have long grown used to it).<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> And I'm sure there are other stupid changes that I can't name at the moment.</p> -<p>Unfortunately, they just won't stop. <a href="http://googlechromereleases.blogspot.com/2016/03/stable-channel-update.html">Four days ago</a> stable 49.0.2623.75 came out with a flurry of horrible visual changes.</p> -<ol style="list-style-type: decimal"> -<li><p>The icon. For whatever reason I have the impression that I might have seen this a while ago, but let's just pretend it's brand new. The new app icon is the most outrageously flat icon I've even seen. Compare it to that of 48.0.2564.103<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a>:</p> -<div class="figure"> -<a href="/img/20160306-chrome-mac-48.0.2564.103-49.0.2623.75-icons-side-by-side.png" target="_blank"><img alt="Old and new app icons side by side. To the left, the 48.0.2564.103 icon; to the right, the 49.0.2623.75 icon." src="/img/20160306-chrome-mac-48.0.2564.103-49.0.2623.75-icons-side-by-side.png" width="512"/></a> -<p class="caption">Old and new app icons side by side. To the left, <a href="/img/20160306-chrome-mac-48.0.2564.103-icon.png">the 48.0.2564.103 icon</a>; to the right, <a href="/img/20160306-chrome-mac-49.0.2623.75-icon.png">the 49.0.2623.75 icon</a>.</p> -</div> -<p>And let's see them in action:</p> -<div class="figure"> -<a href="/img/20160306-chrome-mac-48.0.2564.103-49.0.2623.75-icons-side-by-side-in-dock.png" target="_blank"><img alt="Both icons in the dock, old one the left and new one on the right." src="/img/20160306-chrome-mac-48.0.2564.103-49.0.2623.75-icons-side-by-side-in-dock.png" width="560"/></a> -<p class="caption">Both icons in the dock, old one the left and new one on the right.</p> -</div> -<p>Apart from flatness (lack of any gloss found in almost all Apple icons, however flattened they are), see how the new icon is notably larger than the old one, and any other circular icons for that matter. Apparently, consistency and guidelines mean nothing to them.</p> -<p>I wonder why they made this change. Maybe for material design? I certainly don't want to see my Mac infested by material design, thank you. And maybe to keep the icon in line with their new Google branding? Indeed, just like <a href="https://web.archive.org/web/20160306221914/https://g-design.storage.googleapis.com/production/v5/assets/g-logo.png">the new Google logo</a> which did away with serifs, this one has no depth at all and is very childish.</p> -<p>It's a shame I can't just throw this icon out of my dock. Looks like in addition to iTunes now I have yet another icon to replace following each update, except this one updates much more often, and almost silently.</p></li> -<li><p>Downloads. I almost thought I was hacked when I opened the Downloads tab and saw</p> -<div class="figure"> -<a href="/img/20160306-chrome-mac-49.0.2623.75-downloads.png" target="_blank"><img alt="Downloads in 49.0.2623.75." src="/img/20160306-chrome-mac-49.0.2623.75-downloads.png" width="848"/></a> -<p class="caption">Downloads in 49.0.2623.75.</p> -</div> -<p>instead of a nice and clean</p> -<div class="figure"> -<a href="/img/20160306-chrome-mac-48.0.2564.103-downloads.png" target="_blank"><img alt="Downloads in 48.0.2564.103." src="/img/20160306-chrome-mac-48.0.2564.103-downloads.png" width="728"/></a> -<p class="caption">Downloads in 48.0.2564.103.</p> -</div> -<p>Materail design infestation, apparently. Funny how they managed to convey less info in a LOT more space, and look horrible at the same time. At least they can choose a pleasant color palette if they want to use color (which is totally unnecessary as seen from the old design)? No, they can't.</p></li> -<li><p>Incognito mode. There's a reason why books are printed on light-colored paper, and there's a reason why the web is predominantly light-backgrounded, including user agent default style sheets. The old incognito follows the light background rule, plus a non-intrusive notice in the middle and a reasonably shaded tab bar to indicate incognito status:</p> -<div class="figure"> -<a href="/img/20160306-chrome-mac-48.0.2564.103-incognito.png" target="_blank"><img alt="Incognito window in 48.0.2564.103." src="/img/20160306-chrome-mac-48.0.2564.103-incognito.png" width="893"/></a> -<p class="caption">Incognito window in 48.0.2564.103.</p> -</div> -<p>But not anymore. Since those of you using Incognito mode must be conducting shady business, why not highlight that with a black background:</p> -<div class="figure"> -<a href="/img/20160306-chrome-mac-49.0.2623.75-incognito.png" target="_blank"><img alt="Incognito window in 49.0.2623.75. Even more shocking if you maximize your browser windows." src="/img/20160306-chrome-mac-49.0.2623.75-incognito.png" width="625"/></a> -<p class="caption">Incognito window in 49.0.2623.75. Even more shocking if you maximize your browser windows.</p> -</div> -<p>Oh. My. God. Now I hesitate whenever I want to press ⇧⌘N; it's just too great a cultural shock for me to handle.</p></li> -</ol> -<p>Those are just three changes I've discovered so far. Hopefully there are no more lurking surprises.</p> -<p>Conclusion? Sigh.</p> -<hr/> -<p><strong>03/09/2016 update</strong>. They also broke showing/hiding extension buttons (from toolbar) recently, probably in the same update. We used to be able to reshow a hidden button from <code>chrome://extensions</code>; that's no longer possible. Now we need to click on the hamburger (great), right click on one of the hidden buttons — which temporarily promotes the button to the toolbar and display the context menu, and while the context menu is still on, click on "Keep in Toolbar". So intuitive, your average computer users are definitely going to figure that out by themselves. Very nice.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>Dev left a <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=276746#c28">comment</a> when marking that issue as wont fix:</p> -<blockquote> -<p>... The current look is a precursor to a family of related work to make the Omnibox better, so expect to see more investment in this space to come. ...</p> -</blockquote> -<p>A family of related work? After 2.5 years the omnibox looks almost exactly the same as the screenshot in the issue. More to come my ass. Maybe I should be grateful, at least it didn't get worse.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>I realized the last stable was 48.0.2564.109 instead of 48.0.2564.103 only after taking the screenshots. Doesn't matter anyway.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2016-04-10-emacss-got-a-redesigned-website.html b/build/blog/2016-04-10-emacss-got-a-redesigned-website.html deleted file mode 100644 index fdc802c6..00000000 --- a/build/blog/2016-04-10-emacss-got-a-redesigned-website.html +++ /dev/null @@ -1,56 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2016-04-10T03:04:19-07:00" name="date"/> -<title>Emacs's got a redesigned website!</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Emacs's got a redesigned website!</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2016-04-10T03:04:19-07:00">April 10, 2016</time> -</div> -</header> -<p>I've been very busy lately, so I haven't posted anything for a month. As a result, I have many topic notes sitting in Notes.app — including the kik-left-pad-npm drama, the Text Expander outcry, and such — waiting to be organized and written up (I'll probably never write them up in the end, since these days it's very weird to write an opinion piece about an event whose attention span has already lapsed).</p> -<p>Anyway, this will be a short post about Emacs's <a href="https://gnu.org/software/emacs/">redesigned website</a>. See screenshot at the end. Apparently this was <a href="https://twitter.com/NicolasPetton/status/714854524108800000">last week's news</a>, but there's little interest in Emacs in general, so the news only reached me two days ago, sort of by chance.</p> -<p>According my impression, Emacs has been the underdog for quite some time. First, when you compare to vi/Vim, hard stats shed light on popularity: there are way more VimL repos than Elisp ones on GitHub.<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> Also, there are more exciting (or at least exciting-sounding or excitement-inducing) things happening in the Vim realm, e.g. Neovim, but not so much in the Emacs kingdom (excuse me if I missed something big). I'm actually very curious how Vim sold itself to so many people. I, for one, can't tolerate the Esc key at all (yes, I know basic editing in Vim, and I know the various workarounds to Esc, some of them reasonable and some not). I can't understand how people could laugh at Escape Meta Alt Control Shift — oh, I never used Esc in Emacs once, by the way — when the single most awkward Esc key serves a fundamental purpose by default in their own beloved editor. The Esc key is of course not my only gripe with Vim, nor the biggest; I'll however stop here to avoid turing this post into a complaint about Vim. Apart from Vim, Emacs is also being sidelined by more modern GUI-based text editors like Atom,<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a> or various IDEs. Atom <a href="http://blog.atom.io/2016/03/28/atom-reaches-1m-users.html">recently</a> reached one million monthly active users. I actually like certain parts of Atom a lot, e.g. the project navigation sidebar,<a class="footnoteRef" href="#fn3" id="fnref3"><sup>3</sup></a> but I simply can't give up my good ol' tty.</p> -<p>Personal preferences aside, I think Emacs does need a bit more publicity to draw a few more users. Whether redesigning the website will help at all I don't know; maybe the effect will be statistically indistinguishable from zero, but the bottom line is that people like pretty websites, so why not. The redesigned homepage is a bit more graphics-heavy, but it currently weighs a total of 521.33KB — within the tolerable range.</p> -<p>The most interesting thing I found on the redesigned homepage is the link to <a href="http://emacsrocks.com">emacsrocks.com</a>. I aimlessly clicked on the last episode — <a href="http://emacsrocks.com/e15.html">episode 15</a> — just to see what it was like, and ended up astonished. The episode is about <a href="https://github.com/pashky/restclient.el"><code>restclient.el</code></a>, which turned out to be wicked cool. In the real world it's probably a little bit too geeky to my liking, and I use the more mundane (and more powerful) <a href="https://luckymarmot.com/paw">Paw</a> as my REST client, but I can't stop admiring the beauty of <code>restclient-mode</code>. I'll definitely find time to watch all episodes of Emacs Rocks, and you probably should, too.</p> -<div class="figure"> -<a href="/img/20160409-emacs-website-screenshot-half-size.png" target="_blank"><img alt="A scaled down screenshot of the redesigned gnu.org/software/emacs. Full screenshot on my 2880x1800 MBP is here. Actually I lied a bit — the screenshots were taken with pageres, so I could have specified any resolution." src="/img/20160409-emacs-website-screenshot-half-size.png" width="720"/></a> -<p class="caption">A scaled down screenshot of the redesigned <a href="https://gnu.org/software/emacs/">gnu.org/software/emacs</a>. Full screenshot on my 2880x1800 MBP is <a href="/img/20160409-emacs-website-screenshot.png">here</a>. Actually I lied a bit — the screenshots were taken with <a href="https://github.com/sindresorhus/pageres"><code>pageres</code></a>, so I could have specified any resolution.</p> -</div> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>According to <a href="http://githut.info/">GitHut</a>, in 2014 Q4, there were 22,450 VimL and 9,978 Elisp repositories on GitHub, respectively. And according to a real time search I did just now, the <a href="https://github.com/search?q=language%3AVimL">VimL number</a> has risen to 82,519 and the <a href="https://github.com/search?q=language%3AElisp">Elisp number</a> to 30,320. The ratio has risen from 2.25:1 to 2.72:1. To add insult to injury, on GitHub's <a href="https://github.com/search/advanced">advanced search page</a>, GitHub lists VimL in the "Popular" language section and Elisp in "Everything else". Hurt feelings anyone?<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>Of course Emacs can operate in standalone GUI mode (or more precisely, window system mode), and more can be done in GUI mode (both in terms of customizability and functinality). However, in my early days with Emacs I found the GUI look like crap — the default always does, even to this day. I can never bring myself to use anything crappy-looking, unless I've got no choice, so I went with the TUI. Later I learned how to make the GUI habitable (still not as nice as the uniformity I find in tty, though), but by that time I'm already totally in love with tty mode and probably will never switch.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -<li id="fn3"><p>In Emacs I have ido, fiplr and sr-speedbar to help with navigation, but this is one area where a graphical sidebar really shines.<a class="footnotes-backlink" href="#fnref3">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2016-05-07-chrome-is-screwing-with-our-extensions-again.html b/build/blog/2016-05-07-chrome-is-screwing-with-our-extensions-again.html deleted file mode 100644 index 0344aadd..00000000 --- a/build/blog/2016-05-07-chrome-is-screwing-with-our-extensions-again.html +++ /dev/null @@ -1,63 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2016-05-07T18:49:26-07:00" name="date"/> -<title>Chrome is screwing with our extensions... Again</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Chrome is screwing with our extensions... Again</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2016-05-07T18:49:26-07:00">May 7, 2016</time> -</div> -</header> -<p>Chrome is growing more and more hostile by the day. See <a href="/blog/2016-03-06-google-chrome-keeps-getting-uglier.html">Google Chrome keeps getting uglier</a> for an earlier take. What I didn't report in the earlier post is that not only can't you show/hide extension buttons as easily as before, you can't even control which buttons appear in the toolbar anymore — they come and go as they wish.</p> -<p>As if screwing the app icon, extension buttons and the overall design is not enough, now they have upped their game again. I'm running Chrome 50.0.2661.94 from April 28, and I just rebooted my machine only to be greeted with a fleeting "unsupported extensions" (or something like that) message as I launched Chrome. I digged into the extensions page, and guess what, all sideloaded extensions (except unpacked ones) have been disabled.<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> This in itself may not be too surprising (Google took away sideloaded extensions from non-developers last year), except that <strong>the "enable" button, which used to work at least in developer mode, doesn't function anymore.</strong> The message is very stupid:</p> -<blockquote> -<p>This extension is not listed in the Chrome Web Store and <strong>may</strong> have been added without your knowledge.</p> -</blockquote> -<p>Bold by me. Okay, so what if they have been added <strong>with my knowledge</strong>? No way to enable legit extensions (some written by none other than myself) just because of a "may"? Here's the <a href="https://support.google.com/chrome/answer/2811969">only migration path</a> they offer, by the way:</p> -<blockquote> -<p>If you need to use a disabled extension, you can contact the extension's developer and ask them to upload their extension to the Chrome Web Store.</p> -</blockquote> -<p>Seriously? Do they honestly think Chrome Web Store serves everyone's needs? First, they have every right to refuse or take down any extension in their store. This is dangerous. What if one day they conclude that Adblock Plus is hurting their ad revenue too much and decide to take it down? Secondly, people may not want to make every extension publicly available. For instance, I have some personal extensions that I have developed on my dev machine, packaged into .crx, and installed on other machines. Some of these are publicly available (on GitHub), and others are not. It's not hard to conclude that other people may have private extensions too, and there may be extensions that are only available in some private circles. Now, people have to load unpacked extensions, which is much easier to screw up for regular folks, or they're out of luck.</p> -<p>To add insult to injury, every time I launch Chrome now, I'm greeted by this "Disable Developer Mode Extensions" message:</p> -<blockquote> -<p>Extensions running in developer mode can harm your computer. If you're not a developer, you should disable these extensions running in developer mode to stay safe.</p> -</blockquote> -<p>As if there're not enough malicious extensions in the Chrome Web Store, let alone crap. May I tell Chrome that I <em>am</em> a developer and ask it to shut up? Apparently no.</p> -<p>With the current trend in Chrome, I might want to switch to Opera again.<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a> The only thing preventing me from doing so right now is their new <a href="https://i.imgur.com/F8Tc67m.png">horrendous-looking fat icon</a>. However, Chrome has also destroyed their icon and I need to <a href="https://github.com/zmwangx/fileicon">replace it</a> after every update anyway, so I might as well do the same thing for Opera. We'll see.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>I'm not sure why they weren't disabled upon first launch after the update, but given the randomness of extension buttons in my toolbar with hardly any action on my part, I won't be surprised if I were told that they had messed up the extension system completely.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>Modern day Safari is also pretty nice, and the team is showing great attitude lately, with Safari Technology Preview and tweets like <a href="https://twitter.com/webkit/status/725725657548738561">this one</a>, for instance. However, the lack of extensions is a big road block, and the fact that the used-to-be-free Safari Developer Program has been incorporated into the $99/yr Apple Developer Program certainly doesn't help. (I used to be a member. Now I've been kicked out.)</p> -<p>Note that Safari is more locked down in a sense compared to OS X and iOS. On OS X you can apparently run unsigned software; on iOS 9 and later you can create personal provisioning profiles with just an Apple ID. Neither is true for Safari extensions, which still require a signing key from developer program membership. I wonder if Apple will introduce free keys for personal use on Safari, too.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2016-06-24-its-2016-and-microsoft-is-the-only-legit-player-who-spams-me-without-unsubscribe-links.html b/build/blog/2016-06-24-its-2016-and-microsoft-is-the-only-legit-player-who-spams-me-without-unsubscribe-links.html deleted file mode 100644 index e9dfbc86..00000000 --- a/build/blog/2016-06-24-its-2016-and-microsoft-is-the-only-legit-player-who-spams-me-without-unsubscribe-links.html +++ /dev/null @@ -1,47 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2016-06-24T05:40:01+08:00" name="date"/> -<title>It's 2016, and Microsoft is the only legit player who spams me without unsubscribe links</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">It's 2016, and Microsoft is the only legit player who spams me without unsubscribe links</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2016-06-24T05:40:01+08:00">June 24, 2016</time> -</div> -</header> -<p>I'm so tired of Microsoft spam. Microsoft is known for being intrusive accross the board, and their newsletters are no different: I literally can't name one legit company in this day and age who doesn't put unsubscribe links in newsletters.<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a> I get "Azure pricing and services updates" newsletters all the time, as well as "exciting news" from Windows Insider Program (which doesn't excite me at all) every once in a short while.<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a> I still occasionally receive random Chinese language promotions of Windows, presumably because I used a Windows Phone as my secondary phone for three months back home in the summer of 2013 (which was a horrible experience). Why Microsoft hasn't been regulated for spam yet, I do not know.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>To be fair, Amazon used to force promotional email on student members, but (if memory serves) I haven't seen one in ages.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>"If you wish to stop receiving Windows Insider Program emails, you will need to leave the program." I guess that's the price of downloading a couple of Windows 10 insider builds.<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2016-09-01-this-blog-is-now-behind-cloudflare.html b/build/blog/2016-09-01-this-blog-is-now-behind-cloudflare.html deleted file mode 100644 index 9f87bab9..00000000 --- a/build/blog/2016-09-01-this-blog-is-now-behind-cloudflare.html +++ /dev/null @@ -1,54 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2016-09-01T20:11:00+08:00" name="date"/> -<title>This blog is now behind CloudFlare</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">This blog is now behind CloudFlare</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2016-09-01T20:11:00+08:00">September 1, 2016</time> -</div> -</header> -<p>Back in July I registered the domain <a href="http://zhimingwang.org">zhimingwang.org</a> and pointed this GitHub Pages-powered blog at it. Since then I have lost the HTTPS badge due to GitHub Pages not supporting HTTPS on custom domains (see <a href="https://github.com/isaacs/github/issues/156">isaacs/github#156</a>).</p> -<p>There have been a lot of discussions on isaacs/github#156 (and stupid <a href="/blog/2016-01-18-me-too-comments-on-github.html">+1's</a> too). Among the proposed solutions is putting the website behind CloudFlare. I carefully investigated <a href="https://blog.cloudflare.com/secure-and-fast-github-pages-with-cloudflare/">this option</a> and read almost all the arguments against it. I fully understand CloudFlare's SSL models (summarized in the image below), and I do realize most if not all of the limitations of CloudFlare, including CloudFlare being a huge MITM (which is inevitable for a CDN anyway), as well as most if not all of its annoyances, including CAPTCHAs which I myself would occasionally run into when I'm browsing with PIA VPN, and JavaScript-based browser checks.</p> -<div class="figure"> -<a href="/img/20160901-cloudflare-ssl-modes.png" target="_blank"><img alt="CloudFlare's SSL modes. I use the Full SSL mode so that both ends of the connection are encrypted. Again, I know CloudFlare is a big MITM and could be a high profile target. Credit: CloudFlare." src="/img/20160901-cloudflare-ssl-modes.png" width="500"/></a> -<p class="caption">CloudFlare's SSL modes. I use the Full SSL mode so that both ends of the connection are encrypted. Again, I know CloudFlare is a big MITM and could be a high profile target. Credit: <a href="https://blog.cloudflare.com/secure-and-fast-github-pages-with-cloudflare/">CloudFlare</a>.</p> -</div> -<p>After careful evaluation, I decided that CloudFlare's SSL model is good enough for me. After all, this is just a damn blog, with nothing sensitive. TLS is still nice because it guards against prying eyes and unethical ad-injecting ISPs or Wi-Fi hotspots, but other than that, it isn't necessary.</p> -<p>End result: this blog is now behind CloudFlare. Readers should now see that green HTTPS badge again (note that I'm enforcing HTTPS — without HSTS though). As for CAPTCHAs, I have adjusted the firewall settings on CloudFlare's dashboard — "Security Level" to "Essentially Off" and "Challenge Passage" to 1 year, so hopefully it won't be too annoying.<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a></p> -<p><strong>09/01/2016 Update.</strong> I just realized that <a href="https://support.cloudflare.com/hc/en-us/articles/203306930-Does-CloudFlare-block-Tor-">CloudFlare supports whitelisting Tor traffic</a>. Did that.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>I don't use Tor, and don't intend to raise Big Brother's suspicion by using it, so I have no idea of the actual Tor experience.<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/2016-10-26-pyenv-compiling-python-with-sqlite-in-nonstandard-location.html b/build/blog/2016-10-26-pyenv-compiling-python-with-sqlite-in-nonstandard-location.html deleted file mode 100644 index 0a1fab47..00000000 --- a/build/blog/2016-10-26-pyenv-compiling-python-with-sqlite-in-nonstandard-location.html +++ /dev/null @@ -1,68 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2016-10-26T12:16:22-04:00" name="date"/> -<title>pyenv: compiling Python with SQLite in nonstandard location</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/highlight.css" media="all" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">pyenv: compiling Python with SQLite in nonstandard location</h1> -<div class="article-metadata"> -<time class="article-timestamp" datetime="2016-10-26T12:16:22-04:00">October 26, 2016</time> -</div> -</header> -<p>This is a quick post sharing a workaround that I needed just now.</p> -<p>I was trying to compile Pythons with pyenv on a RHEL 6.8 cluster. Unfortunately <code>sqlite-devel</code> is not installed and I doubt I can convince my sysadmin to install a package for me. The lack of SQLite headers resulted in Pythons without <code>_sqlite3</code> which is essential for me. Hinting at SQLite headers from Linuxbrew with <code>CPATH</code> did not help either.</p> -<p>Digging into CPython source code, turns out that CPython only looks into <a href="https://github.com/python/cpython/blob/59fa72e34da71fb24f52251c1cc88ed3c3b14797/setup.py#L1132-L1138">a fixed set of paths</a>:</p> -<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python">sqlite_inc_paths <span class="op">=</span> [ <span class="st">'/usr/include'</span>, - <span class="st">'/usr/include/sqlite'</span>, - <span class="st">'/usr/include/sqlite3'</span>, - <span class="st">'/usr/local/include'</span>, - <span class="st">'/usr/local/include/sqlite'</span>, - <span class="st">'/usr/local/include/sqlite3'</span>, - ] -<span class="cf">if</span> cross_compiling: - sqlite_inc_paths <span class="op">=</span> []</code></pre></div> -<p>Well that's unfortunate. Luckily pyenv makes it really easy to patch Python source code; take a look at <a href="https://github.com/yyuu/pyenv/tree/master/plugins/python-build/share/python-build/patches"><code>plugins/python-build/share/python-build/patches</code></a> and you'll get the idea. Therefore, in the case of Linuxbrew'ed pyenv and SQLite, say we want to build Python 3.5.2 with SQLite support, we simply put the following patch at <code>~/.linuxbrew/opt/pyenv/plugins/python-build/share/python-build/patches/3.5.2/Python-3.5.2/linuxbrew-sqlite3.patch</code>:</p> -<div class="sourceCode"><pre class="sourceCode diff"><code class="sourceCode diff"><span class="kw">diff --git a/setup.py b/setup.py</span> -index 174ce72..774fd65 100644 -<span class="dt">--- a/setup.py</span> -+++ b/setup.py -@@ -1108,6 +1108,7 @@ class PyBuildExt(build_ext): - '/usr/local/include', - '/usr/local/include/sqlite', - '/usr/local/include/sqlite3', -+ os.path.expanduser('~/.linuxbrew/opt/sqlite/include/'), - ] - if cross_compiling: - sqlite_inc_paths = []</code></pre></div> -<p>That's it. Now</p> -<pre><code>$ pyenv install 3.5.2</code></pre> -<p>and enjoy.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/blog/index.html b/build/blog/index.html deleted file mode 100644 index 06f0a47b..00000000 --- a/build/blog/index.html +++ /dev/null @@ -1,11 +0,0 @@ -<!DOCTYPE html> -<html> -<head> - <meta charset="UTF-8"/> - <meta http-equiv="refresh" content="0; url=/#toc"/> - <title>dl? cmplnts?</title> -</head> -<body> - <p>Redirecting to <a href="/#toc">/#toc</a>...</p> -</body> -</html> diff --git a/build/css/highlight.css b/build/css/highlight.css deleted file mode 100644 index 665dea4f..00000000 --- a/build/css/highlight.css +++ /dev/null @@ -1,35 +0,0 @@ -/* Based on Pandoc's Pygments color theme */ -table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode { - margin: 0; padding: 0; vertical-align: baseline; border: none; } -table.sourceCode { width: 100%; line-height: 100%; } -td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; } -td.sourceCode { padding-left: 5px; } -code > span.kw { color: #007020; font-weight: bold; } /* Keyword */ -code > span.dt { color: #902000; } /* DataType */ -code > span.dv { color: #40a070; } /* DecVal */ -code > span.bn { color: #40a070; } /* BaseN */ -code > span.fl { color: #40a070; } /* Float */ -code > span.ch { color: #4070a0; } /* Char */ -code > span.st { color: #4070a0; } /* String */ -code > span.co { color: #60a0b0; font-style: italic; } /* Comment */ -code > span.ot { color: #007020; } /* Other */ -code > span.al { color: #ff0000; font-weight: bold; } /* Alert */ -code > span.fu { color: #06287e; } /* Function */ -code > span.er { color: #ff0000; font-weight: bold; } /* Error */ -code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */ -code > span.cn { color: #880000; } /* Constant */ -code > span.sc { color: #4070a0; } /* SpecialChar */ -code > span.vs { color: #4070a0; } /* VerbatimString */ -code > span.ss { color: #bb6688; } /* SpecialString */ -code > span.im { color: #007020; font-weight: bold; } /* Import */ -code > span.va { color: #19177c; } /* Variable */ -code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */ -code > span.op { color: #666666; } /* Operator */ -code > span.bu { } /* BuiltIn */ -code > span.ex { } /* Extension */ -code > span.pp { color: #bc7a00; } /* Preprocessor */ -code > span.at { color: #7d9029; } /* Attribute */ -code > span.do { color: #ba2121; font-style: italic; } /* Documentation */ -code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */ -code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */ -code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */ diff --git a/build/css/normalize.css b/build/css/normalize.css deleted file mode 100644 index 5250b745..00000000 --- a/build/css/normalize.css +++ /dev/null @@ -1,422 +0,0 @@ -/*! normalize.css v4.2.0 | MIT License | github.com/necolas/normalize.css */ - -/** - * 1. Change the default font family in all browsers (opinionated). - * 2. Correct the line height in all browsers. - * 3. Prevent adjustments of font size after orientation changes in IE and iOS. - */ - -html { - font-family: sans-serif; /* 1 */ - line-height: 1.15; /* 2 */ - -ms-text-size-adjust: 100%; /* 3 */ - -webkit-text-size-adjust: 100%; /* 3 */ -} - -/** - * Remove the margin in all browsers (opinionated). - */ - -body { - margin: 0; -} - -/* HTML5 display definitions - ========================================================================== */ - -/** - * Add the correct display in IE 9-. - * 1. Add the correct display in Edge, IE, and Firefox. - * 2. Add the correct display in IE. - */ - -article, -aside, -details, /* 1 */ -figcaption, -figure, -footer, -header, -main, /* 2 */ -menu, -nav, -section, -summary { /* 1 */ - display: block; -} - -/** - * Add the correct display in IE 9-. - */ - -audio, -canvas, -progress, -video { - display: inline-block; -} - -/** - * Add the correct display in iOS 4-7. - */ - -audio:not([controls]) { - display: none; - height: 0; -} - -/** - * Add the correct vertical alignment in Chrome, Firefox, and Opera. - */ - -progress { - vertical-align: baseline; -} - -/** - * Add the correct display in IE 10-. - * 1. Add the correct display in IE. - */ - -template, /* 1 */ -[hidden] { - display: none; -} - -/* Links - ========================================================================== */ - -/** - * 1. Remove the gray background on active links in IE 10. - * 2. Remove gaps in links underline in iOS 8+ and Safari 8+. - */ - -a { - background-color: transparent; /* 1 */ - -webkit-text-decoration-skip: objects; /* 2 */ -} - -/** - * Remove the outline on focused links when they are also active or hovered - * in all browsers (opinionated). - */ - -a:active, -a:hover { - outline-width: 0; -} - -/* Text-level semantics - ========================================================================== */ - -/** - * 1. Remove the bottom border in Firefox 39-. - * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. - */ - -abbr[title] { - border-bottom: none; /* 1 */ - text-decoration: underline; /* 2 */ - text-decoration: underline dotted; /* 2 */ -} - -/** - * Prevent the duplicate application of `bolder` by the next rule in Safari 6. - */ - -b, -strong { - font-weight: inherit; -} - -/** - * Add the correct font weight in Chrome, Edge, and Safari. - */ - -b, -strong { - font-weight: bolder; -} - -/** - * Add the correct font style in Android 4.3-. - */ - -dfn { - font-style: italic; -} - -/** - * Correct the font size and margin on `h1` elements within `section` and - * `article` contexts in Chrome, Firefox, and Safari. - */ - -h1 { - font-size: 2em; - margin: 0.67em 0; -} - -/** - * Add the correct background and color in IE 9-. - */ - -mark { - background-color: #ff0; - color: #000; -} - -/** - * Add the correct font size in all browsers. - */ - -small { - font-size: 80%; -} - -/** - * Prevent `sub` and `sup` elements from affecting the line height in - * all browsers. - */ - -sub, -sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} - -sub { - bottom: -0.25em; -} - -sup { - top: -0.5em; -} - -/* Embedded content - ========================================================================== */ - -/** - * Remove the border on images inside links in IE 10-. - */ - -img { - border-style: none; -} - -/** - * Hide the overflow in IE. - */ - -svg:not(:root) { - overflow: hidden; -} - -/* Grouping content - ========================================================================== */ - -/** - * 1. Correct the inheritance and scaling of font size in all browsers. - * 2. Correct the odd `em` font sizing in all browsers. - */ - -code, -kbd, -pre, -samp { - font-family: monospace, monospace; /* 1 */ - font-size: 1em; /* 2 */ -} - -/** - * Add the correct margin in IE 8. - */ - -figure { - margin: 1em 40px; -} - -/** - * 1. Add the correct box sizing in Firefox. - * 2. Show the overflow in Edge and IE. - */ - -hr { - box-sizing: content-box; /* 1 */ - height: 0; /* 1 */ - overflow: visible; /* 2 */ -} - -/* Forms - ========================================================================== */ - -/** - * 1. Change font properties to `inherit` in all browsers (opinionated). - * 2. Remove the margin in Firefox and Safari. - */ - -button, -input, -optgroup, -select, -textarea { - font: inherit; /* 1 */ - margin: 0; /* 2 */ -} - -/** - * Restore the font weight unset by the previous rule. - */ - -optgroup { - font-weight: bold; -} - -/** - * Show the overflow in IE. - * 1. Show the overflow in Edge. - */ - -button, -input { /* 1 */ - overflow: visible; -} - -/** - * Remove the inheritance of text transform in Edge, Firefox, and IE. - * 1. Remove the inheritance of text transform in Firefox. - */ - -button, -select { /* 1 */ - text-transform: none; -} - -/** - * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` - * controls in Android 4. - * 2. Correct the inability to style clickable types in iOS and Safari. - */ - -button, -html [type="button"], /* 1 */ -[type="reset"], -[type="submit"] { - -webkit-appearance: button; /* 2 */ -} - -/** - * Remove the inner border and padding in Firefox. - */ - -button::-moz-focus-inner, -[type="button"]::-moz-focus-inner, -[type="reset"]::-moz-focus-inner, -[type="submit"]::-moz-focus-inner { - border-style: none; - padding: 0; -} - -/** - * Restore the focus styles unset by the previous rule. - */ - -button:-moz-focusring, -[type="button"]:-moz-focusring, -[type="reset"]:-moz-focusring, -[type="submit"]:-moz-focusring { - outline: 1px dotted ButtonText; -} - -/** - * Change the border, margin, and padding in all browsers (opinionated). - */ - -fieldset { - border: 1px solid #c0c0c0; - margin: 0 2px; - padding: 0.35em 0.625em 0.75em; -} - -/** - * 1. Correct the text wrapping in Edge and IE. - * 2. Correct the color inheritance from `fieldset` elements in IE. - * 3. Remove the padding so developers are not caught out when they zero out - * `fieldset` elements in all browsers. - */ - -legend { - box-sizing: border-box; /* 1 */ - color: inherit; /* 2 */ - display: table; /* 1 */ - max-width: 100%; /* 1 */ - padding: 0; /* 3 */ - white-space: normal; /* 1 */ -} - -/** - * Remove the default vertical scrollbar in IE. - */ - -textarea { - overflow: auto; -} - -/** - * 1. Add the correct box sizing in IE 10-. - * 2. Remove the padding in IE 10-. - */ - -[type="checkbox"], -[type="radio"] { - box-sizing: border-box; /* 1 */ - padding: 0; /* 2 */ -} - -/** - * Correct the cursor style of increment and decrement buttons in Chrome. - */ - -[type="number"]::-webkit-inner-spin-button, -[type="number"]::-webkit-outer-spin-button { - height: auto; -} - -/** - * 1. Correct the odd appearance in Chrome and Safari. - * 2. Correct the outline style in Safari. - */ - -[type="search"] { - -webkit-appearance: textfield; /* 1 */ - outline-offset: -2px; /* 2 */ -} - -/** - * Remove the inner padding and cancel buttons in Chrome and Safari on OS X. - */ - -[type="search"]::-webkit-search-cancel-button, -[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; -} - -/** - * Correct the text style of placeholders in Chrome, Edge, and Safari. - */ - -::-webkit-input-placeholder { - color: inherit; - opacity: 0.54; -} - -/** - * 1. Correct the inability to style clickable types in iOS and Safari. - * 2. Change font properties to `inherit` in Safari. - */ - -::-webkit-file-upload-button { - -webkit-appearance: button; /* 1 */ - font: inherit; /* 2 */ -} diff --git a/build/css/normalize.min.css b/build/css/normalize.min.css deleted file mode 100644 index c23c8f8f..00000000 --- a/build/css/normalize.min.css +++ /dev/null @@ -1 +0,0 @@ -/*! normalize.css v4.2.0 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block}audio:not([controls]){display:none;height:0}progress{vertical-align:baseline}template,[hidden]{display:none}a{background-color:transparent;-webkit-text-decoration-skip:objects}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:0;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:inherit}b,strong{font-weight:bolder}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}svg:not(:root){overflow:hidden}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}figure{margin:1em 40px}hr{box-sizing:content-box;height:0;overflow:visible}button,input,optgroup,select,textarea{font:inherit;margin:0}optgroup{font-weight:bold}button,input{overflow:visible}button,select{text-transform:none}button,html [type="button"],[type="reset"],[type="submit"]{-webkit-appearance:button}button::-moz-focus-inner,[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring{outline:1px dotted ButtonText}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-cancel-button,[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-input-placeholder{color:inherit;opacity:.54}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}
\ No newline at end of file diff --git a/build/css/theme-chinese-article.css b/build/css/theme-chinese-article.css deleted file mode 100644 index 1b76afaf..00000000 --- a/build/css/theme-chinese-article.css +++ /dev/null @@ -1,74 +0,0 @@ -h1 { - font-size: 140%; -} - -h2 { - font-size: 110%; -} - -h3 { - font-size: 100%; -} - -p { - margin-top: 0; - margin-bottom: 0; - text-indent: 2em; - line-height: 1.3em; -} - -blockquote { - margin: 1em 2em 1em 2em; - padding: 0; - border: none; - font-style: normal; -} - -article a { - text-decoration: none; - color: #777; -} - -sup { - margin: 0; -} - -.en p, .en li { - text-indent: 0; - margin-top: 0.5em; - margin-bottom: 0.5em; -} - -.en blockquote { - font-style: italic; -} - -.date-tag { - text-align: right; -} - -.poem { - text-align: center; -} - -.undent, .footnotes p { - text-indent: 0; -} - -.skip { - margin-bottom: 1em; -} - -.poem p { - margin-top: 1em; - margin-bottom: 1em; - text-indent: 0; -} - -@media print { - footer { - width: 0; - height: 0; - visibility: hidden; - } -} diff --git a/build/css/theme.css b/build/css/theme.css deleted file mode 100644 index 6735e8c0..00000000 --- a/build/css/theme.css +++ /dev/null @@ -1,391 +0,0 @@ -/*** Webfonts ***/ - -/* icon font from fontello */ -@font-face { - font-family: 'fontello'; - src: url('../fonts/fontello.eot'); - src: url('../fonts/fontello.eot?#iefix') format('embedded-opentype'), - url('../fonts/fontello.woff') format('woff'), - url('../fonts/fontello.ttf') format('truetype'), - url('../fonts/fontello.svg#fontello') format('svg'); - font-weight: normal; - font-style: normal; -} - -/*** Main theme ***/ - -body { - color: #000; - font-family: Times, "Times New Roman", - /* Chinese fonts */ - "Kaiti SC", /* macOS */ - "Songti SC", /* macOS 10.12+ where Kaiti SC isn't installed by default - but is instead available as a downloadable component */ - KaiTi, /* Windows (simkai.ttf, not always included despite - https://www.microsoft.com/typography/fonts/product.aspx?PID=161 - https://www.microsoft.com/typography/fonts/product.aspx?PID=164) */ - "Microsoft YaHei", /* Windows */ - "Heiti SC", /* iOS */ - serif; - font-size: 16px; - -webkit-font-smoothing: antialiased; - margin: 100px 0; -} - -@media -only screen and (-webkit-min-device-pixel-ratio: 1.25), -only screen and ( min-device-pixel-ratio: 1.25), -only screen and ( min-resolution: 200dpi), -only screen and ( min-resolution: 1.25dppx) { - -webkit-font-smoothing: subpixel-antialiased; -} - -#archival-notice { - position: absolute; - top: 30px; - left: 0; - right: 0; - margin: 0 auto; - text-align: center; - color: red; -} - -.nav { - position: fixed; - left: 5%; - top: 90px; - height: 150px; - width: 100px; - text-align: center; -} - -.nav-icon { - display: block; - margin: 2px auto; - width: 100px; - height: 100px; - border-radius: 50%; - background: #ddd; - line-height: 100px; - text-align: center; - text-decoration: none; - font-size: 0; -} - -.nav-icon:before { - content: "ZW"; - display: inline-block; - position: relative; - left: 2px; - font-family: "Helvetica Neue", Arial, sans-serif; - font-size: 35px; - font-weight: normal; - letter-spacing: 2px; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - color: #fff; - transform: scale(1,0.95); - -webkit-transform: scale(1,0.95); - -moz-transform: scale(1,0.95); - -ms-transform: scale(1,0.95); - -o-transform: scale(1,0.95); -} - -.nav-title { - font-size: 17px; - font-weight: bold; - margin: 2px 0 1px 0; - text-decoration: none; -} - -.nav-title:before { - content: "dl? cmplnts?"; -} - -.nav-author { - font-size: 13px; - text-decoration: none; -} - -.nav-author:before { - content: "by Zhiming Wang"; -} - -.content, .content-separator, .footer { - width: 60%; - margin: 0 auto; -} - -hr { - border: 0; - height: 1px; - background: #888; -} - -.content-separator { - margin: 15px auto 3px auto; -} - -.content { - text-align: justify; -} - -h1 { - text-align: center; - font-size: 160%; - font-weight: bold; -} - -h2 { - text-align: center; - font-size: 125%; - font-weight: bold; -} - -.article-metadata { - text-align: center; - font-size: 100%; - font-weight: normal; - margin: 1em 0; -} - -a { - color: inherit; - word-wrap: break-word; -} - -code { - font-size: 90%; - color: #333; - font-family: Courier, monospace; - white-space: pre-wrap; - word-wrap: break-word; -} - -h1 code, h2 code { - font-size: 95%; - color: #000; -} - -pre { - overflow-x: scroll; - padding: 1em; - background: #fbfbfb; - border-left: 0.4em solid #ddd; -} - -/* Pandoc wraps pre[class*=sourceCode] in a div tag, so it is necessary to -eliminate the margins of such pre tags to avoid too much spacing.*/ -pre[class*=sourceCode] { - margin: 0; -} - -pre code { - font-size: 85%; - color: #000; - white-space: pre; - word-wrap: normal; -} - -ol { - padding-left: 20px; -} - -ul { - padding-left: 16px; -} - -blockquote { - margin: 0; - padding: 0 1em; - font-style: italic; - border-left: 0.4em solid #ddd; -} - -img { - display: block; - max-width: 100%; - margin: 5px auto; -} - -.figure { - text-align: center; -} - -.figure img { - display: inline; - margin: 0 0 5px 0; -} - -.figure .caption { - width: 80%; - margin: auto; - font-size: 90%; -} - -sup { - font-size: 11px; - margin: 0 0 0 1px; -} - -noscript { - color: #999; -} - -noscript a { - color: #999; -} - -.footnotes { - font-size: 90%; -} - -.footnotes ol { - padding-left: 1.4em; -} - -.footnotes p { - margin: 0.6em 0; -} - -.footnotes-backlink { - margin-left: 0.2em; - vertical-align: -0.2em; - color: #bbb; - text-decoration: none; -} - -.footnotes-backlink:hover { - background-color: #bbb; - color: #fff; -} - -.lfooter { - float: left; -} - -.lfooter .updated:before { - content: "Last updated: " -} - -.rfooter { - float: right; -} - -.rss-icon, .atom-icon, .cc-icon { - text-decoration: none; - position: relative; - top: 1px; -} - -.rss-icon, .atom-icon { - margin: 0 3px; -} - -.cc-icon { - margin: 0 1px; -} - -.rss-icon:before, .atom-icon:before { - content: "\e800"; - font-family: fontello; - font-size: 105%; -} - -.rss-icon:before { - display: inline-block; - transform: scale(-1,1); - -webkit-transform: scale(-1,1); -} - -.cc-icon:before { - content: "\e801"; - font-family: fontello; - font-size: 95%; -} - -/*** Wide screen ***/ - -@media screen and (min-width: 1441px) { - .content, .content-separator, .footer { - width: 50%; - } -} - -/*** Narrow screen ***/ - -@media screen and (max-width: 1023px) { - body { - margin: 40px 0 100px 0; - } - - .nav { - position: static; - width: 100%; - height: 150px; - margin: 80px 0 20px 0; - } - - .nav-icon { - width: 150px; - height: 150px; - line-height: 150px; - } - - .nav-icon:before { - font-size: 54px; - } - - .nav-title, .nav-author { - height: 0; - width: 0; - visibility: hidden; - pointer-events: none; - } - - .content, .content-separator, .footer { - width: 80%; - } -} - -/*** Ultranarrow screen ***/ - -@media screen and (max-width: 500px) { - .content, .content-separator, .footer { - width: 90%; - } - - .blog-index-yearly-index { - margin-left: 0; - } - - .blog-index-post-date { - width: 4em; - } -} - -/*** Print ***/ - -@media print { - body { - margin: 5% 0; - font-size: 12px; - } - - sup { - font-size: 0.5em; - top: -1em; - } - - pre { - -webkit-print-color-adjust: exact; - } - - .content, .content-separator, .footer { - width: 90%; - } - - .nav, .rss-icon, .atom-icon, .cc-icon, #archival-notice { - display: none; - } -} diff --git a/build/favicon.ico b/build/favicon.ico Binary files differdeleted file mode 100644 index a57f6f26..00000000 --- a/build/favicon.ico +++ /dev/null diff --git a/build/fonts/fontello.eot b/build/fonts/fontello.eot Binary files differdeleted file mode 100644 index 9f5d486b..00000000 --- a/build/fonts/fontello.eot +++ /dev/null diff --git a/build/fonts/fontello.svg b/build/fonts/fontello.svg deleted file mode 100644 index 3ce4b9b1..00000000 --- a/build/fonts/fontello.svg +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" standalone="no"?> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg xmlns="http://www.w3.org/2000/svg"> -<metadata>Copyright (C) 2016 by original authors @ fontello.com</metadata> -<defs> -<font id="fontello" horiz-adv-x="1000" > -<font-face font-family="fontello" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" /> -<missing-glyph horiz-adv-x="1000" /> -<glyph glyph-name="rss" unicode="" d="m0 730q314 0 537-223t223-537l-118 0q0 266-188 453t-454 187l0 120z m0-238q218 0 371-153t153-369l-118 0q0 166-119 285t-287 119l0 118z m114-296q46 0 80-33t34-81q0-46-34-79t-80-33-80 33-34 79q0 48 34 81t80 33z" horiz-adv-x="760" /> -<glyph glyph-name="cc" unicode="" d="m474 830q198 2 340-136t146-336q2-200-136-342t-338-146q-198-2-341 137t-145 337q-4 200 135 342t339 144z m12-858q156 2 266 114t108 270-115 267-269 107q-158-2-267-114t-107-270 114-267 270-107z m-124 298q40 0 58 40l56-30q-20-36-50-52-32-20-70-20-62 0-100 38-38 36-38 104t38 106 96 38q86 0 124-66l-62-32q-10 20-24 28t-28 8q-60 0-60-82 0-38 14-58 18-22 46-22z m266 0q42 0 56 40l58-30q-18-32-50-52t-70-20q-64 0-100 38-38 36-38 104 0 64 38 106 38 38 98 38 84 0 120-66l-60-32q-10 20-24 28t-28 8q-62 0-62-82 0-36 16-58t46-22z" horiz-adv-x="960" /> -</font> -</defs> -</svg>
\ No newline at end of file diff --git a/build/fonts/fontello.ttf b/build/fonts/fontello.ttf Binary files differdeleted file mode 100644 index 4b372c14..00000000 --- a/build/fonts/fontello.ttf +++ /dev/null diff --git a/build/fonts/fontello.woff b/build/fonts/fontello.woff Binary files differdeleted file mode 100644 index 04b7ffcd..00000000 --- a/build/fonts/fontello.woff +++ /dev/null diff --git a/build/googleb62a7d99e962cf5a.html b/build/googleb62a7d99e962cf5a.html deleted file mode 100644 index 830d36fd..00000000 --- a/build/googleb62a7d99e962cf5a.html +++ /dev/null @@ -1 +0,0 @@ -google-site-verification: googleb62a7d99e962cf5a.html
\ No newline at end of file diff --git a/build/img/20150608-ios-9-preview-1920x1080-50%.png b/build/img/20150608-ios-9-preview-1920x1080-50%.png Binary files differdeleted file mode 100644 index 6114b632..00000000 --- a/build/img/20150608-ios-9-preview-1920x1080-50%.png +++ /dev/null diff --git a/build/img/20150608-osx-el-capitan-preview-1920x1080-50%.png b/build/img/20150608-osx-el-capitan-preview-1920x1080-50%.png Binary files differdeleted file mode 100644 index 1a7beef0..00000000 --- a/build/img/20150608-osx-el-capitan-preview-1920x1080-50%.png +++ /dev/null diff --git a/build/img/20150608-wwdc-2015-banner.png b/build/img/20150608-wwdc-2015-banner.png Binary files differdeleted file mode 100644 index 0669487d..00000000 --- a/build/img/20150608-wwdc-2015-banner.png +++ /dev/null diff --git a/build/img/20150608-wwdc-2015-liveblog-1920x1080.png b/build/img/20150608-wwdc-2015-liveblog-1920x1080.png Binary files differdeleted file mode 100644 index e3001059..00000000 --- a/build/img/20150608-wwdc-2015-liveblog-1920x1080.png +++ /dev/null diff --git a/build/img/20150608-wwdc-2015-liveblog-960x981.png b/build/img/20150608-wwdc-2015-liveblog-960x981.png Binary files differdeleted file mode 100644 index 27b82707..00000000 --- a/build/img/20150608-wwdc-2015-liveblog-960x981.png +++ /dev/null diff --git a/build/img/20150610-old-bookmark-manager.png b/build/img/20150610-old-bookmark-manager.png Binary files differdeleted file mode 100644 index 79777bce..00000000 --- a/build/img/20150610-old-bookmark-manager.png +++ /dev/null diff --git a/build/img/20150610-omnibox-with-aged-star.png b/build/img/20150610-omnibox-with-aged-star.png Binary files differdeleted file mode 100644 index 7d134b4b..00000000 --- a/build/img/20150610-omnibox-with-aged-star.png +++ /dev/null diff --git a/build/img/20150627-macrumors-demo-ios9-searchable-settings.png b/build/img/20150627-macrumors-demo-ios9-searchable-settings.png Binary files differdeleted file mode 100644 index d1eab05b..00000000 --- a/build/img/20150627-macrumors-demo-ios9-searchable-settings.png +++ /dev/null diff --git a/build/img/20150629-news-publisher-acceptance-email.png b/build/img/20150629-news-publisher-acceptance-email.png Binary files differdeleted file mode 100644 index bf0264ca..00000000 --- a/build/img/20150629-news-publisher-acceptance-email.png +++ /dev/null diff --git a/build/img/20150630-dl-cmplnts-on-apple-news.png b/build/img/20150630-dl-cmplnts-on-apple-news.png Binary files differdeleted file mode 100644 index 97b4e10c..00000000 --- a/build/img/20150630-dl-cmplnts-on-apple-news.png +++ /dev/null diff --git a/build/img/20150719-github-attachment-new-formats.png b/build/img/20150719-github-attachment-new-formats.png Binary files differdeleted file mode 100644 index 23c76841..00000000 --- a/build/img/20150719-github-attachment-new-formats.png +++ /dev/null diff --git a/build/img/20150725-performance-of-my-blog-breakdown.png b/build/img/20150725-performance-of-my-blog-breakdown.png Binary files differdeleted file mode 100644 index 23ed4cbf..00000000 --- a/build/img/20150725-performance-of-my-blog-breakdown.png +++ /dev/null diff --git a/build/img/20150725-performance-of-my-blog-requests.png b/build/img/20150725-performance-of-my-blog-requests.png Binary files differdeleted file mode 100644 index 9d8ce87a..00000000 --- a/build/img/20150725-performance-of-my-blog-requests.png +++ /dev/null diff --git a/build/img/20150802-assistive-access-nightmare.png b/build/img/20150802-assistive-access-nightmare.png Binary files differdeleted file mode 100644 index bf995b73..00000000 --- a/build/img/20150802-assistive-access-nightmare.png +++ /dev/null diff --git a/build/img/20150805-my-current-dock.png b/build/img/20150805-my-current-dock.png Binary files differdeleted file mode 100644 index 8bd3364e..00000000 --- a/build/img/20150805-my-current-dock.png +++ /dev/null diff --git a/build/img/20150819-ios9-wifi-assist.png b/build/img/20150819-ios9-wifi-assist.png Binary files differdeleted file mode 100644 index 888bb2a1..00000000 --- a/build/img/20150819-ios9-wifi-assist.png +++ /dev/null diff --git a/build/img/20150825-osx-provisioning-system.png b/build/img/20150825-osx-provisioning-system.png Binary files differdeleted file mode 100644 index 65e12b45..00000000 --- a/build/img/20150825-osx-provisioning-system.png +++ /dev/null diff --git a/build/img/20150831-hack-10pt-antialiased.png b/build/img/20150831-hack-10pt-antialiased.png Binary files differdeleted file mode 100644 index 99ca67e7..00000000 --- a/build/img/20150831-hack-10pt-antialiased.png +++ /dev/null diff --git a/build/img/20150831-hack-11pt-antialiased.png b/build/img/20150831-hack-11pt-antialiased.png Binary files differdeleted file mode 100644 index c91032f9..00000000 --- a/build/img/20150831-hack-11pt-antialiased.png +++ /dev/null diff --git a/build/img/20150831-hack-8,9,10,11pt-antialiased-combined.png b/build/img/20150831-hack-8,9,10,11pt-antialiased-combined.png Binary files differdeleted file mode 100644 index e776965b..00000000 --- a/build/img/20150831-hack-8,9,10,11pt-antialiased-combined.png +++ /dev/null diff --git a/build/img/20150831-hack-8pt-antialiased.png b/build/img/20150831-hack-8pt-antialiased.png Binary files differdeleted file mode 100644 index 3931e252..00000000 --- a/build/img/20150831-hack-8pt-antialiased.png +++ /dev/null diff --git a/build/img/20150831-hack-9pt-antialiased.png b/build/img/20150831-hack-9pt-antialiased.png Binary files differdeleted file mode 100644 index 28fe6b5c..00000000 --- a/build/img/20150831-hack-9pt-antialiased.png +++ /dev/null diff --git a/build/img/20150831-monaco-10pt-non-antialiased.png b/build/img/20150831-monaco-10pt-non-antialiased.png Binary files differdeleted file mode 100644 index a7a4d1f0..00000000 --- a/build/img/20150831-monaco-10pt-non-antialiased.png +++ /dev/null diff --git a/build/img/20150831-terminal-app-pro-profile.png b/build/img/20150831-terminal-app-pro-profile.png Binary files differdeleted file mode 100644 index 67756be8..00000000 --- a/build/img/20150831-terminal-app-pro-profile.png +++ /dev/null diff --git a/build/img/20151001-maximized-window-vs-full-screen.png b/build/img/20151001-maximized-window-vs-full-screen.png Binary files differdeleted file mode 100644 index e56105ad..00000000 --- a/build/img/20151001-maximized-window-vs-full-screen.png +++ /dev/null diff --git a/build/img/20151001-osx-el-capitan-icloud-password-to-log-in.png b/build/img/20151001-osx-el-capitan-icloud-password-to-log-in.png Binary files differdeleted file mode 100644 index 39f1e074..00000000 --- a/build/img/20151001-osx-el-capitan-icloud-password-to-log-in.png +++ /dev/null diff --git a/build/img/20151001-osx-el-capitan-three-finger-drag-there-it-is.png b/build/img/20151001-osx-el-capitan-three-finger-drag-there-it-is.png Binary files differdeleted file mode 100644 index b6f52b86..00000000 --- a/build/img/20151001-osx-el-capitan-three-finger-drag-there-it-is.png +++ /dev/null diff --git a/build/img/20151001-osx-el-capitan-wheres-my-three-finger-drag.png b/build/img/20151001-osx-el-capitan-wheres-my-three-finger-drag.png Binary files differdeleted file mode 100644 index b6cb6d54..00000000 --- a/build/img/20151001-osx-el-capitan-wheres-my-three-finger-drag.png +++ /dev/null diff --git a/build/img/20151003-ios-security-white-paper-but-no-osx.png b/build/img/20151003-ios-security-white-paper-but-no-osx.png Binary files differdeleted file mode 100644 index 4cc23c97..00000000 --- a/build/img/20151003-ios-security-white-paper-but-no-osx.png +++ /dev/null diff --git a/build/img/20151010-bash-print-sample-page.png b/build/img/20151010-bash-print-sample-page.png Binary files differdeleted file mode 100644 index 6e35c6d8..00000000 --- a/build/img/20151010-bash-print-sample-page.png +++ /dev/null diff --git a/build/img/20151229-win7-iso-language-choice.png b/build/img/20151229-win7-iso-language-choice.png Binary files differdeleted file mode 100644 index ad1d124e..00000000 --- a/build/img/20151229-win7-iso-language-choice.png +++ /dev/null diff --git a/build/img/20160124-antivirus-sentinel-pro-reviews.png b/build/img/20160124-antivirus-sentinel-pro-reviews.png Binary files differdeleted file mode 100644 index fbd9a42a..00000000 --- a/build/img/20160124-antivirus-sentinel-pro-reviews.png +++ /dev/null diff --git a/build/img/20160124-mas-top-paid.png b/build/img/20160124-mas-top-paid.png Binary files differdeleted file mode 100644 index 5e002694..00000000 --- a/build/img/20160124-mas-top-paid.png +++ /dev/null diff --git a/build/img/20160126-dropbox-noteworthy.png b/build/img/20160126-dropbox-noteworthy.png Binary files differdeleted file mode 100644 index 0f3769e5..00000000 --- a/build/img/20160126-dropbox-noteworthy.png +++ /dev/null diff --git a/build/img/20160126-pdf-expert-note.png b/build/img/20160126-pdf-expert-note.png Binary files differdeleted file mode 100644 index 3e5ffb5a..00000000 --- a/build/img/20160126-pdf-expert-note.png +++ /dev/null diff --git a/build/img/20160306-chrome-mac-48.0.2564.103-49.0.2623.75-icons-side-by-side-in-dock.png b/build/img/20160306-chrome-mac-48.0.2564.103-49.0.2623.75-icons-side-by-side-in-dock.png Binary files differdeleted file mode 100644 index 61d1a171..00000000 --- a/build/img/20160306-chrome-mac-48.0.2564.103-49.0.2623.75-icons-side-by-side-in-dock.png +++ /dev/null diff --git a/build/img/20160306-chrome-mac-48.0.2564.103-49.0.2623.75-icons-side-by-side.png b/build/img/20160306-chrome-mac-48.0.2564.103-49.0.2623.75-icons-side-by-side.png Binary files differdeleted file mode 100644 index d37a1ea2..00000000 --- a/build/img/20160306-chrome-mac-48.0.2564.103-49.0.2623.75-icons-side-by-side.png +++ /dev/null diff --git a/build/img/20160306-chrome-mac-48.0.2564.103-downloads.png b/build/img/20160306-chrome-mac-48.0.2564.103-downloads.png Binary files differdeleted file mode 100644 index b561717f..00000000 --- a/build/img/20160306-chrome-mac-48.0.2564.103-downloads.png +++ /dev/null diff --git a/build/img/20160306-chrome-mac-48.0.2564.103-icon.png b/build/img/20160306-chrome-mac-48.0.2564.103-icon.png Binary files differdeleted file mode 100644 index 1e68ce11..00000000 --- a/build/img/20160306-chrome-mac-48.0.2564.103-icon.png +++ /dev/null diff --git a/build/img/20160306-chrome-mac-48.0.2564.103-incognito.png b/build/img/20160306-chrome-mac-48.0.2564.103-incognito.png Binary files differdeleted file mode 100644 index c8ff3076..00000000 --- a/build/img/20160306-chrome-mac-48.0.2564.103-incognito.png +++ /dev/null diff --git a/build/img/20160306-chrome-mac-49.0.2623.75-downloads.png b/build/img/20160306-chrome-mac-49.0.2623.75-downloads.png Binary files differdeleted file mode 100644 index c1746504..00000000 --- a/build/img/20160306-chrome-mac-49.0.2623.75-downloads.png +++ /dev/null diff --git a/build/img/20160306-chrome-mac-49.0.2623.75-icon.png b/build/img/20160306-chrome-mac-49.0.2623.75-icon.png Binary files differdeleted file mode 100644 index 7172764d..00000000 --- a/build/img/20160306-chrome-mac-49.0.2623.75-icon.png +++ /dev/null diff --git a/build/img/20160306-chrome-mac-49.0.2623.75-incognito.png b/build/img/20160306-chrome-mac-49.0.2623.75-incognito.png Binary files differdeleted file mode 100644 index 046dc510..00000000 --- a/build/img/20160306-chrome-mac-49.0.2623.75-incognito.png +++ /dev/null diff --git a/build/img/20160409-emacs-website-screenshot-half-size.png b/build/img/20160409-emacs-website-screenshot-half-size.png Binary files differdeleted file mode 100644 index 0e1303ef..00000000 --- a/build/img/20160409-emacs-website-screenshot-half-size.png +++ /dev/null diff --git a/build/img/20160409-emacs-website-screenshot.png b/build/img/20160409-emacs-website-screenshot.png Binary files differdeleted file mode 100644 index b48ab644..00000000 --- a/build/img/20160409-emacs-website-screenshot.png +++ /dev/null diff --git a/build/img/20160901-cloudflare-ssl-modes.png b/build/img/20160901-cloudflare-ssl-modes.png Binary files differdeleted file mode 100644 index f7f9f554..00000000 --- a/build/img/20160901-cloudflare-ssl-modes.png +++ /dev/null diff --git a/build/img/apple-touch-icon-152.png b/build/img/apple-touch-icon-152.png Binary files differdeleted file mode 100644 index 9c48d849..00000000 --- a/build/img/apple-touch-icon-152.png +++ /dev/null diff --git a/build/img/favicon-144.png b/build/img/favicon-144.png Binary files differdeleted file mode 100644 index 014cab41..00000000 --- a/build/img/favicon-144.png +++ /dev/null diff --git a/build/index.html b/build/index.html deleted file mode 100644 index 573e24ad..00000000 --- a/build/index.html +++ /dev/null @@ -1,923 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <meta charset="UTF-8"/> - <meta name="generator" content="pandoc"/> - <meta name="author" content="Zhiming Wang"/> - <title>dl? cmplnts?</title> - <link rel="apple-touch-icon-precomposed" href="/img/apple-touch-icon-152.png"/> - <meta name="msapplication-TileColor" content="#FFFFFF"/> - <meta name="msapplication-TileImage" content="/img/favicon-144.png"/> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> - <link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> - <style type="text/css">.blog-index-year-title { text-align: left; } .blog-index-yearly-index { margin-left: 1em; } .blog-index td { vertical-align: top; } .blog-index-post-date { width: 5em; }</style> - </head> - <body> - <div id="archival-notice">This blog has been archived.<br>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> - <nav class="nav"> - <a class="nav-icon" href="/" title="Home"><!--blog icon--></a> - <a class="nav-title" href="/"><!--blog title--></a> - <a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> - </nav> - <article class="content"> - <header class="article-header"> - <h1 class="article-title">dl? cmplnts?</h1> - <div class="article-metadata"> - </div> - </header> -<p>My name is Zhiming Wang (Simplified Chinese: 王之铭), and I am a Ph.D. student in high energy theory at Princeton Physics (first year as of September 2016). Previously I earned my bachelor's degree in mathematics and physics at Stanford. I enjoy coding in my spare time, for fun and profit — I hate repetitive tasks, so computer programs help me automate and get things done quickly.</p> -<p>My first programming language was Pascal and I consider C my mother tongue, but recently I write most of my stuff in Python and Zsh. My operating system is OS X / macOS, my text editor is Emacs, my interactive (and non-interactive) shell is Zsh, my package manager is Homebrew, and my default browser at the moment is Google Chrome. I use four-space indents when the target language has no established convention that says otherwise. Any source code I publish on the Web is licensed under <a href="http://www.wtfpl.net/">WTFPL</a> unless a license is explicitly declared (usually OSI's MIT, aka Expat). I am on <a href="https://keybase.io/zmwangx">Keybase</a> in case you are security-minded (or use <a href="https://keybase.io/zmwangx/key.asc">this link</a> if you just want my public key). PGP or not, you can reach me at <a href="mailto:zmwangx@gmail.com">zmwangx@gmail.com</a>. You won't and likely never will find me on SNS. What else is there to tell?</p> -<p>This blog could be about anything, but most of the stuff here should be technical. Oh yes, this blog is fully open source, down to how image assets were generated. All tools necessary for reproducing this blog are either in or documented in <a href="https://github.com/zmwangx/zmwangx.github.io/tree/source">the source branch</a> of <a href="https://github.com/zmwangx/zmwangx.github.io">zmwangx/zmwangx.github.io</a>.</p> -<hr> -<div id="toc" class="blog-index"> -<h2 class="blog-index-year-title" id="2016"> -2016 -</h2> -<table class="blog-index-yearly-index"> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2016-10-26T12:16:22-04:00">Oct 26</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2016-10-26-pyenv-compiling-python-with-sqlite-in-nonstandard-location.html">pyenv: compiling Python with SQLite in nonstandard location</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2016-09-01T20:11:00+08:00">Sep 01</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2016-09-01-this-blog-is-now-behind-cloudflare.html">This blog is now behind CloudFlare</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2016-06-24T05:40:01+08:00">Jun 24</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2016-06-24-its-2016-and-microsoft-is-the-only-legit-player-who-spams-me-without-unsubscribe-links.html">It's 2016, and Microsoft is the only legit player who spams me without unsubscribe links</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2016-05-07T18:49:26-07:00">May 07</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2016-05-07-chrome-is-screwing-with-our-extensions-again.html">Chrome is screwing with our extensions... Again</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2016-04-10T03:04:19-07:00">Apr 10</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2016-04-10-emacss-got-a-redesigned-website.html">Emacs's got a redesigned website!</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2016-03-06T14:59:45-08:00">Mar 06</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2016-03-06-google-chrome-keeps-getting-uglier.html">Google Chrome keeps getting uglier</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2016-01-26T12:18:36-08:00">Jan 26</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2016-01-26-dropbox-noteworthy-and-damned-skeuomorphism.html">Dropbox, Noteworthy, and damned skeuomorphism</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2016-01-24T18:43:28-08:00">Jan 24</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2016-01-24-antivirus-app-on-mas-top-chart.html">Antivirus app on MAS top chart?</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2016-01-18T16:36:40-08:00">Jan 18</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2016-01-18-me-too-comments-on-github.html">Me-too comments on GitHub</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2016-01-14T01:02:52-08:00">Jan 14</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2016-01-14-the-dirtiest-mistakes-of-os-x.html">The dirtiest mistakes of OS X</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2016-01-01T22:21:14-08:00">Jan 01</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2016-01-01-virtualenvs-for-everyone.html">Virtualenvs for everyone</a> -</td> -</tr> -</table> -<h2 class="blog-index-year-title" id="2015"> -2015 -</h2> -<table class="blog-index-yearly-index"> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-12-29T15:09:16-08:00">Dec 29</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-12-29-catches-when-installing-windows-7-with-boot-camp.html">Catches when installing Windows 7 with Boot Camp</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-12-28T03:15:45-08:00">Dec 28</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-12-28-why-i-want-lossless-music-on-itunes-music-store.html">Why I want lossless music on iTunes Music Store</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-12-27T16:47:05-08:00">Dec 27</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-12-27-lesson-on-magic-method-access-of-python-new-style-classes-from-my-failed-python3-port-of-tomorrow.html">Lesson on magic method access of Python new-style classes (from my failed Python3 port of Tomorrow)</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-12-26T00:15:48-08:00">Dec 26</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-12-26-autoenv-with-auto-cleanup.html">autoenv with auto cleanup</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-12-20T16:03:03-08:00">Dec 20</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-12-20-regex-flavor-hell.html">Regex flavor hell</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-12-16T21:10:08-08:00">Dec 16</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-12-16-spoiled-by-retina-in-less-than-a-day.html">Spoiled by Retina, in less than a day</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-12-08T00:17:39-08:00">Dec 08</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-12-08-safeguarding-git-repos-against-accidental-rm.html">Safeguarding git repos against accidental rm</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-11-25T15:38:13-08:00">Nov 25</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-11-25-bash-function-exporting-fiasco.html">Bash function exporting fiasco</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-11-15T02:17:05-08:00">Nov 15</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-11-15-we-need-a-programming-keyboard-on-ios.html">We need a programming keyboard on iOS</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-11-06T10:49:51-08:00">Nov 06</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-11-06-microsoft-drops-unlimited-onedrive-storage-after-people-use-it-for-unlimited-storage.html">Microsoft drops unlimited OneDrive storage after people use it for unlimited storage</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-10-26T00:00:30-07:00">Oct 26</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-10-26-att-to-pure-talkusa-one-month-later.html">AT&T to Pure TalkUSA, one month later</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-10-14T17:07:24-07:00">Oct 14</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-10-14-sip-for-the-greater-good.html">SIP — For the Greater Good</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-10-14T12:30:32-07:00">Oct 14</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-10-14-follow-up-the-sad-state-of-finder-on-el-capitan.html">Follow-up: The sad state of Finder on El Capitan</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-10-12T14:29:42-07:00">Oct 12</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-10-12-the-importance-of-dated-detailed-release-notes.html">The importance of dated, detailed release notes</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-10-10T22:35:15-07:00">Oct 10</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-10-10-printing-long-80-character-per-line-plain-text-document-in-two-columns.html">Printing long, 80-character-per-line plain text document in two columns</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-10-03T03:34:24-07:00">Oct 03</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-10-03-we-need-an-os-x-security-white-paper.html">We need an OS X security white paper</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-10-01T15:48:59-07:00">Oct 01</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-10-01-auto-hidden-menu-bar-dock-maximized-window-is-the-new-full-screen-mode.html">Auto hidden menu bar & dock + maximized window is the new full screen mode</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-10-01T11:46:44-07:00">Oct 01</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-10-01-upgrading-to-el-capitan.html">Upgrading to El Capitan</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-09-25T12:30:25-07:00">Sep 25</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-09-25-removing-google-analytics-from-this-blog.html">Removing Google Analytics from this blog</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-09-24T10:55:38-07:00">Sep 24</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-09-24-apple-watch-digital-crown-tightness-issue.html">Apple Watch: Digital Crown tightness issue</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-09-21T14:40:36-07:00">Sep 21</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-09-21-zsh-51-and-bracketed-paste.html">Zsh 5.1 and bracketed paste</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-08-31T06:31:03+08:00">Aug 31</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-08-31-after-all-these-years-10pt-non-anti-aliased-monaco-is-still-the-best.html">After all these years, 10pt non-anti-aliased Monaco is still the best</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-08-25T08:16:44-07:00">Aug 25</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-08-25-automated-os-x-provisioning.html">Automated OS X provisioning</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-08-20T20:58:55-07:00">Aug 20</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-08-20-i-installed-blockparty-and-the-only-thing-i-can-say-is-wow.html">I installed BlockParty, and the only thing I can say is WOW</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-08-20T01:01:57-07:00">Aug 20</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-08-20-ios-9-turn-off-wi-fi-assist.html">iOS 9: turn off Wi-Fi Assist!</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-08-14T18:32:13-07:00">Aug 14</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-08-14-laymen.html">Laymen</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-08-13T02:00:24-07:00">Aug 13</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-08-13-other-peoples-___.html">Other people's ___</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-08-05T19:38:37-07:00">Aug 05</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-08-05-switching-to-capitalized-commit-messages.html">Switching to capitalized commit messages</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-08-05T14:09:51-07:00">Aug 05</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-08-05-should-apple-split-up-itunes-on-os-x.html">Should Apple split up iTunes on OS X?</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-08-02T22:11:56-07:00">Aug 02</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-08-02-sync-chrome-bookmarks-with-safari-on-os-x.html">Sync Chrome bookmarks with Safari on OS X</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-07-30T23:59:09-07:00">Jul 30</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-07-30-the-sad-state-of-finder-on-el-capitan.html">The sad state of Finder on El Capitan</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-07-25T11:31:54-07:00">Jul 25</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-07-25-dl-cmplntss-web-doesnt-suck.html">dl? cmplnts?'s web doesn't suck</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-07-19T21:58:01-07:00">Jul 19</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-07-19-github-experimental-attachment-formats-pdf-docx-and-pptx.html">GitHub experimental attachment formats: PDF, DOCX and PPTX!?!</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-07-15T09:21:47-07:00">Jul 15</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-07-15-zsh-save-stdout-stderr-and-return-value-of-command-to-different-variables-without-temp-file.html">Zsh: save stdout, stderr, and return value of command to different variables (without temp file)</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-06-29T23:14:42-07:00">Jun 29</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-06-29-dl-cmplnts-in-apple-news.html">dl? cmplnts? in Apple News</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-06-27T21:19:59-07:00">Jun 27</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-06-27-automatically-clean-up-previous-mobile-applications.html">Automatically clean up "Previous Mobile Applications"</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-06-26T23:59:28-07:00">Jun 26</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-06-26-ios-9-searchable-settings.html">iOS 9: searchable Settings</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-06-23T21:47:07-07:00">Jun 23</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-06-23-all-problems-solved.html">All problems solved!?</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-06-12T14:24:18-07:00">Jun 12</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-06-12-the-tip-of-the-iceberg.html">The tip of the iceberg</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-06-10T23:17:05-07:00">Jun 10</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-06-10-chrome-disappointment-the-shabby-and-boring-old-bookmark-system-from-stone-age-strikes-back.html">Chrome disappointment: the shabby and boring old bookmark system from Stone Age strikes back</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-06-08T14:42:50-07:00">Jun 08</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-06-08-apple-turns-its-homepage-into-a-wwdc-liveblog.html">Apple turns its homepage into a WWDC liveblog</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-06-07T18:58:57-07:00">Jun 07</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-06-07-stackoverflow-review-system-is-completely-bs.html">StackOverflow review system is completely BS</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-05-30T22:48:57-07:00">May 30</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-05-30-using-a-personal-helper-package-in-everyday-scripting.html">Using a personal helper package in everyday scripting</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-05-29T20:40:05-07:00">May 29</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-05-29-apples-customer-service-is-still-the-best-plus-an-authy-horror-story.html">Apple's customer service is still the best (plus an Authy horror story)</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-05-22T00:48:19-07:00">May 22</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-05-22-using-a-command-table-as-wallpaper.html">Using a command table as wallpaper</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-05-19T18:33:51-07:00">May 19</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-05-19-bash-the-special-slash-character-in-filename-expansion.html">Bash: the special slash character in filename expansion</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-05-09T00:32:28-07:00">May 09</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-05-09-storyboard-reached-01.html">storyboard reached 0.1</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-05-06T19:29:46-07:00">May 06</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-05-06-searchable-settings-are-one-honking-great-idea-lets-do-more-of-those.html">Searchable settings are one honking great idea — let's do more of those!</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-05-05T22:03:39-07:00">May 05</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-05-05-graceful-handling-of-sigint-when-using-pythons-multiprocessingprocess.html">Graceful handling of SIGINT when using Python's multiprocessing.Process</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-05-05T02:42:44-07:00">May 05</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-05-05-new-blog-new-start.html">New blog, new start</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-05-03T17:15:49-07:00">May 03</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-05-03-why-oh-my-zsh-is-completely-broken.html">Why Oh My Zsh is completely broken</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-04-26T21:19:14-07:00">Apr 26</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-04-26-using-python-3-with-emacs-jedi.html">Using Python 3 with Emacs Jedi</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-03-22T16:58:50-07:00">Mar 22</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-03-22-back-up-os-x-app-icons.html">Back up OS X app icons</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-02-24T18:31:19-08:00">Feb 24</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-02-24-the-new-onedrive-api.html">The new OneDrive API</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-02-21T17:12:32-08:00">Feb 21</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-02-21-all-is-not-lost.html">All is not lost</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-02-20T16:16:10-08:00">Feb 20</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-02-20-my-dock-and-updated-omnifocus.html">My dock and updated OmniFocus</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-02-17T18:57:19-08:00">Feb 17</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-02-17-microsoft-is-getting-cool-but-not-its-website.html">Microsoft is getting cool (but not its website)</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-02-10T02:18:30-08:00">Feb 10</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-02-10-monitor-progress-of-your-unix-pipes-with-pv.html">Monitor progress of your Unix pipes with pv</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-01-21T16:30:51-08:00">Jan 21</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-01-21-web-design-microsoft-vs-apple.html">Web design: Microsoft vs Apple</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-01-10T09:30:02-08:00">Jan 10</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-01-10-fonts-why-chinese-web-design-is-hard.html">Fonts: why Chinese web design is hard</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2015-01-01T22:49:39-08:00">Jan 01</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2015-01-01-os-x-system-ruby-encoding-annoyance.html">OS X system ruby encoding annoyance</a> -</td> -</tr> -</table> -<h2 class="blog-index-year-title" id="2014"> -2014 -</h2> -<table class="blog-index-yearly-index"> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-12-23T00:51:05-08:00">Dec 23</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-12-23-mpv-launcher.html">mpv launcher</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-12-22T12:42:16-08:00">Dec 22</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-12-22-10k-images-on-imgur.html">10k images on imgur</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-12-19T14:08:57-08:00">Dec 19</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-12-19-app-suggestion-dropzone-3.html">App suggestion: Dropzone 3</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-12-14T17:42:55-08:00">Dec 14</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-12-14-the-google-chrome-comic-a-classic.html">The Google Chrome Comic — A classic</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-12-14T10:06:02-08:00">Dec 14</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-12-14-speeding-up-emacs-with-emacsclient.html">Speeding up Emacs with emacsclient</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-12-13T21:47:31-08:00">Dec 13</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-12-13-the-mac-like-evernote.html">The Mac-like Evernote</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-12-10T22:45:34-08:00">Dec 10</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-12-10-omnifocus-change-sync-behavior-mac-and-ios.html">OmniFocus: change sync behavior, Mac and iOS</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-12-05T21:09:10-08:00">Dec 05</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-12-05-distraction-free-writing.html">Distraction free writing</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-11-30T17:20:20-08:00">Nov 30</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-11-30-opera-style-advanced-keyboard-shortcuts-in-safari.html">Opera-style advanced keyboard shortcuts in Safari</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-11-28T19:05:59-08:00">Nov 28</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-11-28-going-diceware.html">Going Diceware</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-11-28T00:18:19-08:00">Nov 28</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-11-28-given-infinite-time.html">Given infinite time</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-11-26T00:22:16-08:00">Nov 26</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-11-26-original-images-in-day-one-journal.html">Original images in Day One journal</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-11-25T16:28:30-08:00">Nov 25</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-11-25-i-got-16-gigs-of-ram.html">I got 16 gigs of RAM</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-11-24T20:54:36-08:00">Nov 24</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-11-24-why-i-abandoned-mathjax-and-fell-back-to-pdf.html">Why I abandoned MathJax and fell back to PDF</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-11-24T12:42:25-08:00">Nov 24</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-11-24-iphone-photography-frustration.html">iPhone photography frustration</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-11-20T09:48:15-08:00">Nov 20</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-11-20-dropbot-for-geeks(r).html">Dropbot for Geeks®</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-11-19T20:40:37-08:00">Nov 19</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-11-19-convolution-of-irreducible-characters.html">Convolution of irreducible characters</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-11-11T13:31:25-08:00">Nov 11</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-11-11-re-encoding-everything-for-iphone-6-plus.html">Re-encoding everything for iPhone 6 Plus</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-11-10T11:11:46-08:00">Nov 10</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-11-10-average-phone-plan-in-the-u-dot-s-costs-ten-time-as-much-as-that-in-the-u-dot-k.html">Average phone plan in the U.S. costs ten time as much as that in the U.K.</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-11-07T23:56:31-08:00">Nov 07</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-11-07-interstellar.html">Interstellar</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-11-06T11:08:45-08:00">Nov 06</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-11-06-2014-nobel-prize-in-physics-led-lights-seriously.html">2014 Nobel Prize in Physics — LED lights, seriously?</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-11-05T22:17:01-08:00">Nov 05</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-11-05-apple-is-pushing-yosemite-hard.html">Apple is pushing Yosemite hard</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-11-05T10:37:58-08:00">Nov 05</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-11-05-list-youtube-playlist-with-youtube-dl.html">List YouTube playlist with youtube-dl</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-11-02T15:06:07-08:00">Nov 02</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-11-02-vobcopy-dvdbackup-etc.html">vobcopy, dvdbackup, etc.</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-10-29T11:26:29-07:00">Oct 29</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-10-29-fun.html">Fun</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-10-28T20:49:24-07:00">Oct 28</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-10-28-google-drive-no-selective-subfolder-sync.html">Google Drive — no selective subfolder sync?</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-10-28T01:57:06-07:00">Oct 28</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-10-28-mou-1-dot-0-fundraiser-goal-reached.html">Mou 1.0 fundraiser: goal reached</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-10-27T09:44:51-07:00">Oct 27</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-10-27-onedrive-goes-unlimited.html">OneDrive goes unlimited</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-10-26T23:29:47-07:00">Oct 26</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-10-26-audio-cd-slash-dvd-to-iso-image-on-os-x.html">Convert Audio CD/DVD to ISO image on OS X</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-10-26T00:02:22-07:00">Oct 26</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-10-26-disk-visualizer-daisydisk.html">Disk visualizer: DaisyDisk</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-10-25T13:26:02-07:00">Oct 25</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-10-25-os-x-package-receipts.html">OS X package receipts</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-10-24T16:41:36-07:00">Oct 24</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-10-24-charles-munger-donated-$65m-to-kitp.html">Charles Munger donated $65M to KITP</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-10-23T20:03:22-07:00">Oct 23</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-10-23-ripping-copy-protected-dvd-with-mpv.html">Ripping copy-protected DVD with mpv</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-10-21T11:40:14-07:00">Oct 21</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-10-21-get-rolling.html">Get rolling</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-10-20T17:37:45-07:00">Oct 20</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-10-20-help-mou-hit-1-dot-0.html">Help Mou hit 1.0</a> -</td> -</tr> -<tr> -<td class="blog-index-post-date"> -<time class="date" datetime="2014-10-20T16:53:00-07:00">Oct 20</time> -</td> -<td class="blog-index-post-title"> -<a href="/blog/2014-10-20-hello-octopress.html">Hello, Octopress!</a> -</td> -</tr> -</table> -</div> - </article> - <hr class="content-separator"/> - <footer class="footer"> - <span class="rfooter"> - <a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> - <a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> - </span> - </footer> - </body> -</html> diff --git a/build/pub/15-18.html b/build/pub/15-18.html deleted file mode 100644 index 576a683e..00000000 --- a/build/pub/15-18.html +++ /dev/null @@ -1,172 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2012-05-26" name="date"/> -<title>十五岁,十八岁</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme-chinese-article.css" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">十五岁,十八岁</h1> -<div class="article-metadata"> -<span class="article-author">王之铭</span><br/> -<time class="article-timestamp" datetime="2012-05-26">二〇一二年五月廿六日</time> -</div> -</header> -<h2 id="序">序</h2> -<p>高中毕业前夕,我为南京师大附中2012届毕业典礼的诗朗诵环节写了这首诗。具体成诗时间我已不得而知,大约是典礼前几周吧。毕业典礼于2012年5月26日举行,题名“青春是美丽的”。母校的网站上有部分图片和资料。<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a></p> -<p class="date-tag"> -2016年7月9日 -</p> -<hr/> -<div class="poem"> -<p>标本林古木轻舒枝干<br/> -鲁迅园瀑布水声潺潺<br/> -未名湖畔清风拂过面颊<br/> -又悄然吹进你我心田<br/> -桃李阁的藤萝<br/> -自萧索至繁花从落英到绿叶<br/> -一个轮回于百年校史不过惊鸿一瞥</p> -<p>十五岁<br/> -又一群刚告别儿童节的孩子</p> -<p>以为自己早已长大<br/> -以为自己无所不晓<br/> -一点点自大 一点点轻狂<br/> -满怀憧憬走进学校</p> -<p>崭新的天地铺开在面前<br/> -万紫千红 分外妖娆<br/> -世界忽然绚烂了你我忘情地奔跑<br/> -渐渐明白自己什么也不知道</p> -<p>什么也不知道?<br/> -是不是有点可笑?<br/> -不 一颗无畏的心<br/> -才是最最重要</p> -<p>生命刚刚展开<br/> -跌倒总可以重来<br/> -奋起去推常人不敢靠近的大门<br/> -否则我们凭什么叫附中人?</p> -<p>沿途的困难挡不住勇者<br/> -一时的失落又算得了什么?<br/> -挑战 人生才精彩<br/> -青春 永远不言败</p> -<p>忙到无暇回头是少年的格调<br/> -只顾着飞 飞得更高<br/> -匆匆奔走在校园的大道<br/> -你我是否忽略了身边那些悄悄——</p> -<p>标本林古木轻舒枝干<br/> -鲁迅园瀑布水声潺潺<br/> -未名湖畔清风拂过面颊<br/> -又悄然吹进你我心田<br/> -桃李阁的藤萝<br/> -自萧索至繁花从落英到绿叶<br/> -一个轮回于百年校史不过惊鸿一瞥<br/> -只是——<br/> -有一双无形的眼睛<br/> -凝视着你我每一个人<br/> -静静地<br/> -目送你我成长</p> -<p>十八岁<br/> -又一群即将远走高飞的年轻人</p> -<p>曾经那样渴望毕业渴望自由<br/> -如今竟有淡淡的离愁<br/> -灯下疾书中猛地停笔<br/> -蓦然回首——<br/> -去梳理那些恍如隔世 又如此鲜明的记忆</p> -<p>当年你我有着同样朦胧的梦想<br/> -当年你我其实不懂什么叫追求<br/> -当年你我打打闹闹不知轻重<br/> -当年你我心眼儿挺小偶尔闹闹别扭</p> -<p>你我在广阔天地间追寻生命的碎片<br/> -师长好友书籍活动都是宝贵的体验<br/> -像一株小树 缓缓萌芽——<br/> -渐渐你我找到了自己的灵魂——<br/> -于是有了清晰的梦想走上了不同的路线</p> -<p>吃喝玩乐的闲扯渐渐缩短<br/> -往昔的好友 可曾悄悄疏远?<br/> -不——<br/> -也许话语少了 那是心照不宣<br/> -读着朋友们惜别的日志<br/> -一点一滴全浮现在眼前</p> -<p>捧起一张当年的相片<br/> -你我可曾淡然一笑<br/> -多少次以为我们已经长大<br/> -回头看还是那样稚嫩幼小</p> -<p>如今真的十八岁了<br/> -心底存放着十八年的美好<br/> -有那些经年不变的温情<br/> -也有那些相伴太久的悄悄——</p> -<p>标本林古木轻舒枝干<br/> -鲁迅园瀑布水声潺潺<br/> -未名湖畔清风拂过面颊<br/> -又悄然吹进你我心田<br/> -桃李阁的藤萝<br/> -自萧索至繁花从落英到绿叶<br/> -又一个轮回于百年校史不过惊鸿一瞥<br/> -只是——<br/> -有一双无形的眼睛<br/> -凝视着你我每一个人<br/> -静静地<br/> -目送你我成长</p> -<p>(高潮)<br/> -一百一十载 春去秋来<br/> -一百一十载 花谢花开<br/> -春风化雨 润物无声<br/> -谆谆诲人 从未倦怠</p> -<p>万千十五岁学子<br/> -带着十五岁的躁动<br/> -争先恐后 蜂拥而来<br/> -来享受青春的精彩</p> -<p>千万十八岁英才<br/> -怀着十八岁的热情<br/> -扬帆启航 振翅远去<br/> -去创造崭新的时代</p> -<p>你我只是平凡的万千分之一<br/> -却拥有各自绝版的回忆<br/> -时光将洗去一切棱角<br/> -沉淀下永不褪色的美丽</p> -<p>神州大地有太多的附中<br/> -但在你我眼里 附中只是唯一<br/> -走出这片土地 不再时常提起<br/> -但是,附中啊,我们永远不会忘记</p> -<p>(尾声)<br/> -回头看,你我青春年少<br/> -向前望,你我心比天高<br/> -十八岁的花季没有泪水<br/> -告别时亦当高歌、欢笑</p> -<p>让我们把感伤抛在脑后<br/> -让我们的呼声直干云霄<br/> -附中,我们为你骄傲!<br/> -附中,你终将为我们自豪!</p> -</div> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>新闻页面见<a href="http://58.213.145.148/Press/ViewDetails.aspx?id=3997">此链接</a>。如网页失效,请参见<a href="https://web.archive.org/web/20160709123341/http://58.213.145.148/News/20120526/20120526113211.html">Wayback Machine</a>。<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/pub/autobiography-up-to-college.html b/build/pub/autobiography-up-to-college.html deleted file mode 100644 index a98fbd5c..00000000 --- a/build/pub/autobiography-up-to-college.html +++ /dev/null @@ -1,243 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2012-05-07" name="date"/> -<title>自主学习,自由成长</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme-chinese-article.css" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">自主学习,自由成长</h1> -<div class="article-metadata"> -<span class="article-author">王之铭</span><br/> -<time class="article-timestamp" datetime="2012-05-07">二〇一二年五月七日</time> -</div> -</header> -<h2 id="序">序</h2> -<p>本文算是我十八岁以前的自传,为二〇一二年接受采访前所作。比起说,我更会写,于是写了这篇稿件供记者参考。</p> -<p>同年,我烧毁了中学时代所有的手稿,而本文由于被学校发布到网站上<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a>而成为了硕果仅存的几篇之一。只可惜网上流传的版本曾经校办轻度摧残(最明显的特征是一众突兀、尴尬、时而断章取义的粗体小标题),少数段落已面目全非。</p> -<p>时至昨日,我才知道家里还留有一份原稿的打印件,于是本文的原貌才得以重见天日。发表在这里的版本经过了轻度的编辑——英文和阿拉伯数字已尽可能替换为中文。当年我还没有为中文的纯粹性而担忧。</p> -<p>我并不后悔在火光中湮灭了大片的回忆。但谨以此文作为少年时代最后的纪念。</p> -<p class="date-tag"> -2016年7月10日 -</p> -<hr/> -<h2 id="童年">童年</h2> -<p>我天性热爱自由,不喜欢约束。而我的童年也是自由自在的。</p> -<p>有些父母从幼年时就注重孩子的学习能力开发。又有些天才儿童在幼年时就展现出超高的天赋,一岁开始识字、三岁开始背诗、七岁自学微积分等等,这些例子不少。不过我和这些都沾不上边。父母似乎从来没有教过我识字啦、算术啦,这些都只是在幼儿园跟着老师稍稍学了一些。</p> -<p>我上的小学是离我家很近的中山小学。不像那些以繁重课业、激烈竞争闻名的“名校”,我在中山小学学得很轻松,每天按时放学回家,做完不多的作业,时间就是自己的了。一直到小学二三年级,我从未试过“超前”。学校的课业对我来说挺简单,考试成绩也都不错。我按部就班地走着,享受着快乐的童年。(现在,大多数孩子的快乐童年似乎被剥夺了?)</p> -<p class="skip"> -</p> -<p>其实,父母并不是没有培养我,只是他们换了一种方式。我的妈妈是一位很有理念的母亲,她没有让我早早识字背诗学算术,而是培养我的艺术才能。</p> -<p>从三岁半起,我就开始学习音乐和美术。音乐方面我学的乐器是电子琴;美术方面我学过各种技法,一开始大概是儿童画。我并不很自觉;三岁半的孩子肯定是喜欢偷懒的。在电子琴方面,妈妈对我非常严格,总是监督我练习。我练琴时大概经常哭闹吧,以至于爸爸曾经劝妈妈放弃。但是妈妈逼着我坚持下来了。我练了五年电子琴,从四级一直考到十级。十级证书是二年级暑假拿到的。那时妈妈问我要不要继续学双排的电子琴,我说算了。如今想来挺后悔。最近正要重拾键盘。美术则持续了更长的时间,一直学到将近小学毕业。</p> -<p>现在回头看来,早年的艺术训练是非常珍贵的。它们陶冶了我的性情,在我内心深处植下了审美的种子,让我爱上了文学艺术,也让我对周围的世界有一种敏感而神奇的洞察力。这种洞察力对我以后的一切都有巨大影响。它影响了我生命发展的轨迹;而现实地说,我想它也在录取中扮演了重要的角色。这些后面还会谈到。</p> -<p class="skip"> -</p> -<p>小学阶段还有两件事值得提起。</p> -<p>我说过我不喜欢约束,所以我一直不太遵守纪律。记得四五年级的时候,我上课总是不听讲,在课桌肚里面看书,以小说为主。有短篇的,也有长篇的。长篇小说大多是西方经典,大多数不太适合我那时的年龄。四大名著也看,看原著,《水浒》、《三国》、《红楼》都看过好多遍。上课不听讲自然是不好的,但那段时间我确实看了不少书。那段时间的阅读大概打下了我精神世界的基石。</p> -<p>到了五六年级的时候,我的语文老师让我们写小说。这真是一个创举。其实我一直很想写自己的小说,只不过缺乏动力,每次写了开头就不了了之了。现在有了老师的要求,我自然有了力量,开始了创作。我们写小说是各人写各人的。不过组成五人小组,共用一个活页本,每周活页本轮转,轮到我时我就把自己新写的一章放进去,同时还可以欣赏其他几位的成果。每次我写的都是最多的,别人一章写四五百字最多一千字,我则总是写到两三千,有一次甚至写了将近一万字。写这么多是需要时间的,我常常整晚伏案疾书,当然,很多时候上课时间又被借用了,呵呵。</p> -<p>现在回头看当年的作品,肯定很幼稚啦。不过,写自己的小说总是很开心也很充实。而且,我的写作能力也得到了相应的锻炼吧,毕竟,不论质量如何,我写作文时从来没有出现过挤牙膏凑字数的情况。</p> -<p>我的小学生活就是这样轻松愉快,我很感谢我的母校,她给了我充足的课余时间去做我喜欢做的事情。我并不是贬低那些“名校”的高强度教育,毕竟,教育是因人而异的,不同人适合不同的环境。只是,由于我天生热爱自由讨厌约束,并且客观地说,我也有一定自主学习能力,所以,这种自由自在的氛围最适合我。我很幸运地遇到了我的母校,度过了快乐的童年。</p> -<h2 id="竞赛历程">竞赛历程</h2> -<p>参加学科竞赛有一点偶然成分。</p> -<p>因为小学课业很轻松,有不少课余时间,所以二年级暑假时经人介绍,我去参加了奥数培训班。去了之后感觉学得还不错,也挺有兴趣,就坚持了下去。</p> -<p>记得三年级的时候,有一次去玄武区少年宫上课,大概是记错了时间到早了,教室里在上四年级的课。妈妈就鼓励我进去听听。我一开始有点害怕,怕自己听不懂,但真的进去听了之后,发现其实还有不少我会的东西。从此我就把课从三年级调到了四年级,走上了“超前学习”的历程。</p> -<p>在那之后,我一直走在同龄人的前面,提前学习数学课程,参加高年级的竞赛,成绩还是不错的。进入初中后,我受学校老师的鼓励学习信息学竞赛,一学就是四年。进入高中之后,又参加了物理竞赛。数学、物理和信息本来就是我最感兴趣的内容,所以学起来挺有劲头。化学竞赛的学习我也参加了一些,但由于对化学兴趣稍低,所以后来退出了。尽管如此,化学竞赛的学习还是让我迅速掌握了高考化学内容,使我应对课业时游刃有余。</p> -<p class="skip"> -</p> -<p>在学习竞赛内容、参加学科竞赛的同时,我一直坚持着一个理念,就是“学有余力才搞竞赛”。尽管学习拔高的内容需要不少时间,但我一直保证自己在学校的学业成绩名列前茅。事实上,通过学习理科竞赛内容,可以站在更高的层面上俯视各门理科课程,学得轻松。语文方面,由于我热爱文学,喜欢动笔写,所以水平还不错。英语方面,关键就是多读,放声朗读,读得多了,语感自然就有了。我从小学三年级刚开始学英语时就习惯大声朗读,所以语感一直保持得不错。其他课程方面,上课好好听,课后做好作业(作业不多),用心理解,也就不会有问题了。</p> -<p>现在有很多人反对学科竞赛,就是因为许多人把竞赛当作了升学的工具,放弃了其他所有去攻竞赛。我估计有人是这样想的:反正我到大学是学物理,那语文有什么用?历史有什么用?地理有什么用?这种想法其实是极为错误的。人,首先要有广度,才能谈得上深度。这个问题后面还会谈到。学习竞赛前,基本的课业是必须保证的。如果竞赛变成一种“学有余力”后拓展性研究性的学习,竞赛就有百利而无一害了。</p> -<p>这点我感觉附中做得很好。附中在高一时向同学们开放各门竞赛课程,同学们可以先去听课,从基础学起,如果感觉不适应,可以随时退出。这样,同学们既可以挑战自我,又可以根据自身情况作出合理安排。即使退出了,之前学的竞赛基础对于常规课业也有很大的帮助。</p> -<p class="skip"> -</p> -<p>接着谈谈我又竞赛走向北京大学的历程。</p> -<p>最正规的、受教育部认可的竞赛当然是高中阶段的五大联赛,即数学、物理、化学、生物和信息学。</p> -<p>我在高一时就幸运地进入了约九人的(具体人数记不太清了)数学省队,代表江苏省参加了在重庆南开中学举办的第二十五届中国数学奥林匹克。当时考得不太好,只得了银牌。虽然高一获得银牌已经不算易事,但考虑到成绩不算好,另外离升学还很遥远,我当时没有联系大学。</p> -<p>一年以后,我代表江苏省赴吉林长春东北师大附中再战中国数学奥林匹克,结果顺利获得金牌并进入约五十人的国家集训队。就在那时,我获得了北京大学数学学院的预录取,提前摆脱了升学的烦恼。</p> -<p>之后的竞赛路不太顺畅。2011年3月,我参加了在福州一中举办的为期半个月的国家集训队选拔,结果未能进入六人国家队。2012年1月,我在陕西西安西北工大附中再收一枚中国数学奥林匹克金牌,再次进入国家集训队,但最终在江西南昌大学附中又一次与国家队失之交臂。</p> -<p class="skip"> -</p> -<p>回想我的高中竞赛历程,附中给了我太多的便利、太多的帮助。</p> -<p>从高一下学期起,学校就批准我数学课免修,让我在图书馆里自学更深的数学课程。</p> -<p>高二时,为了备战中国数学奥林匹克和国家集训队,学校批准我部分课程停课自学,集中精力提高数学水平。当然,我没有滥用学校赋予我的权利,各科课程(包括小四门)都没有落下。</p> -<p>为了营造一个安静的学习氛围,学校还特批我使用教师阅览室。在教师阅览室里,我的注意力更加集中,学习效率更高。</p> -<p>高二的国家集训队恰好与小高考冲突了,也是学校一手帮我处理,使我没有后顾之忧。</p> -<p>为了进一步提高水平,学校还特地请来专家与我交流,对我进行指导。</p> -<p>每次参加比赛,我的教练陈老师总是陪着我,西南、东北、东南、西北、中部整整绕神州大地转了一圈。</p> -<p>……</p> -<p>真的很感激附中。</p> -<p class="skip"> -</p> -<p>最终未能进入国家队,摘得国际金牌,我个人感觉对学校还是有愧的。</p> -<p>我说过,我从小就不很自觉。即使到了高中,还是会浪费不少时间,并没有尽自己的全力。这点的确很惭愧。最终未能进入国家队,虽然有一些偶然因素,但最重要的还是水平还没有炉火纯青。</p> -<p>当然,我并不后悔。其实人生没什么好后悔的,做过的事情,后悔也改变不了。而且,对于人生中的那些失败的经历,还有两种解释。</p> -<p>其一,后悔是因为离成功已经很近了。就像晚了一分钟错过飞机的人肯定比晚了一小时错过飞机的人后悔,后悔其实说明我们本来离成功只有一步之遥了,也许只要改变一个小小的细节,结果就会很不一样。这种理解是说,那些值得后悔的事,只是一种激励,一种借鉴,甚至是一种肯定。</p> -<p>另一种解释是我自己的,有点玄,但我很相信这个解释,因为我人生中的很多经历印证了这一点。(当然,在这里无法展开这些经历。)这种解释简单说来是这样的:我们走上了一条路,就再也无法判断另一条路会通向何方。我们只能做一些短期的预测,表现为日常的后悔:要是我那天晚上没有看小说,认真复习了,也许我考试就考好了。但是,考试考好之后又会通向何方呢?也许,是一个更差的结局呢?人生是非线性的,有无穷多的蝴蝶效应。短期的好并不能代表长期的成功。如果一个人一天到晚把自己封闭在书桌前,只做高考题,他可能会成为高考状元(这不是在讽刺高考状元),但这真的好吗?我习惯把一切往好的方向想,虽然我以前浪费了许多时间,但这些玩掉的、消磨掉的时间真的就“浪费”掉了吗?它们就不会为我的人生提供些什么吗?我不好说。从我的人生经历来看,这些“废品”里很可能藏着千金不换的宝藏。我习惯把一切往好的方向想,我认为:其实我们的每一次选择,都是发自我们的真心,并且把我们带到了更好的地方。</p> -<p>我的想法可以概括成一句话:</p> -<p>人生的每一个经历都是有道理的。如果你还没看出它的意义,说明时候还没到。</p> -<p>我知道,这个理论完全经不起推敲,但也没有人能将它证伪。许多东西关键看你信不信,不要用逻辑去解释它。必须强调的是,这不是消极的宿命论,这不是让大家心安理得地玩游戏、浪费时间。这只是一种积极的人生态度,让大家尽可能享受丰富多彩的人生,尽可能快乐尽可能幸福;永远不要为无法改变的事伤心,永远不要为无法预料的事担心;只要认准前方的光明,剩下的只是向着光明奔跑。毕竟,人生的终极目标对每个人都一样,那就是——幸福。</p> -<p>以上是个人的人生哲学,很多是在最近才想通的。下一个部分将详细谈谈我在附中的精神发展历程。</p> -<p class="skip"> -</p> -<p>关于竞赛,还有最后三点想说。</p> -<p>第一,竞赛从客观上帮了我很多。因为竞赛成绩突出,我成功地免去了小升初的烦恼,后来又拿着北大的入场券,毫无顾虑地追逐自己的梦想。竞赛,使我受益良多。这并不是说竞赛适合每个人。只是,竞赛恰恰适合我,并且我恰恰遇到了理科竞赛这条路。就像小学一样,我必须说我是幸运的。命运给了我机遇。总体来说,我把握住了。</p> -<p>第二,一个小小的实例,来说明经历的神奇意义,来说明:一些不经意的东西,很可能会影响一生。小学的时候,有不少同学参加信息竞赛,但我从来没碰过。小升初暑假的时候,树人信息组的老师打电话给一些数学竞赛成绩较好的同学,希望我们也来试听信息的课程。我就抱着试一试的心态去了。因为完全没有程序设计的基础,我一开始也学得不怎么样吧。课程告一段落时有一次选拔,我自我感觉考得挺差,估计要被淘汰。(当时有一半左右的同学是有基础的,而淘汰的人也差不多一半?我记不清了。)但神奇的是,我们的教练孙老师似乎很赏识我,把我留了下来。(为什么赏识我呢?我至今都有点迷茫。)后来,孙老师给我提供了许多便利,让我每天中午去机房编程序。我渐渐把Pascal语言用得很熟,并且掌握了各种算法。更重要的是,我养成了许多良好的程序设计习惯,比如模块化的习惯、提高程序可读性的习惯。真正懂程序设计的人都知道,这些习惯在设计小程序时用处不大,反而会增大代码量,但就是这些细节,在设计大型程序时会发挥无穷的威力。同时,Pascal时代精通了的那些基本思想,也是终生受用的。</p> -<p>如今我在学习C和C++语言,有了多年的基础和良好习惯,上手很快,学得很轻松,代码质量也很高。这些还仅仅是表面的可见的作用。事实上,程序设计的思想扎根于我的内心深处,对我的一切思索,不论是数学的还是哲学的,都有深远的影响。</p> -<p>就是当年的一次不经意的尝试,让我受益无穷,时间愈久,愈见其力量。所以,在人生路上不要放弃任何一个尝试新事物的机会。不尝试,永远不知道那经历有多宝贵。尝试了,往往发现,结果比预期好很多。即使不如预期,一个新的经历也是人生的一笔新财富,它很可能在适当的时候大放异彩。这也是我人生哲学的一部分。</p> -<p>第三,为了学科竞赛,我必然也牺牲了一些东西。我参加的活动主要以竞赛相关活动为主,其他的活动主要是校内活动。即使是2010年夏天赴美,其主要目的也是参加American Regions Mathematical League(美国地区数学联盟)。(中国队在此次竞赛中获得国际组第一名;值得注意的是,这是中国大陆第一次参加ARML,由于签证的问题代表队里只有八名选手;而一支完整的队伍有十五名选手。我们用八名选手打败了很多代表队的十五名选手。)</p> -<p>现在,告别了高中竞赛,也确定了录取的大学,我在进行一些有意义的活动,比如参加毕业典礼的准备,又如为高考的同学们进行数学辅导。</p> -<p>我有时会想,如果没有竞赛,我是否会参加更丰富多彩的活动,全方位锻炼自己的能力,度过更加充实的高中生活?这不好说。毕竟,如果没有学习拔高的竞赛内容,我也许会花更多时间应付学校课业;我也会为了升学烦恼,无法潇洒地去尝试常人不敢想象的东西。</p> -<p>不论怎样,人生只有一回。我不需要回头猜想其他的可能。我只要把明天走好。</p> -<h2 id="附中的点点滴滴">附中的点点滴滴</h2> -<p>从进入熟人的那一天起,我就一直把自己当做附中人。光阴荏苒,一转眼已是六年。</p> -<p>在附中的校园里度过了六个春秋的我,大概是最纯粹的附中人吧。</p> -<p class="skip"> -</p> -<p>附中的理念。</p> -<p>附中在旁人眼里是一个高考导向型、竞赛导向型的学校,很容易和所谓的县中模式联系在一起。实际上,真正的附中给我们足够的空间,鼓励我们自由发展;真正的附中包容多元的发展模式,海纳百川,有容乃大。</p> -<p>不论这种教育模式是否适合所有同学,我还是要说,至少我是幸运的,因为我喜欢自主发展。</p> -<p>从树人一直到附中,放学从来都是准时的;我一般在学校就完成了大部分作业,回家工作量很小,剩下的时间都是自己的。即使是中考前夕最紧张的时候,我一般七点钟也就完成了作业,最晚写到九点。以前听人说中考苦、苦、苦,结果我从头“盼”到尾也没有盼来苦日子。当然,当时我所在的班是“2+4整体实验班”,基本没有中考压力。由于提前一步跨进了附中门,中考的时候心态也就更加平和。</p> -<p>另外,附中周六、周日、假期不补课,除了周六有选修课、社团活动和竞赛课以外,所有休假都是自行安排。这当然需要一定的自主能力。假如没有自主学习能力,附中也许不是最好的选择。但假如拥有这种能力,附中就是一片自由的天空。当然,缺乏自主学习能力的同学也可以在附中摸索着培养出这种能力来。也许会走一些弯路,但这对终生发展来讲,绝对是极其重要的。</p> -<p class="skip"> -</p> -<p>附中的老师。</p> -<p>附中老师不但教学水平高超,而且平易近人,和我们都是亦师亦友的关系。我对教过我或者给过我帮助的每一位老师都是感激的。</p> -<p>印象最深的老师,有初中教我信息的孙小明老师,初中教我语文的汤海涓老师,高中教我语文的倪峰老师,高中我的数学竞赛教练陈兴江老师,以及教我时间最长的两位班主任,初一、初二的刘莉老师,和从初三起教我三年的秦岭老师。</p> -<p>孙老师前面提到过了,他对我特别好,特别关心我的发展。初一、初二几乎所有的中午我都是在孙老师的机房度过的。在我初中毕业以后,孙老师又和我长谈过很多次,还邀请我参加过他组织的活动。我知道录取结果后,第一个想起的人就是孙老师,想起他多年的照顾与鼓励,想起他对我殷切的期望。</p> -<p>我的初中、高中两位语文老师汤老师和倪老师,都饱读诗书,满腹经纶,而且很有思想。他们的语文课总是像讲座一样,介绍的东西很多很广,娓娓道来;又像讨论班一样,鼓励我们自己找出答案,而且是在讨论中不断深入。有时,语文课上持不同观点的同学们会展开辩论,争先恐后。我也曾是讨论的中坚力量之一,只不过后来因为竞赛、留学准备等事情不得不停课了,至今觉得有点遗憾。这些语文课看上去跟考试完全没有关系。但通过这些课程培养出的自主思考理解能力,一方面是应试时阅读理解和作文的核心,另一方面更是一个独立自由的精神存在所必需的特质。语文,不仅仅培养语言文字的能力。母语与人的精神世界联系往往是最紧密的,语文,正是通过母语直接刺激人的精神世界,从而深刻影响人的整个存在。我想,在附中,最让我受益的,就是语文教育。</p> -<p>陈老师前面已经提到过了,一直陪我走来,很辛苦。</p> -<p>而我的两位班主任老师,都是严格的典范,受到很多同学的非议,但我知道,她们的严格,是认真负责的表现。我的确不喜欢约束,但老师的用心,我能体会到。相信那些曾经对老师不满的同学们有一天也会理解的。</p> -<p>其实,不仅仅是附中的老师,我的成长过程中还有很多人提供了巨大的帮助,包括南师大的夏建国教授,等等。我真心感谢每个帮助过我的人——其中最重要的是我的父母。没有他们的支持,我不可能走到今天。</p> -<p class="skip"> -</p> -<p>附中的同学。</p> -<p>学校如果只是简单地传授知识,那么学校几乎可以由图书馆替代。真实的学校不是这样的。学校最大的功能也许就是把一群同龄的年轻人聚集在一起,让他们互相影响,互相启发。</p> -<p>附中的同学们是优秀的,充满活力的,富于创造的,分外可爱的。</p> -<p>我至今犹记得初中时我们自己发明的游戏,犹记得我们开过的每个玩笑,犹记得我们创作或改编的打油诗,犹记得借用上课时间奋笔疾书写成的搞笑文学(我好喜欢借用上课时间啊),犹记得我们为运动会入场式一遍遍排练,犹记得我们为英语节付出的创意与努力。初中也许是十八年中最美好的日子吧,我想。</p> -<p>高中的同学们依然给我留下了许多美好的回忆。但是由于停课时间较长,我错过了许多和同学们在一起的日子,实在有些遗憾。</p> -<p class="skip"> -</p> -<p>附中的环境,以及我在附中的故事。</p> -<p>附中的校园是园林式的,幽静而美丽。</p> -<p>停课的日子里,我常常独自漫步在校园里,在鲁迅园,在小溪边,在标本林里,在未名湖畔。</p> -<p>而高一的时候,教室的阳台恰好面向标本林。我总是坐在阳台上,静静地注视着摇曳的树木,静静聆听风吹过的声音。</p> -<p>这样的校园,最适合思考,也最容易挑起散文与诗的情思。</p> -<p>而附中提供的大量自主安排时间,让我自由地释放自己的能量。</p> -<p>我本来就很喜欢写作,高一那年冬天时,这种喜欢渐渐发展为热爱。我开始用笔记录自己的一切思想。我疯狂的写着,几乎每天都会写上千字。随笔本一页一页翻过去,上面写满了校园的景色、景色里蕴含的宇宙的真谛、我林林总总的对人生的思索以及对哲学的探寻。还有一份份厚厚的读书报告。在附中,高中阶段要提交十二份阅读文学名著的读书报告。从我奋发写作开始,我的读书每份报告都不曾低于万字。文字总是很自由,只是用名著作为引子,将阅读的名著映射到自己的人生,抒发自己真切的感情。这才是最真的读后感吧。</p> -<p>这种高强度的写作保持了一年半以上。之后,即使因为种种原因,写的频率减少了,但我早已把钢笔当作了思考的工具,每当我迷茫时,就提起笔记下些什么。其实,人的大脑也是有中央处理器的,中央处理器只能放那么多东西。只有把脑海里的东西写下来,写到“外存”上,中央处理器才可以处理更多的内容。而写作的过程,是一个组织的过程,这种组织必然会把朦胧的念头清晰化,同时发现更深的层次,最终达到纯粹思想无法到达的境界。我没有列提纲的习惯(除非想法特别多时稍稍记一下要点以防忘掉)。我总是从一个基本的念头出发,随心所欲地写,让笔随着倾泻的思路自然地流淌。最后得到的东西总是远超过一开始所想的。考场作文也不例外,我只是想好一个开头和一个中心思想,然后就顺其自然。实践表明往往这种文章是越写越好,因为思路会渐渐打开,超越原来的立意。考试时我的作文经常远远超出字数限制,其他同学时常惊讶不已。我并不是说我会写作,并不是说我文章写得好。也许我的大多数文章在他人看来一钱不值。不过,我自信我是一个真正掌握了写作也用好了写作的人,因为我为自己而写,快乐地写,满足地写,通过写作找到了自己的许多心灵碎片,把写作融入了自己的生命。我的人生哲学,大多数都是写着写着顿悟的。</p> -<p>在附中的这段日子,附中的课程,以及我自己的思索,构建起一个复杂的精神世界。</p> -<p>我即将从附中毕业了,但这个精神的骨架,会陪伴我走过一生。</p> -<p class="skip"> -</p> -<p>很遗憾地,由于个人的特殊性,我并没有体验过附中的全部生活。</p> -<p>我体验过的那一部分,那样值得回味;我又要说,我是幸运的,因为附中给了我一个自由的精神家园。我没体验过的那一部分,我不好妄加评论;不过,我相信它同样精彩。</p> -<p>感谢附中让我体验了一个附中人应该体验的;也感谢附中充分尊重我的特殊性,并给予最大的支持。</p> -<p>六年,很美好。</p> -<p>附中,我的母校,会更加美好的。</p> -<h2 id="出国始末">出国始末</h2> -<p>我很早就想出国接受最先进的本科教育,但是一直没有付诸行动。</p> -<p>直到2011年四月从福州的数学国家集训队回来,我才开始着手打听出国的具体申请流程。</p> -<p>当时时间已经很紧了,而我手握的唯一优势是:我已经有了北大的入场券,可以大胆冲刺顶级名校,不用害怕折翼而归。</p> -<p class="skip"> -</p> -<p>留美申请的第一个项目是参加标准化考试,获得标准化考试成绩。标准化考试主要指SAT Reasoning Test(俗称SAT I)及TOEFL iBT。排名较高的院校一般都要求至少两门SAT Subject Test成绩(俗称SAT II)。其中对中国学生挑战性最大的是SAT I。满分2400分,申请斯坦福、加州理工、普林斯顿、哈佛、耶鲁、麻省理工、哥大、芝大、宾大等名校一般需要2200分以上的成绩。</p> -<p>SAT I和SAT II在大陆均不设考点,得到香港考,一年只有一月、五月、六月、十月、十一月、十二月六次。我开始准备的时候已经四月中下旬了,五月自然赶不上。而一月一日是大多数学校的申请截止日期,十二月的考试是基本没法指望的。所以我只有三次机会。比较恶心的是,SAT I和SAT II是同时进行的,也就是说去一次香港只能选考其中之一。SAT II数理化自然不成问题,但必须占用一次机会,剩下的比较困难的SAT I,我只有两次机会。</p> -<p>大多数出国的同学至少提前半年准备SAT,而我开始准备时离六月的考试不足五十天,其中还参加了一次期中考试,真正全心准备的时间只有三十天略多。而SAT是没有诀窍的,一万多词汇必须背下来,阅读必须多做。当时我不是很努力吧,考试时词汇不太过关,而六月那次考试的词汇恰好较生僻,结果不尽人意。得分在2100+档次,虽然不算低了,但只适合申请前二十的学校,离我的目标还有距离。于是,又经过一番准备后,十月份我再次走进SAT I的考场。由于同时还在准备数学竞赛,参加了国家队培训等活动,加之有些偷懒的缘故,这次水平还是不够过硬,虽然达到了2200+,但未能上2300。暑期我也在仓促准备半个月后参加了TOEFL。由于SAT I对英语水平的要求远高于TOEFL,所以准备并不吃力。结果考到了110+,应该说是高分中的平均水平。十二月考了SAT II,由于我选考的是数理化,所以轻松地拿到了满分2400。</p> -<p>总结一下,由于准备时间短、经历较分散,加之个人不够有毅力,标准化考试成绩都只是较高;达到了顶尖名校的水平,但并不出彩。</p> -<p class="skip"> -</p> -<p>由于有北京大学的坚强后盾,我并不像一般的同学申请多个层次的许多学校(保底的学校、与自身条件相当的学校以及用于冲刺的学校,这几个档次均会申请多所),也没有选校时的迟疑不决。我只选择了几所最好的学校:斯坦福、加州理工、普林斯顿、哈佛和麻省理工,并且都申请了助学金。</p> -<p class="skip"> -</p> -<p>标准化考试成绩,特别是对于顶级名校来说,只是基本的参考,用于推断一个学生是否有足够的学习能力胜任大学学习。学习能力对于顶级名校来说只是评价标准的一小部分,更重要的是一个人的其他内在特质。毕竟,顶级名校想要招收的,不是最优秀的学生,而是具有成功潜质的人。</p> -<p>申请过程中最重要的项目,当然是全方位展现自己的文书写作。</p> -<p>我的各种人生经历,尤其是文学艺术的部分在这里发挥了关键的作用。虽然我是一个理科生,但我的主打文章是从艺术的角度写的,用艺术的眼光审视科学,用审美的眼光评判科学的语言文字表达系统,借此体现自己对科学的理解。另一篇主打文章描述了我从小学一直到高中的写作历程,从写作历程中揭示自己的精神世界。这些都是长期在我脑海中盘旋的问题,于是它们反映出一个最真实的我。</p> -<p>当然,各个学校还有自己特殊的补充文章。比如,斯坦福补充了几道短问答,以及三篇小文章,主题分别是“Intellectual vitality”、“A note to roommate”以及“What matters to you”(意译一下就是:鼓舞你不断探究的精神动力、写给未来室友的一封短信和什么对你最重要)。最有意思的是加州理工补充的两篇文章,主题分别是“Ethical dilemma”和“Quirky sense of humor”,即要求展示你曾面临的一个道德困境及你的应对,以及举例说明你与众不同的奇怪的幽默感。</p> -<p>写文书的过程,是一个认识自我的过程。不得不指出,因为竞赛的缘故,我原本的生活有点儿单调。而出国准备的这段时间,我的视野渐渐放宽了;结合文书写作期间对于整个人生的回味与思考,我想通了很多事情。前面提到的很多想法,就是来自于出国准备的大半年。</p> -<p>写文书的过程,同时也是提高英文写作水平的过程。纯大陆背景及大多数有过交流经历的学生都会通过中介公司或咨询公司的帮助提高文书的质量。我所在的咨询公司拓思教育非常强调自主,顾问老师只是不断地和我交流,给我启发,文书写作的主体是自己。与顾问老师就主题进行大量探讨之后,自己写成初稿,顾问老师会对稿子提出意见。很多时候意见只是启发性的问题,启发我往某个方向深入挖掘,启发我调整文章的结构,而我在这种启发中逐渐把文章改得越来越好。我的顾问老师十分严格。尽管我准备时间较晚,进度比较紧,但一篇文章仍然会改到七八稿甚至更多。这个过程就像一个写作课程,帮助我渐渐提高英语写作的能力,以适应美国名校的高强度学习。</p> -<p class="skip"> -</p> -<p>申请的其他过程也是我自己一手完成的,比如联系老师、翻译推荐信、办理成绩单、填写各类表格、邮寄和传真各类文件等等。这个过程中,由于要接触的人、要处理的文件很多,所以与人打交道的能力以及条理性等都得到了长足的发展。</p> -<p class="skip"> -</p> -<p>申请过程中有的学校有面试,有的学校没有。比如斯坦福不提供面试,而麻省理工和哈佛就会提供。我参加的面试不多,而且都是较为随意的校友面试,所以没什么发言权。总的来说面试主题比较自由多样吧,如哈佛面试时是在星巴克,两个面试官跟我聊,基本上什么都问,连我在哪家咨询公司做材料都谈。而麻省理工面试是一边吃早餐一边谈,面试官是微软中国区的一个管理人员,学的物理不是很多,他一直让我解释相对论。</p> -<p class="skip"> -</p> -<p>我说过,我在出国申请的过程中想通了很多事情,思想也发生了巨大的转变。</p> -<p>一开始我想去美国,完全是因为美国的研究水平、学术水平;但经过大半年的深入了解,我终于明白了:大学的核心意义,在于成人,而不在于研究。所以,大学最重要的是人,是学校的老师和同学,是他们能给自己带来的影响。</p> -<p>刚开始的时候,我最喜欢的是普林斯顿(我曾把这个告诉很多人), 因为普林斯顿有最强的数学系,有据说是最美的校园,有一个好听的名字,还有爱因斯坦的光环笼罩。(我一直是个理想主义的人,我的很多选择出于感性而非理性,所以我给出的原因常常让别人难以理解。比如,Princeton为什么最好听呢?答:我就是有这种感觉。不过现在我觉得Stanford一样好听。再如,爱因斯坦光环跟我上学有什么关系呢?答:没关系,但我就是看重这个。不过,现在我想通了很多东西,这种虚名也就看得淡多了。不是说爱因斯坦是虚名。这里可以展开来解释的,但展开来就偏离主题了。)</p> -<p>而大半年之后,斯坦福成了我最心仪的学校。为什么?因为加州温和的气候。因为斯坦福八千余英亩的全美最大校园——同时也是一个美丽的校园。因为斯坦福最强的计算机科学——这是个属于信息技术的年代,一切研究、工作都是基于信息技术的,而我希望能将信息技术应用于数学与物理学基础,彻底革新人类的科学探索——我需要最优秀的信息技术教育。因为斯坦福铭于校徽上的格言:Die Luft der Freiheit weht——The wind of freedom blows——让自由之风劲吹。也因为斯坦福的官方颜色是我最喜欢的Cardinal鲜红色。又因为斯坦福的网站做得最出色最漂亮(这出于是我对艺术的敏感吧)。还有很多很多理由。</p> -<p>录取结果出来,我被斯坦福和加州理工录取了,两所学府都提供了全额助学金。幸运再一次垂青了我。我毅然地选择了斯坦福,因为“自由之风劲吹”。</p> -<p>加州理工学院每年只招收一两百名学生,都是对理工有着高度热情的年轻人。加州理工绝对是小而精悍的,但是,在这种环境中,每个人都有着类似的追求,这样一个密集的社交网络,会不会限制我的视野,使我们这样一个特殊群体的各种特质——好的和坏的,在个体身上不断强化呢?北京大学,在我看来,可能也有相似的问题,毕竟,大家都是竞赛和高考的佼佼者,组成的是一个学习能力很强的群体,但是这个群体的每个个体之间相似度非常高。</p> -<p>斯坦福大学则是一个很大很综合的学校,拥有各种院系,拥有各式背景的学生和教工。在斯坦福,我可以接触到各种各样的人,和他们交流,被他们启发,从他们身上汲取新鲜的活力。同时,斯坦福崇尚自由而广博的教育,其本科有一个专门的学业要求,即每名本科生必须在自然科学、数学科学、工程应用科学、人文科学、社会科学方面分别完成指定的学分,必须完成人文素养、写作方法、公民养成等课程,必须学习一门外语并达标。我相信,斯坦福自由而广博的发展模式,各式各样的人和活动,以及多元化的校园将会更适合我,给我一个精彩纷呈的本科生活。</p> -<p>当然,事实上,我对加州理工和北大都不是很了解,我并没有贬低它们的意思。我只是阐述了自己和斯坦福的相互适应关系。加州理工和北大也是最好的学府,但我只能选择一所学校。我很遗憾。</p> -<h2 id="总结">总结</h2> -<p>我,是幸运的。</p> -<p>我幸运地碰到了适合我的小学。</p> -<p>我幸运地碰到了适合我的竞赛。</p> -<p>我幸运地碰到了适合我的附中。</p> -<p>我幸运地选择了出国的道路,不论结果如何,仅仅申请的过程,就是十分宝贵的经历。</p> -<p>更加幸运地是,结果很让人满意,我的梦中学府——斯坦福大学向我抛出了橄榄枝。</p> -<p>当然,美国顶级名校的学习会很苦,比北大苦很多。</p> -<p>但我相信,一切经历都是宝贵的。</p> -<p>我相信,自由之风会将我带到很远、很远的地方。</p> -<p>我相信,一切都会很好。</p> -<hr/> -<h2 id="附录">附录</h2> -<h3 id="获得录取的大学">获得录取的大学</h3> -<ul> -<li>Stanford University 斯坦福大学</li> -<li>California Institute of Technology (Caltech) 加州理工学院</li> -<li>北京大学</li> -</ul> -<h3 id="助学金数额及介绍">助学金数额及介绍</h3> -<p>斯坦福及加州理工均为我提供了全额助学金,涵盖学费、住宿费及伙食费等。其中斯坦福提供的助学金每年约$59000,四年合约150万人民币。</p> -<p>我要强调一下,我这里说的是助学金,而非奖学金。</p> -<p>在美国,最顶尖的高等学府,如斯坦福、加州理工、普林斯顿、哈佛、耶鲁、麻省理工,对本科生均不发放除体育奖学金以外的任何奖学金。学校提供的一切助学金都是基于需求的,也就是根据家庭经济状况给予适当的经济援助,确保学生没有经济上的后顾之忧。</p> -<p>虽然是完全基于需求的,但不得不指出,国际生申请助学金会影响到录取。</p> -<p>宾大沃顿商学院做过统计,培养一个本科生一年的开支约十万美元。即使在消费水平较高的斯坦福,一个本科生的一年所有花费也只有$63500左右,剩下的四万美元(或者更多)由学校承担。也就是说,学校的教育是亏本的,学校是在做长线投资。提供全额助学金的话,学校就会付出更大的代价。</p> -<p>招收本土学生是为美国培养人才,而招收国际学生并提供全额助学金则很可能是斥巨资为别国培养人才。学校是以育人为主的,学校肯定希望将优秀的学子培养成才,但投资的去向自然也是重要的现实考虑之一。所以,美国顶级名校招收国际生是十分谨慎的,对国际生提供助学金就更加谨慎。可见,作为国际生获得全额助学金还是比较困难的,也是比较幸运的。</p> -<h3 id="获得的奖项">获得的奖项</h3> -<p class="undent"> -(高中阶段,仅列举省级以上官方认可的学科竞赛奖项) -</p> -<ul> -<li>2011、2012中国数学奥林匹克金牌,入选国家集训队</li> -<li>2010中国数学奥林匹克银牌</li> -<li>2009、2010全国高中数学联赛一等奖,获得保送资格并入选省队(2011年直接入选省队,未参加高中数学联赛)</li> -<li>2010、2011全国中学生物理竞赛(省级赛区)一等奖,获得保送资格</li> -<li>2010全国青少年信息学奥林匹克联赛一等奖,获得保送资格</li> -<li>2010全国高中生化学竞赛(省级赛区)江苏省一等奖</li> -</ul> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>见<a href="http://58.213.145.148/Press/ViewDetails.aspx?id=3963">南师附中网站</a>。若页面失效,请参见<a href="https://web.archive.org/web/20160710012701/http://58.213.145.148/News/20120509/20120509162146.html">Wayback Machine</a>。<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/pub/index.html b/build/pub/index.html deleted file mode 100644 index 06a04dc2..00000000 --- a/build/pub/index.html +++ /dev/null @@ -1,39 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<title>Publications</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<style type="text/css">.hidden-link { color: inherit; cursor: text; text-decoration: none; }</style> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">Publications</h1> -<div class="article-metadata"> -</div> -</header> -<p>No content <a class="hidden-link" href="autobiography-up-to-college.html">at</a> <a class="hidden-link" href="15-18.html">the</a> <a class="hidden-link" href="random-thoughts.html">moment</a>.</p> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/pub/random-thoughts.html b/build/pub/random-thoughts.html deleted file mode 100644 index bdbbad15..00000000 --- a/build/pub/random-thoughts.html +++ /dev/null @@ -1,105 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"/> -<meta content="pandoc" name="generator"/> -<meta content="Zhiming Wang" name="author"/> -<meta content="2015-4-12" name="date"/> -<title>杂谈</title> -<link href="/img/apple-touch-icon-152.png" rel="apple-touch-icon-precomposed"/> -<meta content="#FFFFFF" name="msapplication-TileColor"/> -<meta content="/img/favicon-144.png" name="msapplication-TileImage"/> -<meta content="width=device-width, initial-scale=1" name="viewport"/> -<link href="/css/normalize.min.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme.css" media="all" rel="stylesheet" type="text/css"/> -<link href="/css/theme-chinese-article.css" rel="stylesheet" type="text/css"/> -</head> -<body> -<div id="archival-notice">This blog has been archived.<br/>Visit my home page at <a href="https://zhimingwang.org">zhimingwang.org</a>.</div> -<nav class="nav"> -<a class="nav-icon" href="/" title="Home"><!--blog icon--></a> -<a class="nav-title" href="/"><!--blog title--></a> -<a class="nav-author" href="https://github.com/zmwangx" target="_blank"><!--blog author--></a> -</nav> -<article class="content"> -<header class="article-header"> -<h1 class="article-title">杂谈</h1> -<div class="article-metadata"> -<span class="article-author">王之铭</span><br/> -<time class="article-timestamp" datetime="2015-4-12">二〇一五年四月十二日</time> -</div> -</header> -<p>接到约稿后,我苦恼了很久,不知该写什么。<a class="footnoteRef" href="#fn1" id="fnref1"><sup>1</sup></a>我不是个会讲故事的人,更不是个有故事的人。我不曾飞蛾扑火地拿起过什么,也不曾急流勇退地放下过什么。我不曾经历过奋不顾身的爱情,也不曾踏上过说走就走的旅行。我只是带着仿佛与生俱来的一点执着,平平淡淡地向前走;回头看,一切都波澜不惊。</p> -<p>既然没有引人入胜的故事,我想,我不妨谈几则不甚相关的感想,这样读者随时随地可以拾起,又随时随地可以放下。所谓闻道有先后,术业有专攻。专攻的术业自然无足道;不过我应该比多数读者虚长几岁,闻道在先,就泛泛地谈些言行与人生之道吧。基本都是我上大学后想通的,一部分还处于自勉阶段。大部分内容和出不出国无关,因为道跟出不出国无关,只不过视角或许不同罢了。</p> -<h2 id="关于别人的故事">关于别人的故事</h2> -<p>四天前,我在Hacker News上看到<a href="https://news.ycombinator.com/item?id=9337863" title="Ask HN: How do you deal with professional jealousy and getting older?">一篇支持者甚众的帖子</a>,发帖者问大家如何应对职业上对他人(通常是比自己年轻的人)的羡慕或嫉妒。注意,他只有二十六岁。他这样描述自己:</p> -<div class="en"> -<blockquote> -<p>I'm a 26 y.o. software dev working on going indie. All my life, I've struggled with procrastination. I find it very hard to sit down and work on a project without an external motivator, and on many nights I end up vegging out in front of the TV or aimlessly clicking around on the internet. As a result, even though I am successful on an absolute scale — CS degree from a top-10, worked at a startup and a large company, enough savings to last a few years of solo development — by my own metric of success, I am crippled by the feeling that it's "too late". Every day, I read an article by some hot-shot young dev who has a handful of fancy projects behind his belt (not to mention a great website and design sensibility) while I have exactly zero — and he's half a decade younger than me! How will I ever be able to catch up? Experience-wise, I'm still a junior dev.<a class="footnoteRef" href="#fn2" id="fnref2"><sup>2</sup></a></p> -</blockquote> -</div> -<p class="undent"> -我想,每一个上游却不闪耀的人都会有这样的感触、这样的伤痛。至少我是如此。当我放眼世界的时候,舞台上已经渐渐充满了我的同龄人,甚至低龄人。而我,还在默默无闻地对着一个个小问题皱眉思索,万里之行中看不到一个路标。 -</p> -<p>前面我说过,我是个没有故事的人。从前,我还在刷人人网的时候,我时常会听到很多真人的故事,同龄人的故事——励志的故事,追逐梦想的故事,环球旅行的故事,等等等等。我是个挺淡泊的人,可我偶尔还是会羡慕别人的故事。但是,羡慕又能如何呢。受到别人的激励而努力工作固然是好的,但很多时候,只有沿着属于自己的乏味的路慢慢走,才能走得更远。这有些许自欺欺人的意味——也许慢慢走的你我永远都会落在“有故事的人”的后面。但是我想,看到别人照的风景好看就买个照相机屁颠屁颠到处跑的人,很难成为自己的主宰。</p> -<p>另外,我还发现了一个秘密:故事时常比真人光鲜很多,就像简历往往比真人优秀很多。人总会下意识地隐藏黑暗的一面,所以你我羡慕的,很可能是有意无意过滤过、伟岸化了的形象。更何况,这个时代的传媒太可怕了,一丁点成功就能被放大千万倍(同时,一丁点过失也能被放大千万倍);有些人,只因为恰好挣了过剩的钱,甚至是因为天生长得好看些,就被捧成了神,然后随便吹口气、写点垃圾都会被捧成圣经,而犯过的每个错误也会被美化成“必经之路”云云。你我实在没必要为此所动。退一万步讲,即使我们看到的故事百分百真实,在落幕之前,谁知道还会有怎样的跌宕?想想看,那些曾让人感动得一塌糊涂的故事,特别是那些放下一切毅然创业的故事,它们的结果又是怎样呢?你我后来听到过它们的音讯吗?写到这里,我脑海中自然地浮起一个四年前红极一时、至今令我记忆犹新的故事;我随手搜索了故事的主角,不料(或者,早有预料?)第一条结果就是“如何看待XX的失败?”。当然,失败依然不是落幕,不是结局。借这个例子我只是想说:对别人的故事看得淡一点吧,另外也不要给自己一个“不如别人”或“失败”的一刀切。这个社会已经太能一刀切了。</p> -<h2 id="关于改变">关于改变</h2> -<p>我总以为自己成长了,立场坚定了,可以给别人讲道理了(我现在何尝不是如此)。但回顾五年前、一年前、一个月前甚至昨天的自己,总会发现从前的自己好蠢。究竟从前的自己是不是更蠢并不好说,但不论如何,我发现自己对各种事物的看法总是不断改变着,并且是光滑地改变着,很少能看到转折点。既然明天自己的看法很难预测,今天的言行中就要留些余地。不要急着公开发表意见,因为人的深度往往不在于他说了多少,而在于他听了多少。不要急着跳进辩论的正反一方,因为很可能双方都是错的。不要把“我喜欢”、“我支持”作为反对的唯一理由,特别是对反对的事物一无所知时。特别是,在热血的言论旁署名的时候——不管它当时多流行——一定要三思而后行。我前阵子听说了一本书,叫《<a href="http://www.amazon.com/The-Anarchist-Cookbook-William-Powell/dp/1502994380" title="The Anarchist Cookbook">The Anarchist Cookbook</a>》,成书于上世纪70年代初越战时期的美国,其中收录了自制枪支、爆炸物、非法药物等的方法。有意思的是,作者多年来屡次要求出版商将此书下架,无果。作者本人多年后在书评里说:</p> -<div class="en"> -<blockquote> -<p>During the years that followed its publication, I went to university, married, became a father and a teacher of adolescents. These developments had a profound moral and spiritual effect on me. I found that I no longer agreed with what I had written earlier and I was becoming increasingly uncomfortable with the ideas that I had put my name to.<a class="footnoteRef" href="#fn3" id="fnref3"><sup>3</sup></a></p> -</blockquote> -</div> -<p class="undent"> -这只是个极端的例子,但它值得你我引以为鉴。 -</p> -<h2 id="关于不变">关于不变</h2> -<p>前面说了改变,这里再说说不变。人的思想的确会不断前进、不断否定自我,但这并不能成为摇摆不定的借口。人只有相对地稳定、相对地不变才能作为独立的精神个体而存在,听一篇陈词改一个主意的人只能被别人操纵于股掌之间。我说不要急着发表意见、不要急着跳进辩论的某个阵营,但当你我积累了足够的信息而能形成自己的判断时,我们应该相信并坚持自己的判断。大多数时候,有了判断并不代表要满世界宣扬,默默地坚持就好了,不轻易被人蛊惑就行了。坚持判断并不代表固执己见,所以当决定性的证据证明自己的坚持有误时,我们应该大胆地服输,然后抛下误解,前进。承认错误很潇洒。</p> -<p>我还想谈另一种不变,这种不变叫做“我不在乎”。生活总会将很多莫名其妙的问题、话题扔进你我的收件箱里,比如一个人见人谈却毫无意义的时下热点、一门从出发点就错得一塌糊涂的必修课、或者别人对你我的议论纷纷。这些浪费生命的东西来了又去、瞬息万变,而应对的方式很简单——以不变应万变,直接扔进垃圾箱。不管别人如何争论,我不在乎的东西我就是不在乎,这样生活会宁静很多、轻松很多。相信我,我们已经被生活强加了太多的东西;仅以我所在的学术界为例,我们时常要花与研究相当甚至更长的时间百无聊赖地写论文、改论文(参见Scott Aaronson的《<a href="http://www.scottaaronson.com/blog/?p=478" title="Waste papers">Waste papers</a>》),甚至有些人在<a href="http://arxiv.org/">arXiv</a>上发个预印都得掐时间点——文章在email digest里出现的位置有时很大程度影响到引用数。这些都是不得已而为之,是生活、职业的枷锁。我们已经有那么多无法摆脱的枷锁,为什么不在少数有选择的时候酷酷地说声“我不在乎”呢?</p> -<p>很多问题,在七十亿人的基数下真的很复杂,但放在一个相对平均的个体身上,却非常简单。我想,只有学会把不重要的方面尽量简单化,才能全力追求值得付出生命的东西。</p> -<h2 id="关于爱国">关于爱国</h2> -<p>这个话题有点敏感。</p> -<p>当我走出国门的时候,我能切实地感到:我是中国人。这是值得自豪的事。(我知道少数人似乎以此为耻,似乎是抱着逃离的态度出国的;对此我只能说,道不同不相为谋。)而不少海外国人的某些言行实在让我痛心。</p> -<p>首先是崇洋媚外,传播不尽不实信息。后者在留学生中不多,前者却屡见不鲜,觉得外国月亮圆的大有人在。我觉得,崇洋媚外是我国当前一个巨大的问题;缺乏见闻的平民把外国当做天堂尚可理解,可一些相对见多识广的人也是如此,还妄谈自己不了解的事物、毒害无知者的思想,这就让我难以接受了。举三个例子。第一个例子,几年前曾有一篇“哈佛图书馆凌晨四点座无虚席”的文章流传甚广<a class="footnoteRef" href="#fn4" id="fnref4"><sup>4</sup></a>,一时在名校圈内传为笑谈。最搞笑的是,作者居然声称凌晨四点“湖边、路边,许多学子正在聚精会神地晨读着”。晨读?!?凌晨四点还在外面晃悠的,一般不是可疑人物就是通宵派对的(通宵做实验的研究生一般都在实验室里睡);除非是考试前夕,平时拖着的人都去图书馆抱佛脚了——还是不会有傻冒在湖边、路边等着冻感冒。(当然,据我了解,某些同学的正常作息时间就是五点睡到下午一点,跟我们这些不争气的十二点睡到八点的凡人本质区别不大。)诚然,真正上进的人都在努力学习努力工作,可就我所知并无“凌晨四点座无虚席”那么夸张。第二个例子,很多人认为国人不文明,以公众场合大声喧哗、旅游景点“到此一游”之类为证。对这些行为,我自然是持反对态度的,但我不得不说,很多东西其实是由于民族历史文化差异而造成的行为习惯的不同,不能一刀切为“不文明”。关于在饭店等公众场合喧哗,我国人民自古以来就喜欢高朋满座、畅饮畅谈;关于“到此一游”,我国自古就有文人骚客题壁的传统,不少题壁传为千古佳话(当然也有题反诗被抓的反面教材),这也是不文明吗?这些有失瞻观的习惯在日益国际化的今天的确要改(特别是出国时要注意),但一味说国人不文明、素质低,甚至低人一等,这种态度就要不得了。反之,外国人就很有素质吗?除非我三年换了三次邻居都恰好遇到了精神病,否则你来我宿舍接受一周时不时一百二十分贝“音乐”的洗礼<a class="footnoteRef" href="#fn5" id="fnref5"><sup>5</sup></a>,你就会对美国人的素质有一个全新的认识。当然,这其实也很大程度上是习惯的问题,而不是简单的“素质低”。最后再谈谈中小学教育。现在有些教育“专家”(骗子),张口闭口就是国外的教育如何如何,仿佛说国外教育就倍儿有面子似的。其实我真不知道他们对国外教育的认知都是从哪儿来的。随便找个接受过美国公立教育(包括那些“全美最好”的公立学校)的同学来问问,你就会庆幸你出生在中国、接受了中国的义务教育和附中的一流高中教育。我不评论美国的私立教育(一方面我没怎么跟直接经历者谈过这个问题,另一方面私立教育的经费不是一般家庭能承受的——其实我对私立教育的质量也抱怀疑态度),但公立高中教师的无知程度、学生的不上进程度、总体风气的恶劣程度都是很惊人的。综上所述,我觉得,我们留学生的使命之一,就是真实反映国外的情况,打破无知者对别国夸大其实的想象,从而让国民树立对祖国的正确认识。</p> -<p>再者,盲目听信西方媒体,对我国政府持片面的反对态度。政治问题我不想多谈,点到为止。以美国为例,由于两党轮流执政和权力的(表面)分立,权力机关和传媒确实比较透明<a class="footnoteRef" href="#fn6" id="fnref6"><sup>6</sup></a>。但这仅限于国内的互相揭短。媒体、特别是主流媒体的对外态度(特别是对不同意识形态或有利益争端的国家的态度)还是基本一致且扭曲的。这不过是人之常情罢了——在国家、民族利益面前,如何定义正义?每个地方都有腐败(还是人之常情),的确有的地方轻有的地方重、有的地方合法有的地方非法,但大方向往往还是国家利益,所以我们需要多方面地看问题,而不是因为某些错误而全盘质疑出发点、全盘否认;特别是,如果你把颠覆分子、政治在逃犯的话全盘当做事实,甚至把某些人当做英雄,你就太天真了。想想前面说过的《Anarchist Cookbook》。其实西方的思想文化、科学技术、社会制度的确有很多值得借鉴之处(师夷长技以制夷,我时常考虑别国究竟为什么超过了我们——考察对象通常是美国和日本),我国权力机关的行为也的确有很多值得改进之处,但当别人说我国坏话的时候,我总是很警醒,并批判地思考他们的话究竟有多少事实成分。我可以对我祖国发牢骚,但你们不可以;这就是我对我祖国的态度。</p> -<p>其次,关于给祖国丢脸。我想,中国人在海外的形象早已被大量或经济拮据或目光短浅的前辈们毁得惨不忍睹了;并且很多我几乎目击的事实表明,这些目光短浅的自毁形象行为,还在随时随地发生着。最近几年,中国经济终于举足轻重了起来,世界终于看到了中国的潜力;值此中华民族伟大复兴的关键时刻,我恳请各位青年朋友自重自爱,积极挽回中国人的形象,让世界把我们当作一个值得尊敬的民族,而不仅仅是个待宰的人傻钱多的市场。请记住那句说烂了的话:在国外,你代表的是中国人。特别是,在别人的领地上,投机取巧、违法乱纪的小动作请收起来(我必须澄清,此类行为在美国人里其实也是很多的,但这并不能成为借口)。举个例子,每当听说某人又成功挟带了违禁土特产入境,我就无言以对——家乡的土特产真的那么重要,让您茶饭不思,非违禁而后快吗?另外,前面提到的“不文明”行为,不管是文化差异还是怎样,都应尽量收敛。你们能想象我到美国的第一个月,在图书馆桌上看到中文“篆刻”<a class="footnoteRef" href="#fn7" id="fnref7"><sup>7</sup></a>时那种噎住的感觉吗?</p> -<p>最后顺便说一句,多给父母打打电话吧。古人云:修身,齐家,治国,平天下;又云:树欲静而风不止,子欲养而亲不待。所以,在你酝酿着改变世界的同时,不要忘了家乡的亲人。</p> -<h2 id="关于社交网络">关于社交网络</h2> -<p>前面讨论的问题都比较大比较虚。我决定以一个很具体的建议作结:慎用社交网络。</p> -<p>在电子通讯日益发达的今天,我们公开说过的每一句话几乎都会被记录下来;特别是在网络上,说出的话就像泼出的水,几乎不可能消除痕迹,而且最可怕的是,全世界(至少是权力机关)都可以看到这些痕迹。不好的痕迹(也许这痕迹在产生时完全无害)很可能在未来某个时刻给你带来难以预见的伤害。你未来的雇主在录用你前可以Google你;你未来的另一半在跟你交往前可以Google你;与你共事的任何人也都可以Google你。<a href="http://arstechnica.com/tech-policy/2015/01/the-incredibly-simple-story-of-how-the-govt-googled-ross-ulbricht/" title="The incredibly simple story of how the gov’t Googled Ross Ulbricht">Ars Technica上</a>有一则关于著名黑市购物网站“丝路”头脑如何落网的故事;正如文章标题所言,该头脑身份暴露的原因很简单——特工进行了一次简单的、任何人都可以重复的Google搜索。举这个例子并不是提醒大家藏匿自己的犯罪证据,而是要强化“关于变化”一节中已提出的建议:慎留痕迹,因为互联网的检索和传播功能太强大了。</p> -<p>退一万步讲,假定你在社交网络上发的东西在现在和将来都完全无害。但当前主流的社交网络往往默认你发的任何状态都是全世界可见;你真的想对全世界直播你的生活,让任何素不相识的人掌握你的行踪、心情吗?也许你觉得,除了熟人外谁会盯着你,那你就错了。两个月前纽约时报杂志上就刊载了一篇文章,其中讨论了当前社交网络上大规模公开羞辱的现象,并详细跟踪了一名受害者的始末。这名受害者所做的只是在Twitter上对着一个很小的受众开了个玩笑,一个可能有歧义、但和她亲近的人都能理解的玩笑。但她的这条状态被曲解为种族歧视(原意是反讽),然后瞬间被转成了Twitter全球第一趋势。最后她因此丢了工作,因为给家庭蒙羞而丢了亲人的支持,并且这条状态永远留在了互联网的历史里,任何搜索她名字的人都可以看到这段过去。这绝不是个例;这种故事越来越多了。<strong>所以,即使你想使用社交网络,也请先做好隐私设置,并且在发可能有争议的内容前三思而后行。</strong>在你按发送按钮的时候,一切都会永远地留在互联网里;而你,不知道别人会怎么解读。</p> -<p>我自己几年前彻底告别了社交网络。再也不会一刷状态就是半个小时。没有社交网络,我过得很好。</p> -<hr/> -<h2 id="参考文献">参考文献</h2> -<div class="en" style="text-align: left"> -<ol style="list-style-type: decimal"> -<li>tastyface, <em>Ask HN: How do you deal with professional jealousy and getting older?</em>, Hacker News. <a class="uri" href="https://news.ycombinator.com/item?id=9337863" title="Ask HN: How do you deal with professional jealousy and getting older?">https://news.ycombinator.com/item?id=9337863</a></li> -<li>Jeff Atwood, <em>Because reading is fundamental</em>, Coding Horror. <a class="uri" href="http://blog.codinghorror.com/because-reading-is-fundamental-2/" title="Because reading is fundamental">http://blog.codinghorror.com/because-reading-is-fundamental-2/</a></li> -<li>William Powell, <em>The Anarchist Cookbook</em> and the editorial review from the author, Amazon. <a class="uri" href="http://www.amazon.com/The-Anarchist-Cookbook-William-Powell/dp/1502994380" title="The Anarchist Cookbook">http://www.amazon.com/The-Anarchist-Cookbook-William-Powell/dp/1502994380</a></li> -<li>Scott Aaronson, <em>Waste Papers</em>, Shtetl-Optimized. <a class="uri" href="http://www.scottaaronson.com/blog/?p=478" title="Waste papers">http://www.scottaaronson.com/blog/?p=478</a></li> -<li>Joe Mullin, <em>The incredibly simple story of how the gov’t Googled Ross Ulbricht</em>, Ars Technica. <a href="http://www.nytimes.com/2015/02/15/magazine/how-one-stupid-tweet-ruined-justine-saccos-life.html" title="How One Stupid Tweet Blew Up Justine Sacco’s Life">http://arstechnica.com/tech-policy/2015/01/the-incredibly-simple-story-of-how-the-govt-googled-ross-ulbricht/</a></li> -<li>Jon Ronson, <em>How one stupid tweet blew up Justine Sacco's life</em>, The New York Times Magazine. <a href="http://arstechnica.com/tech-policy/2015/01/the-incredibly-simple-story-of-how-the-govt-googled-ross-ulbricht/" title="The incredibly simple story of how the gov’t Googled Ross Ulbricht">http://www.nytimes.com/2015/02/15/magazine/how-one-stupid-tweet-ruined-justine-saccos-life.html</a></li> -</ol> -</div> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>原稿写给南师附中出国生杂志。<a class="footnotes-backlink" href="#fnref1">↩︎</a></p></li> -<li id="fn2"><p>这段话的大意是:我是一个二十六岁、正在准备单干的软件开发者。我一生都在和拖延症作斗争。没有外界的刺激我就很难静坐下来工作,于是大多数晚上我都颓废地坐在电视机前,或者在网上没有目标地游荡。结果,尽管我在绝对尺度上看起来挺成功——拥有前十名大学的计算机学历,在一个创业公司和一个大公司工作过,积累了能支持我几年独立开发的存款——从我自己的标准来看,我总觉得自己已经“太晚了”。每天我都能读到某些超强的年轻开发者写的文章,他们的简历上往往已经挂着好几个很精彩的项目(更不用说他们有很漂亮的网站和很强的设计感)——而我有足足零个。并且他们往往比我小整整半个年代!我怎么可能有追上去的那一天?从履历来说,我还只是个初级开发者。<a class="footnotes-backlink" href="#fnref2">↩︎</a></p></li> -<li id="fn3"><p>这段话的大意是:在这部书出版后的那些年里,我上了大学,结了婚,成了一些青春期年轻人的父亲和师长。我发现我不再赞同我当年的著述,并且我日益因那些署着我名字的观点而不舒服。<a class="footnotes-backlink" href="#fnref3">↩︎</a></p></li> -<li id="fn4"><p>这篇文章的源头难以确定,并且有多种版本,不过很容易搜索到。<a class="footnotes-backlink" href="#fnref4">↩︎</a></p></li> -<li id="fn5"><p>并且我已多次通过多方进行交涉,无果。<a class="footnotes-backlink" href="#fnref5">↩︎</a></p></li> -<li id="fn6"><p>但你听说过NSA吗?<a class="footnotes-backlink" href="#fnref6">↩︎</a></p></li> -<li id="fn7"><p>当然,旁边也有英文的篆刻。<a class="footnotes-backlink" href="#fnref7">↩︎</a></p></li> -</ol> -</div> -</article> -<hr class="content-separator"/> -<footer class="footer"> -<span class="rfooter"> -<a class="rss-icon" href="/rss.xml" target="_blank" title="RSS feed"><!--RSS feed icon--></a><a class="atom-icon" href="/atom.xml" target="_blank" title="Atom feed"><!--Atom feed icon--></a><a class="cc-icon" href="https://creativecommons.org/licenses/by/4.0/" target="_blank" title="Released under the Creative Commons Attribution 4.0 International license."><!--CC icon--></a> -<a href="https://github.com/zmwangx" target="_blank">Zhiming Wang</a> -</span> -</footer> -</body> -</html> diff --git a/build/robots.txt b/build/robots.txt deleted file mode 100644 index 20bab2ef..00000000 --- a/build/robots.txt +++ /dev/null @@ -1,4 +0,0 @@ -User-agent: * -Disallow: - -Sitemap: http://zmwangx.github.io/sitemap.xml diff --git a/build/rss.xml b/build/rss.xml deleted file mode 100644 index 56cfa154..00000000 --- a/build/rss.xml +++ /dev/null @@ -1,567 +0,0 @@ -<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><atom:link href="http://archive.zhimingwang.org/rss.xml" rel="self" type="application/rss+xml"/><title>dl? cmplnts?</title><link>http://archive.zhimingwang.org/</link><description>Zhiming Wang's personal blog</description><language>en-us</language><managingEditor>zmwangx@gmail.com (Zhiming Wang)</managingEditor><webMaster>zmwangx@gmail.com (Zhiming Wang)</webMaster><pubDate>Thu, 27 Apr 2017 22:29:42 GMT</pubDate><lastBuildDate>Thu, 27 Apr 2017 22:29:42 GMT</lastBuildDate><generator>pyblog (https://github.com/zmwangx/zmwangx.github.io)</generator><docs>https://validator.w3.org/feed/docs/rss2.html</docs><image><url>http://archive.zhimingwang.org/img/icon-100.png</url><title>dl? cmplnts?</title><link>http://archive.zhimingwang.org/</link><width>100</width><height>100</height></image><item><title>pyenv: compiling Python with SQLite in nonstandard location</title><link>http://archive.zhimingwang.org/blog/2016-10-26-pyenv-compiling-python-with-sqlite-in-nonstandard-location.html</link><description><![CDATA[ - -<p>This is a quick post sharing a workaround that I needed just now.</p> -<p>I was trying to compile Pythons with pyenv on a RHEL 6.8 cluster. Unfortunately <code>sqlite-devel</code> is not installed and I doubt I can convince my sysadmin to install a package for me. The lack of SQLite headers resulted in Pythons without <code>_sqlite3</code> which is essential for me. Hinting at SQLite headers from Linuxbrew with <code>CPATH</code> did not help either.</p> -<p>Digging into CPython source code, turns out that CPython only looks into <a href="https://github.com/python/cpython/blob/59fa72e34da71fb24f52251c1cc88ed3c3b14797/setup.py#L1132-L1138">a fixed set of paths</a>:</p> -<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python">sqlite_inc_paths <span class="op">=</span> [ <span class="st">'/usr/include'</span>, - <span class="st">'/usr/include/sqlite'</span>, - <span class="st">'/usr/include/sqlite3'</span>, - <span class="st">'/usr/local/include'</span>, - <span class="st">'/usr/local/include/sqlite'</span>, - <span class="st">'/usr/local/include/sqlite3'</span>, - ] -<span class="cf">if</span> cross_compiling: - sqlite_inc_paths <span class="op">=</span> []</code></pre></div> -<p>Well that's unfortunate. Luckily pyenv makes it really easy to patch Python source code; take a look at <a href="https://github.com/yyuu/pyenv/tree/master/plugins/python-build/share/python-build/patches"><code>plugins/python-build/share/python-build/patches</code></a> and you'll get the idea. Therefore, in the case of Linuxbrew'ed pyenv and SQLite, say we want to build Python 3.5.2 with SQLite support, we simply put the following patch at <code>~/.linuxbrew/opt/pyenv/plugins/python-build/share/python-build/patches/3.5.2/Python-3.5.2/linuxbrew-sqlite3.patch</code>:</p> -<div class="sourceCode"><pre class="sourceCode diff"><code class="sourceCode diff"><span class="kw">diff --git a/setup.py b/setup.py</span> -index 174ce72..774fd65 100644 -<span class="dt">--- a/setup.py</span> -+++ b/setup.py -@@ -1108,6 +1108,7 @@ class PyBuildExt(build_ext): - '/usr/local/include', - '/usr/local/include/sqlite', - '/usr/local/include/sqlite3', -+ os.path.expanduser('~/.linuxbrew/opt/sqlite/include/'), - ] - if cross_compiling: - sqlite_inc_paths = []</code></pre></div> -<p>That's it. Now</p> -<pre><code>$ pyenv install 3.5.2</code></pre> -<p>and enjoy.</p> -]]></description><author>zmwangx@gmail.com (Zhiming Wang)</author><guid isPermaLink="true">http://archive.zhimingwang.org/blog/2016-10-26-pyenv-compiling-python-with-sqlite-in-nonstandard-location.html</guid><pubDate>Wed, 26 Oct 2016 16:16:22 GMT</pubDate></item><item><title>This blog is now behind CloudFlare</title><link>http://archive.zhimingwang.org/blog/2016-09-01-this-blog-is-now-behind-cloudflare.html</link><description><![CDATA[ - -<p>Back in July I registered the domain <a href="http://zhimingwang.org">zhimingwang.org</a> and pointed this GitHub Pages-powered blog at it. Since then I have lost the HTTPS badge due to GitHub Pages not supporting HTTPS on custom domains (see <a href="https://github.com/isaacs/github/issues/156">isaacs/github#156</a>).</p> -<p>There have been a lot of discussions on isaacs/github#156 (and stupid <a href="http://archive.zhimingwang.org/blog/2016-01-18-me-too-comments-on-github.html">+1's</a> too). Among the proposed solutions is putting the website behind CloudFlare. I carefully investigated <a href="https://blog.cloudflare.com/secure-and-fast-github-pages-with-cloudflare/">this option</a> and read almost all the arguments against it. I fully understand CloudFlare's SSL models (summarized in the image below), and I do realize most if not all of the limitations of CloudFlare, including CloudFlare being a huge MITM (which is inevitable for a CDN anyway), as well as most if not all of its annoyances, including CAPTCHAs which I myself would occasionally run into when I'm browsing with PIA VPN, and JavaScript-based browser checks.</p> -<div class="figure"> -<a href="http://archive.zhimingwang.org/img/20160901-cloudflare-ssl-modes.png" target="_blank"><img alt="CloudFlare's SSL modes. I use the Full SSL mode so that both ends of the connection are encrypted. Again, I know CloudFlare is a big MITM and could be a high profile target. Credit: CloudFlare." src="http://archive.zhimingwang.org/img/20160901-cloudflare-ssl-modes.png" width="500"/></a> -<p class="caption">CloudFlare's SSL modes. I use the Full SSL mode so that both ends of the connection are encrypted. Again, I know CloudFlare is a big MITM and could be a high profile target. Credit: <a href="https://blog.cloudflare.com/secure-and-fast-github-pages-with-cloudflare/">CloudFlare</a>.</p> -</div> -<p>After careful evaluation, I decided that CloudFlare's SSL model is good enough for me. After all, this is just a damn blog, with nothing sensitive. TLS is still nice because it guards against prying eyes and unethical ad-injecting ISPs or Wi-Fi hotspots, but other than that, it isn't necessary.</p> -<p>End result: this blog is now behind CloudFlare. Readers should now see that green HTTPS badge again (note that I'm enforcing HTTPS — without HSTS though). As for CAPTCHAs, I have adjusted the firewall settings on CloudFlare's dashboard — "Security Level" to "Essentially Off" and "Challenge Passage" to 1 year, so hopefully it won't be too annoying.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-09-01-this-blog-is-now-behind-cloudflare.html#fn1" id="fnref1"><sup>1</sup></a></p> -<p><strong>09/01/2016 Update.</strong> I just realized that <a href="https://support.cloudflare.com/hc/en-us/articles/203306930-Does-CloudFlare-block-Tor-">CloudFlare supports whitelisting Tor traffic</a>. Did that.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>I don't use Tor, and don't intend to raise Big Brother's suspicion by using it, so I have no idea of the actual Tor experience.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-09-01-this-blog-is-now-behind-cloudflare.html#fnref1">↩︎</a></p></li> -</ol> -</div> -]]></description><author>zmwangx@gmail.com (Zhiming Wang)</author><guid isPermaLink="true">http://archive.zhimingwang.org/blog/2016-09-01-this-blog-is-now-behind-cloudflare.html</guid><pubDate>Thu, 01 Sep 2016 12:11:00 GMT</pubDate></item><item><title>It's 2016, and Microsoft is the only legit player who spams me without unsubscribe links</title><link>http://archive.zhimingwang.org/blog/2016-06-24-its-2016-and-microsoft-is-the-only-legit-player-who-spams-me-without-unsubscribe-links.html</link><description><![CDATA[ - -<p>I'm so tired of Microsoft spam. Microsoft is known for being intrusive accross the board, and their newsletters are no different: I literally can't name one legit company in this day and age who doesn't put unsubscribe links in newsletters.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-06-24-its-2016-and-microsoft-is-the-only-legit-player-who-spams-me-without-unsubscribe-links.html#fn1" id="fnref1"><sup>1</sup></a> I get "Azure pricing and services updates" newsletters all the time, as well as "exciting news" from Windows Insider Program (which doesn't excite me at all) every once in a short while.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-06-24-its-2016-and-microsoft-is-the-only-legit-player-who-spams-me-without-unsubscribe-links.html#fn2" id="fnref2"><sup>2</sup></a> I still occasionally receive random Chinese language promotions of Windows, presumably because I used a Windows Phone as my secondary phone for three months back home in the summer of 2013 (which was a horrible experience). Why Microsoft hasn't been regulated for spam yet, I do not know.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>To be fair, Amazon used to force promotional email on student members, but (if memory serves) I haven't seen one in ages.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-06-24-its-2016-and-microsoft-is-the-only-legit-player-who-spams-me-without-unsubscribe-links.html#fnref1">↩︎</a></p></li> -<li id="fn2"><p>"If you wish to stop receiving Windows Insider Program emails, you will need to leave the program." I guess that's the price of downloading a couple of Windows 10 insider builds.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-06-24-its-2016-and-microsoft-is-the-only-legit-player-who-spams-me-without-unsubscribe-links.html#fnref2">↩︎</a></p></li> -</ol> -</div> -]]></description><author>zmwangx@gmail.com (Zhiming Wang)</author><guid isPermaLink="true">http://archive.zhimingwang.org/blog/2016-06-24-its-2016-and-microsoft-is-the-only-legit-player-who-spams-me-without-unsubscribe-links.html</guid><pubDate>Thu, 23 Jun 2016 21:40:01 GMT</pubDate></item><item><title>Chrome is screwing with our extensions... Again</title><link>http://archive.zhimingwang.org/blog/2016-05-07-chrome-is-screwing-with-our-extensions-again.html</link><description><![CDATA[ - -<p>Chrome is growing more and more hostile by the day. See <a href="http://archive.zhimingwang.org/blog/2016-03-06-google-chrome-keeps-getting-uglier.html">Google Chrome keeps getting uglier</a> for an earlier take. What I didn't report in the earlier post is that not only can't you show/hide extension buttons as easily as before, you can't even control which buttons appear in the toolbar anymore — they come and go as they wish.</p> -<p>As if screwing the app icon, extension buttons and the overall design is not enough, now they have upped their game again. I'm running Chrome 50.0.2661.94 from April 28, and I just rebooted my machine only to be greeted with a fleeting "unsupported extensions" (or something like that) message as I launched Chrome. I digged into the extensions page, and guess what, all sideloaded extensions (except unpacked ones) have been disabled.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-05-07-chrome-is-screwing-with-our-extensions-again.html#fn1" id="fnref1"><sup>1</sup></a> This in itself may not be too surprising (Google took away sideloaded extensions from non-developers last year), except that <strong>the "enable" button, which used to work at least in developer mode, doesn't function anymore.</strong> The message is very stupid:</p> -<blockquote> -<p>This extension is not listed in the Chrome Web Store and <strong>may</strong> have been added without your knowledge.</p> -</blockquote> -<p>Bold by me. Okay, so what if they have been added <strong>with my knowledge</strong>? No way to enable legit extensions (some written by none other than myself) just because of a "may"? Here's the <a href="https://support.google.com/chrome/answer/2811969">only migration path</a> they offer, by the way:</p> -<blockquote> -<p>If you need to use a disabled extension, you can contact the extension's developer and ask them to upload their extension to the Chrome Web Store.</p> -</blockquote> -<p>Seriously? Do they honestly think Chrome Web Store serves everyone's needs? First, they have every right to refuse or take down any extension in their store. This is dangerous. What if one day they conclude that Adblock Plus is hurting their ad revenue too much and decide to take it down? Secondly, people may not want to make every extension publicly available. For instance, I have some personal extensions that I have developed on my dev machine, packaged into .crx, and installed on other machines. Some of these are publicly available (on GitHub), and others are not. It's not hard to conclude that other people may have private extensions too, and there may be extensions that are only available in some private circles. Now, people have to load unpacked extensions, which is much easier to screw up for regular folks, or they're out of luck.</p> -<p>To add insult to injury, every time I launch Chrome now, I'm greeted by this "Disable Developer Mode Extensions" message:</p> -<blockquote> -<p>Extensions running in developer mode can harm your computer. If you're not a developer, you should disable these extensions running in developer mode to stay safe.</p> -</blockquote> -<p>As if there're not enough malicious extensions in the Chrome Web Store, let alone crap. May I tell Chrome that I <em>am</em> a developer and ask it to shut up? Apparently no.</p> -<p>With the current trend in Chrome, I might want to switch to Opera again.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-05-07-chrome-is-screwing-with-our-extensions-again.html#fn2" id="fnref2"><sup>2</sup></a> The only thing preventing me from doing so right now is their new <a href="https://i.imgur.com/F8Tc67m.png">horrendous-looking fat icon</a>. However, Chrome has also destroyed their icon and I need to <a href="https://github.com/zmwangx/fileicon">replace it</a> after every update anyway, so I might as well do the same thing for Opera. We'll see.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>I'm not sure why they weren't disabled upon first launch after the update, but given the randomness of extension buttons in my toolbar with hardly any action on my part, I won't be surprised if I were told that they had messed up the extension system completely.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-05-07-chrome-is-screwing-with-our-extensions-again.html#fnref1">↩︎</a></p></li> -<li id="fn2"><p>Modern day Safari is also pretty nice, and the team is showing great attitude lately, with Safari Technology Preview and tweets like <a href="https://twitter.com/webkit/status/725725657548738561">this one</a>, for instance. However, the lack of extensions is a big road block, and the fact that the used-to-be-free Safari Developer Program has been incorporated into the $99/yr Apple Developer Program certainly doesn't help. (I used to be a member. Now I've been kicked out.)</p> -<p>Note that Safari is more locked down in a sense compared to OS X and iOS. On OS X you can apparently run unsigned software; on iOS 9 and later you can create personal provisioning profiles with just an Apple ID. Neither is true for Safari extensions, which still require a signing key from developer program membership. I wonder if Apple will introduce free keys for personal use on Safari, too.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-05-07-chrome-is-screwing-with-our-extensions-again.html#fnref2">↩︎</a></p></li> -</ol> -</div> -]]></description><author>zmwangx@gmail.com (Zhiming Wang)</author><guid isPermaLink="true">http://archive.zhimingwang.org/blog/2016-05-07-chrome-is-screwing-with-our-extensions-again.html</guid><pubDate>Sun, 08 May 2016 01:49:26 GMT</pubDate></item><item><title>Emacs's got a redesigned website!</title><link>http://archive.zhimingwang.org/blog/2016-04-10-emacss-got-a-redesigned-website.html</link><description><![CDATA[ - -<p>I've been very busy lately, so I haven't posted anything for a month. As a result, I have many topic notes sitting in Notes.app — including the kik-left-pad-npm drama, the Text Expander outcry, and such — waiting to be organized and written up (I'll probably never write them up in the end, since these days it's very weird to write an opinion piece about an event whose attention span has already lapsed).</p> -<p>Anyway, this will be a short post about Emacs's <a href="https://gnu.org/software/emacs/">redesigned website</a>. See screenshot at the end. Apparently this was <a href="https://twitter.com/NicolasPetton/status/714854524108800000">last week's news</a>, but there's little interest in Emacs in general, so the news only reached me two days ago, sort of by chance.</p> -<p>According my impression, Emacs has been the underdog for quite some time. First, when you compare to vi/Vim, hard stats shed light on popularity: there are way more VimL repos than Elisp ones on GitHub.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-04-10-emacss-got-a-redesigned-website.html#fn1" id="fnref1"><sup>1</sup></a> Also, there are more exciting (or at least exciting-sounding or excitement-inducing) things happening in the Vim realm, e.g. Neovim, but not so much in the Emacs kingdom (excuse me if I missed something big). I'm actually very curious how Vim sold itself to so many people. I, for one, can't tolerate the Esc key at all (yes, I know basic editing in Vim, and I know the various workarounds to Esc, some of them reasonable and some not). I can't understand how people could laugh at Escape Meta Alt Control Shift — oh, I never used Esc in Emacs once, by the way — when the single most awkward Esc key serves a fundamental purpose by default in their own beloved editor. The Esc key is of course not my only gripe with Vim, nor the biggest; I'll however stop here to avoid turing this post into a complaint about Vim. Apart from Vim, Emacs is also being sidelined by more modern GUI-based text editors like Atom,<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-04-10-emacss-got-a-redesigned-website.html#fn2" id="fnref2"><sup>2</sup></a> or various IDEs. Atom <a href="http://blog.atom.io/2016/03/28/atom-reaches-1m-users.html">recently</a> reached one million monthly active users. I actually like certain parts of Atom a lot, e.g. the project navigation sidebar,<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-04-10-emacss-got-a-redesigned-website.html#fn3" id="fnref3"><sup>3</sup></a> but I simply can't give up my good ol' tty.</p> -<p>Personal preferences aside, I think Emacs does need a bit more publicity to draw a few more users. Whether redesigning the website will help at all I don't know; maybe the effect will be statistically indistinguishable from zero, but the bottom line is that people like pretty websites, so why not. The redesigned homepage is a bit more graphics-heavy, but it currently weighs a total of 521.33KB — within the tolerable range.</p> -<p>The most interesting thing I found on the redesigned homepage is the link to <a href="http://emacsrocks.com">emacsrocks.com</a>. I aimlessly clicked on the last episode — <a href="http://emacsrocks.com/e15.html">episode 15</a> — just to see what it was like, and ended up astonished. The episode is about <a href="https://github.com/pashky/restclient.el"><code>restclient.el</code></a>, which turned out to be wicked cool. In the real world it's probably a little bit too geeky to my liking, and I use the more mundane (and more powerful) <a href="https://luckymarmot.com/paw">Paw</a> as my REST client, but I can't stop admiring the beauty of <code>restclient-mode</code>. I'll definitely find time to watch all episodes of Emacs Rocks, and you probably should, too.</p> -<div class="figure"> -<a href="http://archive.zhimingwang.org/img/20160409-emacs-website-screenshot-half-size.png" target="_blank"><img alt="A scaled down screenshot of the redesigned gnu.org/software/emacs. Full screenshot on my 2880x1800 MBP is here. Actually I lied a bit — the screenshots were taken with pageres, so I could have specified any resolution." src="http://archive.zhimingwang.org/img/20160409-emacs-website-screenshot-half-size.png" width="720"/></a> -<p class="caption">A scaled down screenshot of the redesigned <a href="https://gnu.org/software/emacs/">gnu.org/software/emacs</a>. Full screenshot on my 2880x1800 MBP is <a href="http://archive.zhimingwang.org/img/20160409-emacs-website-screenshot.png">here</a>. Actually I lied a bit — the screenshots were taken with <a href="https://github.com/sindresorhus/pageres"><code>pageres</code></a>, so I could have specified any resolution.</p> -</div> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>According to <a href="http://githut.info/">GitHut</a>, in 2014 Q4, there were 22,450 VimL and 9,978 Elisp repositories on GitHub, respectively. And according to a real time search I did just now, the <a href="https://github.com/search?q=language%3AVimL">VimL number</a> has risen to 82,519 and the <a href="https://github.com/search?q=language%3AElisp">Elisp number</a> to 30,320. The ratio has risen from 2.25:1 to 2.72:1. To add insult to injury, on GitHub's <a href="https://github.com/search/advanced">advanced search page</a>, GitHub lists VimL in the "Popular" language section and Elisp in "Everything else". Hurt feelings anyone?<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-04-10-emacss-got-a-redesigned-website.html#fnref1">↩︎</a></p></li> -<li id="fn2"><p>Of course Emacs can operate in standalone GUI mode (or more precisely, window system mode), and more can be done in GUI mode (both in terms of customizability and functinality). However, in my early days with Emacs I found the GUI look like crap — the default always does, even to this day. I can never bring myself to use anything crappy-looking, unless I've got no choice, so I went with the TUI. Later I learned how to make the GUI habitable (still not as nice as the uniformity I find in tty, though), but by that time I'm already totally in love with tty mode and probably will never switch.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-04-10-emacss-got-a-redesigned-website.html#fnref2">↩︎</a></p></li> -<li id="fn3"><p>In Emacs I have ido, fiplr and sr-speedbar to help with navigation, but this is one area where a graphical sidebar really shines.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-04-10-emacss-got-a-redesigned-website.html#fnref3">↩︎</a></p></li> -</ol> -</div> -]]></description><author>zmwangx@gmail.com (Zhiming Wang)</author><guid isPermaLink="true">http://archive.zhimingwang.org/blog/2016-04-10-emacss-got-a-redesigned-website.html</guid><pubDate>Sun, 10 Apr 2016 10:04:19 GMT</pubDate></item><item><title>Google Chrome keeps getting uglier</title><link>http://archive.zhimingwang.org/blog/2016-03-06-google-chrome-keeps-getting-uglier.html</link><description><![CDATA[ - -<p>I hate to say this, but the Google Chrome team keeps making poor design decisions to make it more and more ugly. I still remember the sad day when the kind of cool wrench button gave way to the utterly boring hamburger one. I also remember the sad day when the omnibox dropdown <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=276746">pointlessly went full width</a> (after more than two years, I still fail to see how it makes any sense, although my eyes have long grown used to it).<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-03-06-google-chrome-keeps-getting-uglier.html#fn1" id="fnref1"><sup>1</sup></a> And I'm sure there are other stupid changes that I can't name at the moment.</p> -<p>Unfortunately, they just won't stop. <a href="http://googlechromereleases.blogspot.com/2016/03/stable-channel-update.html">Four days ago</a> stable 49.0.2623.75 came out with a flurry of horrible visual changes.</p> -<ol style="list-style-type: decimal"> -<li><p>The icon. For whatever reason I have the impression that I might have seen this a while ago, but let's just pretend it's brand new. The new app icon is the most outrageously flat icon I've even seen. Compare it to that of 48.0.2564.103<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-03-06-google-chrome-keeps-getting-uglier.html#fn2" id="fnref2"><sup>2</sup></a>:</p> -<div class="figure"> -<a href="http://archive.zhimingwang.org/img/20160306-chrome-mac-48.0.2564.103-49.0.2623.75-icons-side-by-side.png" target="_blank"><img alt="Old and new app icons side by side. To the left, the 48.0.2564.103 icon; to the right, the 49.0.2623.75 icon." src="http://archive.zhimingwang.org/img/20160306-chrome-mac-48.0.2564.103-49.0.2623.75-icons-side-by-side.png" width="512"/></a> -<p class="caption">Old and new app icons side by side. To the left, <a href="http://archive.zhimingwang.org/img/20160306-chrome-mac-48.0.2564.103-icon.png">the 48.0.2564.103 icon</a>; to the right, <a href="http://archive.zhimingwang.org/img/20160306-chrome-mac-49.0.2623.75-icon.png">the 49.0.2623.75 icon</a>.</p> -</div> -<p>And let's see them in action:</p> -<div class="figure"> -<a href="http://archive.zhimingwang.org/img/20160306-chrome-mac-48.0.2564.103-49.0.2623.75-icons-side-by-side-in-dock.png" target="_blank"><img alt="Both icons in the dock, old one the left and new one on the right." src="http://archive.zhimingwang.org/img/20160306-chrome-mac-48.0.2564.103-49.0.2623.75-icons-side-by-side-in-dock.png" width="560"/></a> -<p class="caption">Both icons in the dock, old one the left and new one on the right.</p> -</div> -<p>Apart from flatness (lack of any gloss found in almost all Apple icons, however flattened they are), see how the new icon is notably larger than the old one, and any other circular icons for that matter. Apparently, consistency and guidelines mean nothing to them.</p> -<p>I wonder why they made this change. Maybe for material design? I certainly don't want to see my Mac infested by material design, thank you. And maybe to keep the icon in line with their new Google branding? Indeed, just like <a href="https://web.archive.org/web/20160306221914/https://g-design.storage.googleapis.com/production/v5/assets/g-logo.png">the new Google logo</a> which did away with serifs, this one has no depth at all and is very childish.</p> -<p>It's a shame I can't just throw this icon out of my dock. Looks like in addition to iTunes now I have yet another icon to replace following each update, except this one updates much more often, and almost silently.</p></li> -<li><p>Downloads. I almost thought I was hacked when I opened the Downloads tab and saw</p> -<div class="figure"> -<a href="http://archive.zhimingwang.org/img/20160306-chrome-mac-49.0.2623.75-downloads.png" target="_blank"><img alt="Downloads in 49.0.2623.75." src="http://archive.zhimingwang.org/img/20160306-chrome-mac-49.0.2623.75-downloads.png" width="848"/></a> -<p class="caption">Downloads in 49.0.2623.75.</p> -</div> -<p>instead of a nice and clean</p> -<div class="figure"> -<a href="http://archive.zhimingwang.org/img/20160306-chrome-mac-48.0.2564.103-downloads.png" target="_blank"><img alt="Downloads in 48.0.2564.103." src="http://archive.zhimingwang.org/img/20160306-chrome-mac-48.0.2564.103-downloads.png" width="728"/></a> -<p class="caption">Downloads in 48.0.2564.103.</p> -</div> -<p>Materail design infestation, apparently. Funny how they managed to convey less info in a LOT more space, and look horrible at the same time. At least they can choose a pleasant color palette if they want to use color (which is totally unnecessary as seen from the old design)? No, they can't.</p></li> -<li><p>Incognito mode. There's a reason why books are printed on light-colored paper, and there's a reason why the web is predominantly light-backgrounded, including user agent default style sheets. The old incognito follows the light background rule, plus a non-intrusive notice in the middle and a reasonably shaded tab bar to indicate incognito status:</p> -<div class="figure"> -<a href="http://archive.zhimingwang.org/img/20160306-chrome-mac-48.0.2564.103-incognito.png" target="_blank"><img alt="Incognito window in 48.0.2564.103." src="http://archive.zhimingwang.org/img/20160306-chrome-mac-48.0.2564.103-incognito.png" width="893"/></a> -<p class="caption">Incognito window in 48.0.2564.103.</p> -</div> -<p>But not anymore. Since those of you using Incognito mode must be conducting shady business, why not highlight that with a black background:</p> -<div class="figure"> -<a href="http://archive.zhimingwang.org/img/20160306-chrome-mac-49.0.2623.75-incognito.png" target="_blank"><img alt="Incognito window in 49.0.2623.75. Even more shocking if you maximize your browser windows." src="http://archive.zhimingwang.org/img/20160306-chrome-mac-49.0.2623.75-incognito.png" width="625"/></a> -<p class="caption">Incognito window in 49.0.2623.75. Even more shocking if you maximize your browser windows.</p> -</div> -<p>Oh. My. God. Now I hesitate whenever I want to press ⇧⌘N; it's just too great a cultural shock for me to handle.</p></li> -</ol> -<p>Those are just three changes I've discovered so far. Hopefully there are no more lurking surprises.</p> -<p>Conclusion? Sigh.</p> -<hr/> -<p><strong>03/09/2016 update</strong>. They also broke showing/hiding extension buttons (from toolbar) recently, probably in the same update. We used to be able to reshow a hidden button from <code>chrome://extensions</code>; that's no longer possible. Now we need to click on the hamburger (great), right click on one of the hidden buttons — which temporarily promotes the button to the toolbar and display the context menu, and while the context menu is still on, click on "Keep in Toolbar". So intuitive, your average computer users are definitely going to figure that out by themselves. Very nice.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>Dev left a <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=276746#c28">comment</a> when marking that issue as wont fix:</p> -<blockquote> -<p>... The current look is a precursor to a family of related work to make the Omnibox better, so expect to see more investment in this space to come. ...</p> -</blockquote> -<p>A family of related work? After 2.5 years the omnibox looks almost exactly the same as the screenshot in the issue. More to come my ass. Maybe I should be grateful, at least it didn't get worse.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-03-06-google-chrome-keeps-getting-uglier.html#fnref1">↩︎</a></p></li> -<li id="fn2"><p>I realized the last stable was 48.0.2564.109 instead of 48.0.2564.103 only after taking the screenshots. Doesn't matter anyway.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-03-06-google-chrome-keeps-getting-uglier.html#fnref2">↩︎</a></p></li> -</ol> -</div> -]]></description><author>zmwangx@gmail.com (Zhiming Wang)</author><guid isPermaLink="true">http://archive.zhimingwang.org/blog/2016-03-06-google-chrome-keeps-getting-uglier.html</guid><pubDate>Sun, 06 Mar 2016 22:59:45 GMT</pubDate></item><item><title>Dropbox, Noteworthy, and damned skeuomorphism</title><link>http://archive.zhimingwang.org/blog/2016-01-26-dropbox-noteworthy-and-damned-skeuomorphism.html</link><description><![CDATA[ - -<p>I just opened a note in a PDF within Dropbox's iOS app (never done that before), and instead of readable text what I saw was basically spaghetti:</p> -<div class="figure"> -<a href="http://archive.zhimingwang.org/img/20160126-dropbox-noteworthy.png" target="_blank"><img alt="A PDF note in Dropbox iOS. Noteworthy (scream). I know there's a typo, by the way." src="http://archive.zhimingwang.org/img/20160126-dropbox-noteworthy.png" width="300"/></a> -<p class="caption">A PDF note in Dropbox iOS. Noteworthy (scream). I know there's a typo, by the way.</p> -</div> -<p>That font is unmistakably Noteworthy, the default font in Apple's Notes app in Mountain Lion, when Apple was still practicing the damned skeuomorphism. (In case you can't recall how it looked like, let me point you to <a href="http://arstechnica.com/apple/2012/07/os-x-10-8/7/#notes">the John Siracusa review</a> for screenshots.) Just like your coworker's average handwritten notes, it is hardly legible and takes tremendous effort just to decode, especially when clustered in a paragraph rather than a short one-liner. Compare that to the same note, legibly rendered in Helvetica in PDF Expert:</p> -<div class="figure"> -<a href="http://archive.zhimingwang.org/img/20160126-pdf-expert-note.png" target="_blank"><img alt="The same note (typo corrected) in PDF Expert Mac." src="http://archive.zhimingwang.org/img/20160126-pdf-expert-note.png" width="258"/></a> -<p class="caption">The same note (typo corrected) in PDF Expert Mac.</p> -</div> -<p>This is an example of sacrificing usability for design aesthetics (an old-fashioned one for that matter, and an abonimable one if you ask for my opinion). Hard to believe we can still see it in 2016, from an otherwise great developer that is Dropbox.</p> -]]></description><author>zmwangx@gmail.com (Zhiming Wang)</author><guid isPermaLink="true">http://archive.zhimingwang.org/blog/2016-01-26-dropbox-noteworthy-and-damned-skeuomorphism.html</guid><pubDate>Tue, 26 Jan 2016 20:18:36 GMT</pubDate></item><item><title>Antivirus app on MAS top chart?</title><link>http://archive.zhimingwang.org/blog/2016-01-24-antivirus-app-on-mas-top-chart.html</link><description><![CDATA[ - -<p>Today for whatever reason I clicked on MAS's "Top Charts" page, and was immediately in for a surprise. Next to our great friend 1Password is an app called "AntiVirus Sentinel Pro", which sells for $9.99:</p> -<div class="figure"> -<a href="http://archive.zhimingwang.org/img/20160124-mas-top-paid.png" target="_blank"><img alt="AntiVirus Sentinel "Pro". These days many people like to end their apps' names with "Pro", even when there's nothing pro about them. This "Pro" app, for instance, comes from a developer whose three out of four apps matches the regex ^([A-Z](a-z)+ )+Pro$, and despite their names they are definitely geared towards uninformed newbies." src="http://archive.zhimingwang.org/img/20160124-mas-top-paid.png"/></a> -<p class="caption">AntiVirus Sentinel "Pro". These days many people like to end their apps' names with "Pro", even when there's nothing pro about them. This "Pro" app, for instance, comes from a developer whose three out of four apps matches the regex <code>^([A-Z](a-z)+ )+Pro$</code>, and despite their names they are definitely geared towards uninformed newbies.</p> -</div> -<p>The first rule of using MAS (or any kind of app store, for that matter) is that you research MAS apps outside the MAS. So let's Google "AntiVirus Sentinel Pro"... First result: <a href="https://discussions.apple.com/thread/6749331">Apple Support forum thread</a> from late 2014, "Is AntiVirus Sentinel Pro legit? If not, how can I delete it?" Good question about any AV product. However, you'll immediately find it hilarious when you read on:</p> -<blockquote> -<p>I have purchased and downloaded AntiVirus Sentinel Pro for Macintosh with Yosemite OS. I have a bad feeling this application is useless and maybe even harmful. Anyone knows if it is safe to use it?</p> -</blockquote> -<p>Okay, so why did you purchase it in the first place? I guess clueless users like this one are in every MAS developer's wet dreams.</p> -<p>Let's continue with the Google search results. Second one is the iTunes preview link. Third one is a <a href="http://www.securityfocus.eu/www/sentinel-pro.html">YouTube video</a> (also linked from MAS) which seems to be the only online documentation this app's got. Judging from the video the interface seems to be done in Java or something... Never mind that. Fourth result is a <a href="http://www.mac-forums.com/os-x-operating-system/327356-antivirus-sentinel-pro.html">rather recent thread</a> (August 2015) from Mac Forums. Not this again:</p> -<blockquote> -<p>I am a new Mac user. Can somebody answer these questions? Somehow it appears I have installed AntiVirus Sentinel Pro. What is this? Is it a real software? Should I keep it or try to uninstall it?</p> -</blockquote> -<p>The fifth and sixth results are general OS X AV product reviews that don't even mention this app. The next three results are from MAS aggregation sites. The last result on the first page is the app's product page on MacUpdate (now apparently abandoned), with a shiny 0.5/5 stars (note the zero point) badge.</p> -<p>Now that we've finished the first page (and the results are not a bit reassuring), the question comes: where the heck is this app's home page? It's also not on the second page, actually. There's something interesting on the third (still no home page), that is <a href="https://twitter.com/claud_xiao/status/681981763938197504">this tweet</a>:</p> -<blockquote> -<p>$10 "AntiVirus Sentinel Pro" got top2 in US Mac App Store and top1 in 48 countries--but it's just ClamAV+AdwareMedic signs+3 bullshit signs.</p> -</blockquote> -<p>Hmm. You might want to read Thomas Reed's (known for The Safe Mac) responses from that thread.</p> -<p>Anyway, we were sidetracked. Back to the home page, actually this app does have one, but it's just <a href="http://www.securityfocus.eu/www/sentinel-pro.html">a single page</a>, which simply states some marketing bullshit and directs to MAS (where the same bullshit is repeated). Seriously? That's the best you can do for your "pro" app, especially a security-related one?</p> -<p>Back to MAS, the reviews are kind of jokes, too:</p> -<div class="figure"> -<a href="http://archive.zhimingwang.org/img/20160124-antivirus-sentinel-pro-reviews.png" target="_blank"><img alt="Stupid reviews for stupid app." src="http://archive.zhimingwang.org/img/20160124-antivirus-sentinel-pro-reviews.png"/></a> -<p class="caption">Stupid reviews for stupid app.</p> -</div> -<p>The first one begins with</p> -<blockquote> -<p>Just switched to Apple from Windows ... and researched anti-virus software.</p> -</blockquote> -<p>Don't really need to read further.</p> -<p>Second one, speaking of customer service:</p> -<blockquote> -<p>... it only took one email to him explaining my problem... had a patch up and ready on the app store to download within hours.</p> -</blockquote> -<p>This review is from October 2015. Since when was MAS so efficient? Why do I (and everyone else keeping tabs on Apple stuff) keep hearing stories like <a href="http://mjtsai.com/blog/2015/12/01/sketch-leaving-the-mac-app-store/">bug fix updates waiting for review after 59 days</a>?</p> -<p>The pattern goes on. By the way, how does this app keep track of all disk and network activity when itself is running in a sandbox? No idea (maybe I'm misunderstanding sandboxing).</p> -<p>In summary, even as an AV product, this one seems untrustworthy. Not to mention AV products on the Mac are generally superfluous if not harmful.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-01-24-antivirus-app-on-mas-top-chart.html#fn1" id="fnref1"><sup>1</sup></a> What people really need to learn is to practice safe browsing habits and to properly use content blockers, which AV product vendors and (intrusive-)ad-supported websites (that is most, commercial websites today) won't tell you because they would go out of business if they do.</p> -<p>And how this app got onto the top charts, that is a real mystery.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>Disclaimer: I personally have used ClamXav and AdwareMedic (which has since been bought by Malwarebytes) before to help my social-engineered friend (tech support scam, in case you ask). Just to scan their documents though. It is my belief that once you're pwned (even slightly), clean system reinstall is the only way to go, despite what AV products might tell you. In addition, I don't use AV products myself (except Microsoft Security Essentials on Windows); as a programmer I've had enough bad experience with AV blocking <em>my</em> programs back in the Windows days.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-01-24-antivirus-app-on-mas-top-chart.html#fnref1">↩︎</a></p></li> -</ol> -</div> -]]></description><author>zmwangx@gmail.com (Zhiming Wang)</author><guid isPermaLink="true">http://archive.zhimingwang.org/blog/2016-01-24-antivirus-app-on-mas-top-chart.html</guid><pubDate>Mon, 25 Jan 2016 02:43:28 GMT</pubDate></item><item><title>Me-too comments on GitHub</title><link>http://archive.zhimingwang.org/blog/2016-01-18-me-too-comments-on-github.html</link><description><![CDATA[ - -<p>I frequently subscribe to issues on GitHub, be it bugs I want to see fixed or features I would like to see implemented. Then every once in a short while I get an email notification about one of those obnoxious "me too" or "+1" comments, by which I mean terse comments with little to no content other than "me too" or "+1" or some other variant bearing the same meaning.</p> -<p>Me-too comments under bug reports are the most untolerable. If you have more details regarding the issue (e.g., a more reliable reproducer) or insights into what's really going on, then by any means post them. On the other hand, if you can't provide anything helpful, then just keep your mouth shut, and quietly press "subscribe" if you would like to be kept posted. Posting a me-too comment adds nothing to the discussion, does not expedite the resolution a tiny bit, and only serves to annoy all parties involved.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-01-18-me-too-comments-on-github.html#fn1" id="fnref1"><sup>1</sup></a> As always, submit a patch if you're dissatisfied with the progress. Keep in mind that no one is obligated to fix bugs for you in FOSS.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-01-18-me-too-comments-on-github.html#fn2" id="fnref2"><sup>2</sup></a></p> -<p>Me-too comments under feature requests are more understandable, though I genuinely doubt that two or three people requesting a feature instead of one would make a big difference. After all, the issue tracker is not a feature voting platform; most folks understand this and behave themselves, so "me-too demand" isn't even remotely accurate at reflecting demand.</p> -<p>Me-too folks: please stop being childish. If you have nothing to add, don't add anything (unless otherwise requested).</p> -<hr/> -<p><strong>01/20/2015 Update.</strong> I came accross <a href="https://github.com/dear-github/dear-github">dear-githuub/dear-github</a> just now, which was started a mere six days ago, and the <a href="https://github.com/dear-github/dear-github/blob/bc7a4f6bc78445905751061bf96f731edda14c25/README.md">open letter</a> of which also places +1 comments on its list of biggest problems on GitHub.</p> -<hr/> -<p><strong>03/10/2015 Update.</strong> GitHub is finally reacting. See <a href="https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments">Add Reactions to Pull Requests, Issues, and Comments</a>.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>There are exceptional cases.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-01-18-me-too-comments-on-github.html#fnref1">↩︎</a></p></li> -<li id="fn2"><p>Here we're talking about the subset of FOSS that is also free as in beer.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-01-18-me-too-comments-on-github.html#fnref2">↩︎</a></p></li> -</ol> -</div> -]]></description><author>zmwangx@gmail.com (Zhiming Wang)</author><guid isPermaLink="true">http://archive.zhimingwang.org/blog/2016-01-18-me-too-comments-on-github.html</guid><pubDate>Tue, 19 Jan 2016 00:36:40 GMT</pubDate></item><item><title>The dirtiest mistakes of OS X</title><link>http://archive.zhimingwang.org/blog/2016-01-14-the-dirtiest-mistakes-of-os-x.html</link><description><![CDATA[ - -<p>I must have written about this elsewhere, but here are my top three:</p> -<ol style="list-style-type: decimal"> -<li><p><code>.DS_Store</code>. Finder litters faster than one could clean up.</p></li> -<li><p>HFS+ NFD*.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-01-14-the-dirtiest-mistakes-of-os-x.html#fn1" id="fnref1"><sup>1</sup></a> Heard of the cursed encoding <code>UTF8-MAC</code>? Pure Evil. Culprit of tons of garbled text issues (especially cross platform ones) and probably most length miscalculation issues. Even Apple's Terminal.app can't do NFD right. I wonder how Korean users navigate their filesystems in terminal.</p></li> -<li><p>Plist XML. It's XML, but even worse.</p></li> -</ol> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>NFD with an asterisk, i.e., not even NFD. According to Apple in <a href="https://developer.apple.com/library/mac/qa/qa1173/_index.html">an old Technical Q&A</a>,</p> -<blockquote> -<p>The terms used in this Q&A, precomposed and decomposed, roughly correspond to Unicode Normal Forms C and D, respectively. However, most volume formats do not follow the exact specification for these normal forms. For example, HFS Plus (Mac OS Extended) uses a variant of Normal Form D in which U+2000 through U+2FFF, U+F900 through U+FAFF, and U+2F800 through U+2FAFF are not decomposed (this avoids problems with round trip conversions from old Mac text encodings). It's likely that your volume format has similar oddities.</p> -</blockquote> -<p>They are conscious enough to call these oddities.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-01-14-the-dirtiest-mistakes-of-os-x.html#fnref1">↩︎</a></p></li> -</ol> -</div> -]]></description><author>zmwangx@gmail.com (Zhiming Wang)</author><guid isPermaLink="true">http://archive.zhimingwang.org/blog/2016-01-14-the-dirtiest-mistakes-of-os-x.html</guid><pubDate>Thu, 14 Jan 2016 09:02:52 GMT</pubDate></item><item><title>Virtualenvs for everyone</title><link>http://archive.zhimingwang.org/blog/2016-01-01-virtualenvs-for-everyone.html</link><description><![CDATA[ - -<p>Python distutils for the most part is rather pleasant to work with. That is, pleasant until you've accumulated so many packages that you eventually run into a clash of namespace, or a dependency conflict (or dependency hell as most would affectionately call it).<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2016-01-01-virtualenvs-for-everyone.html#fn1" id="fnref1"><sup>1</sup></a> In contrast, npm's approach to dependencies shuts out dependency hell completely, but it is so paranoid and costs so much duplication that I find it hard to appreciate unless necessary. Somewhere in between there's the virtualenv approach which I find most appealing for smallish projects — keep a single copy of each package in the dependency tree in a contained environment specific to the project at hand. This is how we debug Python projects, and it certainly also should be <em>the</em> way we run command line tools written in Python.</p> -<p>There's another reason I like virtualenvs. There are tons of problems associated with choosing between Python 2 and 3 — some projects are Python 2 only, some are instead Python 3, some claim to be compatible with both but actually present subtle problems when you use one instead of the other. However, without virtualenvs, there's only one <code>bin</code> — <code>/usr/local/bin</code> — and everything's competing for it. Most programs (especially ones with a typical <code>setup.py</code>) don't install a soft/hardlink with a helpful <code>2</code> or <code>3</code> suffix when installing executables, let alone detailed suffixes like <code>2.7</code> or <code>3.5</code>, so without probing into the shebangs you're never sure which version of Python you're running your program with, and as a result Python 2/3 (or even a point release)-specific bugs occur randomly. Virtualenvs solve the problem by allowing you to have as many bins (and includes, and libs) as you like.</p> -<p>Hence the title "virtualenvs for everyone". I would like to install each command line program written in Python into a separate virtualenv. The only issue is that apparently I don't want too many bins in my <code>$PATH</code>; to solve this issue, the executable bits of each project should be linked to a central place, for which I choose <code>$HOME/bin</code>. There could be as many symlinks as we like, so now we can have multiple links with increasing detailed version suffixes, e.g., <code>3</code>, <code>3.5</code>, <code>3.5.1</code>. Very nice.</p> -<p>This task could clearly be automated; the only slightly tricky bit is to programmatically figure out which scripts a project installs to <code>bin</code>. Luckily, for projects using <code>setuptools.setup</code>, we can simply spoof that function. Here's my <code>setuptools/__init__.py</code>:</p> -<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="co">#!/usr/bin/env python3</span> - -<span class="co">"""setuptools stubs.</span> - -<span class="co">Here we only stubbed the symbols in setuptools.__all__. Hopefully that's</span> -<span class="co">enough (actually I can't remember seeing any setup.py using more than</span> -<span class="co">setup and find_packages).</span> - -<span class="co">setup has been spoofed to print the names of scripts, console_scripts</span> -<span class="co">and gui_scripts defined in the arguments to setup. Some user-friendly</span> -<span class="co">messages are also printed to stderr.</span> - -<span class="co">"""</span> - -<span class="im">from</span> __future__ <span class="im">import</span> print_function - -<span class="im">import</span> re -<span class="im">import</span> sys -<span class="im">import</span> os - -__all__ <span class="op">=</span> [ - <span class="st">'setup'</span>, <span class="st">'Distribution'</span>, <span class="st">'Feature'</span>, <span class="st">'Command'</span>, <span class="st">'Extension'</span>, <span class="st">'Require'</span>, - <span class="st">'find_packages'</span> -] - -<span class="kw">def</span> setup(<span class="op">**</span>kwargs): - scripts <span class="op">=</span> [os.path.basename(script_path) - <span class="cf">for</span> script_path <span class="kw">in</span> kwargs.pop(<span class="st">'scripts'</span>, [])] - <span class="cf">if</span> scripts: - <span class="bu">print</span>(<span class="st">'scripts:</span><span class="ch">\n</span><span class="st"> - </span><span class="sc">%s</span><span class="st">'</span> <span class="op">%</span> <span class="st">'</span><span class="ch">\n</span><span class="st"> - '</span>.join(scripts), <span class="bu">file</span><span class="op">=</span>sys.stderr) - entry_points <span class="op">=</span> kwargs.pop(<span class="st">'entry_points'</span>, {}) - <span class="cf">for</span> entry_point <span class="kw">in</span> [<span class="st">'console_scripts'</span>, <span class="st">'gui_scripts'</span>]: - extra_scripts <span class="op">=</span> [re.split(<span class="st">'(\s|=)'</span>, spec.strip())[<span class="dv">0</span>] - <span class="cf">for</span> spec <span class="kw">in</span> entry_points.pop(entry_point, [])] - <span class="cf">if</span> extra_scripts: - <span class="bu">print</span>(<span class="st">'</span><span class="sc">%s</span><span class="st">:</span><span class="ch">\n</span><span class="st"> - </span><span class="sc">%s</span><span class="st">'</span> <span class="op">%</span> (entry_point, <span class="st">'</span><span class="ch">\n</span><span class="st"> - '</span>.join(extra_scripts)), - <span class="bu">file</span><span class="op">=</span>sys.stderr) - scripts.extend(extra_scripts) - <span class="bu">print</span>(<span class="st">'</span><span class="ch">\n</span><span class="st">'</span>.join(<span class="bu">sorted</span>(scripts))) - -<span class="kw">class</span> Distribution(<span class="bu">object</span>): <span class="cf">pass</span> -<span class="kw">class</span> Feature(<span class="bu">object</span>): <span class="cf">pass</span> -<span class="kw">class</span> Command(<span class="bu">object</span>): <span class="cf">pass</span> -<span class="kw">class</span> Extension(<span class="bu">object</span>): <span class="cf">pass</span> -<span class="kw">class</span> Require(<span class="bu">object</span>): <span class="cf">pass</span> -<span class="kw">def</span> find_packages(<span class="op">**</span>kwargs): <span class="cf">pass</span></code></pre></div> -<p>Now, let <code>$HERE</code> be the directory containing our fake <code>setuptools/</code>, and <code>$PROJECT_ROOT</code> be the project root directory containing <code>setup.py</code>. Run</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh"><span class="ot">PYTHONPATH=$HERE</span>:<span class="ot">$PYTHONPATH</span> python <span class="ot">$PROJECT_ROOT</span>/setup.py</code></pre></div> -<p>and bam! We get the names of all scripts on stdout.</p> -<p>My full automation scripts, including the Zsh main function <code>virtual-install</code>, can be found in <a href="https://github.com/zmwangx/prezto/tree/master/modules/python/functions"><code>modules/python/functions</code> in zmwangx/prezto</a>. I'm not including it here because it uses some custom helper, and it's just too long (200+ lines, but not very sophisticated). Happy virtualenving!</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>In rare cases, even installing a single package could land you in trouble. The classical example is installing the <code>readme</code> package on a case-insensitive filesystem (e.g., the default mode of HFS+). "Unfortunately" <a href="https://bugs.python.org/issue24633">this</a> has been fixed.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2016-01-01-virtualenvs-for-everyone.html#fnref1">↩︎</a></p></li> -</ol> -</div> -]]></description><author>zmwangx@gmail.com (Zhiming Wang)</author><guid isPermaLink="true">http://archive.zhimingwang.org/blog/2016-01-01-virtualenvs-for-everyone.html</guid><pubDate>Sat, 02 Jan 2016 06:21:14 GMT</pubDate></item><item><title>Catches when installing Windows 7 with Boot Camp</title><link>http://archive.zhimingwang.org/blog/2015-12-29-catches-when-installing-windows-7-with-boot-camp.html</link><description><![CDATA[ - -<p>I was looking for a use for my retired Mid-2012 Non-Retina MacBook Pro 13''<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-12-29-catches-when-installing-windows-7-with-boot-camp.html#fn1" id="fnref1"><sup>1</sup></a>, and unsurprisingly I figured that I would turn it into a OS X-Windows dual boot for some occasional gaming. I'm a CnC fan (not hardcore, but still), mainly for RA2/YR and TW/KW, and playing these inside Fusion is really a subsubpar experience. Due to the age of these games and their compatibility problems on Windows 8 and higher<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-12-29-catches-when-installing-windows-7-with-boot-camp.html#fn2" id="fnref2"><sup>2</sup></a>, I chose to shoot for a Windows 7 install.</p> -<p>Apple has a pretty thorough walkthrough in the support article <a href="https://support.apple.com/en-us/HT205016">Install Windows 7 and earlier on your Mac using Boot Camp</a>. There are, however, some catches that I would like to collect and share in this post.</p> -<ol style="list-style-type: decimal"> -<li><p>Win 7 ISO isn't available for download in the appropriate language (given your product key). This one sounds incredibly stupid... But it is a real problem at least for me and several others (just Google). I have a valid Win 7 Ultimate license from my institution, so I went to <a class="uri" href="https://www.microsoft.com/en-us/software-download/windows7">https://www.microsoft.com/en-us/software-download/windows7</a> to grab my ISO (just for fun; I already have the image). However, after verifying my product key, here's the list of languages that I'm asked to choose from, where English is apparently missing (!!!):</p> -<div class="figure"> -<a href="http://archive.zhimingwang.org/img/20151229-win7-iso-language-choice.png" target="_blank"><img alt="da !@#$?" src="http://archive.zhimingwang.org/img/20151229-win7-iso-language-choice.png" width="394"/></a> -<p class="caption">da !@#$?</p> -</div> -<p>I don't know the solution to this problem. In my case I've archived English Win 7 Ultimate SP1 images (both x86 and x64) before, so I just proceeded with my old image.</p></li> -<li><p>FileVault. It is my belief that FileVault needs to turned off before partitioning the drive with Boot Camp.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-12-29-catches-when-installing-windows-7-with-boot-camp.html#fn3" id="fnref3"><sup>3</sup></a></p></li> -<li><p><em>An error occured while partitioning the disk.</em> That's the unhelpful message from Boot Camp. If you try to manually partition the drive with Disk Utility, you'll probably get a much more helpful message like <em>Partition failed with the error: couldn't modify partition map because file system verification failed</em>. Now the problem is obvious, and the solution is simple. Boot to single user mode and repair the filesystem with <code>/sbin/fsck -fy</code>, or safer, <code>/sbin/fsck -f</code> which might require interaction.</p></li> -<li><p>During Windows installation you'll obviously be prompted to choose a system partition at some point, and due to Boot Camp only formatting to FAT32, you'll get the message <em>Windows cannot be installed to this hard disk space. Windows must be installed to a partition formatted as NTFS.</em> This one is easy, just click "Drive options (advanced)" then "Format", which automatically formats the partition to NTFS. This is actually documented in Apple's walkthrough, but mortals do panic in face of error messages, so let's also note it here.</p></li> -<li><p>Even after formatting the Boot Camp partition, it is still possible to get the error <em>Setup was unable to create a new system partition or locate an existing system partition</em>. It this happens, check if you have any USB drives (other than the installation media) plugged in. In my case my Time Capsule was plugged in, and rebooting with it unplugged fixed the problem. The exact cause of the problem is unclear to me. Some say it's due to Master Boot Record limiting the number of partitions to four, but why the heck is my external drive counted towards that limitation? I'd go for Win 7 installer is just confused. Anyway, just unplug anything that's not needed during Windows installation.</p></li> -</ol> -<p>Hopefully you're good after solving the aforementioned problems. If you followed Apple's walkthrough correctly, Boot Camp's setup.exe will be invoked automatically immediately after Windows finishes installation, and after a certain number of reboots your drivers will be up and running. Now you're ready to take control of your Windows. Install Chrome<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-12-29-catches-when-installing-windows-7-with-boot-camp.html#fn4" id="fnref4"><sup>4</sup></a> and Microsoft Security Essentials immediately, then hop right into the Windows Update hell to patch your four-year-old system. Of course, Windows Update being Windows Update won't be smooth — servers will be crowded as ever and just checking for updates will likely take forever, let alone downloads. After a semi-infinite amount of time you'll get your estimates (I got 212 updates). Click update and let Windows Update grind for hours. And wish yourself a good luck (that no update errors will occur — luckily I didn't get any).</p> -<p>By the way, the otherwise great Apple trackpad is almost unusable on Boot Camp Windows under any setting. I'm forced to use a mouse.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>2.9 GHz i7 + Intel HD Graphics 4000 + 16 GB RAM + frigging slow 750 GB 5400-rpm spinning disk I've yet to replace.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-12-29-catches-when-installing-windows-7-with-boot-camp.html#fnref1">↩︎</a></p></li> -<li id="fn2"><p>RA2/YR used to have problems even on Windows 7, at least inside Fusion, so I used to play them in XP SP3 VMs; I've yet to try them with Windows 7 running on bare metal.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-12-29-catches-when-installing-windows-7-with-boot-camp.html#fnref2">↩︎</a></p></li> -<li id="fn3"><p>I'm not completely sure that this is necessary. I was greeted with partitioning errors initially which I thought was due to FileVault, so I switched it off (the actual process is much longer than "switching it off", since the whole disk has to be decrypted and rewritten), but as you'll see later, the partitioning errors were at least partly due to a slightly corrupt filesystem.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-12-29-catches-when-installing-windows-7-with-boot-camp.html#fnref3">↩︎</a></p></li> -<li id="fn4"><p>You can't even browse Microsoft's own websites with stock IE8. And IE11 is locked behind a hell lot of Windows Updates (even then it is crap). Doing Windows Update is like building up a tech tree.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-12-29-catches-when-installing-windows-7-with-boot-camp.html#fnref4">↩︎</a></p></li> -</ol> -</div> -]]></description><author>zmwangx@gmail.com (Zhiming Wang)</author><guid isPermaLink="true">http://archive.zhimingwang.org/blog/2015-12-29-catches-when-installing-windows-7-with-boot-camp.html</guid><pubDate>Tue, 29 Dec 2015 23:09:16 GMT</pubDate></item><item><title>Why I want lossless music on iTunes Music Store</title><link>http://archive.zhimingwang.org/blog/2015-12-28-why-i-want-lossless-music-on-itunes-music-store.html</link><description><![CDATA[ - -<p>This is an impulse post after reading <a href="https://marco.org/2015/12/27/apple-hd-audio-again">"Apple again rumored to be working on high-resolution audio"</a>.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-12-28-why-i-want-lossless-music-on-itunes-music-store.html#fn1" id="fnref1"><sup>1</sup></a></p> -<p>To be clear, I'm no audiophile. I can't tell the difference between 256kbps AAC and lossless (maybe not even the difference between 128k and 256k), and my midrange to lower midrange equipments probably won't let me tell anyway. I'm certainly not a consumer of snake oil.</p> -<p>However, I still prefer to get everything in lossless, simply because <strong>"good enough" today is almost never good enough tomorrow</strong>. Fifty years later I'm most likely still wandering this planet, I and my music collection. I would be extremely regretful if I didn't archive the highest quality versions of my favorite tracks today, only to find them inferior-sounding fifty years later, which is a pretty realistic possibility given how fast technology advances.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-12-28-why-i-want-lossless-music-on-itunes-music-store.html#fn2" id="fnref2"><sup>2</sup></a> Even today's lossless could be inferior-sounding in the future, but there would be no regret.</p> -<p>To be extra clear, I'm talking about lossless for archival purposes, so what I want to see is a lossless download option in ITMS.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-12-28-why-i-want-lossless-music-on-itunes-music-store.html#fn3" id="fnref3"><sup>3</sup></a> Streaming can be done in whatever good enough® sampling frequency and bitrate that's currently in use, since it's a one-off thing with no effects on tomorrow (and I don't give a shit about streaming and subscription anyway). Offering lossless downloads likely won't put much burden on Apple's infrastructure, since they already deliver much more bandwidth-demanding movies on the same channel. Moreover, albums on ITMS aren't much cheaper than physical CDs, while the cost is apparently lower than CD production, the audience apparently wider, and the chances of impulse purchases (especially of single tracks) much higher, so I would suppose such a move (delivering lossless on ITMS) won't considerably hurt record labels' profits either. After all, if they don't make it easy for consumers, many consumers will just pirate — it's way too easy to pirate music.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>And I did see the <a href="http://www.macrumors.com/2015/12/20/apple-high-resolution-audio/">MacRumors article</a> a week ago. I even registered a MacRumors account, which I never bothered to do, just to comment on that article... It just didn't occur to me to write a blog post at that time.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-12-28-why-i-want-lossless-music-on-itunes-music-store.html#fnref1">↩︎</a></p></li> -<li id="fn2"><p>You might be skeptical of my hearing when I'm in my seventies... But I could well be showing my favorites to someone with perfect hearing, say my grandchildren.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-12-28-why-i-want-lossless-music-on-itunes-music-store.html#fnref2">↩︎</a></p></li> -<li id="fn3"><p>I know there are many online music stores that sell lossless music, but ITMS has the largest catalog in the world, and for many titles I care about, ITMS is still the only place in this country where I can make legal digital purchases.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-12-28-why-i-want-lossless-music-on-itunes-music-store.html#fnref3">↩︎</a></p></li> -</ol> -</div> -]]></description><author>zmwangx@gmail.com (Zhiming Wang)</author><guid isPermaLink="true">http://archive.zhimingwang.org/blog/2015-12-28-why-i-want-lossless-music-on-itunes-music-store.html</guid><pubDate>Mon, 28 Dec 2015 11:15:45 GMT</pubDate></item><item><title>Lesson on magic method access of Python new-style classes (from my failed Python3 port of Tomorrow)</title><link>http://archive.zhimingwang.org/blog/2015-12-27-lesson-on-magic-method-access-of-python-new-style-classes-from-my-failed-python3-port-of-tomorrow.html</link><description><![CDATA[ - -<p>I know the title is formidably long, but I can't find something more accurate (and my homegrown mini CMS doesn't support subtitle), so please bear with me.</p> -<p>So, I have <a href="https://github.com/madisonmay/Tomorrow">madisonmay/Tomorrow</a> — "magic decorator syntax for asynchronous code in Python 2.7" — bookmarked for a long time<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-12-27-lesson-on-magic-method-access-of-python-new-style-classes-from-my-failed-python3-port-of-tomorrow.html#fn1" id="fnref1"><sup>1</sup></a> without ever trying it, because I simply don't write Python 2 code any more (except when I try to maintain compatibililty). I felt kind of strange that a ~50-line project with ~1000 stars on GitHub hasn't been ported to Python 3 already, so I gave it a shot just now.</p> -<p>I thought it would be easy:</p> -<ol style="list-style-type: decimal"> -<li>Modernize the old-style class <code>Tomorrow</code>;</li> -<li>Replace <code>__getattr__</code> with <code>__getattribute__</code> for unconditional attribute routing, then make a few exceptions to prevent infinite recursion;</li> -<li><code>2to3</code> test cases;</li> -<li>Make meta changes, like removing the <code>futures</code> dependency.</li> -</ol> -<p>However, after doing 1–3, I ran the tests, and out of the five test cases, three failed and one errored. I tried to isolate the problem, and ended up with the following piece of proof-of-concept:</p> -<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="kw">class</span> PassThrough(<span class="bu">object</span>): - - <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>, obj): - <span class="va">self</span>._obj <span class="op">=</span> obj - - <span class="kw">def</span> <span class="fu">__getattribute__</span>(<span class="va">self</span>, name): - <span class="cf">if</span> name <span class="op">==</span> <span class="st">"_obj"</span>: - <span class="cf">return</span> <span class="bu">object</span>.<span class="fu">__getattribute__</span>(<span class="va">self</span>, name) - <span class="bu">print</span>(<span class="st">"Accessing '</span><span class="sc">%s</span><span class="st">'"</span> <span class="op">%</span> name) - <span class="cf">return</span> <span class="va">self</span>._obj.<span class="fu">__getattribute__</span>(name)</code></pre></div> -<p>This snippet is valid in both Python 2.7 and Python 3, but here's the surprise:</p> -<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="op">>>></span> g <span class="op">=</span> PassThrough(<span class="dv">0</span>) -<span class="op">>>></span> <span class="bu">print</span>(g) -<span class="op"><</span>__main__.PassThrough <span class="bu">object</span> at <span class="bn">0x10c662e48</span><span class="op">></span> -<span class="op">>>></span> <span class="bu">str</span>(g) -<span class="co">'<__main__.PassThrough object at 0x10c662e48>'</span> -<span class="op">>>></span> <span class="bu">hasattr</span>(g, <span class="st">'__str__'</span>) -Accessing <span class="st">'__str__'</span> -<span class="va">True</span> -<span class="op">>>></span> g.<span class="fu">__str__</span>() -Accessing <span class="st">'__str__'</span> -<span class="co">'0'</span></code></pre></div> -<p>In addition, here's what happens if you try to "pass through" a function:</p> -<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="op">>>></span> <span class="kw">def</span> f(): <span class="cf">return</span> <span class="va">True</span> -<span class="op">>>></span> g <span class="op">=</span> PassThrough(f) -<span class="op">>>></span> g() -Accessing <span class="st">'__class__'</span> -Accessing <span class="st">'__class__'</span> -Traceback (most recent call last): - File <span class="st">"<ipython-input-6-d65ffd94a45c>"</span>, line <span class="dv">1</span>, <span class="kw">in</span> <span class="op"><</span>module<span class="op">></span> - g() -<span class="pp">TypeError</span>: <span class="st">'PassThrough'</span> <span class="bu">object</span> <span class="kw">is</span> <span class="kw">not</span> <span class="bu">callable</span> - -<span class="op">>>></span> <span class="bu">callable</span>(g) -<span class="va">False</span> -<span class="op">>>></span> <span class="bu">hasattr</span>(g, <span class="st">'__call__'</span>) -Accessing <span class="st">'__call__'</span> -<span class="va">True</span> -<span class="op">>>></span> g.<span class="fu">__call__</span>() -Accessing <span class="st">'__call__'</span> -<span class="va">True</span></code></pre></div> -<p>As you can tell, although <code>__str__</code> or <code>__call__</code> may have been implemented through <code>__getattribute__</code>, and <code>hasattr</code> (which in turn depends on <code>getattr</code>) has no trouble finding them, they are not picked up by <code>str</code> or function call <code>(...)</code>. At this point, one would suspect that this is due to <code>str</code> or function call only looking at the class instance's <code>__dict__</code>. Compare this to the behavior of an old-style class:</p> -<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="kw">class</span> PassThrough(): - - <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>, obj): - <span class="va">self</span>._obj <span class="op">=</span> obj - - <span class="kw">def</span> <span class="fu">__getattr__</span>(<span class="va">self</span>, name): - <span class="bu">print</span>(<span class="st">"Acessing '</span><span class="sc">%s</span><span class="st">'"</span> <span class="op">%</span> name) - <span class="cf">return</span> <span class="va">self</span>._obj.<span class="fu">__getattribute__</span>(name)</code></pre></div> -<p>Now:</p> -<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="op">>>></span> g <span class="op">=</span> PassThrough(<span class="dv">0</span>) -<span class="op">>>></span> <span class="bu">print</span>(g) -Acessing <span class="st">'__str__'</span> -<span class="dv">0</span> -<span class="op">>>></span> <span class="kw">def</span> f(): <span class="cf">return</span> <span class="va">True</span> -<span class="op">>>></span> g <span class="op">=</span> PassThrough(f) -<span class="op">>>></span> g() -Acessing <span class="st">'__call__'</span> -<span class="va">True</span></code></pre></div> -<p>Note that magic method access is always routed through <code>__getattr__</code>.</p> -<p>After some digging, my suspicion was confirmed: indeed, for new-style classes, rather than invoking <code>__getattribute__</code>, the Python interpreter only looks for magic methods in <code>__dict__</code>. But is there a workaround for implementing something like the <code>PassThrough</code> class above? There's a <a href="http://stackoverflow.com/a/9059858/">nice answer</a> on StackOverflow that uses a metaclass to "automatically add proxies for magic methods at the time of class creation", to quote the author. However, the thing about Tomorrow is that <em>we don't have the result and don't know whatever magic methods it might have at class creation</em> — after all, Python isn't a statically typed language. It is possible for programmers to offer hints, but then Tomorrow won't be as elegant and magical anymore. Therefore, unfortunately enough, Tomorrow isn't portable to Python 3 — at least not without a substantial hack that's beyond my knowledge, or a complete overhaul of its logic (haven't thought about that).</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>Pretty much since the beginning, I believe (the <a href="https://github.com/madisonmay/Tomorrow/commit/22a53dfbcf9b516ecd1770eeca9fcf1720271240">initial commit</a> was from July 24 of this year). I don't remember how I came accross it though.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-12-27-lesson-on-magic-method-access-of-python-new-style-classes-from-my-failed-python3-port-of-tomorrow.html#fnref1">↩︎</a></p></li> -</ol> -</div> -]]></description><author>zmwangx@gmail.com (Zhiming Wang)</author><guid isPermaLink="true">http://archive.zhimingwang.org/blog/2015-12-27-lesson-on-magic-method-access-of-python-new-style-classes-from-my-failed-python3-port-of-tomorrow.html</guid><pubDate>Mon, 28 Dec 2015 00:47:05 GMT</pubDate></item><item><title>autoenv with auto cleanup</title><link>http://archive.zhimingwang.org/blog/2015-12-26-autoenv-with-auto-cleanup.html</link><description><![CDATA[ - -<p>I heard about <a href="https://github.com/kennethreitz/autoenv">kennethreitz/autoenv</a> a long time ago. The idea of autoloading project-specific environment modifications is nice, but no auto cleanup after leaving a project was a showstopper for me.</p> -<p>Today, I took matters into my own hands and wrote a fresh Zsh implementation<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-12-26-autoenv-with-auto-cleanup.html#fn1" id="fnref1"><sup>1</sup></a> with auto cleanup support. Check it out: <a class="uri" href="https://github.com/zmwangx/prezto/tree/master/modules/autoenv">https://github.com/zmwangx/prezto/tree/master/modules/autoenv</a>.</p> -<p>As a quick promotion, let me show you two common examples.</p> -<p>First, inserting some local bin directory into the search path. This is easily done by a one-line <code>.env</code>, say,</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh">autoenv-insert-paths bin libexec</code></pre></div> -<p>This way <code>$PWD/bin</code> and <code>$PWD/libexec</code> are inserted to the beginning of the search path, which will persist until you leave the directory tree. That is to say, the inserted paths will still be available when you descend into subdirectories (and more specific <code>.env</code>'s can even be stacked as you descend), but they will be purged as soon as you leave the tree. Clever, isn't it?</p> -<p>Secondly, exporting project-specific environment variables. The <code>.env</code> would look like</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh"><span class="kw">export</span> <span class="ot">HOMEBREW_DEVELOPER=</span>not-for-the-faint-hearted - -<span class="fu">autoenv-purge ()</span> <span class="kw">unset</span> HOMEBREW_DEVELOPER</code></pre></div> -<p>where the body of <code>autoenv-purge</code> will be executed when you leave the directory tree. No more junk floating around.</p> -<p>Again, for more info, including detailed usage and customization instructions, please visit <a href="https://github.com/zmwangx/prezto/tree/master/modules/autoenv"><code>modules/autoenv</code></a> in zmwangx/prezto.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>This is not a re-implementation in the common sense. My little Zsh module is inspired by kennethreitz/autoenv and reminiscent of that older project, but I took nothing from there (in fact I didn't even read their source code). I also don't claim to support their entire feature set. For instance, kennethreitz/autoenv claims to be Foreman compatible, which includes turning on <code>ALL_EXPORT</code>. However, I don't think <code>ALL_EXPORT</code> by default is a good idea, so with my <code>autoenv</code>, if you want <code>ALL_EXPORT</code> you have to set it explicitly.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-12-26-autoenv-with-auto-cleanup.html#fnref1">↩︎</a></p></li> -</ol> -</div> -]]></description><author>zmwangx@gmail.com (Zhiming Wang)</author><guid isPermaLink="true">http://archive.zhimingwang.org/blog/2015-12-26-autoenv-with-auto-cleanup.html</guid><pubDate>Sat, 26 Dec 2015 08:15:48 GMT</pubDate></item><item><title>Regex flavor hell</title><link>http://archive.zhimingwang.org/blog/2015-12-20-regex-flavor-hell.html</link><description><![CDATA[ - -<p>I write a lot of shell scripts, which means dealing with common *ix utilities a lot. I typically want my scripts to work on both OS X and Linux (or OS X + GNU utilities, which is my personal setup), which means writing commands that are understood in both GNU/Linux and BSD worlds. Unfortunately that's not so simple, because to do that I usually have to give up readily available functionalities (especially the vast collection of useful options typical of GNU utilities) and am constantly thrown back to the stone age that is POSIX, or a little bit more than POSIX.</p> -<p>Working with regular expressions is especially painful. Almost every implementation of every utility (with regex support) has its own flavor of regex. Most notably the big three: <code>grep</code>, <code>sed</code> and <code>awk</code>. GNU utilities of course come with GNU extensions, but they are nothing when aiming for compatibility. Ignoring GNU extensions, there's a way to turn on standard POSIX extensions (ERE) on <code>sed</code>, but unfortunately GNU and BSD use different flags: <code>-r</code> for GNU sed and <code>-E</code> for BSD sed. The two implementations of <code>grep</code> thankfully use the same flag <code>-E</code> to turn on ERE, but GNU grep, being a GNU utility and having to distinguish itself from its mundane counterpart, further implements <code>-P,--perl-regexp</code> — regexers' dream. It's there but I can't use it, except in an interactive shell. <code>awk</code> has more than two implementations and will be left out of this discussion.</p> -<p>Anyway, despite all these flavor issues, I can usually get away with BRE, although it's verbose and unreadable as hell (quantifiers in particular) and doesn't support alternation. I would be thankful if BRE is the end of the story, but it is not. There are more tools lurking around trying to sabotage scripters. <code>find</code> is a perfect example. BSD <code>find</code>, unsurprisingly, uses BRE by default with <code>-regex</code> and <code>-iregex</code>, and ERE may be turned on with the <code>-E</code> flag. GNU findutils <code>find</code>, however, tries to be helpful and future-proof by having a <code>-regextype</code> option:</p> -<blockquote> -<p>Changes the regular expression syntax understood by <code>-regex</code> and <code>-iregex</code> tests which occur later on the command line. Currently-implemented types are <code>emacs</code> (this is the default), <code>posix-awk</code>, <code>posix-basic</code>, <code>posix-egrep</code> and <code>posix-extended</code>.</p> -</blockquote> -<p>The Emacs flavor? You mean Elisp regexp? Okay fine, <a href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html">BRE</a> — with few features other than grouping (<code>\(...\)</code>), quantifiers (<code>*</code> or <code>\{n,m\}</code>), bracket expressions and character classes — should still be pretty much compatible with Elisp regexp. However, the "Emacs flavor" isn't even the Elisp flavor. It's a <a href="https://www.gnu.org/software/findutils/manual/html_node/find_html/emacs-regular-expression-syntax.html">stripped version</a> specifically for findutils. In particular, there are <code>*</code>, <code>+</code> and <code>?</code> but no curly braces quantifiers, so gone is the dream of writing even just mildly complex regexps that are compatible with both BSD <code>find</code> and GNU findutils <code>find</code>. By the way, in case you wonder, the <a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/find.html">POSIX <code>find</code></a> doesn't even have a <code>-regex</code> primary/operator...</p> -<p>What a cruelly realistic world we live in.</p> -]]></description><author>zmwangx@gmail.com (Zhiming Wang)</author><guid isPermaLink="true">http://archive.zhimingwang.org/blog/2015-12-20-regex-flavor-hell.html</guid><pubDate>Mon, 21 Dec 2015 00:03:03 GMT</pubDate></item><item><title>Spoiled by Retina, in less than a day</title><link>http://archive.zhimingwang.org/blog/2015-12-16-spoiled-by-retina-in-less-than-a-day.html</link><description><![CDATA[ - -<p>I finally got a 15'' Retina MacBook Pro this morning to replace my 13'' mid-2012 non-Retina MacBook Pro, whose spinning disk has been getting increasingly slower (or so I felt).<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-12-16-spoiled-by-retina-in-less-than-a-day.html#fn1" id="fnref1"><sup>1</sup></a> Apparently this is a pretty significant landmark in my personal computing history, since I'm saying goodbye to both spinning disk and non-Retina display on my primary computing device.</p> -<p>The transition was initially smooth except for a few things. First, as a tap-to-click wizard I immediately turned on tap-to-click, but I had a hard time dragging things because it was too easy to trigger a force touch instead on the medium setting, and under the firm setting I could hardly force touch at all; in the end I just turned off force touch altogether, and haven't had any problem since. By the way, I was initially worried about the keyboard too but it worked surprisingly well for me, so no complaints there. Secondly, <a href="http://archive.zhimingwang.org/blog/2015-08-31-after-all-these-years-10pt-non-anti-aliased-monaco-is-still-the-best.html">10pt non-anti-aliased Monaco</a> looks weird on Retina since it's no longer the beloved bitmap version. I turned on antialiasing and now it's no longer weird, but it felt totally different and I'm not sure if I like it (definitely not as much as the 10pt bitmap Monaco anyway). It's okay right now but I'll probably need to spend some time trying out different fonts. Obviously there are <a href="https://news.ycombinator.com/item?id=10140728">like-minded folks</a> out there. Sad story.</p> -<p>So much for first impressions. Apart from Monaco, everything felt great, until I returned home (I was doing setup away from home to get a less shitty connection) and connected my 27'' external monitor. Holy crap, I couldn't believe my eyes. The dock icons — the first things I saw before launching anything — looked <em>so blurry I couldn't stare at them for more than a few seconds</em>. That was after staring at the Retina display for less than five hours. Not to mention PDFs; they look ultra crisp on the Retina display and ultra crappy on non-Retina — especially in Preview, which is a problem I've been aware of since Yosemite.<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-12-16-spoiled-by-retina-in-less-than-a-day.html#fn2" id="fnref2"><sup>2</sup></a> Moreover, the terminal font is more problematic than initially estimated — <em>now I have a retina display and a non-retina one side-by-side, yet I can only set one font for my default profile, which will never satisfy both</em>!<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-12-16-spoiled-by-retina-in-less-than-a-day.html#fn3" id="fnref3"><sup>3</sup></a> This is so awkward I can't think of a solution. One obvious approach is to ditch the blurry 27'' and only work from the Retina 15'', but should I really let the large canvas sit idle? No idea. Or should I get a 4K external display? First, a 4K display at 27'' still can't rival the pixel density of 2880x1800 at 15.4'' (Apple ships 5K at 27'' for a reason). Secondly and more importantly, I don't have the budget for such a thing after throwing money at an expensive 15'' rMBP (with 512 GB SSD)...</p> -<p>Transition periods are always awkward, I guess.</p> -<hr/> -<p><strong>12/17/2015 Update.</strong> After more than a full day's use, I actually quite love 10pt Monaco on a Retina display. I tried various fonts, including Menlo, Consolas and so on, but none of them has that whimsical feeling of Monaco. Hopefully the font is stuck now.</p> -<hr/> -<p><strong>12/28/2015 Update.</strong> A dozen days later, I can hardly look at 10pt Monaco on a non-Retina screen anymore, antialiased or not, especially not in bold. Mind blown.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>I haven't got the nerve to replace the hard drive myself, since it looks so much more complicated than upgrading the memory.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-12-16-spoiled-by-retina-in-less-than-a-day.html#fnref1">↩︎</a></p></li> -<li id="fn2"><p>PDFs looked so horrible in Preview (and TeXShop, my LaTeX previewer, which only serves a niche) that I often viewed them in browsers (!!), where text at least looks reasonable (on par with slightly blurry text elsewhere). PDF Expert came along and kind of made the situation better for non-Retina.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-12-16-spoiled-by-retina-in-less-than-a-day.html#fnref2">↩︎</a></p></li> -<li id="fn3"><p>Provided that I'll religiously stick to 10pt non-anti-aliased Monaco on non-Retina.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-12-16-spoiled-by-retina-in-less-than-a-day.html#fnref3">↩︎</a></p></li> -</ol> -</div> -]]></description><author>zmwangx@gmail.com (Zhiming Wang)</author><guid isPermaLink="true">http://archive.zhimingwang.org/blog/2015-12-16-spoiled-by-retina-in-less-than-a-day.html</guid><pubDate>Thu, 17 Dec 2015 05:10:08 GMT</pubDate></item><item><title>Safeguarding git repos against accidental rm</title><link>http://archive.zhimingwang.org/blog/2015-12-08-safeguarding-git-repos-against-accidental-rm.html</link><description><![CDATA[ - -<p>Everyone who has spent a sizable portion of their life in terminals has experienced that "oh shit" moment: you realize what you've done immediately after you've hit enter, but it's already too late. And needlessly to say, many of those are associated to accidental <code>rm</code>s.</p> -<p>I just had one of those moments. I was going to delete a subdirectory of <code>~/.config</code>, but hit return prematurely, and the command line ended up being <code>rm -r ~/.config</code>. Imagine the horror one second later. Fortunately I was saved by the read-only objects in <code>.git</code>, which triggered prompts; however, damage was already done, to some extent. I had to reinit the repo and do a hard reset, and a corrupted submodule was in my way (it blocked my attempt of <code>git reset --hard</code>) which I eventually had to completely remove and re-add. In the end everything was recovered (hopefully) and back to normal, but this episode was definitely not great for heart health, which led me to rethink <code>rm</code>.</p> -<p>I've tried several safer <code>rm</code> solutions before. The first and obvious is to alias <code>rm</code> to <code>rm -i</code>, but having to answer dozens of prompts a day (or more) is agonizing and unproductive. I've also tried trashing, but a nonempty trash can makes me sick, so not for me either. I also used <code>safe-rm</code> for a couple of months, but without supplying my own blacklist (I have none to be blacklisted), I've never hit the default blacklist; apparently I'm not stupid enough to mess in system locations, so this won't really help much. Fortunately though, this time I might have found a very good solution for myself.</p> -<p>The idea is to protect all git repos. Git repos<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-12-08-safeguarding-git-repos-against-accidental-rm.html#fn1" id="fnref1"><sup>1</sup></a> are among the most valuable assets of programmers, and they have the nice property of not being completely removable without <code>-f</code> or <code>--force</code> (the work tree of a submodule, where <code>.git</code> is a regular file containing the relative path of the git dir, can be removed without <code>--force</code>, but we don't want to damage submodules anyway, so let's not single them out). It's unlikely that we would intend to remove a repo directory without specifying <code>-f</code> or <code>--force</code>, so let's just reject all such <code>rm</code> calls.</p> -<p>The wrapper is very easy to write. Here's one implementation for Zsh with support for both GNU coreutils and BSD <code>rm</code>.</p> -<div class="sourceCode"><pre class="sourceCode zsh"><code class="sourceCode zsh"><span class="kw">rm</span> <span class="kw">()</span> <span class="kw">{</span> - <span class="kw">setopt</span> localoptions noshwordsplit noksharrays - <span class="kw">local</span> <span class="ot">args_backup</span> <span class="ot">force</span> <span class="ot">node</span> - <span class="kw">set</span> -A args_backup <span class="ot">$@</span> - <span class="kw">while</span> <span class="kw">:</span>; <span class="kw">do</span> - <span class="kw">case</span> <span class="ot">$1</span><span class="kw"> in</span> - --force<span class="kw">|</span>-*f*<span class="kw">)</span> <span class="ot">force=</span>1 <span class="kw">&&</span> <span class="kw">shift;;</span> - --<span class="kw">)</span> <span class="kw">shift</span> <span class="kw">&&</span> <span class="kw">break;;</span> - -*<span class="kw">)</span> <span class="kw">shift;;</span> - *<span class="kw">)</span> <span class="kw">break;;</span> - <span class="kw">esac</span> - <span class="kw">done</span> - <span class="kw">for</span> node; <span class="kw">do</span> - <span class="co"># -f, --force hasn't been specified && node is a git repo</span> - [[ -z <span class="ot">$force</span> <span class="kw">&&</span> -e <span class="ot">$node</span>/.git ]] <span class="kw">&&</span> <span class="kw">{</span> - <span class="kw">printf</span> <span class="st">"\e[31m'%s' is a git repo -- won't remove without the -f or --force option\e[0m\n"</span> <span class="ot">$node</span> - <span class="kw">return</span> 1 - <span class="kw">}</span> - <span class="kw">done</span> - <span class="kw">command</span> <span class="kw">rm</span> <span class="ot">$args_backup</span> -<span class="kw">}</span></code></pre></div> -<p>Personally, I stick it into a <a href="https://github.com/zmwangx/prezto/tree/master/modules/rm_guard">Prezto module</a> available from my fork. Hopefully it will serve me well this time round.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>In this article, "repo" stands for the work tree of a repo, unless otherwise noted; the actual repo with git objects is referred to as "git dir".<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-12-08-safeguarding-git-repos-against-accidental-rm.html#fnref1">↩︎</a></p></li> -</ol> -</div> -]]></description><author>zmwangx@gmail.com (Zhiming Wang)</author><guid isPermaLink="true">http://archive.zhimingwang.org/blog/2015-12-08-safeguarding-git-repos-against-accidental-rm.html</guid><pubDate>Tue, 08 Dec 2015 08:17:39 GMT</pubDate></item><item><title>Bash function exporting fiasco</title><link>http://archive.zhimingwang.org/blog/2015-11-25-bash-function-exporting-fiasco.html</link><description><![CDATA[ - -<p>Bash is the only major shell (and the only shell that I know of) that implements function exporting. By now everyone should have heard of this feature, I suppose, after the publicity of Shellshock last year. I was personally introduced to it while writing parallel processing scripts <a href="https://www.gnu.org/software/parallel/parallel_tutorial.html#Transfer-environment-variables-and-functions">with GNU Parallel</a> (long before Shellshock), and it seemed useful and clever at that time. Back then I often wondered why it didn't make its way into Z shell. However, now that I'm much more seasoned in shell scripting, I can see why and how this feature is troubled and of debatable value.</p> -<p>Two problems lie at the heart of function exporting:</p> -<ol style="list-style-type: decimal"> -<li>As always, everything clever comes at a cost;</li> -<li>Code execution from untrusted source.</li> -</ol> -<p>Regarding the first problem, the cost of function exporting is to mess with the environment, in a very hackish way. The environment was designed to hold data, not code, and we're not in the utopia of Lisp; but bash forced its way through. Pre-shellshock, exported <code>func</code> was stored as <code>func=() {...</code> in env; post-shellshock, it was first <code>BASH_FUNC_func()=() {...</code> (which didn't entirely fix the issue), and then <code>BASH_FUNC_func%%=() {...</code>.</p> -<p>The second problem doesn't need much explanation — <em>shellshock it was</em>. It has been extensively documented elsewhere, so I'll just succinctly comment that to load exported functions into a subshell, function definitions have to be retrieved from the environment and executed (again because we're not in the utopia of Lisp<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-11-25-bash-function-exporting-fiasco.html#fn1" id="fnref1"><sup>1</sup></a>), and loading is done passively from the subshell user's point of view, hence the code execution bug(s). The bug(s) has(have) allegedly been fixed, but code execution (presumably with the appropriate safeguards now) still can't be avoided altogether, so just like a sanitized <code>eval</code>, it would still wake you up at night.</p> -<p>Well, if that's all I have to say, I wouldn't have started this post today. The thing that's bugging me is another issue I've found recently that's entirely avoidable, yet upon which we'll probably never see light ever after due to a combination of factors.</p> -<p>It started with <a href="http://stackoverflow.com/q/33819243/19447840">this question on SO</a>. While troubleshooting I quickly noticed that a Bash-emulated <code>sh</code> imports those <code>BASH_FUNC</code>s from the environment:</p> -<pre><code>> bash -c 'func () { echo "exported function loaded"; } && export -f func && ln -sf /bin/bash sh && ./sh -c func' -exported function loaded</code></pre> -<p>It gets worse when the function isn't Bourne shell compatible (e.g., when it uses process substitution):</p> -<pre><code>> bash -c 'func () { cat <(echo hello); } && export -f func && ln -sf /bin/bash sh && ./sh -c func' -cat: <(echo hello): No such file or directory</code></pre> -<p>That's surprising but not scary enough, because if you're not a fool you won't call <code>func</code> in <code>sh</code> anyway. However, if you're unfortunate enough to be dealing with <code>/bin/sh</code> on OS X (bash 3.2 under the hood, modified by Apple or not I'm not sure), then all hell break loose:</p> -<pre><code>> bash -c 'func () { cat <(echo hello); } && export -f func && /bin/sh -c :' # OS X only -/bin/sh: func: line 0: syntax error near unexpected token `(' -/bin/sh: func: line 0: `func () { cat <(echo hello)' -/bin/sh: error importing function definition for `func'</code></pre> -<p>Note that we're actively doing nothing in <code>sh</code>, yet we get all these syntax errors from loading <code>func</code>. This happens to every invocation of <code>sh</code>, and as you might expect, there are no shortage of programs that are either <code>sh</code> scripts (e.g., fasd) or have internal <code>sh</code> calls (e.g., GNU Parallel<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-11-25-bash-function-exporting-fiasco.html#fn2" id="fnref2"><sup>2</sup></a>). A single export of a Bourn shell incompatible function will haunt you through the entire session. Oops.</p> -<p>As I said, I don't know if the displayed error messages are due to Apple's modifications (anyone willing to look at the <a href="https://opensource.apple.com/source/bash/bash-97/">source code</a>?), since a symlink named <code>sh</code> to <code>/bin/bash</code> doesn't print error messages, but instead load the wrong function, which is almost as bad but less annoying to innocent users. At any rate, it's not even worth reporting, either to GNU or Apple, because we're stuck with bash 3.2 for <code>/bin/sh</code> forever (thank you GPLv3), and it takes a hell of a vulnerability like shellshock to get a small update out of Apple's hands. We can install newer shells to <code>/usr/local</code> as much as we'd like to, but <code>/bin/sh</code> is simply the final word for many tasks involving the shell. Yet it's stained by this troubled bash-specific feature, and it's not going anywhere. So sad.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>I'm not commenting on the security of Lisp.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-11-25-bash-function-exporting-fiasco.html#fnref1">↩︎</a></p></li> -<li id="fn2"><p><strong>04/14/2015 Update.</strong> GNU Parallel is no longer haunted by this issue since <a href="http://git.savannah.gnu.org/cgit/parallel.git/commit/?id=3d919c6cd427e9615f56f260eb959a44d5d32c18"><code>3d919c6</code></a>.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-11-25-bash-function-exporting-fiasco.html#fnref2">↩︎</a></p></li> -</ol> -</div> -]]></description><author>zmwangx@gmail.com (Zhiming Wang)</author><guid isPermaLink="true">http://archive.zhimingwang.org/blog/2015-11-25-bash-function-exporting-fiasco.html</guid><pubDate>Wed, 25 Nov 2015 23:38:13 GMT</pubDate></item><item><title>We need a programming keyboard on iOS</title><link>http://archive.zhimingwang.org/blog/2015-11-15-we-need-a-programming-keyboard-on-ios.html</link><description><![CDATA[ - -<p>We do. If you ever tried to say something on GitHub (web) or StackOverflow (web or app) on iOS, you'll probably agree with me. The stock keyboard (or any third party keyboard that I've heard of) is simply awful at this. Typing on iOS software keyboard is unpleasant enough to begin with, but behold:</p> -<ul> -<li>Auto"correct" messes up everything as fast as you can type, which isn't really fast anyway; might as well call it autorot.</li> -<li>The backtick is a click plus a loooong click (on the single quote key) plus another click away. Good luck typing code in Markdown,<a class="footnoteRef" href="http://archive.zhimingwang.org/blog/2015-11-15-we-need-a-programming-keyboard-on-ios.html#fn1" id="fnref1"><sup>1</sup></a> especially if you use GFM fenced code block like all of us do.</li> -<li>Brackets, curly braces, the underscore, the pound, etc. are all three clicks away.</li> -</ul> -<p>The solution is pretty obvious actually. I don't know about smaller phones, but the software keyboard on a landscape iPhone 6 Plus has four rows, which takes up about 40% of vertical screen estate, and it has fourteen keys in the top row. With a little bit of effort it can be made into a five-row, full-sized keyboard (without arrow keys perhaps) without taking up a ridiculous amount of space. Since the horizontal 6 Plus could handle it, any iPad should be able to handle it too; definitely shouldn't be an iPad Pro-only luxury. Turn off autocorrect on top of that, and you get a decent programming (or better put, programmer-oriented) keyboard.</p> -<p>This is merely a rant, but it would awesome if anyone sets out to make one.</p> -<div class="footnotes"> -<hr/> -<ol> -<li id="fn1"><p>To be fair, typing BBCode is even worse. Unfortunately that's what Ars Technica use, and I've given up on commenting there.<a class="footnotes-backlink" href="http://archive.zhimingwang.org/blog/2015-11-15-we-need-a-programming-keyboard-on-ios.html#fnref1">↩︎</a></p></li> -</ol> -</div> -]]></description><author>zmwangx@gmail.com (Zhiming Wang)</author><guid isPermaLink="true">http://archive.zhimingwang.org/blog/2015-11-15-we-need-a-programming-keyboard-on-ios.html</guid><pubDate>Sun, 15 Nov 2015 10:17:05 GMT</pubDate></item></channel></rss> diff --git a/build/sitemap.xml b/build/sitemap.xml deleted file mode 100644 index e9b9cf8e..00000000 --- a/build/sitemap.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"><url><loc>http://archive.zhimingwang.org/</loc><lastmod>2017-04-28T00:29:42+02:00</lastmod><changefreq>daily</changefreq><priority>1.0</priority></url><url><loc>http://archive.zhimingwang.org/blog/2016-10-26-pyenv-compiling-python-with-sqlite-in-nonstandard-location.html</loc><lastmod>2016-10-26T12:16:22-04:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2016-09-01-this-blog-is-now-behind-cloudflare.html</loc><lastmod>2016-09-01T20:11:00+08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2016-06-24-its-2016-and-microsoft-is-the-only-legit-player-who-spams-me-without-unsubscribe-links.html</loc><lastmod>2016-06-24T05:40:01+08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2016-05-07-chrome-is-screwing-with-our-extensions-again.html</loc><lastmod>2016-05-07T18:49:26-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2016-04-10-emacss-got-a-redesigned-website.html</loc><lastmod>2016-04-10T03:04:19-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2016-03-06-google-chrome-keeps-getting-uglier.html</loc><lastmod>2016-03-06T14:59:45-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2016-01-26-dropbox-noteworthy-and-damned-skeuomorphism.html</loc><lastmod>2016-01-26T12:18:36-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2016-01-24-antivirus-app-on-mas-top-chart.html</loc><lastmod>2016-01-24T18:43:28-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2016-01-18-me-too-comments-on-github.html</loc><lastmod>2016-01-18T16:36:40-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2016-01-14-the-dirtiest-mistakes-of-os-x.html</loc><lastmod>2016-01-14T01:02:52-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2016-01-01-virtualenvs-for-everyone.html</loc><lastmod>2016-01-01T22:21:14-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-12-29-catches-when-installing-windows-7-with-boot-camp.html</loc><lastmod>2015-12-29T15:09:16-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-12-28-why-i-want-lossless-music-on-itunes-music-store.html</loc><lastmod>2015-12-28T03:15:45-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-12-27-lesson-on-magic-method-access-of-python-new-style-classes-from-my-failed-python3-port-of-tomorrow.html</loc><lastmod>2015-12-27T16:47:05-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-12-26-autoenv-with-auto-cleanup.html</loc><lastmod>2015-12-26T00:15:48-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-12-20-regex-flavor-hell.html</loc><lastmod>2015-12-20T16:03:03-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-12-16-spoiled-by-retina-in-less-than-a-day.html</loc><lastmod>2015-12-16T21:10:08-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-12-08-safeguarding-git-repos-against-accidental-rm.html</loc><lastmod>2015-12-08T00:17:39-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-11-25-bash-function-exporting-fiasco.html</loc><lastmod>2015-11-25T15:38:13-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-11-15-we-need-a-programming-keyboard-on-ios.html</loc><lastmod>2015-11-15T02:17:05-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-11-06-microsoft-drops-unlimited-onedrive-storage-after-people-use-it-for-unlimited-storage.html</loc><lastmod>2015-11-06T10:49:51-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-10-26-att-to-pure-talkusa-one-month-later.html</loc><lastmod>2015-10-26T00:00:30-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-10-14-sip-for-the-greater-good.html</loc><lastmod>2015-10-14T17:07:24-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-10-14-follow-up-the-sad-state-of-finder-on-el-capitan.html</loc><lastmod>2015-10-14T12:30:32-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-10-12-the-importance-of-dated-detailed-release-notes.html</loc><lastmod>2015-10-12T14:29:42-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-10-10-printing-long-80-character-per-line-plain-text-document-in-two-columns.html</loc><lastmod>2015-10-10T22:35:15-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-10-03-we-need-an-os-x-security-white-paper.html</loc><lastmod>2015-10-03T03:34:24-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-10-01-auto-hidden-menu-bar-dock-maximized-window-is-the-new-full-screen-mode.html</loc><lastmod>2015-10-01T15:48:59-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-10-01-upgrading-to-el-capitan.html</loc><lastmod>2015-10-01T11:46:44-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-09-25-removing-google-analytics-from-this-blog.html</loc><lastmod>2015-09-25T12:30:25-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-09-24-apple-watch-digital-crown-tightness-issue.html</loc><lastmod>2015-09-24T10:55:38-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-09-21-zsh-51-and-bracketed-paste.html</loc><lastmod>2015-09-21T14:40:36-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-08-31-after-all-these-years-10pt-non-anti-aliased-monaco-is-still-the-best.html</loc><lastmod>2015-08-31T06:31:03+08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-08-25-automated-os-x-provisioning.html</loc><lastmod>2015-08-25T08:16:44-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-08-20-i-installed-blockparty-and-the-only-thing-i-can-say-is-wow.html</loc><lastmod>2015-08-20T20:58:55-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-08-20-ios-9-turn-off-wi-fi-assist.html</loc><lastmod>2015-08-20T01:01:57-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-08-14-laymen.html</loc><lastmod>2015-08-14T18:32:13-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-08-13-other-peoples-___.html</loc><lastmod>2015-08-13T02:00:24-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-08-05-switching-to-capitalized-commit-messages.html</loc><lastmod>2015-08-05T19:38:37-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-08-05-should-apple-split-up-itunes-on-os-x.html</loc><lastmod>2015-08-05T14:09:51-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-08-02-sync-chrome-bookmarks-with-safari-on-os-x.html</loc><lastmod>2015-08-02T22:11:56-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-07-30-the-sad-state-of-finder-on-el-capitan.html</loc><lastmod>2015-07-30T23:59:09-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-07-25-dl-cmplntss-web-doesnt-suck.html</loc><lastmod>2015-07-25T11:31:54-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-07-19-github-experimental-attachment-formats-pdf-docx-and-pptx.html</loc><lastmod>2015-07-19T21:58:01-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-07-15-zsh-save-stdout-stderr-and-return-value-of-command-to-different-variables-without-temp-file.html</loc><lastmod>2015-07-15T09:21:47-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-06-29-dl-cmplnts-in-apple-news.html</loc><lastmod>2015-06-29T23:14:42-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-06-27-automatically-clean-up-previous-mobile-applications.html</loc><lastmod>2015-06-27T21:19:59-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-06-26-ios-9-searchable-settings.html</loc><lastmod>2015-06-26T23:59:28-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-06-23-all-problems-solved.html</loc><lastmod>2015-06-23T21:47:07-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-06-12-the-tip-of-the-iceberg.html</loc><lastmod>2015-06-12T14:24:18-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-06-10-chrome-disappointment-the-shabby-and-boring-old-bookmark-system-from-stone-age-strikes-back.html</loc><lastmod>2015-06-10T23:17:05-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-06-08-apple-turns-its-homepage-into-a-wwdc-liveblog.html</loc><lastmod>2015-06-08T14:42:50-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-06-07-stackoverflow-review-system-is-completely-bs.html</loc><lastmod>2015-06-07T18:58:57-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-05-30-using-a-personal-helper-package-in-everyday-scripting.html</loc><lastmod>2015-05-30T22:48:57-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-05-29-apples-customer-service-is-still-the-best-plus-an-authy-horror-story.html</loc><lastmod>2015-05-29T20:40:05-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-05-22-using-a-command-table-as-wallpaper.html</loc><lastmod>2015-05-22T00:48:19-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-05-19-bash-the-special-slash-character-in-filename-expansion.html</loc><lastmod>2015-05-19T18:33:51-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-05-09-storyboard-reached-01.html</loc><lastmod>2015-05-09T00:32:28-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-05-06-searchable-settings-are-one-honking-great-idea-lets-do-more-of-those.html</loc><lastmod>2015-05-06T19:29:46-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-05-05-graceful-handling-of-sigint-when-using-pythons-multiprocessingprocess.html</loc><lastmod>2015-05-05T22:03:39-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-05-05-new-blog-new-start.html</loc><lastmod>2015-05-05T02:42:44-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-05-03-why-oh-my-zsh-is-completely-broken.html</loc><lastmod>2015-05-03T17:15:49-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-04-26-using-python-3-with-emacs-jedi.html</loc><lastmod>2015-04-26T21:19:14-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-03-22-back-up-os-x-app-icons.html</loc><lastmod>2015-03-22T16:58:50-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-02-24-the-new-onedrive-api.html</loc><lastmod>2015-02-24T18:31:19-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-02-21-all-is-not-lost.html</loc><lastmod>2015-02-21T17:12:32-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-02-20-my-dock-and-updated-omnifocus.html</loc><lastmod>2015-02-20T16:16:10-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-02-17-microsoft-is-getting-cool-but-not-its-website.html</loc><lastmod>2015-02-17T18:57:19-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-02-10-monitor-progress-of-your-unix-pipes-with-pv.html</loc><lastmod>2015-02-10T02:18:30-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-01-21-web-design-microsoft-vs-apple.html</loc><lastmod>2015-01-21T16:30:51-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-01-10-fonts-why-chinese-web-design-is-hard.html</loc><lastmod>2015-01-10T09:30:02-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2015-01-01-os-x-system-ruby-encoding-annoyance.html</loc><lastmod>2015-01-01T22:49:39-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-12-23-mpv-launcher.html</loc><lastmod>2014-12-23T00:51:05-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-12-22-10k-images-on-imgur.html</loc><lastmod>2014-12-22T12:42:16-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-12-19-app-suggestion-dropzone-3.html</loc><lastmod>2014-12-19T14:08:57-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-12-14-the-google-chrome-comic-a-classic.html</loc><lastmod>2014-12-14T17:42:55-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-12-14-speeding-up-emacs-with-emacsclient.html</loc><lastmod>2014-12-14T10:06:02-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-12-13-the-mac-like-evernote.html</loc><lastmod>2014-12-13T21:47:31-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-12-10-omnifocus-change-sync-behavior-mac-and-ios.html</loc><lastmod>2014-12-10T22:45:34-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-12-05-distraction-free-writing.html</loc><lastmod>2014-12-05T21:09:10-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-11-30-opera-style-advanced-keyboard-shortcuts-in-safari.html</loc><lastmod>2014-11-30T17:20:20-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-11-28-going-diceware.html</loc><lastmod>2014-11-28T19:05:59-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-11-28-given-infinite-time.html</loc><lastmod>2014-11-28T00:18:19-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-11-26-original-images-in-day-one-journal.html</loc><lastmod>2014-11-26T00:22:16-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-11-25-i-got-16-gigs-of-ram.html</loc><lastmod>2014-11-25T16:28:30-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-11-24-why-i-abandoned-mathjax-and-fell-back-to-pdf.html</loc><lastmod>2014-11-24T20:54:36-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-11-24-iphone-photography-frustration.html</loc><lastmod>2014-11-24T12:42:25-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-11-20-dropbot-for-geeks(r).html</loc><lastmod>2014-11-20T09:48:15-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-11-19-convolution-of-irreducible-characters.html</loc><lastmod>2014-11-19T20:40:37-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-11-11-re-encoding-everything-for-iphone-6-plus.html</loc><lastmod>2014-11-11T13:31:25-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-11-10-average-phone-plan-in-the-u-dot-s-costs-ten-time-as-much-as-that-in-the-u-dot-k.html</loc><lastmod>2014-11-10T11:11:46-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-11-07-interstellar.html</loc><lastmod>2014-11-07T23:56:31-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-11-06-2014-nobel-prize-in-physics-led-lights-seriously.html</loc><lastmod>2014-11-06T11:08:45-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-11-05-apple-is-pushing-yosemite-hard.html</loc><lastmod>2014-11-05T22:17:01-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-11-05-list-youtube-playlist-with-youtube-dl.html</loc><lastmod>2014-11-05T10:37:58-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-11-02-vobcopy-dvdbackup-etc.html</loc><lastmod>2014-11-02T15:06:07-08:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-10-29-fun.html</loc><lastmod>2014-10-29T11:26:29-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-10-28-google-drive-no-selective-subfolder-sync.html</loc><lastmod>2014-10-28T20:49:24-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-10-28-mou-1-dot-0-fundraiser-goal-reached.html</loc><lastmod>2014-10-28T01:57:06-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-10-27-onedrive-goes-unlimited.html</loc><lastmod>2014-10-27T09:44:51-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-10-26-audio-cd-slash-dvd-to-iso-image-on-os-x.html</loc><lastmod>2014-10-26T23:29:47-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-10-26-disk-visualizer-daisydisk.html</loc><lastmod>2014-10-26T00:02:22-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-10-25-os-x-package-receipts.html</loc><lastmod>2014-10-25T13:26:02-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-10-24-charles-munger-donated-$65m-to-kitp.html</loc><lastmod>2014-10-24T16:41:36-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-10-23-ripping-copy-protected-dvd-with-mpv.html</loc><lastmod>2014-10-23T20:03:22-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-10-21-get-rolling.html</loc><lastmod>2014-10-21T11:40:14-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-10-20-help-mou-hit-1-dot-0.html</loc><lastmod>2014-10-20T17:37:45-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url><url><loc>http://archive.zhimingwang.org/blog/2014-10-20-hello-octopress.html</loc><lastmod>2014-10-20T16:53:00-07:00</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url></urlset> |