getbufinfo() で得られる lnum の意味を知りたい #993

Open
thinca opened this Issue Dec 4, 2016 · 11 comments

Projects

None yet

3 participants

@thinca
Member
thinca commented Dec 4, 2016

質問・報告の内容

getbufinfo() で得られる情報の中に lnum があります。help には以下のように書かれています。

lnum            current line number in buffer.

バッファでの現在の行番号…ちょっと意味がわかりません。
バッファ全体の行数というわけでも、カーソルがある行というわけでもなさそうでした。

$ vim -u NONE -i NONE -N
i<CR><CR><CR><Esc>  (適当に改行を入力)
:echo getbufinfo('%')[0].lnum
1
↑バッファの行数も、カーソルがある行も 4

この lnum は一体何を表しているのでしょうか? わかる方いたら教えて頂けると助かります。
Vim のソースコードもチラ見しましたが、Vim 力が低すぎてわかりませんでした…。

Vimのバージョン

8.0.0124

OSの種類/ディストリ/バージョン

  • Gentoo Linux 64bit
@thinca thinca added the kind/question label Dec 4, 2016
@h-east
Member
h-east commented Dec 4, 2016

4回タグジャンプすれば分かる気がします。

:tags
  # TO tag         FROM line  in file/text
  1  1 f_getbufinfo        1  evalfunc.c
  2  1 get_buffer_info  4070  evalfunc.c
  3  1 buflist_findlnum  3976  evalfunc.c
  4  1 buflist_findfpos  2964  return buflist_findfpos(buf)->lnum;

buflist_findfpos()の関数ヘッダコメント

/*
 * Find the position (lnum and col) for the buffer 'buf' for the current
 * window.
 * Returns a pointer to no_position if no position is found.
 */

もしかして、この情報がおかしいということでしょうか?

@thinca
Member
thinca commented Dec 5, 2016

私の英語の読解が間違っていなければ、カレントウィンドウのバッファのポジション(?)のように見えるんですが、動作例に挙げたように、見た限りだとカーソルの位置と言うわけではなさそうで、混乱しています。
そもそも getbufinfo() はカレントバッファに限らず全てのバッファの情報を得るものなので、なぜこの処理で「カレントウィンドウ」が出てくるのかがよくわかりませんでした。
ご存じでしたら解説頂けると助かります。

@k-takata
Member
k-takata commented Dec 5, 2016

getbufinfo() で取れる情報と、:ls で表示される情報を見比べてみると、カレントバッファ以外は lnum として同じ情報が入っているように見えます。
となると、lnum はバッファを切り替えた等のタイミングで更新されるのかもしれません。
で、:ls の実装である buffer.c / buflist_list() を見てみると、行番号を表示する部分はこんな風になっています。

	vim_snprintf((char *)IObuff + len, (size_t)(IOSIZE - len),
		_("line %ld"), buf == curbuf ? curwin->w_cursor.lnum
					       : (long)buflist_findlnum(buf));

カレントバッファの場合は curwin->w_cursor.lnum から行番号を持ってくるようにした方が良いのかもしれません。

@thinca
Member
thinca commented Dec 5, 2016

@k-takata 調査ありがとうございます!

getbufinfo() で取れる情報と、:ls で表示される情報を見比べてみると、カレントバッファ以外は lnum として同じ情報が入っているように見えます。

実際の動作を色々試してみているんですが、どうも同じじゃない場合もあるみたいです。

$ vim -u NONE -i NONE -N
10o<Esc>  (適当に行を作る。10行追加されてカーソルは11行目に来る)
:vnew
:ls!
  1 #a + "[無名]"                       行 1
  2 %a   "[無名]"                       行 1

:echo map(getbufinfo(), {i, info -> [info.bufnr, info.lnum]})
[[1, 1], [2, 0]]

カレントバッファ(bufnr=2) の行が、1 と 0 で違っています。

lnum はバッファを切り替えた等のタイミングで更新されるのかもしれません。

↑の例だと、更新されているなら bufnr=1 の行は 11 になりそうですが、そうなっていません。

上の続きで、再び bufnr=1 のウィンドウに戻ってそれぞれ確認してみると、

<C-w>w  (前のバッファが表示されているウィンドウに戻る)
:ls!
  1 %a + "[無名]"                       行 11
  2  a   "[無名]"                       行 0

:echo map(getbufinfo(), {i, info -> [info.bufnr, info.lnum]})
[[1, 1], [2, 0]]

getbufinfo() の結果は変わりませんが、:ls! の結果は変わってしまいます。

@k-takata
Member
k-takata commented Dec 5, 2016

カレントバッファ(bufnr=2) の行が、1 と 0 で違っています。

カレントバッファの行が違っているのは想定どおりです。

lnum はバッファを切り替えた等のタイミングで更新されるのかもしれません。

↑の例だと、更新されているなら bufnr=1 の行は 11 になりそうですが、そうなっていません。

:set hidden してから :e foo などとして bufnr=1 を隠してしまうと、info.lnum は 11 になりますね。
表示されなくなるとかそんな感じのタイミングで更新されるんじゃないですか?
lnum が 0 になるのは、ファイルサイズ 0 かどうかが影響してそう?

@k-takata
Member
k-takata commented Dec 5, 2016

こんな風にすれば、:ls と同じ結果になるんじゃないの?と思うわけですが試してはいません。
直すべきなのかどうかもよく分かりません。

--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -3979,7 +3979,8 @@ get_buffer_info(buf_T *buf)
     dict_add_nr_str(dict, "bufnr", buf->b_fnum, NULL);
     dict_add_nr_str(dict, "name", 0L,
 	    buf->b_ffname != NULL ? buf->b_ffname : (char_u *)"");
-    dict_add_nr_str(dict, "lnum", buflist_findlnum(buf), NULL);
+    dict_add_nr_str(dict, "lnum", buf == curbuf ? curwin->w_cursor.lnum
+					: buflist_findlnum(buf), NULL);
     dict_add_nr_str(dict, "loaded", buf->b_ml.ml_mfp != NULL, NULL);
     dict_add_nr_str(dict, "listed", buf->b_p_bl, NULL);
     dict_add_nr_str(dict, "changed", bufIsChanged(buf), NULL);
@thinca
Member
thinca commented Dec 6, 2016

@k-takata 色々と調査ありがとうございます!

カレントバッファの行が違っているのは想定どおりです。

完全に発言を見落としていました…すいませんすいません 🙇

表示されなくなるとかそんな感じのタイミングで更新されるんじゃないですか?
lnum が 0 になるのは、ファイルサイズ 0 かどうかが影響してそう?

確かに 1 度隠すと 11 になりますね…。挙動の法則が割と謎です。
挙動も仕様も謎なので、直すべきかどうかわからないというのは完全に同意です。


色々調べてもらって、かつ自分でも色々試して私の中で出た結論は、「何かの役に立ちそうな値ではない」ということのようです。
残念な結論ですが、「実は知ってると役に立つ便利な値」とかでないことが確認できただけでも良かったです。
この、ほぼ無意味な値については他に意見がある人もいるかもしれないですが、本 Issue の目的は意味を知りたいということだったので、本 Issue は閉じます。何か意見ある人は別途 Issue 立ててもらえると助かります。
@h-east @k-takata 改めてお二方、お付き合い頂きありがとうございました!

@thinca thinca closed this Dec 6, 2016
@h-east
Member
h-east commented Dec 8, 2016

@k-takata patch送ってみませんか?
:lsで表示されるものと同じなってないので同じにした」って言えば取り込まれると思います。知らんけど😄

thincaさんが言うように「便利な値」ではないかもしれないのは同意です。
それはそれとして、「:lsで表示されてる行番号です」って説明できるだけでもマシかなぁと思いました。

@k-takata
Member
k-takata commented Dec 8, 2016

すんません。あんまりやる気が起きません。コンパイルすら通してないし、テストを書く気は0。
代わりに投げてもらってもかまいません。

@k-takata
Member
k-takata commented Jan 3, 2017

パッチ投げました。
https://groups.google.com/d/topic/vim_dev/pYKP30rBu80/discussion
いったんreopenしておきます。

@k-takata k-takata reopened this Jan 3, 2017
@k-takata
Member
k-takata commented Jan 6, 2017

8.0.0143 で直りました。
https://groups.google.com/d/topic/vim_dev/uFsBC6iVoiE/discussion
誰かテスト書きませんか? 書くのは src/testdir/test_bufwintabinfo.vim がいいでしょうとのこと。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment