Sublime text 2 completions - sublimetext2

Making the *.sublime-completions file, I found the "bug" which occurs when typing a long function like:
one.two.three.four.five(One := One_var, Two := Two_Var);
So if you type the whole function:
"one.two.three.four.five" and then press tab - it will paste another part of functions without issues.
But, if you type "one.two.thr" - and then in pop-up hint see that function and hit "Enter" it will replaces like:
one.two.one.two.three.four.five(One := One_var, Two := Two_Var);
How can I configure trigger to replace "one.two.thr" to correct function format?
This is my trigger.
{ "trigger": "one.two.three.four.five", "contents": "${TM_CURRENT_LINE/(.*)/(one.two.three.four.five)/}(One := One_var, Two := Two_Var);" },

This is not a bug, but a default setting of Sublime Text. By default, dots are treated as word_separators. Hence every time you type ., the completion trigger will be reset.
Example:
Let's assume we have only the following completions available:
{
"trigger": "one.two.three",
"contents": "one.two.three.four.five"
},
{
"trigger": "two",
"contents": "it_takes_two"
}
Now, let's type them in Sublime Text (the | marks the cursor position!)
one| -> will trigger "one.two.three.four.five"
one.| -> new word, forgot about "one.two.three.four.five"
one.two| -> will trigger "it_takes_two"
In the last case, both completions will be listed in the completion popup does to the fuzzy match for ”two”. However, the closer match ”two” will have a higher priority.
To fix this, you can edit the word_separators setting in a package setting or your global user settings. By default the setting treats the following characters as word separators:
./\\()\"'-:,.;<>~!##$%^&*|+=[]{}`~?
Alternatively, you ommit the dots from your completion triggers, e.g. use one-two-three instead of one.two.three.

Related

DBGrid - OnCellClick & OnDblClick, return a form/TBMemo containing cell/column value/s

I'm using the following code added to my DBGrid - OnCellClick event
procedure TForm2.DBGrid1CellClick(Column: TColumn);
begin
if dbmodule.comenziDataSet.Active then
begin
if not Assigned(dbgridCelulaForm) then
begin
dbgridCelulaForm := TdbgridCelulaForm.Create(Self);
dbgridCelulaForm.DBMemoCelula.DataSource := dbmodule.comenziSource;
end;
dbgridCelulaForm.Visible := False;
dbgridCelulaForm.Visible := True;
dbgridCelulaForm.DBMemoCelula.DataField := Column.FieldName;
dbgridCelulaForm.Caption := Format('%s / randul: %d',[Column.FieldName, DBGrid1.DataSource.DataSet.RecNo]);
end;
end;
dbgridCelulaForm = name of the form containing the TDBMemo
DBMemoCelula = name of the TDBMemo
dbmodule.comenziDataSet = comenziDataSet is the name of the DataSet and dbmodule is the name of a data module (unit, like forms) - the DataSet is on the data module, so, dbmodule.comenziDataSet
dbmodule.comenziSource = same as data set, a DataSource on a data module, the source is named comenziSource
Ok so what this code does:
Once I click a cell on my DBGrid it pops up a form (named dbgridCelulaForm) which contains a TBMemo (named DBMemoCelula) and it shows me the information contained in that cell (like, a Customer Name for example, or whatever the cell is holding, in my db)
This is fine, my problem is I can't select rows now in DBGrid, well, I can but once I do the 1st place I click (a cell, any) on the particular row I want to select with my mouse, then cell activates and the form pops up.
Is it possible to use this code in DBGrid - OnDblClick event instead of the OnCellClick ?
Meaning once i double click a row / cell the form should pop up and show me the info, but double click - not single click.
That way, I can still select the row and still view the info in the cell if I need to.
Or any other way/place to use/receive this functionality.
Any thoughts?
I can post a quick video of everything if my explanation is ambiguous and you think that would help, just tell me in the comment / answer.
Also, I'm using RAD Studio 10 Seattle and dbexpress components for the database - if that helps.
Thanks!
The following code shows how to access the Column and Row coordinates of a dbl-clicked cell of a TDBGrid, and the string value of the cell contents.
As written, it displays the cell's Column and Row number + string contents on the form's caption. Up to you what you actually do with these values.
It work because the dataset cursor on the dataset connected to the DBGrid is moved to the dataset row corresponding to the cell where the mouse pointer is.
type
TMyDBGrid = class(TDBGrid);
procedure TForm1.DBGrid1DblClick(Sender: TObject);
var
ARow,
ACol : Integer;
Pt : TPoint;
CellValue : String;
begin
// First, get the mouse pointer coordinates
Pt.X := Mouse.CursorPos.X;
Pt.Y := Mouse.CursorPos.Y;
// Translate them into the coordinate system of the DBGrid
Pt := DBGrid1.ScreenToClient(Pt);
// Use TDBGrids inbuilt functionality to identify the Column and
// row number.
ACol := DBGrid1.MouseCoord(Pt.X, Pt.Y).X -1;
ARow := DBGrid1.MouseCoord(Pt.X, Pt.Y).Y;
CellValue := DBGrid1.Columns[ACol].Field.AsString;
Caption := Format('Col:%d Row:%d Cell Value:%s', [ACol, ARow, CellValue]);
end;
Note that I've used the Caption property of the form to display the grid cell info just as a quick n dirty way of showing the information somewhere. Of course you could equally well display it on another area of the form or somewhere on a different form entirely. The above code will work equally well in the grid's OnCellClick event, btw.
As noted in a comment, you can use the grid's SelectedField property instead of the above, but personally I think the above is more instructive of how to work with a DBGrid, because it shows how to get the cell's Column and Row coordinates. See the DBGrid's SelectedField, SelectedIndex and SelectedRows properties in the Online Help for more info on useful properties of the TDBGrid.
Update You asked in a comment for an example of showing the information on another form. Let's suppose this form is called OtherForm, is in a unit OtherFormu.Pas and is created before the DBGrid1DblClick evenbt is called. You need to use this unit in the Useslist of the unit which contains the DBGrid. Let's suppose this other form contains a TMemo control called Memo1. Then, you could write your DBGrid1DblClick hanndler like this:
procedure TForm1.DBGrid1DblClick(Sender: TObject);
[as above]
begin
[ as above ]
CellValue := DBGrid1.Columns[ACol].Field.AsString;
OtherForm.Memo1.Lines.Add(Format('Col:%d Row:%d Cell Value:%s', [ACol, ARow, CellValue]));
end;

Copy entire line shortcuts then paste it UNDER cursor

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

Exiting a block enclosed in curly braces in Sublime

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>

Apply a Vim macro to multiple lines

I made a simple macro to increment a number in a json object like this:
{
image: 'images/2.jpg',
thumb: 'images/2-thumb.jpg',
big: 'images/2.jpg',
title: '',
description: '',
link: 'images/2.jpg'
},
with:
q, n, shift-v, down-till-end, p, move-to-numbers, c-a, return-to-top, q, 150#n
(Sorry if that's not the appropriate syntax to post vim macros here in SE)
And it works, but it makes the increment just until the 9th. What am I missing?
Thanks in advance.
EDIT:
I'm trying to reach something like this:
{
image: 'images/3.jpg',
thumb: 'images/3-thumb.jpg',
big: 'images/3.jpg',
title: '',
description: '',
link: 'images/3.jpg'
},
{
image: 'images/4.jpg',
thumb: 'images/4-thumb.jpg',
big: 'images/4.jpg',
title: '',
description: '',
link: 'images/4.jpg'
},
... until *nth* value
Assuming your cursor is on the first opening bracket, here is one way to do it:
qn " start recording in register n
V% " select from here to the closing bracket, linewise
y " yank the selection
% " jump to the closing bracket
p " paste after the current line
:'[,']norm <C-v><C-a> " executing the normal mode command <C-a>(1) on all the lines that we just pasted
q " stop recording
then do 150#n.
(1) <C-v><C-a> is used to insert a literal ^A.
Try this:
Enter visual mode and select the lines to be included in the macro execution an type:
:normal #n
Then, when you hit enter, the macro will be applied to selected lines
I gave it a try:
qqv%:s/\d\+/\=submatch(0)+1/^M[[yGGp
short explanation
qq "recording to register q
v% "select things between { and }
:s/\d\+/\=submatch(0)+1/^M "just do +1 to all numbers (selected range)
[[ "back to begin {
yG "yank till the end
Gp "paste at the end
then do 150#q
if you record the same macro, type ^M simply by Enter
if you assign the macro to #q type ^M by <c-v><enter>
btw, this won't win golf, since the function name submatch(0) is too long...:)
With my UnconditionalPaste plugin, once you have yanked the original block into a register, you can paste [N] auto-incremented blocks simply with [N]gPp (paste linewise with all numbers incremented).
The plugin also allows several other manipulations of the way the text is pasted.

Dynamically Create AutoHotkey Hotkey to Function/Subroutine

The AutoHotkey command Hotkey allows for the creation of dynamic hotkeys at runtime, but its syntax and documentation seems to limit it to built-in or existing labels/subroutines, which makes it much less useful:
Hotkey, KeyName [, Label, Options]
Is there a way to get it to work like regular, hard-coded hotkeys? For example:
#z::MsgBox foobar ; Typical, hard-coded hotkey pops up a message-box
Hotkey, z, MsgBox foobar ; Nope; complains about missing label “MsgBox foobar”
It looks like it might be possible due to the following line from the manual, however it is not clear how it would work:
Label - Both normal labels and hotkey/hotstring labels can be used.
This is a refinement of FakeRainBrigand's answer. It is used exactly the same:
Hotkey("x", "Foo", "Bar") ; this defines: x:: Foo("Bar")
Changes from the original:
Prevent accidental auto-execute of the handler subroutine by tucking it into the function.
Allowing me to reduce namespace pollution by narrowing the scope of the hotkeys variable from global to static.
Optimizations: fun is looked up only once (using Func()) at hotkey definition time; At invocation time, object lookups reduced four to two by splitting hotkeys into two objects funs and args;
This still relies of course on the _L version of AutoHotKey because of Object notation and variadic arg* syntax.
Hotkey(hk, fun, arg*) {
Static funs := {}, args := {}
funs[hk] := Func(fun), args[hk] := arg
Hotkey, %hk%, Hotkey_Handle
Return
Hotkey_Handle:
funs[A_ThisHotkey].(args[A_ThisHotkey]*)
Return
}
Doing exactly what you want isn't possible in AutoHotkey. This is the closest way I can think of.
Call this file Hotkeys.ahk, and put it in My Documents/AutoHotkey/Lib. Alternatively make a folder called Lib, and put it in the same directory as your main script.
Hotkeys := {}
Hotkey(hk, fun, p*) {
global hotkeys
hotkeys[hk] := {}
hotkeys[hk].fun := fun
hotkeys[hk].p := p
Hotkey, %hk%, HandleHotkey
}
HandleHotkey:
hotkeys[A_ThisHotkey].fun(hotkeys[A_ThisHotkey].p*)
return
Here's an example script that you could use it with.
Hotkey("e", "msgbox", "foobar")
MsgBox(msg) {
msgbox % msg
}
#Include <Hotkeys>
The first parameter is the hotkey, the second is the function to call, and everything after that is passed to the function.
Is this what you are looking for?
#Persistent
#SingleInstance Force
#installKeybdHook
Hotkey, #z, MyLabel
MyLabel:
MsgBox,OK
Return
With newer ahk version you can now use functions as label argument. See https://www.autohotkey.com/docs/commands/Hotkey.htm