deno-denops-std icon indicating copy to clipboard operation
deno-denops-std copied to clipboard

option: "local to tab page" options has `getBuffer()` method

Open Milly opened this issue 1 year ago • 5 comments

Describe the bug

Related #267.

"local to tab page" options has getBuffer() method. There is also getWindow() etc. methods.

import { cmdheight } from "jsr:@denops/std/option";

declare const denops: Denops;

await cmdheight.getBuffer(denops, 1);

Currently (Vim/Nvim target for v7) there are only these options:

  • 'cmdheight'
						*'cmdheight'* *'ch'*
'cmdheight' 'ch'	number	(default 1)
			global or local to tab page
	Number of screen lines to use for the command-line.  A larger value
	helps avoiding |hit-enter| prompts.
	The value of this option is stored with the tab page, so that each tab
	page can have a different value.

Expected behavior

  • No getBuffer() etc. methods are available.
  • No setWindow() etc. methods are available.
  • Add getTabPage() etc. methods.

Milly avatar Aug 28 '24 09:08 Milly

I'm working on this.

Milly avatar Aug 28 '24 11:08 Milly

getTabPage() etc. methods cannot be implemented.

getBuffer() method uses getbufvar(), which allows to get buffer options:

getbufvar({buf}, {varname} [, {def}])				*getbufvar()*
		The result is the value of option or local buffer variable
		{varname} in buffer {buf}.  Note that the name without "b:"
		must be used.
		The {varname} argument is a string.
		When {varname} is empty returns a |Dictionary| with all the
		buffer-local variables.
		When {varname} is equal to "&" returns a |Dictionary| with all
		the buffer-local options.
		Otherwise, when {varname} starts with "&" returns the value of
		a buffer-local option.
		This also works for a global or buffer-local option, but it
		doesn't work for a global variable, window-local variable or
		window-local option.

But gettabvar() does not provide to get tab page options:

gettabvar({tabnr}, {varname} [, {def}])				*gettabvar()*
		Get the value of a tab-local variable {varname} in tab page
		{tabnr}. |t:var|
		Tabs are numbered starting with one.
		The {varname} argument is a string.  When {varname} is empty a
		dictionary with all tab-local variables is returned.
		Note that the name without "t:" must be used.
		When the tab or variable doesn't exist {def} or an empty
		string is returned, there is no error message.

Also same issues with settabvar().

Milly avatar Aug 29 '24 02:08 Milly

Not tested but I think we can use win_getid, win_execute like

function! s:gettabopt(tabnr, varname, def) abort
  let l:winid = win_getid(1, a:tabnr)
  let l:result = win_execute(l:winid, printf('echo &l:%s', a:varname))
  return empty(l:result) ? a:def : l:result
endfunction

function! s:settabopt(tabnr, varname, val) abort
  let l:winid = win_getid(1, a:tabnr)
  call win_execute(l:winid, printf('let &l:%s = %s', a:varname, string(a:val)))
endfunction

lambdalisue avatar Sep 06 '24 15:09 lambdalisue

Not tested but I think we can use win_getid, win_execute like

These not work. It always returns the value of the current tab page. Currently Vim does not seem to have a way to get/set local tab options other than actually switching tab pages.

The following works:

function! s:gettabopt(tabnr, varname) abort
  let l:winid_save = win_getid()
  let l:lazyredraw_save = &lazyredraw
  try
    set lazyredraw
    execute a:tabnr 'tabnext'
    let l:result = a:varname->printf('&l:%s')->eval()
    return l:result
  finally
    call win_gotoid(l:winid_save)
    let &lazyredraw = l:lazyredraw_save
  endtry
endfunction

But has side effects (We can add more redundant state saving code):

setglobal cmdheight=1
tabnew
setlocal cmdheight=5
tabnew
1tabnext
echo tabpagenr('#')
" -> 3
echo s:gettabopt(2, 'cmdheight')
" -> 5
echo tabpagenr('#')
" -> 2

And causes an update of the GUI screen. (CUI screen updates seem to be blocked by 'lazyredraw'.)

Milly avatar Sep 16 '24 17:09 Milly

https://github.com/vim/vim/pull/15713 fixes this.

Milly avatar Sep 21 '24 08:09 Milly