<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[尹良灿得闲]]></title>
  <link href="http://wenLiangcan.github.io/atom.xml" rel="self"/>
  <link href="http://wenLiangcan.github.io/"/>
  <updated>2015-08-12T01:40:45+08:00</updated>
  <id>http://wenLiangcan.github.io/</id>
  <author>
    <name><![CDATA[wenLiangcan]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[【译】ArcadeRs 1.1: 一个简单的窗口]]></title>
    <link href="http://wenLiangcan.github.io/blog/2015/08/11/arcaders-1-01/"/>
    <updated>2015-08-11T20:32:00+08:00</updated>
    <id>http://wenLiangcan.github.io/blog/2015/08/11/arcaders-1-01</id>
    <content type="html"><![CDATA[<blockquote><p>原文：<a href="https://jadpole.github.io/arcaders/arcaders-1-1/">ArcadeRS 1.1: A simple window</a></p></blockquote>

<p>本系列文章的目是通过开发一个简单的老式射击游戏来一探 <code>Rust</code> 这门语言，这是其中的第一部分。除去介绍，本系列共有 16 个部分组成：</p>

<ol>
<li><a href="http://wenLiangcan.github.io/blog/2015/08/11/arcaders-1-01/">一个简单的窗口</a>，我们在此安装 SDL2</li>
<li><a href="https://jadpole.github.io/arcaders/arcaders-1-2/">事件处理</a>，我们在此讨论生存期限</li>
<li><a href="https://jadpole.github.io/arcaders/arcaders-1-3/">处理更多的事件</a>，我们在此讨论宏</li>
<li><a href="https://jadpole.github.io/arcaders/arcaders-1-4/">视图</a>，我们在此学习装箱，模式匹配，trait 对象，还有动态分发</li>
<li><a href="https://jadpole.github.io/arcaders/arcaders-1-5/">视图的切换</a>，我们在此使用装箱，模式匹配，trait 对象，还有动态分发</li>
<li><a href="https://jadpole.github.io/arcaders/arcaders-1-6/">移动的矩形</a>，我们在此绘制图像</li>
<li><a href="#">Main menu</a>, where we play with textures and Rust&#8217;s vectors</li>
<li><a href="#">Sprites</a>, where we create shareable images</li>
<li><a href="#">Backgrounds</a>, where we handle resizing, scale and translate through time</li>
<li><a href="#">The player&#8217;s ship</a>, where we control a multi-sprite object</li>
<li><a href="#">Shooting bullets</a>, where we handle resource pooling</li>
<li><a href="#">Animated sprites</a>, where we render animated asteroids</li>
<li><a href="#">Asteroid attack!</a>, where we make multiple objects interact</li>
<li><a href="#">Explosions</a>, where we see things do boom.</li>
<li><a href="#">Music</a>, where we hear things go boom.</li>
<li><a href="#">High score &amp; wrap-up</a>, where we play with the filesystem</li>
</ol>


<h2>一个华丽的新项目</h2>

<p>作为开始，让我们亲切地请求 Cargo 为我们创建一个新项目。在你的项目目录下执行：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'><span class="nv">$ </span>cargo new arcade-rs --bin
</span><span class='line'><span class="nv">$ </span><span class="nb">cd </span>arcade-rs
</span></code></pre></td></tr></table></div></figure>


<p>如果你打开生成的 <code>Cargo.toml</code>，你可以看到类似如下的内容：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'><span class="o">[</span>package<span class="o">]</span>
</span><span class='line'><span class="nv">name</span> <span class="o">=</span> <span class="s2">&quot;arcade-rs&quot;</span>
</span><span class='line'><span class="nv">version</span> <span class="o">=</span> <span class="s2">&quot;0.1.0&quot;</span>
</span><span class='line'><span class="nv">authors</span> <span class="o">=</span> <span class="o">[</span><span class="s2">&quot;John Doe &lt;john.doe@example.com&gt;&quot;</span><span class="o">]</span>
</span></code></pre></td></tr></table></div></figure>


<p>你可以通过 <code>cargo run</code> 命令运行生成的 <code>hello world</code> 程序，然而现在来说这并没有什么卵用。我们要做的是，稍微更改一下这个配置文件以加入所需的依赖。请把以下几行添加到该文件的底部：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'><span class="o">[</span>dependencies<span class="o">]</span>
</span><span class='line'><span class="nv">sdl2</span> <span class="o">=</span> <span class="s2">&quot;0.6&quot;</span>
</span></code></pre></td></tr></table></div></figure>


<p>结束的时候，我们的项目会依赖于更多的外部 <code>crate</code> （<code>Rust</code> 概念中的 库），不过眼下我们只需要这些。<code>sdl2</code> <em>crate</em> 使我们可以创建程序窗口，在上面渲染画面和处理各种事件，而这些也正好是我们在接下来的几章将要做的事情。</p>

<blockquote><p>很可能你的电脑上尚未安装有 SDL2 的开发库，那样的话将无法编译 SDL2 的 Rust 绑定。
我建议你参照 <a href="https://github.com/AngryLawyer/rust-sdl2#sdl20--development-libraries">rust-sdl2 的 README 文件</a> 中的步骤，在你的系统中安装所需的开发库。
等你完成后我们接着继续。</p></blockquote>

<p>现在，SDL2 已经（希望是）安装在你的系统中了，你可以执行：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'><span class="nv">$ </span>cargo build
</span><span class='line'>    Updating registry <span class="sb">`</span>https://github.com/rust-lang/crates.io-index<span class="sb">`</span>
</span><span class='line'> Downloading sdl2 v0.6.0
</span><span class='line'> Downloading sdl2-sys v0.6.0
</span><span class='line'>   Compiling sdl2-sys v0.6.0
</span><span class='line'>   Compiling bitflags v0.2.1
</span><span class='line'>   Compiling rustc-serialize v0.3.15
</span><span class='line'>   Compiling libc v0.1.8
</span><span class='line'>   Compiling rand v0.3.8
</span><span class='line'>   Compiling num v0.1.25
</span><span class='line'>   Compiling sdl2 v0.6.0
</span><span class='line'>   Compiling arcade-rs v0.1.0 <span class="o">(</span>file:///home/johndoe/projects/arcade-rs<span class="o">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>如果一切顺利，各类绑定和它们的依赖就已经编译好而我们也可以开启一个窗口了。否则，很可能你并没有正确安装 SDL2 而你只有解决了这一问题才能进行接下来的步骤。</p>

<h2>激动人心的三秒钟</h2>

<p>好了，让我们来创建一个窗口。用你最喜欢的文本编辑器打开 <code>src/main.rs</code> 然后修改为以下内容：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">extern</span><span class="w"> </span><span class="n">crate</span><span class="w"> </span><span class="n">sdl2</span><span class="p">;</span><span class="w"></span>
</span><span class='line'>
</span><span class='line'><span class="kn">use</span><span class="w"> </span><span class="n">sdl2</span><span class="o">::</span><span class="n">pixels</span><span class="o">::</span><span class="n">Color</span><span class="p">;</span><span class="w"></span>
</span><span class='line'><span class="kn">use</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">thread</span><span class="p">;</span><span class="w"></span>
</span><span class='line'>
</span><span class='line'><span class="k">fn</span><span class="w"> </span><span class="n">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
</span><span class='line'><span class="w">    </span><span class="c1">// 初始化 SDL2</span>
</span><span class='line'><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">sdl_context</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sdl2</span><span class="o">::</span><span class="n">init</span><span class="p">().</span><span class="n">video</span><span class="p">()</span><span class="w"></span>
</span><span class='line'><span class="w">        </span><span class="p">.</span><span class="n">build</span><span class="p">().</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
</span><span class='line'>
</span><span class='line'><span class="w">    </span><span class="c1">// 创建窗口</span>
</span><span class='line'><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">window</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sdl_context</span><span class="p">.</span><span class="n">window</span><span class="p">(</span><span class="s">&quot;ArcadeRS Shooter&quot;</span><span class="p">,</span><span class="w"> </span><span class="mi">800</span><span class="p">,</span><span class="w"> </span><span class="mi">600</span><span class="p">)</span><span class="w"></span>
</span><span class='line'><span class="w">        </span><span class="p">.</span><span class="n">position_centered</span><span class="p">().</span><span class="n">opengl</span><span class="p">()</span><span class="w"></span>
</span><span class='line'><span class="w">        </span><span class="p">.</span><span class="n">build</span><span class="p">().</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
</span><span class='line'>
</span><span class='line'><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">renderer</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">window</span><span class="p">.</span><span class="n">renderer</span><span class="p">()</span><span class="w"></span>
</span><span class='line'><span class="w">        </span><span class="p">.</span><span class="n">accelerated</span><span class="p">()</span><span class="w"></span>
</span><span class='line'><span class="w">        </span><span class="p">.</span><span class="n">build</span><span class="p">().</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
</span><span class='line'>
</span><span class='line'><span class="w">    </span><span class="n">renderer</span><span class="p">.</span><span class="n">set_draw_color</span><span class="p">(</span><span class="n">Color</span><span class="o">::</span><span class="n">RGB</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">));</span><span class="w"></span>
</span><span class='line'><span class="w">    </span><span class="n">renderer</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span><span class="w"></span>
</span><span class='line'><span class="w">    </span><span class="n">renderer</span><span class="p">.</span><span class="n">present</span><span class="p">();</span><span class="w"></span>
</span><span class='line'>
</span><span class='line'><span class="w">    </span><span class="n">thread</span><span class="o">::</span><span class="n">sleep_ms</span><span class="p">(</span><span class="mi">3000</span><span class="p">);</span><span class="w"></span>
</span><span class='line'><span class="p">}</span><span class="w"></span>
</span></code></pre></td></tr></table></div></figure>


<p>现在，如果你运行这个程序的话&#8230;</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'><span class="nv">$ </span>cargo run
</span><span class='line'>   Compiling arcade-rs v0.1.0 <span class="o">(</span>file:///home/johndoe/projects/arcade-rs<span class="o">)</span>
</span><span class='line'>     Running <span class="sb">`</span>target/debug/arcade-rs<span class="sb">`</span>
</span></code></pre></td></tr></table></div></figure>


<p><img src="https://jadpole.github.io/images/arcade-1.png" alt="three_sec" /></p>

<p>&#8230; 你可以看到一个窗口在屏幕上停留了 3 秒钟，然后消失了。就是这样！有趣的部分来了：弄明白刚刚我们所写的究竟是什么意思。</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">extern</span><span class="w"> </span><span class="n">crate</span><span class="w"> </span><span class="n">sdl2</span><span class="p">;</span><span class="w"></span>
</span></code></pre></td></tr></table></div></figure>


<p>一开始我们先包含了作为依赖添加进来的 <code>sdl2</code> <em>crate</em>。如果需要，我们可以像 Python 那样，给它另起一个名字。比如这样：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">extern</span><span class="w"> </span><span class="n">crate</span><span class="w"> </span><span class="n">sdl2</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">pineapple</span><span class="p">;</span><span class="w"></span>
</span></code></pre></td></tr></table></div></figure>


<p>之后我们把代码中出现的所有 <code>sdl2</code> 都换成 <code>pineapple</code>（菠萝） 得到的结果是不变的。虽然我挺喜欢菠萝，接下来的文章里我还是继续使用 <code>sdl2</code> 算了（当然，没人强求 你 也这么做）。有一个类似的语法可以用于重命名被使用（use）的类型（type）和函数（function），我将在<a href="https://jadpole.github.io/arcaders/arcaders-1-6/">第 6 章</a>用到它。</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="kn">use</span><span class="w"> </span><span class="n">sdl2</span><span class="o">::</span><span class="n">pixels</span><span class="o">::</span><span class="n">Color</span><span class="p">;</span><span class="w"></span>
</span><span class='line'><span class="kn">use</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">thread</span><span class="p">;</span><span class="w"></span>
</span></code></pre></td></tr></table></div></figure>


<p>第一行很简单：因为 <code>sdl2::pixels::Color</code> 敲起来太长了，所以我们只使用（use）这一路径下的最后一个标识符 <code>Color</code> 来代表同一事物。<code>use</code> 语句不仅可以用于类型和函数，对 模块（module）同样有效。这就是第二行的用意，现在我们只需要写 <code>thread::某标函数</code> 而不用写 <code>std::thread::某函数</code>。</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">fn</span><span class="w"> </span><span class="n">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
</span><span class='line'>
</span><span class='line'><span class="p">}</span><span class="w"></span>
</span></code></pre></td></tr></table></div></figure>


<p>在此，我们声明了作为我们程序的入口的 <code>main</code> 函数。</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="kd">let</span><span class="w"> </span><span class="n">sdl_context</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sdl2</span><span class="o">::</span><span class="n">init</span><span class="p">().</span><span class="n">video</span><span class="p">()</span><span class="w"></span>
</span><span class='line'><span class="w">    </span><span class="p">.</span><span class="n">build</span><span class="p">().</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
</span></code></pre></td></tr></table></div></figure>


<p>现在，开始触及有趣的部分了！<code>init</code> 函数返回一个我们用来初始化 SDL2 的上下文（context）的对象。厉害之处是这里用到了 <code>Rust</code> 版的<a href="https://aturon.github.io/ownership/builders.html">生成器模式(builder pattern)</a>。就是说，<code>init</code> 返回如下类型的对象：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">pub</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="n">InitBuilder</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
</span><span class='line'><span class="w">    </span><span class="n">flags</span><span class="o">:</span><span class="w"> </span><span class="kt">u32</span><span class="w"></span>
</span><span class='line'><span class="p">}</span><span class="w"></span>
</span></code></pre></td></tr></table></div></figure>


<p>这一类型提供了一个便于使用 SDL2 API 的接口。通过调用比如像 <code>timer()</code>，<code>joystick()</code> 和 <code>video()</code> 这些方法，我们可以选择性的初始化 SDL2 的某些部分，以最小化这个库的占用空间。一旦准备就绪，我们调用 <code>build()</code> 方法，获得 <code>Result&lt;Sdl, String&gt;</code>。</p>

<p>使用 <code>Result</code> 类型的对象是 <code>Rust</code> 中进行错误处理（error handling）的方式。得到错误值的可能性被集成到了类型系统中，开发者被强制要求去处理这一情况，从而获取函数的结果。这一次，我们只是简单的通过 <code>unwrap()</code> “解封”其中的值，这意味着我们断定（assert）我们得到的是被封装在 <code>Ok</code> 类型中的正确值，否则的话就不再执行后续的代码。我们之所以这么做，是因为如果我们创建不了上下文，我们就无法渲染我们的游戏，我们的程序就失去了它的意义了。</p>

<p>解封（unwrapping）<code>Err</code> 中的值会把错误信息打印出来并引发恐慌（panic），使得程序安全地崩溃掉。如果被解封的值是 <code>Ok(Sdl)</code> 类型的话，解封出来的值会被直接返回并赋值给 <code>sdl_context</code>。</p>

<p>把上下文绑定（binding）到一个标识符的好处是，一旦它脱离了自己的作用域（在 <code>main</code> 函数结束处），它所持有的所有资源都会被自动释放。其实，就算我们的程序运行至某处 panic 了，析构器（destructor）也会被如常调用，以防止内存泄漏。这就是我所指的安全地崩溃掉。</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="kd">let</span><span class="w"> </span><span class="n">window</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sdl_context</span><span class="p">.</span><span class="n">window</span><span class="p">(</span><span class="s">&quot;ArcadeRS Shooter&quot;</span><span class="p">,</span><span class="w"> </span><span class="mi">800</span><span class="p">,</span><span class="w"> </span><span class="mi">600</span><span class="p">)</span><span class="w"></span>
</span><span class='line'><span class="w">    </span><span class="p">.</span><span class="n">position_centered</span><span class="p">().</span><span class="n">opengl</span><span class="p">()</span><span class="w"></span>
</span><span class='line'><span class="w">    </span><span class="p">.</span><span class="n">build</span><span class="p">().</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
</span></code></pre></td></tr></table></div></figure>


<p>我们在此处打开了窗口。它有一个名为“ArcadeRS Shooter”的标题，800 象素的宽度 和 600 象素的高度。像前面一样，这里使用了生成器模式，我们可以方便地使窗口居中和激活 OpenGL 模式（更高效）的渲染。</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">renderer</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">window</span><span class="p">.</span><span class="n">renderer</span><span class="p">()</span><span class="w"></span>
</span><span class='line'><span class="w">    </span><span class="p">.</span><span class="n">accelerated</span><span class="p">()</span><span class="w"></span>
</span><span class='line'><span class="w">    </span><span class="p">.</span><span class="n">build</span><span class="p">().</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
</span></code></pre></td></tr></table></div></figure>


<p>这一步你懂的！我们在创建一个与窗口关联的渲染器（renderer），把它设置成可以使用 OpenGL 来辅助渲染，之后我们会用它来“作画”。如果创建失败，程序就会伴随着错误信息 panic 掉。</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="n">renderer</span><span class="p">.</span><span class="n">set_draw_color</span><span class="p">(</span><span class="n">Color</span><span class="o">::</span><span class="n">RGB</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">));</span><span class="w"></span>
</span><span class='line'><span class="n">renderer</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span><span class="w"></span>
</span><span class='line'><span class="n">renderer</span><span class="p">.</span><span class="n">present</span><span class="p">();</span><span class="w"></span>
</span></code></pre></td></tr></table></div></figure>


<p>在第一行，我们把笔刷设置为黑色（red=0，green=0，blue=0）。第二行处，我们先清空缓冲区再填入刚刚选择的笔刷颜色。第三行交换缓冲区正式向用户展现我们绘制的画面。</p>

<p>如果我们去掉最后一行，奇怪的事情就发生了。比如在 Gnome 下，窗口的内容被设置成了它背后的画面。虽然可能听起来怪怪的，按照 <code>Rust</code> 世界的传统，<code>renderer</code> 所提供的接口让我们无法轻易地使程序挂掉。</p>

<p><img src="https://jadpole.github.io/images/arcade-2.png" alt="blank_win" /></p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="n">thread</span><span class="o">::</span><span class="n">sleep_ms</span><span class="p">(</span><span class="mi">3000</span><span class="p">);</span><span class="w"></span>
</span></code></pre></td></tr></table></div></figure>


<p>继续执行程序前，我们在这里先等待 3000 毫秒，即 3 秒钟。也可以看出，此后 <code>main</code> 函数就结束了，在其中分配的所有资源都会被释放掉。在用户看来，就是程序窗口被关掉。对我们来说，也没有太大的不同。美妙的是，即使此处发生了再多的事情，我们也无需为之操心！</p>

<p>你也许注意到了，我们从头到尾都无需写明任何数据类型。当然，我们使用了诸如 <code>sdl2::init</code> 和 <code>Color::new</code> 这些模块函数（module function）和关联函数（associated function）（也许你会对静态方法这个名字更熟悉些），可是我们从来没有告诉 <code>Rust</code> 我们的上下文的类型是 <code>sdl2::Sdl</code>。这被称为 类型推导（type inference），它是使得 <code>Rust</code> 让人愉快地使用的众多特性之一，虽然它们看起来像是无关紧要的附加品。</p>

<p>这就是本系列的第一部分。<a href="https://jadpole.github.io/arcaders/arcaders-1-2/">下一次</a>，我们将提出一种更好的关闭窗口的方式：通过点击那个叉叉（x）。</p>

<p>在那之前，保持 rusting！</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[【译】ArcadeRs 1.0: 介绍]]></title>
    <link href="http://wenLiangcan.github.io/blog/2015/08/11/arcaders-1-00/"/>
    <updated>2015-08-11T20:14:00+08:00</updated>
    <id>http://wenLiangcan.github.io/blog/2015/08/11/arcaders-1-00</id>
    <content type="html"><![CDATA[<blockquote><p>原文：<a href="https://jadpole.github.io/arcaders/arcaders-1-0/">ArcadeRS 1.0: The project</a></p></blockquote>

<p>本系列文章的目是通过开发一个简单的老式射击游戏来一探 <code>Rust</code> 这门语言，这是其中的介绍部分。除去介绍，本系列共有 16 个部分组成：</p>

<ol>
<li><a href="http://wenLiangcan.github.io/blog/2015/08/11/arcaders-1-01/">一个简单的窗口</a>，我们在此安装 SDL2</li>
<li><a href="https://jadpole.github.io/arcaders/arcaders-1-2/">事件处理</a>，我们在此讨论生存期限</li>
<li><a href="https://jadpole.github.io/arcaders/arcaders-1-3/">处理更多的事件</a>，我们在此讨论宏</li>
<li><a href="https://jadpole.github.io/arcaders/arcaders-1-4/">视图</a>，我们在此学习装箱，模式匹配，trait 对象，还有动态分发</li>
<li><a href="https://jadpole.github.io/arcaders/arcaders-1-5/">视图的切换</a>，我们在此使用装箱，模式匹配，trait 对象，还有动态分发</li>
<li><a href="https://jadpole.github.io/arcaders/arcaders-1-6/">移动的矩形</a>，我们在此绘制图像</li>
<li><a href="#">Main menu</a>, where we play with textures and Rust&#8217;s vectors</li>
<li><a href="#">Sprites</a>, where we create shareable images</li>
<li><a href="#">Backgrounds</a>, where we handle resizing, scale and translate through time</li>
<li><a href="#">The player&#8217;s ship</a>, where we control a multi-sprite object</li>
<li><a href="#">Shooting bullets</a>, where we handle resource pooling</li>
<li><a href="#">Animated sprites</a>, where we render animated asteroids</li>
<li><a href="#">Asteroid attack!</a>, where we make multiple objects interact</li>
<li><a href="#">Explosions</a>, where we see things do boom.</li>
<li><a href="#">Music</a>, where we hear things go boom.</li>
<li><a href="#">High score &amp; wrap-up</a>, where we play with the filesystem</li>
</ol>


<p>这是一篇写给那些哪怕仅仅是通过某个脚本语言，已经对软件开发这门技艺有所了解的人的教程，他们刚刚发现了这头名为 <code>Rust</code> 的怪兽。他们过了一遍<a href="https://doc.rust-lang.org/book/">官方教程</a>，阅读了大量关于这门看起来熟悉，据说向原有的软件安全概念发起了挑战的语言的博文，然后 excited，想要发掘如何真正地在实践中运用 <code>Rust</code>。</p>

<p>我对读者的要求是，他或她（或者它？）应该理解诸如接口，方法，条件结构，和（基础的）静态类型这些概念。多数情况下，这些术语的含义在其上下文中是不言自明的。然而，如果理解它们对你来说很成问题，提醒一下我不会对其作长篇大论的解释。</p>

<p>我还期望你阅读这篇教程前已经学习过一点 <code>Rust</code>，即使只是浅显的部分。比如你得明白 <code>Rust</code> 的 <code>use</code> 语句，哪怕仅限于在 <code>main.rs</code> 文件里，是用来干什么的。当然，你不需要成为一名专家才能探索其中的微妙。</p>

<p>在接下来的几周里，我们将会基于 Mike Geig 的棒棒哒 <a href="http://fixbyproximity.com/2d-game-development-course/">2D 游戏开发教程</a> 来制作一个太空射击游戏。我们还会编写一个叫做 <code>phi</code> 的库，它会为我们提供诸如视图（在 LibGDX 中称为 screens），内置碰撞检测（虽然很基础）的矩形，和动态精灵等 2D 游戏所需的组件。</p>

<p>我们将要用到的库是 AngryLawyer 的 SDL2 的绑定，版本为 6.0，你可以在<a href="https://github.com/AngryLawyer/rust-sdl2">这里</a>找到，以及相关的一些插件。</p>

<p>继续讲述前，我要强调的是你无需精通 <code>Rust</code> 再阅读这篇教程。相反，本教程的目的之一就是探索 <code>Rust</code> 的微妙之处，哪怕不是主要的，基于此，老实说，我不推荐在生产中使用 <code>phi</code>。可是，你至少得浏览过<a href="https://doc.rust-lang.org/book/">官方教程</a>或者 <a href="http://rustbyexample.com/">Rust by Example</a>。</p>

<p>基本上，我会直接展示如何<em>使用</em>而不会解释语法。</p>

<p>所以，不多说，我们<a href="http://wenLiangcan.github.io/blog/2015/08/11/arcaders-1-01/">开始吧</a>。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[如何在 Python 中操作正则替换的匹配结果]]></title>
    <link href="http://wenLiangcan.github.io/blog/2014/08/02/processing-pattern-matches-while-performing-string-substitutions-in-python/"/>
    <updated>2014-08-02T21:39:00+08:00</updated>
    <id>http://wenLiangcan.github.io/blog/2014/08/02/processing-pattern-matches-while-performing-string-substitutions-in-python</id>
    <content type="html"><![CDATA[<p>在进行字符串的正则替换时，我们可能会希望替换的结果是基于匹配结果的，就是说把匹配的字符串提取出来进行一定的修改再应用回原文。</p>

<p>以 <code>sed</code> 为例：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">echo</span> <span class="s1">&#39;cat dog mouse&#39;</span> | sed <span class="s1">&#39;s/dog/\*&amp;\*/&#39;</span>
</span><span class='line'>cat *dog* mouse
</span></code></pre></td></tr></table></div></figure>


<p>用 <code>&amp;</code> 符号可以把匹配的字符串 <code>"dog"</code> 提取出来，然后在它的前后加上了 <code>*</code>。</p>

<p>在 <code>Python</code> 使用 <code>re</code> 模块时可以这么写：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">import</span> <span class="nn">re</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">repl</span><span class="p">(</span><span class="n">m</span><span class="p">):</span>
</span><span class='line'>    <span class="k">return</span> <span class="s">&#39;*&#39;</span> <span class="o">+</span> <span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">()</span> <span class="o">+</span> <span class="s">&#39;*&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="k">print</span><span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="s">&#39;dog&#39;</span><span class="p">,</span> <span class="n">repl</span><span class="p">,</span> <span class="s">&#39;cat dog mouse&#39;</span><span class="p">))</span>
</span><span class='line'>
</span><span class='line'><span class="c"># 输出：cat *dog* mouse</span>
</span></code></pre></td></tr></table></div></figure>


<p>当传给 <code>re.sub()</code> 方法的第二个参数是一个函数时，<code>re.sub()</code> 会给这个函数传入一个 <code>Match Object</code> 然后以这个函数的返回值作为替换结果。</p>

<p>我们可以通过这个 <code>Match Object</code> 的 <code>grou()</code> 方法获取每次执行替换前的匹配结果。这个方法之所以叫做 <code>group</code> ，是因为我们有时会使用多个匹配模板，同时获取多个（一组）匹配结果，再以 <code>sed</code> 为例：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">echo</span> <span class="s1">&#39;cat dog mouse&#39;</span> | sed <span class="s1">&#39;s/\(dog\) \(mouse\)/\*\1\* _\2_/&#39;</span>
</span><span class='line'>cat *dog* _mouse_
</span></code></pre></td></tr></table></div></figure>


<p>符号 <code>\1</code> 和 <code>\2</code> 对应于第一和第二个括号里我们要提取的字符串。</p>

<p>Python 则如下：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">import</span> <span class="nn">re</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">repl</span><span class="p">(</span><span class="n">m</span><span class="p">):</span>
</span><span class='line'>    <span class="k">return</span> <span class="s">&#39;*&#39;</span> <span class="o">+</span> <span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="s">&#39;*&#39;</span> <span class="o">+</span> \
</span><span class='line'>    <span class="s">&#39;_&#39;</span> <span class="o">+</span> <span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="s">&#39;_&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="k">print</span><span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="s">&#39;(dog) (mouse)&#39;</span><span class="p">,</span> <span class="n">repl</span><span class="p">,</span> <span class="s">&#39;cat dog mouse&#39;</span><span class="p">))</span>
</span><span class='line'>
</span><span class='line'><span class="c"># 输出：cat *dog* _mouse_</span>
</span></code></pre></td></tr></table></div></figure>


<p>上一例中的 <code>m.group()</code> 也可以写为 <code>m.goup(0)</code>，意为把所有结果作为一个字符串取出。</p>

<p>还有一种跟传统正则表达式比较相似的写法：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">import</span> <span class="nn">re</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">repl</span><span class="p">(</span><span class="n">m</span><span class="p">):</span>
</span><span class='line'>    <span class="k">return</span> <span class="s">&#39;*&#39;</span> <span class="o">+</span> <span class="n">m</span><span class="o">.</span><span class="n">expand</span><span class="p">(</span><span class="s">r&#39;\1&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="s">&#39;*&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="k">print</span><span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="s">&#39;(dog)&#39;</span><span class="p">,</span> <span class="n">repl</span><span class="p">,</span> <span class="s">&#39;cat dog mouse&#39;</span><span class="p">))</span>
</span></code></pre></td></tr></table></div></figure>


<p>用 <code>expand()</code> 方法展开表达式，不过似乎不支持符号 <code>&amp;</code>。</p>

<h2>参考资料</h2>

<ul>
<li><a href="https://docs.python.org/3.4/howto/regex.html">Regular Expression HOWTO</a></li>
<li><a href="https://stackoverflow.com/questions/9134964/regex-in-python-is-it-possible-to-get-the-match-replacement-and-final-string">Regex in python: is it possible to get the match, replacement, and final string?</a></li>
<li><em><a href="http://shop.oreilly.com/product/0636920027072.do">Python Cookbook (3rd Edition)</a></em>: <strong>2.6. Searching and Rplacing Case-Insensitive Text</strong></li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[去除全屏下 GVim 出现的白边]]></title>
    <link href="http://wenLiangcan.github.io/blog/2014/07/26/fix-gvim-empty-border-on-fullscreen/"/>
    <updated>2014-07-26T14:08:00+08:00</updated>
    <id>http://wenLiangcan.github.io/blog/2014/07/26/fix-gvim-empty-border-on-fullscreen</id>
    <content type="html"><![CDATA[<p>全屏下 GVim 的左侧和底部会出现白边，可以在 <code>~/.gtkrc-2.0</code> 文件中加入一下设置：</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>style "vimfix" {
</span><span class='line'>    bg[NORMAL] = "#002B36"
</span><span class='line'>}
</span><span class='line'>widget "vim-main-window.*GtkForm" style "vimfix"</span></code></pre></td></tr></table></div></figure>


<p> <br/>
<code>#002B36</code> 这个颜色对应于我使用的 <code>Solarized Dark</code> <code>Vim</code> 配色的背景色，可以根据个人情况修改。</p>

<h2>参考资料</h2>

<ul>
<li><a href="https://bbs.archlinux.org/viewtopic.php?pid=786106#p786106">howto fix gvim border width ?</a></li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[IPv6 到 IPv4 的代理]]></title>
    <link href="http://wenLiangcan.github.io/blog/2014/05/18/ipv6-to-ipv4-proxy/"/>
    <updated>2014-05-18T01:30:00+08:00</updated>
    <id>http://wenLiangcan.github.io/blog/2014/05/18/ipv6-to-ipv4-proxy</id>
    <content type="html"><![CDATA[<p>为了安装 <a href="http://johnmacfarlane.net/pandoc/">Pandoc</a> 添加了 <a href="https://wiki.archlinux.org/index.php/Unofficial_user_repositories#haskell-core">haskell-core</a> 这个仓库（<code>AUR</code> 里的包要自己编译太麻烦了），不过要用 Goagent 代理才能访问，本来以为是墙了。</p>

<p>可是问题来了，更新/安装一般的官方仓库的包时我是不希望通过代理的，所以会先注释掉 <code>pacman.conf</code> 里的 <code>haskell-core</code> 再 <code>pacman -Syu</code>，这样一来已安装的 <code>haskell</code> 包会引起依赖问题导致更新无法继续。</p>

<p>无意中想起用 <a href="http://cloudmonitor.ca.com/en/ping.php">http://cloudmonitor.ca.com/en/ping.php</a>（以前叫 just-ping.com）ping 一下这个仓库的地址（xsounds.org）看看，结果发现这货只支持通过 <code>IPv6</code> 访问！！！而我学校的网络只支持 <code>IPv4</code>。。。</p>

<p>Google 了一番后让我找到了 <a href="https://www.sixxs.net/tools/gateway/">SixXs</a> 这个服务，提供了 <code>IPv6</code> 到 <code>IPv4</code> 的代理，只要在想要访问的网址后加上 &#8220;.ipv4.sixxs.org&#8221; 这个后缀就可以了，就像这样：</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>xsounds.org.ipv4.sixxs.org/~haskell/core/$arch</span></code></pre></td></tr></table></div></figure>


<p>抱着尝试的心态添加到了 <code>pacman.conf</code> 里，结果真的可用！</p>

<p>ps: 通过这样的地址下载时就看不到进度条了，原因不明。 <br/>
pps: 其实 <code>SixXs</code> 也提供了 <code>IPv4</code> 到 <code>IPv6</code> 的代理服务的，把上面的后缀换成 &#8220;.sixxs.org&#8221; 或者 &#8220;.ipv6.sixxs.org&#8221; 就可以了。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[解决 Linux 下 KeePass 中文显示的问题]]></title>
    <link href="http://wenLiangcan.github.io/blog/2014/04/20/keepass-cjk-fonts-displaying/"/>
    <updated>2014-04-20T23:05:00+08:00</updated>
    <id>http://wenLiangcan.github.io/blog/2014/04/20/keepass-cjk-fonts-displaying</id>
    <content type="html"><![CDATA[<p>Linux 下用 KeePass 中文一直以来都显示为方块，准确的说是点开编辑条目的时候，外面的列表显示倒没有问题，弄得我一直不敢在 Linux 下编辑我的数据文件，每次想要添加新帐号都得开个虚拟机。。。</p>

<p>突然发现原来是 Local 设置的问题，因为我习惯使用英文作为系统语言，所以只要让 KeePass 使用中文 Local 运行就好了。比如 Arch 下安装的官方源里的包的话，在 <code>/usr/bin/keepass</code> 里加入：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nb">export </span><span class="nv">LANG</span><span class="o">=</span>zh_CN.utf8
</span></code></pre></td></tr></table></div></figure>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Linux 版锐捷客户端的 PKGBUILD]]></title>
    <link href="http://wenLiangcan.github.io/blog/2014/04/01/pkgbuild-for-rjsupplicant/"/>
    <updated>2014-04-01T19:58:00+08:00</updated>
    <id>http://wenLiangcan.github.io/blog/2014/04/01/pkgbuild-for-rjsupplicant</id>
    <content type="html"><![CDATA[<p>在愚人节的今天，学校全面强制使用 4.99 版本的锐捷客户端作为上网认证，之前一直在 Arch 下默默辛勤工作的 <a href="https://code.google.com/p/mentohust/">MentoHUST</a> 就这样挂掉了。。。</p>

<p>锐捷其实也有 Linux 版的，叫做 rjsupplicant，试了一下居然能用，不用离开 Linux 回到 Windows 算是万幸，不过不出所料的无法开多网卡建 WiFi 热点了，也只好如此。</p>

<p>自从学了一下下 PKGBUILD 怎么写，无论多小的程序或脚本，不用 <code>Pacman</code> 管理就不舒服，所以这次也打了个包，文件都在<a href="https://github.com/wenLiangcan/PKGBUILD/tree/master/rjsupplicant">这里</a>。</p>

<p>安装好后输入 <code>rjsupplicant --help</code> 查看帮助，我的认证格式如下：</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>sudo rjsupplicant -a1 -d0 -nenp2s0 -u&lt;用户名&gt; -p&lt;密码&gt;</span></code></pre></td></tr></table></div></figure>


<ul>
<li>-a:   1 的话表示有线连接，0 就是无线</li>
<li>-d:   1 使用 dhcp，0 不使用</li>
<li>-n:   网卡名</li>
</ul>


<p>退出可以按 <code>q</code>。</p>

<p>打包里还有个 <code>Systemd</code> 的 service 文件，从 <code>AUR</code> 上的 <a href="https://aur.archlinux.org/packages/mentohust-bin/">mentohust-bin</a> 里修改而来。安装好后如果要启用，先打开 <code>/usr/lib/systemd/system/rjsupplicant.service</code>，在<a href="https://github.com/wenLiangcan/PKGBUILD/blob/master/rjsupplicant/rjsupplicant.service#L10">第 10 行</a>添加上上述的认证参数，想在 <code>makepkg</code> 前添加的话请记得更新 <code>PKGBUILD</code> 里对应的 <code>md5sum</code> 值。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[zip 函数和 Dict Comprehension]]></title>
    <link href="http://wenLiangcan.github.io/blog/2013/12/14/zip-function-and-dict-comprehension-in-python/"/>
    <updated>2013-12-14T16:43:00+08:00</updated>
    <id>http://wenLiangcan.github.io/blog/2013/12/14/zip-function-and-dict-comprehension-in-python</id>
    <content type="html"><![CDATA[<p>要下载某个会反盗图的网站上的图片，想到了这篇 <a href="http://qixinglu.com/post/google_image_proxy.html">Google 的图片代理</a>。</p>

<p>通过 Google 来抓取想要的图片就可以逃过反盗图了，主要的工作就是为一系列原图的 url 生成特定的请求链接，所以要做的就是拼凑字符串，机械的任务当然交给机器去做了，<code>Python</code> 实现之。</p>

<p>虽然听起来挺简单，可是以我原有的知识实现起来还是有些繁琐。 需要处理的数据是存储在一个列表里的原图链接，最终想要获得的数据是一系列的文件名和与之一一对应的下载链接，第一反应当然是用字典组织它们了。 请求地址是从原链接拼凑生成的，文件名也是由原链接获得，使用 <code>os.path.basename()</code> 方法。</p>

<p>开始的想法是用两次 <code>List Comprehension</code>，遍历存储原链接的列表，获得两个分别含有文件名和下载地址的新列表，可是怎么把它们分别作为 <code>Key</code> 和 <code>Value</code> 合成为一个字典呢？我可不要循环操作下标。。。。Google 之，知道了 <code>zip</code> 函数，用法如下：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="o">&gt;&gt;&gt;</span> <span class="n">keys</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#39;a&#39;</span><span class="p">,</span> <span class="s">&#39;b&#39;</span><span class="p">,</span> <span class="s">&#39;c&#39;</span><span class="p">]</span>
</span><span class='line'><span class="o">&gt;&gt;&gt;</span> <span class="n">values</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span>
</span><span class='line'><span class="o">&gt;&gt;&gt;</span> <span class="n">dictionary</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="n">keys</span><span class="p">,</span> <span class="n">values</span><span class="p">))</span>
</span><span class='line'><span class="o">&gt;&gt;&gt;</span> <span class="k">print</span> <span class="n">dictionary</span>
</span><span class='line'><span class="p">{</span><span class="s">&#39;a&#39;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="s">&#39;b&#39;</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span> <span class="s">&#39;c&#39;</span><span class="p">:</span> <span class="mi">3</span><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p> <br/>
<code>zip()</code> 会返回一系列的元组，然后通过 <code>dct()</code> 生成一个字典。</p>

<p>可是两次遍历的都是同一个列表，难道就不能在同一次遍历中完成上面的任务吗 (&#8220;▔□▔)，好吧，原来还有 <a href="http://www.python.org/dev/peps/pep-0274/"><code>Dict Comprehension</code></a> 这个东西：</p>

<ul>
<li>如果需要遍历的 <code>sequence</code> 是一个列表，那么</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">d</span> <span class="o">=</span> <span class="p">{</span><span class="n">l</span> <span class="p">:</span> <span class="n">l</span> <span class="k">for</span> <span class="n">l</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<ul>
<li>如果 <code>sequence</code> 是一个字典</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">d</span> <span class="o">=</span> <span class="p">{</span><span class="n">key</span> <span class="p">:</span> <span class="n">value</span> <span class="k">for</span> <span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span> <span class="ow">in</span> <span class="n">dictionary</span><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<ul>
<li>另外，在 2.6 及以下的 <code>Python</code> 中，需要使用 <code>dict</code> 构造函数</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">d</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="o">...</span> <span class="k">for</span> <span class="o">...</span> <span class="ow">in</span> <span class="n">sequence</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p></p>

<p>再复习一下如何用 <code>for in</code> 迭代一个字典分别获取其中的键和值：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">d</span><span class="o">.</span><span class="n">iteritems</span><span class="p">():</span>
</span><span class='line'>    <span class="o">...</span>
</span></code></pre></td></tr></table></div></figure>


<p>在 <code>Python 3.x</code> 中使用的是 <code>items()</code>, <code>Python 2.x</code> 中也有这个方法，不过返回的是包含一对键、值的元组。</p>

<p>最后，贴一下代码：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="c">#!/usr/bin/python</span>
</span><span class='line'>
</span><span class='line'><span class="kn">import</span> <span class="nn">urllib2</span><span class="o">,</span> <span class="nn">sys</span><span class="o">,</span> <span class="nn">os</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">inputlinks</span><span class="p">():</span>
</span><span class='line'>    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
</span><span class='line'>        <span class="n">links</span> <span class="o">=</span> <span class="nb">raw_input</span><span class="p">(</span><span class="s">&quot;Enter links :</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
</span><span class='line'>    <span class="k">else</span><span class="p">:</span>
</span><span class='line'>        <span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s">&quot;-i&quot;</span><span class="p">:</span>
</span><span class='line'>            <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="s">&#39;r&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
</span><span class='line'>                <span class="n">links</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">read</span><span class="p">()</span><span class="o">.</span><span class="n">splitlines</span><span class="p">()</span>
</span><span class='line'>        <span class="k">else</span><span class="p">:</span>
</span><span class='line'>            <span class="n">links</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span>
</span><span class='line'>    <span class="k">return</span> <span class="n">links</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">generate</span><span class="p">(</span><span class="n">links</span><span class="p">):</span>
</span><span class='line'>    <span class="n">prefix</span> <span class="o">=</span> <span class="s">r&quot;https://images2-focus-opensocial.googleusercontent.com/gadgets/proxy?url=&quot;</span>
</span><span class='line'>    <span class="n">suffix</span> <span class="o">=</span> <span class="s">r&quot;&amp;container=focus&amp;gadget=a&amp;no_expand=1&amp;resize_h=0&amp;rewriteMime=image</span><span class="si">%2F</span><span class="s">*&quot;</span>
</span><span class='line'>    <span class="n">images</span> <span class="o">=</span> <span class="p">{</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">basename</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="p">:</span> <span class="n">prefix</span> <span class="o">+</span> <span class="n">i</span> <span class="o">+</span> <span class="n">suffix</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">links</span><span class="p">}</span>
</span><span class='line'>    <span class="k">return</span> <span class="n">images</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">download</span><span class="p">(</span><span class="n">images</span><span class="p">):</span>
</span><span class='line'>    <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">image</span> <span class="ow">in</span> <span class="n">images</span><span class="o">.</span><span class="n">iteritems</span><span class="p">():</span>
</span><span class='line'>        <span class="k">try</span><span class="p">:</span>
</span><span class='line'>            <span class="n">imgdata</span> <span class="o">=</span> <span class="n">urllib2</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">image</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
</span><span class='line'>            <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="s">&#39;wb&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">output</span><span class="p">:</span>
</span><span class='line'>                <span class="n">output</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">imgdata</span><span class="p">)</span>
</span><span class='line'>        <span class="k">except</span><span class="p">:</span>
</span><span class='line'>            <span class="k">print</span> <span class="s">&quot;Er...&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&quot;__main__&quot;</span><span class="p">:</span>
</span><span class='line'>    <span class="n">download</span><span class="p">(</span><span class="n">generate</span><span class="p">(</span><span class="n">inputlinks</span><span class="p">()))</span>
</span></code></pre></td></tr></table></div></figure>


<h2>参考资料</h2>

<ul>
<li><a href="http://stackoverflow.com/a/4028894/1436873">How do I download a zip file in python using urllib2?</a></li>
<li><a href="http://www.cnblogs.com/cacique/archive/2012/08/02/2617440.html">Python文件读写</a></li>
<li><a href="http://stackoverflow.com/a/209854/1436873">Map two lists into a dictionary in Python</a></li>
<li><a href="http://stackoverflow.com/a/1747827/1436873">Python: create a dictionary with list comprehension</a></li>
<li><a href="http://www.python.org/dev/peps/pep-0274/">PEP 274 &#8211; Dict Comprehensions</a></li>
<li><a href="http://stackoverflow.com/a/3294899/1436873">Iterating over Dictionaries…For Loops in Python</a></li>
<li><a href="http://qixinglu.com/post/google_image_proxy.html">Google 的图片代理</a></li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Nexus 7 升级 4.4 KitKat 后重新提权]]></title>
    <link href="http://wenLiangcan.github.io/blog/2013/11/27/recover-root-permission-on-nexus-7-kitkat/"/>
    <updated>2013-11-27T14:33:00+08:00</updated>
    <id>http://wenLiangcan.github.io/blog/2013/11/27/recover-root-permission-on-nexus-7-kitkat</id>
    <content type="html"><![CDATA[<p>今天我的 N7 二代终于收到 OTA 了，升级后又要重新获取 Root 权限，之前这些工作一直用 Windows 下的 <a href="http://www.wugfresh.com/nrt/%E2%80%8E">Nexus Root Toolkit</a> 完成，现在尝试在 Linux 下解决。</p>

<p>之所以升级后 Root 权限没了，是因为 su 文件被移除了，所以现在只需要重刷一次 <a href="http://forum.xda-developers.com/showthread.php?t=1538053">SuperSU</a> 的升级包。刷升级包需要第三方 Recovery，之前 Root 机子时并没有把它直接刷进机器里，而是采用临时启动的方式，现在也用这个方法。</p>

<ul>
<li>先要确保电脑上有 adb 和 fastboot， Arch 下可以安装 aur 上的 <a href="https://aur.archlinux.org/packages/android-sdk-platform-tools/">android-sdk-platform-tools</a> 包。</li>
<li>然后下载 SuperSU 的<a href="http://download.chainfire.eu/supersu">升级包</a> 和 <a href="http://techerrata.com/browse/twrp2/flo">TWRP</a>。</li>
<li>通过 USB 数据线连接设备到电脑。</li>
<li>把 SuperSU 升级包直接复制到 N7 上，选一个方便找到的路径。</li>
<li>打开终端，cd 到 Recovery 镜像所在的目录。</li>
<li>使用 adb 重启到 BootLoader：</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span>adb reboot-bootloader
</span></code></pre></td></tr></table></div></figure>


<p></p>

<ul>
<li>出现 BootLoader 介面后先看看设备能否被识别：</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span>fastboot devices
</span></code></pre></td></tr></table></div></figure>


<p></p>

<ul>
<li>没问题的话就可以启动镜像了：</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span>fastboot boot ./openrecovery-twrp-2.6.3.1-flo.img
</span></code></pre></td></tr></table></div></figure>


<p></p>

<ul>
<li>成功进入 TWRP 后点 Install，选择 SuperSU 升级包，刷之。返回主介面，Reboot -> System，OK !</li>
</ul>


<p>ps : <br/>
之前之所以不刷入 Recovery，是因为那时的 TWRP 还不支持 N7 二代的分辨率，整个介面缩在了一边，所以其实是刷过一次觉得很难看又删掉了 ╮(￣▽￣&#8221;)╭ 。这次倒是发现已经支持了，不过不想刷了，觉得没必要，想要尽量保持机子的纯净。</p>

<p>刚刚才知道，原来 SuperSU 设置里有一个 叫 Survival mode 的功能，就是用来防止系统 OTA 更新后权限丢失的。不过不能保证百分百有效而且是付费版才能用，我倒是装了个网上找的 key，这次把它勾上，期待下次更新，看有没有效 o((≧▽≦o)</p>

<p>2013-12-12 update: 更新到 4.4.2，Survival mode 生效了^_^)y</p>

<h2>参考资料</h2>

<p>一个<a href="http://kuai.xunlei.com/d/rMTXArBp8JmbUQQA5c0">刷机包</a>里的批处理文件，来自<a href="http://blog.sina.com.cn/s/blog_0058222c0101cddg.html">a860官方和临时Recovery互刷工具</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Linux 下浏览器里使用退格键返回上一页]]></title>
    <link href="http://wenLiangcan.github.io/blog/2013/11/26/press-backspace-key-to-go-back-browser-history-on-linux/"/>
    <updated>2013-11-26T20:44:00+08:00</updated>
    <id>http://wenLiangcan.github.io/blog/2013/11/26/press-backspace-key-to-go-back-browser-history-on-linux</id>
    <content type="html"><![CDATA[<p>这里只针对 Firefox 和 Chrome，Linux 下它们默认都不能用退格键作为返回历史上一页的快捷键，Opera 倒是可以。</p>

<p><strong><em>Firefox</em></strong> : <br/>
在 about:config 里查找到 &#8220;browser.backspace_action&#8221;  这一项，把它的值设置为 0 就可以了。1 代表向上滚动页面（此时要向下滚动的话可以按 Shift 加退格键），我的 fx 默认被设为了 2，按退格键没任何反应。</p>

<p><strong><em>Chrome</em></strong> : <br/>
需要安装一个扩展，叫做 <a href="https://chrome.google.com/webstore/detail/aeffggjddcchloadflonilaahpclmbnm">Backspace As Back/Forward for Linux</a>。安装后在它的设置页勾选 &#8220;Activate Backspace for navigation in history object&#8221; 这一项，里面还可以设置例外，对某些网页不启用这一功能。</p>

<h2>参考资料</h2>

<ul>
<li><a href="http://lifehacker.com/269945/set-backspaces-firefox-behavior">Set Backspace&#8217;s Firefox behavior</a></li>
<li><a href="http://forum.ubuntu.com.cn/viewtopic.php?f=48&amp;t=349227">解决浏览器[←Backspace]键失灵的方法</a></li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[[Python] 校园网网页验证登录脚本]]></title>
    <link href="http://wenLiangcan.github.io/blog/2013/11/24/school-network-auto-login-by-python/"/>
    <updated>2013-11-24T11:14:00+08:00</updated>
    <id>http://wenLiangcan.github.io/blog/2013/11/24/school-network-auto-login-by-python</id>
    <content type="html"><![CDATA[<p>依旧毫无技术含量 =。=，走了很多弯路，很多原理也没深入学习，不过还是记录一下吧。。。</p>

<p>学校的校园网可谓关卡重重，先要锐捷验证一次，然后还要在网页端登录一次，如果一段时间没有网络活动的话又会自动下线（挂 Q 也会）。</p>

<p>之前写过一个自动填写验证码的<a href="http://wenLiangcan.github.io/blog/2013/06/30/iframe-dom/">小书签</a>,后来改成了油猴脚本，让浏览器记住帐号和密码后打开浏览器就能自动登录了。</p>

<p>可是能不能把这一步也省了，开机登录桌面就能直接上网呢？ 因为有一些开机启动的程序是需要网络的。比如 <a href="http://www.go-docky.com/">Docky</a> 的天气插件，获取不到数据就会变成一个问号难看死了（主要因为强迫症，每次网页登录后都要手动点击一下 Check Weather 把那个问号变回天气图标，虽然它会定期自动检查。。。），还有就是 Dropbox，因为这个原因我一直都没设置开机启动。</p>

<p>所以就想看看能不能用 <code>Python</code> 来实现这个功能了。</p>

<p>因为对这一切都毫无概念，所以一开始只能用固有的思维方式考虑问题： 不通过浏览器，就是要用其它语言实现填写文本框然后按确认？或者通过其它语言间接调用 <code>Javascript</code> ？ 导致在这个上面绕了好久，看了半天 <a href="http://code.google.com/p/pyv8/"><code>Pyv8</code></a>, <a href="http://code.google.com/p/python-spidermonkey/"><code>Python-Spidermonkey</code></a> 什么的也没弄懂怎么回事 T^T</p>

<p>其实填写文本框然后按确认按钮的过程就是填写一个表单（<code>&lt;form&gt;</code>），然后浏览器把表单中的数据提交到相应服务器的过程。而 <code>Python</code> 或者其它的一些语言都已经有相应的库提供 post/submit 网页表单数据的方法了。所以现在需要做的就是找出 提交数据的地址 和 需要提交的数据项，然后使用对应的方法提交数据。</p>

<p>提交数据的地址可以由 网页文件中 <code>&lt;form&gt;</code> 标签的 <code>action</code> 属性找到。</p>

<ul>
<li>校园网的验证页面地址格式为：<code>http://address/login.jsp?wlanuserip=xxx.xx.xxx.xx&amp;wlanacip=xxx.xxx.xx.xx</code></li>
<li><code>action</code> 的值为：&#8221;/login.do&#8221;</li>
<li>所以提交地址就是：<code>http://address/login.do</code></li>
</ul>


<p>提交的数据就是 <code>&lt;form&gt;</code> 里的 文本框的输入值，有 5 个。两个属性 <code>type</code> 为 &#8220;hidden&#8221; 的 <code>&lt;input&gt;</code> 标签，叫做 eduuser 和 edubas，它门的值分别对应验证页面地址中的 wlanuserip 和 wlanacip 的值，前一个是我的内网 ip 地址，后一个没搞明白是啥。</p>

<p>另外 3 个是 userName1，password1，rand，就是用户名，密码，和验证码。 其中验证码在写小书签时已经知道，它的生成方法其实是由在浏览器中的 <code>Javascript</code> 产生一个四位数字，然后向服务器请求一张相应数值的图片。</p>

<p>小书签里使用 js 获取执行结果，不过现在我要直接 post 数据并不解释网页。既然那个四位数是客户端脚本所产生的，就是说并不由服务端所控制，所以现在我可以伪造这个事实，直接由我向服务器请求一张图片，而且那个数值也不用随机生成，找一个任意确定的四位数就可以了。请求的方式是访问这样一个格式的地址：<code>http://address/common/image.jsp?rand=xxxx</code></p>

<p>其实到这里我原本的想法是，服务器应该会把对验证页面地址和验证码图片地址的访问作为同一个 session，就是服务器会记录下你请求了的图片的验证码数值，在提交表单时里面的 rand 项的值必须与之相符才能通过验证（关于 session 什么的我不太知道是不是该这么表达）。 可事实是，那个验证码图片的请求不是必须的，就是说我可以直接随便提交一个四位数作为 rand 的值也能通过验证！！！ 这个页面的验证码的部分除了那张图片，全都是由客户端 js 来完成的 Σ(っ  °Д °;)っ</p>

<p>整个脚本所做的事情就是，提交一个包含验证信息的表单。</p>

<figure class='code'><figcaption><span>autologin.py</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="c">#!/usr/bin/env python</span>
</span><span class='line'>
</span><span class='line'><span class="kn">import</span> <span class="nn">requests</span><span class="o">,</span> <span class="nn">time</span>
</span><span class='line'>
</span><span class='line'><span class="n">url</span> <span class="o">=</span> <span class="s">&quot;http://address/login.do&quot;</span>
</span><span class='line'><span class="n">info</span> <span class="o">=</span> <span class="p">{</span><span class="s">&#39;userName1&#39;</span><span class="p">:</span> <span class="s">&#39;...&#39;</span><span class="p">,</span>
</span><span class='line'>        <span class="s">&#39;password1&#39;</span><span class="p">:</span> <span class="s">&#39;...&#39;</span><span class="p">,</span>
</span><span class='line'>        <span class="s">&#39;rand&#39;</span><span class="p">:</span> <span class="s">&#39;2222&#39;</span><span class="p">,</span>
</span><span class='line'>        <span class="s">&#39;eduuser&#39;</span><span class="p">:</span> <span class="s">&#39;...&#39;</span><span class="p">,</span>
</span><span class='line'>        <span class="s">&#39;edubas&#39;</span><span class="p">:</span> <span class="s">&#39;...&#39;</span>
</span><span class='line'>       <span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
</span><span class='line'>    <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="n">info</span><span class="p">)</span>
</span><span class='line'>    <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">65</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>这里用了 <a href="http://docs.python-requests.org/en/latest/"><code>requests</code></a> 这个模块，设置每 65 秒验证一次防止自动下线（表问我为神马是 65 而不是 60）。</p>

<p>ps:</p>

<p>过程中还找到了 Firefox 的一个扩展 <a href="https://addons.mozilla.org/En-us/firefox/addon/httpfox/">HttpFox</a>，可以用来分析 HTTP 网络活动，下面是一张从访问验证页面到提交信息的记录截图： <br/>
<img src="https://dl.dropboxusercontent.com/s/47sr6ye8bu1vuxs/http.png?dl=1&amp;token_hash=AAHk_E3lc7x88hOB6t0fMSLdXRf7z5otjfQN-rbNTDahIw" alt="http" /> <br/>
通过它才发现我原本还遗漏了 eduuser 和 edubas 两个数据项。</p>

<p>另外，点击下面的 &#8220;raw&#8221;，可以看到还能通过把数据嵌入到 url 地址的方式提交表单： <br/>
<img src="https://dl.dropboxusercontent.com/s/uuhxpexkwq5bf3f/raw.png?dl=1&amp;token_hash=AAHdusJ29VHNtLIInwRFziMi6vuNlFwEkM6efKlGepcUew" alt="raw" /> <br/>
url 的格式为： <code>http://address/login.do?userName1=xxx&amp;password1=xxx&amp;rand=xxxx&amp;eduuser=xxx&amp;edubas=xxx</code></p>

<p>pps:</p>

<p>接下来打算把我的树莓派设置成路由器，用这个脚本进行验证（话说买回来没多久就闲置了 -________-&#8221;</p>

<p>还有不知要不要写成 Daemon 的形式？或者学一下写个 Systemd 的 Service 来运行？现在暂时用 Openbox 来自动执行。</p>

<p>不过还都是打算，我的拖延症又犯了。。。</p>

<h2>参考资料</h2>

<ul>
<li><a href="http://www.averainy.info/how-to-use-python-submit-a-web-form/">如何用python提交一个web表单</a></li>
<li><a href="http://docs.python-requests.org/en/latest/user/quickstart/">Requests Quickstart</a></li>
<li><a href="http://www.w3schools.com/tags/tag_form.asp">HTML &lt; form> Tag</a></li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Arch Linux 下搭建 MonoGame 开发环境]]></title>
    <link href="http://wenLiangcan.github.io/blog/2013/11/22/monogame-development-on-archlinux/"/>
    <updated>2013-11-22T15:11:00+08:00</updated>
    <id>http://wenLiangcan.github.io/blog/2013/11/22/monogame-development-on-archlinux</id>
    <content type="html"><![CDATA[<h4>其实就是安装几个包而已：</h4>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span>yaourt -S monodevelop-git monogame monodevelop-monogame-addin-git
</span></code></pre></td></tr></table></div></figure>


<p>第一个是 IDE，<code>Extra</code> 仓库里的更新太慢了，还停留在 <code>4.0.13</code>，<code>MonoDevelop</code> 的稳定版现在是 <code>4.2.1</code>。</p>

<p>最后那个是 <code>MonoDevelop</code> 的 <code>MonoGame</code> 插件，有了它才能在 <code>MonoDevelop</code> 里创建 <code>MonoGame</code> 的解决方案。话说这个当初把我给搞蒙了，看<a href="https://github.com/mono/MonoGame/wiki/Tutorials%3AGetting-Started-Guide-Linux">教程</a>以为直接安装好 <code>MonoGame</code> 就可以了，看了 <a href="https://aur.archlinux.org/packages/monogame/"><code>aur</code></a> 里的评论才知道这么个东西。觉得维护者应该把它加到可选依赖里。</p>

<h4>现在试着创建一个 Solution：</h4>

<ul>
<li>在菜单栏选择 File -> New -> Solution</li>
<li><p>接着选择 C# -> MonoGame -> MonoGame Linux Application <br/>
<img src="https://dl.dropboxusercontent.com/s/rw8l51u6es27pwi/new_solution.png?dl=1&amp;token_hash=AAGKLEegUiW1nYqUbM67-AX-ZorFtbwGqsFLOQb3U2efNg" alt="" /></p></li>
<li><p>命名并保存 <br/>
<img src="https://dl.dropboxusercontent.com/s/8mkdatzfftk49pw/monogame_sln.png?dl=1&amp;token_hash=AAFMSNjCaOBtuzZPYxjAW-_N_tSRdJ8V1gsLYn_0r1ARFw" alt="" /><br/>
(编辑器的配色可以在 Edit -> Preferences -> Text Editor -> Syntax Highlighting 里设置)</p></li>
<li><p>在编译运行应用前可以把第 23 行的 <code>graphics.IsFullScreen</code> 设为 <code>false</code>，全屏运行的话会带来一些不便。 <br/>
<img src="https://dl.dropboxusercontent.com/s/l9ic9t3pwq8jifx/code.png?dl=1&amp;token_hash=AAGdbz1QdMFfZq232ndgEoiIzVujxXJDqRYi3q6r_VnKTg" alt="" /></p></li>
<li><p>按 F5 或 选择菜单 Run -> Start Debugging 启动程序 <br/>
<img src="https://dl.dropboxusercontent.com/s/rbk8w0vmc5c3upb/app.png?dl=1&amp;token_hash=AAGgKRA-3BdwOy2kQNBjvhP8f7w0DpNPzEU9PbwSSJ8jfg" alt="" /> <br/>
不太有趣 _(:3」∠)_</p></li>
</ul>


<h4>为了体验最新的特性，还可以通过 <code>MonoDevelop</code> 的 <code>VersionControl</code> 插件下载最新的 <code>MonoGame</code> 代码用来创建应用：</h4>

<p>详见：<a href="https://github.com/mono/MonoGame/wiki/Tutorials%3AGetting-Started-Guide-Linux#wiki-Getting_and_Building_the_Latest_Sources_develop3d">Getting and Building the Latest Sources (develop3d)</a> 和 <a href="https://github.com/mono/MonoGame/wiki/Tutorials%3AGetting-Started-Guide-Linux#wiki-Creating_a_MonoGame_Application_develop3d_version">Creating a MonoGame Application (develop3d version)</a></p>

<h2>参考资料</h2>

<ul>
<li><a href="https://github.com/mono/MonoGame/wiki/Tutorials%3AGetting-Started-Guide-Linux">Tutorials:Getting Started Guide Linux</a></li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Arch Linux 下自动挂载 MTP]]></title>
    <link href="http://wenLiangcan.github.io/blog/2013/10/19/archlinux-automount-mtp/"/>
    <updated>2013-10-19T20:01:00+08:00</updated>
    <id>http://wenLiangcan.github.io/blog/2013/10/19/archlinux-automount-mtp</id>
    <content type="html"><![CDATA[<p>买了台 N7 二代，发现不支持 USB 大容量存储模式连接电脑（听说 Android 3 开始就不再支持 USB Mass Storage 协议了，不过 Defy 上刷的 CM 10 倒是可以支持，现在看来应该是第三方添加的功能了），只能以 <a href="http://en.wikipedia.org/wiki/Media_Transfer_Protocol">MTP</a> 或 <a href="http://en.wikipedia.org/wiki/Picture_Transfer_Protocol">PTP</a> 的方式连接，导致 Arch 下一直无法自动挂载只能用 Airdroid 传文件，可是用脚本生成的 Wi-Fi 会时不时的断线，传大文件时就杯具了 QAQ</p>

<p>终于让我找到了这个 <a href="https://github.com/fxthomas/android-automount">PKGBUILD 包</a>，<a href="https://github.com/fxthomas/android-automount/archive/master.zip">下载</a>下来后需要先修改一下 <code>PKGBUILD</code> 和 <code>99-android-mtp.rules</code> 这两个文件。</p>

<h3>一、</h3>

<p>首先是为你使用的设备添加相应的挂载规则。（默认的挂载规则已经加入了对 Nexus 7 一代，Galaxy Nexus 和 HP Touchpad 32GB 的支持，如果你使用的是这些设备可以跳过这一步。）</p>

<p>通过 USB 线把设备连接到电脑，在终端里输入命令：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span>udevadm monitor --environment --udev
</span></code></pre></td></tr></table></div></figure>


<p>然后拔出设备，就可以看到类似下面的信息：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>monitor will print the received events <span class="k">for</span>:
</span><span class='line'>UDEV - the event which udev sends out after rule processing
</span><span class='line'>
</span><span class='line'>UDEV  <span class="o">[</span>39055.590819<span class="o">]</span> remove   /devices/pci0000:00/0000:00:12.2/usb1/1-1/1-1:1.0 <span class="o">(</span>usb<span class="o">)</span>
</span><span class='line'><span class="nv">ACTION</span><span class="o">=</span>remove
</span><span class='line'><span class="nv">DEVPATH</span><span class="o">=</span>/devices/pci0000:00/0000:00:12.2/usb1/1-1/1-1:1.0
</span><span class='line'><span class="nv">DEVTYPE</span><span class="o">=</span>usb_interface
</span><span class='line'><span class="nv">ID_MODEL_FROM_DATABASE</span><span class="o">=</span>Nexus 4 <span class="o">(</span>debug<span class="o">)</span>
</span><span class='line'><span class="nv">ID_VENDOR_FROM_DATABASE</span><span class="o">=</span>Google Inc.
</span><span class='line'><span class="nv">INTERFACE</span><span class="o">=</span>255/255/0
</span><span class='line'><span class="nv">MODALIAS</span><span class="o">=</span>usb:v18D1p4EE2d0228dc00dsc00dp00icFFiscFFip00in00
</span><span class='line'><span class="nv">PRODUCT</span><span class="o">=</span>18d1/4ee2/228
</span><span class='line'><span class="nv">SEQNUM</span><span class="o">=</span>1985
</span><span class='line'><span class="nv">SUBSYSTEM</span><span class="o">=</span>usb
</span><span class='line'><span class="nv">TYPE</span><span class="o">=</span>0/0/0
</span><span class='line'><span class="nv">USEC_INITIALIZED</span><span class="o">=</span>662109
</span><span class='line'>
</span><span class='line'>UDEV  <span class="o">[</span>39055.592153<span class="o">]</span> remove   /devices/pci0000:00/0000:00:12.2/usb1/1-1/1-1:1.1 <span class="o">(</span>usb<span class="o">)</span>
</span><span class='line'><span class="nv">ACTION</span><span class="o">=</span>remove
</span><span class='line'><span class="nv">DEVPATH</span><span class="o">=</span>/devices/pci0000:00/0000:00:12.2/usb1/1-1/1-1:1.1
</span><span class='line'><span class="nv">DEVTYPE</span><span class="o">=</span>usb_interface
</span><span class='line'><span class="nv">ID_MODEL_FROM_DATABASE</span><span class="o">=</span>Nexus 4 <span class="o">(</span>debug<span class="o">)</span>
</span><span class='line'><span class="nv">ID_VENDOR_FROM_DATABASE</span><span class="o">=</span>Google Inc.
</span><span class='line'><span class="nv">INTERFACE</span><span class="o">=</span>255/66/1
</span><span class='line'><span class="nv">MODALIAS</span><span class="o">=</span>usb:v18D1p4EE2d0228dc00dsc00dp00icFFisc42ip01in01
</span><span class='line'><span class="nv">PRODUCT</span><span class="o">=</span>18d1/4ee2/228
</span><span class='line'><span class="nv">SEQNUM</span><span class="o">=</span>1986
</span><span class='line'><span class="nv">SUBSYSTEM</span><span class="o">=</span>usb
</span><span class='line'><span class="nv">TYPE</span><span class="o">=</span>0/0/0
</span><span class='line'><span class="nv">USEC_INITIALIZED</span><span class="o">=</span>48662167
</span><span class='line'>
</span><span class='line'>UDEV  <span class="o">[</span>39055.661296<span class="o">]</span> remove   /devices/virtual/bdi/0:41 <span class="o">(</span>bdi<span class="o">)</span>
</span><span class='line'><span class="nv">ACTION</span><span class="o">=</span>remove
</span><span class='line'><span class="nv">DEVPATH</span><span class="o">=</span>/devices/virtual/bdi/0:41
</span><span class='line'><span class="nv">SEQNUM</span><span class="o">=</span>1988
</span><span class='line'><span class="nv">SUBSYSTEM</span><span class="o">=</span>bdi
</span><span class='line'><span class="nv">USEC_INITIALIZED</span><span class="o">=</span>660985
</span><span class='line'>
</span><span class='line'>UDEV  <span class="o">[</span>39055.667918<span class="o">]</span> remove   /devices/pci0000:00/0000:00:12.2/usb1/1-1 <span class="o">(</span>usb<span class="o">)</span>
</span><span class='line'><span class="nv">ACTION</span><span class="o">=</span>remove
</span><span class='line'><span class="nv">BUSNUM</span><span class="o">=</span>001
</span><span class='line'><span class="nv">DEVLINKS</span><span class="o">=</span>/dev/libmtp-1-1
</span><span class='line'><span class="nv">DEVNAME</span><span class="o">=</span>/dev/bus/usb/001/016
</span><span class='line'><span class="nv">DEVNUM</span><span class="o">=</span>016
</span><span class='line'><span class="nv">DEVPATH</span><span class="o">=</span>/devices/pci0000:00/0000:00:12.2/usb1/1-1
</span><span class='line'><span class="nv">DEVTYPE</span><span class="o">=</span>usb_device
</span><span class='line'><span class="nv">ID_BUS</span><span class="o">=</span>usb
</span><span class='line'><span class="nv">ID_FOR_SEAT</span><span class="o">=</span>usb-pci-0000_00_12_2-usb-0_1
</span><span class='line'><span class="nv">ID_MEDIA_PLAYER</span><span class="o">=</span>1
</span><span class='line'><span class="nv">ID_MODEL</span><span class="o">=</span>Nexus_7
</span><span class='line'><span class="nv">ID_MODEL_ENC</span><span class="o">=</span>Nexus<span class="se">\x</span>207
</span><span class='line'><span class="nv">ID_MODEL_FROM_DATABASE</span><span class="o">=</span>Nexus 4 <span class="o">(</span>debug<span class="o">)</span>
</span><span class='line'><span class="nv">ID_MODEL_ID</span><span class="o">=</span>4ee2
</span><span class='line'><span class="nv">ID_MTP_DEVICE</span><span class="o">=</span>1
</span><span class='line'><span class="nv">ID_PATH</span><span class="o">=</span>pci-0000:00:12.2-usb-0:1
</span><span class='line'><span class="nv">ID_PATH_TAG</span><span class="o">=</span>pci-0000_00_12_2-usb-0_1
</span><span class='line'><span class="nv">ID_REVISION</span><span class="o">=</span>0228
</span><span class='line'><span class="nv">ID_SERIAL</span><span class="o">=</span>asus_Nexus_7_06e9d04d
</span><span class='line'><span class="nv">ID_SERIAL_SHORT</span><span class="o">=</span>06e9d04d
</span><span class='line'><span class="nv">ID_USB_INTERFACES</span><span class="o">=</span>:ffff00:ff4201:
</span><span class='line'><span class="nv">ID_VENDOR</span><span class="o">=</span>asus
</span><span class='line'><span class="nv">ID_VENDOR_ENC</span><span class="o">=</span>asus
</span><span class='line'><span class="nv">ID_VENDOR_FROM_DATABASE</span><span class="o">=</span>Google Inc.
</span><span class='line'><span class="nv">ID_VENDOR_ID</span><span class="o">=</span>18d1
</span><span class='line'><span class="nv">MAJOR</span><span class="o">=</span>189
</span><span class='line'><span class="nv">MINOR</span><span class="o">=</span>15
</span><span class='line'><span class="nv">PRODUCT</span><span class="o">=</span>18d1/4ee2/228
</span><span class='line'><span class="nv">SEQNUM</span><span class="o">=</span>1987
</span><span class='line'><span class="nv">SUBSYSTEM</span><span class="o">=</span>usb
</span><span class='line'><span class="nv">TAGS</span><span class="o">=</span>:seat:uaccess:
</span><span class='line'><span class="nv">TYPE</span><span class="o">=</span>0/0/0
</span><span class='line'><span class="nv">USEC_INITIALIZED</span><span class="o">=</span>48644741
</span></code></pre></td></tr></table></div></figure>


<p>我们需要的是 <code>ID_MODEL_ID</code> 和 <code>ID_VENDOR_ID</code> 这两项等于号后面的字符串。</p>

<p>接下来编辑 <code>99-android-mtp.rules</code> 文件，仿照已有的规则和上面得到的信息添加相应的条目，比如我的是 Nexus 7 二代：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="c"># Google Nexus 7 (Wi-Fi, 2013 version) 32GB MTP mode</span>
</span><span class='line'><span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">&quot;usb&quot;</span>, ATTR<span class="o">{</span>idVendor<span class="o">}==</span><span class="s2">&quot;18d1&quot;</span>, ATTR<span class="o">{</span>idProduct<span class="o">}==</span><span class="s2">&quot;4ee1&quot;</span>, <span class="nv">MODE</span><span class="o">=</span><span class="s2">&quot;0666&quot;</span> <span class="c"># MTP media</span>
</span><span class='line'><span class="nv">SUBSYSTEM</span><span class="o">==</span><span class="s2">&quot;usb&quot;</span>, ATTR<span class="o">{</span>idVendor<span class="o">}==</span><span class="s2">&quot;18d1&quot;</span>, ATTR<span class="o">{</span>idProduct<span class="o">}==</span><span class="s2">&quot;4ee2&quot;</span>, <span class="nv">MODE</span><span class="o">=</span><span class="s2">&quot;0666&quot;</span> <span class="c"># MTP media with USB debug on</span>
</span><span class='line'>
</span><span class='line'><span class="c">###################################</span>
</span><span class='line'><span class="c"># Android devices, when unplugged #</span>
</span><span class='line'><span class="c">###################################</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Nexus 7 2013</span>
</span><span class='line'>ENV<span class="o">{</span>ID_MODEL_ID<span class="o">}==</span><span class="s2">&quot;4ee1&quot;</span>, ENV<span class="o">{</span>ID_VENDOR_ID<span class="o">}==</span><span class="s2">&quot;18d1&quot;</span>, <span class="nv">ACTION</span><span class="o">==</span><span class="s2">&quot;remove&quot;</span>, RUN+<span class="o">=</span><span class="s2">&quot;/usr/bin/systemctl stop &#39;android-mtp@$env{ID_MODEL}.service&#39;&quot;</span>
</span><span class='line'>ENV<span class="o">{</span>ID_MODEL_ID<span class="o">}==</span><span class="s2">&quot;4ee2&quot;</span>, ENV<span class="o">{</span>ID_VENDOR_ID<span class="o">}==</span><span class="s2">&quot;18d1&quot;</span>, <span class="nv">ACTION</span><span class="o">==</span><span class="s2">&quot;remove&quot;</span>, RUN+<span class="o">=</span><span class="s2">&quot;/usr/bin/systemctl stop &#39;android-mtp@$env{ID_MODEL}.service&#39;&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="c">####################################</span>
</span><span class='line'><span class="c"># Android devices, when plugged-in #</span>
</span><span class='line'><span class="c">####################################</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Nexus 7 2013</span>
</span><span class='line'>ENV<span class="o">{</span>ID_MODEL_ID<span class="o">}==</span><span class="s2">&quot;4ee1&quot;</span>, ENV<span class="o">{</span>ID_VENDOR_ID<span class="o">}==</span><span class="s2">&quot;18d1&quot;</span>, <span class="nv">ACTION</span><span class="o">==</span><span class="s2">&quot;add&quot;</span>, RUN+<span class="o">=</span><span class="s2">&quot;/usr/bin/systemctl start &#39;android-mtp@$env{ID_MODEL}.service&#39;&quot;</span>
</span><span class='line'>ENV<span class="o">{</span>ID_MODEL_ID<span class="o">}==</span><span class="s2">&quot;4ee2&quot;</span>, ENV<span class="o">{</span>ID_VENDOR_ID<span class="o">}==</span><span class="s2">&quot;18d1&quot;</span>, <span class="nv">ACTION</span><span class="o">==</span><span class="s2">&quot;add&quot;</span>, RUN+<span class="o">=</span><span class="s2">&quot;/usr/bin/systemctl start &#39;android-mtp@$env{ID_MODEL}.service&#39;&quot;</span>
</span></code></pre></td></tr></table></div></figure>


<p>这里包含了纯 MTP 模式 和 MTP，USB debug 模式同时打开时的规则，可以在手机切换到对应的模式通过上一步骤得到相关数据。  <br/>
其中，第一部分里的 <code>ATTR{idVendor}</code> 对应 <code>ID_VENDOR_ID</code>，<code>ATTR{idProduct}</code> 对应 <code>ID_MODEL_ID</code>。</p>

<p><code>ID_MODEL_ID</code> 除了这两种情况，在 PTP 模式，PTP 和 USB debug 模式，Bootloader 模式 还有 Recovery 模式都会有对应的数值，不过我尝试添加了 PTP 模式的规则后没能成功挂载，只好作罢。</p>

<h3>二、</h3>

<p>然后需要修改一下 <code>PKGBUILD</code> 中对应 <code>99-android-mtp.rules</code> 文件的 <code>md5</code> 值，无论你有没有进行上一步的修改，这个值都是错误的。</p>

<p>从 AUR 安装所需的依赖 <a href="https://aur.archlinux.org/packages/go-mtpfs-git/"><code>go-mtpfs-git</code></a> 和 <a href="https://aur.archlinux.org/packages/daemonize/"><code>daemonize</code></a></p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span>yaourt -S go-mtpfs-git daemonize
</span></code></pre></td></tr></table></div></figure>


<p>打包</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">cd </span>android-automount/
</span><span class='line'><span class="nv">$ </span>makepkg
</span></code></pre></td></tr></table></div></figure>


<p>安装</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span>sudo pacman -U android-automount-0.1-1-any.pkg.tar.xz
</span></code></pre></td></tr></table></div></figure>


<p>OK，现在连接你的 Android 设备到电脑上，看看 Arch 是不是成功挂载了呢~    <br/>
如果需要断开连接，只需直接拔掉数据线就好，无需手动 unmount。</p>

<h2>参考资料</h2>

<ul>
<li><a href="https://bbs.archlinux.org/viewtopic.php?id=154123">Automounting MTP devices</a></li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[修正图片文件扩展名的 Python 脚本]]></title>
    <link href="http://wenLiangcan.github.io/blog/2013/10/18/correct-image-file-extension/"/>
    <updated>2013-10-18T16:32:00+08:00</updated>
    <id>http://wenLiangcan.github.io/blog/2013/10/18/correct-image-file-extension</id>
    <content type="html"><![CDATA[<p>有时候从往上下再下来的图片会出现扩展名与实际的图片格式不一致的情况，在 Linux 里我用 <a href="http://projects.gnome.org/eog/" title="Homepage">Eye of GNOME</a> 看图，就会因为这样而无法显示。</p>

<p>最近尝试自学 Python，查了一下相关资料后试着写了一个识别图片格式并更正扩展名的脚本。</p>

<h3>1. 识别图片格式</h3>

<p>不看扩展名如何知道一个图片文件是什么格式呢？ 网上说的比较多的是通过检查<a href="http://baike.baidu.com/view/1606305.htm">文件头</a>标志的方法来判断图片格式，可是自己写的话感觉有点麻烦。</p>

<p>其实已经有现成的轮子可以用了，就是 <code>imghdr</code> 这个模块，可以看一下它的 Docstring 的说明</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="o">&gt;&gt;&gt;</span> <span class="kn">import</span> <span class="nn">imghdr</span>
</span><span class='line'><span class="o">&gt;&gt;&gt;</span> <span class="k">print</span> <span class="n">imghdr</span><span class="o">.</span><span class="n">__doc__</span>
</span><span class='line'><span class="n">Recognize</span> <span class="n">image</span> <span class="nb">file</span> <span class="n">formats</span> <span class="n">based</span> <span class="n">on</span> <span class="n">their</span> <span class="n">first</span> <span class="n">few</span> <span class="nb">bytes</span><span class="o">.</span>
</span></code></pre></td></tr></table></div></figure>


<p>只能识别一些常见的图片格式，对一些特殊的图片文件比如 svg， psd 就无力了，不过已经满足我的需求啦。</p>

<p>用法：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">imghdr</span><span class="o">.</span><span class="n">what</span><span class="p">(</span><span class="o">&lt;</span><span class="n">image_file</span><span class="o">&gt;</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>返回对应格式的扩展名字符串。</p>

<h3>2. 更正文件扩展名</h3>

<p>需要用到一些文件操作的方法，用到 <code>os</code> 这个模块，记录一下：</p>

<ul>
<li><code>os.chdir(dirname)</code>: 用于改变工作路径到 dirname。</li>
<li><code>os.listdir(dirname)</code>: 列出 dirname 下的目录和文件。</li>
<li><code>os.path.isfile(name)</code>: 判断 name 是否为文件。</li>
<li><code>os.path.splitext()</code>: 分离文件名与扩展名。</li>
<li><code>os.rename(a, b)</code>: 重命名文件。</li>
</ul>


<h3>3. 脚本</h3>

<figure class='code'><figcaption><span>correct-image-file-extension.py</span><a href='https://gist.github.com/wenLiangcan/7040164'>link</a></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="c">#!/usr/bin/python</span>
</span><span class='line'>
</span><span class='line'><span class="kn">import</span> <span class="nn">os</span><span class="o">,</span> <span class="nn">sys</span><span class="o">,</span> <span class="nn">imghdr</span>
</span><span class='line'>
</span><span class='line'><span class="c">#允许指定文件目录，默认则检测当前目录</span>
</span><span class='line'><span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
</span><span class='line'>    <span class="k">try</span><span class="p">:</span>
</span><span class='line'>        <span class="n">os</span><span class="o">.</span><span class="n">chdir</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
</span><span class='line'>    <span class="k">except</span> <span class="ne">OSError</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
</span><span class='line'>        <span class="k">if</span> <span class="n">e</span><span class="o">.</span><span class="n">errno</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
</span><span class='line'>            <span class="k">print</span> <span class="s">&quot;No such file or directory: &#39;</span><span class="si">%s</span><span class="s">&#39;&quot;</span> <span class="o">%</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
</span><span class='line'>
</span><span class='line'><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="s">&#39;.&#39;</span><span class="p">):</span>
</span><span class='line'>    <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isfile</span><span class="p">(</span><span class="n">i</span><span class="p">):</span>
</span><span class='line'>        <span class="n">name</span> <span class="o">=</span> <span class="n">i</span>
</span><span class='line'>        <span class="c">#有时候会出现 &quot;.png.jpg&quot; 这样格式的扩展名，为了美观，作相应的调整。</span>
</span><span class='line'>        <span class="k">while</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">splitext</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">splitext</span><span class="p">(</span><span class="n">name</span><span class="p">)[</span><span class="mi">0</span><span class="p">])[</span><span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="s">&#39;&#39;</span><span class="p">:</span>
</span><span class='line'>            <span class="n">name</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">splitext</span><span class="p">(</span><span class="n">name</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
</span><span class='line'>        <span class="n">fmt</span> <span class="o">=</span> <span class="n">imghdr</span><span class="o">.</span><span class="n">what</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
</span><span class='line'>        <span class="n">xname</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">splitext</span><span class="p">(</span><span class="n">name</span><span class="p">)[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">:]</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
</span><span class='line'>        <span class="k">if</span> <span class="n">fmt</span> <span class="o">!=</span> <span class="bp">None</span> <span class="ow">and</span> <span class="n">fmt</span> <span class="o">!=</span> <span class="n">xname</span><span class="p">:</span>
</span><span class='line'>            <span class="c">#JPEG 图片的扩展名有时会简写为 jpg，而 imghdr 里则表示为 jpeg，遇到这样的情况直接跳过不再更改。</span>
</span><span class='line'>            <span class="k">if</span> <span class="n">fmt</span> <span class="o">==</span> <span class="s">&#39;jpeg&#39;</span> <span class="ow">and</span> <span class="n">xname</span> <span class="o">==</span> <span class="s">&#39;jpg&#39;</span><span class="p">:</span>
</span><span class='line'>                <span class="k">continue</span>
</span><span class='line'>            <span class="n">cn</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">splitext</span><span class="p">(</span><span class="n">name</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s">&#39;.&#39;</span> <span class="o">+</span> <span class="n">fmt</span>
</span><span class='line'>            <span class="n">os</span><span class="o">.</span><span class="n">rename</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">cn</span><span class="p">)</span>
</span><span class='line'>            <span class="k">print</span> <span class="s">&#39;Renamed </span><span class="si">%s</span><span class="s"> to </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">cn</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<h2>参考资料</h2>

<ul>
<li><a href="http://stackoverflow.com/a/902779/1436873">How to check if a file is a valid image file?</a></li>
<li><a href="http://stackoverflow.com/a/2491232/1436873">How to rename a file using Python</a></li>
<li><a href="http://www.cnblogs.com/vivilisa/archive/2009/03/01/1400968.html">python天天进步(2)&#8211;文件操作之遍历目录</a></li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[JS 操作 iframe 非跨域引用页面的DOM]]></title>
    <link href="http://wenLiangcan.github.io/blog/2013/06/30/iframe-dom/"/>
    <updated>2013-06-30T00:00:00+08:00</updated>
    <id>http://wenLiangcan.github.io/blog/2013/06/30/iframe-dom</id>
    <content type="html"><![CDATA[<p>偶然发现了学校校园网登录页上验证码的奇葩特性：</p>

<p><img src="https://dl.dropboxusercontent.com/s/6w4hjuewsb8xzbh/CAPTCHA.png?token_hash=AAFpHUTYN6B9vrtHK1plhgeV3N10ZWyFGHPKlx5PsBQeKw&amp;dl=1" alt="" /></p>

<p>于是写了个小书签，自动填写验证码并登录：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nx">javascript</span><span class="o">:</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span><span class="kd">var</span> <span class="nx">a</span><span class="o">=</span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s2">&quot;main&quot;</span><span class="p">).</span><span class="nx">contentWindow</span><span class="p">;</span><span class="nx">a</span><span class="p">.</span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s2">&quot;rand&quot;</span><span class="p">).</span><span class="nx">value</span><span class="o">=</span><span class="nx">a</span><span class="p">.</span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s2">&quot;confirmrand&quot;</span><span class="p">).</span><span class="nx">value</span><span class="p">;</span><span class="nx">a</span><span class="p">.</span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s2">&quot;login1&quot;</span><span class="p">).</span><span class="nx">submit</span><span class="p">();})()</span>
</span></code></pre></td></tr></table></div></figure>


<p>            <br/>
登录信息填写的部分是一个由 iframe 标签引用的非跨域页面，可以通过 <em>contentWindow</em> 属性在父页面中对其元素进行操作：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">a</span><span class="o">=</span><span class="nx">doucument</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s2">&quot;iframe 标签的ID&quot;</span><span class="p">).</span><span class="nx">contentWindow</span><span class="p">;</span>
</span></code></pre></td></tr></table></div></figure>


<p></p>

<h2>参考资料</h2>

<ul>
<li><a href="http://hi.baidu.com/tang_guangyao/item/464da28619aa49e9b07154dd">javascript访问操作iframe中的元素（不跨域）</a></li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[SQL：一次性插入多个元组]]></title>
    <link href="http://wenLiangcan.github.io/blog/2013/04/24/sql-multiple-row-insert/"/>
    <updated>2013-04-24T19:21:00+08:00</updated>
    <id>http://wenLiangcan.github.io/blog/2013/04/24/sql-multiple-row-insert</id>
    <content type="html"><![CDATA[<p>书本上没有，在 StackOverflow 找到了，做一下笔记</p>

<p><strong>句式一：</strong></p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='sql'><span class='line'><span class="k">INSERT</span> <span class="k">INTO</span> <span class="s1">&#39;tablename&#39;</span> <span class="p">(</span><span class="s1">&#39;column1&#39;</span><span class="p">,</span> <span class="s1">&#39;column2&#39;</span><span class="p">)</span> <span class="k">VALUES</span>
</span><span class='line'><span class="p">(</span><span class="s1">&#39;data1&#39;</span><span class="p">,</span> <span class="s1">&#39;data2&#39;</span><span class="p">),</span>
</span><span class='line'><span class="p">(</span><span class="s1">&#39;data3&#39;</span><span class="p">,</span> <span class="s1">&#39;data4&#39;</span><span class="p">),</span>
</span><span class='line'><span class="p">(</span><span class="s1">&#39;data5&#39;</span><span class="p">,</span> <span class="s1">&#39;data6&#39;</span><span class="p">),</span>
</span><span class='line'><span class="p">(</span><span class="s1">&#39;data7&#39;</span><span class="p">,</span> <span class="s1">&#39;data8&#39;</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>                      <br/>
<strong>句式二：</strong></p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='sql'><span class='line'><span class="k">INSERT</span> <span class="k">INTO</span> <span class="s1">&#39;tablename&#39;</span>
</span><span class='line'>      <span class="k">SELECT</span> <span class="s1">&#39;data1&#39;</span> <span class="k">AS</span> <span class="s1">&#39;column1&#39;</span><span class="p">,</span> <span class="s1">&#39;data2&#39;</span> <span class="k">AS</span> <span class="s1">&#39;column2&#39;</span>
</span><span class='line'><span class="k">UNION</span> <span class="k">SELECT</span> <span class="s1">&#39;data3&#39;</span><span class="p">,</span> <span class="s1">&#39;data4&#39;</span>
</span><span class='line'><span class="k">UNION</span> <span class="k">SELECT</span> <span class="s1">&#39;data5&#39;</span><span class="p">,</span> <span class="s1">&#39;data6&#39;</span>
</span><span class='line'><span class="k">UNION</span> <span class="k">SELECT</span> <span class="s1">&#39;data7&#39;</span><span class="p">,</span> <span class="s1">&#39;data8&#39;</span>
</span></code></pre></td></tr></table></div></figure>


<p></p>

<h2>参考资料</h2>

<ul>
<li><a href="http://stackoverflow.com/questions/1609637/is-it-possible-to-insert-multiple-rows-at-a-time-in-an-sqlite-database">Is it possible to insert multiple rows at a time in an SQLite database?</a></li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Windows下编译支持多种脚本语言的64位VIM(GVIM)]]></title>
    <link href="http://wenLiangcan.github.io/blog/2013/04/21/vim-compilation/"/>
    <updated>2013-04-21T10:30:00+08:00</updated>
    <id>http://wenLiangcan.github.io/blog/2013/04/21/vim-compilation</id>
    <content type="html"><![CDATA[<p>想要玩一下 <a href="http://www.vim.org/scripts/script.php?script_id=931">VimIRC.vim</a> 这款插件，不过这货竟然是 Perl 写的，而我用的 vim 没有加入 Perl 支持，所以想不如试试编译一个支持多种脚本语言的 vim</p>

<ul>
<li><strong>Vim版本</strong>：7.3.905</li>
<li><strong>需要支持的语言</strong>：Python2/3， Ruby， Perl， Lua， Tcl</li>
<li><strong>编译环境</strong>：Cygwin</li>
<li><strong>操作系统</strong>：64 位的 Windows8</li>
</ul>


<h2>一.准备工作</h2>

<h4>1.Cygwin</h4>

<p>除了默认的组件外，还需要选择以下的包：autobuild，autoconf，automake，binutils，cmake，gcc-core，gcc,gcc-g77，gcc-g++，gcc4-core，gcc4，gcc4-g++，make，makedepend，pkg-config，gcc-mingw-core，gcc-mingw-g++，gdb，最后，因为现在是编译 64 位版本的 vim 而我又不清楚具体需要哪些包，所以直接搜索 64，选择安装所有的搜索结果 XD</p>

<h4>2.各种语言的包</h4>

<p>我一律选择了 64 位的版本。Python 分别为 2.7.3 跟 3.3.1。Ruby 本来纠结是用 1.9.3 还是 2.0.0 好，本来电脑里因为配置 Octopress 已经安装了 1.9.3 ,可是 RubyInstaller 似乎只有 2.0 有 64 位的版本，又不知道 Octopress 对 2.0 会不会有兼容性问题。最后选择了下 2.0.0 的 zip 包。Perl 5 的实现选用了 ActivePerl，版本为 5.16.3。Lua 到<a href="http://luabinaries.sourceforge.net/download.html">这里</a>下载 <a href="http://sourceforge.net/projects/luabinaries/files/5.2.1/Executables/lua-5.2.1_Win64_bin.zip/download">lua-5.2.1_Win64_bin.zip</a> 和 <a href="http://sourceforge.net/projects/luabinaries/files/5.2.1/Windows%20Libraries/Dynamic/lua-5.2.1_Win64_dllw4_lib.zip/download">lua-5.2.1_Win64_dllw4_lib.zip</a> 这两个文件，解压到同一目录下。</p>

<p><em>update (20130501)</em>：增加对 Tcl 的支持，版本为 <a href="http://www.activestate.com/activetcl/downloads/thank-you?dl=http://downloads.activestate.com/ActiveTcl/releases/8.5.13.0/ActiveTcl8.5.13.0.296436-win32-x86_64-threaded.exe">ActiveTcl 8.5.13</a>。原本打算用 8.6 的，无奈编译不成功，原因不明。。。</p>

<h4>3.VIM 源代码</h4>

<p>在这里 <a href="ftp://ftp.vim.org/pub/vim/pc/">ftp://ftp.vim.org/pub/vim/pc/</a> 下载，当然是选
7.3啦，找到 vim73_46rt.zip，vim73_46src.zip 这两个包，前一个是运行时文件后一个是源代码，从 7.3 开始语言文件已经打包进了runtime里。然后再到这里 <a href="ftp://ftp.vim.org/pub/vim/patches/7.3/">ftp://ftp.vim.org/pub/vim/patches/7.3/</a> 下载补丁。</p>

<p>不过这些补丁实在太多了（911 个！），下载起来实在有点麻烦。最开始想到用 Firefox的DownThemAll 扩展，不过不知为什么下载下来的文件名开头都多了个 2.3（记不太清，反正就是多了几个数字，不过现在想想其实也没什么影响 ←_←）。然后又想到在资源管理器打开再全选复制，不过速度实在慢的可以。最终 google 后选择了 wget，查了一下命令：</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>$ wget -c -r -nd -np www.xxx.org/pub/path/</span></code></pre></td></tr></table></div></figure>


<p>-c：断点续传；-r：递归目录；-nd：递归是不创建各层目录直接下载到当前目录下；-np：递归时不搜索上层目录。</p>

<p>把vim73_46src.zip里的src 文件夹（其他的可有可无）解压到一个暂命名为 make 的目录下，把所有的补丁文件放到与 make 目录同级的 patches 文件夹里。打开 Cygwin，c d到 make 目录下(在 Cygwin 里的 /cygdrive 路径下可以找到系统里的各分区)，执行以下命令打补丁：</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>$ for file in ../patches/7.3.*; do patch -Np0 -i $file; done</span></code></pre></td></tr></table></div></figure>


<h2>二.开始编译</h2>

<p>cd 到 src 文件夹下，执行以下编译命令：</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>$ make -f Make_cyg.mak CC=x86_64-w64-mingw32-gcc RC=x86_64-w64-mingw32-windres ARCH=x86-64 PYTHON=/cygdrive/c/Python27 PYTHON_VER=27 DYNAMIC_PYTHON=yes PYTHON3=/cygdrive/c/Python33 PYTHON3_VER=33 DYNAMIC_PYTHON3=yes RUBY=/cygdrive/c/Ruby200_64 RUBY_VER=200 RUBY_VER_LONG=2.0.0 DYNAMIC_RUBY=yes LUA=/cygdrive/c/Lua52 LUA_VER=52 DYNAMIC_LUA=yes PERL=/cygdrive/c/Perl64 PERL_VER=516 DYNAMIC_PERL=yes TCL=/cygdrive/c/Tcl TCL_VER=85 DYNAMIC_TCL=yes -j5 GUI=yes STATIC_STDCPLUS=yes OLE=yes FEATURES=HUGE USERNAME=wenLiangcan USERDOMAIN=Cygwin</span></code></pre></td></tr></table></div></figure>


<p>*_VER 跟 *_VER_LONG 的区别是，前者使用不带“.”的版本号，如 200，而后者则需要，如 2.0.0。查看 Make_cyg.ma k文件可以发现，对 ruby 的支持编译需要通过版本号定位到 \$(RUBY)/lib/ruby/\$(RUBY_VER_LONG)/… 这样的路径下，所以对 ruby 使用的这个参数。</p>

<p>不使用 STATIC_STDCPLUS=yes 的话，gvim 运行时会需要 libstdc++-6.dll 跟 libgcc_s_sjlj-1.dll 这两个文件。</p>

<p>GUI=yes 就是编译 gvim，GUI=no 则编译 vim。</p>

<p>多字长跟 cscope 支持都是默认为 yes。</p>

<p>编译完成后，复制 src/ 下的 vim.exe，gvim.exe，install.exe，uninstal.exe，vimrun.exe 跟 GvimExt/ 下的 gvimext.dll（用来添加系统右键菜单的“Edit with Vim”） 还有 xxd/ 下的 xxd.exe到运行时目录下（由 vim73_46rt.zip 解压得到）就可以啦。如果需要安装，就在 cmd 里以管理员权限运行 install.exe。</p>

<h2>三.查看成果</h2>

<p>运行 vim/gvim ，执行命令：</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>:version</span></code></pre></td></tr></table></div></figure>


<p><img src="https://dl.dropboxusercontent.com/s/j558p79x9rnx5cf/vim_version.jpg?token_hash=AAFQm5Bxld04uNOc_j4PaJ_ArAir2S0sI2FDMEEfpjAARA&amp;dl=1" alt="" /></p>

<p>(￣一￣)y</p>

<p>附上<a href="https://bitbucket.org/wenliangcan/win64-releases-of-vim-with-multiple-languages-surpport/downloads">下载</a></p>

<h2>四.补充</h2>

<ul>
<li>中文系统下 cygwin 的 shell 也会自动支持中文，如果编译过程出现错误想要复制 google
一下，英文关键词的搜索结果往往会更准确，所以我想把它改为英文提示，可以在 ~/.bashrc 里末尾加上：</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nb">export </span><span class="nv">LANG</span><span class="o">=</span><span class="s1">&#39;en_US&#39;</span>
</span><span class='line'><span class="nb">export </span><span class="nv">LC_ALL</span><span class="o">=</span><span class="s1">&#39;en_US.GBK&#39;</span>
</span></code></pre></td></tr></table></div></figure>


<ul>
<li>编译后可以执行以下命令清理编译文件：</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span>make -f Make_cyg.mak clean
</span></code></pre></td></tr></table></div></figure>


<h2>五.参考资料</h2>

<ul>
<li><a href="http://www.vimer.cn/2010/04/windows%E4%B8%8B%E7%BC%96%E8%AF%91vimgvim%E5%B9%B6%E5%8A%A0%E5%85%A5python2-6%E5%92%8C3-1%E6%94%AF%E6%8C%81.html">windows下编译vim(gvim)并加入python2.6和3.1支持</a></li>
<li><a href="https://groups.google.com/forum/?fromgroups=#!topic/vim_dev/2_bsP-SfnRo">How to compile 64 bit with cygwin/mingw?</a></li>
<li><a href="http://people.smu.edu/jrobinet/howto/compile-vim-on-windows.asp">Compiling Vim on Windows</a></li>
<li><a href="http://www.joynb.net/blog/archives/973">[转载]本人在cygwin下完整工作环境的搭建(备忘)</a></li>
<li><a href="http://blog.csdn.net/jianping_shen/article/details/6300638">eclipse+cdt+cygwin配置c/c++开发环境</a></li>
<li><a href="http://5iwww.blog.51cto.com/856039/620831">使用wget递归下载某目录下的所有文件</a></li>
<li><a href="http://blog.csdn.net/a221133/article/details/7043318">让cygwin使用英文shell界面</a></li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[test]]></title>
    <link href="http://wenLiangcan.github.io/blog/2012/09/14/test/"/>
    <updated>2012-09-14T01:24:00+08:00</updated>
    <id>http://wenLiangcan.github.io/blog/2012/09/14/test</id>
    <content type="html"><![CDATA[<p><em>Test</em> <br/>
<strong>测试</strong> <br/>
測試</p>
]]></content>
  </entry>
  
</feed>
