I've configured Vim to look like this:
+------------------------------------+
| N | Code |
| E | |
| R | |
| D | |
| T | |
| r |-------------------------------|
| e | REPL |
| e | |
+------------------------------------+
Every element is in it's own buffer. Is it possible to delete the REPL buffer only when I quit the code buffer? If I open and close help, for example, the REPL should stay but when I close the code buffer, the REPL buffer should close as well.
This is what I have now:
let s:code_repl_nrs = {} " A map of (code buffer number) - (REPL buffer number)
let s:last_leaved_buffer_nr = -1 " The number of the last leaved buffer
autocmd BufLeave,BufDelete * let s:last_leaved_buffer_nr = bufnr('%')
autocmd BufUnload * call <SID>StopREPL(s:last_leaved_buffer_nr) " Stop the REPL when closing the code buffer
"" Stops a REPL given the number of the current buffer
function! s:StopREPL(buffer_nr)
let l:repl_nr = get(s:code_repl_nrs, a:buffer_nr . '', -1) " Get the number of the REPL buffer
if l:repl_nr != -1
exec l:repl_nr . 'bdelete!'
endif
endfunction
When I use :h, the REPL closes. How can I prevent this?
Turns out <abuf> is the answer, replacing s:last_leaved_buffer_nr:
autocmd BufUnload * call <SID>StopRepl(expand('<abuf>'))
As per :h <abuf>:
When executing autocommands, is replaced with the currently
effective buffer number (for ":r file" and ":so file" it is
the current buffer, the file being read/sourced is not in a
buffer).
Turns out <abuf> gets expanded to the buffer number of the buffer that is currently unloading. When the code buffer is unloading, the buffer number will be in s:code_repl_nrs and s:StopREPL will be able to delete the REPL buffer. When some other buffer is unloading, s:StopREPL will not be able to delete the REPL buffer.
Related
The idea is to do something similar to what Golden Ratio (the vim plugin) does. But instead of sizing to a "golden ratio", I want to set a specific size to the unselected windows.
Ex:
# Window 1 selected
----------------------
| | | | |
| | | | |
| 1 | 2 | 3 | 4 |
| | | | |
| | | | |
----------------------
# Window 3 selected
----------------------
| | | | |
| | | | |
| 1 | 2 | 3 | 4 |
| | | | |
| | | | |
----------------------
Here's what I've written so far (It's just a WIP):
function g:ResizeWindow()
let tabs = gettabinfo()
let current_tabnr = tabpagenr()
let current_window = win_getid()
let tab = filter(tabs, 'v:val.tabnr == current_tabnr')[0]
for window in tab.windows
if window != current_window
call win_gotoid(window)
exe 'vertical resize' 20
endif
endfor
call win_gotoid(current_window)
let current_window_size = &columns - ((len(tab.windows) - 1) * 20)
exe 'vertical resize' current_window_size
endfunction
autocmd WinNew,WinEnter * :call g:ResizeWindow()
To test, you can open a single buffer and just :vsp it several times. Then when you navigate the windows, it seems to work in most case but occasionally one of the windows collapses in an inconsistent way. It's much smaller than the rest. Usually this happens as I navigate from the left to right... and the back from right to left.
Any ideas on what's wrong with this and how to fix it?
super interesting function!
Here's a working version:
function g:ResizeWindow()
let tabs = gettabinfo()
let current_tabnr = tabpagenr()
let current_window = win_getid()
let tab = filter(tabs, 'v:val.tabnr == current_tabnr')[0]
let small_size = 5
for window in tab.windows
if window == current_window
let size = &columns - ((len(tab.windows) - 1) * small_size) - (len(tab.windows) - 1)
else
let size = small_size
endif
noautocmd call win_gotoid(window)
exe 'noautocmd vertical resize ' . size
endfor
call win_gotoid(current_window)
endfunction
set winwidth=1
set winminwidth=1
autocmd WinNew,WinEnter * :call g:ResizeWindow()
Explanation
I did quite a few changes to your initial WIP, here are the main problems your code encountered:
The function was called recursively: call of the function win_gotoid was triggering the autocmd. So this was messing up all the sizes
The default minimum window size (minwinwidth) and default window size (winwidth) were messing up with the size you applied
You resized the current window as last, which squished the window on the right
Your main window size calculation didn't take in account the window separators
Disclaimer
This function breaks if there is an horizontal split on one window!
This thread here discuss about piping output of shell command into a new buffer in vim but it does not discuss it by using the current buffer like
%new | r !%gcut -d '"' -f2,4,6,8,10
where the percentage sign % tries to use the current buffer, unfortunately resulting to
E499: Empty file name for '%' or '#', only works with ":p:h"
so
How can I pipe the shell-command-edited buffer into a new buffer in Vim?
:new | r !gcut -d '"' -f2,4,6,8,10 #
# is a placeholder for "the previous file".
If you have spaces in the filename, then use quotes
:new | r !gcut -d '"' -f2,4,6,8,10 "#"
I've been using shortcutfoo to tighten up my vim muscle memory and I ran across some commands I can't understand even with their animations and explanations.
These are the explanations for the commands:
fw | Move to next 'w' on line
Fw | Move to previous 'w' on line
tw | Move before next 'w' on line
Tw | Move before previous 'w' on line
; | Repeat last f, F, t, or T
I've tried using these commands in my vim but they don't seem to do anything noticeable.
Go to link:
https://www.shortcutfoo.com/app/dojos/vim/cheatsheet
Search keyword: Intermediate Text Navigation I.
Hover in icon camera preview. You can see an example to imagine easy.
Example:
fw | Move to next 'w' on line:
Fw | Move to previous 'w' on line
tw | Move before next 'w' on line
Tw | Move before previous 'w' on line
; | Repeat last f, F, t, or T
Similar with other key shortcut.
The Problem
I understand that a variant of this question might have been answered.
I have tried :set guitablabel=%t, but there are two problems:
It doesn't work in Vim in the terminal (since gui settings only work for GVim). I exclusively use terminal Vim, so the answer given doesn't apply.
Files with same names in different directories are not shown their relative folders for distinction.
Current Situation
To better understand my question, say I have a project folder, awesome-project with the following structure:
awesome-project
AAA/
file1.txt
file2.txt
CCC/
special.txt
BBB/
file2.txt
file3.txt
DDD/
special.txt
Say I cd to the project in my terminal and vim from there.Then I proceed to open all the files in separate tabs.
Currently, my vim is set up to display the tabs as following (the |s are separators - use your imagination!):
AAA/file1.txt | AAA/file1.txt | AAA/CCC/special.txt | BBB/file2.txt | BBB/file3.txt | BBB/DDD/special.txt
What I Want
I want the tabs to display as:
file1.txt | AAA/file2.txt | CCC/special.txt | BBB/file2.txt | file3.txt | DDD/special.txt
or what Sublime Text does:
file1.txt | file2.txt --- AAA | special.txt --- AAA/CCC | file2.txt --- BBB | file3.txt | special.txt --- BBB/DDD
Essentially, given the current tabs have file names that are unique, all tabs should just display their file name. Otherwise, provide the first distinct relative folder to display in the tab so I can tell which files are file.
This is a feature in many other text editors (Sublime Text, Atom) that I would really like to keep because the relative path file names are too long for my own good.
Any help would be appreciated, whether it be:
a simple command that fixes the problem (yay!)
an available plugin
tips on how I can configure this manually in .vimrc
You are — unsurprisingly — misunderstanding and misusing tab pages.
Just like Atom or Sublime Text, Vim is a document-based program but, unlike the others, it doesn't use the "tab" metaphor as proxy for those documents. Instead, tab pages are workspaces designed to contain one or more windows, themselves viewports designed to display buffers. Buffers are Vim's equivalent of the documents in other editors and there's thankfully no built-in way to have an "always-on" list of buffers. "Thankfully" because such a feature would be just as useless as it is in those other editors.
Instead of using tab pages as document proxies — something that can't work anyway — I'd suggest you get used to Vim's buffer-based workflow.
Here is a bit of reading to get you started on the good foot.
I am also trying to do the same thing. You need to read tabline and setting-tabline if you are interested in writting your own tab lines. However, if you just want a simple one, you are free to copy this to your vimrc:
"tabline
if exists("+showtabline")
function MyTabLine()
let s = ''
let t = tabpagenr()
let i = 1
while i <= tabpagenr('$')
let buflist = tabpagebuflist(i)
let winnr = tabpagewinnr(i)
let s .= '%' . i . 'T'
let s .= (i == t ? '%1*' : '%2*')
let s .= ' '
let s .= '|'. i . ')'
let s .= ' %*'
let s .= (i == t ? '%#TabLineSel#' : '%#TabLine#')
let file = bufname(buflist[winnr - 1])
let file = fnamemodify(file, ':p:t')
if file == ''
let file = '[No Name]'
endif
let s .= file
let s .= ' '
let i = i + 1
endwhile
let s .= '%T%#TabLineFill#%='
let s .= (tabpagenr('$') > 1 ? '%999XX' : 'X')
return s
endfunction
set stal=2
set tabline=%!MyTabLine()
endif
I have come up with a perl script that outputs a template for documenting functions and structures given the definition of a function/struct from my C code.
To use it , i visually select the definition of the struct, yank and paste it right above the original definition, and invoke the script on this pasted struct. It replaces it with document for that struct.
Now is there a way that will avoid that yank paste? I am looking for a way to invoke a shell command but the output from that should be pasted somewhere else in the file, not necessarily on top of it.
IOW
:'a,'b!perl ~/bin/document.pl
replaces text between mark a and markb, I want to add the output of document.pl above mark a.
One possible solution would be to modify the perl script in a way that it also outputs its input at the end. Then you would end up with the desired result.
If you have zsh as your shell, you can use co-process:
'a,'b!coproc perl ~/bin/document.pl ; tee >&p | cat <&p
To get output before your text (this command puts it after), you should use a slightly more complex command:
'a,'b!coproc perl ~/bin/document.pl ; tee >&p | cat <(<&p) -
System-independent solution, using vim and temporary buffer:
'a,'byank a | new | 0put a | $d | execute "%!perl ~/bin/document.pl" | %d a | bw! | 'a-1put a
Try with something like this:
function! MyFunc() range
" Preserve the register.
let old_reg = #a
exec a:firstline.','.a:lastline.'yank a'
" Change to do what you need with register a.
" Insert output before a:firstline
exec (a:firstline - 1).'read !your magic with '.#a
" Restore the register
let #a = old_reg
endfunction
" :2,5MyOwn will process lines from 2 to 5 and insert the output before line 2
command! -bar -range -nargs=? MyOwn <line1>,<line2>call MyFunc()