UIAttach, UIDetach

doc: ginit.vim, gvimrc
fix #3656
This commit is contained in:
Justin M. Keyes 2019-09-11 18:44:20 -07:00
parent e9cf515888
commit 6dd56d0902
14 changed files with 85 additions and 121 deletions

View File

@ -280,7 +280,7 @@ Name triggered by ~
Startup and exit
|VimEnter| after doing all the startup stuff
|UIAttach| after a new UI attaches
|UIAttach| after a UI attaches
|UIDetach| after a UI detaches
|TermResponse| after the terminal response to t_RV is received
|QuitPre| when using `:quit`, before deciding whether to exit
@ -805,13 +805,16 @@ FuncUndefined When a user function is used but it isn't
NOTE: When writing Vim scripts a better
alternative is to use an autoloaded function.
See |autoload-functions|.
{Nvim} *UIAttach*
UIAttach After a new UI connects to nvim and successfully
calls |nvim_ui_attach|. Sets chan in |v:event| with
the channel id or 0 if using the internal UI.
{Nvim} *UIDetach*
UIDetach After a UI detaches from nvim. Sets chan in |v:event|
with the channel id or 0 if using the internal UI.
*UIAttach*
UIAttach After a UI connects via |nvim_ui_attach()|,
after VimEnter. Can be used for GUI-specific
configuration.
Sets these |v:event| keys:
chan
*UIDetach*
UIDetach After a UI detaches from Nvim.
Sets these |v:event| keys:
chan
*InsertChange*
InsertChange When typing <Insert> while in Insert or
Replace mode. The |v:insertmode| variable

View File

@ -28,7 +28,7 @@ Environment Variables ~
Events ~
*EncodingChanged* Never fired; 'encoding' is always "utf-8".
*FileEncoding* Never fired; equivalent to |EncodingChanged|.
*GUIEnter* Never fired; Use |UIAttach| instead.
*GUIEnter* Never fired; use |UIAttach| instead.
*GUIFailed* Never fired.
Keycodes ~

View File

@ -1567,6 +1567,7 @@ v:event Dictionary of event data for the current |autocommand|. Valid
abort Whether the event triggered during
an aborting condition (e.g. |c_Esc| or
|c_CTRL-C| for |CmdlineLeave|).
chan |channel-id| or 0 for "internal".
cmdlevel Level of cmdline.
cmdtype Type of cmdline, |cmdline-char|.
cwd Current working directory.

View File

@ -4,7 +4,7 @@
VIM REFERENCE MANUAL by Bram Moolenaar
Vim's Graphical User Interface *gui* *GUI*
Nvim Graphical User Interface *gui* *GUI*
Type |gO| to see the table of contents.
@ -12,30 +12,11 @@ Vim's Graphical User Interface *gui* *GUI*
Starting the GUI *gui-start* *E229* *E233*
*ginit.vim* *gui-init* *gvimrc* *$MYGVIMRC*
The gvimrc file is where GUI-specific startup commands should be placed. It
is always sourced after the |init.vim| file. If you have one then the
$MYGVIMRC environment variable has its name.
For GUI-specific configuration Nvim provides the |UIAttach| event. This
happens after other |initialization|s, like reading your vimrc file.
When the GUI starts up initializations are carried out, in this order:
- If the system menu file exists, it is sourced. The name of this file is
normally "$VIMRUNTIME/menu.vim". You can check this with ":version". Also
see |$VIMRUNTIME|. To skip loading the system menu include 'M' in
'guioptions'. *buffers-menu* *no_buffers_menu*
The system menu file includes a "Buffers" menu. If you don't want this, set
the "no_buffers_menu" variable in your init.vim (not ginit.vim!): >
:let no_buffers_menu = 1
< NOTE: Switching on syntax highlighting also loads the menu file, thus
disabling the Buffers menu must be done before ":syntax on".
The path names are truncated to 35 characters. You can truncate them at a
different length, for example 50, like this: >
:let bmenu_max_pathlen = 50
All this happens AFTER the normal Vim initializations, like reading your
vimrc file. See |initialization|.
But the GUI window is only opened after all the initializations have been
carried out. If you want some commands to be executed just after opening the
GUI window, use the |GUIEnter| autocommand event. Example: >
:autocmd GUIEnter * winpos 100 50
Example: this sets "g:gui" to the value of the UI's "rgb" field: >
:autocmd UIAttach * let g:gui = filter(nvim_list_uis(),{k,v-> v.chan==v:event.chan})[0].rgb
<
*:winp* *:winpos* *E188*

View File

@ -236,35 +236,6 @@ using the terminal for something else. The "-f" argument is used here to run
the GUI in the foreground. You can also use ":gui -f".
THE GVIM STARTUP FILE
When gvim starts, it reads the gvimrc file. That's similar to the vimrc file
used when starting Vim. The gvimrc file can be used for settings and commands
that are only to be used when the GUI is going to be started. For example,
you can set the 'lines' option to set a different window size: >
:set lines=55
You don't want to do this in a terminal, since its size is fixed (except for
an xterm that supports resizing).
The gvimrc file is searched for in the same locations as the vimrc file.
Normally its name is "~/.config/nvim/ginit.vim".
The $MYGVIMRC environment variable is set to it, thus you can use this command
to edit the file, if you have one: >
:edit $MYGVIMRC
<
If for some reason you don't want to use the normal gvimrc file, you can
specify another one with the "-U" argument: >
gvim -U thisrc ...
That allows starting gvim for different kinds of editing. You could set
another font size, for example.
To completely skip reading a gvimrc file: >
gvim -U NONE ...
==============================================================================
Next chapter: |usr_32.txt| The undo tree

View File

@ -19,8 +19,6 @@
#include "nvim/highlight.h"
#include "nvim/screen.h"
#include "nvim/window.h"
#include "nvim/fileio.h"
#include "nvim/eval.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/ui.c.generated.h"
@ -59,7 +57,7 @@ void remote_ui_disconnect(uint64_t channel_id)
pmap_del(uint64_t)(connected_uis, channel_id);
xfree(ui->data);
ui->data = NULL; // Flag UI as "stopped".
ui_detach_impl(ui);
ui_detach_impl(ui, channel_id);
xfree(ui);
}
@ -170,13 +168,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height,
ui->data = data;
pmap_put(uint64_t)(connected_uis, channel_id, ui);
ui_attach_impl(ui);
dict_T *dict = get_vim_var_dict(VV_EVENT);
tv_dict_add_nr(dict, S_LEN("chan"), (long)channel_id);
tv_dict_set_keys_readonly(dict);
apply_autocmds(EVENT_UIATTACH, NULL, NULL, false, curbuf);
tv_dict_clear(dict);
ui_attach_impl(ui, channel_id);
}
/// @deprecated
@ -204,12 +196,6 @@ void nvim_ui_detach(uint64_t channel_id, Error *err)
return;
}
remote_ui_disconnect(channel_id);
dict_T *dict = get_vim_var_dict(VV_EVENT);
tv_dict_add_nr(dict, S_LEN("chan"), (long)channel_id);
tv_dict_set_keys_readonly(dict);
apply_autocmds(EVENT_UIDETACH, NULL, NULL, false, curbuf);
tv_dict_clear(dict);
}

View File

@ -7,11 +7,32 @@
#include "nvim/main.h"
#include "nvim/ui.h"
#include "nvim/aucmd.h"
#include "nvim/eval.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "aucmd.c.generated.h"
#endif
void do_autocmd_uiattach(uint64_t chanid, bool attached)
{
static bool recursive = false;
if (recursive) {
return; // disallow recursion
}
recursive = true;
dict_T *dict = get_vim_var_dict(VV_EVENT);
assert(chanid < VARNUMBER_MAX);
tv_dict_add_nr(dict, S_LEN("chan"), (varnumber_T)chanid);
tv_dict_set_keys_readonly(dict);
apply_autocmds(attached ? EVENT_UIATTACH : EVENT_UIDETACH,
NULL, NULL, false, curbuf);
tv_dict_clear(dict);
recursive = false;
}
static void focusgained_event(void **argv)
{
bool *gainedp = argv[0];
@ -38,4 +59,3 @@ static void do_autocmd_focusgained(bool gained)
NULL, NULL, false, curbuf);
recursive = false;
}

View File

@ -1,6 +1,8 @@
#ifndef NVIM_AUCMD_H
#define NVIM_AUCMD_H
#include <stdint.h>
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "aucmd.h.generated.h"
#endif

View File

@ -3111,8 +3111,6 @@ int do_source(char_u *fname, int check_other, int is_vimrc)
}
if (is_vimrc == DOSO_VIMRC) {
vimrc_found(fname_exp, (char_u *)"MYVIMRC");
} else if (is_vimrc == DOSO_GVIMRC) {
vimrc_found(fname_exp, (char_u *)"MYGVIMRC");
}
#ifdef USE_CRNL

View File

@ -7,19 +7,18 @@
typedef void (*DoInRuntimepathCB)(char_u *, void *);
/*
* flags for check_changed()
*/
#define CCGD_AW 1 /* do autowrite if buffer was changed */
#define CCGD_MULTWIN 2 /* check also when several wins for the buf */
#define CCGD_FORCEIT 4 /* ! used */
#define CCGD_ALLBUF 8 /* may write all buffers */
#define CCGD_EXCMD 16 /* may suggest using ! */
//
// flags for check_changed()
//
#define CCGD_AW 1 // do autowrite if buffer was changed
#define CCGD_MULTWIN 2 // check also when several wins for the buf
#define CCGD_FORCEIT 4 // ! used
#define CCGD_ALLBUF 8 // may write all buffers
#define CCGD_EXCMD 16 // may suggest using !
/* last argument for do_source() */
// last argument for do_source()
#define DOSO_NONE 0
#define DOSO_VIMRC 1 /* loading vimrc file */
#define DOSO_GVIMRC 2 /* loading gvimrc file */
#define DOSO_VIMRC 1 // loading vimrc file
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ex_cmds2.h.generated.h"

View File

@ -9,6 +9,7 @@
#include "nvim/vim.h"
#include "nvim/log.h"
#include "nvim/aucmd.h"
#include "nvim/ui.h"
#include "nvim/charset.h"
#include "nvim/cursor.h"
@ -268,7 +269,7 @@ void ui_busy_stop(void)
}
}
void ui_attach_impl(UI *ui)
void ui_attach_impl(UI *ui, uint64_t chanid)
{
if (ui_count == MAX_UI_COUNT) {
abort();
@ -292,9 +293,14 @@ void ui_attach_impl(UI *ui)
ui_send_all_hls(ui);
}
ui_refresh();
bool is_compositor = (ui == uis[0]);
if (!is_compositor) {
do_autocmd_uiattach(chanid, true);
}
}
void ui_detach_impl(UI *ui)
void ui_detach_impl(UI *ui, uint64_t chanid)
{
size_t shift_index = MAX_UI_COUNT;
@ -326,6 +332,8 @@ void ui_detach_impl(UI *ui)
if (!ui->ui_ext[kUIMultigrid] && !ui->ui_ext[kUIFloatDebug]) {
ui_comp_detach(ui);
}
do_autocmd_uiattach(chanid, false);
}
void ui_set_ext_option(UI *ui, UIExtension ext, bool active)

View File

@ -17,8 +17,6 @@
#include "nvim/ui_bridge.h"
#include "nvim/ugrid.h"
#include "nvim/api/private/helpers.h"
#include "nvim/fileio.h"
#include "nvim/eval.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ui_bridge.c.generated.h"
@ -87,13 +85,7 @@ UI *ui_bridge_attach(UI *ui, ui_main_fn ui_main, event_scheduler scheduler)
}
uv_mutex_unlock(&rv->mutex);
ui_attach_impl(&rv->bridge);
dict_T *dict = get_vim_var_dict(VV_EVENT);
tv_dict_add_nr(dict, S_LEN("chan"), 0);
tv_dict_set_keys_readonly(dict);
apply_autocmds(EVENT_UIATTACH, NULL, NULL, false, curbuf);
tv_dict_clear(dict);
ui_attach_impl(&rv->bridge, 0);
return &rv->bridge;
}
@ -115,13 +107,7 @@ static void ui_bridge_stop(UI *b)
{
// Detach bridge first, so that "stop" is the last event the TUI loop
// receives from the main thread. #8041
ui_detach_impl(b);
dict_T *dict = get_vim_var_dict(VV_EVENT);
tv_dict_add_nr(dict, S_LEN("chan"), 0);
tv_dict_set_keys_readonly(dict);
apply_autocmds(EVENT_UIDETACH, NULL, NULL, false, curbuf);
tv_dict_clear(dict);
ui_detach_impl(b, 0);
UIBridgeData *bridge = (UIBridgeData *)b;
bool stopped = bridge->stopped = false;

View File

@ -83,7 +83,7 @@ void ui_comp_init(void)
kv_push(layers, &default_grid);
curgrid = &default_grid;
ui_attach_impl(compositor);
ui_attach_impl(compositor, 0);
}
void ui_comp_syn_init(void)

View File

@ -6,7 +6,6 @@ local eval = helpers.eval
local meths = helpers.meths
local request = helpers.request
local pcall_err = helpers.pcall_err
local command = helpers.command
describe('nvim_ui_attach()', function()
before_each(function()
@ -35,13 +34,23 @@ describe('nvim_ui_attach()', function()
eq('UI already attached to channel: 1',
pcall_err(request, 'nvim_ui_attach', 40, 10, { rgb=false }))
end)
it('autocmds UIAttach/Detach set v:event', function()
local screen = Screen.new()
command('autocmd UIAttach * :let g:ui_attach_v_event = deepcopy(v:event)')
command('autocmd UIDetach * :let g:ui_detach_v_event = deepcopy(v:event)')
screen:attach()
assert.same({chan=1}, eval('g:ui_attach_v_event'))
screen:detach()
assert.same({chan=1}, eval('g:ui_detach_v_event'))
end)
end)
it('autocmds UIAttach/UIDetach', function()
clear{args={
'--cmd', 'let g:evs = []',
'--cmd', 'autocmd UIAttach * :call add(g:evs, "UIAttach") | let g:ui_attach_ev = deepcopy(v:event)',
'--cmd', 'autocmd UIDetach * :call add(g:evs, "UIDetach") | let g:ui_detach_ev = deepcopy(v:event)',
'--cmd', 'autocmd VimEnter * :call add(g:evs, "VimEnter")',
}}
local screen = Screen.new()
screen:attach()
eq({chan=1}, eval('g:ui_attach_ev'))
screen:detach()
eq({chan=1}, eval('g:ui_detach_ev'))
eq({
'VimEnter',
'UIAttach',
'UIDetach',
}, eval('g:evs'))
end)