How to set highlights for new windows except from specific filetypes in neovim? - neovim

I'm trying to create a highlight for trailing spaces and tabs for all windows in NeoVim, but I'm having problems to handle exceptions. Basically I want to set it for all windows except terminal windows (which I use the plugin toggleterm) and the help page.
From reading the docs I realised that the WinNew or WinEnter events are fired before the filetype is set, so it basically inherits the filetype from the current window. Because of that my check never works properly. Is there a way to make this check work? I thought of using buffer events, but then I'd be executing this many times unnecessarily since the match applies for the window and not for the buffer.
vim.cmd('highlight ExtraWhitespace ctermbg=lightyellow guibg=lightyellow')
vim.api.nvim_create_autocmd({ 'VimEnter', 'WinNew' }, {
desc = 'Highlight all tabs and trailing whitespaces',
pattern = '*',
callback = function()
-- TODO: implement blacklist
if vim.bo.filetype ~= 'toggleterm' or vim.bo.filetype ~= 'help' then
vim.fn.matchadd('ExtraWhitespace', '\\s\\+$\\|\\t')
end
end,
})

Terminal can be opened in any existing window, and so you can't tell this beforehand and can't blacklist anything.
Instead, remove the match after terminal has been opened.
augroup mystuff | au!
autocmd VimEnter,WinNew 2match Todo /\s\+$\|\t/
autocmd TermOpen,TerminalWinOpen * 2match none
" ^-- Nvim ^-- Vim
augroup end

Related

Weird cases when drag and droping files in to vscode terminal

My problem
I am currently working with Python in VS Code and I encountered a weird problem with the drag and drop feature. When I drag a folder path or a file path into the Terminal, then it always begins with the &
sign. This only happens when I start my program.
Here is an example:
& 'filepath' or
& "filepath"
I don't have a problem with the quotes but with the & and the blankspace. I can't find anything online, I was wondering if anybody else has this problem.
Thanks in advance :)
What did you try and what were you expecting?
Well, I did try it with other files and folders, but it didn't help.
I've also tried running the code outside VS Code and drag and dropping was fine. So I guess it has something to do with VS Code.
This happens in certain conditions when the path contains a space or parenthesis and the current terminal is powershell based.
I'm not sure why this was added, but the mechanism happens here:
src/vs/workbench/contrib/terminal/browser/terminalInstance.ts:2664
if (isPowerShell && (hasSpace || originalPath.indexOf('\'') !== -1)) {
return `& '${originalPath.replace(/'/g, '\'\'')}'`;
}
if (hasParens && isPowerShell) {
return `& '${originalPath}'`;
}
The original PRs introducing this change are here and here
The rationale seems to be to run files with certain symbols in their name:
single quotes in paths for PowerShell (i.e /Users/tyler/tyler's stuff/ -> & '/Users/tyler/tyler''s stuff/' to escape a ' in a ' ' string, you add an extra ')
The smallest workaround is to not open a powershell terminal.
So either open a terminal with the drop-down next to the "+" (#command:workbench.action.terminal.newWithProfile) which should have other entries next to powershell like "Command Prompt"(cmd.exe).
If you want to make this the default select the terminal profile then use the "Terminal: Select Default Profile"
(#command:workbench.action.terminal.selectDefaultShell) command to change the default.
If you want this to be configurable or not happen when the foreground application is no longer powershell you should probably file an issue with vscode.

How to highlight multiple words on VIM and modify them all? Like CTRL+D does on VS-Code?

On VSCode, if you highlight a text, you can do "CTRL+d" and it will highlight the next matching text and add a cursor there.
You can then start typing/deleting and it will affect all the cursors.
How can I do this in VIM?
Note: I know the search and replace function, this is too slow to type, is there something as easy or almost as easy as it is on VSCode?
:%s/foo/bar
Visual explanation on VSCode:
Highlight the word you're looking to replace:
CTRL+d two times, which highlights them all:
Now modify them all at the same time:
I want this will help you.
You can do the below steps to change all selected words.
< SHIFT > + # // select the all words on your cursor.
:%s//NEW_WORD/g
If you want to change all 'const' to 'AAA',
move to one of the 'const' words and press < SHIFT >+'#'.
And type the command ":%s//AAA/g".
Move the cursor on top of a word in your code.
Type gb to add another cursor. This puts Vim into Visual
mode and ready to operate on the word you have selected.
Type gb to continue adding cursors until you’re done.
Now you can perform an action in Visual mode (delete,
change, etc).
Go back to Normal mode with <ESC>

vim + janus / indent a perl block

using vim + janus (https://github.com/carlhuda/janus)
is enabled by default in .vim/vimrc
filetype plugin indent on
i'm writing perl, every newline is indented by default.
how i can select a block (or the full document) and
reindent automatically?
You can select the block by going to visual mode (press v or Shift + v or Ctrl + v in normal mode). Reindent can be done pressing = after selection of the block.
To apply the same formatting to the whole document you can use:
gg=G which means "go to the beginning", "reformat" until "end of document".
You can use :help = to get more information on reformatting.
If your block is a paragraph separated by empty line you, can use vip to select it quickly.
See :help text-objects for more information.
Since you're asking about perl I'm assuming "blocks" are identified by { and }. If that's the case, I'd suggest indenting the block by using one of the following from somewhere inside the block:
>i{ to forcibly indent all lines by one shiftwidth
=i{ to reindent the block per the indent rules for perl
I personally prefer the latter, but if you have some non-standard indentation you don't want to screw up inside the block then you'd want to use the prior.
This takes advantage of vim's "Block" text objects to operate on only the desired text.

How can I script vim to run perltidy on a buffer?

At my current job, we have coding-style standards that are different from the ones I normally follow. Fortunately, we have a canned RC file for perltidy that I can apply to reformat files before I submit them to our review process.
I have code for emacs that I use to run a command over a buffer and replace the buffer with the output, which I have adapted for this. But I sometimes alternate between emacs and vim, and would like to have the same capabilities there. I'm sure that this or something similar is simple and had been done and re-done many times over. But I've not had much luck finding any examples of vim-script that seem to do what I need. Which is, in essence, to be able to hit a key combo (like Ctrl-F6, what I use in emacs) and have the buffer be reformatted in-place by perltidy. While I'm a comfortable vim-user, I'm completely clueless at writing this sort of thing for vim.
After trying #hobbs answer I noticed that when filtering the entire buffer through perltidy the cursor returned to byte 1, and I had to make a mental note of the original line number so I could go back after :Tidy completed.
So building on #hobbs' and #Ignacio's answers, I added the following to my .vimrc:
"define :Tidy command to run perltidy on visual selection || entire buffer"
command -range=% -nargs=* Tidy <line1>,<line2>!perltidy
"run :Tidy on entire buffer and return cursor to (approximate) original position"
fun DoTidy()
let l = line(".")
let c = col(".")
:Tidy
call cursor(l, c)
endfun
"shortcut for normal mode to run on entire buffer then return to current line"
au Filetype perl nmap <F2> :call DoTidy()<CR>
"shortcut for visual mode to run on the current visual selection"
au Filetype perl vmap <F2> :Tidy<CR>
(closing " added to comments for SO syntax highlighting purposes (not required, but valid vim syntax))
DoTidy() will return the cursor to its original position plus or minus at most X bytes, where X is the number of bytes added/removed by perltidy relative to the original cursor position. But this is fairly trivial as long as you keep things tidy :).
[Vim version: 7.2]
EDIT: Updated DoTidy() to incorporate #mikew's comment for readability and for compatibility with Vim 7.0
My tidy command:
command -range=% -nargs=* Tidy <line1>,<line2>!
\perltidy (your default options go here) <args>
If you use a visual selection or provide a range then it will tidy the selected range, otherwise it will use the whole file. You can put a set of default options (if you have any) at the point where I wrote (your default options go here), but any arguments that you provide to :Tidy will be appended to the perltidy commandline, overriding your defaults. (If you use a .perltidyrc you might not have default args -- that's fine -- but then again you might want to have a default like --profile=vim that sets up defaults only for when you're working in vim. Whatever works.)
The command to filter the entire buffer through an external program is:
:%!command
Put the following in ~/.vimrc to bind it to Ctrl-F6 in normal mode:
:nmap <C-F6> :%!command<CR>
For added fun:
:au Filetype perl nmap <C-F6> :%!command<CR>
This will only map the filter if editing a Perl file.
Taking hobbs' answer a step further, you can map that command to a shortcut key:
command -range=% -nargs=* Tidy <line1>,<line2>!perltidy -q
noremap <C-F6> :Tidy<CR>
And another step further: Only map the command when you're in a Perl buffer (since you probably wouldn't want to run perltidy on any other language):
autocmd BufRead,BufNewFile *.pl,*.plx,*.pm command! -range=% -nargs=* Tidy <line1>,<line2>!perltidy -q
autocmd BufRead,BufNewFile *.pl,*.plx,*.pm noremap <C-F6> :Tidy<CR>
Now you can press Ctrl-F6 without an active selection to format the whole file, or with an active selection to format just that section.
Instead of creating a new keyboard shortcut, how about replacing the meaning of the = command which is already in people's finger memory for indenting stuff? Yes, perlcritic does more than just indent but when you use perlcritic anyways, then you probably don't want to go back to the inferior "just indent" = command. So lets overwrite it!
filetype plugin indent on
autocmd FileType perl setlocal equalprg=perltidy
And now we can use = just like before but with the added functionality of perlcritic that goes beyond just indenting lines:
== run perlcritic on the current line
5== run perlcritic on five lines
=i{ Re-indent the 'inner block', i.e. the contents of the block
=a{ Re-indent 'a block', i.e. block and containing braces
=2a{ Re-indent '2 blocks', i.e. this block and containing block
gg=G run perlcritic on the entire buffer
And the best part is, that you don't have to learn any new shortcuts but can continue using the ones you already used with more power. :)
I'm used to select text using line oriented visual Shift+V and then I press : an I have !perltidy -pbp -et4 somewhere in history so I hit once or more up arrow ⇧.

Is there any way to enable code completion for Perl in vim?

Surprisingly as you get good at vim, you can code even faster than standard IDEs such as Eclipse. But one thing I really miss is code completion, especially for long variable names and functions.
Is there any way to enable code completion for Perl in vim?
Ctrl-P (Get Previous Match) and Ctrl-N (Get Next Match) are kind of pseudo code completion. They basically search the file (Backwards for Ctrl-P, Forwards for Ctrl-N) you are editing (and any open buffers, and if you are using TAGS anything in your TAG file) for words that start with what you are typing and add a drop down list. It works surprisingly well for variables and function names, even if it isn't intellisense. Generally I use Ctrl-P as the variable or function I am looking for is usually behind in the code. Also if you keep the same copy of Vim open, it will search the files you have previously opened.
Vim 7 supports omni completion.
For example, I have this in my vimrc
autocmd FileType php set omnifunc=phpcomplete#CompletePHP
and then, when I press Ctrl-X Ctrl-O in Insert mode, I get a dropdown list of autocomplete possibilities.
Here's an omnicfunc for perl. No idea how well it works though.
Well, Vim's generic completion mechanism is surprisingly good, just using Ctrl-N in insert mode. Also, line completion is very handy, using C-x C-l.
Also check out this vim script for perl.
The standard Ctrl+N and Ctrl+P works even better if you add the following to your ~/.vim/ftplugin/perl.vim file:
set iskeyword+=:
Then it will autocomplete module names, etc.
The .vimrc clip in one of the other answers is slightly wrong. To turn your tab key into an auto-complete key, use this code:
inoremap <tab> <c-r>=InsertTabWrapper()<cr>
function! InsertTabWrapper()
let col = col('.') - 1
if !col || getline('.')[col - 1] !~ '\k'
return "\<tab>"
else
return "\<c-p>"
endif
endfunction
You can find this, and tons of other vim tricks in this thread at Perlmonks--which links to even more threads with lots more customizations.
You should look at the SuperTab plugin:
http://www.vim.org/scripts/script.php?script_id=1643
It let's you do completion (either the OmniCompletion or the regular completion) using tab and shift-tab instead of ^N and ^P.
https://github.com/c9s/perlomni.vim
Ctrl+N
This is explained in the Perl Hacks book, along with how to do Package completion. Highly recommended.