PK V4=Ó•N select_between_quotes.py"""
Sublime Text - PowerUser Package
By: EJ12N
Plugin Code By: Sublimator
"""
import pprint, functools, re
import sublime
import sublimeplugin
################################### SETTINGS ###################################
SLOW_MOTION = 0
################################ STOP CONDITIONS ###############################
QUOTES = '["\']'
def direction_extent_index(d):
return (d -1) / 2
character_is_quote = ( lambda v, c:
re.match (
c.looking_for,
v.substr (
v.sel()[0].begin() +
direction_extent_index(c.direction) )
))
def update_context(v, c):
sel_set = v.sel()
cursor = sel_set[0].begin()
behind1 = v.substr(cursor + direction_extent_index(c.direction) -1)
behind2 = v.substr(cursor + direction_extent_index(c.direction) -2)
if behind1 == '\\' and behind2 != '\\':
return c, False
c.setdefault('stop_regions', []).append(sel_set[0])
# re_instate starting point
if c.direction == -1:
c['looking_for'] = v.substr(cursor -1)
sel_set.clear()
sel_set.add(c.start_sel)
return c, True
start_context = dict (
looking_for = QUOTES,
)
actions = (
# key # stop_condition # contexter
( "Character behind cursor is a quote",
character_is_quote,
update_context ),
)
#################################### HELPERS ###################################
class Context(dict):
"Sugar"
__setattr__ = dict.__setitem__
__getattr__ = lambda s, a: s[a]
def staggered(every=1):
"Slow mowifier"
def coRoutine(f):
@functools.wraps(f)
def run(*args):
routine = f(*args)
def next():
try: routine.next()
except StopIteration: return
sublime.setTimeout(next, every)
next()
return run
return coRoutine
############################# SELECT STRING COMMAND ############################
class SelectString(sublimeplugin.TextCommand):
def run(self, view, args):
if SLOW_MOTION:
return staggered(SLOW_MOTION)(self.select)(view, args)
else:
for yield_pt in self.select(view, args): pass
def select(self, view, args):
sel_set = view.sel()
start_points = list(sel_set)
finds = []
while start_points:
sel_set.clear()
sel_set.add(start_points.pop())
c = Context(start_context.copy())
c.start_sel = sel_set[0]
for direction in (-1, 1):
c.direction = direction
while True:
fails = {}
for key, expr, context_check in actions:
stop_cond = expr(view, c)
if stop_cond:
c, met_condition = context_check(view, c)
if met_condition:
fails[key] = stop_cond
if fails:
break
else:
yield view.runCommand('move characters %s' % direction)
pos = sel_set[0].begin()
if pos == 0 or pos == view.size():
break
region = c.stop_regions[0]
for reg in c.stop_regions[1:]:
region = region.cover(reg)
finds.append(region)
map(sel_set.add, finds)
################################################################################PK V4=Ó|Í>\ \ PowerUser.py"""
Sublime Text - PowerUser Package
By: EJ12N
"""
#stuff for plugins :)
import sublime, sublimeplugin
import string, textwrap, re
import webbrowser
import __builtin__, sys, os, calendar, random, time, cgi, urllib
from htmlentitydefs import name2codepoint as n2cp
from datetime import datetime
"""
Long awaited online help for PHP/XHTML/CSS :)
default binding: shift+f1
If word is selected it'll use selection else it'll use word under cursor
"""
class getOnlineHelp(sublimeplugin.TextCommand):
def run(self, view, args):
word_under_cursor = view.substr(view.word(view.sel()[0].begin()))
view_scope = view.syntaxName(view.sel()[0].begin()).strip()
#seleted text
for region in view.sel():
if not region.empty():
# line = view.line(region)
s = view.substr(region)
for match in re.finditer(r"(?sim)(source\.php)|(text\.html)|(source\.css)", view_scope):
if match.group(0) == 'source.php':
# sublime.messageBox('php!')
webbrowser.open_new_tab('http://www.php.net/' + s)
break
elif match.group(0) == 'text.html':
# sublime.messageBox('html!')
webbrowser.open_new_tab('http://reference.sitepoint.com/html/' + s)
elif match.group(0) == 'source.css':
# sublime.messageBox('css!')
webbrowser.open_new_tab('http://reference.sitepoint.com/css/' + s)
# no text selected? use word under cursor
else:
# sublime.messageBox('no selection')
for match in re.finditer(r"(?sim)(source\.php)|(text\.html)|(source\.css)", view_scope):
if match.group(0) == 'source.php':
# sublime.messageBox('php!')
webbrowser.open_new_tab('http://www.php.net/' + word_under_cursor)
break
elif match.group(0) == 'text.html':
# sublime.messageBox('html!')
webbrowser.open_new_tab('http://reference.sitepoint.com/html/' + word_under_cursor)
elif match.group(0) == 'source.css':
# sublime.messageBox('css!')
webbrowser.open_new_tab('http://reference.sitepoint.com/css/' + word_under_cursor)
""" #delete this line to use project panel command
#FEEL FREE TO USE THIS IF YOU'D LIKE.
#ALL IT DOES IS OPEN A PROJECT PANEL (on the left) whenever you open/refresh a project
class showProjectPanel(sublimeplugin.TextCommand):
def run(self, view, args):
window = view.window()
project = window.project().fileName()
if (project != ''):
# window.runCommand('openBrowseableProject', [project.replace('\\','/')])
self.onProjectLoad(window)
else:
window.runCommand('openProject')
# This takes care of showing the projects panel whenever
# you open/reload a project.
def onProjectLoad(self, window):
project = window.project().fileName()
window.runCommand('openBrowseableProject', [project.replace('\\','/')])
def onProjectClose(self, window):
window.runCommand('closeBrowseableProject')
class hideProjectPanel(sublimeplugin.TextCommand):
def run(self, view, args):
window = view.window()
window.runCommand('closeBrowseableProject')
""" #delete this line to use project panel command
"""
Allows me to select tabs by numbers :)
Order: leftmost to rightmost
Todo: number tabs with aliases or something.
"""
class selectView(sublimeplugin.TextCommand):
views = {}
def run(self, view, args):
for index, window_view in enumerate(view.window().views()):
self.views[index+1] = window_view
view.window().focusView(self.views[int(args[0])])
"""
Save current buffer (tab) and exits sublime but preserves the session :)
"""
class saveAndExit(sublimeplugin.TextCommand):
def run(self, view, args):
window = view.window();
window.runCommand('save')
window.runCommand('hotExit')
"""
Copies Scope to Clipboard
---
Useful for when you are creating snippets or macros and you want to assign it
to a certain scope only. By default Sublime Text only allows you to see
the current scope, so you have to memorize it and then write it. That's gone with
this command :)
"""
class ScopeToClipboardCommand(sublimeplugin.TextCommand):
def run(self, view, args):
sublime.setClipboard(view.syntaxName(view.sel()[0].begin()).strip());
sublime.statusMessage('Scope copied to clipboard')
class ReverseStringCommand(sublimeplugin.TextCommand):
def run(self, view, args):
for region in view.sel():
sublime.statusMessage('reversing strings!')
s = view.substr(region)
s = s[::-1]
view.replace(region, s)
class ReverseSelectionDirections(sublimeplugin.TextCommand):
def run(self, view, args):
sels = [sublime.Region(sel.b, sel.a) for sel in view.sel()]
view.sel().clear()
map(view.sel().add, sels)
class OpenFileUnderCursorCommand(sublimeplugin.WindowCommand):
def run(self, window, args):
curdir = os.getcwdu()
view = window.activeView()
for region in view.sel():
s = view.substr(region)
if(s != ''):
f = curdir + '\\' + s
if(os.path.exists(f)):
window.openFile(f)
else:
sublime.errorMessage('The file under cursor does not exists in the directory of the current file')
else:
# f = curdir + '\\' + str(args[1])
word_under_cursor = view.substr(view.word(view.sel()[0].begin()))
dot_pos = view.find('\.',view.sel()[0].begin())
if(dot_pos):
f = view.substr(view.word(dot_pos))
if(os.path.exists(f)):
window.openFile(f)
else:
sublime.errorMessage('The file under cursor does not exists in the directory of the current file')
"""
Nick (sublimator) functions :)
Thank you very much Nick!
"""
class DeleteLineCommand(sublimeplugin.TextCommand):
def run(self, view, args):
print 'hello world'
for sel in view.sel():
view.erase(view.fullLine(sel))
# -- REPLACED BY DEFAULT scanProject command
# class ReloadProjectCommand(sublimeplugin.WindowCommand):
# def isEnabled(self, window, args):
# return window.project()
# def run(self, window, args):
# project = window.project().fileName()
# window.runCommand('closeProject')
# window.runCommand('openProject', [project.replace('\\','/')])
class StripTrailingOnSaveCommand(sublimeplugin.TextCommand):
def strip_trailing(self, view, save_recent_indentation=True, ignore='string'):
trailing_spaces = view.findAll('[ \t]+(?![^\n])')
if not trailing_spaces: return
if save_recent_indentation:
for sel in view.sel():
if not sel.empty(): continue
line = view.line(sel)
if view.substr(line).isspace() and sel.end() == line.end():
pos = bisect.bisect(trailing_spaces, line) - 1
trailing_sel = trailing_spaces[pos]
if line.contains(trailing_sel):
del trailing_spaces[pos]
for sel in reversed(trailing_spaces):
if ignore:
pt_range = xrange(sel.begin(), sel.end())
if any(view.matchSelector(pt, ignore) for pt in pt_range):
continue
view.erase(sel)
def onPreSave(self, view):
self.strip_trailing(view)
def run(self, view, args):
self.strip_trailing(view, ignore=None, save_recent_indentation=False)
"""
DO MULTIPLE SELECTION - MULTIPLE SELECTIONS WITHOUT USING MOUSE!
Allows you to do multiple selections without using the mouse.
Usage: Just navigate to where you want to add a new selection
Run the command (via shortcut I suppose) and then just run the command to
restore your selections :D
"""
class DoMultipleSelectionCommand(sublimeplugin.TextCommand):
selections = [] # Store selections here
def run(self, view, (args, )):
if args == 'store':
# Store the selections
self.selections.extend(list(view.sel()))
sublime.statusMessage("Selection stored sucessfully.")
else:
# Restore the selections
while self.selections:
view.sel().add(self.selections.pop())
sublime.statusMessage("All Selection have been restored.")
"""
/END Nick functions
"""
"""
Duplicates Current Line or Selected text
---
Duplicates current line if there's nothing selected. Else duplicates content
"""
class DuplicateLineCommand(sublimeplugin.TextCommand):
def run(self, view, args):
for region in view.sel():
if region.empty():
line = view.line(region)
lineContents = view.substr(line) + '\n'
view.insert(line.begin(), lineContents)
else:
s = view.substr(region)
view.insert(region.end(), s)
"""
HTML Entities
---
It converts selected text to HTML entities, just like textmate does...
"""
class UndoEntitiesCommand(sublimeplugin.TextCommand):
def run(self, view, args):
def decode_htmlentities(string):
def substitute_entity(match):
ent = match.group(3)
if match.group(1) == "#":
# decoding by number
if match.group(2) == '':
# number is in decimal
return unichr(int(ent))
elif match.group(2) == 'x':
# number is in hex
return unichr(int('0x'+ent, 16))
else:
# they were using a name
cp = n2cp.get(ent)
if cp: return unichr(cp)
else: return match.group()
entity_re = re.compile(r'&(#?)(x?)(\w+);')
return entity_re.subn(substitute_entity, string)[0]
for region in view.sel():
# line = view.line(region)
s = view.substr(region)
view.replace(region, decode_htmlentities(s))
class DoEntitiesCommand(sublimeplugin.TextCommand):
def run(self, view, args):
for region in view.sel():
s = view.substr(region)
view.replace(region, cgi.escape(s, 1))
"""
HTML URL Escaping
---
URL Escapes selected text, just like textmate does...
"""
class DoURLEscapeCommand(sublimeplugin.TextCommand):
def run(self, view, args):
for region in view.sel():
s = view.substr(region)
view.replace(region, urllib.quote(s))
class UndoURLEscapeCommand(sublimeplugin.TextCommand):
def run(self, view, args):
for region in view.sel():
s = view.substr(region)
view.replace(region, urllib.unquote(s))
"""
Add Numbers in selected text.
"""
class AddNumbersCommand(sublimeplugin.TextCommand):
def run(self, view, args):
for region in view.sel():
if not region.empty():
# Get the selected text
line = view.line(region)
s = view.substr(region)
num = re.compile('([0-9]+(\.[0-9]+)?)')
isNum = num.finditer(s)
totalNum = 0;
# sublime.statusMessage(m.group(2))
for m in isNum:
if m.group(2):
totalNum = float(totalNum) + float(m.group())
else:
totalNum = int(totalNum) + int(m.group())
view.insert(line.end(), '\n= ' + str(totalNum))
"""
Firebug like Number increasing/decreasing.
---
Ever used firebug? Ever use up/down arrows to increase/decrease a number?
Well this is what that does ;)
"""
class UpNumCommand(sublimeplugin.TextCommand):
def run(self, view, args):
for region in view.sel():
if not region.empty():
# Get the selected text
s = view.substr(region)
# Put it on the status bar?
num = re.compile('([0-9]+)([a-zA-Z%]+)?')
isNum = num.match(s)
if (isNum):
upNum = int(isNum.group(1)) + 1
# sublime.statusMessage(isNum.group())
# Replace the selection with transformed text
if(isNum.group(2)):
view.replace(region, str(upNum) + isNum.group(2))
else:
view.replace(region, str(upNum))
def isEnabled(self, view, args):
return view.hasNonEmptySelectionRegion()
class DownNumCommand(sublimeplugin.TextCommand):
def run(self, view, args):
for region in view.sel():
if not region.empty():
# Get the selected text
s = view.substr(region)
# Put it on the status bar?
num = re.compile('([0-9]+)([a-zA-Z%]+)?')
isNum = num.match(s)
if (isNum):
downNum = int(isNum.group(1)) - 1
# sublime.statusMessage(str(upNum))
# Replace the selection with transformed text
if(isNum.group(2)):
view.replace(region, str(downNum) + isNum.group(2))
else:
view.replace(region, str(downNum))
def isEnabled(self, view, args):
return view.hasNonEmptySelectionRegion()
class UpNumTenCommand(sublimeplugin.TextCommand):
def run(self, view, args):
for region in view.sel():
if not region.empty():
# Get the selected text
s = view.substr(region)
# Put it on the status bar?
num = re.compile('([0-9]+)([a-zA-Z%]+)?')
isNum = num.match(s)
if (isNum):
upNum = int(isNum.group(1)) + 10
# sublime.statusMessage(isNum.group())
# Replace the selection with transformed text
if(isNum.group(2)):
view.replace(region, str(upNum) + isNum.group(2))
else:
view.replace(region, str(upNum))
def isEnabled(self, view, args):
return view.hasNonEmptySelectionRegion()
class DownNumTenCommand(sublimeplugin.TextCommand):
def run(self, view, args):
for region in view.sel():
if not region.empty():
# Get the selected text
s = view.substr(region)
# Put it on the status bar?
num = re.compile('([0-9]+)([a-zA-Z%]+)?')
isNum = num.match(s)
if (isNum):
downNum = int(isNum.group(1)) - 10
# sublime.statusMessage(str(upNum))
# Replace the selection with transformed text
if(isNum.group(2)):
view.replace(region, str(downNum) + isNum.group(2))
else:
view.replace(region, str(downNum))
def isEnabled(self, view, args):
return view.hasNonEmptySelectionRegion()
"""
Execute Selected Text
---
This evals selected text and puts result of that in new line.
This gives you power to execute anything in python and use it on your editor!
Ex:
Selected Text: 5+5
Output: 10 (in a new line)
"""
class ExecSelCommand(sublimeplugin.TextCommand):
def run(self, view, args):
for region in view.sel():
if not region.empty():
# Get the selected text
line = view.line(region)
s = view.substr(region)
evalResult = eval(s, globals(), locals())
view.insert(line.end(), '\n' + str(evalResult))
def isEnabled(self, view, args):
return view.hasNonEmptySelectionRegion()
"""
Execute Selected Text & Replace
---
This evals selected text and replaces the selection with the result.
This gives you power to execute anything in python and use it on your editor!
Ex:
Selected Text: 5+5
Output: 10 (replacing selection)
"""
class ExecSelReplaceCommand(sublimeplugin.TextCommand):
def run(self, view, args):
for region in view.sel():
if not region.empty():
# Get the selected text
line = view.line(region)
s = view.substr(region)
evalResult = eval(s, globals(), locals())
view.replace(region, str(evalResult))
def isEnabled(self, view, args):
return view.hasNonEmptySelectionRegion()
"""
Put Command -- Put X times "my string"
---
You can use it with the SublimeRunCmd and then you can do
put 5 times "hello world\n"
you get:
hello world
hello world
hello world
hello world
hello world
Try it!
"""
class PutCommand(sublimeplugin.TextCommand):
def run(self, view, args):
# args = string.join(args,'')
# sublime.statusMessage(str(args[1]))
num = re.compile('([0-9]+)')
isNum = num.match(args[0])
if(isNum and args[1] == 'times' ):
# sublime.statusMessage(str(args[2]))
# view.runCommand('insertAndDecodeCharacters "' + str(args) + '"')
view.runCommand('times ' + str(isNum.group(1)) + ' insertAndDecodeCharacters "' + str(args[2]) + '"')
"""
SublimeRunCmd - Shorcut for view.runCommand
---
This is so you can type and execute commands in the editor, without having to
go to the output panel. Just use a shortcut :D
"""
class SublimeRunCmdCommand(sublimeplugin.TextCommand):
def run(self, view, args):
for region in view.sel():
if not region.empty():
s = view.substr(region)
evalResult = view.runCommand(s)
def isEnabled(self, view, args):
return view.hasNonEmptySelectionRegion()
"""
Title Case Command
"""
def transformSelectionText(f, v):
for s in v.sel():
if not s.empty():
txt = f(v.substr(s))
v.replace(s, txt)
class TitleCaseCommand(sublimeplugin.TextCommand):
def run(self, view, args):
transformSelectionText(string.capwords, view)
def isEnabled(self, view, args):
return view.hasNonEmptySelectionRegion()
#====================================================================================================================================================================================================
"""
ALL THE FOLLOWING WERE TAKEN FROM COMMUNITY PACKAGES.
THEY ARE HERE BECAUSE I USE THEM AND INSTEAD OF DOWNLOADING A BUNCH OF PACKAGES
I CAN JUST USE THIS ONE :) -- VERY CONVINIENT WHEN YOU WORK IN MORE THAN 1 PC.
"""
"""
ZOOMIN / ZOOMOUT
----------------
IF YOU WANT TO BIND THESE COMMANDS TO CTRL+MWHEELUP/CTRL+MWHEELDOWN
YOU CAN USE AUTOHOTKEY TO ACHIEVE THIS.
USE THE FOLLOWING SCRIPT.
THIS WORKS FOR AS LONG AS THE ZOOMIN/ZOOMOUT COMMAND ARE BINDED TO
IF YOU CHANGE THE BINDINGS THEN U MUST MODIFY THE SCRIPT.
;=========================================================
;Sublime ZoomIn/ZoomOut
;=========================================================
^WheelUp::
IfWinActive, ahk_class SKMainWindowClass
Send !{=}
return
^WheelDown::
IfWinActive, ahk_class SKMainWindowClass
Send !{-}
return
;=========================================================
;END Sublime ZoomIn/ZoomOut
;=========================================================
HAPPY ZOOMING!
"""
class ZoomInCommand(sublimeplugin.TextCommand):
def run(self, view, args):
current_font = view.options().get('font')
(font, sep, size) = current_font.rpartition(" ")
new_size = int(size) + 1
new_font = font + " " + str(new_size)
view.options().set('font', new_font)
print "set new font to: " + new_font
class ZoomOutCommand(sublimeplugin.TextCommand):
def run(self, view, args):
current_font = view.options().get('font')
(font, sep, size) = current_font.rpartition(" ")
new_size = int(size) - 1
new_font = font + " " + str(new_size)
view.options().set('font', new_font)
print "set new font to: " + new_font
"""
Excellent plugins by gpfsmurf
"""
#PasteColumn
class pasteColumnCommand(sublimeplugin.TextCommand):
"""
Use this command to cut and paste whole columns.
If you had i.e. 10 selection cursors when cutting the column, you need 10
selection cursors to paste the column.
"""
def run(self, view, args):
clip = sublime.getClipboard().split(u"\n")
for region in view.sel():
view.replace(region, clip.pop(0))
def isEnabled(self, view, args):
return sublime.getClipboard() != ""
#Strip Selection
class stripSelectionCommand(sublimeplugin.TextCommand):
"""
Removes leading and trailing whitespace from selections
"""
def run(self, view, args):
rs = []
for region in view.sel():
s = view.substr(region)
if(not s.strip()):
# strip whitespace selections
rs.append(sublime.Region(region.begin(),region.begin()))
continue
a, b = region.a, region.b
if(b > a):
a += len(s) - len(s.lstrip())
b -= len(s) - len(s.rstrip())
else: # selection is inverted, keep it that way
b += len(s) - len(s.lstrip())
a -= len(s) - len(s.rstrip())
rs.append(sublime.Region(a,b))
view.sel().clear()
for region in rs:
view.sel().add(region)
def isEnabled(self, view, args):
return view.hasNonEmptySelectionRegion();
"""
For more info see:
http://www.sublimetext.com/forum/viewtopic.php?f=5&t=158#p843
By: eric1235711
"""
class RightEraseByCharClassCommand(sublimeplugin.TextCommand):
def run(self, view, args):
# patterns
pt_s = re.compile(r"\s")
pt_w = re.compile(r"\w")
pt_o = re.compile(r"[^\w\s]")
sz = view.size()
for region in view.sel():
pos = region.begin()
# check first char
if pt_w.match(view.substr(pos)) :
pt = pt_w
elif pt_s.match(view.substr(pos)) :
pt = pt_s
else :
pt = pt_o
# removes according to first char
while pt.match(view.substr(pos)) and pos < sz :
view.erase(sublime.Region(pos,pos+1))
class LeftEraseByCharClassCommand(sublimeplugin.TextCommand):
def run(self, view, args):
# patterns
pt_s = re.compile(r"\s")
pt_w = re.compile(r"\w")
pt_o = re.compile(r"[^\w\s]")
for region in view.sel():
pos = region.end()-1
# check last char
if pt_w.match(view.substr(pos)) :
pt = pt_w
elif pt_s.match(view.substr(pos)) :
pt = pt_s
else :
pt = pt_o
# removes according to last char
while pos > 1 and pt.match(view.substr(pos)) :
view.erase(sublime.Region(pos,pos+1))
pos -= 1
"""
These 2 do the same as above but they just take away 1 character...
For more info about these functions visit:
http://www.sublimetext.com/forum/viewtopic.php?p=1772#p1772
"""
class SingleRightEraseByCharClassCommand(sublimeplugin.TextCommand):
def run(self, view, args):
# patterns
pt_s = re.compile(r"\s")
pt_w = re.compile(r"\w")
pt_o = re.compile(r"[^\w\s]")
sz = view.size()
for region in view.sel():
pos = region.begin()
# check first char
if pt_w.match(view.substr(pos)) :
pt = pt_w
elif pt_s.match(view.substr(pos)) :
pt = pt_s
else :
pt = pt_o
# removes according to first char
if pt.match(view.substr(pos)) and pos < sz :
view.erase(sublime.Region(pos,pos+1))
class SingleLeftEraseByCharClassCommand(sublimeplugin.TextCommand):
def run(self, view, args):
# patterns
pt_s = re.compile(r"\s")
pt_w = re.compile(r"\w")
pt_o = re.compile(r"[^\w\s]")
for region in view.sel():
pos = region.end()-1
# check last char
if pt_w.match(view.substr(pos)) :
pt = pt_w
elif pt_s.match(view.substr(pos)) :
pt = pt_s
else :
pt = pt_o
# removes according to last char
if pos > 1 and pt.match(view.substr(pos)):
view.erase(sublime.Region(pos,pos+1))
pos -= 1
PK V4=•3Ëu  select_column.py"""
Sublime Text - PowerUser Package
By: EJ12N
Plugin Code By: Nicholas (Sublimator)
!Experimental!
"""
#!/usr/bin/env python
#coding: utf8
#################################### IMPORTS ###################################
import pprint
import functools
# Sublime Libs
import sublime
import sublimeplugin
# from geniusql.logic import Expression as E # Overkill, trying it out
E = lambda e: e
################################### CONSTANTS ##################################
index_selection_by_direction = {-1: 0, 1: -1}
direction_by_name = {-1: 'up', 1: 'down'}
STARS = '*' * 30
################################### SETTINGS ###################################
SLOW_MOTION = 0 # ms delay per `yield` to Sublime
# Set at high values to see rendering of command in slow mo,
# or to any value with boolean evaluation of False
# to run normally. Handy for debugging customisations and to
# `see` what is going on.
DEBUG = SLOW_MOTION or 0
################################ STOP CONDITIONS ###############################
# Stop conditions are those that stop the cursor moving up / down
# When in slow motion motion mode, will log all failing stop conditions
# as well as pretty print the locals().
# Uses geniusql ast Expressions; which can be strung together if needed
# eg: (e1 | e2) & e3.
# Will print a nice __repr__ of Expressions too (locals pprint)
stop_conds = {
"New area doesnt match start scope": E (
lambda v, sel, new_sel, c:
not v.matchSelector(new_sel.begin(), c.start_scope)),
"Behind cursor is not space but is on new cursor": E (
lambda v, sel, new_sel, c:
not v.substr(sel.begin()-1).isspace()
and v.substr(new_sel.begin()-1).isspace() ),
"Behind cursor is space but behind new cursor isn't": E (
lambda v, sel, new_sel, c:
v.substr(sel.begin()-1).isspace()
and not v.substr(new_sel.begin()-1).isspace() ),
"Cursor is space but new cursor isn't": E (
lambda v, sel, new_sel, c:
v.substr(sel.begin()).isspace()
and not v.substr(new_sel.begin()).isspace() ),
"Cursor isn't space but new cursor is": E (
lambda v, sel, new_sel, c:
not v.substr(sel.begin()).isspace()
and v.substr(new_sel.begin()).isspace() ),
# Usually only hit on rare cases
"Different Start Point" : E (
lambda v, sel, new_sel, c: c.new_start_pt != c.start_pt ),
'selectLines was noop' : E (lambda v, sel, new_sel, c: c.going_nowhere),
# Unlikely to need this due to `cursor is space but ... ` type conditions
# "Hit a blank Blank line" : E (
# lambda v, sel, new_sel, c:
# view.substr(view.line(new_sel)).isspace() ),
}
#################################### HELPERS ###################################
class Context(dict):
"Sugar"
__setattr__ = dict.__setitem__
__getattr__ = lambda s, a: s[a]
def expanded_tabs_region_length(view, start, end):
tab_size = int(view.options().get('tabSize', 8))
region = sublime.Region(start, end)
return len(view.substr(region).expandtabs(tab_size))
def get_sel_pts(view, sel):
"Tab normalized character point"
start = expanded_tabs_region_length(view, view.line(sel).begin(), sel.begin())
length = expanded_tabs_region_length(view, sel.begin(), sel.end())
return start, length
def staggered(every=1):
"Slow mowifier"
def coRoutine(f):
@functools.wraps(f)
def run(*args):
routine = f(*args)
def next():
try: routine.next()
except StopIteration: return
sublime.setTimeout(next, every)
next()
return run
return coRoutine
normed_scope = lambda v, pt: " ".join (
t.strip() for t in reversed(v.syntaxName(pt).split()) )
################################################################################
class SelectColumn(sublimeplugin.TextCommand):
isEnabled = lambda s,v,a: len(v.sel())
def run(self, view, args):
if SLOW_MOTION:
return staggered(SLOW_MOTION)(self.select)(view, args)
else:
for yield_pt in self.select(view, args): pass
def select(self, view, args):
if DEBUG: print STARS, "COLUMN SELECT COMMAND", STARS
# All selections from all potential columns ( col per starting_pt )
all_selections = []
# Save all the starting collections:
start_selections = []
starting_points = set()
for sel in view.sel():
start_pt, length = get_sel_pts(view, sel)
if start_pt not in starting_points:
starting_points.add(start_pt)
start_selections.append((sel, start_pt, length))
yield view.sel().clear()
for sel, start_pt, length in start_selections:
c = Context(start_pt=start_pt)
view.sel().add(sel)
c.start_scope = normed_scope(view, sel.begin())
# If there is a non empty selection make it empty first for purposes
# of expansion. Move to begin(), command will reinstate length
# later. Works around selection direction LtR, RtL complications
if length:
view.runCommand('move', ['characters', '-1'])
# Foreach direction move cursor that way until hit stop condition
for direction in (1, -1):
sel_index = index_selection_by_direction.get(direction)
rollback_selectLines = False
while True:
# Keep track of number of selections
sels = list(view.sel())
num_sels_b4 = len(view.sel())
# selectLines
yield view.runCommand('selectLines', [`direction`])
# see if selectLines was a noop
c.going_nowhere = num_sels_b4 == len(view.sel())
if c.going_nowhere:
assert sels == list(view.sel())
if not c.going_nowhere:
# If extra cursor was added make sure it doesn't
# hit a stop condition
new_sel = view.sel()[sel_index]
c.new_start_pt, new_end_pt = get_sel_pts(view, new_sel)
fails, fail_expr = {}, []
for key, expr in sorted(stop_conds.items()):
stop_cond = expr(view, sel, new_sel, c)
if stop_cond:
fails[key] = stop_cond
fail_expr.append(expr)
if not SLOW_MOTION:
break
if fails:
rollback_selectLines = True
if DEBUG:
direction = direction_by_name[direction]
print '\nSTOP COND: %s' % direction
print '\n\n%s' % pprint.pformat(fails)
print '\n\n%s' % pprint.pformat(locals())
if c.going_nowhere or rollback_selectLines:
break
# Delete cursor that hit stop condition
if rollback_selectLines:
yield view.sel().subtract(new_sel)
for sel in view.sel():
yield all_selections.append (
sublime.Region(sel.begin(), sel.begin()+length ))
view.sel().clear()
for sel in all_selections:
view.sel().add(sel)
################################################################################PK V4=3§T;¼
¼
useful_python_commands.txtYou can use all these with Execute[&Replace] selection commands.
****************************************************************************************************
print "Current date and time using instance attributes:"
print "Current year: %d" % now.year
print "Current month: %d" % now.month
print "Current day: %d" % now.day
print "Current hour: %d" % now.hour
print "Current minute: %d" % now.minute
print "Current second: %d" % now.second
print "Current microsecond: %d" % now.microsecond
****************************************************************************************************
#print april 2009 plain text calendar :)
calendar.TextCalendar(calendar.SUNDAY).formatmonth(2009, 4) =
April 2009
Su Mo Tu We Th Fr Sa
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30
calendar.TextCalendar(calendar.SUNDAY).formatmonth(datetime.datetime.now().year, datetime.datetime.now().month)
****************************************************************************************************
#print "Day and Date:"
time.strftime("%a %m/%d/%y", time.localtime()) = Fri 05/01/09
--------------------------------------------------
#print "Day, Date :"
time.strftime("%A, %B %d, %Y", time.localtime()) = Friday, May 01, 2009
--------------------------------------------------
#print "Time (12hr) :"
time.strftime("%I:%M:%S %p", time.localtime()) = 01:21:15 PM
--------------------------------------------------
#print "Time (24hr) :"
time.strftime("%H:%M:%S", time.localtime()) = 13:21:05
--------------------------------------------------
#print "DayMonthYear:"
time.strftime("%d%b%Y", time.localtime()) = 01May2009
--------------------------------------------------
#print NOTEPAD Time/date
time.strftime("%I:%M %p %m/%d/%Y", time.localtime())
****************************************************************************************************
#print day names list
"\n".join(calendar.day_name) =
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday
****************************************************************************************************
#print string * X times
"*" * 100
****************************************************************************************************
#print random float number
random.random()
****************************************************************************************************
****************************************************************************************************
REGEX NOTES:
****************************************************************************************************
Select between quotes:
(?