How to wrap currently selected text in `` - autohotkey

How can write a hotkey (which works in any editor) to wrap currently selected text in ``
e.g double click "text", it becomes selected, then by pressing key for single `` it
is converted to text
Here is mix of pseudo code and actual code. Text within <> is what I'm not sure of
^<COMMAND FOR PRESSING ` KEY>::
KeyWait Control
<STORE CURRENTLY SELECTED TEXT IN MEMORY>
SendInput `<STORED SELECTED TEXT>'
return

Your approach is pretty good already. Try this:
$`::
clp_tmp := ClipboardAll
send ^c
currently_selected := Clipboard
stringReplace, currently_selected, currently_selected, `r,, All
Clipboard := clp_tmp
sendraw ``%A_Space%
sendraw %currently_selected%
sendraw ``%A_Space%
return
$ is needed because otherwise, sendraw `` would re-trigger this hotkey. The built-in variable clipboard / clipboardAll contains windows' clipboard. Also, you don't need any keywaits. ahk manages concurring modifiers from hotkey triggers by itself. I also suggest using sendraw which will not treat # as the win-button, + as Shift and so on.
script inserts new lines between each line if multiple lines are selected
Weird. When using msgBox, %currently_selected% instead of any send command, the line breaks are displayed correctly... there is obviously some strange formatting going on, I fixed it by simply removing all Carriage Returns (CR) (`r) from the string which does not change the selected text at all.
The given solution works for my keyboard which is German. This might be different for other keyboard layouts. For me, the %A_Space% in sendraw ``%A_Space% (at least in the second one) is needed, because if you state sendraw `` (a literal space character in the end), AHK will ignore it. You could also put all three sends in one line like
sendraw `` %currently_selected%``%A_Space%
Another solution might be
sendInput ````{BS}%currently_selected%````{BS}
or just simply
sendRaw `%currently_selected%`
Finally: If you wanted to make everything easier, make use of the #EscapeChar command and change the delimiter from ` to \ or sth. similar.

Related

Autohotkey: How to correctly write text, enclosed within brackets, to text files?

I need Autohotkey (AHK) to insert text, enclosed within brackets, into my text files. However, my AHK code results in erroneous text input depending on using the code on text files opened in Notepad3 or opened in Emacs. My use of brackets are obviously wrong relative to the AHK syntax.
My minimum working example:
::ttt::
; define variables
myString = abcdf
myFile = C:\Users\myUser\notes\myFile.tex
; write variables into current file
SendInput, <<%myString%>> {enter}
SendInput, [[%myFile%]]
return
The results I need should look like this:
<< abcde>>
[[C:\Users\myUser\notes\myFile.tex]]
Emacs When using this script on a text file opened with Emacs, the result looks like this:
<< abcde>>
[[C:\Users\myUser\notes\myFile.tex]]]
The first line written the way I need it, while the second line has got an extra "]" added in the end.
Notepad3 When using this script on a text file opened with Notepad3, the result looks like this:
<< abcde>>
[[C:\Users\myUser\notes\myFile.tex]]< /abcde>
The first line is written the way I need it, while the second line has got a variant of the first line added in the end, though with an "/" added.
How can I modify my code so the text input will look correct both in Notpad3 and in Emacs?
Is the space in << abcde>> necessary? The definition of your variable doesn't seem to reflect that.
Nonetheless, the issue likely stems from the fact that these keys are being inputted instead of sending the text directly. I find that it's usually best to send strings as text if you wish to avoid other hotkeys from potentially disturbing your output. Try this adjustment:
SendInput {text}<< %myString%>>
SendInput {enter}
SendInput {text}[[%myFile%]]

How do I delete the current line using AutoHotkey?

Using an AutoHotkey script I'd like to set the keyboard command Ctrl+D to delete the current line in any active Windows app.
How?
^d::Send {Home}{ShiftDown}{End}{Right}{ShiftUp}{Del}
Might not work in all edge cases, but passes some very basic testing in Notepad. =~)
HaveSpacesuit's answer works but after using it for a while I realized it deletes the active line and sometimes re-positions the spacing of the line below.
This led me to rethink his solution. Instead of going from the front of the line to the back, I tried going from back to front. This solved the re-positioning issue.
SendInput {End}
SendInput +{Home}
SendInput ^+{Left}
SendInput {Delete}
There is still a small problem though. If the cursor is on an empty line, with more empty lines above, then all empty lines get deleted.
I don't know a key combo to replace ^+{Left} that doesn't have this behavior so I had to write a more comprehensive solution.
^d:: DeleteCurrentLine()
DeleteCurrentLine() {
SendInput {End}
SendInput +{Home}
If get_SelectedText() = "" {
; On an empty line.
SendInput {Delete}
} Else {
SendInput ^+{Left}
SendInput {Delete}
}
}
get_SelectedText() {
; See if selection can be captured without using the clipboard.
WinActive("A")
ControlGetFocus ctrl
ControlGet selectedText, Selected,, %ctrl%
;If not, use the clipboard as a fallback.
If (selectedText = "") {
originalClipboard := ClipboardAll ; Store current clipboard.
Clipboard := ""
SendInput ^c
ClipWait .2
selectedText := ClipBoard
ClipBoard := originalClipboard
}
Return selectedText
}
As far as I can tell this produces no unexpected behaviour.
However, be careful if you're using a clipboard manager as this script uses the clipboard, if necessary, as an intermediary to get the selected text. This will impact clipboard manager history.
In case you run into problems where you need different behaviours for different programs, you can "duplicate" your ^d command for specific programs like this:
SetTitleMatchMode, 2 ; Makes the #IfWinActive name searching flexible
^d::Send {Home}{ShiftDown}{End}{Right}{ShiftUp}{Del} ; Generic response to ^d.
#IfWinActive, Gmail ; Gmail specific response
^d::Send {Home}{ShiftDown}{End}{Right}{ShiftUp}{Del} ; adapt this line for gmail
#IfWinActive ; End of Gmail's specific response to ^d
#IfWinActive, Excel ; Excel specific response.
^d::Send {Home}{ShiftDown}{End}{Right}{ShiftUp}{Del} ; adapt this line for Excel
#IfWinActive ; End of Excel's specific response to ^d
This way your ^d command will work differently in Excel and Gmail.
I have a simple way to solve the repositioning issue. Without using the clipboard.
The repositioning issue is due to the need to handle 2 separate cases.
if there's existing text in a line,
we want to select them all, and delete the text (backspace 1)
and backspace one more time to delete the empty line (backspace 2)
if it's a blank line,
we want to delete the empty line (backspace 1)
To cater for both of above cases, I introduced a dummy character.
This will make sure BOTH cases will act the same way.
So doing backspace 2 times, will result in the same transformation each time.
Simply,
; enable delete line shortcut
^d::
Send {Home}
Send {Shift Down}{End}{Shift Up}
Send d
Send {Backspace 2}
Send {down}
return
Disadvantage with this approach,
the dummy character "d" will appear when you undo. Not a bad tradeoff since I don't undo delete lines very often.

Insert Tab character into Word

I'm trying to create a script, which will insert Tab character into Word.
Quick note: I've also tested it in OpenOffice. So if you haven't Word, you may test it in OpenOffice or, probably, LibreOffice Writer.
If you are familiar with Word, you know that if you press Tab key on a blank line, you get the Word-like indentation, instead of inserting real Tab char.
Here is attempt to fix it:
$Tab::
old := ClipboardAll
Sleep, 1000 ; Just for testing. If I remove this line, the error still
; occurs, but much more randomly.
Clipboard := " " ; Tab character
ClipWait
SendInput, ^v
KeyWait, Tab
Clipboard := old
return
The problem is, that sometimes (when I press Tab quickly), it is inserted an old content of the clipboard, instead of Tab.
I've tried to use ClipWait, KeyWait, Sleep, InstallKeybdHook in different combinations.
Maybe someone knows what's the problem here and how it can be solved?
Sends tab without triggering indent in word
SetTitleMatchMode 2
#IfWinActive Microsoft Word
$tab:: sendinput .{tab}{left}{backspace}{right}
If I'm understanding you correctly, a better solution might be to turn off this feature with Options > Proofing > Autoformat as you type > Set left and first indent with tabs and backspaces (see here)

SendInput %userInput% causes my computer to malfunction oddly

SendInput %userInput% causes my computer to do very weird stuff. Sometimes it logs off, sometimes my arrows of the keyboard get disabled, sometimes it runs cmd in windows an infinite times...
UPDATE:
this is the thing that gets inputed in the command line and runs:
runas /user:administrator cmd
UPDATE:
I think I almost got the problem, as such I edited the question to leave out what I deem to be irrelevant now.
When SendInput is happening, and the user is still inputting data in the keyboard, such as pressing the win-key, then this can cause the system to log off because win-key + l is a shortcut for that. Likewise must be for all the other things that are happening. Another observation is that SendInput skips certain characters, like {enter} etc. It only processes them at the end, when all the regular characters are put into place. I notice that at the end, SendInput is still busy doing stuff, perhaps some exotic characters it delayed till the end. Because the user think the output is complete, he ends up pressing the shortcut key again which in combination with the current sendInput is causing the system to crash.
UPDATE:
It also goes bezerk if there is a "!" to be send with SendInput.
This is one string I pasted to the copyboard:
dsjkfhjdsfsjdh!!!!!!!!!!!####################$$$$$$$$$$$%%%%%%%%%^^^^^^^^^^^^^&&&&&&&&&&&&&*****(((((((((())))))))))))____++++++++++++++++=======------------000000000000000099999988888.
But the output is WITHOUT the exclamation marks. Like this:
dsjkfhjdsfsjdh#######$$$$$$$$$$%%%%%%%%%&&&&&&&&&&&&*****(((((((((())))))))))))____+======------------000000000000000099999988888.
Why is that? Are there any other characters? Exclamation marks are important I feel, and I don't want to remove them. Are there any workarounds?
UPDATE:
It is more complicated than that. When I copy paste the above characters WITHOUT the exclamation marks, it still does weird stuff.
Here is some of the code that eventually userInput combines and sends away with SendInput:
StringReplace, contents, save_selection, ``, ````, All ; Do this replacement first to avoid interfering with the others below.
StringReplace, contents, contents, `r`n, %A_SPACE%, All ; Using `r works better than `n in MS Word, etc.
StringReplace, contents, contents, `;, ```;, All
;* loc_title origanally contains browser specification. Remove it.
StringGetPos, pos_delim, loc_title, - , R
length := StrLen(loc_title)
count := length - pos_delim
StringTrimRight, loc_title, loc_title, count
You could use sendraw instead of sendinput.
Here is what the docs say:
Raw mode: The SendRaw command interprets all characters literally
rather than translating {Enter} to an ENTER keystroke, ^c to
Control-C, etc. However, the normal rules for escape sequences,
variable references and expressions still apply since these are
processed before the command executes. To use raw mode with SendInput,
SendPlay, or SendEvent, write {Raw} as the first item in the string;
for example: SendInput {Raw}abc.
Then you don't have to worry about the ! or other control modifiers.
The reason that the exclamation mark character is an issue is because SendInput treats it as a code to press the Alt key.
There are several similar codes:
^ = Ctrl
+ = Shift
# = Windows key
You can find the others listed in the documentation for SendInput.
It seems like you want to send the raw text and not have SendInput look for these codes. You should be able to put {Raw} at the beginning of the userinput variable and it will ignore any codes in the rest of the characters.
If it is typing too slowly, you could put SetKeyDelay,-1 in your script to remove the key sending delay.
A good workaround that I found was to avoid SendInput altogether. Rather use the clipboard to copy the string inside, to then paste it on your screen. It works flawlessly, and is a billion times faster. Why would a person utilize SendInput in the first place? However, the actual question still is standing, why does SendInput behave so strangely? What is inside that string: %userInput% that causes my system to crash? How can I find out?

can somebody help to write a autohotkey script for select all the pasted content after paste?

the autohotkey script should do follows:
after I tap the hotkey,
it will paste the content from the clipboard, then immediately select all the pasted content?
I write a script as follows:
^+p::
clipvar:=Clipboard
num:=strlen(clipvar)
send ^v
send +{left %num%}
return
This script works.
But the selecting process is too slow!!!
Can somebody write a better script?
SendMode, Input optionally combined with SetBatchLines, -1 and variations of SetKeyDelay can accelerate key sequences.
However, the selection of large texts will still take some time, and slow machines may slow it down even further.
Here's another approach which - in terms of sending keystrokes - is more efficient:
^+p::
oldCaretX := A_CaretX
oldCaretY := A_CaretY
Send, ^v
WaitForCaretChange()
MouseGetPos, mX, mY
MouseClickDrag, Left, %A_CaretX%, %A_CaretY%, %oldCaretX%, %oldCaretY%
MouseMove, %mX%, %mY%
return
WaitForCaretChange() {
oldCaretX := A_CaretX
oldCaretY := A_CaretY
while(A_CaretX = oldCaretX && A_CaretY = oldCaretY) {
Sleep, 15
}
}
This code relies on the window to expose the caret position, which unfortunately, not every window does. It remembers the caret position before the paste and selects text up to the old position after pasting new text; this should be equal to selecting all the newly inserted text. If you're only working with editors that expose their caret position, I recommend you go with this one since it's faster. Otherwise, you can still think about using both your method and this one, depending on the window and/or the text length.