How to add space to both ends of a equal-sign when not in parentheses with specified file types? - sublimetext2

Is it possible? For example, When in .py and .lua file, not in () and I type =, st3 will automatically add a space to both ends. such as a assignment statement:
a = 1
But it is disabled if in a () state:
func(a=1)
func(a=1,func(b=1))

You can do this by creating a keybinding on the = key, to insert a space, followed by the = and another space, that will check:
that the syntax at the caret corresponds to Python or Lua
that the text between the beginning of the line and the text caret contains no unbalanced brackets
If the conditions are not met, the keybinding is not used, and = will be inserted without surrounding whitespace as normal. (Assuming other keybindings on the = key, if any, are evaluated and found not to apply.)
Steps
In Sublime Text, open the Preferences menu and select Keybindings - User.
If the document is not empty, move the text caret to after the first [ character at the beginning of the document.
Paste in the following:
{ "keys": ["="], "command": "insert", "args": { "characters": " = " }, "context":
[
{ "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
{ "key": "selector", "operator": "equal", "operand": "source.python, source.lua", "match_all": true },
{ "key": "preceding_text", "operator": "regex_match", "operand": "^(([^()]*+)(\\((?:(?2)|(?3))*\\))?+)(?1)*+$", "match_all": true }
]
},
If the document was previously empty, type a [ at the beginning of the document, and a ] at the end of the document. This is to ensure that it is a valid JSON array.
Save the file.
Press the = key in a Python or Lua document, and see that it will automatically insert spaces around it when not inside unbalanced parens.
Explanation of the regex:
This aspect of Sublime Text uses the PCRE regex flavor provided by the Boost library, which supports recursion, and thus allows us to not have to repeat ourselves to determine whether the brackets are balanced or not.
^ start of the line
( begin capture group 1
([^()]*+) - possessively capture every consecutive non-parenthesis character into capture group 2
( begin capture group 3
\( match a literal ( character
(?:(?2)|(?3))* recursively match the same regex pattern that corresponds to capture group 2 or 3 (i.e. recursive), zero or unlimited times
\) match a literal ) character
) end capture group 3
?+ make the previous group optional but possessive
) end capture group 1
(?1)*+ possessively recursively match the same regex pattern that corresponds to capture group 1, zero or unlimited times
$ end of the text to be matched - in this case, where the text caret is, because the preceding_text context is used.
The overall effect is that is will match where any of the following are true on the line where the text caret is, before the caret position:
no parens are used
non-nested parens are opened and closed
nested parens are all closed
there are no closing parens that don't have a corresponding open paren
Because the regex is being stored in JSON, the \ characters need to be escaped with an extra \, which is why the operand string contains \\( but I only refer to \( in the regex explanation.
Scope Selector
To ensure that the keybinding is only active on Python and lua, the scope selector context is used, with an argument of source.python, source.lua. This selector matches either source.python or source.lua, or indeed both together if such a thing were possible to embed one language in the other.
One way to find what the base scope of a language in Sublime Text is, would be to go to the very beginning of a document set to the relevant syntax, and go to the Tools menu -> Developer -> Show Scope Name. It will even work on an empty file.
Scope selectors are borrowed from TextMate, and more documentation on them can be found here:
TextMate docs
SO answer
Keybinding Documentation
More information about keybindings can be found here: http://docs.sublimetext.info/en/latest/reference/key_bindings.html#structure-of-a-key-binding
I personally find it useful to view the default keybindings for inspiration.

Related

How to change all numbers by a % in Visual Studio Code

Sorry I am still a beginner but slowly getting there. I want to change all the "base-purchase-prices" by a % all at once? I am tearing my hair out trying to work out how to do it. There are 7000 line items so simply saying "get a calculator" is not going to work
{
"tradeable-code": "Scissors_01",
"base-purchase-price": "110",
"base-sell-price": "12",
"delta-price": "-1.0",
"can-be-purchased":"default"
},
{
"tradeable-code": "Scissors_Plastic",
"base-purchase-price": "88",
"base-sell-price": "9",
"delta-price": "-1.0",
"can-be-purchased":"default"
},
You can use the extension Regex Text Generator
select all the base-purchase-price prices
perform a regex find with: (?<="base-purchase-price": ")([^"]*)
press Alt+Enter while focus in Find dialog
Execute command: Generate text based on Regular Expression (regex)
for Match Original Text Regular Expression enter: (.*)
for Generator Regular Expression enter: {{=N[1]*1.05:fixed(2):simplify}}
this increases the prices with 5% (1+0.05) and rounds it to 2 decimal digits
if you like the preview type Enter otherwise Esc
press Esc to leave Multi Cursor Mode
Using this extension: Find and Transform, full disclosure - written by me, it is easy to do math on any values in your file.
For example, make this keybinding, in your keybindings.json file (it could also be made into a setting that will become a command in the Command Palette if you want:
{
"key": "alt+c", // whatever keybinding you want
"command": "findInCurrentFile",
"args": {
"find": "(?<=base-purchase-price\":\\s*\")(\\d+)",
"isRegex": true,
"replace": [
"$${",
"return ($1 * 1.05).toFixed(2);",
"}$$"
]
}
The find will capture only the digits you want to change. The replace will run any math (or string) operation you want. Here I simply multiplied the capture group $1 by 1.05 and set it to 2 decimal places.

Is there a way to copy a single line of code but have it incrementally increase a number in said line of code for each paste?

I have a line of code I want to mass-paste into a file.
The line of code is "enchantment.level.x": "string". I want to paste this multiple times into my program, but each time I paste the line, I want x to increase by one.
So if line 2000 is "enchantment.level.1": "I", I would want line 2001 to be "enchantment.level.2": "I" (but I would change "I" to "II" manually).
Is there a way I can achieve this?
Thank you
I don't think there is any way to do what you want on each paste. But if you make all your pastes first then you can #rioV8's or my extension to accomplish the same goal.
The extension is Find and Transform that I wrote. It supports replacing with the match number (or index). Put this keybinding into your keybindings.json:
{
"key": "alt+m",
"command": "findInCurrentFile",
"args": {
"find": "(?<=enchantment\\.level\\.)x", // match the "x"
"replace": "${matchNumber}", // replace with the matchNumber
"isRegex": true
}
}
You could make that into a named setting too if you don't want to run it from the Command Palette.
${matchNumber} starts at 1. ${matchIndex} starts at 0.
You can use the extension Regex Text Generator to generate the new numbers.
Paste the line as often as you like
Select the number on all the lines with Multiple Cursors
use the extension and use (.*) for match regex and {{=i+1}} for generator expression

Vim regex to add curly braces every few lines

I am creating a json file and have worked out how to append double quotes and such to appropriate lines, but I need to know how to wrap every 2 lines in curly braces.
Ex:
"value": "Bahraini Foreign Ministry"
"tag": "project:bahrain;id:2201",
"value": "Bahraini Foreign Minister"
"tag": "project:bahrain;id:2202",
needs to be:
{
"value": "Bahraini Foreign Ministry"
"tag": "project:bahrain;id:2201",
},
{
"value": "Bahraini Foreign Minister"
"tag": "project:bahrain;id:2202",
},
I have tried with :%norm and :%s and am going around in circles here. Any ideas are appreciated!
dNitro's solution is one way to do it. Here is another way:
qqqqqqO{<esc>jjo},<esc>j#qq#q
This creates a recursive macro, e.g. a macro that calls itself. Since recursive macros run until they hit an error, and calling j on the last line throws an error, this will work for any data size. Explanation:
qqq clear the register 'q'. qq starts recording in register 'q'. O{<esc> inserts a bracket on the line above the current line. jj moves down (to the line with "tag" on it). o},<esc> puts a bracket on the next line after the current one. j#q puts on back on a line with "value", and #q calls the 'q' macro. Since it's empty while you record, this won't actually do anything. However, once you hit q#q, this will stop recording, and then call this recursive macro.
Another alternative is to use the :global command, e.g.
:g/value/normal O{^[jjo},
Note that ^[ is a literal escape character that you must enter by pressing "ctrl-v, ctrl-esc"
This is essentially the same thing, except instead of using a macro, it automatically applies the set of keystrokes after "normal" to every line containing the text "value".
And just for fun, here is one last alternative, a substitute command:
:%s/.*"value".*\n.*,/{\r&\r},,
This replaces two lines where the first line contains the text "value", with the same text enclosed in brackets.

Sublime Text: Pressing Esc from multiple selections -- put cursor at last selection?

With Sublime Text, after a multi selection is with from CMD+D, I usually alter the text, then want to escape the selections and have the cursor at where the last selection was.
Some feature that are close:
CMD+U will reselect selections
CMD+G will skip to the next occurence
CMD+Shift+G will skip backwards to the previous occurence
Are there any keyboard shortcuts that will do what I want, similar to Esc but forward, rather than backward?
You can create a very simple plugin to do this, and then bind a key to it:
From the Tools menu, select Developer -> New Plugin...
Paste in the following:
import sublime, sublime_plugin
class SingleSelectionLastCommand(sublime_plugin.TextCommand):
def run(self, edit):
last = self.view.sel()[-1]
self.view.sel().clear()
self.view.sel().add(last)
self.view.show(last)
Save it in the folder it recommends, name the file something like single_selection_keep_last_cursor.py
Open Preferences -> Key Bindings - User
Type/Paste in something similar to the following:
{ "keys": ["escape"], "command": "single_selection_last", "context":
[
{ "key": "num_selections", "operator": "not_equal", "operand": 1 }
]
}
Save it
This example creates a new plugin with a command called single_selection_last, and then binds the Esc key to it when there is more than one selection. This therefore overrides the default Esc behavior of keeping the first selection.
The keybindings file needs to be a valid JSON array, so if it is empty you will need to wrap the example above in square brackets [...] for it to work.
If you wish to use a different key, you just need to replace escape with the key combination you want. See Preferences -> Key Bindings - Default for examples.

Hotkey to end the line with a semicolon and jump to a new line in Sublime Text 2

I'm trying to figure out a hotkey at work. I just got this job and I am using a Mac for more or less the first time in my life.
Back home on my Laptop, when using Eclipse, I seem to remember there being a single hotkey which would both:
Add a ; to the end of my current line (no matter where the caret was within said line)
Place my cursor at the beginning of a new line, with the same indentation level as the line I had just added a semicolon to
Does anybody know if this was an Eclipse-specific hotkey, or know of a way to replicate said hotkey in Sublime Text 2?
Best solution for this is recording a macro on Sublime Text and then assigning it to a keyboard shortcut. Follow these steps:
Create a line such as alert('hello') and leave the cursor right
after letter 'o'.
Then go to Tools > Record a Macro to start recording.
Press Command+→ to go to the end of line.
Press ; and hit Enter
Stop recording the macro by going to Tools > Stop Recording Macro
You can now test your macro by Tools > Playback Macro (optional)
Save your macro by going to Tools > Save Macro (ex: EndOfLine.sublime-macro)
Create a shortcut by adding this between the square brackets in your
in your Preferences > Key Bindings - User file:
{
"keys": ["super+;"], "command": "run_macro_file", "args": {"file": "Packages/User/EndOfLine.sublime-macro"}
}
Now, every time you hit Command+;, it will
magically place the semicolon at the end of current line and move the cursor to the next line.
Happy coding!
After reading your question about three times, I finally realized that you were looking for one hotkey to perform both operations. Whoops.
Your request sounds like the Ctrl+Shift+; hotkey of the Smart Semicolon Eclipse plugin. While adding semicolons of a genius-level IQ would probably require an entirely new Sublime Text 2 plugin, you can easily create a smart semicolon–esque key binding with Sublime Text's Macros. I actually didn't know about them until now!
In this case, recording the macro yourself is actually the fastest way to create it, rather than copying and pasting a new file (and now you'll have the experience for making more). First, open a new file and type in your favorite garbage line:
Lord Vetinari's cat|
Then move the caret to anywhere within the line:
Lord Veti|nari's cat
Now, press Ctrl+Q, the hotkey for Tools -> Record Macro. If the status bar is enabled, it will notify you that it is "Starting to record [a] macro". Press End (if you don't have an End key, skip to below), then ;, then Enter. Finally, press Ctrl+Q again to stop recording. When you do, the status bar will display "Stopped recording macro". Check that your macro is working by hitting Ctrl+Shift+Q on a code segment of your choosing.
Just pressing Enter will adjust indentation on the next line accordingly as long as the "auto_indent" setting is set to true. See Preferences -> Settings – Default, line 59.
When you're satisfied, save your new macro with Tools -> Save Macro.... I saved mine as Packages/User/smart-semicolon.sublime-macro. My file looked something like this; feel free to copy it if you can't or won't make the macro manually:
[
{
"args":
{
"extend": false,
"to": "eol"
},
"command": "move_to"
},
{
"args":
{
"characters": ";"
},
"command": "insert"
},
{
"args":
{
"characters": "\n"
},
"command": "insert"
}
]
"extend": false, just means that the macro won't add any text to the working selection. Read more about the options for commands at the Unofficial Docs Commands Page.
Now that you have your macro, we can give it a custom key binding. Add the following lines to your Preferences -> Key Bindings – User file:
{ "keys": ["ctrl+shift+;"], "command": "run_macro_file", "args": {"file": "Packages/User/smart-semicolon.sublime-macro"}, "context":
[
{ "key": "selector", "operator": "equal", "operand": "source.java" }
]
},
Replace Ctrl+Shift+; with whatever key binding you prefer, save your file, and give it a shot. The "context" array restricts the key binding to Java files (see the Unofficial Docs Key Bindings page for more information on contexts); if you want the key binding to be active everywhere, use this line instead:
{ "keys": ["ctrl+shift+;"], "command": "run_macro_file", "args": {"file": "Packages/User/smart-semicolon.sublime-macro"} },
This NetTuts+ article has much more information on macros and binding them to keys; I referenced it often. This UserEcho post looks like it has more information on making the insertion more extensible.
You can also use a ready-made sublime package built for this purpose: AppendSemiColon
You can use package control to install it, just search for "AppendSemiColon".
Place a semicolon at the end of the cursor's current line(s) by pressing:
Command+; on OS X
Ctrl+; on Windows and Linux
and
You can also automatically go to the next line at the same time like this:
Command+Shift+; on OS X
Ctrl+Shift+; on Windows and Linux
I've been using this package for a while now, and it works great.
UPDATE:
As the author mentioned in a comment, you can now also change the default hotkeys if you like (personally, I love the defaults). As an example, just change:
[
{ "keys": ["ctrl+;"], "command": "append_semi_colon" },
{ "keys": ["ctrl+shift+;"], "command": "append_semi_colon", "args": {"enter_new_line": "true"} }
]
in your sublime-keymap to use whatever keys you want.
I tested the latest version, and this feature too works fine. There was a bug where extra semicolons were being appended incorrectly upon extra hotkey presses - this minor annoyance has been fixed too. Thanks, MauriceZ/mzee99!
Ctrl+Enter will create a new line with the same level of indentation.
I could not find anything like the Ctrl+A you mentioned
I'm on Sublime Text 3 ... inspired by your post, I've added the following to my .sublime-keymap:
{ "keys": ["ctrl+enter"], "command": "run_macro_file", "args": {"file": "Packages/User/endOfLine.sublime-macro"} },
I'm amazed at how much time this saves.
#Felipe covered the second point. You can mimic the behavior of the first with a simple macro or plugin. I say or because you didn't describe the cursor position after you hit the key combination. Does it move the cursor to the next line? Does it insert a new line? I think you get the idea.
I'm pretty sure eclipse works on OS X as well as windows, so if you are more comfortable with that, why not use it (unless your job requires ST of course)? Most of the key bindings are probably the same/similar (well it's probably command rather than control for shortcuts).
http://www.eclipse.org/downloads/?osType=macosx
If you continue using ST, it's probably worthwhile to learn the basics of plugins. A lot can be built so you have the same behavior as other editors, it just takes some extra effort (through creating the plugin or finding a plugin that does it) up front.