<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:dc="http://purl.org/dc/elements/1.1/"
     xmlns:wfw="http://wellformedweb.org/CommentAPI/"
     >
  <channel>
    <title>mojavy.com</title>
    <link>http://mojavy.com/blog</link>
    <description></description>
    <pubDate>Tue, 13 Dec 2011 00:58:29 GMT</pubDate>
    <generator>Blogofile</generator>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>tmuxでマウスを使う</title>
      <link>http://mojavy.com/blog/2011/12/13/tmux_advent_calendar_2_2011/</link>
      <pubDate>Tue, 13 Dec 2011 00:58:29 JST</pubDate>
      <category><![CDATA[advent calendar]]></category>
      <category><![CDATA[tmux]]></category>
      <guid isPermaLink="true">http://mojavy.com/blog/2011/12/13/tmux_advent_calendar_2_2011/</guid>
      <description>tmuxでマウスを使う</description>
      <content:encoded><![CDATA[<p>これは<a href="http://atnd.org/events/22320">ターミナルマルチプレクサ Advent Calendar 2011</a>の13日目です。
12日目はnetmarkjpさんの<a href="http://netmark.jp/2011/12/gnu-screen-xmodem.html">GNU screen でシリアル通信 + xmodem転送</a>でした。</p>
<p>今日はtmuxのマウスまわりの設定について紹介してみます。</p>
<p>tmuxにはマウスで操作するための機能がいくつか提供されています。ChangeLogを見る限りでは結構前からマウスサポートはされているようですが、mac portから入れたtmuxでは動かなかったのでソースから最新版をいれることをおすすめします。
macでソースから入れる方法は初日に<a href="http://d.hatena.ne.jp/tmatsuu/20111130/1322677832">matsuuさんが紹介してくれている</a>のでそちらを参考にしてください。</p>
<p>tmux-1.5の時点で使えるマウス関連の設定項目は以下の通りです。</p>
<dl>
<dt>mode-mouse</dt>
<dd>onにすると、マウスで画面をドラッグしたときにコピーモードに入ります。マウスホイールでスクロールすることもできます。</dd>
<dt>mouse-select-pane</dt>
<dd>マウスクリックでpaneを選択できるようになります。</dd>
<dt>mouse-select-window</dt>
<dd>statusを有効にしているときに、window名の部分をクリックすることでwindowを切り替えられます。</dd>
<dt>mouse-utf8</dt>
<dd>マウスの入力をutf-8として扱うための設定だそうです。効果はよくわかりませんでした。</dd>
</dl>
<p>なお、shiftを押しながらターミナルをクリックすれば、本来のマウスの動作になります。</p>
<p>macのiTerm, windowsのputty, ubuntuのgnome-terminalで動作確認できました。
たまに画面が乱れることがありますが、再描画すると直ります。</p>
<h1 id="_1">まとめ</h1>
<p>以下を.tmux.confにコピペするとtmuxでマウスがつかえます。</p>
<div class="pygments_borland"><pre><span class="nb">set</span> -g mode-mouse on
<span class="nb">set</span> -g mouse-resize-pane on
<span class="nb">set</span> -g mouse-select-pane on
<span class="nb">set</span> -g mouse-select-window on
</pre></div>

<p>本当は、set-clipboardという機能も紹介したかったのですが、ちゃんと動かすことができなかったのでまたの機会にします。
以上非常に簡単でしたがマウスサポート機能の紹介でした。</p>]]></content:encoded>
    </item>
    <item>
      <title>tmuxに独自機能を追加する</title>
      <link>http://mojavy.com/blog/2011/12/06/tmux_advent_calendar_2011/</link>
      <pubDate>Tue, 06 Dec 2011 01:05:10 JST</pubDate>
      <category><![CDATA[advent calendar]]></category>
      <category><![CDATA[tmux]]></category>
      <guid isPermaLink="true">http://mojavy.com/blog/2011/12/06/tmux_advent_calendar_2011/</guid>
      <description>tmuxに独自機能を追加する</description>
      <content:encoded><![CDATA[<p>これは<a href="http://atnd.org/events/22320">ターミナルマルチプレクサ Advent Calendar 2011</a>の<s>6日目</s>7日目です。(netmark.jpさん,matsuuさん、すいません、出遅れました。)</p>
<p>5日目はyoshikawさんの<a href="http://yskwkzhr.blogspot.com/2011/12/lets-use-development-version-gnu-screen.html">開発版GNU Screenを使ってみよう</a>でした。</p>
<p>6日目はnetmark.jpさんの<a href="http://netmark.jp/2011/12/gnu-screen-plusone.html">GNU screenをもうちょっとだけ便利に使おう！</a>でした。</p>
<p>この記事ではtmuxのいじり方を簡単に紹介してみます。</p>
<h1 id="_1">はじめに</h1>
<p>tmuxは比較的若いプロジェクトなこともあってか、かゆいところに手が届かないシチュエーションがたまにあります。
個人的に不満だったのはバッファの挙動です。</p>
<p>tmuxでバッファに文字列をコピーした場合、list-buffersに新しいものほど前方になるように格納されていきます。
choose-bufferコマンドを使えばある程度簡単に過去のものもさかのぼれますがしばらくすると埋もれてしまいます。
tmuxのバッファにはホスト名とかよくつかうコマンドとかをいれておいて番号を指定して最速でとりだしたいのに、
場所が固定されていないといちいち探さなくてはならず不便に感じていました。
なんとかできないかと思ってソースをいじってみたら、意外と簡単だったので簡単な解説をまじえつつ手順を紹介してみます。</p>
<h1 id="_2">目次</h1>
<div class="toc">
<ul>
<li><a href="#_1">はじめに</a></li>
<li><a href="#_2">目次</a></li>
<li><a href="#_3">準備</a><ul>
<li><a href="#_4">ソースをとってくる</a></li>
<li><a href="#_5">依存パッケージを入れる</a></li>
<li><a href="#_6">ビルド</a></li>
</ul>
</li>
<li><a href="#_7">ソース構成</a></li>
<li><a href="#_8">いじってみる</a></li>
<li><a href="#_9">まとめ</a></li>
</ul>
</div>
<h1 id="_3">準備</h1>
<h2 id="_4">ソースをとってくる</h2>
<p>本家サイトからソースをおとします。とりあえず現在の最新版(1.5)でいいと思います。</p>
<p><a href="http://tmux.sourceforge.net/">http://tmux.sourceforge.net/</a></p>
<h2 id="_5">依存パッケージを入れる</h2>
<p><a href="http://d.hatena.ne.jp/tmatsuu/20111130/1322677832">tmatsuuさんの記事</a>にもちょっとありましたが、
tmuxはlibeventとnlcursesに依存しているのでビルドするにはライブラリのヘッダも必要です。
ubuntuだと以下パッケージを入れとけばたぶん大丈夫です。</p>
<div class="pygments_borland"><pre>sudo apt-get install libevent-dev libncurses5-dev
</pre></div>

<h2 id="_6">ビルド</h2>
<div class="pygments_borland"><pre>./configure <span class="o">&amp;&amp;</span> make
</pre></div>

<p>ここまでできたら準備OKです。</p>
<h1 id="_7">ソース構成</h1>
<p>結構たくさんファイルがありますが、ファイル名を見れば大体雰囲気がつかめると思います。</p>
<p>何か機能を追加したいだけなら、いじる必要のあるファイルはごく一部です。</p>
<dl>
<dt>tmux.h</dt>
<dd>
<dl>
<dt>ほとんどのコマンドは全部ここに宣言がまとめられてるのでほぼ必ずいじります。</dt>
<dt>options-table.c</dt>
<dd>オプション追加する場合はここに追加します。値の肩などを定義するテーブルが宣言されているので、中身を見れば大体わかると思います。</dd>
</dl>
</dd>
</dl>
<p>いじる必要はないですがarray.hはいろんなところでつかわれてるので目を通しとくとよいと思います。
Cでリストが使いたい場合は他のとこでも流用できそうな便利なヘッダです。</p>
<p>あとは必要に応じて関係しそうなところをみていけばよいです。</p>
<h1 id="_8">いじってみる</h1>
<p>バッファまわりを改造したいので、paste.cというファイルが主な対象になります。</p>
<p>細かい解説は省略しますが、paste_stackという構造体がグローバルで共有しているリストの本体で、array.hで宣言されているマクロで値がとりだせるようになっています。
本来の動作であるpaste_addを参考にしつつpaste_add_tailなんて関数を追加します。
後に追加した文字列ほど後ろにいってほしいですが、直前のものだけは先頭にあったほうが便利なのでちょっと変則的な感じになってますが、やっていることはシンプルです。</p>
<div class="pygments_borland"><pre><span class="gh">diff -u tmux-1.5/paste.c tmux-1.5-patched/paste.c</span>
<span class="gd">--- tmux-1.5/paste.c    2011-07-09 18:42:38.000000000 +0900</span>
<span class="gi">+++ tmux-1.5-patched/paste.c    2011-12-06 23:36:31.921805251 +0900</span>
<span class="gu">@@ -119,6 +119,38 @@</span>
        pb-&gt;size = size;
 }

<span class="gi">+/*</span>
<span class="gi">+ * Add an item onto the tail of the stack, freeing the bottom if at limit. Note</span>
<span class="gi">+ * that the caller is responsible for allocating data.</span>
<span class="gi">+ */</span>
<span class="gi">+void</span>
<span class="gi">+paste_add_tail(struct paste_stack *ps, char *data, size_t size, u_int limit)</span>
<span class="gi">+{</span>
<span class="gi">+       struct paste_buffer     *pb;</span>
<span class="gi">+</span>
<span class="gi">+       if (size == 0)</span>
<span class="gi">+               return;</span>
<span class="gi">+</span>
<span class="gi">+       while (ARRAY_LENGTH(ps) &gt;= limit) {</span>
<span class="gi">+               pb = ARRAY_LAST(ps);</span>
<span class="gi">+               xfree(pb-&gt;data);</span>
<span class="gi">+               xfree(pb);</span>
<span class="gi">+               ARRAY_TRUNC(ps, 1);</span>
<span class="gi">+       }</span>
<span class="gi">+</span>
<span class="gi">+       pb = xmalloc(sizeof *pb);</span>
<span class="gi">+</span>
<span class="gi">+       if (ARRAY_LENGTH(ps) &gt; 0) {</span>
<span class="gi">+               ARRAY_ADD(ps, ARRAY_FIRST(ps));</span>
<span class="gi">+               ARRAY_SET(ps, 0, pb);</span>
<span class="gi">+       } else {</span>
<span class="gi">+               ARRAY_ADD(ps, pb);</span>
<span class="gi">+       }</span>
<span class="gi">+       ARRAY_INSERT(ps, 0, pb);</span>
<span class="gi">+</span>
<span class="gi">+       pb-&gt;data = data;</span>
<span class="gi">+       pb-&gt;size = size;</span>
<span class="gi">+}</span>
</pre></div>

<p>ここで追加した関数はtmux.hで宣言しておきます</p>
<div class="pygments_borland"><pre><span class="gh">diff -u tmux-1.5/tmux.h tmux-1.5-patched/tmux.h</span>
<span class="gd">--- tmux-1.5/tmux.h     2011-07-09 18:42:38.000000000 +0900</span>
<span class="gi">+++ tmux-1.5-patched/tmux.h     2011-12-06 23:36:31.925805201 +0900</span>
<span class="gu">@@ -1487,6 +1487,7 @@</span>
 int             paste_free_top(struct paste_stack *);
 int             paste_free_index(struct paste_stack *, u_int);
 void            paste_add(struct paste_stack *, char *, size_t, u_int);
<span class="gi">+void            paste_add_tail(struct paste_stack *, char *, size_t, u_int);</span>
 int             paste_replace(struct paste_stack *, u_int, char *, size_t);
 char           *paste_print(struct paste_buffer *, size_t);
</pre></div>

<p>また、今回の機能は設定ファイルでon/offを切り替えられるようにしておきたいので、options-table.cも編集します。</p>
<div class="pygments_borland"><pre><span class="n">diff</span> <span class="o">-</span><span class="n">u</span> <span class="n">tmux</span><span class="o">-</span><span class="mf">1.5</span><span class="o">/</span><span class="n">options</span><span class="o">-</span><span class="n">table</span><span class="p">.</span><span class="n">c</span> <span class="n">tmux</span><span class="o">-</span><span class="mf">1.5</span><span class="o">-</span><span class="n">patched</span><span class="o">/</span><span class="n">options</span><span class="o">-</span><span class="n">table</span><span class="p">.</span><span class="n">c</span>
<span class="o">---</span> <span class="n">tmux</span><span class="o">-</span><span class="mf">1.5</span><span class="o">/</span><span class="n">options</span><span class="o">-</span><span class="n">table</span><span class="p">.</span><span class="n">c</span>    <span class="mi">2011</span><span class="o">-</span><span class="mo">07</span><span class="o">-</span><span class="mi">09</span> <span class="mi">18</span><span class="o">:</span><span class="mi">42</span><span class="o">:</span><span class="mf">38.000000000</span> <span class="o">+</span><span class="mi">0900</span>
<span class="o">+++</span> <span class="n">tmux</span><span class="o">-</span><span class="mf">1.5</span><span class="o">-</span><span class="n">patched</span><span class="o">/</span><span class="n">options</span><span class="o">-</span><span class="n">table</span><span class="p">.</span><span class="n">c</span>    <span class="mi">2011</span><span class="o">-</span><span class="mi">12</span><span class="o">-</span><span class="mo">06</span> <span class="mi">23</span><span class="o">:</span><span class="mi">36</span><span class="o">:</span><span class="mf">31.921805251</span> <span class="o">+</span><span class="mi">0900</span>
<span class="err">@@</span> <span class="o">-</span><span class="mi">57</span><span class="p">,</span><span class="mi">6</span> <span class="o">+</span><span class="mi">57</span><span class="p">,</span><span class="mi">11</span> <span class="err">@@</span>
          <span class="p">.</span><span class="n">default_num</span> <span class="o">=</span> <span class="mi">20</span>
        <span class="p">},</span>

<span class="o">+</span>       <span class="p">{</span> <span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">&quot;reverse-buffer&quot;</span><span class="p">,</span>
<span class="o">+</span>         <span class="p">.</span><span class="n">type</span> <span class="o">=</span> <span class="n">OPTIONS_TABLE_FLAG</span><span class="p">,</span>
<span class="o">+</span>         <span class="p">.</span><span class="n">default_num</span> <span class="o">=</span> <span class="mi">0</span>
<span class="o">+</span>       <span class="p">},</span>
<span class="o">+</span>
        <span class="p">{</span> <span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">&quot;escape-time&quot;</span><span class="p">,</span>
          <span class="p">.</span><span class="n">type</span> <span class="o">=</span> <span class="n">OPTIONS_TABLE_NUMBER</span><span class="p">,</span>
          <span class="p">.</span><span class="n">minimum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
</pre></div>

<p>実際にバッファの制御関数を呼び出しているのはwindow-copy.cなので、さっき追加したオプションの値をみて切り替えられるようにします。</p>
<div class="pygments_borland"><pre><span class="gh">diff -u tmux-1.5/window-copy.c tmux-1.5-patched/window-copy.c</span>
<span class="gd">--- tmux-1.5/window-copy.c      2011-07-09 18:42:38.000000000 +0900</span>
<span class="gi">+++ tmux-1.5-patched/window-copy.c      2011-12-06 23:36:31.921805251 +0900</span>
<span class="gu">@@ -1348,7 +1348,11 @@</span>
        /* Add the buffer to the stack. */
        limit = options_get_number(&amp;global_options, &quot;buffer-limit&quot;);
<span class="gd">-       paste_add(&amp;global_buffers, buf, off, limit);</span>
<span class="gi">+       if (options_get_number(&amp;global_options, &quot;reverse-buffer&quot;)) {</span>
<span class="gi">+               paste_add(&amp;global_buffers, buf, off, limit);</span>
<span class="gi">+       } else {</span>
<span class="gi">+               paste_add(&amp;global_buffers, buf, off, limit);</span>
<span class="gi">+       }</span>
 }
</pre></div>

<p>あとは設定ファイルに以下を追加してmakeしたtmuxを起動してみます。</p>
<div class="pygments_borland"><pre><span class="nb">set</span> -g reverse-buffer on
</pre></div>

<p>バッファにコピーした文字列がlist-buffersの後ろに追加されていけば成功です。
簡単ですよね？</p>
<h1 id="_9">まとめ</h1>
<p>以上、tmuxにreverse-bufferというオプションを追加して、バッファの挙動を変更できるようにしてみました。</p>
<p>端末制御のプログラムは普段あまり触れる機会がないし複雑そうなイメージがあって敬遠しがちですが、ちょっとした機能を追加するだけだったら意外と簡単だったりするのでどんどんいじってみるといいと思います。</p>]]></content:encoded>
    </item>
  </channel>
</rss>
