Related
I want to be able to control vim/neovim on a per-key basis with python scripting. There is a function called feedkeys in the python vim module (vim.feedkeys) that is nearly what I want. However, I haven't been able to figure out how to send things like function keys, arrow keys, pgup, pgdown etc as it always takes my strings completely literally.
As per the documentation for vim's feedkeys (vimscript version, not python)
feedkeys("\<CR>") simulates pressing of the <Enter> key. But feedkeys('\<CR>') pushes 5 characters.
Things I've tried with the python counterpart that haven't worked (note, <CR> is just an example; I know I can use \n for that. Nonetheless, this should simulate an enter keypress):
vim.feedkeys("\<CR>")
vim.feedkeys("<CR>")
vim.feedkeys("\<CR\>")
vim.call("feedkeys", "\<CR>")
vim.call("feedkeys", '"\<CR>"')
All of these were interpreted literally. I want to do something like
vim.feedkeys("\<F5>") etc. Any ideas?
This isn't ideal, but it solves my issue well enough:
vim.command('call feedkeys("\<F5>")')
In case this is useful to anyone, I've written a general function that will handle the \<> escapes as well as double-quotes:
def fkeys(text):
firstsub = True
for sub in text.split('"'):
if firstsub:
firstsub = False
else:
vim.feedkeys('"')
vim.command(f'call feedkeys("{sub}")')
Sorry for being Captain Obvious, but it doesn't work, because Python is not VimScript.
See :h nvim_replace_termcodes() and :h nvim_feedkeys() for a complete example. In case of <CR>, simply byte value of 13 will do.
You don't, because the interpretation of something like "\<CR>" is a function of VimL string literals. In other words, feedkeys("\<CR>") is the same thing as (probably) feedkeys("\x0d") — the function doesn't see the difference, the interpretation happens at a source code level. Naturally, Python doesn't have the same feature in the same way.
If you don't want to figure out what the escape sequence is for F5 and code it into your Python script, perhaps you could use vim.eval() to eval a VimL expression, e.g. vim.eval(r'feedkeys("\<F5>")').
Am I correct in thinking that that Python doesn't have a direct equivalent for Perl's __END__?
print "Perl...\n";
__END__
End of code. I can put anything I want here.
One thought that occurred to me was to use a triple-quoted string. Is there a better way to achieve this in Python?
print "Python..."
"""
End of code. I can put anything I want here.
"""
The __END__ block in perl dates from a time when programmers had to work with data from the outside world and liked to keep examples of it in the program itself.
Hard to imagine I know.
It was useful for example if you had a moving target like a hardware log file with mutating messages due to firmware updates where you wanted to compare old and new versions of the line or keep notes not strictly related to the programs operations ("Code seems slow on day x of month every month") or as mentioned above a reference set of data to run the program against. Telcos are an example of an industry where this was a frequent requirement.
Lastly Python's cult like restrictiveness seems to have a real and tiresome effect on the mindset of its advocates, if your only response to a question is "Why would you want to that when you could do X?" when X is not as useful please keep quiet++.
The triple-quote form you suggested will still create a python string, whereas Perl's parser simply ignores anything after __END__. You can't write:
"""
I can put anything in here...
Anything!
"""
import os
os.system("rm -rf /")
Comments are more suitable in my opinion.
#__END__
#Whatever I write here will be ignored
#Woohoo !
What you're asking for does not exist.
Proof: http://www.mail-archive.com/python-list#python.org/msg156396.html
A simple solution is to escape any " as \" and do a normal multi line string -- see official docs: http://docs.python.org/tutorial/introduction.html#strings
( Also, atexit doesn't work: http://www.mail-archive.com/python-list#python.org/msg156364.html )
Hm, what about sys.exit(0) ? (assuming you do import sys above it, of course)
As to why it would useful, sometimes I sit down to do a substantial rewrite of something and want to mark my "good up to this point" place.
By using sys.exit(0) in a temporary manner, I know nothing below that point will get executed, therefore if there's a problem (e.g., server error) I know it had to be above that point.
I like it slightly better than commenting out the rest of the file, just because there are more chances to make a mistake and uncomment something (stray key press at beginning of line), and also because it seems better to insert 1 line (which will later be removed), than to modify X-many lines which will then have to be un-modified later.
But yeah, this is splitting hairs; commenting works great too... assuming your editor supports easily commenting out a region, of course; if not, sys.exit(0) all the way!
I use __END__ all the time for multiples of the reasons given. I've been doing it for so long now that I put it (usually preceded by an exit('0');), along with BEGIN {} / END{} routines, in by force-of-habit. It is a shame that Python doesn't have an equivalent, but I just comment-out the lines at the bottom: extraneous, but that's about what you get with one way to rule them all languages.
Python does not have a direct equivalent to this.
Why do you want it? It doesn't sound like a really great thing to have when there are more consistent ways like putting the text at the end as comments (that's how we include arbitrary text in Python source files. Triple quoted strings are for making multi-line strings, not for non-code-related text.)
Your editor should be able to make using many lines of comments easy for you.
Does anybody know of a method, or perhaps a plugin, that will
automatically fold long docstrings in Python? I have docstrings in my
code that span several pages, so it is troublesome to keep paging
through them. The other tricky part is that there is embedded python
testing code in the docstrings, so that might make parsing them
difficult. Note that I only need to automatically fold the entire
docstring, regardless of what is in it.
This is a bit of a dirty hack, but you can go through the python syntax file (:sp $VIMRUNTIME/syntax/python.vim) and find all the syntax regions for triple-quoted strings (search for ''' and """) and add the fold keyword to the end of those statements. Then just set foldmethod=syntax for python files and the comments should be folded.
I'm not sure about a plugin or automation, but if you type zf/ you can then search for something and it will fold up to the next instance of it. So in a document like the following (where [] is the cursor):
def foo():
"""[]
Some long docstring
that takes up many
lines
"""
pass
Look at edit2 first for the updated search string!
If you use the command zf/"""[ENTER], it should fold everything from the current line (the beginning of the docstring) to the next occurrence of """ which should be the end of the docstring.
I know this isn't automation, but perhaps it will help in the interim, or lead you down the right path to automating it. See edit2 for a better search function, although I still don't know how to automate.
Hope this helps.
Edit: in a corollary, you can search for any docstring with /"""\_.\{-}""", although this will also return the code within the docstring. To search for a function definition followed by a docstring, you can use /def\_.\{-}"""\_.\{-}""", although this breaks on a def inside the docstring.
Edit2: Actually, some more playing with regexs led me to this: /def.\{-}):\_s*"""\_.\{-}""" which should find any function followed by a docstring. It searches for def followed by any characters, then ): followed by a newline and/or whitespace followed by """ followed by any number of lines than the next """, but always ensures the 2nd triple quote is the one immediately following the first.
In your .vimrc add:
" folding
set foldmethod=indent
This will auto-fold at every indentation, which, in python, translates to docstrings. It works VERY VERY nice. Give it a try. The above answer is correct, but requires a bunch of keystrokes (blah!)
I think I've found a slight improvement to the answer of #too_much_php by trying to figure out how to do the same thing without root access. Copying the syntax region definitions from $VIMRUNTIME/syntax/python.vim to ~/.vim/after/syntax/python.vim and editing them solved the problem for me. Here's my code for ~/.vim/after/syntax/python.vim:
syn region docString1
\ start=+[uU]\=\z('''\|"""\)+ end="\z1" keepend transparent fold
syn region docString2
\ start=+[uU]\=[rR]\z('''\|"""\)+ end="\z1" keepend transparent fold
Now I can run :set foldmethod=syntax to fold docstrings.
PS: Credits to #too_much_php for the initial idea
You can do this with :set foldmethod=marker foldmarker=""",""", I think. I haven't tested it, but that should do the trick. The arguments to foldmarker are start and end markers.
I wrote a vimscript plugin many years ago to do exactly this, but never got around to publishing it. I've put it up as a gist, but have also pasted the source below. I've also replicated its functionality for Sublime Text here.
"
" Fold multi-line Python comments into one line.
"
" Also maps the "-" key to toggle expansion and <C-f> to toggle all folding.
"
setlocal foldmethod=syntax
setlocal foldtext=FoldText()
setlocal fillchars=
map <buffer> - za
map <buffer> <C-f> :call ToggleFold()<CR>
let b:folded = 1
hi Folded gui=bold cterm=bold guifg=cyan ctermfg=cyan guibg=NONE ctermbg=NONE
function! ToggleFold()
if b:folded == 0
exec "normal! zM"
let b:folded = 1
else
exec "normal! zR"
let b:folded = 0
endif
endfunction
function! s:Strip(string)
return substitute(a:string, '^[[:space:][:return:][:cntrl:]]\+\|[[:space:][:return:][:cntrl:]]\+$', '', '')
endfunction
" Extract the first line of a multi-line comment to use as the fold snippet
function! FoldText()
let l:snippet = getline(v:foldstart)
if len(s:Strip(l:snippet)) == 3
let l:snippet = strpart(l:snippet, 1) . s:Strip(getline(v:foldstart + 1))
endif
return '+' . l:snippet . ' ...'
endfunction
My solution involves using SimpylFold. After installing it using Vundle, I put this in my vimrc file:
autocmd FileType python setlocal foldlevel=2
Which makes all docstrings folded by default when you open a python file, which is super awesome.
This question already has answers here:
Why doesn't Python have multiline comments?
(18 answers)
Closed 9 years ago.
Is there a mechanism to comment out large blocks of Python code?
Right now, the only ways I can see of commenting out code are to either start every line with a #, or to enclose the code in triple quotes: """.
The problem with these is that inserting # before every line is cumbersome and """ makes the string I want to use as a comment show up in generated documentation.
After reading all comments, the answer seems to be "No".
Python does not have such a mechanism. Prepend a # to each line to block comment. For more information see PEP 8. Most Python IDEs support a mechanism to do the block-commenting-with-hash-signs automatically for you. For example, in IDLE on my machine, it's Alt+3 and Alt+4.
Don't use triple-quotes; as you discovered, this is for documentation strings not block comments, although it has a similar effect. If you're just commenting things out temporarily, this is fine as a temporary measure.
Hide the triple quotes in a context that won't be mistaken for a docstring, eg:
'''
...statements...
''' and None
or:
if False: '''
...statements...
'''
The only cure I know for this is a good editor. Sorry.
The only way you can do this without triple quotes is to add an:
if False:
And then indent all your code. Note that the code will still need to have proper syntax.
Many Python IDEs can add # for you on each selected line, and remove them when un-commenting too. Likewise, if you use vi or Emacs you can create a macro to do this for you for a block of code.
In JetBrains PyCharm on Mac use Command + / to comment/uncomment selected block of code. On Windows, use CTRL + /.
M-x comment-region, in Emacs' Python mode.
At least in VIM you can select the first column of text you want to insert using Block Visual mode (CTRL+V in non-windows VIMs) and then prepend a # before each line using this sequence:
I#<esc>
In Block Visual mode I moves to insert mode with the cursor before the block on its first line. The inserted text is copied before each line in the block.
In vi:
Go to top of block and mark it with letter a.
Go to bottom of block and mark it with letter b
Then do
:'a,'b s!^!#!
comm='''
Junk, or working code
that I need to comment.
'''
You can replace comm by a variable of your choice that is perhaps shorter, easy to touch-type, and you know does not (and will not) occur in your programs. Examples: xxx, oo, null, nil.
In Visual Studio using the Python Tools for Visual Studio, blocks can be commented out by Ctrl+K, Ctrl+C and uncommented by Ctrl+K, Ctrl+U.
I use Notepad++ on a Windows machine, select your code, type CTRL-K. To uncomment you select code and press Ctrl + Shift + K.
Incidentally, Notepad++ works nicely as a Python editor. With auto-completion, code folding, syntax highlighting, and much more. And it's free as in speech and as in beer!
In Eclipse + PyDev, Python block commenting is similar to Eclipse Java block commenting; select the lines you want to comment and use Ctrl + / to comment. To uncomment a commented block, do the same thing.
Yes, there is (depending on your editor). In PyDev (and in Aptana Studio with PyDev):
Ctrl + 4 - comment selected block
Ctrl + 5 - uncomment selected block
The only mechanism to comment out Python code (understood as code ignored by the interpreter) is the #.
As you say, you can also use string literals, that are not ignored by the interpreter, but can be completely irrelevant for the program execution.
In Eclipse using PyDev, you can select a code block and press Ctrl + #.
Triple quotes are OK to me.
You can use ''' foo ''' for docstrings and """ bar """ for comments or vice-versa to make the code more readable.
Another editor-based solution: text "rectangles" in Emacs.
Highlight the code you want to comment out, then C-x-r-t #
To un-comment the code: highlight, then C-x-r-k
I use this all-day, every day. (Assigned to hot-keys, of course.)
This and powerful regex search/replace is the reason I tolerate Emacs's other "eccentricities".
On Eric4 there is an easy way: select a block, type Ctrl+M to comment the whole block or Ctrl+alt+M to uncomment.
Use a nice editor like SciTe, select your code, press Ctrl + Q and done.
If you don't have an editor that supports block comments you can use a triple quoted string at the start and the end of your code block to 'effectively' comment it out. It is not the best practice though.
I am a totally blind programmer who would like to learn Python. Unfortunately the fact that code blocks are represented with different levels of indentation is a major stumbling block. I was wondering if there were any tools available that would allow me to write code using braces or some other code block delimiter and then convert that format into a properly indented representation that the Python interpreter could use?
There's a solution to your problem that is distributed with python itself. pindent.py, it's located in the Tools\Scripts directory in a windows install (my path to it is C:\Python25\Tools\Scripts), it looks like you'd have to grab it from svn.python.org if you are running on Linux or OSX.
It adds comments when blocks are closed, or can properly indent code if comments are put in. Here's an example of the code outputted by pindent with the command:
pindent.py -c myfile.py
def foobar(a, b):
if a == b:
a = a+1
elif a < b:
b = b-1
if b > a: a = a-1
# end if
else:
print 'oops!'
# end if
# end def foobar
Where the original myfile.py was:
def foobar(a, b):
if a == b:
a = a+1
elif a < b:
b = b-1
if b > a: a = a-1
else:
print 'oops!'
You can also use pindent.py -r to insert the correct indentation based on comments (read the header of pindent.py for details), this should allow you to code in python without worrying about indentation.
For example, running pindent.py -r myfile.py will convert the following code in myfile.py into the same properly indented (and also commented) code as produced by the pindent.py -c example above:
def foobar(a, b):
if a == b:
a = a+1
elif a < b:
b = b-1
if b > a: a = a-1
# end if
else:
print 'oops!'
# end if
# end def foobar
I'd be interested to learn what solution you end up using, if you require any further assistance, please comment on this post and I'll try to help.
I personally doubt that there currently is at the moment, as a lot of the Python afficionados love the fact that Python is this way, whitespace delimited.
I've never actually thought about that as an accessibility issue however. Maybe it's something to put forward as a bug report to Python?
I'd assume that you use a screen reader here however for the output? So the tabs would seem "invisible" to you? With a Braille output, it might be easier to read, but I can understand exactly how confusing this could be.
In fact, this is very interesting to me. I wish that I knew enough to be able to write an app that will do this for you.
I think it's definately something that I'll put in a bug report for, unless you've already done so yourself, or want to.
Edit: Also, as noted by John Millikin There is also PyBraces Which might be a viable solution to you, and may be possible to be hacked together dependant on your coding skills to be exactly what you need (and I hope that if that's the case, you release it out for others like yourself to use)
Edit 2: I've just reported this to the python bug tracker
Although I am not blind, I have heard good things about Emacspeak. They've had a Python mode since their 8.0 release in 1998 (they seem to be up to release 28.0!). Definitely worth checking out.
You should be able to configure your editor to speak the tabs and spaces -- I know it's possible to display whitespace in most editors, so there must be an accessibility option somewhere to speak them.
Failing that, there is pybraces, which was written as a practical joke but might actually be useful to you with a bit of work.
If you're on Windows, I strongly recommend you take a look at EdSharp from:
http://empowermentzone.com/EdSharp.htm
It supports all of the leading Windows screenreaders, it can be configured to speak the indentation levels of code, or it has a built in utility called PyBrace that can convert to and from braces syntax if you want to do that instead, and it supports all kinds of other features programmers have come to expect in our text editors. I've been using it for years, for everything from PHP to JavaScript to HTML to Python, and I love it.
All of these "no you can't" types of answers are really annoying. Of course you can.
It's a hack, but you can do it.
http://timhatch.com/projects/pybraces/
uses a custom encoding to convert braces to indented blocks before handing it off to the interpreter.
As an aside, and as someone new to python - I don't accept the reasoning behind not even allowing braces/generic block delimiters ... apart from that being the preference of the python devs. Braces at least won't get eaten accidentally if you're doing some automatic processing of your code or working in an editor that doesn't understand that white space is important. If you're generating code automatically, it's handy to not have to keep track of indent levels. If you want to use python to do a perl-esque one-liner, you're automatically crippled. If nothing else, just as a safeguard. What if your 1000 line python program gets all of its tabs eaten? You're going to go line-by-line and figure out where the indenting should be?
Asking about it will invariably get a tongue-in-cheek response like "just do 'from __ future __ import braces'", "configure your IDE correctly", "it's better anyway so get used to it" ...
I see their point, but hey, if i wanted to, i could put a semicolon after every single line. So I don't understand why everyone is so adamant about the braces thing. If you need your language to force you to indent properly, you're not doing it right in the first place.
Just my 2c - I'm going to use braces anyway.
I appreciate your problem, but think you are specifying the implementation instead of the problem you need solved. Instead of converting to braces, how about working on a way for your screen reader to tell you the indentation level?
For example, some people have worked on vim syntax coloring to represent python indentation levels. Perhaps a modified syntax coloring could produce something your screen reader would read?
Searching an accessible Python IDE, found this and decided to answer.
Under Windows with JAWS:
Go to Settings Center by pressing JawsKey+6 (on the number row above the letters) in your favorite text editor. If JAWS prompts to create a new configuration file, agree.
In the search field, type "indent"
There will be only one result: "Say indent characters". Turn this on.
Enjoy!
The only thing that is frustrating for us is that we can't enjoy code examples on websites (since indent speaking in browsers is not too comfortable — it generates superfluous speech).
Happy coding from another Python beginner).
I use eclipse with the pydev extensions since it's an IDE I have a lot of experience with. I also appreciate the smart indentation it offers for coding if statements, loops, etc. I have configured the pindent.py script as an external tool that I can run on the currently focused python module which makes my life easier so I can see what is closed where with out having to constantly check indentation.
There are various answers explaining how to do this. But I would recommend not taking this route. While you could use a script to do the conversion, it would make it hard to work on a team project.
My recommendation would be to configure your screen reader to announce the tabs. This isn't as annoying as it sounds, since it would only say "indent 5" rather than "tab tab tab tab tab". Furthermore, the indentation would only be read whenever it changed, so you could go through an entire block of code without hearing the indentation level. In this way hearing the indentation is no more verbose than hearing the braces.
As I don't know which operating system or screen reader you use I unfortunately can't give the exact steps for achieving this.
Edsger Dijkstra used if ~ fi and do ~ od in his "Guarded Command Language", these appear to originate from the Algol68. There were also some example python guarded blocks used in RosettaCode.org.
fi = od = yrt = end = lambda object: None;
class MyClass(object):
def myfunction(self, arg1, arg2):
for i in range(arg1) :# do
if i > 5 :# then
print i
fi
od # or end(i) #
end(myfunction)
end(MyClass)
Whitespace mangled python code can be unambiguously unmangled and reindented if one uses
guarded blocks if/fi, do/od & try/yrt together with semicolons ";" to separate statements. Excellent for unambiguous magazine listings or cut/pasting from web pages.
It should be easy enough to write a short python program to insert/remove the guard blocks and semicolons.