Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

タブ文字と breakindentopt=list:-1 組み合わせ時のインデント量 #1398

Open
iranoan opened this issue Oct 14, 2022 · 5 comments

Comments

@iranoan
Copy link

iranoan commented Oct 14, 2022

質問の内容

set breakindentopt=list:-1

とした時、折返し行のインデント量は、タブ文字が常に1として計算されます

これは意図してこの様になっているのでしょうか?

再現動画

breakindentoption
上動画は GVim を使っていますが、下記設定ファイルのコメントに有るように端末でも再現します
また set expandtab を使っていませんが、使った場合の自動整形は tabstop に応じた個数だけスペースが入力されるので、strwidth() ではなく strdisplaywidth() 相当でインデントされたほうが対応を考えると自然な気がします

~/.vim/vimrc

filetype plugin on
set autoindent
set formatoptions+=n
set breakindent
set breakindentopt+=list:-1
set textwidth=40
" 下記は幅指定目的で GVim を使い、動画で違いをわかりやすくする指定で再現自体には関係しない
set background=dark
colorscheme desert
set guioptions+=M
set guioptions-=T
set guioptions-=m
set list listchars=tab:\I-,space:␣,eol:$
set number
set columns=40 lines=8
augroup GUIVIM
	autocmd!
	autocmd VimEnter,GUIEnter * ++nested set columns=40 lines=8
augroup END

Vimのバージョン

$ vim --version
VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Sep 13 2022 09:35:02)
適用済パッチ: 1-3995, 4563, 4646, 4774, 4895, 4899, 4901, 4919
Modified by team+vim@tracker.debian.org
Compiled by team+vim@tracker.debian.org
Huge 版 with GTK3 GUI. 機能の一覧 有効(+)/無効(-)

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

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 22.04.1 LTS
Release: 22.04
Codename: jammy
$ uname -a
Linux xxxxxxx 5.15.0-50-generic #56-Ubuntu SMP Tue Sep 20 13:23:26 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

@koron
Copy link
Member

koron commented Oct 15, 2022

9.0.0752 で再現

image

  • 上側: formatlistpat にマッチする時、タブを含むインデントは物理文字数で適用される(タブは1セルとカウントされる
  • 下側: formatlistpat にマッチしない時、タブを含むインデントが見た目通りに適用される

こんな感じの矛盾があるっぽい。なんでこうなってるのかは不明。


補足:

breakindent は warp された行の先頭に見た目上のインデントを追加する。

breakindentopt はその動作をカスタマイズするためのオプション。

breakindentoptlist:-1 という値は、インデント量の判定に formatlistpat でマッチした物理的な長さを使ってる。

一方で breakindent 自身は、先行する空白文字を別口でインデントとするらしい。
そしてその場合の長さは物理的なものではなく、見た目的なものとなっている。

この違いが不自然さを生じていると考えられる。

@koron
Copy link
Member

koron commented Oct 16, 2022

先行する空白をインデントと認識している箇所。

https://github.com/vim/vim/blob/db4c94788ad70118fa1ccc5fbc821757350ac771/src/indent.c#L978-L979

コメントを見ると、見た目(cell)で取れることがわかる。

https://github.com/vim/vim/blob/db4c94788ad70118fa1ccc5fbc821757350ac771/src/indent.c#L430-L435

つまり prev_indent にインデント幅が見た目(cellサイズ)で入ることがわかる。

その後 formatlistpat が利用でき、かつマッチする際に prev_indent が上書きされる。
この時は見た目は考慮せず純粋にマッチした文字数に上書きされている。

https://github.com/vim/vim/blob/db4c94788ad70118fa1ccc5fbc821757350ac771/src/indent.c#L986-L1001

@koron
Copy link
Member

koron commented Oct 16, 2022

prev_indent = (*regmatch.endp - *regmatch.startp); の箇所で
linetabsize_str()*regmatch.endp[0] = NUL して
regmatch.startup[0] (もしくは *regmatch.startup) を渡せばよいはず。

ただ漫然と endp[0] を書き替えて良いとも思えないので、
呼び出し前に退避して呼び出し後に復帰する
もしくは save & free するみたいなことが要りそうね。

@koron
Copy link
Member

koron commented Oct 16, 2022

やる気が切れたので僕はいったんここまで。

@iranoan
Copy link
Author

iranoan commented Oct 16, 2022

色々調べていただきありがとうございました
環境依存でないことが分かっただけでも助かります

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

No branches or pull requests

2 participants