Browse Source

vim: vim-floaterm++

Maxim Likhachev 5 years ago
parent
commit
67e33184dc
  1. 492
      etc/soft/nvim/+plugins/vim-floaterm/README.md
  2. 44
      etc/soft/nvim/+plugins/vim-floaterm/autoload/clap/provider/floaterm.vim
  3. 447
      etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm.vim
  4. 23
      etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/buffer.vim
  5. 201
      etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/buflist.vim
  6. 94
      etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/cmdline.vim
  7. 149
      etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/resolver.vim
  8. 189
      etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/terminal.vim
  9. 132
      etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/util.vim
  10. 222
      etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/window.vim
  11. 44
      etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/fff.vim
  12. 18
      etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/fzf.vim
  13. 34
      etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/lf.vim
  14. 34
      etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/nnn.vim
  15. 38
      etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/ranger.vim
  16. 34
      etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/vifm.vim
  17. 36
      etc/soft/nvim/+plugins/vim-floaterm/autoload/health/floaterm.vim
  18. 146
      etc/soft/nvim/+plugins/vim-floaterm/doc/floaterm.txt
  19. 39
      etc/soft/nvim/+plugins/vim-floaterm/plugin/floaterm.vim
  20. 87
      etc/soft/nvim/+plugins/vim-floaterm/rplugin/python3/denite/kind/floaterm.py
  21. 71
      etc/soft/nvim/+plugins/vim-floaterm/rplugin/python3/denite/source/floaterm.py
  22. 118
      etc/soft/nvim/+plugins/vim-floaterm/test/command.vader
  23. 118
      etc/soft/nvim/+plugins/vim-floaterm/test/keymap.vader
  24. 12
      etc/soft/nvim/+plugins/vim-floaterm/test/vimrc

492
etc/soft/nvim/+plugins/vim-floaterm/README.md

@ -1,10 +1,57 @@ @@ -1,10 +1,57 @@
# vim-floaterm
![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)
- [Features](#features)
- [Requirements](#requirements)
- [Installation](#installation)
- [Basic Usage](#basic-usage)
- [Commands](#commands)
- [Global variables](#global-variables)
- [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)
- [Credits](#credits)
- [License](#license)
[![Build Status](https://travis-ci.org/voldikss/vim-floaterm.svg?branch=master)](https://travis-ci.org/voldikss/vim-floaterm)
## 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.)
- Use as a custom task runner for [asynctasks.vim](https://github.com/skywind3000/asynctasks.vim)
## Requirements
Use neovim terminal in the floating window.
- Vim or NeoVim with `terminal` feature
![](https://user-images.githubusercontent.com/20282795/71553203-f59c6980-2a45-11ea-88f2-747e938f7f49.gif)
Run `:checkhealth` to check the environment.
## Installation
@ -20,92 +67,412 @@ Plug 'voldikss/vim-floaterm' @@ -20,92 +67,412 @@ Plug 'voldikss/vim-floaterm'
call dein#add('voldikss/vim-floaterm')
```
## Keymaps
## Basic Usage
Use `:FloatermNew` command to open a terminal window, use `:FloatermToggle` to hide/reopen that. The filetype of the terminal buffer is set to `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.
### 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`.
- `height` see `g:floaterm_height`
- `width` see `g:floaterm_width`
- `wintype` see `g:floaterm_wintype`
- `position` see `g:floaterm_position`
- `name` name of the floaterm
- Use `<TAB>` to get completion.
For example, command
```vim
:FloatermNew height=0.6 width=0.4 wintype=floating name=floaterm1 position=topleft ranger --cmd="cd ~"
```
will open a new `floating` floaterm instance named `floaterm1` running `ranger --cmd="cd ~"` in the `topleft` corner of the main window.
#### `:FloatermUpdate [options]` Update floaterm window attributes(`height`, `width`, etc.).
- The `options` is the same as in `:FloatermNew`.
- Use `<TAB>` to get completion.
#### `:FloatermToggle [floaterm_name]` Open or hide the floaterm window.
- If `floaterm_name` exists, toggle the floaterm instance whose `name` attribute is `floaterm_name`.
- Use `<TAB>` to get completion.
#### `:FloatermPrev` Switch to the previous floaterm instance
#### `:FloatermNext` Switch to the next floaterm instance
#### `:FloatermHide` Hide all visible floaterms
#### `:'<,'>FloatermSend [floaterm_name]` Send selected lines to a job in floaterm.
- If `floaterm_name` exists, send to the floaterm instance whose `name` is `floaterm_name`.
- Use `<TAB>` to get completion.
Note: This command must be executed with a range!
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.
### Global variables
#### **`g:floaterm_wintype`**
Type `string`. `'floating'`(neovim) or `'popup'`(vim) by default. Set it to `'normal'` if your vim/nvim doesn't support `floatwin` or `popup`.
#### **`g:floaterm_wintitle`**
Type `bool`. Whether to show floaterm info(e.g., `'floaterm: 1/3'`) at the top left corner of floaterm window. Default: `v:true`
#### **`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`
#### **`g:floaterm_height`**
Type `int` (number of lines) or `float` (between 0 and 1). If `float`, the height is relative to `&lines`. Default: `0.6`
#### **`g:floaterm_winblend`**
Type `int`. The transparency of the floating terminal. Only works in neovim. Default: `0`
#### **`g:floaterm_position`**
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'`
#### **`g:floaterm_borderchars`**
Type `array of string`. Characters of the floating window border.
This plugin doesn't supply any default mappings.
Default: `['─', '│', '─', '│', '┌', '┐', '┘', '└']`
#### **`g:floaterm_rootmarkers`**
Type `array of string`. If not empty, floaterm will be opened in the project root directory.
Example: `['.project', '.git', '.hg', '.svn', '.root', '.gitignore']`, Default: `[]`
#### **`g:floaterm_autoinsert`**
Type `bool`. Enter terminal mode after opening a floaterm. Default: `v:true`
#### **`g:floaterm_open_command`**
Type `string`. Command used for opening a file 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.
Available: `'floaterm'`(open `gitcommit` file in the floaterm window), `'split'`, `'vsplit'`, `'tabe'`.
Default: `v:null` which means this is disabled by default(use your own `$GIT_EDITOR`).
### Keymaps
This plugin doesn't supply any default mappings. To use a recommended mappings, put the following code in your `vimrc`.
```vim
""" Example configuration
""" Configuration example
let g:floaterm_keymap_new = '<F7>'
let g:floaterm_keymap_prev = '<F8>'
let g:floaterm_keymap_next = '<F9>'
let g:floaterm_keymap_toggle = '<F10>'
```
## Features
You can also use other keys as shown below:
- 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)(try `:Clap floaterm`)
```vim
let g:floaterm_keymap_new = '<Leader>fn'
```
## Configurations
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,
#### **`g:floaterm_type`**
```vim
nnoremap <silent> <F7> :FloatermNew<CR>
tnoremap <silent> <F7> <C-\><C-n>:FloatermNew<CR>
nnoremap <silent> <F8> :FloatermPrev<CR>
tnoremap <silent> <F8> <C-\><C-n>:FloatermPrev<CR>
nnoremap <silent> <F9> :FloatermNext<CR>
tnoremap <silent> <F9> <C-\><C-n>:FloatermNext<CR>
nnoremap <silent> <F10> :FloatermToggle<CR>
tnoremap <silent> <F10> <C-\><C-n>:FloatermToggle<CR>
```
- Available: `'floating'`(neovim only), `'normal'`(vim8 and neovim)
### Change highlight
- Default: `'floating'`
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.
#### **`g:floaterm_width`**
By default, they are both linked to `Normal`. To customize, use `hi` command together with the colors you prefer.
```vim
" Configuration example
- Type: `int` (number of columns) or `float` (between 0 and 1). If `float`, the width is relative to `&columns`.
- Default: `0.6`
" Set floaterm window's background to black
hi Floaterm guibg=black
" Set floating window border line color to cyan, and background to orange
hi FloatermBorder guibg=orange guifg=cyan
```
#### **`g:floaterm_height`**
![](https://user-images.githubusercontent.com/20282795/74794098-42d9e080-52fd-11ea-9ccf-661dd748aa03.png)
- Type: `int` (number of lines) or `float` (between 0 and 1). If `float`, the height is relative to `&lines`.
- Default: `0.6`
## More use cases and demos
#### `g:floaterm_winblend`
vim-floaterm is a nvim/vim terminal plugin, it can run all the command-line programs in the terminal even `nvim/vim` itself.
- Description: The opacity of the floating terminal
**❗Note**: The following cases should work both in Vim and NeoVim unless otherwise specifically noted.
- Default: `0`
### General
#### **`g:floaterm_position`**
Requirements: For neovim users, `nvr` is required, please install it via pip using `pip3 install neovim-remote`.
- Available: `'center'`, `'topleft'`, `'topright'`, `'bottomleft'`, `'bottomright'`, `'auto'(at the cursor place)`
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`
- Default: `'center'`
![](https://user-images.githubusercontent.com/20282795/74755351-06cb5f00-52ae-11ea-84ba-d0b3e88e9377.gif)
#### **`g:floaterm_background`**
### Use as the git editor
- Type: string(e.g. `'#000000'`, `'black'`)
See `g:floaterm_gitcommit` option.
- Default: background color of normal floating window
Execute `git commit` in the terminal window without starting a nested nvim.
#### **`g:floaterm_borderchars`**
![](https://user-images.githubusercontent.com/20282795/76213003-b0b26180-6244-11ea-85ad-1632adfd07d9.gif)
### Use as an fzf plugin
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:
```vim
command! FZF FloatermNew fzf
```
![](https://user-images.githubusercontent.com/20282795/78089550-60b95b80-73fa-11ea-8ac8-8fab2025b4d8.gif)
### Use as an fff plugin
There is also an [fff wrapper](./autoload/floaterm/wrapper/fff.vim)
Try `:FloatermNew fff` or define a new command:
```vim
command! FFF FloatermNew fff
```
![](https://user-images.githubusercontent.com/1472981/75105718-9f315d00-567b-11ea-82d1-6f9a6365391f.gif)
### Use as an nnn plugin
There is also an [nnn wrapper](./autoload/floaterm/wrapper/nnn.vim)
Try `:FloatermNew nnn` or define a new command:
```vim
command! NNN FloatermNew nnn
```
![](https://user-images.githubusercontent.com/20282795/75599726-7a594180-5ae2-11ea-80e2-7a33df1433f6.gif)
### Use as an lf plugin
There is also an [lf wrapper](./autoload/floaterm/wrapper/lf.vim)
Try `:FloatermNew lf` or define a new command:
```vim
command! LF FloatermNew lf
```
![](https://user-images.githubusercontent.com/20282795/77142551-6e4a1980-6abb-11ea-9525-73e1a1844e83.gif)
### Use as a ranger plugin
This plugin can also be a handy ranger plugin since it also has a [ranger wrapper](./autoload/floaterm/wrapper/ranger.vim)
Try `:FloatermNew ranger` or define a new command:
```vim
command! Ranger FloatermNew ranger
```
![](https://user-images.githubusercontent.com/20282795/74800026-2e054900-530d-11ea-8e2a-67168a9532a9.gif)
### Use as a Vifm plugin
There is also a [vifm wrapper](./autoload/floaterm/wrapper/vifm.vim)
Try `:FloatermNew vifm` or define a new command:
```vim
command! Vifm FloatermNew vifm
```
![](https://user-images.githubusercontent.com/43941510/77137476-3c888100-6ac2-11ea-90f2-2345c881aa8f.gif)
### Use as a Python REPL plugin
Use `:FloatermNew python` to open a python shell. After that you can use `:FloatermSend` to send lines to the Python interactive shell.
This can also work for other languages which have interactive shells, such as lua, node, etc.
![](https://user-images.githubusercontent.com/20282795/78530892-0c0d4a80-7817-11ea-8934-835a6e6d0628.gif)
### Use with other command line tools
Furthermore, you can also use other command-line programs, such as lazygit, htop, ncdu, etc.
Use `lazygit` for instance:
![](https://user-images.githubusercontent.com/20282795/74755376-0f239a00-52ae-11ea-9261-44d94abe5924.png)
### Integrate with [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)
### Integrate with [denite.nvim](https://github.com/Shougo/denite.nvim)
Use denite to switch/preview/open floating terminal buffers.
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)
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)
### Integrate with [asynctasks.vim](https://github.com/skywind3000/asynctasks.vim)
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.
- Default: `['─', '│', '─', '│', '┌', '┐', '┘', '└']`
```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
endfunction
let g:asyncrun_runner = get(g:, 'asyncrun_runner', {})
let g:asyncrun_runner.floaterm = function('s:runner_proc')
```
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.
## How to define more wrappers
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)
```vim
function! floaterm#wrapper#fzf#() abort
return ['floaterm $(fzf)', {}, v:true]
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.
- 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)
```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]
endfunction
function! s:ranger_callback(...) abort
if filereadable(s:ranger_tmpfile)
let filenames = readfile(s:ranger_tmpfile)
if !empty(filenames)
for filename in filenames
execute 'edit ' . 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.
## 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`.
For reference, see [floaterm source for vim-clap](./autoload/clap/provider/floaterm.vim).
#### **`g:floaterm_border_color`**
## APIs
- Type: string(e.g. `'#FFFFFF'`, `'blue'`)
- `floaterm#new(cmd, win_opts, job_opts)` create a new floaterm instance and return the bufnum
- Default: foreground color of normal floating window
- `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)
## Commands
- `floaterm#update(win_opts)` update floaterm window attributes
- `:FloatermNew`
- `floaterm#toggle(name)` toggle on/off a floaterm
- `:FloatermToggle`
- `name` name of the floaterm, if empty(`''`), toggle the current floaterm
- `:FloatermPrev`
- `floaterm#prev()` switch to the previous floaterm buffeum and return the bufnum
- `:FloatermNext`
- `floaterm#next()` switch to the next floaterm buffer and return the bufnum
## Q & A
- `floaterm#curr()` return current floaterm buffer number
- #### This plugin leaves an empty buffer on startify window
- `floaterm#hide()` hide all visible floaterms
Put this code in `vimrc`
- `floaterm#window#hide_floaterm(bufnr)` hide the floaterm whose bufnum is `bufnr`
- `floaterm#terminal#send(bufnr, cmds)` send commands to a terminal whose bufnum is `bufnr`
- `cmd`: a list contains some commands
- `floaterm#window#open_floating(bufnr, width, height, pos)` open a generic floating window with a border, return window id
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)
- #### I want to use another shell in the terminal. (e.g., Use fish instead of bash)
Set `shell` option in your `vimrc`:
@ -113,7 +480,7 @@ let g:floaterm_keymap_toggle = '<F10>' @@ -113,7 +480,7 @@ let g:floaterm_keymap_toggle = '<F10>'
set shell=/path/to/shell
```
- #### I would like to customize the style of the floating terminal window
- #### I would like to customize the style of the floaterm window
Use `autocmd`. For example
@ -125,3 +492,36 @@ let g:floaterm_keymap_toggle = '<F10>' @@ -125,3 +492,36 @@ let g:floaterm_keymap_toggle = '<F10>'
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`
## 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)
- Some features require [neovim-remote](https://github.com/mhinz/neovim-remote)
## License
MIT

44
etc/soft/nvim/+plugins/vim-floaterm/autoload/clap/provider/floaterm.vim

@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
" vim:sw=2:
" ============================================================================
" FileName: floaterm.vim
" Description:
" Author: voldikss <dyzplus@gmail.com>
" GitHub: https://github.com/voldikss
" ============================================================================
let s:floaterm = {}
let s:preview_height = 10
let s:bar = '[bufnr] [name]'
function! s:floaterm.source() abort
let candidates = [s:bar]
let bufs = floaterm#buflist#gather()
for bufnr in bufs
let bufinfo = getbufinfo(bufnr)[0]
let name = bufinfo['name']
let title = getbufvar(bufnr, 'term_title')
let line = printf(' %s %s %s', bufnr, name, title)
call add(candidates, line)
endfor
return candidates
endfunction
function! s:floaterm.on_move() abort
let curline = g:clap.display.getcurline()
if curline == s:bar
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]):]
call g:clap.preview.show(lines)
endfunction
function! s:floaterm.sink(curline) abort
if a:curline == s:bar | return | endif
let bufnr = str2nr(matchstr(a:curline, '\S'))
call floaterm#terminal#open_existing(bufnr)
endfunction
let g:clap#provider#floaterm# = s:floaterm

447
etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm.vim

@ -1,323 +1,220 @@ @@ -1,323 +1,220 @@
" vim:sw=2:
" ============================================================================
" FileName: autocmd/floaterm.vim
" Description:
" FileName: floaterm.vim
" Author: voldikss <dyzplus@gmail.com>
" GitHub: https://github.com/voldikss
" ============================================================================
" `hidden` option must be set, otherwise the floating terminal would be wiped
" out, see #17
set hidden
"-----------------------------------------------------------------------------
" script level variables and environment variables
"-----------------------------------------------------------------------------
let $VIM_SERVERNAME = v:servername
let $VIM_EXE = v:progpath
" Note:
" The data structure of the floaterm chain is a double circular linkedlist
" g:floaterm.count is the count of the terminal node
" g:floaterm.index is the pointer
" g:floaterm.head is the HEAD node which only have 'prev' and 'next'
" g:floaterm_node is the node prototype to create a terminal node
let g:floaterm = {}
let g:floaterm.count = 0
let g:floaterm.head = {}
let g:floaterm.head.next = g:floaterm.head
let g:floaterm.head.prev = g:floaterm.head
let g:floaterm.index = g:floaterm.head
let s:home = fnamemodify(resolve(expand('<sfile>: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')
let g:floaterm_node = {
\ 'bufnr': 0,
\ 'border_bufnr': 0,
\ 'next': v:null,
\ 'prev': v:null
\ }
if g:floaterm_border_color == v:null
let g:floaterm_border_color = floaterm#util#get_normalfloat_fg()
if stridx($PATH, s:script) < 0
if s:windows == 0
let $PATH .= ':' . s:script
else
let $PATH .= ';' . s:script
endif
endif
if g:floaterm_background == v:null
let g:floaterm_background = floaterm#util#get_normalfloat_bg()
if g:floaterm_gitcommit != v:null
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',
\ g:floaterm_gitcommit
\ )
endif
endif
" Remove a node if it was closed(the buffer doesn't exist)
function! g:floaterm.kickout() dict abort
if self.count == 0 | return | endif
let self.index.prev.next = self.index.next
let self.index.next.prev = self.index.prev
let self.count -= 1
"-----------------------------------------------------------------------------
" 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
function! g:floaterm.toggle() dict abort
let found_winnr = self.find_term_win()
if found_winnr > 0
if &buftype ==# 'terminal'
execute found_winnr . ' wincmd q'
else
execute found_winnr . ' wincmd w | startinsert'
endif
else
while v:true
if self.count == 0
call self.open(0)
return
endif
" If the current node is HEAD(which doesn't have 'bufnr' key),
" skip and point to the node after HEAD
if self.index == self.head
let self.index = self.head.next
endif
let found_bufnr = self.index.bufnr
if found_bufnr != 0 && bufexists(found_bufnr)
call self.open(found_bufnr)
return
else
call self.kickout()
let self.index = self.index.next
endif
endwhile
" ----------------------------------------------------------------------------
" wrapper function for `floaterm#new()` and `floaterm#update()` since they
" share the same argument: `winopts`
" ----------------------------------------------------------------------------
function! floaterm#run(action, ...) abort
if a:action == 'new'
let [cmd, winopts] = floaterm#cmdline#parse(a:000)
call floaterm#new(cmd, winopts, {})
elseif a:action == 'update'
let [_, winopts] = floaterm#cmdline#parse(a:000)
call floaterm#update(winopts)
endif
endfunction
function! g:floaterm.new() dict abort
call self.hide()
call self.open(0)
endfunction
function! g:floaterm.next() dict abort
call self.hide()
while v:true
if self.count == 0
call floaterm#util#show_msg('No more terminal buffers', 'warning')
return
endif
" If the current node is the end node(whose next node is HEAD),
" skip and point to the HEAD's next node
if self.index.next == self.head
let self.index = self.head.next
else
let self.index = self.index.next
endif
let next_bufnr = self.index.bufnr
if next_bufnr != 0 && bufexists(next_bufnr)
call self.open(next_bufnr)
return
" ----------------------------------------------------------------------------
" create a floaterm. `jobopts` is not used inside this pugin actually, it's
" reserved for outer invoke
" ----------------------------------------------------------------------------
function! floaterm#new(cmd, winopts, jobopts) abort
if a:cmd != ''
let wrappers = s:get_wrappers()
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)
call floaterm#terminal#send(bufnr, [name])
else
let bufnr = floaterm#terminal#open(-1, name, jobopts, a:winopts)
endif
else
call self.kickout()
let bufnr = floaterm#terminal#open(-1, &shell, a:jobopts, a:winopts)
call floaterm#terminal#send(bufnr, [a:cmd])
endif
endwhile
else
let bufnr = floaterm#terminal#open(-1, &shell, a:jobopts, a:winopts)
endif
return bufnr
endfunction
function! g:floaterm.prev() dict abort
call self.hide()
while v:true
if self.count == 0
call floaterm#util#show_msg('No more terminal buffers', 'warning')
return
endif
" If the current node is the node after HEAD(whose previous node is HEAD),
" skip and point to the HEAD's prev node(the end node)
if self.index.prev == self.head
let self.index = self.head.prev
else
let self.index = self.index.prev
endif
let prev_bufnr = self.index.bufnr
if prev_bufnr != 0 && bufexists(prev_bufnr)
call self.open(prev_bufnr)
" ----------------------------------------------------------------------------
" toggle on/off the floaterm named `name`
" ----------------------------------------------------------------------------
function! floaterm#toggle(name) abort
if 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)
elseif bufwinnr(bufnr) > -1
execute bufwinnr(bufnr) . 'wincmd w'
else
call self.kickout()
call floaterm#terminal#open_existing(bufnr)
endif
endwhile
endfunction
" Hide the current terminal before opening another terminal window
" Therefore, you cannot have two terminals displayed at once
function! g:floaterm.hide() dict abort
while v:true
let found_winnr = self.find_term_win()
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 q'
execute found_winnr . 'wincmd w'
call floaterm#util#startinsert()
else
break
call floaterm#curr()
endif
endwhile
endfunction
" Find if there is a terminal among all opened windows
" If found, hide it or jump into it
function! g:floaterm.find_term_win() abort
let found_winnr = 0
for winnr in range(1, winnr('$'))
if getbufvar(winbufnr(winnr), '&filetype') ==# 'floaterm'
let found_winnr = winnr
endif
endfor
return found_winnr
endif
endfunction
function! g:floaterm.open(found_bufnr) dict abort
let height = g:floaterm_height == v:null ? 0.6 : g:floaterm_height
if type(height) == v:t_float | let height = height * &lines | endif
let height = float2nr(height)
" ----------------------------------------------------------------------------
" update the attributes of a floaterm
" ----------------------------------------------------------------------------
function! floaterm#update(winopts) abort
if &filetype !=# 'floaterm'
call floaterm#util#show_msg('You have to be in a floaterm window to change window opts.', 'error')
return
endif
let width = g:floaterm_width == v:null ? 0.6 : g:floaterm_width
if type(width) == v:t_float | let width = width * &columns | endif
let width = float2nr(width)
let bufnr = bufnr('%')
call floaterm#window#hide_floaterm(bufnr)
call floaterm#buffer#update_winopts(bufnr, a:winopts)
call floaterm#terminal#open_existing(bufnr)
endfunction
if g:floaterm_type ==# 'floating'
let [bufnr, border_bufnr] = s:open_floating_terminal(a:found_bufnr, height, width)
function! floaterm#next() abort
call floaterm#window#hide_floaterm(bufnr('%'))
let next_bufnr = floaterm#buflist#find_next()
if next_bufnr == -1
let msg = 'No more floaterms'
call floaterm#util#show_msg(msg, 'warning')
else
let bufnr = s:open_floating_normaml(a:found_bufnr, height, width)
let border_bufnr = 0
endif
if bufnr != 0
" Build a terminal node
let node = deepcopy(g:floaterm_node)
let node.bufnr = bufnr
let node.prev = self.index
let node.next = self.index.next
" If current node is the end node, let HEAD's prev point to the new node
if self.index.next == self.head
let self.head.prev = node
endif
let self.index.next = node
let self.index = self.index.next
let self.count += 1
call floaterm#terminal#open_existing(next_bufnr)
endif
if border_bufnr != 0
let self.index.border_bufnr = border_bufnr
endif
call s:on_open()
endfunction
function! s:on_open() abort
setlocal cursorline
setlocal filetype=floaterm
" Find the true background(not 'hi link') for floating
if has('nvim')
execute 'setlocal winblend=' . g:floaterm_winblend
execute 'hi FloatTermNormal term=NONE guibg='. g:floaterm_background
setlocal winhighlight=NormalFloat:FloatTermNormal,FoldColumn:FloatTermNormal
augroup close_floaterm_window
autocmd!
autocmd TermClose <buffer> if &filetype ==# 'floaterm' |
\ bdelete! |
\ endif
autocmd TermClose,BufHidden <buffer> if exists('g:floaterm.index.border_bufnr')
\ && bufexists(g:floaterm.index.border_bufnr)
\ && g:floaterm.index.border_bufnr != 0 |
\ execute 'bw ' . g:floaterm.index.border_bufnr |
\ endif
augroup END
function! floaterm#prev() abort
call floaterm#window#hide_floaterm(bufnr('%'))
let prev_bufnr = floaterm#buflist#find_prev()
if prev_bufnr == -1
let msg = 'No more floaterms'
call floaterm#util#show_msg(msg, 'warning')
else
call floaterm#terminal#open_existing(prev_bufnr)
endif
startinsert
endfunction
function! s:open_floating_terminal(found_bufnr, height, width) abort
let [row, col, vert, hor] = floaterm#util#floating_win_pos(a:width, a:height)
let border_opts = {
\ 'relative': 'editor',
\ 'anchor': vert . hor,
\ 'row': row,
\ 'col': col,
\ 'width': a:width + 2,
\ 'height': a:height + 2,
\ 'style':'minimal'
\ }
let top = g:floaterm_borderchars[4] .
\ repeat(g:floaterm_borderchars[0], a:width) .
\ g:floaterm_borderchars[5]
let mid = g:floaterm_borderchars[3] .
\ repeat(' ', a:width) .
\ g:floaterm_borderchars[1]
let bot = g:floaterm_borderchars[7] .
\ repeat(g:floaterm_borderchars[2], a:width) .
\ g:floaterm_borderchars[6]
let lines = [top] + repeat([mid], a:height) + [bot]
let border_bufnr = nvim_create_buf(v:false, v:true)
call nvim_buf_set_option(border_bufnr, 'synmaxcol', 3000) " #27
call nvim_buf_set_lines(border_bufnr, 0, -1, v:true, lines)
call nvim_open_win(border_bufnr, v:false, border_opts)
" Floating window border highlight
augroup floaterm_border_highlight
autocmd!
autocmd FileType floaterm_border ++once execute printf(
\ 'syn match Border /.*/ | hi Border guibg=%s guifg=%s',
\ g:floaterm_background,
\ g:floaterm_border_color
\ )
augroup END
call nvim_buf_set_option(border_bufnr, 'filetype', 'floaterm_border')
""
" TODO:
" Use 'relative': 'cursor' for the border window
" Use 'relative':'win'(which behaviors not as expected...) for content window
let opts = {
\ 'relative': 'editor',
\ 'anchor': vert . hor,
\ 'row': row + (vert ==# 'N' ? 1 : -1),
\ 'col': col + (hor ==# 'W' ? 1 : -1),
\ 'width': a:width,
\ 'height': a:height,
\ 'style':'minimal'
\ }
if a:found_bufnr > 0
call nvim_open_win(a:found_bufnr, v:true, opts)
return [0, border_bufnr]
function! floaterm#curr() abort
let curr_bufnr = floaterm#buflist#find_curr()
if curr_bufnr == -1
let curr_bufnr = floaterm#new('', {}, {})
else
let bufnr = nvim_create_buf(v:false, v:true)
call nvim_open_win(bufnr, v:true, opts)
terminal
return [bufnr, border_bufnr]
call floaterm#terminal#open_existing(curr_bufnr)
endif
return curr_bufnr
endfunction
function! s:open_floating_normaml(found_bufnr, height, width) abort
if a:found_bufnr > 0
if &lines > 30
execute 'botright ' . a:height . 'split'
execute 'buffer ' . a:found_bufnr
else
botright split
execute 'buffer ' . a:found_bufnr
endif
return
else
if &lines > 30
if has('nvim')
execute 'botright ' . a:height . 'split term://' . &shell
else
botright terminal
resize a:height
endif
else
if has('nvim')
execute 'botright split term://' . &shell
else
botright terminal
endif
endif
return bufnr('%')
endif
"-----------------------------------------------------------------------------
" hide all floaterms
"-----------------------------------------------------------------------------
function! floaterm#hide() abort
let buffers = floaterm#buflist#gather()
for bufnr in buffers
call floaterm#window#hide_floaterm(bufnr)
endfor
endfunction
function! floaterm#start(action) abort
if !floaterm#util#is_floaterm_available()
function! floaterm#send(bang, termname) 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:action ==# 'new'
call g:floaterm.new()
elseif a:action ==# 'next'
call g:floaterm.next()
elseif a:action ==# 'prev'
call g:floaterm.prev()
elseif a:action ==# 'toggle'
call g:floaterm.toggle()
if a:termname != ''
let bufnr = floaterm#terminal#get_bufnr(a:termname)
if bufnr == -1
call floaterm#util#show_msg('No floaterm found with name: ' . a:termname, 'error')
return
endif
else
let bufnr = floaterm#buflist#find_curr()
if bufnr == -1
let bufnr = floaterm#new('', {}, {})
call floaterm#toggle('')
call floaterm#send(a:bang, a:termname)
call floaterm#toggle('')
return
endif
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
endif
call floaterm#terminal#send(bufnr, linelist)
endfunction

23
etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/buffer.vim

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
" vim:sw=2:
" ============================================================================
" FileName: buffer.vim
" Author: voldikss <dyzplus@gmail.com>
" GitHub: https://github.com/voldikss
" ============================================================================
function! floaterm#buffer#create(linelist, opts) 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
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]
endfor
call setbufvar(a:bufnr, 'floaterm_winopts', winopts)
endfunction

201
etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/buflist.vim

@ -0,0 +1,201 @@ @@ -0,0 +1,201 @@
" vim:sw=2:
" ============================================================================
" FileName: buflist.vim
" Author: voldikss <dyzplus@gmail.com>
" GitHub: https://github.com/voldikss
" ============================================================================
" ----------------------------------------------------------------------------
" Node type
" ----------------------------------------------------------------------------
" @type
" {
" \'next': s:node,
" \'prev': s:node,
" \'bufnr': int
" \}
let s:node = {}
function! s:node.new(bufnr) dict abort
let node = deepcopy(self)
let node.bufnr = a:bufnr
return node
endfunction
function! s:node.to_string() dict abort
return string(self.bufnr)
endfunction
function! s:node.is_valid() dict abort
return bufexists(self.bufnr)
" return bufexists(self.bufnr) && floaterm#terminal#jobexists(self.bufnr)
endfunction
" ----------------------------------------------------------------------------
" Linkedlist type and functions
" ----------------------------------------------------------------------------
" @type
" {
" \'head': s:none,
" \'index': s:node,
" \'size': int
" \}
let s:buflist = {}
let s:buflist.head = s:node.new(-1)
let s:buflist.head.next = s:buflist.head
let s:buflist.head.prev = s:buflist.head
let s:buflist.index = s:buflist.head
let s:buflist.size = 0
function! s:buflist.insert(node) dict abort
let a:node.prev = self.index
let a:node.next = self.index.next
let self.index.next.prev = a:node
let self.index.next = a:node
let self.index = a:node
let self.size += 1
endfunction
function! s:buflist.remove(node) dict abort
if self.empty() || a:node == self.head
return v:false
endif
if bufexists(a:node.bufnr)
execute a:node.bufnr . 'bdelete!'
endif
let a:node.prev.next = a:node.next
let a:node.next.prev = a:node.prev
let self.index = a:node.next
let self.size -= 1
return v:true
endfunction
function! s:buflist.empty() dict abort
" Method 1: use self.size
" return self.size == 0
" Method 2: only head node
return self.head.next == self.head
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
let node = self.index.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 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
let node = self.index.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
" 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
let node = self.index
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
" Return buflist str, note that node.bufnr may not exist
function! s:buflist.to_string() dict abort
let str = '[-'
let curr = self.head
let str .= printf('(%s)', curr.to_string())
let curr = curr.next
while curr != self.head
let str .= printf('--(%s)', curr.to_string())
let curr = curr.next
endwhile
let str .= '-]'
let str .= ' current index: ' . self.index.bufnr
return str
endfunction
" For source extensions(vim-clap, denite)
" Return a list containing floaterm bufnr
" Every bufnr should exist
function! s:buflist.gather() dict abort
let candidates = []
let curr = self.head.next
while curr != self.head
if curr.is_valid()
call add(candidates, curr.bufnr)
endif
let curr = curr.next
endwhile
return candidates
endfunction
" ----------------------------------------------------------------------------
" Wrap functions to allow to be involved
" ----------------------------------------------------------------------------
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()
endfunction
function! floaterm#buflist#find_prev() abort
return s:buflist.find_prev()
endfunction
function! floaterm#buflist#find_curr() abort
return s:buflist.find_curr()
endfunction
function! floaterm#buflist#info() abort
echom s:buflist.to_string()
endfunction
function! floaterm#buflist#gather() abort
return s:buflist.gather()
endfunction
" ----------------------------------------------------------------------------
" UNIT TEST
" ----------------------------------------------------------------------------
function! floaterm#buflist#test() abort
let list = deepcopy(s:buflist)
echo list.index.bufnr
call list.insert(s:node.new(1))
echo list.index.bufnr
call list.insert(s:node.new(2))
echo list.index.bufnr
call list.insert(s:node.new(3))
echo list.index.bufnr
echo list.to_string()
endfunction
" call floaterm#buflist#test()
" ----------------------------------------------------------------------------

94
etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/cmdline.vim

@ -0,0 +1,94 @@ @@ -0,0 +1,94 @@
" vim:sw=2:
" ============================================================================
" FileName: cmdline.vim
" Author: voldikss <dyzplus@gmail.com>
" GitHub: https://github.com/voldikss
" ============================================================================
" ----------------------------------------------------------------------------
" used for `:FloatermNew` and `:FloatermUpdate`
" parse argument list to `cmd`(string, default '') and `winopts`(dict)
" ----------------------------------------------------------------------------
function! floaterm#cmdline#parse(arglist) abort
let winopts = {}
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'
let value = eval(value)
endif
let winopts[key] = value
endif
let c += 1
endfor
endif
return [cmd, winopts]
endfunction
" ----------------------------------------------------------------------------
" used for `:FloatermNew` and `:FloatermUpdate`
" ----------------------------------------------------------------------------
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 cmd_line_before_cursor = a:cmd_line[:a:cursor_pos - 1]
let args = split(cmd_line_before_cursor, '\v\\@<!(\\\\)*\zs\s+', 1)
call remove(args, 0)
for key in winopts_key
if match(cmd_line_before_cursor, key) != -1
let idx = index(candidates, key)
call remove(candidates, idx)
endif
endfor
let prefix = args[-1]
if prefix ==# ''
return candidates
endif
if match(prefix, 'wintype=') > -1
if has('nvim')
let wintypes = ['normal', 'floating']
else
let wintypes = ['normal', 'popup']
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')
endfunction
" ----------------------------------------------------------------------------
" used for `:FloatermToggle`
" ----------------------------------------------------------------------------
function! floaterm#cmdline#floaterm_names(arg_lead, cmd_line, cursor_pos) 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
endif
endfor
return ret
endfunction

149
etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/resolver.vim

@ -0,0 +1,149 @@ @@ -0,0 +1,149 @@
" vim:sw=2:
" ============================================================================
" FileName: resolver.vim
" Author: voldikss <dyzplus@gmail.com>
" GitHub: https://github.com/voldikss
" Description: This is modified from part of skywind3000/asyncrun
" ============================================================================
if has('win32') || has('win64')
let s:is_windows = 1
else
let s:is_windows = 0
endif
" find project root
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')
endif
return '' " skip any fugitive buffers early
endif
let pivot = fullname
if !isdirectory(pivot)
let pivot = fnamemodify(pivot, ':h')
endif
while 1
let prev = pivot
for marker in a:markers
let newname = s:path_join(pivot, marker)
if newname =~ '[\*\?\[\]]'
if glob(newname) != ''
return pivot
endif
elseif filereadable(newname)
return pivot
elseif isdirectory(newname)
return pivot
endif
endfor
let pivot = fnamemodify(pivot, ':h')
if pivot == prev
break
endif
endwhile
return ''
endfunction
let root = s:guess_root(a:path, a:markers)
if root != ''
return s:fullname(root)
elseif a:strict != 0
return ''
endif
" Not found: return parent directory of current file / file itself.
let fullname = s:fullname(a:path)
if isdirectory(fullname)
return fullname
endif
return s:fullname(fnamemodify(fullname, ':h'))
endfunction
" Replace string
function! s:StringReplace(text, old, new) abort
let l:data = split(a:text, a:old, 1)
return join(l:data, a:new)
endfunction
function! s:fullname(f) abort
let f = a:f
if f =~ "'."
try
redir => m
silent exe ':marks' f[1]
redir END
let f = split(split(m, '\n')[-1])[-1]
let f = filereadable(f)? f : ''
catch
let f = '%'
endtry
endif
let f = (f != '%')? f : expand('%')
let f = fnamemodify(f, ':p')
if s:is_windows
let f = substitute(f, "\\", '/', 'g')
endif
if len(f) > 1
let size = len(f)
if f[size - 1] == '/'
let f = strpart(f, 0, size - 1)
endif
endif
return f
endfunction
function! s:path_join(home, name) abort
let l:size = strlen(a:home)
if l:size == 0 | return a:name | endif
let l:last = strpart(a:home, l:size - 1, 1)
if has("win32") || has("win64") || has("win16") || has('win95')
let l:first = strpart(a:name, 0, 1)
if l:first == "/" || l:first == "\\"
let head = strpart(a:home, 1, 2)
if index([":\\", ":/"], head) >= 0
return strpart(a:home, 0, 2) . a:name
endif
return a:name
elseif index([":\\", ":/"], strpart(a:name, 1, 2)) >= 0
return a:name
endif
if l:last == "/" || l:last == "\\"
return a:home . a:name
else
return a:home . '/' . a:name
endif
else
if strpart(a:name, 0, 1) == '/'
return a:name
endif
if l:last == "/"
return a:home . a:name
else
return a:home . '/' . a:name
endif
endif
endfunction
function! floaterm#resolver#get_root() abort
let markers = g:floaterm_rootmarkers
let strict = 0
let l:hr = s:find_root(getcwd(), markers, strict)
if s:is_windows
let l:hr = s:StringReplace(l:hr, '/', "\\")
endif
return l:hr
endfunction
function! floaterm#resolver#chdir(path) abort
if has('nvim')
let cmd = haslocaldir()? 'lcd' : (haslocaldir(-1, 0)? 'tcd' : 'cd')
else
let cmd = haslocaldir()? ((haslocaldir() == 1)? 'lcd' : 'tcd') : 'cd'
endif
silent execute cmd . ' '. fnameescape(a:path)
endfunction

189
etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/terminal.vim

@ -0,0 +1,189 @@ @@ -0,0 +1,189 @@
" vim:sw=2:
" ============================================================================
" FileName: terminal.vim
" Author: voldikss <dyzplus@gmail.com>
" GitHub: https://github.com/voldikss
" ============================================================================
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
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 <buffer=' . a:bufnr . '> call s:on_floaterm_close(' . a:bufnr .')'
execute 'autocmd! BufHidden <buffer=' . a:bufnr . '> call floaterm#window#hide_floaterm_border(' . a:bufnr . ')'
augroup END
endif
if g:floaterm_autoinsert == v:true
call floaterm#util#startinsert()
endif
endfunction
function! s:on_floaterm_close(bufnr) abort
if getbufvar(a:bufnr, '&filetype') != 'floaterm'
return
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('%'))
endif
" change to root directory
if !empty(g:floaterm_rootmarkers)
let dest = floaterm#resolver#get_root()
if dest !=# ''
call floaterm#resolver#chdir(dest)
endif
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)
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)
let wintype = get(a:winopts, 'wintype', s:wintype)
let pos = get(a:winopts, 'position', g:floaterm_position)
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
endif
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
else
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)
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
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)
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 has('nvim')
if !empty(a:cmds[len(a:cmds) - 1])
call add(a:cmds, '')
endif
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'
endif
execute curr_winnr . 'wincmd w'
else
let newline = s:is_win ? "\r\n" : "\n"
call ch_sendraw(ch, join(a:cmds, newline) . newline)
endif
endfunction
function! floaterm#terminal#get_bufnr(termname) abort
return bufnr('floaterm://' . a:termname)
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
else
let job = term_getjob(a:bufnr)
return job_status(job) !=# 'dead'
endif
endfunction

132
etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/util.vim

@ -1,79 +1,10 @@ @@ -1,79 +1,10 @@
" vim:sw=2:
" ============================================================================
" FileName: autoload/floaterm/util.vim
" Description:
" Author: voldikss <dyzplus@gmail.com>
" GitHub: https://github.com/voldikss
" ============================================================================
function! floaterm#util#floating_win_pos(width, height) abort
if g:floaterm_position ==# 'topright'
let row = 0
let col = &columns
let vert = 'N'
let hor = 'E'
elseif g:floaterm_position ==# 'topleft'
let row = 0
let col = 0
let vert = 'N'
let hor = 'W'
elseif g:floaterm_position ==# 'bottomright'
let row = &lines
let col = &columns
let vert = 'S'
let hor = 'E'
elseif g:floaterm_position ==# 'bottomleft'
let row = &lines
let col = 0
let vert = 'S'
let hor = 'W'
elseif g:floaterm_position ==# 'center'
let row = (&lines - a:height)/2
let col = (&columns - a:width)/2
let vert = 'N'
let hor = 'W'
if row < 0
let row = 0
endif
if col < 0
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 vert = 'N'
else
let vert = 'S'
endif
if col + a:width <= &columns
let hor = 'W'
else
let hor = 'E'
endif
endif
return [row, col, vert, hor]
endfunction
function! floaterm#util#is_floaterm_available() abort
if exists('*nvim_win_set_config')
if g:floaterm_type == v:null
let g:floaterm_type = 'floating'
endif
elseif has('terminal')
let g:floaterm_type = 'normal'
else
let message = 'Terminal feature is required, please upgrade your vim/nvim'
call floaterm#util#show_msg(message, 'error')
return v:false
endif
return v:true
endfunction
function! s:echo(group, msg) abort
if a:msg ==# '' | return | endif
execute 'echohl' a:group
@ -114,36 +45,41 @@ function! floaterm#util#show_msg(message, ...) abort @@ -114,36 +45,41 @@ function! floaterm#util#show_msg(message, ...) abort
endif
endfunction
function! floaterm#util#get_normalfloat_fg() abort
let hiGroup = 'NormalFloat'
while v:true
let hiInfo = execute('hi ' . hiGroup)
let fgcolor = matchstr(hiInfo, 'guifg=\zs\S*')
let hiGroup = matchstr(hiInfo, 'links to \zs\S*')
if fgcolor !=# '' || hiGroup ==# ''
break
endif
endwhile
" If the foreground color isn't found eventually, use white
if fgcolor ==# ''
let fgcolor = '#FFFFFF'
function! floaterm#util#edit(_bufnr, filename) abort
call floaterm#hide()
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'
endif
return fgcolor
endfunction
function! floaterm#util#get_normalfloat_bg() abort
let hiGroup = 'NormalFloat'
while v:true
let hiInfo = execute('hi ' . hiGroup)
let bgcolor = matchstr(hiInfo, 'guibg=\zs\S*')
let hiGroup = matchstr(hiInfo, 'links to \zs\S*')
if bgcolor !=# '' || hiGroup ==# ''
break
endif
endwhile
" If the background color isn't found eventually, use black
if bgcolor ==# ''
let bgcolor = '#000000'
"-----------------------------------------------------------------------------
" compose two string(thank skywind3000/vim-quickui)
"-----------------------------------------------------------------------------
function! floaterm#util#string_compose(target, pos, source)
if a:source == ''
return a:target
endif
let pos = a:pos
let source = a:source
if pos < 0
let source = strcharpart(a:source, -pos)
let pos = 0
endif
let target = strcharpart(a:target, 0, pos)
if strchars(target) < pos
let target .= repeat(' ', pos - strchars(target))
endif
return bgcolor
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
endfunction

222
etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/window.vim

@ -0,0 +1,222 @@ @@ -0,0 +1,222 @@
" vim:sw=2:
" ============================================================================
" FileName: floatwin.vim
" Author: voldikss <dyzplus@gmail.com>
" 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
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
let buffers = floaterm#buflist#gather()
let cnt = len(buffers)
let idx = index(buffers, a:bufnr) + 1
return printf(' floaterm: %s/%s', idx, cnt)
endfunction
function! s:floatwin_pos(width, height, pos) abort
if a:pos == 'topright'
let row = 2
let col = &columns - 1
let anchor = 'NE'
elseif a:pos == 'topleft'
let row = 2
let col = 1
let anchor = 'NW'
elseif a:pos == 'bottomright'
let row = &lines - 3
let col = &columns - 1
let anchor = 'SE'
elseif a:pos == 'bottomleft'
let row = &lines - 3
let col = 1
let anchor = 'SW'
elseif a:pos == 'top'
let row = 2
let col = (&columns - a:width)/2
let anchor = 'NW'
elseif a:pos == 'right'
let row = (&lines - a:height)/2
let col = &columns - 1
let anchor = 'NE'
elseif a:pos == 'bottom'
let row = &lines - 3
let col = (&columns - a:width)/2
let anchor = 'SW'
elseif a:pos == 'left'
let row = (&lines - a:height)/2
let col = 1
let anchor = 'NW'
elseif a:pos == 'center'
let row = (&lines - a:height)/2
let col = (&columns - a:width)/2
let anchor = 'NW'
if row < 0
let row = 0
endif
if col < 0
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 vert = 'N'
else
let vert = 'S'
endif
if col + a:width <= &columns
let hor = 'W'
else
let hor = 'E'
endif
let anchor = vert . hor
endif
if !has('nvim')
let anchor = substitute(anchor, '\CN', 'top', '')
let anchor = substitute(anchor, '\CS', 'bot', '')
let anchor = substitute(anchor, '\CW', 'left', '')
let anchor = substitute(anchor, '\CE', 'right', '')
endif
return [row, col, anchor]
endfunction
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)
endif
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')
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'
else " default position: bottom
execute 'botright' . a:height . 'split'
endif
wincmd J
execute 'buffer ' . a:bufnr
return win_getid()
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)
endif
call setbufvar(a:bufnr, 'floaterm_border_winid', v:null)
endfunction
function! floaterm#window#hide_floaterm(bufnr) abort
let winid = getbufvar(a:bufnr, 'floaterm_winid', -1)
if winid == -1 | return | endif
if has('nvim')
if !s:winexists(winid) | return | endif
call nvim_win_close(winid, v:true)
else
try " there should be a function like `win_type()`
call popup_close(winid)
catch
hide
endtry
endif
endfunction
"-----------------------------------------------------------------------------
" find **one** visible floaterm window
"-----------------------------------------------------------------------------
function! floaterm#window#find_floaterm_window() abort
let found_winnr = 0
for winnr in range(1, winnr('$'))
if getbufvar(winbufnr(winnr), '&filetype') ==# 'floaterm'
let found_winnr = winnr
break
endif
endfor
return found_winnr
endfunction

44
etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/fff.vim

@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
" vim:sw=2:
" ============================================================================
" FileName: fff.vim
" Author: benwoodward <ben@terminalcoder.dev>
" GitHub: https://github.com/benwoodward
" ============================================================================
function! floaterm#wrapper#fff#(cmd) abort
let original_dir = getcwd()
lcd %:p:h
let cmdlist = split(a:cmd)
let cmd = 'fff -p'
if len(cmdlist) > 1
let cmd .= ' ' . join(cmdlist[1:], ' ')
else
let cmd .= ' ' . getcwd()
endif
exe "lcd " . original_dir
return [cmd, {'on_exit': funcref('s:fff_callback')}, v:false]
endfunction
function! s:fff_callback(...) abort
let s:fff_tmpfile = $XDG_CACHE_HOME
if !isdirectory(s:fff_tmpfile)
let s:fff_tmpfile = $HOME . "/.cache"
endif
let s:fff_tmpfile .= "/fff/opened_file"
let s:fff_tmpfile = fnameescape(s:fff_tmpfile)
if filereadable(s:fff_tmpfile)
let file_data = readfile(s:fff_tmpfile)
execute delete(s:fff_tmpfile)
else
return
endif
if filereadable(file_data[0])
execute g:floaterm_open_command . ' ' . file_data[0]
endif
endfunction

18
etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/fzf.vim

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
" vim:sw=2:
" ============================================================================
" FileName: fzf.vim
" Author: voldikss <dyzplus@gmail.com>
" 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)'
endif
return [cmd, {}, v:true]
endfunction

34
etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/lf.vim

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
" vim:sw=2:
" ============================================================================
" FileName: lf.vim
" Author: benwoodward <ben@terminalcoder.dev>
" GitHub: https://github.com/benwoodward
" ============================================================================
function! floaterm#wrapper#lf#(cmd) abort
let s:lf_tmpfile = tempname()
let original_dir = getcwd()
lcd %:p:h
let cmdlist = split(a:cmd)
let cmd = 'lf -selection-path=' . s:lf_tmpfile
if len(cmdlist) > 1
let cmd .= ' ' . join(cmdlist[1:], ' ')
else
let cmd .= ' ' . getcwd()
endif
exe "lcd " . original_dir
return [cmd, {'on_exit': funcref('s:lf_callback')}, v:false]
endfunction
function! s:lf_callback(...) abort
if filereadable(s:lf_tmpfile)
let filenames = readfile(s:lf_tmpfile)
if !empty(filenames)
for filename in filenames
execute g:floaterm_open_command . ' ' . fnameescape(filename)
endfor
endif
endif
endfunction

34
etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/nnn.vim

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
" vim:sw=2:
" ============================================================================
" FileName: nnn.vim
" Author: voldikss <dyzplus@gmail.com>
" GitHub: https://github.com/voldikss
" ============================================================================
function! floaterm#wrapper#nnn#(cmd) abort
let s:nnn_tmpfile = tempname()
let original_dir = getcwd()
lcd %:p:h
let cmdlist = split(a:cmd)
let cmd = 'nnn -p ' . s:nnn_tmpfile
if len(cmdlist) > 1
let cmd .= ' ' . join(cmdlist[1:], ' ')
else
let cmd .= ' ' . getcwd()
endif
exe "lcd " . original_dir
return [cmd, {'on_exit': funcref('s:nnn_callback')}, v:false]
endfunction
function! s:nnn_callback(...) abort
if filereadable(s:nnn_tmpfile)
let filenames = readfile(s:nnn_tmpfile)
if !empty(filenames)
for filename in filenames
execute g:floaterm_open_command . ' ' . fnameescape(filename)
endfor
endif
endif
endfunction

38
etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/ranger.vim

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
" vim:sw=2:
" ============================================================================
" FileName: ranger.vim
" Author: voldikss <dyzplus@gmail.com>
" GitHub: https://github.com/voldikss
" ============================================================================
function! floaterm#wrapper#ranger#(cmd) abort
let s:ranger_tmpfile = tempname()
let original_dir = getcwd()
lcd %:p:h
let cmdlist = split(a:cmd)
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()
endif
endif
exe "lcd " . original_dir
return [cmd, {'on_exit': funcref('s:ranger_callback')}, v:false]
endfunction
function! s:ranger_callback(...) abort
if filereadable(s:ranger_tmpfile)
let filenames = readfile(s:ranger_tmpfile)
if !empty(filenames)
for filename in filenames
execute g:floaterm_open_command . ' ' . fnameescape(filename)
endfor
endif
endif
endfunction

34
etc/soft/nvim/+plugins/vim-floaterm/autoload/floaterm/wrapper/vifm.vim

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
" vim:sw=2:
" ============================================================================
" FileName: vifm.vim
" Author: kazhala <kevin7441@gmail.com>
" GitHub: https://github.com/kazhala
" ============================================================================
function! floaterm#wrapper#vifm#(cmd) abort
let s:vifm_tmpfile = tempname()
let original_dir = getcwd()
lcd %:p:h
let cmdlist = split(a:cmd)
let cmd = 'vifm --choose-files ' . s:vifm_tmpfile
if len(cmdlist) > 1
let cmd .= ' ' . join(cmdlist[1:], ' ')
else
let cmd .= ' ' . getcwd()
endif
exe "lcd " . original_dir
return [cmd, {'on_exit': funcref('s:vifm_callback')}, v:false]
endfunction
function! s:vifm_callback(...) abort
if filereadable(s:vifm_tmpfile)
let filenames = readfile(s:vifm_tmpfile)
if !empty(filenames)
for filename in filenames
execute g:floaterm_open_command . ' ' . fnameescape(filename)
endfor
endif
endif
endfunction

36
etc/soft/nvim/+plugins/vim-floaterm/autoload/health/floaterm.vim

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
" vim:sw=2:
" ============================================================================
" FileName: floaterm.vim
" Author: voldikss <dyzplus@gmail.com>
" GitHub: https://github.com/voldikss
" ============================================================================
function! s:check_terminal() abort
if exists(':terminal') > 0
call health#report_ok('Terminal feature is OK')
else
call health#report_error('Terminal feature is required but not found')
endif
endfunction
function! s:check_floating() abort
if has('nvim') && exists('*nvim_win_set_config')
call health#report_ok('Floating window feature is OK')
else
call health#report_error('Floating window feature is required but not found, will use normal window')
endif
endfunction
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')
endif
endfunction
function! health#floaterm#check() abort
call s:check_terminal()
call s:check_floating()
call s:check_nvr()
endfunction

146
etc/soft/nvim/+plugins/vim-floaterm/doc/floaterm.txt

@ -1,7 +1,11 @@ @@ -1,7 +1,11 @@
*floaterm.txt* Neovim's floating terminal plugin Last change: 2019-12-28
*floaterm.txt* Neovim floating terminal plugin Last change: 2019-02-07
Author : voldikss <https://github.com/voldikss>
License: MIT license
NOTE: This is outdated, please refer to the README file:
../README.md
or
https://github.com/voldikss/vim-floaterm/blob/master/README.md
==============================================================================
CONTENTS *floaterm-contents*
@ -11,6 +15,8 @@ CONTENTS *floaterm-contents* @@ -11,6 +15,8 @@ CONTENTS *floaterm-contents*
Variables |floaterm-variables|
Keymappings |floaterm-key-mappings|
Commands |floaterm-commands|
Highlight |floaterm-highlight|
Extensions |floaterm-extensions|
Q-A |floaterm-q&a|
Repository |floaterm-repository|
@ -18,15 +24,15 @@ CONTENTS *floaterm-contents* @@ -18,15 +24,15 @@ CONTENTS *floaterm-contents*
==============================================================================
INTRODUCTION *floaterm-introduction*
Use neovim terminal in the floating window.
Use neovim terminal in the floating window.
==============================================================================
INSTALL *floaterm-install*
With vim-plug:
>
Plug 'voldikss/vim-floaterm'
With vim-plug:
>
Plug 'voldikss/vim-floaterm'
<
==============================================================================
@ -38,60 +44,55 @@ FEATURES *floaterm-features* @@ -38,60 +44,55 @@ FEATURES *floaterm-features*
- Customizable floating terminal style
- Switch/Preview floating terminal buffer using [vim-clap](https://github.com/liuchengxu/vim-clap)(try `:Clap floaterm`)
- 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_type *g:floaterm_type*
g:floaterm_wintype *g:floaterm_wintype*
Available:`'floating'`(neovim only), `'normal'`(vim8 and neovim)
Available: "floating"(neovim only), "normal"(vim8 and neovim)
Default: `'floating'`
Default: "floating"
g:floaterm_width *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: |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: `int` (number of lines) or `float` (between 0 and 1).
If `float`, the height is relative to `&lines`.
Default: `0.6`
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 opacity of the floating terminal
Description: The transparency of the floating terminal
Default: `0`
Default: 0
g:floaterm_position *g:floaterm_position*
Available: `'center'`, `'topleft'`, `'topright'`, `'bottomleft'`,
`'bottomright'`, `'auto'`
Available: "center", "topleft", "topright", "bottomleft",
"bottomright", "auto"
Default: `'center'`
g:floaterm_background *g:floaterm_background*
Type: string(e.g. `'#000000'`, `'black'`)
Default: background color of normal floating window
Default: "center"
g:floaterm_borderchars *g:floaterm_borderchars*
Default: `['─', '│', '─', '│', '┌', '┐', '┘', '└']`
g:floaterm_border_color *g:floaterm_border_color*
Type: string(e.g. `'#FFFFFF'`, `'white'`)
Default: "['─', '│', '─', '│', '┌', '┐', '┘', '└']"
Default: foreground color of normal floating window
==============================================================================
@ -99,14 +100,13 @@ MAPPINGS *floaterm-key-mappings* @@ -99,14 +100,13 @@ MAPPINGS *floaterm-key-mappings*
This plugin doesn't supply any default mappings.
>
""" Example configuration
let g:floaterm_keymap_new = '<F7>'
let g:floaterm_keymap_prev = '<F8>'
let g:floaterm_keymap_next = '<F9>'
let g:floaterm_keymap_toggle = '<F10>'
""" Configuration example
let g:floaterm_keymap_new = '<F7>'
let g:floaterm_keymap_prev = '<F8>'
let g:floaterm_keymap_next = '<F9>'
let g:floaterm_keymap_toggle = '<F10>'
<
==============================================================================
COMMANDS *floaterm-commands*
@ -121,25 +121,87 @@ COMMANDS *floaterm-commands* @@ -121,25 +121,87 @@ COMMANDS *floaterm-commands*
:FloatermToggle *:FloatermToggle*
==============================================================================
HIGHLIGHT *floaterm-highlight*
This plugin supplies two `highlight-groups` to specify the
background/foregrond color of floaterm(border) window
By default, they are both linked to `Normal`
>
" Configuration example
hi Floaterm guibg=black
hi FloatermBorder guibg=gray guifg=blue
<
==============================================================================
EXTENSIONS *floaterm-extensions*
------------------------------------------------------------------------------
VIM-CLAP *Clap-floaterm*
Start |vim-clap| to manage floaterms.
>
:Clap floaterm
<
------------------------------------------------------------------------------
DENITE.NVIM *Denite-floaterm*
*denite-source-floaterm*
SOURCES~
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*
ACTIONS~
open (default)
Open the selected floaterm.
new
Open a new floaterm.
preview
Preview the selected floaterm.
*denite-floaterm-usage*
USAGE~
Start to manage existent floaterms.
>
:Denite floaterm
<
Start to open a new floaterm.
>
:Denite floaterm:new
<
Start with all features and preview automatically with moving the cursor.
>
:Denite floaterm floaterm:new -auto-action=preview
<
==============================================================================
Q-A *floaterm-q&a*
- This plugin leaves an empty buffer on startify window
Put this code in `vimrc`
Put this code in "vimrc"
>
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`:
Set 'shell' option in your "vimrc":
>
set shell=/path/to/shell
- I would like to customize the style of the floating terminal window
Use `autocmd`. For example
Use |autocmd|. For example,
>
function s:floatermSettings()
setlocal number

39
etc/soft/nvim/+plugins/vim-floaterm/plugin/floaterm.vim

@ -1,30 +1,43 @@ @@ -1,30 +1,43 @@
" vim:sw=2:
" ============================================================================
" FileName: plugin/floaterm.vim
" Description:
" Author: voldikss <dyzplus@gmail.com>
" GitHub: https://github.com/voldikss
" ============================================================================
scriptencoding utf-8
let g:floaterm_type = get(g:, 'floaterm_type', v:null)
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', 'auto')
let g:floaterm_background = get(g:, 'floaterm_background', v:null)
let g:floaterm_borderchars = get(g:, 'floaterm_borderchars', ['─', '│', '─', '│', '┌', '┐', '┘', '└'])
let g:floaterm_border_color = get(g:, 'floaterm_border_color', v:null)
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_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)
command! -nargs=0 FloatermNew call floaterm#start('new')
command! -nargs=0 FloatermPrev call floaterm#start('prev')
command! -nargs=0 FloatermNext call floaterm#start('next')
command! -nargs=0 FloatermToggle call floaterm#start('toggle')
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', <f-args>)
command! -nargs=* -complete=customlist,floaterm#cmdline#complete
\ FloatermUpdate call floaterm#run('update', <f-args>)
command! -nargs=? -complete=customlist,floaterm#cmdline#floaterm_names
\ FloatermToggle call floaterm#toggle(<q-args>)
command! -nargs=? -range -bang -complete=customlist,floaterm#cmdline#floaterm_names
\ FloatermSend call floaterm#send('<bang>', <q-args>)
hi def link Floaterm Normal
hi def link FloatermBorder Normal
function! s:install_keymap()
if g:floaterm_keymap_new != v:null

87
etc/soft/nvim/+plugins/vim-floaterm/rplugin/python3/denite/kind/floaterm.py

@ -0,0 +1,87 @@ @@ -0,0 +1,87 @@
from denite.kind.base import Base
from denite.util import Nvim, UserContext
PREVIEW_FILENAME = "[denite-floaterm-preview]"
class Kind(Base):
def __init__(self, vim: Nvim) -> None:
super().__init__(vim)
self.name = "floaterm"
self.default_action = "open"
self._previewed_bufnr = -1
self._is_nvim = bool(vim.funcs.has("nvim"))
def action_new(self, context: UserContext) -> None:
self.vim.command("FloatermNew")
def action_open(self, context: UserContext) -> None:
target = context["targets"][0]
if target.get("action__is_new", False):
self.action_new(context)
return
bufnr = target["action__bufnr"]
self.vim.call("floaterm#terminal#open_existing", bufnr)
def action_preview(self, context: UserContext) -> None:
target = context["targets"][0]
if "action__bufnr" not in target:
self.vim.command("pclose!")
return
bufnr = target["action__bufnr"]
if (
context["auto_action"] != "preview"
and self._is_preview_window_opened()
and self._previewed_bufnr == bufnr
):
self.vim.command("pclose!")
self._previewed_bufnr = -1
return
self._save_win()
self.vim.call("denite#helper#preview_file", context, PREVIEW_FILENAME)
self.vim.command("wincmd P")
self.vim.current.buffer.options["swapfile"] = False
self.vim.current.buffer.options["bufhidden"] = "wipe"
self.vim.current.buffer.options["buftype"] = "nofile"
buf = self.vim.buffers[bufnr]
last_line = len(buf) - 1
last_non_empty_line = next(
filter(lambda x: buf[x] != "", range(last_line, 0, -1)), last_line
)
start = max(0, last_non_empty_line - self.vim.options["previewheight"] + 1)
end = last_non_empty_line + 1
self.vim.current.buffer[:] = buf[start:end]
self._restore_win()
self._previewed_bufnr = bufnr
def _is_preview_window_opened(self) -> bool:
# NOTE: Using `vim.windows` is better, but vim does not recognize it.
# So here uses an odd way to list windows.
return next(
filter(
lambda x: bool(self.vim.call("getwinvar", x, "&previewwindow")),
range(1, self.vim.call("winnr", "$") + 1),
),
False,
)
def _save_win(self) -> None:
if self._is_nvim:
self._current_window = self.vim.current.window
else:
self._current_window = self.vim.funcs.win_getid()
def _restore_win(self) -> None:
if self._is_nvim:
self.vim.current.window = self._current_window
else:
self.vim.funcs.win_gotoid(self._current_window)

71
etc/soft/nvim/+plugins/vim-floaterm/rplugin/python3/denite/source/floaterm.py

@ -0,0 +1,71 @@ @@ -0,0 +1,71 @@
from denite.base.source import Base
from denite.util import Nvim, UserContext, Candidate, Candidates
DELIMITER = "\u00a0:\u00a0"
FLOATERM_HIGHLIGHT_SYNTAX = [
{"name": "Bufnr", "link": "Constant", "re": r"\d\+ ", "next": "Name"},
{"name": "Name", "link": "Function", "delimiter": DELIMITER, "next": "Title"},
{"name": "Title", "link": "Title", "re": r".*"},
]
class Source(Base):
def __init__(self, vim: Nvim) -> None:
super().__init__(vim)
self.name = "floaterm"
self.kind = "floaterm"
self._is_nvim = bool(vim.funcs.has("nvim"))
def on_init(self, context: UserContext) -> None:
self.vim.call("floaterm#hide")
def gather_candidates(self, context: UserContext) -> Candidates:
return (
[{"word": "[open new floaterm]", "action__is_new": True}]
if "new" in context["args"]
else [
self._make_candidate(x)
for x in self.vim.call("floaterm#buflist#gather")
]
)
def highlight(self) -> None:
for i, syn in enumerate(FLOATERM_HIGHLIGHT_SYNTAX):
def syn_name(key: str) -> str:
return "_".join([self.syntax_name, syn[key]])
self.vim.command(
f"highlight default link {syn_name('name')} {syn['link']}")
containedin = f" containedin={self.syntax_name}" if i == 0 else ""
nextgroup = f" nextgroup={syn_name('next')}" if "next" in syn else ""
if "delimiter" in syn:
self.vim.command(
"syntax region {0} matchgroup=Delimiter start=/{1}/ end=/{1}/ concealends contained{2}{3}".format(
syn_name(
"name"), syn["delimiter"], containedin, nextgroup
)
)
else:
self.vim.command(
"syntax match {0} /{1}/ contained{2}{3}".format(
syn_name("name"), syn["re"], containedin, nextgroup
)
)
def _make_candidate(self, bufnr: int) -> Candidate:
name = self.vim.buffers[bufnr].name
title = self._term_title(bufnr)
return {
"word": name,
"abbr": f"{bufnr: >2} {DELIMITER}{name}{DELIMITER} {title}",
"action__bufnr": bufnr,
}
def _term_title(self, bufnr: int) -> str:
return str(
self.vim.api.buf_get_var(bufnr, "term_title")
if self._is_nvim
else self.vim.funcs.term_gettitle(bufnr)
)

118
etc/soft/nvim/+plugins/vim-floaterm/test/command.vader

@ -0,0 +1,118 @@ @@ -0,0 +1,118 @@
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):
\<C-\><C-n><F12>
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):
\<C-\><C-n><F12>
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

118
etc/soft/nvim/+plugins/vim-floaterm/test/keymap.vader

@ -0,0 +1,118 @@ @@ -0,0 +1,118 @@
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):
\<F7>
Then:
call AssertFiletype('floaterm')
call CheckWindow(v:true)
let buffer1 = bufnr('%')
Do (Open second floaterm):
\<F7>
Then:
call AssertFiletype('floaterm')
call CheckWindow(v:true)
let buffer2 = bufnr('%')
Do (Open third floaterm):
\<F7>
Then:
call AssertFiletype('floaterm')
call CheckWindow(v:true)
let buffer3 = bufnr('%')
Do (Toggle close floaterm):
\<C-\><C-n><F12>
Then:
call AssertFiletype('')
call CheckWindow(v:false)
call AssertBufnr(buffer0)
Do (Toggle open floaterm):
\<F12>
Then:
call AssertFiletype('floaterm')
call CheckWindow(v:true)
call AssertBufnr(buffer3)
Do (Toggle close floaterm):
\<C-\><C-n><F12>
Then:
call AssertFiletype('')
call CheckWindow(v:false)
call AssertBufnr(buffer0)
Do (Next floaterm):
\<F9>
Then:
call AssertFiletype('floaterm')
call CheckWindow(v:true)
call AssertBufnr(buffer1)
Do (Next floaterm):
\<F9>
Then:
call AssertFiletype('floaterm')
call CheckWindow(v:true)
call AssertBufnr(buffer2)
Do (Next floaterm):
\<F9>
Then:
call AssertFiletype('floaterm')
call CheckWindow(v:true)
call AssertBufnr(buffer3)
Do (Prev floaterm):
\<F8>
Then:
call AssertFiletype('floaterm')
call CheckWindow(v:true)
call AssertBufnr(buffer2)
Do (Prev floaterm):
\<F8>
Then:
call AssertFiletype('floaterm')
call CheckWindow(v:true)
call AssertBufnr(buffer1)
Do (Insert a floaterm between first and second):
\<F7>
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

12
etc/soft/nvim/+plugins/vim-floaterm/test/vimrc

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
filetype off
let &runtimepath .= ',' . expand('<sfile>:p:h:h')
let &runtimepath .= ',' . expand('<sfile>:p:h:h') . '/vader.vim'
echom &runtimepath
filetype plugin indent on
syntax enable
let g:floaterm_wintype = 'floating'
let g:floaterm_keymap_new = '<F7>'
let g:floaterm_keymap_prev = '<F8>'
let g:floaterm_keymap_next = '<F9>'
let g:floaterm_keymap_toggle = '<F12>'
Loading…
Cancel
Save