On Github ncaq / symbolword-mode-presentation
まず言っておくことがあります
これはゲームじゃないです,
ゲームは完成しませんでした.
ごめんなさい
と言うと,
Emacs用の,いわゆる拡張機能です.
テキストエディタの1種です.
私はEmacsを便利に常用していたのですが,少し気に入らないことがありました. それは,「単語」の句切りです.
+=の手前にカーソルがあることに注目してください,
ここでM-dに割り当てられた,「単語削除」コマンドを押すと,
このように,+=だけを消したくても,
;のところまで削られてしまいます.
英文の,「単語」の区切りはそれで良いのかもしれませんが,
プログラムを書いている時に,
こんな単語の区切りで嬉しいことなど何もありません.
そこで,改善をすることにしました.
プログラマの3大美徳は,'(怠惰 短気 傲慢)
Emacsには大きな特徴があります.
それは,Emacs自身が,Emacsで動くEmacs Lispで実装されているという事です.
最低限の所をC言語で実装し,他を動的実行言語で実装することで,大きな柔軟性を手に入れています.
さらに,全てのキーバインドには関数を割り当てられます.
つまり,単語関連の機能を自作してしまえば,自分の思い通りの単語移動が出来るという事です.
さて,この機能を実現するのには,一体何が必要なのか. まずこれを考えてみる.
単語の区切りを判別する 区切りまで{移動,削除}する.判別する関数がこれです.
(defun div-symbolword-forward (currstr nextstr)
"単語を分けるか?"
(let ((currtype (unicode-block-type currstr))
(nexttype (unicode-block-type nextstr)))
(cond ((eq nexttype 'space) nil);次が空白の時は単語を分けない
((not (equal-syntax currstr nextstr)) t);違う意味の文字なら分ける
((and
(not (or
(cl-find currtype *latin*)
(cl-find nexttype *latin*)));ラテン文字以外で,
(not (eq currtype nexttype)))
t);Unicode的に違う文字であるなら分ける
((and;自分が小文字で,次が大文字である時分ける
(eq currtype 'downcase)
(eq nexttype 'upcase))
t))))
lispの高い表現力が,
極めて短いコードで定義を示すことに役だっています.
ここで紹介しておくと,lispにはcond式というものがあり,
(cond ((exp1) t)
((exp2) nil)
((exp3) t))
(or (exp1)
(and (not (exp2))
(exp3)))
上と下の式は等価なものとなっています.
(defun div-symbolword-forward-and (currstr nextstr)
"単語を分けるか?"
(let ((currtype (unicode-block-type currstr))
(nexttype (unicode-block-type nextstr)))
(and (not (eq nexttype 'space));次が空白の時は単語を分けない
(or (not (equal-syntax currstr nextstr));違う意味の文字なら分ける
(and (not (or
(cl-find currtype *latin*)
(cl-find nexttype *latin*)));ラテン文字以外で,
(not (eq currtype nexttype)));Unicode的に違う文字であるなら分ける
(and;自分が小文字で,次が大文字である時分ける
(eq currtype 'downcase)
(eq nexttype 'upcase))))))
cond式を使ったものに比べると,
だいぶ分かり辛くなっていますね…
(lisperによってはこっちのほうが良いと言うかもしれません,実際,私はこっちを使っています.)
condは,式が上から評価されてるのを分かり易くする働きがあります.
(defun kill-symbolword ()
(interactive)
(c-hungry-delete-forward)
(kill-forward-chars (kill-symbolword-size (get-str-from-buffer) 1)))
(defun kill-symbolword-size (curr num)
(let ((next (get-str-from-buffer-dif num)))
(if (not (div-symbolword-forward curr next))
(kill-symbolword-size next (incf num))
num)))