Permalink
Browse files

add actions to wrap current word or selected text into specified open…

…/close characters (like: (){}[]<>"). add one indent level in case of multiline selection
  • Loading branch information...
1 parent 8589333 commit bd26af97b672e9ec184598a9b52c7bac83ba13cb @zaufi committed Jan 23, 2013
Showing with 170 additions and 76 deletions.
  1. +98 −7 block.py
  2. +26 −43 commentar.py
  3. +15 −16 expand/expand.py
  4. +5 −3 expand/text_x-c++src.expand
  5. +4 −4 format.py
  6. +21 −2 libkatepate/common.py
  7. +1 −1 libkatepate/decorators.py
View
@@ -33,6 +33,21 @@
# remove text from cursor position to the start of the current line
# but keep leading spaces (to avoid breaking indentation)
#
+# Wrap into Braces (Ctrl+'(')
+# wrap current word (identifier) or selection into pair of '(' and ')' characters
+#
+# Wrap into Brackets (Ctrl+{')
+# wrap current word (identifier) or selection into pair of '[' and ']' characters
+#
+# Wrap into Curve Brackets (Meta+{')
+# wrap current word (identifier) or selection into pair of '{' and '}' characters
+#
+# Wrap into Angle Brackets (Ctrl+<')
+# wrap current word (identifier) or selection into pair of '<' and '>' characters
+#
+# Wrap into Quotes (Ctrl+')
+# wrap current word (identifier) or selection into pair of '"' characters
+#
import kate
import kate.gui
@@ -43,6 +58,7 @@
@kate.action('Insert Char From Line Above', shortcut='Meta+E')
def insertCharFromLineAbove():
+ '''add the same char to the current cursor position as in the line above'''
doc = kate.activeDocument()
view = kate.activeView()
pos = view.cursorPosition()
@@ -62,6 +78,7 @@ def insertCharFromLineAbove():
@kate.action('Insert Char From Line Below', shortcut='Meta+W')
def insertCharFromLineBelow():
+ '''add the same char to the current cursor position as in the line below'''
doc = kate.activeDocument()
view = kate.activeView()
pos = view.cursorPosition()
@@ -81,6 +98,7 @@ def insertCharFromLineBelow():
@kate.action('Kill Text After Cursor', shortcut='Meta+K')
def killRestOfLine():
+ '''remove text from cursor position to the end of the current line'''
doc = kate.activeDocument()
view = kate.activeView()
pos = view.cursorPosition()
@@ -98,6 +116,7 @@ def killLeadOfLine():
''' Remove text from a start of a line to the current crsor position
NOTE This function suppose spaces as indentation character!
+ TODO Get indent character from config
'''
doc = kate.activeDocument()
view = kate.activeView()
@@ -113,12 +132,84 @@ def killLeadOfLine():
doc.endEditing()
-@kate.action('Test', shortcut='Meta+O', menu='View')
-def test():
+def _wrapRange(rangeToWrap, openCh, closeCh, doc = None):
+ if not doc:
+ doc = kate.activeDocument()
+
+ doc.startEditing() # Start atomic UnDo operation
+ doc.replaceText(rangeToWrap, openCh + doc.text(rangeToWrap) + closeCh)
+ doc.endEditing() # Done editing
+
+
+def _wrapBlockWithChar(openCh, closeCh, indentMultiline = True):
+ '''Wrap next word or selection (if any) into given open and close chars
+
+ If current selection is multiline, add one indentation level and put
+ open/close chars on separate lines
+ '''
doc = kate.activeDocument()
view = kate.activeView()
- ui.popup(
- text="Current document MIME type: <b>" + doc.mimeType() + "</b><br/>hl: <b>" + doc.highlightingMode() + "</b>"
- , caption="Some document info: file type"
- , iconName="face-wink"
- )
+ pos = view.cursorPosition()
+
+ # Try to extend selection to be started from 0 columns at both ends
+ common.extendSelectionToWholeLine(view)
+
+ selectedRange = view.selectionRange()
+ if selectedRange.isEmpty():
+ # No text selected. Ok, lets wrap a word where cursor positioned
+ wordRange = common.getBoundTextRangeSL(
+ common.CXX_IDENTIFIER_BOUNDARIES
+ , common.CXX_IDENTIFIER_BOUNDARIES
+ , pos
+ , doc
+ )
+ _wrapRange(wordRange, openCh, closeCh, doc)
+ else:
+ if selectedRange.start().line() == selectedRange.end().line() or indentMultiline == False:
+ # single line selection (or no special indentation required)
+ _wrapRange(selectedRange, openCh, closeCh, doc)
+
+ # extend current selection
+ selectedRange.end().setColumn(selectedRange.end().column() + len(openCh) + len(closeCh))
+ view.setSelection(selectedRange)
+ else:
+ # multiline selection
+ # 0) extend selection to capture whole lines
+ gap = ' ' * common.getLineIndentation(selectedRange.start().line(), doc)
+ text = gap + openCh + '\n' \
+ + '\n'.join([' ' * 4 + line for line in doc.text(selectedRange).split('\n')[:-1]]) \
+ + '\n' + gap + closeCh + '\n'
+ doc.startEditing()
+ doc.replaceText(selectedRange, text)
+ doc.endEditing()
+
+ # extend current selection
+ selectedRange.end().setColumn(selectedRange.end().column() + len(openCh) + len(closeCh))
+ r = KTextEditor.Range(selectedRange.start().line(), 0, selectedRange.end().line() + 2, 0)
+ view.setSelection(r)
+
+
+@kate.action('Wrap into Braces', shortcut='Ctrl+(')
+def wrapBlockWithBraces():
+ '''wrap current word (identifier) or selection into pair of '(' and ')' characters'''
+ _wrapBlockWithChar('(', ')')
+
+@kate.action('Wrap into Brackets', shortcut='Ctrl+{')
+def wrapBlockWithBraces():
+ '''wrap current word (identifier) or selection into pair of '[' and ']' characters'''
+ _wrapBlockWithChar('[', ']')
+
+@kate.action('Wrap into Curve Brackets', shortcut='Meta+{')
+def wrapBlockWithBraces():
+ '''wrap current word (identifier) or selection into pair of '{' and '}' characters'''
+ _wrapBlockWithChar('{', '}')
+
+@kate.action('Wrap into Angle Brackets', shortcut='Ctrl+<')
+def wrapBlockWithBraces():
+ '''wrap current word (identifier) or selection into pair of '<' and '>' characters'''
+ _wrapBlockWithChar('<', '>')
+
+@kate.action('Wrap into Quotes', shortcut='Ctrl+\'')
+def wrapBlockWithBraces():
+ '''wrap current word (identifier) or selection into pair of '"' characters'''
+ _wrapBlockWithChar('"', '"', False)
View
@@ -70,20 +70,14 @@
from PyKDE4.ktexteditor import KTextEditor
from libkatepate.decorators import *
-from libkatepate.common import getCommentStyleForDoc, getTextBlockAroundCursor, getCurrentLineIndentation
-from libkatepate import ui, selection
+from libkatepate import common, ui, selection
# text processing predicates
from libkatepate import pred
from libkatepate.pred import neg, all_of, any_of
-if 'commentar:comment-position' not in kate.configuration:
- kate.configuration['commentar:comment-position'] = int(60)
-if 'commentar:comment-threashold' not in kate.configuration:
- kate.configuration['commentar:comment-threashold'] = int(50)
-
-COMMENT_POS = kate.configuration['commentar:comment-position']
-COMMENT_THRESHOLD = kate.configuration['commentar:comment-threashold']
+COMMENT_POS = 60
+COMMENT_THRESHOLD = 50
BLOCK_ANY_START_SEARCH_RE = re.compile('^\s*#\s*if.*$')
BLOCK_START_SEARCH_RE = re.compile('^\s*#\s*if\s*([01])$')
BLOCK_ELSE_SEARCH_RE = re.compile('^\s*#\s*else.*$')
@@ -96,16 +90,6 @@ def isApplicableMime():
return str(kate.activeDocument().mimeType()).find('c++') != -1
-def extendSelectionToWholeLine(view):
- selectedRange = view.selectionRange()
- if not selectedRange.isEmpty():
- # ... extend selection to whole line, before do smth
- selectedRange.start().setColumn(0)
- if selectedRange.end().column() != 0:
- selectedRange.end().setColumn(0)
- selectedRange.end().setLine(selectedRange.end().line() + 1)
- view.setSelection(selectedRange)
-
#
# Build a list of tuples (start, end, elseif, is_comment) for all #if/#elseif/#endif blocks
# in a document. If block contains #endif 3rd element will point its line, -1 otherwise.
@@ -145,14 +129,14 @@ def buildIfEndifMap(document):
def locateBlock(currentLine, blockRanges, ignoreComments = False):
- """Find an index of a current block
+ '''Find an index of a current block
Return index into blockRanges of the block pointer by current cursor position
or -1 if nothing found.
TODO Rename to better name?
TODO Is there any better way to implement a code similar to std::find_if in C++?
- """
+ '''
# Locate a block where cursor currently positioned
idx = -1
c = 0
@@ -231,18 +215,18 @@ def processLine(line, commentCh):
@comment_char_must_be_known()
@selection_mode(selection.NORMAL)
def commentar():
- """Append or align an inlined comment to COMMENT_POS for the current line or the selection.
+ '''Append or align an inlined comment to COMMENT_POS for the current line or the selection.
Move cursor to the start of a comment, if nothing has changed.
- """
+ '''
document = kate.activeDocument()
view = kate.activeView()
pos = view.cursorPosition()
- commentCh = getCommentStyleForDoc(document)
+ commentCh = common.getCommentStyleForDoc(document)
if view.selection():
# If selected smth on a single line...
- extendSelectionToWholeLine(view)
+ common.extendSelectionToWholeLine(view)
selectedText = view.selectionText().split('\n')
if not bool(selectedText[-1]):
@@ -288,12 +272,12 @@ def commentar():
@check_constraints
@comment_char_must_be_known()
def moveAbove():
- """Move inlined comment before the current line at same align
- """
+ '''Move inlined comment before the current line at same align
+ '''
document = kate.activeDocument()
view = kate.activeView()
pos = view.cursorPosition()
- commentCh = getCommentStyleForDoc(document)
+ commentCh = common.getCommentStyleForDoc(document)
insertionText = list()
line = document.line(pos.line())
@@ -346,7 +330,7 @@ def moveInline():
document = kate.activeDocument()
view = kate.activeView()
pos = view.cursorPosition()
- commentCh = getCommentStyleForDoc(document)
+ commentCh = common.getCommentStyleForDoc(document)
insertionText = []
currentLine = document.line(pos.line())
@@ -413,12 +397,12 @@ def moveInline():
@kate.action('Comment Block w/ `#if0`', shortcut='Meta+D', menu='Edit')
@check_constraints
-@restrict_doc_type('C++', 'C')
+@restrict_doc_type('C++', 'C++11', 'C++11/Qt4', 'C')
def commentBlock():
view = kate.activeView()
# This operation have no sense for partly selected lines
- extendSelectionToWholeLine(view)
+ common.extendSelectionToWholeLine(view)
start = -1
end = -1
@@ -442,7 +426,7 @@ def commentBlock():
@kate.action('Toggle `#if0/#if1` Block', shortcut='Meta+Shift+D', menu='Edit')
@check_constraints
-@restrict_doc_type('C++', 'C')
+@restrict_doc_type('C++', 'C++11', 'C++11/Qt4', 'C')
def toggleBlock():
document = kate.activeDocument()
view = kate.activeView()
@@ -476,7 +460,7 @@ def toggleBlock():
@kate.action('Remove `#if0` Block', shortcut='Meta+R', menu='Edit')
@check_constraints
-@restrict_doc_type('C++', 'C')
+@restrict_doc_type('C++', 'C++11', 'C++11/Qt4', 'C')
def removeBlock():
document = kate.activeDocument()
view = kate.activeView()
@@ -504,7 +488,6 @@ def removeBlock():
else:
# No! So just remove whole block
r = KTextEditor.Range(blocksList[idx][0], 0, blocksList[idx][1] + 1, 0)
- print r
document.removeText(r)
else:
if blocksList[idx][2] != -1: # Is there `#else` part?
@@ -523,7 +506,7 @@ def removeBlock():
@kate.action('Select Current `#if0/#if1` Block', shortcut='Meta+S', menu='Edit')
@check_constraints
-@restrict_doc_type('C++', 'C')
+@restrict_doc_type('C++', 'C++11', 'C++11/Qt4', 'C')
def selectBlock():
document = kate.activeDocument()
view = kate.activeView()
@@ -551,7 +534,7 @@ def turnToBlockComment():
start = sr.start().line()
end = sr.end().line()
else:
- r = getTextBlockAroundCursor(
+ r = common.getTextBlockAroundCursor(
document
, pos
, [neg(any_of(pred.startsWith('///'), pred.startsWith('//!')))]
@@ -598,7 +581,7 @@ def turnFromBlockComment():
end = sr.end().line()
else:
# Try to detect block comment (/* ... */)
- r = getTextBlockAroundCursor(
+ r = common.getTextBlockAroundCursor(
document
, pos
, [pred.blockCommentStart, neg(pred.startsWith('*'))]
@@ -640,7 +623,7 @@ def turnFromBlockComment():
@kate.action('Transform Doxygen Comments', shortcut='Meta+X', menu='Edit')
@check_constraints
-@restrict_doc_type('C++', 'JavaScript')
+@restrict_doc_type('C++', 'C++11', 'C++11/Qt4', 'JavaScript')
@has_selection(False)
def toggleDoxyComment():
document = kate.activeDocument()
@@ -659,7 +642,7 @@ def toggleDoxyComment():
def getParagraphRange(doc, pos):
# Try to detect block comment (/* ... */)
- r = getTextBlockAroundCursor(
+ r = common.getTextBlockAroundCursor(
doc
, pos
, [pred.blockCommentStart, pred.equalTo('*'), neg(pred.startsWith('*'))]
@@ -668,7 +651,7 @@ def getParagraphRange(doc, pos):
isBlock = True
if r.isEmpty():
# Ok, maybe it's a single lines comment block?
- r = getTextBlockAroundCursor(
+ r = common.getTextBlockAroundCursor(
doc
, pos
, [neg(pred.onlySingleLineComment)]
@@ -688,7 +671,7 @@ def changeParagraphWidth(step):
ui.popup("Sorry", "can't detect commented paragraph at cursor...", "face-sad")
return # Dunno what to do on empty range!
- indent = getCurrentLineIndentation(view) # detect current align
+ indent = common.getCurrentLineIndentation(view) # detect current align
# Processing:
# 0) split text into left stripped lines
originalText = view.document().text(originRange)
@@ -740,14 +723,14 @@ def changeParagraphWidth(step):
@kate.action('Shrink Comment Paragraph', shortcut='Meta+[', menu='Edit')
@check_constraints
-@restrict_doc_type('C++', 'JavaScript')
+@restrict_doc_type('C++', 'C++11', 'C++11/Qt4', 'JavaScript')
def shrinkParagraph():
changeParagraphWidth(-1)
@kate.action('Extend Comment Paragraph', shortcut='Meta+]', menu='Edit')
@check_constraints
-@restrict_doc_type('C++', 'JavaScript')
+@restrict_doc_type('C++', 'C++11', 'C++11/Qt4', 'JavaScript')
def extendParagraph():
changeParagraphWidth(1)
Oops, something went wrong.

0 comments on commit bd26af9

Please sign in to comment.