akinomyoga / ble.sh

Bash Line Editor―a line editor written in pure Bash with syntax highlighting, auto suggestions, vim modes, etc. for Bash interactive sessions.
BSD 3-Clause "New" or "Revised" License
2.6k stars 82 forks source link

[Vim-mode] ヴィジュアルモードを開始したとき,単語単位のオブジェクトが正しく選択できない #16

Closed cmplstofB closed 5 years ago

cmplstofB commented 6 years ago

Commit ID: b7291a7 Version of GNU Bash: 4.4.12

ノーマルモードでvを入力した後にawなどとすると単語単位で選択することができる筈ですが,できなくなっています。 参考: https://vim-jp.org/vimdoc-ja/motion.html#v_aw

$ echo 'fo@bar'
# vawを送信
$ echo 'foobar'
          ^^^^

波下線部が選択されます。本来はfoobar全体が選択されるべきです。 同じような挙動は単語を単位とする全てのオブジェクトで起こっているようです。

akinomyoga commented 6 years ago

すみません。この振る舞いに関しては手元では適当に直してみましたが、他にもテストケースを作って調べると沢山 vim と違う動作が判明したので後で纏めて修正します。

(vim の help の説明は厳密には書いていないので、様々な個別の状況でどういう動作をすれば良いのかが全部試さないと分からないんですよね。今の所分かっている注意点(テストのチェックポイント)は「omap と xmap で動作が微妙に変わる事」「引数を与えた時の振る舞い」「xmap でカーソル位置が選択範囲の他の端点の前にあるか後にあるか同じ位置にあるかで振る舞いが変わる事」など…)

akinomyoga commented 6 years ago
cmplstofB commented 6 years ago

確認いたしました。ありがとうございます。

以下,本筋と関係ないです。 Vimの仕様の曖昧性は少なくとも日本ではあまり議論されていないようですね。Vimを仕様として定めようという意見[\@kedama17 2017]はあるにはありますが,その後音沙汰ありませんし。僕個人の経験においては,大半の状況では手引きを見れば解決するので,あまり気にしていませんでしたが,動作を再現実装しようとする段階では現状ではあまり褒められた精度ではないのですね……。

仕様としてのVim - Qiita - @kedama17

akinomyoga commented 6 years ago

仕様として定めるというのは楽しそうですね。ble.sh を実装する上で分かった細かい振る舞い (テキストオブジェクト以外にも沢山あります) について折角だから説明書に記述できたら良いな、ということを妄想しますがそれをやり始めるとどう考えても物凄く時間がかかるので現実的には難しいです。

テキストオブジェクトの不思議な動作を考えると、他の模倣実装がどのレベルで Vim に準拠しているのかはまちまちなのだろうという気がします…。仕様・規格として定めるとしたら未定義の動作・未規定の動作などを持ち込んで誤魔化すか Vim 自体の細かい動作に対しても全般的に見直しが迫られるかのどちらかでしょうね。

akinomyoga commented 6 years ago

一応 vi は POSIX で規格化されているので、POSIX.1-2017 vi を見に行ったら

Historically, vi commands that used bigwords, words, paragraphs, and sentences as objects treated groups of empty lines, or lines that contained only \<blank> characters, inconsistently. Some commands treated them as a single entity, while others treated each line separately. For example, the w, W, and B commands treated groups of empty lines as individual words; that is, the command would move the cursor to each new empty line. The e and E commands treated groups of empty lines as a single word; that is, the first use would move past the group of lines. The b command would just beep at the user, or if done from the start of the line as a motion command, fail in unexpected ways. If the lines contained only (or ended with) characters, the w and W commands would just beep at the user, the E and e commands would treat the group as a single word, and the B and b commands would treat the lines as individual words. For consistency and simplicity of specification, POSIX.1-2017 requires that all vi commands treat groups of empty or blank lines as a single entity, and that movement through lines ending with characters be consistent with other movements.

と書いてありますね… (如何に inconsistent なのかの長い説明が…)。結局 POSIX vi では空行と空白行の取り扱いに関しては単純化しているようです。一方で ble.sh で調べている限りは Vim の振る舞いは historical な (つまり inconsistent な) 振る舞いですね。

cmplstofB commented 6 years ago

VimはPOSIXの一部仕様を意図的に無視する方針のようですね[vim 2005]。しかし挙げられている非互換な項目に,テキストオブジェクトの空白文字に対する振舞いについてのものはありません。(Vimの開発陣がこれらの振舞いについて気が付いていないなんてことはありえないと思うのですが……)

他の模倣実装がどのレベルで Vim に準拠しているのか

NeoVimが一番忠実にVimの挙動を再現しようとしているのかな,とも思いました。が,そもそもNeoVimはVimをフルスクラッチで再実装するのではなく,Vimのソースコードをリファクタリングするというプロジェクト指針ですので,本質的にVimと同じですね。つまりNeoVimを開発するにあたって,あまりVimの厳密な仕様を考慮する必要はないのでしょう。「中枢部分はVimのものを利用する」と明記してありますし。

POSIX準拠 - Vim日本語ドキュメント

akinomyoga commented 6 years ago

ありがとうございます! POSIX準拠についてもドキュメントに書かれているのですね。「テストを行いました」と言っていますが、たぶん POSIX のすべての記述内容に関して真面目に検証したのではなくて、テストを作りやすい項目の確認だけに留まっているのではないかという気がします。

POSIX 2004 でも該当部分の記述は同じですね…。POSIX を読み違えていなければ、少なくとも motion w は確実に all vi commands treat groups of empty or blank lines as a single entity とは違う動きをするような… (テキストオブジェクト iw/aw 自体は POSIX にはありませんが、内部的には w/e で使われているのと同じ関数を (変なやり方で) 組み合わせて実装しているので、より凶悪な振る舞いです)。

Vim のソースコードをリファクタリングしたくなる気持ち、物凄く分かります…

cmplstofB commented 6 years ago

使わないテキストエディタの模倣実装にこんなに労力を割けさしてしまって,ほんと,すいません。ありがとうございます。

(NeoVimでも当該部分に関しては同じコードのようですね。https://github.com/neovim/neovim/blob/master/src/nvim/search.c​ )

ところで,これは全く無関係な話題ですが,@akinomyoga 様が書かれているmemo.txtは,Emacsのorgモードで書かれているんでしょうか?

akinomyoga commented 6 years ago

こちらの趣味で恐縮させてしまっているようですみません。お気になさらないで下さい。何れは直さなければならなくなる (もし ble.sh を使う人が増えればですが) と思うので、できるだけ一回で片を付けたいのでした。少しずつ修正すると、その都度テキストオブジェクトの処理の構造を再考しなければならず面倒なので (そしてテキストオブジェクトの謎には今後できるだけ関わりたくないので)、一回で全容を把握して完全撃退したいということなのでした。

(NeoVimでも当該部分に関しては同じコードのようですね。

なるほど。NeoVim もテキストオブジェクトには近づきたくないのですかね…

memo.txtは,Emacsのorgモードで書かれているんでしょうか?

memo.txt はすみません、上等なものは何も使っていなくて単に text-mode でやってます。

昔は、色々の開発ログや研究ログなどを HTML で書いたり Markdown にして見たり Wiki にして見たりなど試行錯誤したのですが、結局ただのテキストに落ち着いたのでした。どうせ端末の中でしか見ないので端末の中での見易さが重視で、そうするとマークアップ言語だと制限や面倒があります (Markdown はそれが目的で設計されたのだとは思うのですが、やはり面倒になりまして…)。体裁など考えず思考をただただ書きなぐるのに集中したいのでした。また昔は種類ごとにファイルを分けたりしていたのですが、isearch を使っていると全て一つのファイルに入れる方が都合が良いのですよね。後、種類に関係なく時系列に線形で記録する方が、後々まで整理する必要もないし却って後で探しやすいということにも気づいたのでした。

ただ Emacs のバインディングは (モードに関係なく) 弄っていて、memo.txt に特に関係のありそうなのは、例えば C-f5 で日付挿入で、M-f M-w で現在の単語の選択で、選択状態で C-s / C-r で選択内容を後方・前方に検索、C-prior / C-next で前・次の FF (^L) に移動など…。基本的に大きな移動はページ移動 prior / next か isearch C-s / C-r でやってますね。あとは、端末はいつも全画面にしてるので広い (180x70 ぐらい) です。

cmplstofB commented 6 years ago

memo.txtには,僕ではとても与りきれないような沢山の有益な情報が詰まっていて,日々勉強させていただいております(問題が発生したときの対処の手順など)。memo.txtを構文強調で着色できれば更に素晴らしくなるなと思って,構文の種類を質問したのです(Emacsでのメモならばすなわちorgモードかな,と勝手に想像していまして。どうでもいいですが,なぜかVimの組み込みの構文強調にはorgモード用のものが存在しないんです。かなり有名なLML方言だと思うんですが)。 あと^Lはそういう意味だったんですね。というか,言われてから調べると,もともとは改頁用の文字だったそうで(今更ですよね……無知で恥かしい),やっと,対話型シェルの多くがCtrl+Lにclear(1)コマンド相当の機能を束縛している理由が解りました。

メモをどういった形式で書くかというのは,結構重要な要素の割に,個人の感性にかなり左右される部分があるせいで決定打となる記述形式がないのが現状ですよね……。最近はAsciiDocなんかもいいかなと僕としては思っています。公式がUML図やLaTeX形式での数式表現をサポートしていたり,XML形式であるDocBookと互換性がある点が気に入りました。欠点は,プレーンテキストとして見たときに(つまり端末上などで),可読であるとは言えかなり煩雑なマークアップが目立つという点です。

akinomyoga commented 6 years ago

memo.txtには,

いえ、適当に思考を書き散らしているだけなのでそう価値のあるものではないはずなのです…。元々人に読ませるためのものではないので (そして問題対処の部分は自分が読み返すことすら想定していなかったり…)、冗長だったり、そもそも日本語になっていなかったり、検証していないいい加減なことが書かれていたり、その辺りは留意していただければ幸いです。

問題が発生したときの対処の手順など

あと必ずしも上から下に順番に書いている訳ではない、ということも…。

memo.txtを構文強調で

大した構文はないですし参考になるか分かりませんが、一応気分は書いておきます。

取り敢えず (1) 入れ子構造はインデントで表現する (2) 箇条書きは ``` * 普通の箇条書き - (気分的に)小さな箇条書き + 同上 x 欠点・問題・バグ o 利点・チェック済み 1. リスト。手順など (and 的な関係) に使う傾向 a. リスト。選択肢など (or 的な関係) に使う傾向 ``` (3) 基本的にブロックは書きながらではなくて書き終わった後に囲んでいます。 ``` > 引用。 > どこかからのコピーペーストなど % 取り消し。 % 思考の前提が間違っていたなど。大きな×で消す気持ち。 | その他のブロック。書き散らした後で全体を四角で囲む気持ち。 |
的な使い方だったり、 | コードブロックの気分で使うこともある。 # コメント。 # どうでも良いこと。余談 ```

LML なら構文強調の拡張を自分で書いても良いのかもしれませんね。ただ、memo.txt に対して構文強調を作ったとしても、余り厳密にやっていないのでただのテキストが偶々構文になっているなどのトラブル、などありそうです…。

あと^Lはそういう意味だったんですね。

あ、はいそうなのです。知っていても大して訳には立たないですが、そういう色々の裏が見えてくると楽しいですよね。

メモをどういった形式で書くかというのは,

これは難しいですよね。個人の性格やメモの用途にもよりそうです。僕の場合は、下手に構文が定義されているとその構文を使って整える事に凝ってしまって、肝心の思考の方が進まなくなって駄目駄目なのです。果ては構文を作ることにまで凝りだしたり… (akinomyoga/aghakinomyoga/lwiki などはその副産物…)。そういう訳でテキストファイル (検証手段なし) にまで退化したのでした。あと、試行錯誤は memo.txt の類でやりますが、特に記録しておきたいことなどは今でも HTML (+ akinomyoga/agh/latex) に書いたりします。

akinomyoga commented 6 years ago
akinomyoga commented 5 years ago

本当はもっと沢山テストケースを作って試そうと考えていましたが、もう疲れたのでまたいつか試すことにします… (作るとまた振る舞いの違いが明らかになって修正しなければならなくなる…)。

※既知の違い: ビジュアルモードで現在位置が1行目の2文字目でありそれが開始点よりも前にある時、aw もしくは iw を実行すると Vim では内部的に検索失敗してベルを鳴らし、フォールバックとして現在位置を先頭に移動します。これは Vim の欠陥の様な気がするので、ble.sh では内部的な検索失敗は起こさず、ベルを鳴らさずに先頭に移動します。

問題がなければ後で閉じますね

cmplstofB commented 5 years ago

ありがとうございます。 正直なところ,Vimを完全に使いこなしている訳ではないのですが,僕からするとVimと同じ操作感が得られました。

akinomyoga commented 5 years ago

ありがとうございます! 取り敢えず閉じますね