Is there a way to do the reverse selection in Sublime Text 2?
I know that you can skip (Ctrl + K, Ctrl + D), undo (Ctrl + Y) and cherry pick (hold alt) your selection from Ctrl + D but how do I tell sublime to multi-select in reverse order?
Let's say, instead of going up to down, I want to go down to up.
If anyone can please improve upon this plugin so that it scrolls the screen upwards as it selects, that would be greatly appreciated.
NOTE: The OSX key binding that I chose for this example conflicts with duplicate_line, so that key binding would need to be commented out for this new key binding to work -- otherwise, select a different key binding that is not already taken.
{ "keys": ["super+shift+d"], "command": "inverse_find_under_expand" },
import sublime, sublime_plugin
class InverseFindUnderExpandCommand(sublime_plugin.TextCommand):
"Add the previous occurrence of the word under the cursor to the selection"
def run(self, edit):
sel = [s for s in self.view.sel()]
new_sel = []
for s in sel:
self.view.sel().clear()
self.view.sel().add(s)
self.view.window().run_command('find_under_prev')
for ns in self.view.sel():
new_sel.append(ns)
self.view.sel().clear()
for s in sel:
self.view.sel().add(s)
for s in new_sel:
self.view.sel().add(s)
Related
using urwid, I'm trying to separate the highlight/walk and cursor functionality of a Pile widget. How can I use up/down to change which widget is highlighted, while keeping the cursor in a different widget?
The default focus behavior couples the cursor with attribute (highlighting) behavior. The example below shows one way to decouple these, where a list of SelectableIcons retains the highlight feature, while the cursor is moved to a separate Edit widget. It does this via:
overriding the keypress method to update the focus where the cursor is not
wrapping each SelectableIcon in AttrMap that change their attribute based on their Pile's focus_position
after changing the SelectableIcon attributes, the focus (cursor) is set back to the Edit widget via focus_part='body'
self._w = ... is called to update all widgets on screen
There may be more concise ways of doing this, but this should be rather flexible.
import urwid
def main():
my_widget = MyWidget()
palette = [('unselected', 'default', 'default'),
('selected', 'standout', 'default', 'bold')]
urwid.MainLoop(my_widget, palette=palette).run()
class MyWidget(urwid.WidgetWrap):
def __init__(self):
n = 10
labels = ['selection {}'.format(j) for j in range(n)]
self.header = urwid.Pile([urwid.AttrMap(urwid.SelectableIcon(label), 'unselected', focus_map='selected') for label in labels])
self.edit_widgets = [urwid.Edit('', label + ' edit_text') for label in labels]
self.body = urwid.Filler(self.edit_widgets[0])
super().__init__(urwid.Frame(header=self.header, body=self.body, focus_part='body'))
self.update_focus(new_focus_position=0)
def update_focus(self, new_focus_position=None):
self.header.focus_item.set_attr_map({None: 'unselected'})
try:
self.header.focus_position = new_focus_position
self.body = urwid.Filler(self.edit_widgets[new_focus_position])
except IndexError:
pass
self.header.focus_item.set_attr_map({None: 'selected'})
self._w = urwid.Frame(header=self.header, body=self.body, focus_part='body')
def keypress(self, size, key):
if key == 'up':
self.update_focus(new_focus_position=self.header.focus_position - 1)
if key == 'down':
self.update_focus(new_focus_position=self.header.focus_position + 1)
if key in {'Q', 'q'}:
raise urwid.ExitMainLoop()
super().keypress(size, key)
main()
If you really need this, it probably makes sense to write your own widgets -- maybe based on some classes extending urwid.Text and urwid.Button
There is no real "highlight" feature in the widgets that come with urwid, there is only a "focus" feature, and it doesn't seem to be easy to decouple the focus highlight from the focus behavior.
You probably want to implement your own widgets with some sort of secondary highlighting.
On Sublime Text 3 (but I guess it's the same with ST2), I know that when you copy ( CTRL + C ) when there is nothing selected, the entire line is copied but I need to know how to paste it below my cursor.
It currently paste it above it and it doesn't seem logical to me, is there a way to modify this behaviour ?
Following Dan Lowe's answer, I made this file :
http://pastebin.com/7nPWZCPh
and added this line
{ "keys": ["ctrl+shift+v"], "command": "run_macro_file", "args": {"file": "res://Packages/User/paste_no_line.sublime-macro"}},
to my user's keybindings.
Works as intended but I have two differente "paste command" now.
It's not that it pastes "above" or "below", it's that it is operating on the current line. When you copy without first making a selection, it copies the current line. When you paste that, it also operates on the current line -- it pastes the buffer into that line, and as a side effect, whatever was on that line is bumped out of the way to the next line. It can't be bumped upward instead - the file can only grow or add new lines downward, you can't grow upward beyond line 1.
As to how to modify the behavior, I would suggest trying to make a macro.
http://docs.sublimetext.info/en/latest/extensibility/macros.html
As you pointed out in the comments, a macro works but it leaves you with two different ways to do a paste, one for normal use and the other for this "entire line" behavior. That is unfortunate, though there is another (harder) solution. You could try to write a Sublime plugin to detect how to behave and do what you want in each case. This is a bit beyond my ability to do for you... but in thinking about this, I realized that the Vintage package already has a command for this, because its p and P keys paste before and after the cursor, respectively. I looked inside the Vintage package to find where they did it. Here is their code, though I couldn't explain to you exactly how it works. You would want to try to emulate ViPasteRight.
class ViPrefixableCommand(sublime_plugin.TextCommand):
# Ensure register and repeat are picked up from g_input_state, and that
# it'll be recorded on the undo stack
def run_(self, edit_token, args):
if not args:
args = {}
if g_input_state.register:
args['register'] = g_input_state.register
g_input_state.register = None
if g_input_state.prefix_repeat_digits:
args['repeat'] = digits_to_number(g_input_state.prefix_repeat_digits)
g_input_state.prefix_repeat_digits = []
if 'event' in args:
del args['event']
edit = self.view.begin_edit(edit_token, self.name(), args)
try:
return self.run(edit, **args)
finally:
self.view.end_edit(edit)
class ViPasteRight(ViPrefixableCommand):
def advance(self, pt):
if self.view.substr(pt) == '\n' or pt >= self.view.size():
return pt
else:
return pt + 1
def run(self, edit, register = '"', repeat = 1):
visual_mode = self.view.has_non_empty_selection_region()
if not visual_mode:
transform_selection(self.view, lambda pt: self.advance(pt))
self.view.run_command('paste_from_register', {'forward': not visual_mode,
'repeat': repeat,
'register': register})
class ViPasteLeft(ViPrefixableCommand):
def run(self, edit, register = '"', repeat = 1):
self.view.run_command('paste_from_register', {'forward': False,
'repeat': repeat,
'register': register})
And here is how they bind them to keys. If you wanted to try to adapt this you probably would not need the context, that is something they need due to Vintage mode's modal nature.
{ "keys": ["P"], "command": "vi_paste_left",
"context": [{"key": "setting.command_mode"}]
},
{ "keys": ["p"], "command": "vi_paste_right",
"context": [{"key": "setting.command_mode"}]
},
Here is the docs section about plugins, if you want to try to tackle it that way.
http://docs.sublimetext.info/en/latest/extensibility/plugins.html
OS X, Sublime Text 3
I can double click a word and use CMD + D to select the next instance of the word.
However if I want to replace this 30 times I need to CMD + D 30 times.
Is there a way to have it select all that it finds?
OpeningScene* OpeningScene::pinstance = 0;
OpeningScene* OpeningScene::Instance()
{
if (pinstance == 0)
{
pinstance = new OpeningScene;
pinstance->initInstance();
}
return pinstance;
}
OpeningScene::OpeningScene() { }
In the above, replacing OpeningScene I'd need to CMD + D 6 times after double clicking the first instance.
I guess I could do a Find/Replace using the dialog but is there a keyboard way of doing this?
Yes. Put your cursor over the word and type:
Ctrl+Cmd+G
This should do a quick find all on your current word.
I see no option to sort the sidebar in Sublime, how can I do it? I'd like to sort it alphabetically.
There is a Sublime plugin for that, called SortTabs. It works both with Sublime Text 2 and 3.
You can install it using Sublime Package Manger and then sort tabs using any of the following methods:
Sort Tabs by file name
Sort Tabs by file type
Sort Tabs by file path
Sort Tabs by modification date
Sort Tabs by last activation
I have found this answer
If you sort the tabs, it sorts the sidebar, and this sorts the tabs
I amended the classname though not to anything better. the classname was probably better before.
{ "keys": ["ctrl+alt+b"], "command": "sorttsortsidebar" }
http://www.sublimetext.com/forum/viewtopic.php?f=4&t=3876&start=20
import sublime_plugin
from os import path
from operator import itemgetter
# A simple command to sort current tabs alphabetically (returning focus to the
# original tab).
# Does not work with different groups or windows. Not catered for unsaved views
# (although it seems to work okay if there are any). It could be modified to
# work in these circumstances.
# { "keys": ["ctrl+alt+b"], "command": "sort_tabs" },
class SorttsortsidebarCommand(sublime_plugin.WindowCommand):
def run(self):
print("ddffd_sorttabs")
file_views = []
win = self.window
curr_view = win.active_view()
for vw in win.views():
_, tail = path.split(vw.file_name() or path.sep)
group, _ = win.get_view_index(vw)
file_views.append((tail.lower(), vw, group))
file_views.sort(key = itemgetter(2, 0))
moving_index = 0
for index, (_, vw, group) in enumerate(file_views):
if index == 0 or group > prev_group:
moving_index = 0
prev_group = group
else:
moving_index += 1
win.set_view_index(vw, group, moving_index)
win.focus_view(curr_view)
Say if I have the following code in Sublime:
if (condition) {
// code
}
When my cursor is at the end of // code, I would like to set a key bind (e.g. Tab) that will exit the if-statement block and move it to the end of }. Thanks.
The BracketHighlighter plugin can provide this functionality natively... sort of. In its example shortcuts file, Example.sublime-keymap, there is a "Go to Right Bracket" example key binding:
// Go to right bracket
{
"keys": ["ctrl+alt+super+down"],
"command": "bh_key",
"args":
{
"lines" : true,
"plugin":
{
"type": ["__all__"],
"command": "bh_modules.bracketselect",
"args": {"select": "right"}
}
}
},
The only problem is that the called bracketselect command moves the cursor to the left side of the right bracket, requiring another keypress to fully escape from the block. I don't think that's what you want.
Worry not! Thankfully, BracketHighlighter provides a very intuitive plugin API, and I found that I could modify the bracketselect plugin to create a command that would escape from a bracket-enclosed block—basically the same as bracketselect, but it moves the cursor to the right side of the closing bracket rather than the left, and doesn't need any extra arguments.
You'll first need to install BracketHighlighter if you haven't yet.
Next, save blockescape.py (see below if the link ever dies) to
Preferences -> Browse Packages... -> BracketHighlighter/bh_modules/blockescape.py
Then, add this entry to the top of your user key bindings (Preferences -> Key Bindings — User):
{
"keys": ["tab"],
"command": "bh_key",
"args":
{
"lines" : true,
"plugin":
{
"type": ["__all__"],
"command": "bh_modules.blockescape"
}
}
},
I wouldn't recommend using tab as your trigger key, because tab has an important role already with expansions. Of course, you could define a special context in which to use tab, but that is up to you.
In case Github is ever down, here's the plugin code:
import bh_plugin
import sublime
DEFAULT_TAGS = ["cfml", "html", "angle"]
class BlockEscape(bh_plugin.BracketPluginCommand):
def run(self, edit, name, tags=DEFAULT_TAGS):
current_left, current_right = self.selection[0].begin(), self.selection[0].end()
left, right = self.left, self.right
first, last = left.end, right.begin
if left.end != right.end:
if name in tags and left.size() > 1:
first, last = right.begin + 1, right.begin + 1
if first == current_left and last == current_right:
first, last = right.end, right.end
else:
first, last = right.begin, right.begin
if first == current_left and last == current_right:
first, last = right.end, right.end
else:
# There is no second bracket, so just select the first
if name in tags and left.size() > 1:
first, last = left.begin + 1, left.begin + 1
else:
first, last = right.end, right.end
if first == current_left and last == current_right:
first, last = right.end, right.end
self.selection = [sublime.Region(first+1, last+1)]
def plugin():
return BlockEscape
Since I more or less hacked the plugin together, it might not work properly. In that case, feel free to edit it yourself or leave a comment on the Gist page.
You can add the $0 in a snippet to tab to that location:
<snippet>
<description>If Condition</description>
<content><![CDATA[if (${1:/* condition */}){
${2:/* code */}
}${0}]]></content>
<tabTrigger>if</tabTrigger>
<scope>source.c</scope>
</snippet>