blog/content/post/2008/12/21/2008-12-21-00001101.md

169 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: カーソル位置から行末までの数字を全て加算してその結果を返すelisp
author: kazu634
date: 2008-12-21
wordtwit_post_info:
- 'O:8:"stdClass":13:{s:6:"manual";b:0;s:11:"tweet_times";i:1;s:5:"delay";i:0;s:7:"enabled";i:1;s:10:"separation";s:2:"60";s:7:"version";s:3:"3.7";s:14:"tweet_template";b:0;s:6:"status";i:2;s:6:"result";a:0:{}s:13:"tweet_counter";i:2;s:13:"tweet_log_ids";a:1:{i:0;i:4459;}s:9:"hash_tags";a:0:{}s:8:"accounts";a:1:{i:0;s:7:"kazu634";}}'
categories:
- Emacs
- Lisp
---
<div class="section">
<p>
<a href="http://d.hatena.ne.jp/asin/4906391702" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://d.hatena.ne.jp/asin/4906391702', 'やさしいEmacsLisp講座');">やさしいEmacsLisp講座</a>』での勉強がてら作ってみました。編集系コマンドを駆使すると、できました。要は、
</p>
<blockquote>
<p>
100 200 300 400
</p>
</blockquote>
<p>
という行があったときに、100の「1」の部分にカーソルを合わせてこの関数を実行すると、
</p>
<blockquote>
<p>
1000
</p>
</blockquote>
<p>
としてくれます。
</p>
<h4>
対象とする人
</h4>
<p>
とりあえず簡単なLispはわかるーという人。letとかの説明はされなくても大丈夫な人。
</p>
<h4>
できたコード
</h4>
<pre class="syntax-highlight">
<span class="synSpecial">(</span><span class="synStatement">defun</span> my-calc-sum <span class="synSpecial">()</span>
<span class="synSpecial">(</span>interactive<span class="synSpecial">)</span>
<span class="synComment">;; tmp_point: カーソル行末のポイント</span>
<span class="synComment">;; sum: 計算結果を格納するための変数</span>
<span class="synSpecial">(</span><span class="synStatement">let</span> <span class="synSpecial">((</span>tmp_point <span class="synSpecial">(</span><span class="synStatement">progn</span>
<span class="synSpecial">(</span>save-excursion <span class="synComment">;; 現在のカーソル位置を記憶</span>
<span class="synSpecial">(</span>end-of-line<span class="synSpecial">)</span> <span class="synComment">;; 行末に移動</span>
<span class="synSpecial">(</span>point<span class="synSpecial">))))</span> <span class="synComment">;; 現在のポイント位置を取得し、tmp_pointに代入</span>
<span class="synSpecial">(</span>sum <span class="synConstant"></span><span class="synSpecial">))</span> <span class="synComment">;; sumに0を代入</span>
<span class="synSpecial">(</span>save-excursion <span class="synComment">;; 現在のカーソル位置を記憶</span>
<span class="synComment">;; 数字がカーソル行に存在する間は以下の処理を実施</span>
<span class="synSpecial">(</span>while <span class="synSpecial">(</span>re-search-forward <span class="synConstant">&#34;[0-9]+&#34;</span> tmp_point <span class="synStatement">t</span><span class="synSpecial">)</span>
<span class="synComment">;; 検索結果を数字として認識し、sumに加算</span>
<span class="synSpecial">(</span><span class="synStatement">setq</span> sum <span class="synSpecial">(</span><span class="synStatement">+</span> sum <span class="synSpecial">(</span>string-to-number <span class="synSpecial">(</span>buffer-substring <span class="synSpecial">(</span>match-beginning <span class="synConstant"></span><span class="synSpecial">)</span> <span class="synSpecial">(</span>match-end <span class="synConstant"></span><span class="synSpecial">)))))))</span>
<span class="synSpecial">(</span>kill-line<span class="synSpecial">)</span> <span class="synComment">;; カーソル位置から行末までを消去</span>
<span class="synSpecial">(</span>insert <span class="synSpecial">(</span>number-to-string sum<span class="synSpecial">))))</span> <span class="synComment">;;計算結果を挿入</span>
</pre>
<h4>
考えたこと
</h4>
<ol>
<li>
とりあえず正規表現を使って、数字を抜き出そう
</li>
<li>
正規表現を使った検索コマンドは範囲指定ができるから、行末のポイント位置が知りたい(→prognが必要となる理由が理解できた)
</li>
<li>
whileを使うなら、検索コマンドは見つからなかったときにnilを返してほしいな
</li>
<li>
検索結果を抜き出すイディオムがあるんだー
</li>
</ol>
<h4>
用いた関数
</h4>
<h5>
re-search-forward
</h5>
<p>
re(gular)-search-forwardという意味です。そのままずばりで、「正規表現を用いた前方検索」というやつです。使い方は、
</p>
<pre class="syntax-highlight">
<span class="synSpecial">(</span>re-search-forward <span class="synConstant">&#34;正規表現&#34;</span> 検索する範囲 エラー回避 回数<span class="synSpecial">)</span>
</pre>
<p>
となります。
</p>
<ul>
<li>
正規表現: 自分で勉強してください
</li>
<li>
検索する範囲: Emacsでいうところのポイントで指定します。ここで指定された部分まで検索します。
</li>
<li>
エラー回避: 正規表現で指定したものが見つからないと、この関数はエラーを返します。それが嫌なときはここに「t」を指定します。
</li>
</ul>
<h5>
save-excursion
</h5>
<p>
現在位置のポイントを記憶し、以降に記述する処理を実行します。save-excursionのブロックを抜けると、記憶したポイント位置に戻ります。
</p>
<h5>
kill-line
</h5>
<p>
カーソル位置から行末までを消去します。これは知っている人も多いCtrl-kにデフォルトでは割り当てられています。
</p>
<div class="hatena-asin-detail">
<a href="http://www.amazon.co.jp/dp/4906391702/?tag=hatena_st1-22&ascsubtag=d-7ibv" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://www.amazon.co.jp/dp/4906391702/?tag=hatena_st1-22&ascsubtag=d-7ibv', '');"><img src="https://images-na.ssl-images-amazon.com/images/I/51C4N4SHT7L._SL160_.jpg" class="hatena-asin-detail-image" alt="やさしいEmacsLisp講座" title="やさしいEmacsLisp講座" /></a></p>
<div class="hatena-asin-detail-info">
<p class="hatena-asin-detail-title">
<a href="http://www.amazon.co.jp/dp/4906391702/?tag=hatena_st1-22&ascsubtag=d-7ibv" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://www.amazon.co.jp/dp/4906391702/?tag=hatena_st1-22&ascsubtag=d-7ibv', 'やさしいEmacsLisp講座');">やさしいEmacsLisp講座</a>
</p>
<ul>
<li>
<span class="hatena-asin-detail-label">作者:</span> <a href="http://d.hatena.ne.jp/keyword/%B9%AD%C0%A5%CD%BA%C6%F3" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://d.hatena.ne.jp/keyword/%B9%AD%C0%A5%CD%BA%C6%F3', '広瀬雄二');" class="keyword">広瀬雄二</a>
</li>
<li>
<span class="hatena-asin-detail-label">出版社/メーカー:</span> <a href="http://d.hatena.ne.jp/keyword/%A5%AB%A5%C3%A5%C8%A5%B7%A5%B9%A5%C6%A5%E0" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://d.hatena.ne.jp/keyword/%A5%AB%A5%C3%A5%C8%A5%B7%A5%B9%A5%C6%A5%E0', 'カットシステム');" class="keyword">カットシステム</a>
</li>
<li>
<span class="hatena-asin-detail-label">発売日:</span> 1999/01
</li>
<li>
<span class="hatena-asin-detail-label">メディア:</span> 単行本
</li>
<li>
<span class="hatena-asin-detail-label">購入</span>: 4人 <span class="hatena-asin-detail-label">クリック</span>: 145回
</li>
<li>
<a href="http://d.hatena.ne.jp/asin/4906391702" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://d.hatena.ne.jp/asin/4906391702', 'この商品を含むブログ (30件) を見る');" target="_blank">この商品を含むブログ (30件) を見る</a>
</li>
</ul>
</div>
<div class="hatena-asin-detail-foot">
</div>
</div>
</div>