Running blocks of code inside vim - python

I recently added the following code in the .vimrc:
" Runs python inside vim
autocmd FileType python nnoremap <buffer> <F9> :exec '!clear; python' shellescape(#%, 1)<cr>
which allows me to run the entire python script from inside vim when pressed the F9 key. Nevertheless, several times I do not want to run the entire python script but just one line or even a block of lines. I googled in searching for these behavior but could not find any solution that worked, at least for me.
Someone can help me on this?
Thanks

First you should make a function to get your visually selected text. I brought it from https://stackoverflow.com/a/6271254/3108885:
function! s:GetVisualSelection()
let [lnum1, col1] = getpos("'<")[1:2]
let [lnum2, col2] = getpos("'>")[1:2]
let lines = getline(lnum1, lnum2)
let lines[-1] = lines[-1][:col2 - (&selection == 'inclusive' ? 1 : 2)]
let lines[0] = lines[0][col1 - 1:]
return join(lines, "\n")
endfunction
Then, add an autocmd for Visual mode.
autocmd FileType python vnoremap <buffer> <F9> :<C-U>exec '!clear; python -c' shellescape(<SID>GetVisualSelection(), 1)<CR>
Note that <C-U> is for cleaning '<,'> things when : is pressed on Visual mode. Also we use python -c to pass a program as a string.

Related

how to comment the selected block of code at a time in Vim?

I know how to comment one line,which is quite easy
:autocmd FileType python nnoremap <buffer> <leader>c I#<esc>
but how to comment multiple lines at one time by a mapping shortcut? I cannot think out it
i.e, I enter v mode and select a block of code , can I use a mapping shortcut to comment them at one time ?
the comment of a block of code means, put the # at every line of the selected block ,like
a = 2
b = 3
c = 4
to
#a = 2
#b = 3
#c = 4
You need a visual mode mapping to operate on a visual selection. Normal mode mappings start with n, insert mode mappings start with i, and visual mode mappings start with x (yeah…).
For this to work you will need :help :normal to execute your normal mode command on every line in the given range:
xnoremap <leader>c :normal I#<CR>
So…
augroup myStuff
autocmd!
autocmd FileType python nnoremap <buffer> <leader>c I#<esc>
autocmd FileType python xnoremap <buffer> <leader>c :normal I#<CR>
augroup END
For what it's worth, you might want to take a look at NERDCommenter, which does all the heavy-lifting for you.

introduce <Tab> in new line while creating a block for python files in vim

I want to introduce a tab character in the new line for creating a new block in vim for python files.
Example
when I write
if(a < 5):
and press Enter, the cursor should come in next line with a tab after if in vertical alignment from the above line. Something like this
if(a < 5):
a = 5
I have configured my .vimrc file like this
set nu
set autoindent
set tabstop=4
syntax enable
set showmatch
colorscheme gruvbox
set bg=dark
"automatically creates a block after :
autocmd FileType python inoremap :<CR> :<CR><Tab>
Note:
1) Last line, I have written for the intended purpose mentioned in my question.
2) autoindent is set.
3) I dont want to use any plugin.
Problem I am facing:
When I press Enter after : , in addition to tab, one extra space is also created which creates wrong indentation.
Thanks in advance for helping
The way you're trying to do this is the hard way. There's a filetype plugin and a Python syntax type and it already knows what to do.
filetype plugin indent on
And don't use set autoindent. It's not very intelligent, it just copies the indent from the previous line. It's the opposite of what you're trying to do.
Files ending in .py should automatically get the right settings. If you need to force the current syntax type in a buffer, you can do that with
:set filetype=python
If you want to use tabs instead of spaces,
" Globally
set noexpandtab
" Python only
autocmd FileType python set noexpandtab
However, I'll note that using tabs in Python is not recommended and goes against published best practices (see PEP 8).
Lastly I'll mention that "plugin" is just a Vim term. All of this ships with Vim by default, this does not create a third-party dependency.

Auto-indent not working on Python's "with"

I am using VIM 7.4 on Ubuntu 16.04, and am coding for Python 3.5.
When writing a Python file (.py), the indentation works perfectly, except for the with statement. Namely, I could remap tab to indent by four spaces, VIM automatically indents by four spaces after a colon (:), and so on.
But when it comes to the with ... as syntax, it fails indenting a newline.
Visual example:
if x == 12:
then tab results on an indented newline, but
with open("test.txt", 'r') as file:
then tab resultes on a not indented newline.
I checked a lot of questions, that I won't link because they are too numerous, but here are some of the things I tried:
Adding set autoindent in my .vimrc;
Adding set smartindent in my .vimrc;
Typing filetype indent on in VIM's interpreter;
Typing :set indentkeys? and checking if the colon was in the list (it was).
It is nearly empty, so I doubt it will be useful, but here is my .vimrc:
set nocompatible
set autoindent
set smartindent
set tabstop=8 softtabstop=0 expandtab shiftwidth=4 smarttab
inoremap <S-Tab> <C-d>
How can I fix VIM so it recognizes with...as and indents after this on a newline?
The solution is indeed in the filetype indent on command.
For some reason, typing it in the VIM interpreter will not do anything. Therefore, one could think that this is not the way to fix this.
However, adding the following line to the .vimrc effectively fixed the problem:
filetype indent on

vim expandtab doesn't work after new installation

let mapleader = ","
set number
set textwidth=79 " lines longer than 79 columns will be broken
set shiftwidth=4 " operation >> indents 4 columns; << unindents 4 columns
set tabstop=4 " a hard TAB displays as 4 columns
set expandtab " insert spaces when hitting TABs
set softtabstop=4 " insert/delete 4 spaces when hitting a TAB/BACKSPACE
set shiftround " round indent to multiple of 'shiftwidth'
set cindent " align the new line indent with the previous line
set nobackup
set nowritebackup
set noswapfile
vnoremap < <gv " continue visual selecting after shiftwidh
vnoremap > >gv
nnoremap <C-h> <C-w>h
nnoremap <C-j> <C-w>j
nnoremap <C-k> <C-w>k
nnoremap <C-l> <C-w>l
nnoremap j gj
nnoremap k gk
nnoremap <Leader>r :w \| !clear && ./%<CR>
command W w !sudo tee % > /dev/null
noremap <silent><Leader>/ :nohls<CR>
set clipboard=unnamedplus
set paste
set ignorecase
Somehow after reinstallation of my arch linux, vim stoped work poperly.
After doing the same I did couple days ago with old system - now python complains about indentation.
I have no installed plugins or whatever, why does this broke?
P.S. already viewed same quiestions, but them was about plugins, which I doesn't have.
P.S. Noticed that after : vim won't start newline according cindent
Still indentation brokes after :set paste. Why this happens?
set paste "breaks" the indentation. That is all it does. That is the reason it works. Pasting text into Vim would normally be the same thing as just typing each letter. For example, open a file that has some text in it (in Vim), and make sure that Vim is in normal mode. Copy the following text: d4dAhowdy. Paste it into Vim. You will see that it deletes four lines (d4d), changes to insert mode at the end of the line (A), and types howdy. Pasting into Vim is the same thing as typing the letters; it does not necessarily just paste everything exactly how it comes. Let's say you type:
if this:
that
Once you hit Enter after if this:, Vim would indent the line, so that code would actually appear as:
if this:
that
Using set paste turns that off so that when you paste that code in (with the indentation included), Vim does not auto-indent and everything shows up normally. If you were to set nopaste and then paste the above unindented code, Vim would indent it for you.

vim: use selected line as input of a python function

I am quite newbie in vim.
What I want to achieve is that vim will return the output of a python function in my text file. The idea is that I select a part of text and press F5 and get the output. The complication is that this function is part of a library and I have to import it.
I tried this
command MyPythonFunction execute "!python from Bio.Seq import reverse_complement; reverse_complement(%)"
map <F5> :MyPythonFunction<CR>
and I get "no range allowed"
Selected lines are passed to stdin of the command. So read it using sys.stdin.read()
fun! ReverseComplement()
exec ":'<,'>! python -c \"import sys, Bio.Seq; print Bio.Seq.reverse_complement(sys.stdin.read().rstrip())\""
endfun
vnoremap <F5> :call ReverseComplement()<CR>
EDIT
pass a part of a line:
vnoremap <F5> d:let #a=system('python -c "import sys, Bio.Seq; sys.stdout.write(Bio.Seq.reverse_complement(\"' . #" . '\"))"')<CR>"aP
d -> delete selected part. side effect: content of register " changed.
#": content of register " (cut contents)
.: binary operator that concatenate strings.
let #a = system(..): Execute external command, and save its output to a register.
"aP: Paste content of a register before current cursor position.
First of all, you are going to need** write your python parts in such a manner that the data is read from stdin and then output to stdout. You can then apply your code in following style:
fun! DoMyPythonThing() range
exec ":'<,'>! python ./path/to/your/script.py"
endfun
vnoremap <F3> :call DoMyPythonThing()<CR>
The idea behind ex's command :! is that you give it an executable program, and vim pipes the visualized text to it and replaces the region with the ouput of the program.
Note the range there in the function definition. Note about the mapping that we restrict ourselves in visual mode mappings only. If you like to wave the mouse as well, consider mapping in selection mode as well.
**) Well, it's possible to write in-vim python to perform this, but that's harder to test and you went with the external-program route by calling ! anyway.

Categories

Resources