diff --git a/etc/soft/nvim/+plugins/vim-floaterm/README.md b/etc/soft/nvim/+plugins/vim-floaterm/README.md index 8dcd120..fd8d1a7 100644 --- a/etc/soft/nvim/+plugins/vim-floaterm/README.md +++ b/etc/soft/nvim/+plugins/vim-floaterm/README.md @@ -1,57 +1,48 @@ -![CI](https://github.com/voldikss/vim-floaterm/workflows/CI/badge.svg) - -【[Introduction in Chinese|中文文档](https://zhuanlan.zhihu.com/p/107749687)】 - Use (neo)vim terminal in the floating/popup window. -![](https://user-images.githubusercontent.com/20282795/74799912-de268200-530c-11ea-9831-d412a7700505.png) +[![CI](https://github.com/voldikss/vim-floaterm/workflows/CI/badge.svg)](https://github.com/voldikss/vim-floaterm/actions?query=workflow%3ACI) [![GitHub license](https://img.shields.io/github/license/voldikss/vim-floaterm.svg)](https://github.com/voldikss/vim-floaterm/blob/master/LICENSE) [![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://github.com/voldikss/vim-floaterm/graphs/commit-activity) + +![](https://user-images.githubusercontent.com/20282795/91376670-2db3b080-e850-11ea-9991-efa4f4da6f44.png) - [Features](#features) - [Requirements](#requirements) - [Installation](#installation) -- [Basic Usage](#basic-usage) +- [Get started](#get-started) - [Commands](#commands) - - [Global variables](#global-variables) + - [Options](#options) - [Keymaps](#keymaps) - - [Change highlight](#change-highlight) -- [More use cases and demos](#more-use-cases-and-demos) - - [General](#general) - - [Use as the git editor](#use-as-the-git-editor) - - [Use as an fzf plugin](#use-as-an-fzf-plugin) - - [Use as an fff plugin](#use-as-an-fff-plugin) - - [Use as an nnn plugin](#use-as-an-nnn-plugin) - - [Use as an lf plugin](#use-as-an-lf-plugin) - - [Use as a ranger plugin](#use-as-a-ranger-plugin) - - [Use as a vifm plugin](#use-as-a-vifm-plugin) - - [Use as a Python REPL plugin](#use-as-a-python-repl-plugin) - - [Use with other command line tools](#use-with-other-command-line-tools) - - [Integrate with vim-clap](#integrate-with-vim-clap) - - [Integrate with denite.nvim](#integrate-with-denitenvim) - - [Integrate with coc.nvim](#integrate-with-cocnvim) - - [Integrate with asynctasks.vim](#integrate-with-asynctasksvim) -- [How to define more wrappers](#how-to-define-more-wrappers) -- [How to write sources for fuzzy finder plugins](#how-to-write-sources-for-fuzzy-finder-plugins) -- [APIs](#apis) -- [F.A.Q](#f.a.q) -- [Break Changes](#break-changes) + - [Highlights](#highlights) +- [Advanced Topics](#advanced-topics) + - [Use with command line tools](#use-with-command-line-tools) + - [Use with other plugins](#use-with-other-plugins) + - [How to define more wrappers](#how-to-define-more-wrappers) + - [How to write sources for fuzzy finder plugins](#how-to-write-sources-for-fuzzy-finder-plugins) +- [Wiki](#wiki) +- [FAQ](#faq) +- [Breaking changes](#breaking-changes) +- [Related projects](#related-projects) - [Credits](#credits) - [License](#license) ## Features -- NeoVim floatwin and Vim8 popup support -- Open and toggle terminal window quickly -- Multiple terminal instances -- Customizable floating terminal style -- Switch/Preview floating terminal buffers using [vim-clap](https://github.com/liuchengxu/vim-clap), [denite.nvim](https://github.com/Shougo/denite.nvim) or [coc.nvim](https://github.com/neoclide/coc.nvim) -- Integrate with other external command-line tools(ranger, lf, fzf, etc.) +- Support neovim floatwin and vim8 popupwin +- Manage multiple terminal instances +- Customizable terminal window style +- Switch/preview floating terminal buffers using fuzzy-finder plugins such as + [denite.nvim](https://github.com/Shougo/denite.nvim) or + [coc.nvim](https://github.com/neoclide/coc.nvim), etc. +- Use with other external command-line tools(ranger, lf, fzf, etc.) +- Autocompletion from within floaterms(require [coc.nvim](https://github.com/neoclide/coc.nvim) + or [deoplete.nvim](https://github.com/Shougo/deoplete.nvim)) - Use as a custom task runner for [asynctasks.vim](https://github.com/skywind3000/asynctasks.vim) + or [asyncrun.vim](https://github.com/skywind3000/asyncrun.vim) ## Requirements -- Vim or NeoVim with `terminal` feature +- Vim or neovim with `terminal` feature -Run `:checkhealth` to check the environment. +Run `:checkhealth` for more info. ## Installation @@ -67,136 +58,269 @@ Plug 'voldikss/vim-floaterm' call dein#add('voldikss/vim-floaterm') ``` -## Basic Usage +## Get Started -Use `:FloatermNew` command to open a terminal window, use `:FloatermToggle` to hide/reopen that. The filetype of the terminal buffer is set to `floaterm`. +Use `:FloatermNew` to open a terminal window, use `:FloatermToggle` to +hide/reopen that. The filetype of the terminal buffer is `floaterm`. -If you've opened multiple floaterm instances, they will be attached to a double-circular-linkedlist. Then you can use `:FloatermNext` or `:FloatermPrev` to switch between them. +If you've opened multiple floaterm instances, they will be attached to a +double-circular-linkedlist. Then you can use `:FloatermNext` or +`: FloatermPrev` to switch between them. ### Commands -#### `:FloatermNew [options] [cmd]` Open a floaterm window. - -- If `cmd` exists, it will be executed automatically after the shell startup. -- The `options` is formed as `key=value`, it is used to specify some attributes of the floaterm instance, including `height`, `width`, `wintype`, `position` and `name`. +#### `:FloatermNew[!] [options] [cmd]` Open a floaterm window. + +- If `!` is given, execute `cmd` in `$SHELL`. Try `:FloatermNew python` and + `: FloatermNew! python` to learn about the difference. +- If execute without `cmd`, open `$SHELL`. +- The `options` is formed as `--key[=value]`, it is used to specify local + attributes of a specific floaterm instance. Note that in order to input + space, you have to form it as `\` followed by space, and `\` must be typed + as `\\` + - `cwd` working directory that floaterm will be opened at, accept either a + path or literal `` which represents the project root directory + - `name` name of the floaterm + - `silent` If `--silent` is given, spawn a floaterm but not open the window, + you may toggle it afterwards - `height` see `g:floaterm_height` - `width` see `g:floaterm_width` + - `title` see `g:floaterm_title` - `wintype` see `g:floaterm_wintype` - `position` see `g:floaterm_position` - - `name` name of the floaterm + - `borderchars` see `g:floaterm_borderchars` + - `autoclose` see `g:floaterm_autoclose` - Use `` to get completion. +- This command basically shares the consistent behaviors with the builtin `:terminal` : + - The special characters(`:help cmdline-special`) such as `%` and `` + will be auto-expanded, to get standalone characters, use `\` followed by + the corresponding character(e.g., `\%`). + - Note that ``(i.e., `|`) will be seen as an argument of the command, + therefore it can not be followed by another Vim command. + +For example, the command + +```vim +:FloatermNew --height=0.6 --width=0.4 --wintype=float --name=floaterm1 --position=topleft --autoclose=2 ranger --cmd="cd ~" +``` -For example, command +will open a new floating/popup floaterm instance named `floaterm1` running `ranger --cmd="cd ~"` in the `topleft` corner of the main window. + +The following command allows you to compile and run your C code in the floaterm window: ```vim -:FloatermNew height=0.6 width=0.4 wintype=floating name=floaterm1 position=topleft ranger --cmd="cd ~" +:FloatermNew --autoclose=0 gcc % -o %< && ./%< ``` -will open a new `floating` floaterm instance named `floaterm1` running `ranger --cmd="cd ~"` in the `topleft` corner of the main window. +#### `:FloatermPrev` Switch to the previous floaterm instance + +#### `:FloatermNext` Switch to the next floaterm instance + +#### `:FloatermFirst` Switch to the first floaterm instance + +#### `:FloatermLast` Switch to the last floaterm instance #### `:FloatermUpdate [options]` Update floaterm window attributes(`height`, `width`, etc.). -- The `options` is the same as in `:FloatermNew`. +- The `options` is the same as in `:FloatermNew` (except `--silent`). - Use `` to get completion. -#### `:FloatermToggle [floaterm_name]` Open or hide the floaterm window. +#### `:[N]FloatermToggle[!] [floaterm_name]` Open or hide the floaterm window. -- If `floaterm_name` exists, toggle the floaterm instance whose `name` attribute is `floaterm_name`. +- If `N` is given, toggle the floaterm whose buffer number is `N` +- If `floaterm_name` is given, toggle the floaterm instance whose `name` + attribute is `floaterm_name`. Otherwise create a new floaterm named + `floaterm_name`. - Use `` to get completion. +- If `!` is given, toggle all floaterms -#### `:FloatermPrev` Switch to the previous floaterm instance +#### `:[N]FloatermShow[!] [floaterm_name]` Show the current floaterm window. -#### `:FloatermNext` Switch to the next floaterm instance +- If `N` is given, show the floaterm whose buffer number is `N` +- If `floaterm_name` is given, show the floaterm named `floaterm_name`. +- If `!` is given, show all floaterms + +#### `:[N]FloatermHide[!] [floaterm_name]` Hide the current floaterms window. + +- If `N` is given, hide the floaterm whose buffer number is `N` +- If `floaterm_name` is given, show the floaterm named `floaterm_name`. +- If `!` is given, hide all floaterms -#### `:FloatermHide` Hide all visible floaterms +#### `:[N]FloatermKill[!] [floaterm_name]` Kill the current floaterm instance -#### `:'<,'>FloatermSend [floaterm_name]` Send selected lines to a job in floaterm. +- If `N` is given, kill the floaterm whose buffer number is `N` +- If `floaterm_name` is given, kill the floaterm instance named `floaterm_name`. +- If `!` is given, kill all floaterms -- If `floaterm_name` exists, send to the floaterm instance whose `name` is `floaterm_name`. +#### `:FloatermSend [--name=floaterm_name] [cmd]` Send command to a job in floaterm. + +- If `--name=floaterm_name` is given, send lines to the floaterm instance + whose `name` is `floaterm_name`. Otherwise use the current floaterm. +- If `cmd` is given, it will be sent to floaterm and selected lines will be ignored. +- This command can also be used with a range, i.e., `'<,'>:FloatermSend [--name=floaterm_name]` to send selected lines to a floaterm. + - If `cmd` is given, the selected lines will be ignored. + - If use this command with a `!`, i.e., `'<,'>:FloatermSend! [--name=floaterm_name]` the common white spaces in the beginning of lines + will be trimmed while the relative indent between lines will still be + kept. - Use `` to get completion. +- Examples + ```vim + :FloatermSend " Send current line to the current floaterm (execute the line in the terminal) + :FloatermSend --name=ft1 " Send current line to the floaterm named ft1 + :FloatermSend ls -la " Send `ls -la` to the current floaterm + :FloatermSend --name=ft1 ls -la " Send `ls -la` to the floaterm named ft1 + :23FloatermSend ... " Send the line 23 to floaterm + :1,23FloatermSend ... " Send lines between line 1 and line 23 to floaterm + :'<,'>FloatermSend ... " Send lines selected to floaterm(visual block selection are supported) + :%FloatermSend ... " Send the whole buffer to floaterm + ``` -Note: This command must be executed with a range! +### Options -Also you may try `:'<,'>FloatermSend!`, which trims the whitespace in the begin of the line, and the latter removes the whitespace but still keeps the indent. +#### **`g:floaterm_shell`** -### Global variables +Type `String`. Default: `&shell` -#### **`g:floaterm_wintype`** +#### **`g:floaterm_title`** -Type `string`. `'floating'`(neovim) or `'popup'`(vim) by default. Set it to `'normal'` if your vim/nvim doesn't support `floatwin` or `popup`. +Type `String`. Show floaterm info(e.g., `'floaterm: 1/3'` implies there are 3 +floaterms in total and the current is the first one) at the top left corner of +floaterm window. -#### **`g:floaterm_wintitle`** +Default: `'floaterm: $1/$2'`(`$1` and `$2` will be substituted by 'the index of +the current floaterm' and 'the count of all floaterms' respectively) -Type `bool`. Whether to show floaterm info(e.g., `'floaterm: 1/3'`) at the top left corner of floaterm window. Default: `v:true` +Example: `'floaterm($1|$2)'` + +#### **`g:floaterm_wintype`** + +Type `String`. `'float'`(nvim's floating or vim's popup) by default. Set it to +`'normal'` if your vim/nvim doesn't support `floatwin` or `popupwin` feature. #### **`g:floaterm_width`** -Type `int` (number of columns) or `float` (between 0 and 1). If `float`, the width is relative to `&columns`. Default: `0.6` +Type `Number` (number of columns) or `Float` (between 0 and 1). If `Float`, +the width is relative to `&columns`. -#### **`g:floaterm_height`** +Default: `0.6` -Type `int` (number of lines) or `float` (between 0 and 1). If `float`, the height is relative to `&lines`. Default: `0.6` +#### **`g:floaterm_height`** -#### **`g:floaterm_winblend`** +Type `Number` (number of lines) or `Float` (between 0 and 1). If `Float`, the +height is relative to `&lines`. -Type `int`. The transparency of the floating terminal. Only works in neovim. Default: `0` +Default: `0.6` #### **`g:floaterm_position`** -Type `string`. The position of the floating window. Available values: +Type `String`. The position of the floating window. Available values: - If `wintype` is `normal`: `'top'`, `'right'`, `'bottom'`, `'left'`. Default: `'bottom'` -- If `wintype` is `floating` or `popup`: `'top'`, `'right'`, `'bottom'`, `'left'`, `'center'`, `'topleft'`, `'topright'`, `'bottomleft'`, `'bottomright'`, `'auto'(at the cursor place)`. Default: `'center'` +- If `wintype` is `float`: `'top'`, `'right'`, `'bottom'`, `'left'`, + `'center'`, `'topleft'`, `'topright'`, `'bottomleft'`, `'bottomright'`, + `'auto'(at the cursor place)`. Default: `'center'` + +In addition, there is another option `'random'` which allows to pick a random +position from above when (re)opening a floaterm window. #### **`g:floaterm_borderchars`** -Type `array of string`. Characters of the floating window border. +Type `String`. 8 characters of the floating window border (top, right, bottom, +left, topleft, topright, botright, botleft). -Default: `['─', '│', '─', '│', '┌', '┐', '┘', '└']` +Default: `─│─│┌┐┘└` #### **`g:floaterm_rootmarkers`** -Type `array of string`. If not empty, floaterm will be opened in the project root directory. +Type `List` of `String`. Markers used to detect the project root directory for `--cwd=` -Example: `['.project', '.git', '.hg', '.svn', '.root', '.gitignore']`, Default: `[]` - -#### **`g:floaterm_autoinsert`** - -Type `bool`. Enter terminal mode after opening a floaterm. Default: `v:true` +Default: `['.project', '.git', '.hg', '.svn', '.root']` #### **`g:floaterm_open_command`** -Type `string`. Command used for opening a file from within `:terminal`. +Type `String`. Command used for opening a file in the outside nvim from within `:terminal`. Available: `'edit'`, `'split'`, `'vsplit'`, `'tabe'`, `'drop'`. Default: `'edit'` #### **`g:floaterm_gitcommit`** -Type `string`. Opening strategy for running `git commit` in floaterm window. Only works in neovim. +Type `String`. Opening strategy for `COMMIT_EDITMSG` window by running `git commit` in the floaterm window. Only works in neovim. + +Available: `'floaterm'`(open `gitcommit` in the floaterm window), `'split'`(recommended), `'vsplit'`, `'tabe'`. + +Default: `''`, which means this is disabled by default(use your own `$GIT_EDITOR`). + +#### **`g:floaterm_autoclose`** + +Type `Number`. Whether to close floaterm window once the job gets finished. + +- `0`: Always do NOT close floaterm window +- `1`: Close window if the job exits normally, otherwise stay it with messages like `[Process exited 101]` +- `2`: Always close floaterm window + +Default: `0`. + +#### **`g:floaterm_autoinsert`** + +Type `Boolean`. Whether to enter Terminal-mode after opening a floaterm. + +Default: `v:true` + +#### **`g:floaterm_autohide`** + +Type `Boolean`. Decide whether to hide previous floaterms before switching to or opening a new one. + +Default: `v:true`. -Available: `'floaterm'`(open `gitcommit` file in the floaterm window), `'split'`, `'vsplit'`, `'tabe'`. +#### **`g:floaterm_complete_options`** -Default: `v:null` which means this is disabled by default(use your own `$GIT_EDITOR`). +Type `Dict`. Autocompletion options (The completion from floaterm is synchronous) + +Available options: + +- `shortcut`: A string. +- `priority`: Number between 0-99. +- `filetypes`: Array of filetype names this source should be triggered by. + Available for all filetypes when ommited and for no filetypes when empty +- `filter_length`: Array of 2 numbers. Candidates whose length is not + in the range will be removed. + +Default value: `{'shortcut': 'floaterm', 'priority': 5, 'filter_length': [5, 20]}` ### Keymaps -This plugin doesn't supply any default mappings. To use a recommended mappings, put the following code in your `vimrc`. +This plugin doesn't supply any default mappings. Here are the configuration examples. ```vim -""" Configuration example +" Configuration example let g:floaterm_keymap_new = '' let g:floaterm_keymap_prev = '' let g:floaterm_keymap_next = '' -let g:floaterm_keymap_toggle = '' +let g:floaterm_keymap_toggle = '' ``` You can also use other keys as shown below: ```vim -let g:floaterm_keymap_new = 'fn' +let g:floaterm_keymap_new = 'ft' ``` -Note that this key mapping is installed from the [plugin](./plugin) directory, so if you use on-demand loading provided by some plugins-managers, the keymap above won't take effect(`:help load-plugins`). Then you have to define the key bindings yourself by putting the code used to define the key bindings in your `vimrc`. For example, +All options for the mappings are listed below: + +- `g:floaterm_keymap_new` +- `g:floaterm_keymap_prev` +- `g:floaterm_keymap_next` +- `g:floaterm_keymap_first` +- `g:floaterm_keymap_last` +- `g:floaterm_keymap_hide` +- `g:floaterm_keymap_show` +- `g:floaterm_keymap_kill` +- `g:floaterm_keymap_toggle` + +Note that the key mappings are set from the [plugin/floaterm.vim](./plugin/floaterm.vim), +so if you are using on-demand loading feature provided by some plugin-managers, +the keymap above won't take effect(`:help load-plugins`). Then you have to +define the key bindings by yourself. For example, ```vim nnoremap :FloatermNew @@ -205,15 +329,16 @@ nnoremap :FloatermPrev tnoremap :FloatermPrev nnoremap :FloatermNext tnoremap :FloatermNext -nnoremap :FloatermToggle -tnoremap :FloatermToggle +nnoremap :FloatermToggle +tnoremap :FloatermToggle ``` -### Change highlight +### Highlights -This plugin provides two `highlight-groups` to specify the background/foreground color of floaterm (also the border color if `g:floaterm_wintype` is `'floating'` or `'popup'`) window. +There are two `highlight-groups` to specify the color of floaterm (also the +border color if `g: floaterm_wintype` is `'float'`) window. -By default, they are both linked to `Normal`. To customize, use `hi` command together with the colors you prefer. +To customize, use `hi` command together with the colors you prefer. ```vim " Configuration example @@ -224,33 +349,62 @@ hi Floaterm guibg=black hi FloatermBorder guibg=orange guifg=cyan ``` -![](https://user-images.githubusercontent.com/20282795/74794098-42d9e080-52fd-11ea-9ccf-661dd748aa03.png) +![](https://user-images.githubusercontent.com/20282795/91368959-fee00f00-e83c-11ea-9002-cab992d30794.png) -## More use cases and demos +Besides, there is a neovim only highlight group which can be used to configure +no-current-focused window(`:help NormalNC`). -vim-floaterm is a nvim/vim terminal plugin, it can run all the command-line programs in the terminal even `nvim/vim` itself. +```vim +" Configuration example -**❗️Note**: The following cases should work both in Vim and NeoVim unless otherwise specifically noted. +" Set floaterm window background to gray once the cursor moves out from it +hi FloatermNC guibg=gray +``` + +![](https://user-images.githubusercontent.com/20282795/91380259-28a62f80-e857-11ea-833f-11160d15647a.gif) + +## Advanced Topics + +### Use with command line tools -### General +The following cases should work both in Vim and NeoVim unless otherwise +specifically noted. -Requirements: For neovim users, `nvr` is required, please install it via pip using `pip3 install neovim-remote`. +#### floaterm -Normally if you run `vim/nvim somefile.txt` within a builtin terminal, you will get another nvim/vim instance running in the subprocess. This plugin allows you to open files from within `:terminal` without starting a nested nvim process. To archive that, just replace `vim/nvim` with `floaterm`, i.e., `floaterm somefile.txt` +Normally if you run `vim/nvim somefile.txt` within the builtin terminal, you +would get another nvim/vim instance running in the subprocess. -![](https://user-images.githubusercontent.com/20282795/74755351-06cb5f00-52ae-11ea-84ba-d0b3e88e9377.gif) +[Floaterm](https://github.com/voldikss/vim-floaterm/tree/master/bin), which is +a builtin script in this plugin, allows you to open files from within `: terminal` without starting a nested nvim. To archive that, just literally +replace `vim/nvim` with `floaterm`, i.e., `floaterm somefile.txt` + +**❗️Note**: This should works both in neovim and vim, but if you are using +neovim, make sure [neovim-remote](https://github.com/mhinz/neovim-remote) has been installed. You can install it via +pip: + +```sh +pip install neovim-remote +``` -### Use as the git editor +P.S. [#208](https://github.com/voldikss/vim-floaterm/issues/208#issuecomment-747829311) describes how to use `gf` in the floating terminal window. + +![](https://user-images.githubusercontent.com/20282795/91380257-27750280-e857-11ea-8d49-d760c009fee0.gif) + +#### git See `g:floaterm_gitcommit` option. Execute `git commit` in the terminal window without starting a nested nvim. -![](https://user-images.githubusercontent.com/20282795/76213003-b0b26180-6244-11ea-85ad-1632adfd07d9.gif) +**❗️Note**: neovim only feature. Moreover, it also requires [neovim-remote](https://github.com/mhinz/neovim-remote), please install it using `pip3 install neovim-remote`. -### Use as an fzf plugin +![](https://user-images.githubusercontent.com/20282795/91380268-2cd24d00-e857-11ea-8dbd-d39a0bbb105e.gif) -This plugin has implemented a [wrapper](./autoload/floaterm/wrapper/fzf.vim) for fzf command. So it can be used as a tiny fzf plugin. +#### fzf + +This plugin has implemented a [wrapper](./autoload/floaterm/wrapper/fzf.vim) +for `fzf` command. So it can be used as a tiny fzf plugin. Try `:FloatermNew fzf` or even wrap this to a new command like this: @@ -258,9 +412,9 @@ Try `:FloatermNew fzf` or even wrap this to a new command like this: command! FZF FloatermNew fzf ``` -![](https://user-images.githubusercontent.com/20282795/78089550-60b95b80-73fa-11ea-8ac8-8fab2025b4d8.gif) +![](https://user-images.githubusercontent.com/20282795/91380264-2b088980-e857-11ea-80ff-062b3d3bbf12.gif) -### Use as an fff plugin +#### fff There is also an [fff wrapper](./autoload/floaterm/wrapper/fff.vim) @@ -272,7 +426,7 @@ command! FFF FloatermNew fff ![](https://user-images.githubusercontent.com/1472981/75105718-9f315d00-567b-11ea-82d1-6f9a6365391f.gif) -### Use as an nnn plugin +#### nnn There is also an [nnn wrapper](./autoload/floaterm/wrapper/nnn.vim) @@ -282,9 +436,9 @@ Try `:FloatermNew nnn` or define a new command: command! NNN FloatermNew nnn ``` -![](https://user-images.githubusercontent.com/20282795/75599726-7a594180-5ae2-11ea-80e2-7a33df1433f6.gif) +![](https://user-images.githubusercontent.com/20282795/91380278-322f9780-e857-11ea-8b1c-d40fc91bb07d.gif) -### Use as an lf plugin +#### lf There is also an [lf wrapper](./autoload/floaterm/wrapper/lf.vim) @@ -294,9 +448,9 @@ Try `:FloatermNew lf` or define a new command: command! LF FloatermNew lf ``` -![](https://user-images.githubusercontent.com/20282795/77142551-6e4a1980-6abb-11ea-9525-73e1a1844e83.gif) +![](https://user-images.githubusercontent.com/20282795/91380274-3065d400-e857-11ea-86df-981adddc04c6.gif) -### Use as a ranger plugin +#### ranger This plugin can also be a handy ranger plugin since it also has a [ranger wrapper](./autoload/floaterm/wrapper/ranger.vim) @@ -306,9 +460,9 @@ Try `:FloatermNew ranger` or define a new command: command! Ranger FloatermNew ranger ``` -![](https://user-images.githubusercontent.com/20282795/74800026-2e054900-530d-11ea-8e2a-67168a9532a9.gif) +![](https://user-images.githubusercontent.com/20282795/91380284-3360c480-e857-11ea-9966-34856592d487.gif) -### Use as a Vifm plugin +#### vifm There is also a [vifm wrapper](./autoload/floaterm/wrapper/vifm.vim) @@ -320,31 +474,33 @@ command! Vifm FloatermNew vifm ![](https://user-images.githubusercontent.com/43941510/77137476-3c888100-6ac2-11ea-90f2-2345c881aa8f.gif) -### Use as a Python REPL plugin +#### lazygit -Use `:FloatermNew python` to open a python shell. After that you can use `:FloatermSend` to send lines to the Python interactive shell. +Furthermore, you can also use other command-line programs, such as lazygit, htop, ncdu, etc. -This can also work for other languages which have interactive shells, such as lua, node, etc. +Use `lazygit` for instance: -![](https://user-images.githubusercontent.com/20282795/78530892-0c0d4a80-7817-11ea-8934-835a6e6d0628.gif) +![](https://user-images.githubusercontent.com/20282795/74755376-0f239a00-52ae-11ea-9261-44d94abe5924.png) -### Use with other command line tools +#### python -Furthermore, you can also use other command-line programs, such as lazygit, htop, ncdu, etc. +Use `:FloatermNew python` to open a python shell. After that you can use `: FloatermSend` to send lines to the Python interactive shell. -Use `lazygit` for instance: +This can also work for other languages which have interactive shells, such as lua, node, etc. -![](https://user-images.githubusercontent.com/20282795/74755376-0f239a00-52ae-11ea-9261-44d94abe5924.png) +![](https://user-images.githubusercontent.com/20282795/91380286-352a8800-e857-11ea-800c-ac54efa7dd72.gif) + +### Use with other plugins -### Integrate with [vim-clap](https://github.com/liuchengxu/vim-clap) +#### [vim-clap](https://github.com/liuchengxu/vim-clap) Use vim-clap to switch/preview floating terminal buffers. Try `:Clap floaterm` -![](https://user-images.githubusercontent.com/20282795/74755336-00d57e00-52ae-11ea-8afc-030ff55c2145.gif) +![](https://user-images.githubusercontent.com/20282795/91380243-217f2180-e857-11ea-9f64-46e8676adc11.gif) -### Integrate with [denite.nvim](https://github.com/Shougo/denite.nvim) +#### [denite.nvim](https://github.com/Shougo/denite.nvim) Use denite to switch/preview/open floating terminal buffers. @@ -352,44 +508,81 @@ Try `:Denite floaterm` ![](https://user-images.githubusercontent.com/1239245/73604753-17ef4d00-45d9-11ea-967f-ef75927e2beb.gif) -### Integrate with [coc.nvim](https://github.com/neoclide/coc.nvim) +#### [coc.nvim](https://github.com/neoclide/coc.nvim) Use CocList to switch/preview/open floating terminal buffers. Install [coc-floaterm](https://github.com/voldikss/coc-floaterm) and try `:CocList floaterm` -![](https://user-images.githubusercontent.com/20282795/75005925-fcc27f80-54aa-11ea-832e-59ea5b02fc04.gif) +![](https://user-images.githubusercontent.com/20282795/91380254-25ab3f00-e857-11ea-9733-d0ae5a954848.gif) + +#### [fzf](https://github.com/junegunn/fzf) + +Install [fzf-floaterm](https://github.com/voldikss/fzf-floaterm) and try `:Floaterms` + +#### [LeaderF](https://github.com/Yggdroot/LeaderF) -### Integrate with [asynctasks.vim](https://github.com/skywind3000/asynctasks.vim) +Install [LeaderF-floaterm](https://github.com/voldikss/LeaderF-floaterm) and try `:Leaderf floaterm` -This plugin can be a runner for [asynctasks.vim](https://github.com/skywind3000/asynctasks.vim/). To use it, copy the following code to your `vimrc` set `g:asynctasks_term_pos` to `"floaterm"` or add a `"pos=floaterm"` filed in your asynctasks configuration files. +#### [asynctasks.vim](https://github.com/skywind3000/asynctasks.vim) | [asyncrun.vim](https://github.com/skywind3000/asyncrun.vim) + +This plugin can be a runner for asynctasks.vim or asyncrun.vim. +To use it, try the following code in your `vimrc`. ```vim -function! s:runner_proc(opts) - let curr_bufnr = floaterm#curr() - if has_key(a:opts, 'silent') && a:opts.silent == 1 - call floaterm#hide() - endif - let cmd = 'cd ' . shellescape(getcwd()) - call floaterm#terminal#send(curr_bufnr, [cmd]) - call floaterm#terminal#send(curr_bufnr, [a:opts.cmd]) - stopinsert - if &filetype == 'floaterm' && g:floaterm_autoinsert - call floaterm#util#startinsert() - endif +function! s:run_in_floaterm(opts) + execute 'FloatermNew --position=bottomright' . + \ ' --wintype=float' . + \ ' --height=0.4' . + \ ' --width=0.4' . + \ ' --title=floaterm_runner' . + \ ' --autoclose=0' . + \ ' --silent=' . get(a:opts, 'silent', 0) + \ ' --cwd=' . a:opts.cwd + \ ' ' . a:opts.cmd + " Do not focus on floaterm window, and close it once cursor moves + " If you want to jump to the floaterm window, use p + " You can choose whether to use the following code or not + stopinsert | noa wincmd p + augroup close-floaterm-runner + autocmd! + autocmd CursorMoved,InsertEnter * ++nested + \ call timer_start(100, { -> s:close_floaterm_runner() }) + augroup END +endfunction +function! s:close_floaterm_runner() abort + if &ft == 'floaterm' | return | endif + for b in tabpagebuflist() + if getbufvar(b, '&ft') == 'floaterm' && + \ getbufvar(b, 'floaterm_jobexists') == v:false + execute b 'bwipeout!' + break + endif + endfor + autocmd! close-floaterm-runner endfunction - let g:asyncrun_runner = get(g:, 'asyncrun_runner', {}) -let g:asyncrun_runner.floaterm = function('s:runner_proc') +let g:asyncrun_runner.floaterm = function('s:run_in_floaterm') +let g:asynctasks_term_pos = 'floaterm' ``` -Then your task will be ran in the floaterm instance. See asynctasks.vim [Wiki](https://github.com/skywind3000/asynctasks.vim/wiki/Customize-Runner) for more information. +Then your task will be run in the floaterm instance. See asynctasks.vim +[Wiki](https://github.com/skywind3000/asynctasks.vim/wiki/Customize-Runner) for more information. -## How to define more wrappers +You can also modify the code in `s: run_in_floaterm` by yourself to meet your +tastes, which is the reason why this code is not made builtin. + +![](https://user-images.githubusercontent.com/20282795/104123344-b3f70c00-5385-11eb-9f61-0a5703ba78f5.gif) + +### How to define more wrappers + +The wrapper script must be located in `autoload/floaterm/wrapper/` directory, +e.g., `autoload/floaterm/wrapper/fzf.vim`. There are two ways for a command to be spawned: -- To be executed after `&shell` was startup. see [fzf wrapper](./autoload/floaterm/wrapper/fzf.vim) +- To be executed after spawning `$SHELL`. Here is the old implementation of + [fzf wrapper](./autoload/floaterm/wrapper/fzf.vim) ```vim function! floaterm#wrapper#fzf#() abort @@ -397,128 +590,78 @@ There are two ways for a command to be spawned: endfunction ``` - The code above returns an array. `floaterm $(fzf)` is the command to be executed. `v:true` means the command will be executed after the `&shell` startup. + The code above returns a list. `floaterm $(fzf)` is the command to be + executed. `v:true` means the command will be executed after the `&shell` + startup. In this way, the second element of the list must be `{}`. -- To be executed through `termopen()`/`term_start()` function, in that case, a callback function is can be provided. See [ranger wrapper](./autoload/floaterm/wrapper/ranger.vim) +- To be executed through `termopen()`/`term_start()` function, in that case, a + callback option can be provided. See [fzf wrapper](./autoload/floaterm/wrapper/fzf.vim) ```vim - function! floaterm#wrapper#ranger#() abort - let s:ranger_tmpfile = tempname() - let cmd = 'ranger --choosefiles=' . s:ranger_tmpfile - return [cmd, {'on_exit': funcref('s:ranger_callback')}, v:false] + function! floaterm#wrapper#fzf#(cmd) abort + let s:fzf_tmpfile = tempname() + let cmd = a:cmd . ' > ' . s:fzf_tmpfile + return [cmd, {'on_exit': funcref('s:fzf_callback')}, v:false] endfunction - function! s:ranger_callback(...) abort - if filereadable(s:ranger_tmpfile) - let filenames = readfile(s:ranger_tmpfile) + function! s:fzf_callback(...) abort + if filereadable(s:fzf_tmpfile) + let filenames = readfile(s:fzf_tmpfile) if !empty(filenames) + if has('nvim') + call floaterm#window#hide(bufnr('%')) + endif for filename in filenames - execute 'edit ' . fnameescape(filename) + execute g:floaterm_open_command . ' ' . fnameescape(filename) endfor endif endif endfunction ``` - Here `v:false` means `cmd` will be passed through `termopen()`(neovim) or `term_start()`(vim). Function `s:ranger_callback()` will be invoked when `cmd` exits. + In the example above, after executing `:FloatermNew fzf`, function + `floaterm#wrapper#fzf#` will return `['fzf > /tmp/atmpfilename', {'on_exit': funcref('s:fzf_callback')}, v:false]`. + + Here `v:false` means `cmd`(`fzf > /tmp/atmpfilename`) will be passed through + `termopen()`(neovim) or `term_start()`(vim). As a result, an fzf interactive + will be opened in a floaterm window. After choosing a file using ``, fzf + exits and the filepath will be written in `/tmp/atmpfilename`. Then the + function `s:fzf_callback()` will be invoked to open the file. -## How to write sources for fuzzy finder plugins +### How to write sources for fuzzy finder plugins Function `floaterm#buflist#gather()` returns a list contains all the floaterm buffers. -Function `floaterm#terminal#open({bufnr})` opens the floaterm whose buffer number is `bufnr`. +Function `floaterm#terminal#open_existing({bufnr})` opens the floaterm whose buffer number is `{bufnr}`. For reference, see [floaterm source for vim-clap](./autoload/clap/provider/floaterm.vim). -## APIs - -- `floaterm#new(cmd, win_opts, job_opts)` create a new floaterm instance and return the bufnum - - - `cmd` type `string`, if empty(`''`), will use `&shell` - - `win_opts` type `dict`. See [FloatermNew options](#floatermnew-options-cmd-open-a-floaterm-window), e.g., `{'name': 'floaterm1', 'wintype': 'floating', 'position': 'top'}` - - `job_opts` type `dict`. For reference, see `:help job-options`(for vim) or `:help jobstart-options`(for nvim) - -- `floaterm#update(win_opts)` update floaterm window attributes - -- `floaterm#toggle(name)` toggle on/off a floaterm - - - `name` name of the floaterm, if empty(`''`), toggle the current floaterm - -- `floaterm#prev()` switch to the previous floaterm buffeum and return the bufnum - -- `floaterm#next()` switch to the next floaterm buffer and return the bufnum +## Wiki -- `floaterm#curr()` return current floaterm buffer number +https://github.com/voldikss/vim-floaterm/wiki -- `floaterm#hide()` hide all visible floaterms +## FAQ -- `floaterm#window#hide_floaterm(bufnr)` hide the floaterm whose bufnum is `bufnr` +https://github.com/voldikss/vim-floaterm/issues?q=label%3AFAQ -- `floaterm#terminal#send(bufnr, cmds)` send commands to a terminal whose bufnum is `bufnr` +## Breaking Changes - - `cmd`: a list contains some commands +https://github.com/voldikss/vim-floaterm/issues?q=label%3A%22breaking+change%22 -- `floaterm#window#open_floating(bufnr, width, height, pos)` open a generic floating window with a border, return window id +## Related projects -There are some other functions which can be served as APIs, for detail infomation, go and check source files yourself. - -## F.A.Q - -- #### This plugin leaves an empty buffer/window on startify window - - Put this code in your `vimrc` - - ```vim - autocmd User Startified setlocal buflisted - ``` - -- #### I want to use another shell in the terminal. (e.g., Use fish instead of bash) - - Set `shell` option in your `vimrc`: - - ```vim - set shell=/path/to/shell - ``` - -- #### I would like to customize the style of the floaterm window - - Use `autocmd`. For example - - ```vim - function s:floatermSettings() - setlocal number - " more settings - endfunction - - autocmd FileType floaterm call s:floatermSettings() - ``` - -- #### I want to open normal(non-floating) floaterm in a vsplit window. - - Use `:FloatermUpdate` - - ```vim - :FloatermUpdate wintype=normal position=right - ``` - -- #### Can not enter insert mode after creating a new floaterm... - - See option [g:floaterm_autoinsert](#gfloaterm_autoinsert), also [#52](https://github.com/voldikss/vim-floaterm/issues/52) might be helpful. - -- #### Why the plugin is named "vim-floaterm" instead of "vim-popterm" or others? - - Because this was firstly developed based on nvim's floating window. But now it supports both floaterm and popup, you can get similar experience in both. - -## Break Changes - -- Command `FloatermSend` must be used with a range -- Rename: `g:floaterm_type` --> `g:floaterm_wintype` -- Rename: `FloatermNF` --> `Floaterm` -- Rename: `FloatermBorderNF` --> `FloatermBorder` +- [vim-floaterm-repl](https://github.com/windwp/vim-floaterm-repl) +- [coc-floaterm](https://github.com/voldikss/coc-floaterm) +- [fzf-floaterm](https://github.com/voldikss/fzf-floaterm) +- [popc-floaterm](https://github.com/yehuohan/popc-floaterm) +- [Leaderf-floaterm](https://github.com/voldikss/LeaderF-floaterm) ## Credits -- [floaterm executable](https://github.com/voldikss/vim-floaterm/blob/master/bin/floaterm) is modified from [vim-terminal-help](https://github.com/skywind3000/vim-terminal-help/blob/master/tools/utils/drop) +- [Vim](https://github.com/vim/vim/) and [Neovim](https://github.com/neovim/neovim/) the editor God + +- [floaterm executable](https://github.com/voldikss/vim-floaterm/blob/master/bin/floaterm) is modified + from [vim-terminal-help](https://github.com/skywind3000/vim-terminal-help/blob/master/tools/utils/drop) - Some features require [neovim-remote](https://github.com/mhinz/neovim-remote) diff --git a/etc/soft/nvim/+plugins/vim-floaterm/autoload/clap/provider/floaterm.vim b/etc/soft/nvim/+plugins/vim-floaterm/autoload/clap/provider/floaterm.vim index e22ba19..54193e1 100644 --- a/etc/soft/nvim/+plugins/vim-floaterm/autoload/clap/provider/floaterm.vim +++ b/etc/soft/nvim/+plugins/vim-floaterm/autoload/clap/provider/floaterm.vim @@ -29,9 +29,7 @@ function! s:floaterm.on_move() abort return endif let bufnr = str2nr(matchstr(curline, '\S')) - let lnum = getbufinfo(bufnr)[0]['lnum'] - let lines = getbufline(bufnr, max([lnum-s:preview_height, 0]), '$') - let lines = lines[max([len(lines)-s:preview_height, 0]):] + let lines = floaterm#util#getbuflines(bufnr, s:preview_height) call g:clap.preview.show(lines) endfunction diff --git a/etc/soft/nvim/+plugins/vim-floaterm/autoload/coc/source/floaterm.vim b/etc/soft/nvim/+plugins/vim-floaterm/autoload/coc/source/floaterm.vim new file mode 100644 index 0000000..5439c42 --- /dev/null +++ b/etc/soft/nvim/+plugins/vim-floaterm/autoload/coc/source/floaterm.vim @@ -0,0 +1,41 @@ +" ============================================================================ +" FileName: floaterm.vim +" Author: voldikss +" GitHub: https://github.com/voldikss +" ============================================================================ + +function! coc#source#floaterm#init() abort + return g:floaterm_complete_options +endfunction + +function! coc#source#floaterm#complete(opt, cb) abort + let lines = floaterm#util#getbuflines(-1, 100) + let completion = [] + let [minlength, maxlength] = g:floaterm_complete_options['filter_length'] + + for line in lines + let item = map( + \ filter( + \ s:matchstrlist(line, '[a-zA-Z0-9]\+'), + \ { _,val -> len(val) >= minlength && len(val) <= maxlength} + \ ), + \ { _,val -> {'word': val, 'dup': 0} } + \ ) + let completion += item + endfor + call a:cb(completion) +endfunction + +function! s:matchstrlist(expr, pat) abort + let res = [] + let start = 0 + while 1 + let m = matchstrpos(a:expr, a:pat, start) + if m[1] == -1 + break + endif + call add(res, m[0]) + let start = m[2] + endwhile + return res +endfunction diff --git a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm.vim b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm.vim index 46e8eb3..8516313 100644 --- a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm.vim +++ b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm.vim @@ -13,7 +13,6 @@ let $VIM_EXE = v:progpath let s:home = fnamemodify(resolve(expand(':p')), ':h') let s:script = fnamemodify(s:home . '/../bin', ':p') -let s:wrappers = fnamemodify(s:home . '/floaterm/wrapper', ':p') let s:windows = has('win32') || has('win64') if stridx($PATH, s:script) < 0 @@ -24,63 +23,56 @@ if stridx($PATH, s:script) < 0 endif endif -if g:floaterm_gitcommit != v:null +if !empty(g:floaterm_gitcommit) autocmd FileType gitcommit,gitrebase,gitconfig set bufhidden=delete if g:floaterm_gitcommit == 'floaterm' let $GIT_EDITOR = 'nvr --remote-wait' else let $GIT_EDITOR = printf( - \ 'nvr -cc "call floaterm#hide() | %s" --remote-wait', + \ 'nvr -cc "call floaterm#hide(1, 0, \"\") | %s" --remote-wait', \ g:floaterm_gitcommit \ ) endif endif -"----------------------------------------------------------------------------- -" script level functions -"----------------------------------------------------------------------------- -function! s:get_wrappers() abort - let files = split(glob(s:wrappers . '/*.vim'), "\n") - return map(files, "substitute(fnamemodify(v:val, ':t'), '\\..\\{-}$', '', '')") -endfunction - " ---------------------------------------------------------------------------- " wrapper function for `floaterm#new()` and `floaterm#update()` since they -" share the same argument: `winopts` +" share the same argument: `config` " ---------------------------------------------------------------------------- -function! floaterm#run(action, ...) abort +function! floaterm#run(action, bang, ...) abort + let [cmd, config] = floaterm#cmdline#parse(a:000) if a:action == 'new' - let [cmd, winopts] = floaterm#cmdline#parse(a:000) - call floaterm#new(cmd, winopts, {}) + call floaterm#new(a:bang, cmd, {}, config) elseif a:action == 'update' - let [_, winopts] = floaterm#cmdline#parse(a:000) - call floaterm#update(winopts) + call floaterm#update(config) endif endfunction -" ---------------------------------------------------------------------------- -" create a floaterm. `jobopts` is not used inside this pugin actually, it's -" reserved for outer invoke -" ---------------------------------------------------------------------------- -function! floaterm#new(cmd, winopts, jobopts) abort +" create a floaterm. return bufnr of the terminal +" argument `jobopts` is passed by user in the case using this function as API +function! floaterm#new(bang, cmd, jobopts, config) abort + call floaterm#util#autohide() if a:cmd != '' - let wrappers = s:get_wrappers() + let wrappers_path = globpath(&runtimepath, 'autoload/floaterm/wrapper/*vim', 0, 1) + let wrappers = map(wrappers_path, "substitute(fnamemodify(v:val, ':t'), '\\..\\{-}$', '', '')") let maybe_wrapper = split(a:cmd, '\s')[0] if index(wrappers, maybe_wrapper) >= 0 let WrapFunc = function(printf('floaterm#wrapper#%s#', maybe_wrapper)) let [name, jobopts, send2shell] = WrapFunc(a:cmd) if send2shell - let bufnr = floaterm#terminal#open(-1, &shell, {}, a:winopts) + let bufnr = floaterm#terminal#open(-1, g:floaterm_shell, {}, a:config) call floaterm#terminal#send(bufnr, [name]) else - let bufnr = floaterm#terminal#open(-1, name, jobopts, a:winopts) + let bufnr = floaterm#terminal#open(-1, name, jobopts, a:config) endif - else - let bufnr = floaterm#terminal#open(-1, &shell, a:jobopts, a:winopts) + elseif a:bang + let bufnr = floaterm#terminal#open(-1, g:floaterm_shell, a:jobopts, a:config) call floaterm#terminal#send(bufnr, [a:cmd]) + else + let bufnr = floaterm#terminal#open(-1, a:cmd, a:jobopts, a:config) endif else - let bufnr = floaterm#terminal#open(-1, &shell, a:jobopts, a:winopts) + let bufnr = floaterm#terminal#open(-1, g:floaterm_shell, a:jobopts, a:config) endif return bufnr endfunction @@ -88,133 +80,224 @@ endfunction " ---------------------------------------------------------------------------- " toggle on/off the floaterm named `name` " ---------------------------------------------------------------------------- -function! floaterm#toggle(name) abort - if a:name != '' +function! floaterm#toggle(bang, bufnr, name) abort + if a:bang + let found_winnr = floaterm#window#find() + if found_winnr > 0 + for bufnr in floaterm#buflist#gather() + call floaterm#window#hide(bufnr) + endfor + else + for bufnr in floaterm#buflist#gather() + call floaterm#terminal#open_existing(bufnr) + endfor + endif + return + endif + + let bufnr = a:bufnr + if bufnr == 0 && !empty(a:name) let bufnr = floaterm#terminal#get_bufnr(a:name) - if bufnr == -1 - call floaterm#util#show_msg('No floaterm found with name: ' . a:name, 'error') - return - elseif bufnr == bufnr('%') - call floaterm#window#hide_floaterm(bufnr) + endif + + if bufnr == -1 + call floaterm#new(a:bang, '', {}, {'name': a:name}) + elseif bufnr == 0 + if &filetype == 'floaterm' + call floaterm#window#hide(bufnr('%')) + else + let found_winnr = floaterm#window#find() + if found_winnr > 0 + noautocmd execute found_winnr . 'wincmd w' + else + call floaterm#curr() + endif + endif + elseif getbufvar(bufnr, 'floaterm_winid', -1) != -1 + if bufnr == bufnr('%') + call floaterm#window#hide(bufnr) elseif bufwinnr(bufnr) > -1 - execute bufwinnr(bufnr) . 'wincmd w' + noautocmd execute bufwinnr(bufnr) . 'wincmd w' else call floaterm#terminal#open_existing(bufnr) endif - elseif &filetype == 'floaterm' - call floaterm#window#hide_floaterm(bufnr('%')) else - let found_winnr = floaterm#window#find_floaterm_window() - if found_winnr > 0 - execute found_winnr . 'wincmd w' - call floaterm#util#startinsert() - else - call floaterm#curr() - endif + call floaterm#util#show_msg('No floaterms with the bufnr or name', 'error') endif endfunction " ---------------------------------------------------------------------------- " update the attributes of a floaterm " ---------------------------------------------------------------------------- -function! floaterm#update(winopts) abort +function! floaterm#update(config) abort if &filetype !=# 'floaterm' - call floaterm#util#show_msg('You have to be in a floaterm window to change window opts.', 'error') + call floaterm#util#show_msg('You have to be in a floaterm window to change window config.', 'error') return endif let bufnr = bufnr('%') - call floaterm#window#hide_floaterm(bufnr) - call floaterm#buffer#update_winopts(bufnr, a:winopts) + call floaterm#window#hide(bufnr) + call floaterm#buffer#set_config_dict(bufnr, a:config) call floaterm#terminal#open_existing(bufnr) endfunction function! floaterm#next() abort - call floaterm#window#hide_floaterm(bufnr('%')) - let next_bufnr = floaterm#buflist#find_next() + let next_bufnr = floaterm#buflist#next() if next_bufnr == -1 let msg = 'No more floaterms' call floaterm#util#show_msg(msg, 'warning') else + call floaterm#util#autohide() call floaterm#terminal#open_existing(next_bufnr) endif endfunction function! floaterm#prev() abort - call floaterm#window#hide_floaterm(bufnr('%')) - let prev_bufnr = floaterm#buflist#find_prev() + let prev_bufnr = floaterm#buflist#prev() if prev_bufnr == -1 let msg = 'No more floaterms' call floaterm#util#show_msg(msg, 'warning') else + call floaterm#util#autohide() call floaterm#terminal#open_existing(prev_bufnr) endif endfunction function! floaterm#curr() abort - let curr_bufnr = floaterm#buflist#find_curr() + let curr_bufnr = floaterm#buflist#curr() if curr_bufnr == -1 - let curr_bufnr = floaterm#new('', {}, {}) + let curr_bufnr = floaterm#new(v:true, '', {}, {}) else call floaterm#terminal#open_existing(curr_bufnr) endif return curr_bufnr endfunction -"----------------------------------------------------------------------------- -" hide all floaterms -"----------------------------------------------------------------------------- -function! floaterm#hide() abort - let buffers = floaterm#buflist#gather() - for bufnr in buffers - call floaterm#window#hide_floaterm(bufnr) - endfor +function! floaterm#first() abort + let first_bufnr = floaterm#buflist#first() + if first_bufnr == -1 + call floaterm#util#show_msg('No more floaterms', 'warning') + else + call floaterm#util#autohide() + call floaterm#terminal#open_existing(first_bufnr) + endif +endfunction + +function! floaterm#last() abort + let last_bufnr = floaterm#buflist#last() + if last_bufnr == -1 + call floaterm#util#show_msg('No more floaterms', 'warning') + else + call floaterm#util#autohide() + call floaterm#terminal#open_existing(last_bufnr) + endif +endfunction + +function! floaterm#kill(bang, bufnr, name) abort + if a:bang + for bufnr in floaterm#buflist#gather() + call floaterm#terminal#kill(bufnr) + endfor + return + endif + + let bufnr = a:bufnr + if bufnr == 0 && !empty(a:name) + let bufnr = floaterm#terminal#get_bufnr(a:name) + endif + if bufnr == 0 || bufnr == -1 + let bufnr = floaterm#buflist#curr() + endif + + if bufnr > 0 + call floaterm#terminal#kill(bufnr) + else + call floaterm#util#show_msg('No floaterms with the bufnr or name', 'error') + endif +endfunction + +function! floaterm#show(bang, bufnr, name) abort + if a:bang + for bufnr in floaterm#buflist#gather() + call floaterm#terminal#open_existing(bufnr) + endfor + return + endif + + let bufnr = a:bufnr + if bufnr == 0 && !empty(a:name) + let bufnr = floaterm#terminal#get_bufnr(a:name) + endif + if bufnr == 0 || bufnr == -1 + let bufnr = floaterm#buflist#curr() + endif + + if bufnr > 0 + call floaterm#util#autohide() + call floaterm#terminal#open_existing(bufnr) + else + call floaterm#util#show_msg('No floaterms with the bufnr or name', 'error') + endif endfunction -function! floaterm#send(bang, termname) abort +function! floaterm#hide(bang, bufnr, name) abort + if a:bang + for bufnr in floaterm#buflist#gather() + call floaterm#window#hide(bufnr) + endfor + return + endif + + let bufnr = a:bufnr + if bufnr == 0 && !empty(a:name) + let bufnr = floaterm#terminal#get_bufnr(a:name) + endif + if bufnr == 0 || bufnr == -1 + let bufnr = bufnr('%') + endif + + if bufnr > 0 + call floaterm#window#hide(bufnr) + else + call floaterm#util#show_msg('No floaterms with the bufnr or name', 'error') + endif +endfunction + +function! floaterm#send(bang, visualmode, range, line1, line2, argstr) abort if &filetype ==# 'floaterm' let msg = "FloatermSend can't be used in the floaterm window" call floaterm#util#show_msg(msg, 'warning') return endif - if a:termname != '' - let bufnr = floaterm#terminal#get_bufnr(a:termname) + let [cmd, config] = floaterm#cmdline#parse(split(a:argstr)) + let termname = get(config, 'termname', '') + if !empty(termname) + let bufnr = floaterm#terminal#get_bufnr(termname) if bufnr == -1 - call floaterm#util#show_msg('No floaterm found with name: ' . a:termname, 'error') + call floaterm#util#show_msg('No floaterm found with name: ' . termname, 'error') return endif else - let bufnr = floaterm#buflist#find_curr() + let bufnr = floaterm#buflist#curr() if bufnr == -1 - let bufnr = floaterm#new('', {}, {}) - call floaterm#toggle('') - call floaterm#send(a:bang, a:termname) - call floaterm#toggle('') + call floaterm#util#show_msg('No more floaterms', 'warning') return endif endif + if !empty(cmd) + call floaterm#terminal#send(bufnr, [cmd]) + return + endif - " https://vi.stackexchange.com/a/11028/17515 - let [lnum1, col1] = getpos("'<")[1:2] - let [lnum2, col2] = getpos("'>")[1:2] - let lines = getline(lnum1, lnum2) - let lines[-1] = lines[-1][: col2 - 1] - let lines[0] = lines[0][col1 - 1:] - - let linelist = [] - if a:bang ==# '!' - let line1 = lines[0] - let trim_line = substitute(line1, '\v^\s+', '', '') - let indent = len(line1) - len(trim_line) - for line in lines - if line[:indent] =~# '\s\+' - let line = line[indent:] - endif - call add(linelist, line) - endfor - else - let linelist = lines + let lines = floaterm#util#get_selected_text(a:visualmode, a:range, a:line1, a:line2) + if empty(lines) + call floaterm#util#show_msg('No lines were selected', 'error') + return + endif + + if a:bang + let lines = floaterm#util#leftalign_lines(lines) endif - call floaterm#terminal#send(bufnr, linelist) + call floaterm#terminal#send(bufnr, lines) endfunction diff --git a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/buffer.vim b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/buffer.vim index 30c23f7..66fef0e 100644 --- a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/buffer.vim +++ b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/buffer.vim @@ -1,23 +1,65 @@ -" vim:sw=2: " ============================================================================ " FileName: buffer.vim " Author: voldikss " GitHub: https://github.com/voldikss " ============================================================================ -function! floaterm#buffer#create(linelist, opts) abort +function! floaterm#buffer#create_scratch_buf(...) abort let bufnr = nvim_create_buf(v:false, v:true) - call nvim_buf_set_lines(bufnr, 0, -1, v:true, a:linelist) - for [name, value] in items(a:opts) - call nvim_buf_set_option(bufnr, name, value) - endfor + call nvim_buf_set_option(bufnr, 'buftype', 'nofile') + call nvim_buf_set_option(bufnr, 'buftype', 'nofile') + call nvim_buf_set_option(bufnr, 'bufhidden', 'wipe') + call nvim_buf_set_option(bufnr, 'swapfile', v:false) + call nvim_buf_set_option(bufnr, 'undolevels', -1) + let lines = get(a:, 1, v:null) + if type(lines) != 7 + call nvim_buf_set_option(bufnr, 'modifiable', v:true) + call nvim_buf_set_lines(bufnr, 0, -1, v:false, lines) + call nvim_buf_set_option(bufnr, 'modifiable', v:false) + endif return bufnr endfunction -function! floaterm#buffer#update_winopts(bufnr, winopts) abort - let winopts = getbufvar(a:bufnr, 'floaterm_winopts', {}) - for item in items(a:winopts) - let winopts[item[0]] = item[1] +function! floaterm#buffer#create_border_buf(options) abort + let repeat_width = a:options.width - 2 + let repeat_height = a:options.height - 2 + let title = a:options.title + let title = empty(title) ? title : (' ' . title . ' ') + let title_width = strdisplaywidth(title) + let borderchars = a:options.borderchars + let [c_top, c_right, c_bottom, c_left, c_topleft, c_topright, c_botright, c_botleft] = borderchars + let content = [c_topleft . title . repeat(c_top, repeat_width - title_width) . c_topright] + let content += repeat([c_left . repeat(' ', repeat_width) . c_right], repeat_height) + let content += [c_botleft . repeat(c_bottom, repeat_width) . c_botright] + return floaterm#buffer#create_scratch_buf(content) +endfunction + +function! floaterm#buffer#get_config(bufnr, key, ...) abort + let key = 'floaterm_' . a:key + let val = getbufvar(a:bufnr, key) + if val == '' && a:0 == 1 + return a:1 + endif + return val +endfunction + +function! floaterm#buffer#get_config_dict(bufnr) abort + let config = {} + for var in items(getbufvar(a:bufnr, '')) + if var[0] =~ '^floaterm_' + let config[var[0][9:]] = var[1] + endif + endfor + return config +endfunction + +function! floaterm#buffer#set_config(bufnr, key, val) abort + let key = 'floaterm_' . a:key + call setbufvar(a:bufnr, key, a:val) +endfunction + +function! floaterm#buffer#set_config_dict(bufnr, config) abort + for [key, val] in items(a:config) + call floaterm#buffer#set_config(a:bufnr, key, val) endfor - call setbufvar(a:bufnr, 'floaterm_winopts', winopts) endfunction diff --git a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/buflist.vim b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/buflist.vim index 85d4d31..4e4052f 100644 --- a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/buflist.vim +++ b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/buflist.vim @@ -29,7 +29,6 @@ endfunction function! s:node.is_valid() dict abort return bufexists(self.bufnr) - " return bufexists(self.bufnr) && floaterm#terminal#jobexists(self.bufnr) endfunction @@ -83,7 +82,7 @@ endfunction " Find next bufnr with bufexists(bufnr) == v:true " If not found, return -1 " If bufexists(bufnr) != v:true, remove that node -function! s:buflist.find_next() dict abort +function! s:buflist.next() dict abort let node = self.index.next while !node.is_valid() call self.remove(node) @@ -99,7 +98,7 @@ endfunction " Find prev bufnr with bufexists(bufnr) == v:true " If not found, return -1 " If bufexists(bufnr) != v:true, remove that node -function! s:buflist.find_prev() dict abort +function! s:buflist.prev() dict abort let node = self.index.prev while !node.is_valid() call self.remove(node) @@ -115,7 +114,7 @@ endfunction " Find current bufnr with bufexists(bufnr) == v:true " If not found, find next and next " If bufexists(bufnr) != v:true, remove that node -function! s:buflist.find_curr() dict abort +function! s:buflist.curr() dict abort let node = self.index while !node.is_valid() call self.remove(node) @@ -128,6 +127,36 @@ function! s:buflist.find_curr() dict abort return node.bufnr endfunction +" Find the first bufnr with bufexists(bufnr) == v:true +" If bufexists(bufnr) != v:true, remove that node +function! s:buflist.first() dict abort + let node = self.head.next + while !node.is_valid() + call self.remove(node) + if self.empty() + return -1 + endif + let node = node.next + endwhile + let self.index = node + return node.bufnr +endfunction + +" Find the last bufnr with bufexists(bufnr) == v:true +" If bufexists(bufnr) != v:true, remove that node +function! s:buflist.last() dict abort + let node = self.head.prev + while !node.is_valid() + call self.remove(node) + if self.empty() + return -1 + endif + let node = node.prev + endwhile + let self.index = node + return node.bufnr +endfunction + " Return buflist str, note that node.bufnr may not exist function! s:buflist.to_string() dict abort let str = '[-' @@ -139,7 +168,7 @@ function! s:buflist.to_string() dict abort let curr = curr.next endwhile let str .= '-]' - let str .= ' current index: ' . self.index.bufnr + let str .= ' current floaterm buffer number: ' . self.index.bufnr return str endfunction @@ -166,14 +195,20 @@ function! floaterm#buflist#add(bufnr) abort let node = s:node.new(a:bufnr) call s:buflist.insert(node) endfunction -function! floaterm#buflist#find_next() abort - return s:buflist.find_next() +function! floaterm#buflist#next() abort + return s:buflist.next() +endfunction +function! floaterm#buflist#prev() abort + return s:buflist.prev() +endfunction +function! floaterm#buflist#curr() abort + return s:buflist.curr() endfunction -function! floaterm#buflist#find_prev() abort - return s:buflist.find_prev() +function! floaterm#buflist#first() abort + return s:buflist.first() endfunction -function! floaterm#buflist#find_curr() abort - return s:buflist.find_curr() +function! floaterm#buflist#last() abort + return s:buflist.last() endfunction function! floaterm#buflist#info() abort echom s:buflist.to_string() diff --git a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/cmdline.vim b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/cmdline.vim index d080db5..bae7654 100644 --- a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/cmdline.vim +++ b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/cmdline.vim @@ -7,88 +7,170 @@ " ---------------------------------------------------------------------------- " used for `:FloatermNew` and `:FloatermUpdate` -" parse argument list to `cmd`(string, default '') and `winopts`(dict) +" parse argument list to `cmd`(string, default '') and `config`(dict) " ---------------------------------------------------------------------------- function! floaterm#cmdline#parse(arglist) abort - let winopts = {} + let config = {} let cmd = '' if a:arglist != [] let c = 0 for arg in a:arglist - let opt = split(arg, '=') - if len(opt) == 1 - let cmd = join(a:arglist[c:]) - break - elseif len(opt) == 2 - let [key, value] = opt - if key == 'height' || key == 'width' + if arg =~ '^--\S.*=\?.*$' + let pair = split(arg, '=') + if len(pair) != 2 + if index(['--silent'], pair[0]) >= 0 + let [key, value] = [pair[0][2:], v:true] + else + call floaterm#util#show_msg('Argument Error: No value given to option: ' . pair[0], 'error') + return [cmd, config] + endif + else + let [key, value] = [pair[0][2:], pair[1]] + endif + if index(['height', 'width', 'autoclose'], key) > -1 let value = eval(value) endif - let winopts[key] = value + let config[key] = value + else + let cmd = s:expand(join(a:arglist[c:])) + break endif let c += 1 endfor endif - return [cmd, winopts] + return [cmd, config] +endfunction + +function! s:expand(cmd) abort + let wildchars = '\(%\|#\|#\d\|\|\|\|\|\|\|\|\|\|\|\|\|\)' + let cmd = substitute(a:cmd, '\([^\\]\|^\)\zs' . wildchars . '\(<\|\(\(:g\=s?.*?.*?\)\|\(:[phtreS8\~\.]\)\)*\)\ze', '\=expand(submatch(0))', 'g') + let cmd = substitute(cmd, '\zs\\' . wildchars, '\=submatch(0)[1:]', 'g') + return cmd endfunction " ---------------------------------------------------------------------------- " used for `:FloatermNew` and `:FloatermUpdate` " ---------------------------------------------------------------------------- +let s:shellcmds = [] function! floaterm#cmdline#complete(arg_lead, cmd_line, cursor_pos) abort - let winopts_key = ['height=', 'width=', 'wintype=', 'name=', 'position='] - if a:cmd_line =~ '^FloatermNew' - let candidates = winopts_key + sort(getcompletion('', 'shellcmd')) - elseif a:cmd_line =~ '^FloatermUpdate' - let candidates = winopts_key - endif + let options = [ + \ '--cwd=', + \ '--name=', + \ '--width=', + \ '--height=', + \ '--title=', + \ '--silent', + \ '--wintype=', + \ '--position=', + \ '--autoclose=', + \ '--borderchars=', + \ ] let cmd_line_before_cursor = a:cmd_line[:a:cursor_pos - 1] let args = split(cmd_line_before_cursor, '\v\\@ -1 - if has('nvim') - let wintypes = ['normal', 'floating'] + if match(a:arg_lead, '--wintype=') > -1 + let vals = ['normal', 'float'] + let candidates = map(vals, {idx -> '--wintype=' . vals[idx]}) + elseif match(a:arg_lead, '--position=') > -1 + let vals = [ + \ 'top', + \ 'right', + \ 'bottom', + \ 'left', + \ 'center', + \ 'topleft', + \ 'topright', + \ 'bottomleft', + \ 'bottomright', + \ 'auto', + \ ] + let candidates = map(vals, {idx -> '--position=' . vals[idx]}) + elseif match(a:arg_lead, '--autoclose=') > -1 + let vals = [0, 1, 2] + let candidates = map(vals, {idx -> '--autoclose=' . vals[idx]}) + elseif match(a:arg_lead, '--silent') > -1 + return [] + elseif match(a:arg_lead, '--cwd=') > -1 + let prestr = matchstr(a:arg_lead, '--cwd=\zs.*\ze') + let dirs = getcompletion(prestr, 'dir') + [''] + return map(dirs, { k,v -> '--cwd=' . v }) + elseif match(a:arg_lead, '--name=') > -1 + return [] + elseif match(a:arg_lead, '--width=') > -1 + return [] + elseif match(a:arg_lead, '--height=') > -1 + return [] + elseif match(a:arg_lead, '--title=') > -1 + return [] + elseif match(a:arg_lead, '--borderchars=') > -1 + return [] + " The dash absolutely belongs to the `options` instead of executable + " commands(e.g. `nvim-qt.exe`). So if `a:arg_lead` matches 1 or 2 dash, the + " user wants to complete options. + elseif match(a:arg_lead, '^--\=\S*$') > -1 + let candidates = options + elseif a:arg_lead == '' + if a:cmd_line =~ '^FloatermUpdate' + return options + elseif empty(options) + let s:shellcmds = sort(getcompletion('', 'shellcmd')) + return s:shellcmds else - let wintypes = ['normal', 'popup'] + return options + endif + else + if a:cmd_line =~ '^FloatermUpdate' + return [repeat(' ', len(a:arg_lead))] + else + let candidates = sort(getcompletion(a:arg_lead, 'shellcmd')) endif - let candidates = map(wintypes, {idx -> 'wintype=' . wintypes[idx]}) - elseif match(prefix, 'position=') > -1 - let position = ['top', 'right', 'bottom', 'left', 'center', 'topleft', 'topright', 'bottomleft', 'bottomright', 'auto'] - let candidates = map(position, {idx -> 'position=' . position[idx]}) endif - return filter(candidates, 'v:val[:len(prefix) - 1] ==# prefix') + return filter(candidates, 'v:val[:len(a:arg_lead) - 1] == a:arg_lead') endfunction " ---------------------------------------------------------------------------- -" used for `:FloatermToggle` +" used for `:FloatermToggle`, `:FloatermHide`, `:FloatermShow`, `:FloatermKill` " ---------------------------------------------------------------------------- -function! floaterm#cmdline#floaterm_names(arg_lead, cmd_line, cursor_pos) abort +function! floaterm#cmdline#complete_names1(...) abort let buflist = floaterm#buflist#gather() let ret = [] - let pattern = '^floaterm://' for bufnr in buflist - let winopts = getbufvar(bufnr, 'floaterm_winopts', {}) - if !empty(winopts) - let termname = get(winopts, 'name', '') - if !empty(termname) - call add(ret, termname) - endif + let termname = floaterm#buffer#get_config(bufnr, 'name', '') + if !empty(termname) + call add(ret, termname) endif endfor return ret endfunction + +" ---------------------------------------------------------------------------- +" used for `:FloatermSend` +" ---------------------------------------------------------------------------- +function! floaterm#cmdline#complete_names2(arg_lead, cmd_line, cursor_pos) abort + let candidates = ['--name='] + let cmd_line_before_cursor = a:cmd_line[:a:cursor_pos - 1] + let args = split(cmd_line_before_cursor, '\v\\@ -1 + let names = floaterm#cmdline#complete_names1() + let candidates = map(names, {idx -> '--name=' . names[idx]}) + endif + return filter(candidates, 'v:val[:len(a:arg_lead) - 1] == a:arg_lead') +endfunction diff --git a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/resolver.vim b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/path.vim similarity index 90% rename from etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/resolver.vim rename to etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/path.vim index 0d31efc..e21978f 100644 --- a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/resolver.vim +++ b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/path.vim @@ -1,6 +1,6 @@ " vim:sw=2: " ============================================================================ -" FileName: resolver.vim +" FileName: path.vim " Author: voldikss " GitHub: https://github.com/voldikss " Description: This is modified from part of skywind3000/asyncrun @@ -16,9 +16,6 @@ endif function! s:find_root(path, markers, strict) abort function! s:guess_root(filename, markers) abort let fullname = s:fullname(a:filename) - if exists('b:asyncrun_root') - return b:asyncrun_root - endif if fullname =~ '^fugitive:/' if exists('b:git_dir') return fnamemodify(b:git_dir, ':h') @@ -65,7 +62,7 @@ function! s:find_root(path, markers, strict) abort endfunction " Replace string -function! s:StringReplace(text, old, new) abort +function! s:string_replace(text, old, new) abort let l:data = split(a:text, a:old, 1) return join(l:data, a:new) endfunction @@ -129,17 +126,16 @@ function! s:path_join(home, name) abort endif endfunction -function! floaterm#resolver#get_root() abort - let markers = g:floaterm_rootmarkers +function! floaterm#path#get_root() abort let strict = 0 - let l:hr = s:find_root(getcwd(), markers, strict) + let l:hr = s:find_root(getcwd(), g:floaterm_rootmarkers, strict) if s:is_windows - let l:hr = s:StringReplace(l:hr, '/', "\\") + let l:hr = s:string_replace(l:hr, '/', "\\") endif return l:hr endfunction -function! floaterm#resolver#chdir(path) abort +function! floaterm#path#chdir(path) abort if has('nvim') let cmd = haslocaldir()? 'lcd' : (haslocaldir(-1, 0)? 'tcd' : 'cd') else diff --git a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/terminal.vim b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/terminal.vim index 79949da..6b81a42 100644 --- a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/terminal.vim +++ b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/terminal.vim @@ -7,163 +7,157 @@ let s:channel_map = {} let s:is_win = has('win32') || has('win64') -let s:has_popup = has('textprop') && has('patch-8.2.0286') -let s:has_float = has('nvim') && exists('*nvim_win_set_config') - -if g:floaterm_wintype == v:null - if s:has_float - let s:wintype = 'floating' - elseif s:has_popup - let s:wintype = 'popup' - else - let s:wintype = 'normal' - endif -elseif g:floaterm_wintype == 'floating' && !s:has_float - call floaterm#util#show_msg("floating window is not supported in your nvim, fall back to normal window", 'warning') - let s:wintype = 'normal' -elseif g:floaterm_wintype == 'popup' && !s:popup - call floaterm#util#show_msg("popup window is not supported in your vim, fall back to normal window", 'warning') - let s:wintype = 'normal' -else - let s:wintype = g:floaterm_wintype -endif - -function! s:on_floaterm_open(bufnr, winid, winopts) abort - call setbufvar(a:bufnr, 'floaterm_winid', a:winid) - call setbufvar(a:bufnr, 'floaterm_winopts', a:winopts) - let termname = get(a:winopts, 'name', '') - if termname != '' - let termname = 'floaterm://' . termname - execute 'file ' . termname - endif +function! s:on_floaterm_open(bufnr) abort call setbufvar(a:bufnr, '&buflisted', 0) call setbufvar(a:bufnr, '&filetype', 'floaterm') if has('nvim') - let winnr = bufwinnr(a:bufnr) - call setwinvar(winnr, '&winblend', g:floaterm_winblend) - call setwinvar(winnr, '&winhl', 'NormalFloat:Floaterm,Normal:Floaterm') - augroup close_floaterm_window - execute 'autocmd! TermClose call s:on_floaterm_close(' . a:bufnr .')' - execute 'autocmd! BufHidden call floaterm#window#hide_floaterm_border(' . a:bufnr . ')' - augroup END - endif - if g:floaterm_autoinsert == v:true - call floaterm#util#startinsert() + " TODO: need to be reworked + execute printf( + \ 'autocmd BufHidden,BufWipeout ++once call floaterm#window#hide(%s)', + \ a:bufnr, + \ a:bufnr + \ ) endif endfunction -function! s:on_floaterm_close(bufnr) abort - if getbufvar(a:bufnr, '&filetype') != 'floaterm' - return +function! s:on_floaterm_close(bufnr, callback, job, data, ...) abort + if a:bufnr == -1 + " In vim, buffnr is not known before starting a job, therefore, it's + " impossible to pass the bufnr to a job's callback function. Also change + " callback after a job was spawned seem not feasible. Therefore, iterate s: + " channel_map and get the bufnr whose channel matches the channel of a:job + for [buf, chan] in items(s:channel_map) + if chan == job_getchannel(a:job) + let bufnr = str2nr(buf) + break + endif + endfor + else + let bufnr = a:bufnr + endif + call setbufvar(bufnr, '&bufhidden', 'wipe') + call floaterm#buffer#set_config(bufnr, 'jobexists', v:false) + let autoclose = floaterm#buffer#get_config(bufnr, 'autoclose', 0) + if (autoclose == 1 && a:data == 0) || (autoclose == 2) || (a:callback isnot v:null) + call floaterm#window#hide(bufnr) + " if the floaterm is created with --silent, delete the buffer explicitly + silent! execute bufnr . 'bdelete!' + " update lightline + doautocmd BufDelete + endif + if a:callback isnot v:null + call a:callback(a:job, a:data, 'exit') endif - " NOTE: MUST hide border BEFORE deleting floaterm buffer - call floaterm#window#hide_floaterm_border(a:bufnr) - bdelete! - doautocmd BufDelete " call lightline#update() endfunction -function! floaterm#terminal#open(bufnr, cmd, jobopts, winopts) abort - " for vim's popup, must close popup can we open and jump to a new window - if !has('nvim') - call floaterm#window#hide_floaterm(bufnr('%')) +" config: local configuration of a specific floaterm, including: +" cwd, name, width, height, title, silent, wintype, position, autoclose, etc. +function! floaterm#terminal#open(bufnr, cmd, jobopts, config) abort + " vim8: must close popup can we open and jump to a new window + if !has('nvim') && &filetype == 'floaterm' + call floaterm#window#hide(bufnr('%')) endif - " change to root directory - if !empty(g:floaterm_rootmarkers) - let dest = floaterm#resolver#get_root() - if dest !=# '' - call floaterm#resolver#chdir(dest) - endif + " just open if floaterm exists + if a:bufnr > 0 + call floaterm#window#open(a:bufnr, a:config) + call s:on_floaterm_open(a:bufnr) + return a:bufnr endif - let width = type(g:floaterm_width) == 7 ? 0.6 : g:floaterm_width - let width = get(a:winopts, 'width', width) - if type(width) == v:t_float | let width = width * &columns | endif - let width = float2nr(width) + " change cwd + let savedcwd = getcwd() + let dest = get(a:config, 'cwd', '') + if dest == '' + let dest = floaterm#path#get_root() + endif + if !empty(dest) + call floaterm#path#chdir(dest) + endif - let height = type(g:floaterm_height) == 7 ? 0.6 : g:floaterm_height - let height = get(a:winopts, 'height', height) - if type(height) == v:t_float | let height = height * &lines | endif - let height = float2nr(height) + " spawn terminal + let bufnr = s:spawn_terminal(a:cmd, a:jobopts, a:config) - let wintype = get(a:winopts, 'wintype', s:wintype) - let pos = get(a:winopts, 'position', g:floaterm_position) + " hide floaterm immediately if silent + if floaterm#buffer#get_config(bufnr, 'silent', 0) + call floaterm#window#hide(bufnr) + stopinsert + endif - if a:bufnr > 0 - if wintype == 'floating' - let winid = floaterm#window#open_floating(a:bufnr, width, height, pos) - elseif wintype == 'popup' - let winid = floaterm#window#open_popup(a:bufnr, width, height, pos) - else - let winid = floaterm#window#open_split(a:bufnr, height, width, pos) - endif - call s:on_floaterm_open(a:bufnr, winid, a:winopts) - return 0 + " restore cwd + call floaterm#path#chdir(savedcwd) + + return bufnr +endfunction + +function! floaterm#terminal#open_existing(bufnr) abort + if !bufexists(a:bufnr) + call floaterm#util#show_msg(printf("Buffer %s doesn't exists", a:bufnr), 'error') + return + endif + let winnr = bufwinnr(a:bufnr) + if winnr > -1 + execute winnr . 'hide' endif + let config = floaterm#buffer#get_config_dict(a:bufnr) + call floaterm#terminal#open(a:bufnr, '', {}, config) +endfunction +function! s:spawn_terminal(cmd, jobopts, config) abort if has('nvim') let bufnr = nvim_create_buf(v:false, v:true) call floaterm#buflist#add(bufnr) - if wintype == 'floating' - let winid = floaterm#window#open_floating(bufnr, width, height, pos) - call nvim_set_current_win(winid) - let ch = termopen(a:cmd, a:jobopts) - let s:channel_map[bufnr] = ch - else - let winid = floaterm#window#open_split(bufnr, height, width, pos) - let ch = termopen(a:cmd, a:jobopts) - let s:channel_map[bufnr] = ch - endif + let a:jobopts.on_exit = function( + \ 's:on_floaterm_close', + \ [bufnr, get(a:jobopts, 'on_exit', v:null)] + \ ) + call floaterm#window#open(bufnr, a:config) + let ch = termopen(a:cmd, a:jobopts) + let s:channel_map[bufnr] = ch else + let a:jobopts.exit_cb = function( + \ 's:on_floaterm_close', + \ [-1, get(a:jobopts, 'on_exit', v:null)] + \ ) if has_key(a:jobopts, 'on_exit') - let a:jobopts['exit_cb'] = a:jobopts.on_exit unlet a:jobopts.on_exit endif - let a:jobopts.hidden = 1 - let a:jobopts.term_finish = 'close' if has('patch-8.1.2080') let a:jobopts.term_api = 'floaterm#util#edit' endif - let bufnr = term_start(a:cmd, a:jobopts) + let a:jobopts.hidden = 1 + try + let bufnr = term_start(a:cmd, a:jobopts) + catch + call floaterm#util#show_msg('Failed to execute: ' . a:cmd, 'error') + return + endtry call floaterm#buflist#add(bufnr) let job = term_getjob(bufnr) let s:channel_map[bufnr] = job_getchannel(job) - if wintype == 'popup' - let winid = floaterm#window#open_popup(bufnr, width, height, pos) - else - let winid = floaterm#window#open_split(bufnr, height, width, pos) - endif + call floaterm#window#open(bufnr, a:config) endif - - let a:winopts.width = width - let a:winopts.height = height - let a:winopts.wintype = wintype - let a:winopts.pos = pos - call s:on_floaterm_open(bufnr, winid, a:winopts) + call floaterm#buffer#set_config(bufnr, 'jobexists', v:true) + call s:on_floaterm_open(bufnr) return bufnr endfunction -function! floaterm#terminal#open_existing(bufnr) abort - let winopts = getbufvar(a:bufnr, 'floaterm_winopts', {}) - call floaterm#terminal#open(a:bufnr, '', {}, winopts) -endfunction - function! floaterm#terminal#send(bufnr, cmds) abort let ch = get(s:channel_map, a:bufnr, v:null) - if empty(ch) | return | endif + if empty(ch) || empty(a:cmds) + return + endif if has('nvim') - if !empty(a:cmds[len(a:cmds) - 1]) - call add(a:cmds, '') - endif + call add(a:cmds, '') call chansend(ch, a:cmds) let curr_winnr = winnr() let ch_winnr = bufwinnr(a:bufnr) if ch_winnr > 0 - execute ch_winnr . 'wincmd w' - execute 'normal! G' + noautocmd execute ch_winnr . 'wincmd w' + noautocmd execute 'normal! G' endif - execute curr_winnr . 'wincmd w' + noautocmd execute curr_winnr . 'wincmd w' else let newline = s:is_win ? "\r\n" : "\n" call ch_sendraw(ch, join(a:cmds, newline) . newline) @@ -171,19 +165,44 @@ function! floaterm#terminal#send(bufnr, cmds) abort endfunction function! floaterm#terminal#get_bufnr(termname) abort - return bufnr('floaterm://' . a:termname) + let buflist = floaterm#buflist#gather() + for bufnr in buflist + let name = floaterm#buffer#get_config(bufnr, 'name') + if name ==# a:termname + return bufnr + endif + endfor + return -1 endfunction +function! floaterm#terminal#kill(bufnr) abort + call floaterm#window#hide(a:bufnr) + if has('nvim') + let job = getbufvar(a:bufnr, '&channel') + if jobwait([job], 0)[0] == -1 + call jobstop(job) + endif + else + let job = term_getjob(a:bufnr) + if job != v:null && job_status(job) !=# 'dead' + call job_stop(job, 'kill') + endif + endif + try + if bufexists(a:bufnr) + execute a:bufnr . 'bwipeout!' + endif + catch + call popup_close(win_getid()) + endtry +endfunction -"----------------------------------------------------------------------------- -" check if a job is running in the buffer(not used) -"----------------------------------------------------------------------------- function! floaterm#terminal#jobexists(bufnr) abort if has('nvim') - let jobid = getbufvar(a:bufnr, '&channel') - return jobwait([jobid], 0)[0] == -1 + let job = getbufvar(a:bufnr, '&channel') + return jobwait([job], 0)[0] == -1 else let job = term_getjob(a:bufnr) - return job_status(job) !=# 'dead' + return job != v:null && job_status(job) != 'dead' endif endfunction diff --git a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/util.vim b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/util.vim index ce9738e..d8acd79 100644 --- a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/util.vim +++ b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/util.vim @@ -5,81 +5,112 @@ " GitHub: https://github.com/voldikss " ============================================================================ -function! s:echo(group, msg) abort - if a:msg ==# '' | return | endif - execute 'echohl' a:group - echo a:msg - echon ' ' - echohl NONE -endfunction - -function! s:echon(group, msg) abort - if a:msg ==# '' | return | endif - execute 'echohl' a:group - echon a:msg - echon ' ' - echohl NONE +function! s:echohl(group, msg) abort + execute 'echohl ' . a:group + echom '[vim-floaterm] ' . a:msg + echohl None endfunction function! floaterm#util#show_msg(message, ...) abort if a:0 == 0 - let msg_type = 'info' + let msgtype = 'info' else - let msg_type = a:1 + let msgtype = a:1 endif - if type(a:message) != 1 + if type(a:message) != v:t_string let message = string(a:message) else let message = a:message endif - call s:echo('Constant', '[vim-floaterm]') - - if msg_type ==# 'info' - call s:echon('Normal', message) - elseif msg_type ==# 'warning' - call s:echon('WarningMsg', message) - elseif msg_type ==# 'error' - call s:echon('Error', message) + if msgtype ==# 'info' + call s:echohl('MoreMsg', message) + elseif msgtype ==# 'warning' + call s:echohl('WarningMsg', message) + elseif msgtype ==# 'error' + call s:echohl('ErrorMsg', message) endif endfunction function! floaterm#util#edit(_bufnr, filename) abort - call floaterm#hide() + call floaterm#hide(1, 0, '') silent execute g:floaterm_open_command . ' ' . a:filename endfunction function! floaterm#util#startinsert() abort - if mode() == 'i' | return | endif - if has('nvim') - startinsert - else - silent! execute 'normal! i' + if !g:floaterm_autoinsert + call feedkeys("\\", 'n') + elseif mode() != 'i' + if has('nvim') + startinsert + else + silent! execute 'normal! i' + endif endif endfunction -"----------------------------------------------------------------------------- -" compose two string(thank skywind3000/vim-quickui) -"----------------------------------------------------------------------------- -function! floaterm#util#string_compose(target, pos, source) - if a:source == '' - return a:target +function! floaterm#util#autohide() abort + " hide all floaterms before opening a new floaterm + if g:floaterm_autohide + call floaterm#hide(1, 0, '') endif - let pos = a:pos - let source = a:source - if pos < 0 - let source = strcharpart(a:source, -pos) - let pos = 0 +endfunction + +function! floaterm#util#getbuflines(bufnr, length) abort + let lines = [] + if a:bufnr == -1 + for bufnr in floaterm#buflist#gather() + let lnum = getbufinfo(bufnr)[0]['lnum'] + let lines += getbufline(bufnr, max([lnum - a:length, 0]), '$') + endfor + else + let lnum = getbufinfo(a:bufnr)[0]['lnum'] + let lines += getbufline(a:bufnr, max([lnum - a:length, 0]), '$') endif - let target = strcharpart(a:target, 0, pos) - if strchars(target) < pos - let target .= repeat(' ', pos - strchars(target)) + return lines +endfunction + +function! floaterm#util#get_selected_text(visualmode, range, line1, line2) abort + if a:range == 0 + let lines = [getline('.')] + elseif a:range == 1 + let lines = [getline(a:line1)] + else + let [lnum1, col1] = getpos("'<")[1:2] + let [lnum2, col2] = getpos("'>")[1:2] + if lnum1 == 0 || col1 == 0 || lnum2 == 0 || col2 == 0 + let lines = getline(a:line1, a:line2) + else + let lines = getline(lnum1, lnum2) + if !empty(lines) + if a:visualmode ==# 'v' + let lines[-1] = lines[-1][: col2 - (&selection == 'inclusive' ? 1 : 2)] + let lines[0] = lines[0][col1 - 1:] + elseif a:visualmode ==# 'V' + elseif a:visualmode == "\" + let i = 0 + for line in lines + let lines[i] = line[col1 - 1: col2 - (&selection == 'inclusive' ? 1 : 2)] + let i = i + 1 + endfor + endif + endif + endif endif - let target .= source - " vim popup will pad the end of title but not begin part - " so we build the title as ' floaterm idx/cnt' - " therefore, we need to add a space here - let target .= ' ' . strcharpart(a:target, pos + strchars(source) + 1) - return target + return lines +endfunction + +function! floaterm#util#leftalign_lines(lines) abort + let linelist = [] + let line1 = a:lines[0] + let trim_line = substitute(line1, '\v^\s+', '', '') + let indent = len(line1) - len(trim_line) + for line in a:lines + if line[:indent] =~# '\s\+' + let line = line[indent:] + endif + call add(linelist, line) + endfor + return linelist endfunction diff --git a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/window.vim b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/window.vim index 7de6969..cc87d73 100644 --- a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/window.vim +++ b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/window.vim @@ -5,84 +5,70 @@ " GitHub: https://github.com/voldikss " ============================================================================ -" winid: floaterm window id -function! s:add_border(winid, title) abort - let winopts = nvim_win_get_config(a:winid) - let top = g:floaterm_borderchars[4] . - \ repeat(g:floaterm_borderchars[0], winopts.width) . - \ g:floaterm_borderchars[5] - let mid = g:floaterm_borderchars[3] . - \ repeat(' ', winopts.width) . - \ g:floaterm_borderchars[1] - let bot = g:floaterm_borderchars[7] . - \ repeat(g:floaterm_borderchars[2], winopts.width) . - \ g:floaterm_borderchars[6] - let top = floaterm#util#string_compose(top, 1, a:title) - let lines = [top] + repeat([mid], winopts.height) + [bot] - let buf_opts = {} - let buf_opts.synmaxcol = 3000 " #17 - let buf_opts.filetype = 'floaterm_border' - let border_bufnr = floaterm#buffer#create(lines, buf_opts) - call nvim_buf_set_option(border_bufnr, 'bufhidden', 'wipe') - let winopts.row -= (winopts.anchor[0] == 'N' ? 1 : -1) - " adjust offset - if winopts.row < 0 - let winopts.row = 1 - call nvim_win_set_config(a:winid, winopts) - let winopts.row = 0 +let s:has_popup = has('textprop') && has('patch-8.2.0286') +let s:has_float = has('nvim') && exists('*nvim_win_set_config') + +function! s:get_wintype() abort + if empty(g:floaterm_wintype) + if s:has_float || s:has_popup + return 'float' + else + return 'normal' + endif + elseif g:floaterm_wintype == 'normal' + return 'normal' + else " backward compatiblity: float|floating|popup -> float + if s:has_float || s:has_popup + return 'float' + else + call floaterm#util#show_msg("floating or popup feature is not found, fall back to normal window", 'warning') + return 'normal' + endif endif - let winopts.col -= (winopts.anchor[1] == 'W' ? 1 : -1) - let winopts.width += 2 - let winopts.height += 2 - let winopts.style = 'minimal' - let winopts.focusable = v:false - let border_winid = nvim_open_win(border_bufnr, v:false, winopts) - call nvim_win_set_option(border_winid, 'winhl', 'NormalFloat:FloatermBorder') - return border_winid endfunction -function! s:build_title(bufnr) abort - if !g:floaterm_wintitle - return '' - endif +function! s:make_title(bufnr, text) abort + if empty(a:text) | return '' | endif let buffers = floaterm#buflist#gather() let cnt = len(buffers) let idx = index(buffers, a:bufnr) + 1 - return printf(' floaterm: %s/%s', idx, cnt) + let title = substitute(a:text, '$1', idx, 'gm') + let title = substitute(title, '$2', cnt, 'gm') + return title endfunction -function! s:floatwin_pos(width, height, pos) abort +function! s:get_floatwin_pos(width, height, pos) abort if a:pos == 'topright' - let row = 2 - let col = &columns - 1 + let row = 1 + let col = &columns let anchor = 'NE' elseif a:pos == 'topleft' - let row = 2 - let col = 1 + let row = 1 + let col = 0 let anchor = 'NW' elseif a:pos == 'bottomright' - let row = &lines - 3 - let col = &columns - 1 + let row = &lines - &cmdheight - 1 + let col = &columns let anchor = 'SE' elseif a:pos == 'bottomleft' - let row = &lines - 3 - let col = 1 + let row = &lines - &cmdheight - 1 + let col = 0 let anchor = 'SW' elseif a:pos == 'top' - let row = 2 + let row = 1 let col = (&columns - a:width)/2 let anchor = 'NW' elseif a:pos == 'right' let row = (&lines - a:height)/2 - let col = &columns - 1 + let col = &columns let anchor = 'NE' elseif a:pos == 'bottom' - let row = &lines - 3 + let row = &lines - &cmdheight - 1 let col = (&columns - a:width)/2 let anchor = 'SW' elseif a:pos == 'left' let row = (&lines - a:height)/2 - let col = 1 + let col = 0 let anchor = 'NW' elseif a:pos == 'center' let row = (&lines - a:height)/2 @@ -95,13 +81,14 @@ function! s:floatwin_pos(width, height, pos) abort let col = 0 endif else " at the cursor place - let curr_pos = getpos('.') - let row = curr_pos[1] - line('w0') - let col = curr_pos[2] - if row + a:height <= &lines + let winpos = win_screenpos(0) + let row = winpos[0] - 1 + winline() + let col = winpos[1] - 1 + wincol() + if row + a:height <= &lines - &cmdheight - 1 let vert = 'N' else let vert = 'S' + let row -= 1 endif if col + a:width <= &columns let hor = 'W' @@ -123,94 +110,201 @@ function! s:winexists(winid) abort return !empty(getwininfo(a:winid)) endfunction -function! floaterm#window#open_floating(bufnr, width, height, pos) abort - let [row, col, anchor] = s:floatwin_pos(a:width, a:height, a:pos) - let opts = { - \ 'relative': 'editor', - \ 'anchor': anchor, - \ 'row': row, - \ 'col': col, - \ 'width': a:width, - \ 'height': a:height, - \ 'style':'minimal' - \ } - let winid = nvim_open_win(a:bufnr, v:true, opts) - let border_winid = getbufvar(a:bufnr, 'floaterm_border_winid', v:null) - if border_winid == v:null || !s:winexists(border_winid) - let title = s:build_title(a:bufnr) - let border_winid = s:add_border(winid, title) - call setbufvar(a:bufnr, 'floaterm_border_winid', border_winid) +" TODO: give this function a better name +" @argument: config, a floaterm local variable, will be stored as a `b:` variable +" @return: config, generated from `a:config`, has more additional info, used to +" config the floaterm style +function! s:parse_config(bufnr, config) abort + let a:config.title = get(a:config, 'title', g:floaterm_title) + let a:config.width = get(a:config, 'width', g:floaterm_width) + let a:config.height = get(a:config, 'height', g:floaterm_height) + let a:config.wintype = get(a:config, 'wintype', s:get_wintype()) + let a:config.position = get(a:config, 'position', g:floaterm_position) + let a:config.autoclose = get(a:config, 'autoclose', g:floaterm_autoclose) + let a:config.borderchars = get(a:config, 'borderchars', g:floaterm_borderchars) + + if type(a:config.height) == v:t_number && a:config.height < 3 + call floaterm#util#show_msg('Floaterm height should be at least 3', 'warning') + let a:config.height = 3 + endif + if type(a:config.width) == v:t_number && a:config.width < 3 + call floaterm#util#show_msg('Floaterm width should be at least 3', 'warning') + let a:config.width = 3 endif + + " Dump these configs into buffer, they can be reused for reopening + call floaterm#buffer#set_config_dict(a:bufnr, a:config) + + " The following configs (width, height, borderchars, position) should be + " parsed and become static. After opening windows, the configs are discard + let config = deepcopy(a:config) + + let width = config.width + if type(width) == v:t_float | let width = width * &columns | endif + let config.width = float2nr(width) + + let height = config.height + if type(height) == v:t_float | let height = height * (&lines - &cmdheight - 1) | endif + let config.height = float2nr(height) + + let borderchars = config.borderchars + " g:floaterm_borderchars is type v:t_list in old version vim-floaterm + " strcharpart is useful for multiple-byte characters + if type(borderchars) == v:t_string + let borderchars = map(range(8), { idx -> strcharpart(borderchars, idx, 1) }) + endif + let config.borderchars = borderchars + + if config.position == 'random' + let randnum = str2nr(matchstr(reltimestr(reltime()), '\v\.@<=\d+')[1:]) + if s:get_wintype() == 'normal' + let config.position = ['top', 'right', 'bottom', 'left'][randnum % 4] + else + let config.position = ['top', 'right', 'bottom', 'left', 'center', 'topleft', 'topright', 'bottomleft', 'bottomright', 'auto'][randnum % 10] + endif + endif + + let [row, col, anchor] = s:get_floatwin_pos(config.width, config.height, config.position) + let config['anchor'] = anchor + let config['row'] = row + let config['col'] = col + return config +endfunction + +function! s:open_float(bufnr, config) abort + let options = { + \ 'relative': 'editor', + \ 'anchor': a:config.anchor, + \ 'row': a:config.row + (a:config.anchor[0] == 'N' ? 1 : -1), + \ 'col': a:config.col + (a:config.anchor[1] == 'W' ? 1 : -1), + \ 'width': a:config.width - 2, + \ 'height': a:config.height - 2, + \ 'style':'minimal', + \ } + let winid = nvim_open_win(a:bufnr, v:true, options) + call s:init_win(winid, v:false) + call floaterm#buffer#set_config(a:bufnr, 'winid', winid) + + let bd_options = { + \ 'relative': 'editor', + \ 'anchor': a:config.anchor, + \ 'row': a:config.row, + \ 'col': a:config.col, + \ 'width': a:config.width, + \ 'height': a:config.height, + \ 'focusable': v:false, + \ 'style':'minimal', + \ } + let a:config.title = s:make_title(a:bufnr, a:config.title) + let bd_bufnr = floaterm#buffer#create_border_buf(a:config) + let bd_winid = nvim_open_win(bd_bufnr, v:false, bd_options) + call s:init_win(bd_winid, v:true) + call floaterm#buffer#set_config(a:bufnr, 'borderwinid', bd_winid) return winid endfunction -function! floaterm#window#open_popup(bufnr, width, height, pos) abort - let [row, col, anchor] = s:floatwin_pos(a:width, a:height, a:pos) - let width = a:width - let height = a:height - let opts = { - \ 'pos': anchor, - \ 'line': row, - \ 'col': col, - \ 'maxwidth': width, - \ 'minwidth': width, - \ 'maxheight': height, - \ 'minheight': height, - \ 'border': [1, 1, 1, 1], - \ 'borderchars': g:floaterm_borderchars, - \ 'borderhighlight': ['FloatermBorder'], - \ 'padding': [0,1,0,1], - \ 'highlight': 'Floaterm' - \ } - let opts.title = s:build_title(a:bufnr) - let opts.zindex = len(floaterm#buflist#gather()) + 1 - let winid = popup_create(a:bufnr, opts) - call setbufvar(a:bufnr, '&filetype', 'floaterm') +function! s:open_popup(bufnr, config) abort + let options = { + \ 'pos': a:config.anchor, + \ 'line': a:config.row, + \ 'col': a:config.col, + \ 'maxwidth': a:config.width - 2, + \ 'minwidth': a:config.width - 2, + \ 'maxheight': a:config.height - 2, + \ 'minheight': a:config.height - 2, + \ 'border': [1, 1, 1, 1], + \ 'borderchars': a:config.borderchars, + \ 'borderhighlight': ['FloatermBorder'], + \ 'padding': [0,1,0,1], + \ 'highlight': 'Floaterm', + \ 'zindex': len(floaterm#buflist#gather()) + 1 + \ } + + " vim will pad the end of title but not begin part + " so we build the title as ' floaterm (idx/cnt)' + let title =s:make_title(a:bufnr, a:config.title) + let options.title = empty(title) ? '' : ' ' . title + let winid = popup_create(a:bufnr, options) + call s:init_win(winid, v:false) + call floaterm#buffer#set_config(a:bufnr, 'winid', winid) return winid endfunction -function! floaterm#window#open_split(bufnr, height, width, pos) abort - if a:pos == 'top' - execute 'topleft' . a:height . 'split' - elseif a:pos == 'left' - execute 'topleft' . a:width . 'vsplit' - elseif a:pos == 'right' - execute 'botright' . a:width . 'vsplit' +function! s:open_split(bufnr, config) abort + if a:config.position == 'top' + execute 'topleft' . a:config.height . 'split' + elseif a:config.position == 'left' + execute 'topleft' . a:config.width . 'vsplit' + elseif a:config.position == 'right' + execute 'botright' . a:config.width . 'vsplit' else " default position: bottom - execute 'botright' . a:height . 'split' + execute 'botright' . a:config.height . 'split' endif - wincmd J execute 'buffer ' . a:bufnr - return win_getid() + let winid = win_getid() + call s:init_win(winid, v:false) + call floaterm#buffer#set_config(a:bufnr, 'winid', winid) + return winid endfunction -function! floaterm#window#hide_floaterm_border(bufnr, ...) abort - let winid = getbufvar(a:bufnr, 'floaterm_border_winid', v:null) - if winid != v:null && s:winexists(winid) - call nvim_win_close(winid, v:true) +function! s:init_win(winid, is_border) abort + if has('nvim') + call setwinvar(a:winid, '&winhl', 'Normal:Floaterm,NormalNC:FloatermNC') + if a:is_border + call setwinvar(a:winid, '&winhl', 'Normal:FloatermBorder') + endif + else + call setwinvar(a:winid, 'wincolor', 'Floaterm') endif - call setbufvar(a:bufnr, 'floaterm_border_winid', v:null) + call setwinvar(a:winid, '&sidescrolloff', 0) + call setwinvar(a:winid, '&colorcolumn', '') endfunction -function! floaterm#window#hide_floaterm(bufnr) abort - let winid = getbufvar(a:bufnr, 'floaterm_winid', -1) - if winid == -1 | return | endif +function! floaterm#window#open(bufnr, config) abort + let config = s:parse_config(a:bufnr, a:config) + if config.wintype == 'normal' + call s:open_split(a:bufnr, config) + else " backward compatiblity: float|floating|popup -> float + if s:has_float + call s:open_float(a:bufnr, config) + else + call s:open_popup(a:bufnr, config) + endif + endif +endfunction + +function! floaterm#window#hide(bufnr) abort + let winid = floaterm#buffer#get_config(a:bufnr, 'winid', -1) + let bd_winid = floaterm#buffer#get_config(a:bufnr, 'borderwinid', -1) if has('nvim') - if !s:winexists(winid) | return | endif - call nvim_win_close(winid, v:true) + if s:winexists(winid) + call nvim_win_close(winid, v:true) + endif + if s:winexists(bd_winid) + call nvim_win_close(bd_winid, v:true) + endif else - try " there should be a function like `win_type()` - call popup_close(winid) - catch - hide - endtry + if exists('*win_gettype') + if win_gettype() == 'popup' + call popup_close(winid) + elseif bufwinnr(a:bufnr) > 0 + silent! execute bufwinnr(a:bufnr) . 'hide' + endif + else + try + call popup_close(winid) + catch + if bufwinnr(a:bufnr) > 0 + silent! execute bufwinnr(a:bufnr) . 'hide' + endif + endtry + endif endif + silent checktime endfunction -"----------------------------------------------------------------------------- " find **one** visible floaterm window -"----------------------------------------------------------------------------- -function! floaterm#window#find_floaterm_window() abort +function! floaterm#window#find() abort let found_winnr = 0 for winnr in range(1, winnr('$')) if getbufvar(winbufnr(winnr), '&filetype') ==# 'floaterm' diff --git a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/fff.vim b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/fff.vim index 0da989d..beabe2e 100644 --- a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/fff.vim +++ b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/fff.vim @@ -14,7 +14,7 @@ function! floaterm#wrapper#fff#(cmd) abort if len(cmdlist) > 1 let cmd .= ' ' . join(cmdlist[1:], ' ') else - let cmd .= ' ' . getcwd() + let cmd .= ' "' . getcwd() . '"' endif exe "lcd " . original_dir @@ -39,6 +39,9 @@ function! s:fff_callback(...) abort endif if filereadable(file_data[0]) + if has('nvim') + call floaterm#window#hide(bufnr('%')) + endif execute g:floaterm_open_command . ' ' . file_data[0] endif endfunction diff --git a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/fzf.vim b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/fzf.vim index edc43d5..9883510 100644 --- a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/fzf.vim +++ b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/fzf.vim @@ -5,14 +5,22 @@ " GitHub: https://github.com/voldikss " ============================================================================ -function! floaterm#wrapper#fzf#(...) abort - if stridx(&shell, 'fish') >= 0 - let cmd = 'floaterm (fzf)' - elseif stridx(&shell, 'csh') - let cmd = 'floaterm `fzf`' - else - " sh/bash/zsh - let cmd = 'floaterm $(fzf)' +function! floaterm#wrapper#fzf#(cmd) abort + let s:fzf_tmpfile = tempname() + let cmd = a:cmd . ' > ' . s:fzf_tmpfile + return [cmd, {'on_exit': funcref('s:fzf_callback')}, v:false] +endfunction + +function! s:fzf_callback(...) abort + if filereadable(s:fzf_tmpfile) + let filenames = readfile(s:fzf_tmpfile) + if !empty(filenames) + if has('nvim') + call floaterm#window#hide(bufnr('%')) + endif + for filename in filenames + execute g:floaterm_open_command . ' ' . fnameescape(filename) + endfor + endif endif - return [cmd, {}, v:true] endfunction diff --git a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/lf.vim b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/lf.vim index 6b7e2f1..b07b164 100644 --- a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/lf.vim +++ b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/lf.vim @@ -11,11 +11,11 @@ function! floaterm#wrapper#lf#(cmd) abort lcd %:p:h let cmdlist = split(a:cmd) - let cmd = 'lf -selection-path=' . s:lf_tmpfile + let cmd = 'lf -selection-path="' . s:lf_tmpfile . '"' if len(cmdlist) > 1 let cmd .= ' ' . join(cmdlist[1:], ' ') else - let cmd .= ' ' . getcwd() + let cmd .= ' "' . getcwd() . '"' endif exe "lcd " . original_dir @@ -26,6 +26,9 @@ function! s:lf_callback(...) abort if filereadable(s:lf_tmpfile) let filenames = readfile(s:lf_tmpfile) if !empty(filenames) + if has('nvim') + call floaterm#window#hide(bufnr('%')) + endif for filename in filenames execute g:floaterm_open_command . ' ' . fnameescape(filename) endfor diff --git a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/nnn.vim b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/nnn.vim index ba0b3dc..cd20eb9 100644 --- a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/nnn.vim +++ b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/nnn.vim @@ -11,11 +11,11 @@ function! floaterm#wrapper#nnn#(cmd) abort lcd %:p:h let cmdlist = split(a:cmd) - let cmd = 'nnn -p ' . s:nnn_tmpfile + let cmd = 'nnn -p "' . s:nnn_tmpfile . '"' if len(cmdlist) > 1 let cmd .= ' ' . join(cmdlist[1:], ' ') else - let cmd .= ' ' . getcwd() + let cmd .= ' "' . getcwd() . '"' endif exe "lcd " . original_dir @@ -26,6 +26,9 @@ function! s:nnn_callback(...) abort if filereadable(s:nnn_tmpfile) let filenames = readfile(s:nnn_tmpfile) if !empty(filenames) + if has('nvim') + call floaterm#window#hide(bufnr('%')) + endif for filename in filenames execute g:floaterm_open_command . ' ' . fnameescape(filename) endfor diff --git a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/ranger.vim b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/ranger.vim index 84ce46a..0cc572f 100644 --- a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/ranger.vim +++ b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/ranger.vim @@ -11,14 +11,14 @@ function! floaterm#wrapper#ranger#(cmd) abort lcd %:p:h let cmdlist = split(a:cmd) - let cmd = 'ranger --choosefiles=' . s:ranger_tmpfile + let cmd = 'ranger --choosefiles="' . s:ranger_tmpfile . '"' if len(cmdlist) > 1 let cmd .= ' ' . join(cmdlist[1:], ' ') else if expand('%:p') != '' let cmd .= ' --selectfile="' . expand('%:p') . '"' else - let cmd .= ' ' . getcwd() + let cmd .= ' "' . getcwd() . '"' endif endif @@ -30,6 +30,9 @@ function! s:ranger_callback(...) abort if filereadable(s:ranger_tmpfile) let filenames = readfile(s:ranger_tmpfile) if !empty(filenames) + if has('nvim') + call floaterm#window#hide(bufnr('%')) + endif for filename in filenames execute g:floaterm_open_command . ' ' . fnameescape(filename) endfor diff --git a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/rg.vim b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/rg.vim new file mode 100644 index 0000000..8c4c51a --- /dev/null +++ b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/rg.vim @@ -0,0 +1,27 @@ +" vim:sw=2: +" ============================================================================ +" FileName: rg.vim +" Author: voldikss +" GitHub: https://github.com/voldikss +" ============================================================================ + +function! floaterm#wrapper#rg#(cmd) abort + let s:rg_tmpfile = tempname() + let cmd = a:cmd . '| fzf > ' . s:rg_tmpfile + return [cmd, {'on_exit': funcref('s:rg_callback')}, v:false] +endfunction + +function! s:rg_callback(...) abort + if filereadable(s:rg_tmpfile) + let filenames = readfile(s:rg_tmpfile) + if !empty(filenames) + if has('nvim') + call floaterm#window#hide(bufnr('%')) + endif + for filename in filenames + let realfilename = matchlist(filename, '\(.\{-}\):.*$')[1] + execute g:floaterm_open_command . ' ' . fnameescape(realfilename) + endfor + endif + endif +endfunction diff --git a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/vifm.vim b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/vifm.vim index ef58bf9..0e28ca6 100644 --- a/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/vifm.vim +++ b/etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/vifm.vim @@ -11,11 +11,11 @@ function! floaterm#wrapper#vifm#(cmd) abort lcd %:p:h let cmdlist = split(a:cmd) - let cmd = 'vifm --choose-files ' . s:vifm_tmpfile + let cmd = 'vifm --choose-files "' . s:vifm_tmpfile . '"' if len(cmdlist) > 1 let cmd .= ' ' . join(cmdlist[1:], ' ') else - let cmd .= ' ' . getcwd() + let cmd .= ' "' . getcwd() . '"' endif exe "lcd " . original_dir @@ -26,6 +26,9 @@ function! s:vifm_callback(...) abort if filereadable(s:vifm_tmpfile) let filenames = readfile(s:vifm_tmpfile) if !empty(filenames) + if has('nvim') + call floaterm#window#hide(bufnr('%')) + endif for filename in filenames execute g:floaterm_open_command . ' ' . fnameescape(filename) endfor diff --git a/etc/soft/nvim/+plugins/vim-floaterm/autoload/health/floaterm.vim b/etc/soft/nvim/+plugins/vim-floaterm/autoload/health/floaterm.vim index d1793a4..b4ace10 100644 --- a/etc/soft/nvim/+plugins/vim-floaterm/autoload/health/floaterm.vim +++ b/etc/soft/nvim/+plugins/vim-floaterm/autoload/health/floaterm.vim @@ -25,7 +25,7 @@ function! s:check_nvr() abort if executable('nvr') call health#report_ok('nvr is OK') else - call health#report_error('nvr executable is not found, run `pip install neovim-remote` to install') + call health#report_error('nvr executable is not found, run `pip3 install neovim-remote` to install') endif endfunction diff --git a/etc/soft/nvim/+plugins/vim-floaterm/doc/floaterm.txt b/etc/soft/nvim/+plugins/vim-floaterm/doc/floaterm.txt index c6f3bd4..0d58dc2 100644 --- a/etc/soft/nvim/+plugins/vim-floaterm/doc/floaterm.txt +++ b/etc/soft/nvim/+plugins/vim-floaterm/doc/floaterm.txt @@ -1,162 +1,256 @@ -*floaterm.txt* Neovim floating terminal plugin Last change: 2019-02-07 - +*floaterm.txt* (Neo)vim floating/popup terminal plugin +============================================================================== Author : voldikss License: MIT license -NOTE: This is outdated, please refer to the README file: - ../README.md - or +NOTE: This doc may be outdated, please refer to the README file instead, https://github.com/voldikss/vim-floaterm/blob/master/README.md + or + ../README.md ============================================================================== -CONTENTS *floaterm-contents* - - Introduction |floaterm-introduction| - Install |floaterm-install| - Features |floaterm-features| - Variables |floaterm-variables| - Keymappings |floaterm-key-mappings| - Commands |floaterm-commands| - Highlight |floaterm-highlight| - Extensions |floaterm-extensions| - Q-A |floaterm-q&a| - Repository |floaterm-repository| - +CONTENTS *floaterm-contents* +Introduction |floaterm-introduction| +Options |floaterm-options| +Mapping |floaterm-mappings| +Commands |floaterm-commands| +Highlight |floaterm-highlight| +Extensions |floaterm-extensions| +Integrations |floaterm-integrations| +FAQ |floaterm-faq| +Repository |floaterm-repository| ============================================================================== -INTRODUCTION *floaterm-introduction* - -Use neovim terminal in the floating window. - - +INTRODUCTION *floaterm-introduction* + +Use (neo)vim terminal in the floating/popup window. + +- NeoVim |api-floatwin| and Vim8 |popup-window| support +- Open and toggle terminal window quickly +- Manage multiple terminal instances +- Customizable terminal window style +- Switch/Preview floating terminal buffers using fuzzy finder plugins such as + |vim-clap|, |denite.nvim|, |coc.nvim|, |fzf.vim| and |LeaderF|. +- Integrate with other external command-line tools(ranger, lf, fzf, etc.) +- Autocompletion from within floaterms(require |coc.nvim|) +- Use as a custom task runner for |asynctasks.vim| ============================================================================== -INSTALL *floaterm-install* - - With vim-plug: - > - Plug 'voldikss/vim-floaterm' +OPTIONS *floaterm-options* + +g:floaterm_shell *g:floaterm_shell* + Type |String|. + Which shell should floaterm use. + Default value is the same as your 'shell' option. + +g:floaterm_title *g:floaterm_title* + Type |String|. + Title format in the floating/popup terminal window. + If empty, the title won't be show. + Default value is 'floaterm: $1/$2' + +g:floaterm_wintype *g:floaterm_wintype* + Type |String|. + 'float'(nvim's floatwin or vim's popupwin) by default. Set it to 'normal' + if your vim/nvim doesn't support |api-floatwin| or |popup-window|. + +g:floaterm_width *g:floaterm_width* + Type: |Number| (number of columns) or |Float| (between 0 and 1). + If |Float|, the width is relative to 'columns'. + Default value is 0.6. + +g:floaterm_height *g:floaterm_height* + Type |Number| (number of lines) or |Float| (between 0 and 1). + If |Float|, the height is relative to 'lines'. + Default value is 0.6. + +g:floaterm_position *g:floaterm_position* + Type |String|. + The position of the floaterm window. + If |g:floaterm_wintype| is 'normal', the value can be 'top', 'right', + 'bottom', 'left'. Default value is 'bottom'. + If |g:floaterm_wintype| is 'popup', the value can be 'top', 'right', 'bottom', + 'left', 'center', 'topleft', 'topright', 'bottomleft', 'bottomright', + 'auto'(at the cursor place). Default value is 'center'. + +g:floaterm_borderchars *g:floaterm_borderchars* + Type |String|. + 8 characters of the floating window border(top, right, bottom, left, topleft, + topright, botright, botleft). + Default value is '─│─│┌┐┘└'. + +g:floaterm_rootmarkers *g:floaterm_rootmarkers* + Type |List| of |String|. + Markers used to detect the project root directory when running + > + :FloatermNew --cwd= < + Default: `['.project', '.git', '.hg', '.svn', '.root']` + +g:floaterm_open_command *g:floaterm_open_command* + Type |String|. + Command used for opening a file in the outside nvim from within + |terminal|. The value can be 'edit', 'split', 'vsplit', 'tabe', 'drop'. + Default value is 'edit'. + +g:floaterm_gitcommit *g:floaterm_gitcommit* + Type |String|. + Opening strategy for `COMMIT_EDITMSG` window by running `git commit` in + the floaterm window. Only works in neovim. The value can be + 'floaterm'(open gitcommit in the floaterm window), 'split'(recommended), + 'vsplit', 'tabe'. + Default value is '', which means this feature is disabled by default(use + your own `$GIT_EDITOR`). + +g:floaterm_autoclose *g:floaterm_autoclose* + Type |Number|. + Whether to close floaterm window once a job gets finished. + 0 - Always do NOT close floaterm window. + 1 - Close window only if the job exits normally + 2 - Always close floaterm window. + Default value is 0. + +g:floaterm_autoinsert *g:floaterm_autoinsert* + Type |Boolean|. + Whether to enter |Terminal-mode| after opening a floaterm. + Default value is |v:true|. + +g:floaterm_autohide *g:floaterm_autohide* + Type |Boolean|. + Decide whether to hide previous floaterms before switching to or opening + another one. + Default value is |v:true|. + +g:floaterm_complete_options *g:floaterm_complete_options* + Type |Dict|. + Autocompletion options used for coc.nvim. + Available options: + - `shortcut`: a string + - `priority`: number between 0-99 + - `filetypes`: array of filetype names this source should be triggered + by. Available for all filetypes when ommited and for no filetypes + when empty + - `firstMatch`: if not falsy, only the completion item that has the + first letter matching the user input will be shown + - `triggerCharacters`: trigger characters for this source. + Default value: `{'shortcut': 'floaterm', 'priority': 5}` ============================================================================== -FEATURES *floaterm-features* - -- Toggle terminal window quickly - -- Multiple terminal instances - -- Customizable floating terminal style - -- Switch/Preview floating terminal buffer using |vim-clap| - https://github.com/liuchengxu/vim-clap - -- Switch/Preview/Open floating terminal buffer using |denite.nvim| - https://github.com/Shougo/denite.nvim - - -============================================================================== -VARIABLES *floaterm-variables* - -g:floaterm_wintype *g:floaterm_wintype* - - Available: "floating"(neovim only), "normal"(vim8 and neovim) - - Default: "floating" - -g:floaterm_width *g:floaterm_width* - - Type: |v:t_number| (number of columns) or |v:t_float| (between 0 and 1). - If |v:t_float|, the width is relative to `&columns`. - - Default: 0.6 - -g:floaterm_height *g:floaterm_height* - - - Type: |v:t_number| (number of lines) or |v:t_float| (between 0 and 1). - If |v:t_float|, the height is relative to `&lines`. - - Default: 0.6 - - -g:floaterm_winblend *g:floaterm_winblend* - - Description: The transparency of the floating terminal - - Default: 0 - -g:floaterm_position *g:floaterm_position* - - Available: "center", "topleft", "topright", "bottomleft", - "bottomright", "auto" - - Default: "center" - -g:floaterm_borderchars *g:floaterm_borderchars* - - Default: "['─', '│', '─', '│', '┌', '┐', '┘', '└']" - - -============================================================================== - -MAPPINGS *floaterm-key-mappings* +MAPPINGS *floaterm-mappings* -This plugin doesn't supply any default mappings. +This plugin doesn't supply any default mappings. To use a recommended +mappings, put the following code in your `vimrc`. > - """ Configuration example let g:floaterm_keymap_new = '' let g:floaterm_keymap_prev = '' let g:floaterm_keymap_next = '' - let g:floaterm_keymap_toggle = '' + let g:floaterm_keymap_toggle = '' +< +You can also use other keys as shown below: + > + let g:floaterm_keymap_new = 'fn' +< +All options for the mappings are listed below: + > + - g:floaterm_keymap_new + - g:floaterm_keymap_prev + - g:floaterm_keymap_next + - g:floaterm_keymap_first + - g:floaterm_keymap_last + - g:floaterm_keymap_hide + - g:floaterm_keymap_show + - g:floaterm_keymap_kill + - g:floaterm_keymap_toggle + +Note that this key mapping is installed from the `plugin` directory, so if you +are using on-demand loading provided by some plugin-managers, the keymap above +won't take effect(:help |load-plugins|). Then you have to define the key +bindings yourself by putting the code used to define the key bindings in your +`vimrc`. For example, + > + nnoremap :FloatermNew + tnoremap :FloatermNew + nnoremap :FloatermPrev + tnoremap :FloatermPrev + nnoremap :FloatermNext + tnoremap :FloatermNext + nnoremap :FloatermToggle + tnoremap :FloatermToggle < - ============================================================================== -COMMANDS *floaterm-commands* +COMMANDS *floaterm-commands* + +:FloatermNew[!] [options] [cmd] *FloatermNew* + Open a floaterm window. + +:FloatermPrev *FloatermPrev* + Switch to the previous floaterm instance -:FloatermNew *:FloatermNew* +:FloatermNext *FloatermNext* + Switch to the next floaterm instance +:FloatermFirst *FloatermFirst* + Switch to the first floaterm instance -:FloatermNext *:FloatermNext* +:FloatermLast *FloatermLast* + Switch to the last floaterm instance +:FloatermUpdate [options] *FloatermUpdate* + Update floaterm window attributes(`height`, `width`, etc.). -:FloatermPrev *:FloatermPrev* +:[N]FloatermToggle[!] [floaterm_name] *FloatermToggle* + Open or hide the floaterm window. +:[N]FloatermShow[!] [floaterm_name] *FloatermShow* + Show the current floaterm window. -:FloatermToggle *:FloatermToggle* +:[N]FloatermHide[!] [floaterm_name] *FloatermHide* + Hide the current floaterms window. + +:[N]FloatermKill[!] [floaterm_name] *FloatermKill* + Kill the current floaterm instance + +:FloatermSend [--name=floaterm_name] [cmd] *FloatermSend* + Send command to a job in floaterm. + +For the detailed information about the arguments, please refer to +https://github.com/voldikss/vim-floaterm#commands ============================================================================== -HIGHLIGHT *floaterm-highlight* +HIGHLIGHT *floaterm-highlight* -This plugin supplies two `highlight-groups` to specify the -background/foregrond color of floaterm(border) window +This plugin provides two |highlight-groups| to specify the bg/fg color of +floaterm (also the border color if |g:floaterm_wintype| is 'float')window. -By default, they are both linked to `Normal` +To customize, use |hi| command together with the colors you prefer. For example, > - " Configuration example + " Set floaterm window's background to black hi Floaterm guibg=black - hi FloatermBorder guibg=gray guifg=blue + " Set floating window border line color to cyan, and background to orange + hi FloatermBorder guibg=orange guifg=cyan < +Besides, there is a neovim only |hi-group| which can be used to configure +no-current-focused window(:help |hl-NormalNC|). ============================================================================== -EXTENSIONS *floaterm-extensions* +EXTENSIONS *floaterm-extensions* ------------------------------------------------------------------------------ -VIM-CLAP *Clap-floaterm* +VIM-CLAP *clap-floaterm* Start |vim-clap| to manage floaterms. > - :Clap floaterm + :Clap floaterm < ------------------------------------------------------------------------------ -DENITE.NVIM *Denite-floaterm* +DENITE-FLOATERM *denite-floaterm* - *denite-source-floaterm* + *denite-source-floaterm* SOURCES~ -floaterm Gather floaterms as candidates. This accepts an argument - below. +floaterm Gather floaterms as candidates. This accepts an argument below. Source arguments: 1. "new" adds a candidate to open a new floaterm. - *denite-floaterm-actions* + *denite-floaterm-actions* ACTIONS~ open (default) @@ -173,50 +267,113 @@ USAGE~ Start to manage existent floaterms. > - :Denite floaterm + :Denite floaterm < Start to open a new floaterm. > - :Denite floaterm:new + :Denite floaterm:new < Start with all features and preview automatically with moving the cursor. > - :Denite floaterm floaterm:new -auto-action=preview + :Denite floaterm floaterm:new -auto-action=preview < +------------------------------------------------------------------------------ +COC-FLOATERM *coc-floaterm* -============================================================================== -Q-A *floaterm-q&a* +Install coc-floaterm firstly. -- This plugin leaves an empty buffer on startify window +COMMANDS~ + > + CocCommand floaterm.new - Put this code in "vimrc" - > - autocmd User Startified setlocal buflisted + CocCommand floaterm.prev + + CocCommand floaterm.next + + CocCommand floaterm.toggle + + CocCommand floaterm.update +< +COCLIST~ + > + CocList floaterm < -- I want to use another shell in the terminal. (e.g. Use fish instead of bash) +------------------------------------------------------------------------------ +FZF-FLOATERM *fzf-floaterm* - Set 'shell' option in your "vimrc": +Install voldikss/fzf-floaterm and run: > - set shell=/path/to/shell + :Floaterms +< +------------------------------------------------------------------------------ +LEADERF-FLOATERM *leaderf-floaterm* -- I would like to customize the style of the floating terminal window +Install voldikss/leaderf-floaterm and run: + > + :Leaderf floaterm +< +------------------------------------------------------------------------------ +ASYNCTASKS.VIM *asynctasks.vim* - Use |autocmd|. For example, +This plugin can be a runner for |asynctasks.vim|. To use it, copy the +following code to your `vimrc` set |g:asynctasks_term_pos| to `'floaterm'` or +add a `pos=floaterm` filed in your asynctasks configuration files. > - function s:floatermSettings() - setlocal number - " more settings - endfunction + function! s:run_in_floaterm(opts) + execute 'FloatermNew --position=bottomright' . + \ ' --wintype=float' . + \ ' --height=0.4' . + \ ' --width=0.4' . + \ ' --title=floaterm_runner' . + \ ' --autoclose=0' . + \ ' --silent=' . get(a:opts, 'silent', 0) + \ ' --cwd=' . a:opts.cwd + \ ' ' . a:opts.cmd + " Do not focus on floaterm window, and close it once cursor moves + " If you want to jump to the floaterm window, use p + " You can choose whether to use the following code or not + stopinsert | noa wincmd p + augroup close-floaterm-runner + autocmd! + autocmd CursorMoved,InsertEnter * ++nested + \ call timer_start(100, { -> s:close_floaterm_runner() }) + augroup END + endfunction + function! s:close_floaterm_runner() abort + if &ft == 'floaterm' | return | endif + for b in tabpagebuflist() + if getbufvar(b, '&ft') == 'floaterm' && + \ getbufvar(b, 'floaterm_jobexists') == v:false + execute b 'bwipeout!' + break + endif + endfor + autocmd! close-floaterm-runner + endfunction + let g:asyncrun_runner = get(g:, 'asyncrun_runner', {}) + let g:asyncrun_runner.floaterm = function('s:run_in_floaterm') + let g:asynctasks_term_pos = 'floaterm' + < +Then your task will be ran in the floaterm instance. See +https://github.com/skywind3000/asynctasks.vim/wiki/Customize-Runner for more +information. - autocmd FileType floaterm call s:floatermSettings() +============================================================================== +INTEGRATIONS *floaterm-integrations* + +Please refer to +https://github.com/voldikss/vim-floaterm#integrate-with-command-line-tools ============================================================================== -REPOSITORY *floaterm-repository-page* +FAQ *floaterm-faq* - |vim-floaterm| is developed on GitHub. +https://github.com/voldikss/vim-floaterm/issues?q=label%3AFAQ - https://github.com/voldikss/vim-floaterm +============================================================================== +REPOSITORY *floaterm-repository-page* +vim-floaterm is developed on GitHub. Give me a star if it helps you (^_^)! +https://github.com/voldikss/vim-floaterm ============================================================================== -vim:tw=78:nosta:noet:ts=8:sts=0:ft=help:noet:fen:fdm=marker: +vim:tw=78:ts=4:ft=help:fen: diff --git a/etc/soft/nvim/+plugins/vim-floaterm/plugin/floaterm.vim b/etc/soft/nvim/+plugins/vim-floaterm/plugin/floaterm.vim index e9127c5..f82d61c 100644 --- a/etc/soft/nvim/+plugins/vim-floaterm/plugin/floaterm.vim +++ b/etc/soft/nvim/+plugins/vim-floaterm/plugin/floaterm.vim @@ -5,55 +5,100 @@ " GitHub: https://github.com/voldikss " ============================================================================ -scriptencoding utf-8 +if exists('g:loaded_floaterm') + finish +endif +let g:loaded_floaterm = 1 -let g:floaterm_wintype = get(g:, 'floaterm_wintype', v:null) -let g:floaterm_wintitle = get(g:, 'floaterm_wintitle', v:true) -let g:floaterm_width = get(g:, 'floaterm_width', v:null) -let g:floaterm_height = get(g:, 'floaterm_height', v:null) -let g:floaterm_winblend = get(g:, 'floaterm_winblend', 0) -let g:floaterm_position = get(g:, 'floaterm_position', 'center') -let g:floaterm_borderchars = get(g:, 'floaterm_borderchars', ['─', '│', '─', '│', '┌', '┐', '┘', '└']) -let g:floaterm_rootmarkers = get(g:, 'floaterm_rootmarkers', []) -let g:floaterm_autoinsert = get(g:, 'floaterm_autoinsert', v:true) -let g:floaterm_open_command = get(g:, 'floaterm_open_command', 'edit') -let g:floaterm_gitcommit = get(g:, 'floaterm_gitcommit', v:null) +let g:floaterm_shell = get(g:, 'floaterm_shell', &shell) +let g:floaterm_title = get(g:, 'floaterm_title', 'floaterm($1/$2)') +let g:floaterm_width = get(g:, 'floaterm_width', 0.6) +let g:floaterm_height = get(g:, 'floaterm_height', 0.6) +let g:floaterm_wintype = get(g:, 'floaterm_wintype', 'float') +let g:floaterm_autoclose = get(g:, 'floaterm_autoclose', 0) +let g:floaterm_autoinsert = get(g:, 'floaterm_autoinsert', v:true) +let g:floaterm_autohide = get(g:, 'floaterm_autohide', v:true) +let g:floaterm_position = get(g:, 'floaterm_position', 'center') +let g:floaterm_borderchars = get(g:, 'floaterm_borderchars', '─│─│┌┐┘└') +let g:floaterm_rootmarkers = get(g:, 'floaterm_rootmarkers', ['.project', '.git', '.hg', '.svn', '.root']) +let g:floaterm_open_command = get(g:, 'floaterm_open_command', 'edit') +let g:floaterm_gitcommit = get(g:, 'floaterm_gitcommit', '') +let g:floaterm_complete_options = get(g:, 'floaterm_complete_options', {'shortcut': 'floaterm', 'priority': 5, 'filter_length': [5, 20]}) -let g:floaterm_keymap_new = get(g:, 'floaterm_keymap_new', v:null) -let g:floaterm_keymap_prev = get(g:, 'floaterm_keymap_prev', v:null) -let g:floaterm_keymap_next = get(g:, 'floaterm_keymap_next', v:null) -let g:floaterm_keymap_toggle = get(g:, 'floaterm_keymap_toggle', v:null) +let g:floaterm_keymap_new = get(g:, 'floaterm_keymap_new', '') +let g:floaterm_keymap_prev = get(g:, 'floaterm_keymap_prev', '') +let g:floaterm_keymap_next = get(g:, 'floaterm_keymap_next', '') +let g:floaterm_keymap_first = get(g:, 'floaterm_keymap_first', '') +let g:floaterm_keymap_last = get(g:, 'floaterm_keymap_last', '') +let g:floaterm_keymap_hide = get(g:, 'floaterm_keymap_hide', '') +let g:floaterm_keymap_show = get(g:, 'floaterm_keymap_show', '') +let g:floaterm_keymap_kill = get(g:, 'floaterm_keymap_kill', '') +let g:floaterm_keymap_toggle = get(g:, 'floaterm_keymap_toggle', '') +command! -nargs=* -bang -complete=customlist,floaterm#cmdline#complete + \ FloatermNew call floaterm#run('new', 0, ) +command! -nargs=* -complete=customlist,floaterm#cmdline#complete + \ FloatermUpdate call floaterm#run('update', 0, ) +command! -nargs=? -count=0 -bang -complete=customlist,floaterm#cmdline#complete_names1 + \ FloatermShow call floaterm#show(0, , ) +command! -nargs=? -count=0 -bang -complete=customlist,floaterm#cmdline#complete_names1 + \ FloatermHide call floaterm#hide(0, , ) +command! -nargs=? -count=0 -bang -complete=customlist,floaterm#cmdline#complete_names1 + \ FloatermKill call floaterm#kill(0, , ) +command! -nargs=? -count=0 -bang -complete=customlist,floaterm#cmdline#complete_names1 + \ FloatermToggle call floaterm#toggle(0, , ) +command! -nargs=? -range -bang -complete=customlist,floaterm#cmdline#complete_names2 + \ FloatermSend call floaterm#send(0, visualmode(), , , , ) command! -nargs=0 FloatermPrev call floaterm#prev() command! -nargs=0 FloatermNext call floaterm#next() -command! -nargs=0 FloatermHide call floaterm#hide() -command! -nargs=* -complete=customlist,floaterm#cmdline#complete - \ FloatermNew call floaterm#run('new', ) -command! -nargs=* -complete=customlist,floaterm#cmdline#complete - \ FloatermUpdate call floaterm#run('update', ) -command! -nargs=? -complete=customlist,floaterm#cmdline#floaterm_names - \ FloatermToggle call floaterm#toggle() -command! -nargs=? -range -bang -complete=customlist,floaterm#cmdline#floaterm_names - \ FloatermSend call floaterm#send('', ) +command! -nargs=0 FloatermFirst call floaterm#first() +command! -nargs=0 FloatermLast call floaterm#last() hi def link Floaterm Normal -hi def link FloatermBorder Normal +hi def link FloatermNC NormalNC +hi def link FloatermBorder NormalFloat + +augroup floaterm_enter_insertmode + autocmd! + autocmd BufEnter * if &ft == 'floaterm' | call floaterm#util#startinsert() | endif + autocmd FileType floaterm call floaterm#util#startinsert() +augroup END function! s:install_keymap() - if g:floaterm_keymap_new != v:null - exe printf('nnoremap %s :FloatermNew', g:floaterm_keymap_new) + if !empty(g:floaterm_keymap_new) + exe printf('nnoremap %s :FloatermNew', g:floaterm_keymap_new) exe printf('tnoremap %s :FloatermNew', g:floaterm_keymap_new) endif - if g:floaterm_keymap_prev != v:null - exe printf('nnoremap %s :FloatermPrev', g:floaterm_keymap_prev) + if !empty(g:floaterm_keymap_prev) + exe printf('nnoremap %s :FloatermPrev', g:floaterm_keymap_prev) exe printf('tnoremap %s :FloatermPrev', g:floaterm_keymap_prev) endif - if g:floaterm_keymap_next != v:null - exe printf('nnoremap %s :FloatermNext', g:floaterm_keymap_next) + if !empty(g:floaterm_keymap_next) + exe printf('nnoremap %s :FloatermNext', g:floaterm_keymap_next) exe printf('tnoremap %s :FloatermNext', g:floaterm_keymap_next) endif - if g:floaterm_keymap_toggle != v:null - exe printf('nnoremap %s :FloatermToggle', g:floaterm_keymap_toggle) + if !empty(g:floaterm_keymap_first) + exe printf('nnoremap %s :FloatermFirst', g:floaterm_keymap_first) + exe printf('tnoremap %s :FloatermFirst', g:floaterm_keymap_first) + endif + if !empty(g:floaterm_keymap_last) + exe printf('nnoremap %s :FloatermLast', g:floaterm_keymap_last) + exe printf('tnoremap %s :FloatermLast', g:floaterm_keymap_last) + endif + if !empty(g:floaterm_keymap_hide) + exe printf('nnoremap %s :FloatermHide', g:floaterm_keymap_hide) + exe printf('tnoremap %s :FloatermHide', g:floaterm_keymap_hide) + endif + if !empty(g:floaterm_keymap_show) + exe printf('nnoremap %s :FloatermShow', g:floaterm_keymap_show) + exe printf('tnoremap %s :FloatermShow', g:floaterm_keymap_show) + endif + if !empty(g:floaterm_keymap_kill) + exe printf('nnoremap %s :FloatermKill', g:floaterm_keymap_kill) + exe printf('tnoremap %s :FloatermKill', g:floaterm_keymap_kill) + endif + if !empty(g:floaterm_keymap_toggle) + exe printf('nnoremap %s :FloatermToggle', g:floaterm_keymap_toggle) exe printf('tnoremap %s :FloatermToggle', g:floaterm_keymap_toggle) endif endfunction diff --git a/etc/soft/nvim/+plugins/vim-floaterm/rplugin/python3/denite/source/floaterm.py b/etc/soft/nvim/+plugins/vim-floaterm/rplugin/python3/denite/source/floaterm.py index c0c3ddf..c5a1bb9 100644 --- a/etc/soft/nvim/+plugins/vim-floaterm/rplugin/python3/denite/source/floaterm.py +++ b/etc/soft/nvim/+plugins/vim-floaterm/rplugin/python3/denite/source/floaterm.py @@ -18,7 +18,7 @@ class Source(Base): self._is_nvim = bool(vim.funcs.has("nvim")) def on_init(self, context: UserContext) -> None: - self.vim.call("floaterm#hide") + self.vim.call("floaterm#hide", 1, "") def gather_candidates(self, context: UserContext) -> Candidates: return ( diff --git a/etc/soft/nvim/+plugins/vim-floaterm/rplugin/python3/deoplete/source/floaterm.py b/etc/soft/nvim/+plugins/vim-floaterm/rplugin/python3/deoplete/source/floaterm.py new file mode 100644 index 0000000..1131f93 --- /dev/null +++ b/etc/soft/nvim/+plugins/vim-floaterm/rplugin/python3/deoplete/source/floaterm.py @@ -0,0 +1,35 @@ +# ======================================================================== +# FileName: floaterm.py +# Description: +# Author: voldikss +# GitHub: https://github.com/voldikss +# ======================================================================== + +import re +from typing import List + +from .base import Base + + +class Source(Base): + def __init__(self, vim): + super().__init__(vim) + + complete_options = self.vim.eval("g:floaterm_complete_options") + if "filetypes" in complete_options: + self.filetypes = complete_options["filetypes"] + self.mark = complete_options["shortcut"] + self.rank = complete_options["priority"] + [self.minlength, self.maxlength] = complete_options["filter_length"] + self.matchers = ["matcher_length", "matcher_full_fuzzy"] + self.name = "floaterm" + self.max_candidates = 0 + + def gather_candidates(self, context): + lines: List[str] = self.vim.call("floaterm#util#getbuflines", -1, 100) + candidates = [] + for line in lines: + for word in line.split(" "): + if self.minlength <= len(word) <= self.maxlength: + candidates.append({"word": word, "dup": 0}) + return candidates diff --git a/etc/soft/nvim/+plugins/vim-floaterm/test/command.vader b/etc/soft/nvim/+plugins/vim-floaterm/test/command.vader deleted file mode 100644 index 7d6b639..0000000 --- a/etc/soft/nvim/+plugins/vim-floaterm/test/command.vader +++ /dev/null @@ -1,118 +0,0 @@ -Execute (Setup functions): - function! AssertFiletype(filetype) abort - AssertEqual a:filetype, &filetype - endfunction - function! AssertBufnr(bufnr) abort - AssertEqual a:bufnr, bufnr('%') - endfunction - function! CheckWindow(if_floaterm) abort - let has_floaterm = 0 - let has_floaterm_border = 0 - for i in range(1, winnr('$')) - let filetype = getbufvar(winbufnr(i), '&filetype') - if filetype ==# 'floaterm' - let has_floaterm = 1 - elseif filetype ==# 'floaterm_border' - let has_floaterm_border = 1 - endif - endfor - if a:if_floaterm - AssertEqual 1, has_floaterm - AssertEqual 1, has_floaterm_border - else - AssertEqual 0, has_floaterm - AssertEqual 0, has_floaterm_border - endif - endfunction - -Execute (Get original bufnr): - let buffer0 = bufnr('%') - -Execute (Open first floaterm): - FloatermNew height=0.3 width=0.4 wintype=floating name=floating_floaterm_1 -Then: - call AssertFiletype('floaterm') - call CheckWindow(v:true) - let buffer1 = bufnr('%') - -Execute (Open second floaterm): - FloatermNew height=0.3 width=0.4 wintype=floating name=normal_floaterm_2 -Then: - call AssertFiletype('floaterm') - call CheckWindow(v:true) - let buffer2 = bufnr('%') - -Execute (Open third floaterm): - FloatermNew height=0.3 width=0.4 wintype=floating name=floating_floaterm_3 -Then: - call AssertFiletype('floaterm') - call CheckWindow(v:true) - let buffer3 = bufnr('%') - -Do (Toggle close floaterm): - \ -Then: - call AssertFiletype('') - call CheckWindow(v:false) - call AssertBufnr(buffer0) - -Execute (Toggle open floaterm): - FloatermToggle -Then: - call AssertFiletype('floaterm') - call CheckWindow(v:true) - call AssertBufnr(buffer3) - -Do (Toggle close floaterm): - \ -Then: - call AssertFiletype('') - call CheckWindow(v:false) - call AssertBufnr(buffer0) - -Execute (Next floaterm): - FloatermNext -Then: - call AssertFiletype('floaterm') - call CheckWindow(v:true) - call AssertBufnr(buffer1) - -Execute (Next floaterm): - FloatermNext -Then: - call AssertFiletype('floaterm') - call CheckWindow(v:true) - call AssertBufnr(buffer2) - -Execute (Next floaterm): - FloatermNext -Then: - call AssertFiletype('floaterm') - call CheckWindow(v:true) - call AssertBufnr(buffer3) - -Execute (Prev floaterm): - FloatermPrev -Then: - call AssertFiletype('floaterm') - call CheckWindow(v:true) - call AssertBufnr(buffer2) - -Execute (Prev floaterm): - FloatermPrev -Then: - call AssertFiletype('floaterm') - call CheckWindow(v:true) - call AssertBufnr(buffer1) - -Execute (Insert a floaterm between first and second): - FloatermNew -Then: - call AssertFiletype('floaterm') - call CheckWindow(v:true) - let buffer1_5 = bufnr('%') - AssertEqual floaterm#buflist#gather(), [buffer1,buffer1_5,buffer2,buffer3] - -Execute (Exit): - call floaterm#hide() - sleep 100m diff --git a/etc/soft/nvim/+plugins/vim-floaterm/test/keymap.vader b/etc/soft/nvim/+plugins/vim-floaterm/test/keymap.vader deleted file mode 100644 index f210c01..0000000 --- a/etc/soft/nvim/+plugins/vim-floaterm/test/keymap.vader +++ /dev/null @@ -1,118 +0,0 @@ -Execute (Setup functions): - function! AssertFiletype(filetype) abort - AssertEqual a:filetype, &filetype - endfunction - function! AssertBufnr(bufnr) abort - AssertEqual a:bufnr, bufnr('%') - endfunction - function! CheckWindow(if_floaterm) abort - let has_floaterm = 0 - let has_floaterm_border = 0 - for i in range(1, winnr('$')) - let filetype = getbufvar(winbufnr(i), '&filetype') - if filetype ==# 'floaterm' - let has_floaterm = 1 - elseif filetype ==# 'floaterm_border' - let has_floaterm_border = 1 - endif - endfor - if a:if_floaterm - AssertEqual 1, has_floaterm - AssertEqual 1, has_floaterm_border - else - AssertEqual 0, has_floaterm - AssertEqual 0, has_floaterm_border - endif - endfunction - -Execute (Get original bufnr): - let buffer0 = bufnr('%') - -Do (Open first floaterm): - \ -Then: - call AssertFiletype('floaterm') - call CheckWindow(v:true) - let buffer1 = bufnr('%') - -Do (Open second floaterm): - \ -Then: - call AssertFiletype('floaterm') - call CheckWindow(v:true) - let buffer2 = bufnr('%') - -Do (Open third floaterm): - \ -Then: - call AssertFiletype('floaterm') - call CheckWindow(v:true) - let buffer3 = bufnr('%') - -Do (Toggle close floaterm): - \ -Then: - call AssertFiletype('') - call CheckWindow(v:false) - call AssertBufnr(buffer0) - -Do (Toggle open floaterm): - \ -Then: - call AssertFiletype('floaterm') - call CheckWindow(v:true) - call AssertBufnr(buffer3) - -Do (Toggle close floaterm): - \ -Then: - call AssertFiletype('') - call CheckWindow(v:false) - call AssertBufnr(buffer0) - -Do (Next floaterm): - \ -Then: - call AssertFiletype('floaterm') - call CheckWindow(v:true) - call AssertBufnr(buffer1) - -Do (Next floaterm): - \ -Then: - call AssertFiletype('floaterm') - call CheckWindow(v:true) - call AssertBufnr(buffer2) - -Do (Next floaterm): - \ -Then: - call AssertFiletype('floaterm') - call CheckWindow(v:true) - call AssertBufnr(buffer3) - -Do (Prev floaterm): - \ -Then: - call AssertFiletype('floaterm') - call CheckWindow(v:true) - call AssertBufnr(buffer2) - -Do (Prev floaterm): - \ -Then: - call AssertFiletype('floaterm') - call CheckWindow(v:true) - call AssertBufnr(buffer1) - -Do (Insert a floaterm between first and second): - \ -Then: - call AssertFiletype('floaterm') - call CheckWindow(v:true) - let buffer1_5 = bufnr('%') - AssertEqual floaterm#buflist#gather(), [buffer1,buffer1_5,buffer2,buffer3] - -Execute (Exit): - call floaterm#hide() - sleep 100m diff --git a/etc/soft/nvim/+plugins/vim-floaterm/test/notes.txt b/etc/soft/nvim/+plugins/vim-floaterm/test/notes.txt new file mode 100644 index 0000000..7e3f75e --- /dev/null +++ b/etc/soft/nvim/+plugins/vim-floaterm/test/notes.txt @@ -0,0 +1,2 @@ +- For vim8, `:FloatermHide` is required before `[N]FloatermKill`, otherwise the + corresponding floaterm won't be closed diff --git a/etc/soft/nvim/+plugins/vim-floaterm/test/test.sh b/etc/soft/nvim/+plugins/vim-floaterm/test/test.sh new file mode 100755 index 0000000..3fe7192 --- /dev/null +++ b/etc/soft/nvim/+plugins/vim-floaterm/test/test.sh @@ -0,0 +1,33 @@ +#! /usr/bin/env bash + +CRED='\033[0;31m' +CGREEN='\033[0;32m' +CCYAN='\033[0;36m' +CEND='\033[0m' # No Color + +# USAGE: ./test/test.sh [vim] +VIM_EXEC=nvim +if [[ $1 = vim ]] +then + VIM_EXEC=/usr/bin/vim +fi + +passnum=0 +failed=0 +for f in `find test/*/*.vader` +do + $VIM_EXEC -u test/vimrc -c "Vader! $f" + if [[ $? != 0 ]] + then + printf "${CGREEN}Passed $passnum files${CEND}\n" + printf "${CRED}Failed at $f${CEND}\n" + failed=1 + break + fi + passnum=$(( $passnum + 1 )) +done + +if [[ $failed = 0 ]] +then + printf "${CCYAN}All tests passed!${CEND}\n" +fi diff --git a/etc/soft/nvim/+plugins/vim-floaterm/test/test_commands/test-FloatermFirst-FloatermLast.vader b/etc/soft/nvim/+plugins/vim-floaterm/test/test_commands/test-FloatermFirst-FloatermLast.vader new file mode 100644 index 0000000..ee023c6 --- /dev/null +++ b/etc/soft/nvim/+plugins/vim-floaterm/test/test_commands/test-FloatermFirst-FloatermLast.vader @@ -0,0 +1,34 @@ +" vim:ft=vim + +Execute(test-FloatermFirst-FloatermLast): + FloatermNew + let bufnr1 = bufnr('%') + FloatermNew + let bufnr2 = bufnr('%') + FloatermNew + let bufnr3 = bufnr('%') + FloatermNew + let bufnr4 = bufnr('%') + + Log '# Execute `:FloatermFirst`' + FloatermFirst + AssertEqual bufnr1, bufnr('%') + + Log '# Execute `:FloatermLast`' + FloatermLast + AssertEqual bufnr4, bufnr('%') + + Log '# Kill the first floaterm and execute `:FloatermFirst`' + FloatermHide " otherwise vim8 testing fails + execute bufnr1 . 'FloatermKill' + FloatermFirst + AssertEqual bufnr2, bufnr('%') + + Log '# Kill the last floaterm and execute `:FloatermLast`' + FloatermHide " otherwise vim8 testing fails + execute bufnr4 . 'FloatermKill' + FloatermLast + AssertEqual bufnr3, bufnr('%') + + FloatermKill! + stopinsert diff --git a/etc/soft/nvim/+plugins/vim-floaterm/test/test_commands/test-FloatermKill.vader b/etc/soft/nvim/+plugins/vim-floaterm/test/test_commands/test-FloatermKill.vader new file mode 100644 index 0000000..b4e898d --- /dev/null +++ b/etc/soft/nvim/+plugins/vim-floaterm/test/test_commands/test-FloatermKill.vader @@ -0,0 +1,52 @@ +" vim:ft=vim + +Execute(test-FloatermKill): + function! IsBufValid(bufnr) abort + return bufexists(a:bufnr) && floaterm#terminal#jobexists(a:bufnr) + endfunction + + Log '# FloatermKill' + FloatermNew + AssertEqual 'floaterm', &filetype + FloatermKill + AssertEqual '', &filetype + + Log '# FloatermKill!' + FloatermNew + let bufnr1 = bufnr('%') + FloatermNew + let bufnr2 = bufnr('%') + + FloatermKill! + AssertEqual 0, IsBufValid(bufnr1) + AssertEqual 0, IsBufValid(bufnr2) + + Log '# [N]FloatermKill' + FloatermNew + let bufnr1 = bufnr('%') + FloatermNew + let bufnr2 = bufnr('%') + + FloatermHide " otherwise vim8 testing fails + execute bufnr1 . 'FloatermKill' + AssertEqual 0, IsBufValid(bufnr1) + AssertEqual 1, IsBufValid(bufnr2) + execute bufnr2 . 'FloatermKill' + AssertEqual 0, IsBufValid(bufnr1) + AssertEqual 0, IsBufValid(bufnr2) + + Log '# FloatermKill --name' + FloatermNew --name=ft1 + let bufnr1 = bufnr('%') + FloatermNew --name=ft2 + let bufnr2 = bufnr('%') + + FloatermKill ft1 + AssertEqual 0, IsBufValid(bufnr1) + AssertEqual 1, IsBufValid(bufnr2) + FloatermKill ft2 + AssertEqual 0, IsBufValid(bufnr1) + AssertEqual 0, IsBufValid(bufnr2) + + FloatermKill! + stopinsert diff --git a/etc/soft/nvim/+plugins/vim-floaterm/test/test_commands/test-FloatermNew.vader b/etc/soft/nvim/+plugins/vim-floaterm/test/test_commands/test-FloatermNew.vader new file mode 100644 index 0000000..fb92b61 --- /dev/null +++ b/etc/soft/nvim/+plugins/vim-floaterm/test/test_commands/test-FloatermNew.vader @@ -0,0 +1,17 @@ +" vim:ft=vim + +Execute(test-FloatermNew): + Log '# FloatermNew' + FloatermNew + AssertEqual 'floaterm', &filetype + + Log '# FloatermNew!' + FloatermNew! + AssertEqual 'floaterm', &filetype + + Log '# FloatermNew with arguments' + FloatermNew --height=0.6 --width=0.4 --wintype=float --name=test --position=topleft --autoclose=0 ls + AssertEqual 'floaterm', &filetype + + FloatermKill! + stopinsert diff --git a/etc/soft/nvim/+plugins/vim-floaterm/test/test_commands/test-FloatermPrev-FloatermNext.vader b/etc/soft/nvim/+plugins/vim-floaterm/test/test_commands/test-FloatermPrev-FloatermNext.vader new file mode 100644 index 0000000..5a2c013 --- /dev/null +++ b/etc/soft/nvim/+plugins/vim-floaterm/test/test_commands/test-FloatermPrev-FloatermNext.vader @@ -0,0 +1,48 @@ +" vim:ft=vim + +Execute(test-FloatermPrev-FloatermNext): + FloatermNew + let bufnr1 = bufnr('%') + FloatermNew + let bufnr2 = bufnr('%') + FloatermNew + let bufnr3 = bufnr('%') + FloatermNew + let bufnr4 = bufnr('%') + + Log '# Execute `:FloatermPrev' + FloatermPrev + AssertEqual bufnr3, bufnr('%') + FloatermPrev + AssertEqual bufnr2, bufnr('%') + FloatermPrev + AssertEqual bufnr1, bufnr('%') + FloatermPrev + AssertEqual bufnr4, bufnr('%') + + Log '# Execute `:FloatermNext' + FloatermNext + AssertEqual bufnr1, bufnr('%') + FloatermNext + AssertEqual bufnr2, bufnr('%') + FloatermNext + AssertEqual bufnr3, bufnr('%') + FloatermNext + AssertEqual bufnr4, bufnr('%') + + Log '# Kill the prev floaterm and execute `:FloatermPrev' + FloatermHide " otherwise vim8 testing fails + execute bufnr3 . 'FloatermKill' + sleep 100m + FloatermPrev + AssertEqual bufnr2, bufnr('%') + + Log '# Kill the next floaterm and execute `:FloatermPrev' + FloatermHide " otherwise vim8 testing fails + execute bufnr4 . 'FloatermKill' + sleep 100m + FloatermNext + AssertEqual bufnr1, bufnr('%') + + FloatermKill! + stopinsert diff --git a/etc/soft/nvim/+plugins/vim-floaterm/test/test_commands/test-FloatermSend.vader b/etc/soft/nvim/+plugins/vim-floaterm/test/test_commands/test-FloatermSend.vader new file mode 100644 index 0000000..a624cec --- /dev/null +++ b/etc/soft/nvim/+plugins/vim-floaterm/test/test_commands/test-FloatermSend.vader @@ -0,0 +1,29 @@ +" vim:ft=vim + +Given(One line text): + # text to be send + +Execute(test-FloatermSend): + Log '# FloatermNew' + FloatermNew + let bufnr1 = bufnr('%') + FloatermHide + + Log '# FloatermSend' + FloatermSend + sleep 500m + let lines = join(getbufline(bufnr1, 0, '$')) + Log lines + Assert lines =~ '# text to be send' + + Log '# FloatermSend with argument' + FloatermNew + let bufnr2 = bufnr('%') + FloatermHide + FloatermSend \# text to be send + sleep 500m + let lines = join(getbufline(bufnr2, 0, '$')) + Assert lines =~ '# text to be send' + + FloatermKill! + stopinsert diff --git a/etc/soft/nvim/+plugins/vim-floaterm/test/test_commands/test-FloatermShow-FloatermHide.vader b/etc/soft/nvim/+plugins/vim-floaterm/test/test_commands/test-FloatermShow-FloatermHide.vader new file mode 100644 index 0000000..f55a8ad --- /dev/null +++ b/etc/soft/nvim/+plugins/vim-floaterm/test/test_commands/test-FloatermShow-FloatermHide.vader @@ -0,0 +1,57 @@ +" vim:ft=vim + +Execute(FloatermShow/Hide): + Log '# Basic' + FloatermNew + FloatermHide + AssertEqual '', &filetype + FloatermShow + AssertEqual 'floaterm', &filetype + + Log '# Show or hide between multiple floaterms' + FloatermNew + let bufnr1 = bufnr('%') + FloatermNew + let bufnr2 = bufnr('%') + + FloatermHide! + AssertEqual -1,bufwinnr(bufnr1) + AssertEqual -1,bufwinnr(bufnr2) + + if has('nvim') + FloatermShow! + AssertNotEqual -1,bufwinnr(bufnr1) + AssertNotEqual -1,bufwinnr(bufnr2) + endif + + Log '# [N]FloatermHide' + FloatermNew + let bufnr1 = bufnr('%') + execute bufnr1 . 'FloatermHide' + AssertEqual -1,bufwinnr(bufnr1) + + FloatermNew + let bufnr2 = bufnr('%') + execute bufnr2 . 'FloatermHide' + AssertEqual -1,bufwinnr(bufnr2) + + Log '# [N]FloatermShow' + if has('nvim') + execute bufnr1 . 'FloatermShow' + AssertEqual bufnr1, bufnr('%') + execute bufnr2 . 'FloatermShow' + AssertEqual bufnr2, bufnr('%') + endif + + Log '# FloatermHide --name' + FloatermNew --name=ft1 + FloatermHide ft1 + FloatermNew --name=ft2 + FloatermHide ft2 + + Log '# FloatermShow --name' + FloatermShow ft1 + FloatermShow ft2 + + FloatermKill! + stopinsert diff --git a/etc/soft/nvim/+plugins/vim-floaterm/test/test_commands/test-FloatermToggle.vader b/etc/soft/nvim/+plugins/vim-floaterm/test/test_commands/test-FloatermToggle.vader new file mode 100644 index 0000000..c689bbb --- /dev/null +++ b/etc/soft/nvim/+plugins/vim-floaterm/test/test_commands/test-FloatermToggle.vader @@ -0,0 +1,55 @@ +" vim:ft=vim + +Execute(FloatermToggle): + Log '# Basic' + FloatermToggle + AssertEqual 'floaterm', &filetype + FloatermToggle + AssertEqual '', &filetype + + Log '# Toggle between multiple floaterms' + FloatermNew + let bufnr1 = bufnr('%') + FloatermToggle + FloatermNew + let bufnr2 = bufnr('%') + FloatermToggle + + if has('nvim') + Log '# FloatermToggle! to show and hide' + FloatermToggle! + AssertNotEqual -1,bufwinnr(bufnr1) + AssertNotEqual -1,bufwinnr(bufnr2) + + FloatermToggle! + AssertEqual -1,bufwinnr(bufnr1) + AssertEqual -1,bufwinnr(bufnr2) + endif + + Log '# [N]FloatermToggle' + FloatermNew + let bufnr1 = bufnr('%') + FloatermToggle + FloatermNew + let bufnr2 = bufnr('%') + FloatermToggle + execute bufnr1 . 'FloatermToggle' + AssertEqual bufnr1, bufnr('%') + execute bufnr2 . 'FloatermToggle' + AssertEqual bufnr2, bufnr('%') + + Log '# FloatermToggle name, named floaterm exists' + FloatermNew --name=ft1 + FloatermToggle + FloatermNew --name=ft2 + FloatermToggle + + FloatermToggle ft1 + AssertEqual 'ft1', b:floaterm_name + FloatermToggle ft2 + AssertEqual 'ft2', b:floaterm_name + FloatermToggle ft3 + AssertEqual 'ft3', b:floaterm_name + + FloatermKill! + stopinsert diff --git a/etc/soft/nvim/+plugins/vim-floaterm/test/test_commands/test-FloatermUpdate.vader b/etc/soft/nvim/+plugins/vim-floaterm/test/test_commands/test-FloatermUpdate.vader new file mode 100644 index 0000000..4a23abc --- /dev/null +++ b/etc/soft/nvim/+plugins/vim-floaterm/test/test_commands/test-FloatermUpdate.vader @@ -0,0 +1,10 @@ +" vim:ft=vim + +Execute(FloatermUpdate): + Log '# Basic' + FloatermNew + FloatermUpdate --name=ft + AssertEqual 'ft', b:floaterm_name + + FloatermKill! + stopinsert diff --git a/etc/soft/nvim/+plugins/vim-floaterm/test/test_functions/test-floaterm_buffer_get_config_dict.vader b/etc/soft/nvim/+plugins/vim-floaterm/test/test_functions/test-floaterm_buffer_get_config_dict.vader new file mode 100644 index 0000000..294eece --- /dev/null +++ b/etc/soft/nvim/+plugins/vim-floaterm/test/test_functions/test-floaterm_buffer_get_config_dict.vader @@ -0,0 +1,15 @@ +" vim:ft=vim + +Execute(test-floaterm#buffer#get_config_dict): + function! MyFunc() abort + " code + endfunction + + FloatermNew + let bufnr = bufnr('%') + call setbufvar(bufnr, 'Fn', function("MyFunc")) + " https://github.com/voldikss/vim-floaterm/issues/233 + call floaterm#buffer#get_config_dict(bufnr) + + FloatermKill! + stopinsert diff --git a/etc/soft/nvim/+plugins/vim-floaterm/test/test_functions/test-floaterm_cmdline.vader b/etc/soft/nvim/+plugins/vim-floaterm/test/test_functions/test-floaterm_cmdline.vader new file mode 100644 index 0000000..24f4438 --- /dev/null +++ b/etc/soft/nvim/+plugins/vim-floaterm/test/test_functions/test-floaterm_cmdline.vader @@ -0,0 +1,221 @@ +" vim:ft=vim + +Before(Define universal function used to test command completion): + function! CmdlineCompleteTestWrapperFunc(command, expected, handler) abort + let commands = split(a:command) + let arg_lead = a:command[-1:] == ' ' ? '' : commands[-1] + let command = a:command + let cursor_pos = len(a:command) + let result = a:handler(arg_lead, command, cursor_pos) + if a:expected != result + Log printf('Command: `:%s`', a:command) + Log printf("Actual: %s", result) + Log printf('Expected: %s', string(a:expected)) + endif + AssertEqual a:expected, result + endfunction + +Execute(Test floaterm#cmdline#parse): + let argstr ='--height=0.6 --width=0.4 --wintype=float --name=floaterm1 --position=topleft --autoclose=2 ranger --cmd="cd ~"' + let [cmd, config] = floaterm#cmdline#parse(split(argstr)) + AssertEqual 'ranger --cmd="cd ~"', cmd + AssertEqual { + \ 'wintype': 'float', + \ 'name': 'floaterm1', + \ 'autoclose': 2, + \ 'width': 0.4, + \ 'height': 0.6, + \ 'position': 'topleft' + \ }, config + +Execute(Test floaterm#cmdline#parse expand feature): + silent !touch test.txt && echo first.line > test.txt + edit ./test.txt + normal! gg0 + + " %< + AssertEqual expand('%<'), floaterm#cmdline#parse(split('%<'))[0] + " %\(:[phtreS8\~\.]\) + AssertEqual expand('%'), floaterm#cmdline#parse(split('%'))[0] + AssertEqual expand('%:p'), floaterm#cmdline#parse(split('%:p'))[0] + AssertEqual expand('%:h'), floaterm#cmdline#parse(split('%:h'))[0] + AssertEqual expand('%:t'), floaterm#cmdline#parse(split('%:t'))[0] + AssertEqual expand('%:r'), floaterm#cmdline#parse(split('%:r'))[0] + AssertEqual expand('%:e'), floaterm#cmdline#parse(split('%:e'))[0] + AssertEqual expand('%:S'), floaterm#cmdline#parse(split('%:S'))[0] + AssertEqual expand('%:8'), floaterm#cmdline#parse(split('%:8'))[0] + AssertEqual expand('%:~'), floaterm#cmdline#parse(split('%:~'))[0] + AssertEqual expand('%:.'), floaterm#cmdline#parse(split('%:.'))[0] + " %\(:g\=s?.*?.*?\) + AssertEqual expand('%:s?test?main?'), floaterm#cmdline#parse(split('%:s?test?main?'))[0] + AssertEqual expand('%:gs?test?main?'), floaterm#cmdline#parse(split('%:gs?test?main?'))[0] + AssertEqual '%', floaterm#cmdline#parse(split('\%'))[0] + AssertEqual '%:p', floaterm#cmdline#parse(split('\%:p'))[0] + " %\(\(:g\=s?.*?.*?\)\|\(:[phtreS8\~\.]\)\)* + AssertEqual expand('%:p:h'), floaterm#cmdline#parse(split('%:p:h'))[0] + AssertEqual expand('%:p:s?test?main?'), floaterm#cmdline#parse(split('%:p:s?test?main?'))[0] + + " < + AssertEqual expand('<'), floaterm#cmdline#parse(split('<'))[0] + " \(:[phtreS8\~\.]\) + AssertEqual expand(''), floaterm#cmdline#parse(split(''))[0] + AssertEqual expand(':p'), floaterm#cmdline#parse(split(':p'))[0] + AssertEqual expand(':h'), floaterm#cmdline#parse(split(':h'))[0] + AssertEqual expand(':t'), floaterm#cmdline#parse(split(':t'))[0] + AssertEqual expand(':r'), floaterm#cmdline#parse(split(':r'))[0] + AssertEqual expand(':e'), floaterm#cmdline#parse(split(':e'))[0] + AssertEqual expand(':S'), floaterm#cmdline#parse(split(':S'))[0] + AssertEqual expand(':8'), floaterm#cmdline#parse(split(':8'))[0] + AssertEqual expand(':~'), floaterm#cmdline#parse(split(':~'))[0] + AssertEqual expand(':.'), floaterm#cmdline#parse(split(':.'))[0] + " \(:g\=s?.*?.*?\) + AssertEqual expand(':s?test?main?'), floaterm#cmdline#parse(split(':s?test?main?'))[0] + AssertEqual expand(':gs?test?main?'), floaterm#cmdline#parse(split(':gs?test?main?'))[0] + AssertEqual '', floaterm#cmdline#parse(split('\'))[0] + AssertEqual ':p', floaterm#cmdline#parse(split('\:p'))[0] + " \(\(:g\=s?.*?.*?\)\|\(:[phtreS8\~\.]\)\)* + AssertEqual expand(':p:h'), floaterm#cmdline#parse(split(':p:h'))[0] + AssertEqual expand(':p:s?test?main?'), floaterm#cmdline#parse(split(':p:s?test?main?'))[0] + + silent !rm test.txt + +Execute(Test floaterm#cmdline#complete): + function! Test__floaterm_cmdline_complete(command, expected) + call CmdlineCompleteTestWrapperFunc(a:command, a:expected, function('floaterm#cmdline#complete')) + endfunction + call Test__floaterm_cmdline_complete('FloatermNew ', [ + \ '--cwd=', + \ '--name=', + \ '--width=', + \ '--height=', + \ '--title=', + \ '--silent', + \ '--wintype=', + \ '--position=', + \ '--autoclose=', + \ '--borderchars=', + \ ]) + call Test__floaterm_cmdline_complete('FloatermNew nv', sort(getcompletion('nv', 'shellcmd'))) + call Test__floaterm_cmdline_complete('FloatermNew -', [ + \ '--cwd=', + \ '--name=', + \ '--width=', + \ '--height=', + \ '--title=', + \ '--silent', + \ '--wintype=', + \ '--position=', + \ '--autoclose=', + \ '--borderchars=', + \ ]) + call Test__floaterm_cmdline_complete('FloatermNew --', [ + \ '--cwd=', + \ '--name=', + \ '--width=', + \ '--height=', + \ '--title=', + \ '--silent', + \ '--wintype=', + \ '--position=', + \ '--autoclose=', + \ '--borderchars=', + \ ]) + call Test__floaterm_cmdline_complete('FloatermNew --n', ['--name=']) + call Test__floaterm_cmdline_complete('FloatermNew --w', ['--width=', '--wintype=']) + call Test__floaterm_cmdline_complete('FloatermNew --name=', []) + call Test__floaterm_cmdline_complete('FloatermNew --width=', []) + call Test__floaterm_cmdline_complete('FloatermNew --height=', []) + call Test__floaterm_cmdline_complete('FloatermNew --title=', []) + call Test__floaterm_cmdline_complete('FloatermNew --silent', []) + call Test__floaterm_cmdline_complete('FloatermNew --wintype=', [ + \ '--wintype=normal', + \ '--wintype=float' + \ ]) + call Test__floaterm_cmdline_complete('FloatermNew --wintype=n', [ + \ '--wintype=normal' + \ ]) + call Test__floaterm_cmdline_complete('FloatermNew --position=', [ + \ '--position=top', + \ '--position=right', + \ '--position=bottom', + \ '--position=left', + \ '--position=center', + \ '--position=topleft', + \ '--position=topright', + \ '--position=bottomleft', + \ '--position=bottomright', + \ '--position=auto' + \ ]) + call Test__floaterm_cmdline_complete('FloatermNew --position=t', [ + \ '--position=top', + \ '--position=topleft', + \ '--position=topright' + \ ]) + call Test__floaterm_cmdline_complete('FloatermNew '. + \ '--title=1 '. + \ '--name=1 '. + \ '--cwd=1 '. + \ '--width=1 '. + \ '--height=1 '. + \ '--silent '. + \ '--wintype=1 '. + \ '--position=1 '. + \ '--autoclose=1 '. + \ '--borderchars=1 ', sort(getcompletion('', 'shellcmd'))) + call Test__floaterm_cmdline_complete('FloatermUpdate ', [ + \ '--cwd=', + \ '--name=', + \ '--width=', + \ '--height=', + \ '--title=', + \ '--silent', + \ '--wintype=', + \ '--position=', + \ '--autoclose=', + \ '--borderchars=', + \ ]) + call Test__floaterm_cmdline_complete('FloatermUpdate -', [ + \ '--cwd=', + \ '--name=', + \ '--width=', + \ '--height=', + \ '--title=', + \ '--silent', + \ '--wintype=', + \ '--position=', + \ '--autoclose=', + \ '--borderchars=', + \ ]) + call Test__floaterm_cmdline_complete('FloatermUpdate nv', [' ']) + call Test__floaterm_cmdline_complete('FloatermUpdate '. + \ '--title=1 '. + \ '--name=1 '. + \ '--cwd=1 '. + \ '--width=1 '. + \ '--height=1 '. + \ '--silent '. + \ '--wintype=1 '. + \ '--position=1 '. + \ '--autoclose=1 '. + \ '--borderchars=1 ', []) + +Execute(Test floaterm#cmdline#complete_names1): + FloatermNew --name=floaterm + function! Test__floaterm_cmdline_complete_names1(command, expected) + call CmdlineCompleteTestWrapperFunc(a:command, a:expected, function('floaterm#cmdline#complete_names1')) + endfunction + call Test__floaterm_cmdline_complete_names1('abc', ['floaterm']) + FloatermKill! + +Execute(Test floaterm#cmdline#complete_names2): + FloatermNew --name=floaterm1 + FloatermNew --name=floaterm2 + function! Test__floaterm_cmdline_complete_names2(command, expected) + call CmdlineCompleteTestWrapperFunc(a:command, a:expected, function('floaterm#cmdline#complete_names2')) + endfunction + call Test__floaterm_cmdline_complete_names2('FloatermUpdate -', ['--name=']) + call Test__floaterm_cmdline_complete_names2('FloatermSend ', ['--name=']) + call Test__floaterm_cmdline_complete_names2('FloatermSend --name=', ['--name=floaterm1', '--name=floaterm2']) + + FloatermKill! + stopinsert diff --git a/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-autoclose.vader b/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-autoclose.vader new file mode 100644 index 0000000..c0e0488 --- /dev/null +++ b/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-autoclose.vader @@ -0,0 +1,53 @@ +" vim:ft=vim + +Execute(test-autoclose): + Log '# Set autoclose to 0 with normal exit' + FloatermNew --autoclose=0 ls + let bufnr = bufnr('%') + sleep 100m + AssertEqual bufnr, bufnr('%') + + let g:floaterm_autoclose = 0 + FloatermNew ls + let bufnr = bufnr('%') + sleep 100m + AssertEqual bufnr, bufnr('%') + + Log '# Set autoclose to 1 with normal exit' + FloatermNew --autoclose=1 ls + let bufnr = bufnr('%') + sleep 100m + AssertNotEqual bufnr, bufnr('%') + + let g:floaterm_autoclose = 1 + FloatermNew ls + let bufnr = bufnr('%') + sleep 100m + AssertNotEqual bufnr, bufnr('%') + + Log '# Set autoclose to 1 with unnormal exit' + FloatermNew --autoclose=1 xxx + let bufnr = bufnr('%') + sleep 100m + AssertEqual bufnr, bufnr('%') + + let g:floaterm_autoclose = 1 + FloatermNew xxx + let bufnr = bufnr('%') + sleep 100m + AssertEqual bufnr, bufnr('%') + + Log '# Set autoclose to 2 with unnormal exit' + FloatermNew --autoclose=2 xxx + let bufnr = bufnr('%') + sleep 100m + AssertNotEqual bufnr, bufnr('%') + + let g:floaterm_autoclose = 2 + FloatermNew xxx + let bufnr = bufnr('%') + sleep 100m + AssertNotEqual bufnr, bufnr('%') + + FloatermKill! + stopinsert diff --git a/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-autohide.vader b/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-autohide.vader new file mode 100644 index 0000000..254ba1a --- /dev/null +++ b/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-autohide.vader @@ -0,0 +1,94 @@ +" vim:ft=vim + +"============================================================================= +" let g:floaterm_autohide = v:true +"============================================================================= +Execute(Enable autohide): + let g:floaterm_autohide = v:true + + Log '# FloatermNew: the first should be closed, the second should be opened' + FloatermNew + let buffer1 = bufnr('%') + FloatermNew + let buffer2 = bufnr('%') + AssertEqual -1,bufwinnr(buffer1) + if has('nvim') + AssertNotEqual -1,bufwinnr(buffer2) + endif + + Log '# FloatermPrev: the first should be opened, the second should be closed' + FloatermPrev + if has('nvim') + AssertNotEqual -1,bufwinnr(buffer1) + endif + AssertEqual -1,bufwinnr(buffer2) + + Log '# FloatermNext: the first should be closed, the second should be opened' + FloatermNext + AssertEqual -1,bufwinnr(buffer1) + if has('nvim') + AssertNotEqual -1,bufwinnr(buffer2) + endif + + + " FloatermShow/FloatermHide/FloatermToggle should works normally regardless of this option + + Log '# FloatermShow!: both floaterms should be opened' + if has('nvim') + FloatermShow! + AssertNotEqual -1,bufwinnr(buffer1) + AssertNotEqual -1,bufwinnr(buffer2) + endif + + Log '# FloatermHide!: both floaterms should be closed' + FloatermHide! + AssertEqual -1,bufwinnr(buffer1) + AssertEqual -1,bufwinnr(buffer2) + + Log '# FloatermToggle!: both floaterms should be opened' + if has('nvim') + FloatermToggle! + AssertNotEqual -1,bufwinnr(buffer1) + AssertNotEqual -1,bufwinnr(buffer2) + endif + + Log '# FloatermToggle!: both floaterms should be closed' + if has('nvim') + FloatermToggle! + AssertEqual -1,bufwinnr(buffer1) + AssertEqual -1,bufwinnr(buffer2) + endif + + Log '# FloatermKill!: kill all floaterms' + + FloatermKill! + + +"============================================================================= +" let g:floaterm_autohide = v:false +"============================================================================= +Execute(Disable autohide): + let g:floaterm_autohide = v:false + + Log '# FloatermNew && FloatermPrev && FloatermNext: both floaterms should always be opened' + if has('nvim') + FloatermNew + let buffer1 = bufnr('%') + FloatermNew + let buffer2 = bufnr('%') + AssertNotEqual -1,bufwinnr(buffer1) + AssertNotEqual -1,bufwinnr(buffer2) + + FloatermPrev + AssertNotEqual -1,bufwinnr(buffer1) + AssertNotEqual -1,bufwinnr(buffer2) + + FloatermNext + AssertNotEqual -1,bufwinnr(buffer1) + AssertNotEqual -1,bufwinnr(buffer2) + + FloatermKill! + endif + + FloatermKill! + stopinsert diff --git a/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-autoinsert.vader b/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-autoinsert.vader new file mode 100644 index 0000000..4d1acfa --- /dev/null +++ b/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-autoinsert.vader @@ -0,0 +1,24 @@ +" vim:ft=vim + +Execute(test-autoinsert): + Log '# Set autoinsert to 0' + FloatermNew --autoinsert=0 ls + AssertEqual 'floaterm',&filetype + + if has('nvim') + let g:floaterm_autoinsert = 0 + FloatermNew! ls + AssertEqual 'n',mode() + endif + + Log '# Set autoinsert to 1' + FloatermNew --autoinsert=1 ls + AssertEqual 'floaterm',&filetype + + let g:floaterm_autoinsert = 1 + FloatermNew! ls + " FIXME + " AssertEqual 'i',mode() + + FloatermKill! + stopinsert diff --git a/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-cwd.vader b/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-cwd.vader new file mode 100644 index 0000000..aa4c438 --- /dev/null +++ b/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-cwd.vader @@ -0,0 +1,7 @@ +" vim:ft=vim + +Execute(Set cwd and open a floaterm): + " TODO + +Execute(Close floaterm and check cwd): + " TODO diff --git a/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-gitcommit.vader b/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-gitcommit.vader new file mode 100644 index 0000000..1e5bbdc --- /dev/null +++ b/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-gitcommit.vader @@ -0,0 +1,24 @@ +" vim:ft=vim + +Execute(FloatermNew git commit --amend): + if has('nvim') + let g:floaterm_gitcommit = 'split' + let pwd = $PWD + silent execute printf('!touch %s/afile && git add afile', pwd) + FloatermNew git commit + sleep 1000m + + " Log $GIT_EDITOR + " Log nvim_win_get_config(win_getid()) + " for l in range(1, line('$')) + " Log getline(l) + " endfor + " + " Log expand('%') + " Log &ft + AssertNotEqual 'floaterm',&filetype + silent execute printf('!cd %s && rm afile && git add afile', pwd) + endif + + FloatermKill! + stopinsert diff --git a/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-open_command.vader b/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-open_command.vader new file mode 100644 index 0000000..1cc59a6 --- /dev/null +++ b/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-open_command.vader @@ -0,0 +1,31 @@ +" vim:ft=vim + +Execute(test-open_command): + Log '# floaterm test.txt' + let original_winid = win_getid() + silent !touch test.txt + FloatermNew + FloatermHide + FloatermSend floaterm test.txt + sleep 1000m + " Log expand('%') + " Log &ft + AssertEqual 'test.txt',expand('%:t') + AssertNotEqual 'floaterm',&ft + Assert win_getid() == original_winid + silent !rm test.txt + + Log '# cat test.txt | floaterm' + if has('nvim') + silent !touch test.txt + FloatermNew + FloatermHide + FloatermSend cat test.txt | floaterm + sleep 1000m + AssertNotEqual 'floaterm',&ft + Assert win_getid() == original_winid + silent !rm test.txt + endif + + FloatermKill! + stopinsert diff --git a/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-silent.vader b/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-silent.vader new file mode 100644 index 0000000..ebdea95 --- /dev/null +++ b/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-silent.vader @@ -0,0 +1,27 @@ +" vim:ft=vim + +Execute(test-silent): + Log '# FloatermNew --silent --autoclose=0 ls' + FloatermNew --silent --autoclose=0 ls + AssertEqual 1, len(floaterm#buflist#gather()) + FloatermKill! + + Log '# FloatermNew --silent --autoclose=1 ls' + FloatermNew --silent --autoclose=1 ls + sleep 200m " otherwise vim8 testing fails + AssertEqual 0, len(floaterm#buflist#gather()) + FloatermKill! + + Log '# FloatermNew --silent --autoclose=1 xxx' + FloatermNew --silent --autoclose=1 xxx + AssertEqual 1, len(floaterm#buflist#gather()) + FloatermKill! + + Log '# FloatermNew --silent --autoclose=2 ls' + FloatermNew --silent --autoclose=2 ls + sleep 200m " otherwise vim8 testing fails + AssertEqual 0, len(floaterm#buflist#gather()) + FloatermKill! + + FloatermKill! + stopinsert diff --git a/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-title.vader b/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-title.vader new file mode 100644 index 0000000..22af08b --- /dev/null +++ b/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-title.vader @@ -0,0 +1,33 @@ +" vim:ft=vim + +Execute(test-title): + function! GetTitleTopline() abort + if has('nvim') + let bd_winid = getbufvar(bufnr('%'), 'floaterm_borderwinid') + return getbufline(winbufnr(bd_winid), 1)[0] + else + return popup_getoptions(win_getid()).title + endif + endfunction + + let g:floaterm_title = 'floaterm ($1/$2)' + Log '# 1/1' + FloatermNew + Assert GetTitleTopline() =~ 'floaterm (1/1)' + Log '# 2|2' + FloatermNew --title=floaterm\ ($1|$2) + Assert GetTitleTopline() =~ 'floaterm (2|2)' + Log '# 1/2' + FloatermPrev + Assert GetTitleTopline() =~ 'floaterm (1/2)' + Log '# no title' + let g:floaterm_title = '' + FloatermNew + if has('nvim') + Assert GetTitleTopline() =~ '┌─*┐' + else + Assert GetTitleTopline() == '' + endif + + FloatermKill! + stopinsert diff --git a/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-width_height.vader b/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-width_height.vader new file mode 100644 index 0000000..637eb25 --- /dev/null +++ b/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-width_height.vader @@ -0,0 +1,38 @@ +" vim:ft=vim + +Execute(Set g:floaterm_width and g:floaterm_height): + let g:floaterm_height = 0.6 + let g:floaterm_width = 0.6 + let columns_origin = &columns + + Log '# Basic' + FloatermNew + AssertEqual b:floaterm_width, 0.6 + AssertEqual float2nr(0.6*&columns)-2, winwidth(0) + AssertEqual b:floaterm_height, 0.6 + AssertEqual float2nr(0.6*(&lines - &cmdheight - 1))-2, winheight(0) + + " https://github.com/voldikss/vim-floaterm/issues/115 + Log '# Change `&columns` and reopen' + FloatermHide + let &columns = float2nr(&columns/2) + + FloatermShow + AssertEqual b:floaterm_width, 0.6 + AssertEqual float2nr(0.6*&columns)-2, winwidth(0) + AssertEqual b:floaterm_height, 0.6 + AssertEqual float2nr(0.6*(&lines - &cmdheight - 1))-2, winheight(0) + + let &columns = columns_origin + + " https://github.com/voldikss/vim-floaterm/issues/235 + Log '# Given the height or width less than 3' + FloatermNew --height=0 + FloatermNew --height=1 + FloatermNew --height=2 + FloatermNew --width=0 + FloatermNew --width=1 + FloatermNew --width=2 + + FloatermKill! + stopinsert diff --git a/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-wintype.vader b/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-wintype.vader new file mode 100644 index 0000000..813b952 --- /dev/null +++ b/etc/soft/nvim/+plugins/vim-floaterm/test/test_options/test-wintype.vader @@ -0,0 +1,35 @@ +" vim:ft=vim + +Execute(test-wintype): + function! IsFloatOrPopup(winid) abort + if has('nvim') + return has_key(nvim_win_get_config(a:winid), 'anchor') + else + return win_gettype(a:winid) == 'popup' + endif + endfunction + + Log '# Set wintype to normal' + let g:floaterm_wintype = 'normal' + FloatermNew + AssertEqual 0,IsFloatOrPopup(win_getid()) + FloatermNew --wintype=float + AssertEqual 1,IsFloatOrPopup(win_getid()) + + Log '# Set wintype to float' + let g:floaterm_wintype = 'float' + FloatermNew + AssertEqual 1,IsFloatOrPopup(win_getid()) + FloatermNew --wintype=normal + AssertEqual 0,IsFloatOrPopup(win_getid()) + + Log '# Independent wintype value for each floaterm' + FloatermNew --wintype=normal + FloatermNew --wintype=float + FloatermPrev + AssertEqual 0,IsFloatOrPopup(win_getid()) + FloatermNext + AssertEqual 1,IsFloatOrPopup(win_getid()) + + FloatermKill! + stopinsert diff --git a/etc/soft/nvim/+plugins/vim-floaterm/test/test_others/test-auto-close-border.vader b/etc/soft/nvim/+plugins/vim-floaterm/test/test_others/test-auto-close-border.vader new file mode 100644 index 0000000..bed137d --- /dev/null +++ b/etc/soft/nvim/+plugins/vim-floaterm/test/test_others/test-auto-close-border.vader @@ -0,0 +1,23 @@ +" vim:ft=vim + +Execute(test-auto-close-border): + if !has('nvim') | finish | endif + function! BorderExists(bufnr) abort + let bd_winid = getbufvar(a:bufnr, 'floaterm_borderwinid', -1) + return !empty(getwininfo(bd_winid)) + endfunction + + Log '# FloatermToggle and execute `hide` only for floaterm window' + FloatermToggle + let bufnr = bufnr('%') + hide + AssertEqual 0,BorderExists(bufnr) + + FloatermToggle + let bufnr = bufnr('%') + hide + AssertEqual 0,BorderExists(bufnr) + + FloatermKill! + stopinsert + diff --git a/etc/soft/nvim/+plugins/vim-floaterm/test/vimrc b/etc/soft/nvim/+plugins/vim-floaterm/test/vimrc index 4966671..4942323 100644 --- a/etc/soft/nvim/+plugins/vim-floaterm/test/vimrc +++ b/etc/soft/nvim/+plugins/vim-floaterm/test/vimrc @@ -1,12 +1,20 @@ +set nocompatible + filetype off + let &runtimepath .= ',' . expand(':p:h:h') -let &runtimepath .= ',' . expand(':p:h:h') . '/vader.vim' -echom &runtimepath +if $USER == 'runner' + let &runtimepath .= ',' . expand(':p:h:h') . '/vader.vim' + let g:run_in_ci = v:true +else + let &runtimepath .= ',' . expand(':p:h:h') . '/../vader.vim' + let g:run_in_ci = v:false +endif + +" NOTE: echom will frozen vim8 in GitHub Action +" echom &runtimepath + filetype plugin indent on syntax enable -let g:floaterm_wintype = 'floating' -let g:floaterm_keymap_new = '' -let g:floaterm_keymap_prev = '' -let g:floaterm_keymap_next = '' -let g:floaterm_keymap_toggle = '' +nnoremap Q :qa!