Hi,
In my never ending quest for perfect programming text editor I've stumbled upon PN2. Initial impression has been quite good. Then the questions concerning v2.0.8.718 + PyPn 0.8.
1) Are BeginUndoAction and EndUndoAction broken or is there something wrong with my scripts because undo doesn't work in them?
2) Something's rotten in LineEndPosition too. To me it looks like it should be a function with a single int argument but it seems to be a property instead. On top of everything it doesn't seem to work either way. A bug or my incompetence?
3) Is there a way to get current scheme's comment marker from the script (e.g. a function that returns '#' for python, '//' for C/C++, etc.)? This would make my comment toggler much better.
Then the scripts. These will get rid of some of the worst nuisances PN2 had in store for me - lack of comment toggling and lack of a way to change indentation shortcuts (with jEdit I got used to ALT+LEFT and ALT+RIGHT - SHIFT+TAB is also very awkward combination to use).
###############################################################################
## Some helpers for Python programming.
## By: Tomi Lindberg
import pn
import scintilla
import string
from pypn.decorators import script
def expand_selection_to_lines():
"""
Expands selection to cover full lines.
Expands selection so that each line within selection is selected from
start to finish.
"""
editor = scintilla.Scintilla(pn.CurrentDoc())
l_start = editor.LineFromPosition(editor.SelectionStart)
l_end = editor.LineFromPosition(editor.SelectionEnd)
s_start = editor.PositionFromLine(l_start)
s_end = editor.PositionFromLine(l_end) + editor.LineLength(l_end) - 1
editor.SetSel(s_start, s_end)
def indentation(width):
"""
Indentation workhorse.
This function is called by both indent() and unindent() and it shifts
indentation by the amount given as an argument.
"""
editor = scintilla.Scintilla(pn.CurrentDoc())
expand_selection_to_lines()
l_start = editor.LineFromPosition(editor.SelectionStart)
l_end = editor.LineFromPosition(editor.SelectionEnd)
for i in range(l_start, l_end+1):
cur_indent = editor.GetLineIndentation(i)
editor.SetLineIndentation(i, cur_indent+width)
@script("Toggle comment", "Python")
def toggle_comment():
"""
Toggles the comments for selected lines.
If line(s) are currently commented out their comments are removed, and
vice versa. Toggling uses '#~' as a comment to separate it from the
regular '#' comments (ensuring that complete commented sections can be
toggled in and out with one selection).
"""
shift = 0
editor = scintilla.Scintilla(pn.CurrentDoc())
editor.BeginUndoAction()
expand_selection_to_lines()
s_start = editor.SelectionStart
s_end = editor.SelectionEnd
lines = editor.GetText(s_start, s_end).splitlines(1)
for i in range(len(lines)):
if lines[i].startswith("#~"):
lines[i] = lines[i][2:]
shift = -2
else:
lines[i] = "#~" + lines[i]
shift = 2
s_replace = string.join(lines, '')
editor.ReplaceSel(s_replace)
editor.SetSel(s_start, s_end + shift*len(lines))
editor.EndUndoAction()
@script ("Indent", "Python")
def indent():
"""Indents all selected lines by one tab width."""
editor = scintilla.Scintilla(pn.CurrentDoc())
editor.BeginUndoAction()
indentation(editor.TabWidth)
editor.EndUndoAction()
@script ("Unindent", "Python")
def unindent():
"""Unindents all selected lines by one tab width."""
editor = scintilla.Scintilla(pn.CurrentDoc())
editor.BeginUndoAction()
indentation(editor.TabWidth*-1)
editor.EndUndoAction()