Trigger « if last char is whitespace and » if not - autohotkey

I would like to print either « or » whenever I press Shift+Numpad7.
I know how to set up two different scripts: e.g. +Numpad7::« and +Numpad8::», but is there a way to have the output depend on whether the character before the caret is whitespace or not?
I.e., so I could type something like «Hello», where both times I pressed Shift+Numpad7

Shifting numpad numbers can have unintended overrides (like on my system) so I used Ctrl Numpad7, but YMMV:
^Numpad7::
oldClip := Clipboard ; save current clipboard
Send, +{Left}^c{right} ; select char to the left and copy to clipboard
ClipWait
lchar := Clipboard = " " ? "«" : "»" ; check if space or not
Send, %lchar% ; send lchar
clipboard := oldClip ; restore original clipboard
ClipWait
return
Btw, since unicode and ansi vers of AHK handle that character differently, on some systems you may get an extra preceding character in the output. Just change the last Send to:
Send, % SubStr(lchar, 0) ; send last character of lchar
And let us know what version worked for you.

Related

AHK: Copying non-adjacent words & joining them together

As the title already says, I would like to copy and join any number of (mostly) non-adjacent words in any app (Web browser, E-Mail, MS Word, Editor, Evernote etc.). That is, any words that I (mouse-)select and copy hitting the 5-key while I simultaneously hold down the F4 key (but actually any hotkeys and modifiers that don't interfere with their normal functioning and which are also both easily and simultaneously reachable with the left hand would do).
This is what I came up with with my limited AHK-skills. The clipboard-part works, but for all I know not the global-variable (and therefore not the word-joining) nor the F4 Down & 5-hotkey-combo (without Down or without & 5 it technically would, though):
global MyString := "" ; make string global to keep contents between {5}-key presses
~F4 Down & 5:: ; copy any (non-adjacent) words with {5}-key as long as I hold down {F4}-key
clipboard := ""
Sleep 100
Send ^c
ClipWait, 1
MyString := MyString Trim(clipboard) ; append lastly copied word to any words copied before (while holding down {F4})
~F4 Up::
MsgBox, %MyString% ; show final string consisting of ALL copied words separated by a space
MyString := "" ; reset string
Return
Ultimately, I would like to copy %MyString% to the clipboard as one single long string rather than show it in a message box. I think I'm already near to the solution.
Can you solve it?
You're never ending the first hotkey's execution block, so its execution bleeds into the hotkey below and your MyString gets reset every time.
Also if you have an down/up hotkey pair, you don't specify the first down, only the up.
Also, there's no need to make your variable super-global.
Fixed script:
~F4 & 5::
Clipboard := ""
Sleep, 100
Send, ^c
ClipWait, 1
MyString := MyString " " Trim(Clipboard)
return
~F4 Up::
MsgBox, % MyString
MyString := ""
return
Pretty cool idea for a script btw. I might use something like this myself.

AutoHotKey String substitution

I am writing a small AHK script that defines a few simple HotStrings.
The concept is that when I type "Build QA1", the appropriate text associated with that HotString appears.
No problem there ...quite simple ...the issue is that I wish to have the string associated with the HotString appear as part of the substitute text ...in the example below, the results should be
Build QA1
Now is the time for all good men
The script below accomplishes this and works fine ...it does exactly what I ask, HOWEVER, when I enter the HotString text and hit Enter or Tab or whatever initiates the HotString, that first line of text ( Build QA1 ) will "flash" on the screen as it is being substituted ...it makes it obvious that a HotString substitution is in operation ...
I would ideally like the HotString ( Build QA1 ) to remain as a part of the
substitute text without being replaced ...is this possible or is there a way to avoid the "flash" as that string is substituted ?
::Build QA1::
send, Build QA1
send, {enter}
send, Now is the time for all good men
return
Try it this way:
::b0::Build QA1:: ; automatic backspacing is not done to erase the abbreviation you type.
ClipSaved := ClipboardAll ; save the entire clipboard to the variable ClipSaved
clipboard := "" ; empty the clipboard (start off empty to allow ClipWait to detect when the new text has arrived
clipboard = ; copy this text:
(
Now is the time for all good men
)
ClipWait, 1 ; wait for the clipboard to contain data.
if (!ErrorLevel) ; if NOT ErrorLevel ClipWait found data on the clipboard
Send ^v ; paste the text
Sleep, 300 ; don't change clipboard while pasting! (Sleep > 0)
clipboard := ClipSaved ; restore original clipboard
VarSetCapacity(ClipSaved, 0) ; free the memory of the variable ClipSaved
return
See Hotstrings Options, Clipboard and ClipboardAll in the documentation.

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)

Creating text macro system on AHK

I am quite new on AutoHotKey, and I'm trying to make my macro system. Currently I have a system that looks like this:
I have text variables
hi =
(
Hello,
Some more text
)
a Hotstring
::\hi::
Macro(hi)
return
And a function Macro:
Macro(text)
{
ClipSaved := ClipboardAll ; save clipboard
clipboard := text
ClipWait
Sleep, 150
Send, ^v
clipboard := ClipSaved ; restore original clipboard
return
}
The reason for using a function with clipboard is because long text blocks tend to have a delay until they are printed out, an issue that does not occur with the function.
I've found a concept called dynamic hotstrings, and I think I can somehow implement it so that I wouldn't have to write the second displayed block for every text field, but instead have a one hotstring that would understand that if it's my input starts with \ and there is a variable in the script under the name x that follows it, it should execute Macro(x), but I have never found any similar examples.
Could you provide me with a code sample or give any leads to what I should check out?
There are several dynamic Hotstring AutoHotkey functions, but this is probably the one you want to use Hotstring by menixator
So you need to download the hotstring.ahk and #include it as in the examples.
#SingleInstance, force
#include Hotstring.ahk
hi=
(
Hello,
Some more text
)
bye=
(
So long,
Some more text
)
Hotstring("/hi", "Paste")
Hotstring("/bye", "Paste")
return
Paste:
text:=Trim($,"/") ; we need to get rid of the leading /
text:=% %text% ; and need to dereference it
Macro(text)
Return
Macro(text)
{
ClipSaved := ClipboardAll ; save clipboard
Clipboard := text
ClipWait
Sleep, 150
Send, ^v
clipboard := ClipSaved ; restore original clipboard
return
}
There are some more elegant ways to do it, especially with the variables, you could store them in a global object (associative array) for example, but this should get you going.

Selecting the last N characters before caret with AutoHotkey

Is there a way to select last N symbols with autohotkey?
I'm making a function which replicates Sublime Text's duplicate function (Ctrl+Shift+D). I want text to be selected before it is duplicated via SendInput ^C{right}^V
Technically, I could make something like:
selectBefore(n){
Loop, %n% {
SendInput +{Left}
}
}
But that has shown poor performance.
Another method would be to play with Shift+Home. For example, Send +{Home}, then count the number of symbols selected, then Send {Left} and Send +{Home} again, and so on until reaching the length of the duplicated string.
I don't see any better alternatives.
Is there a good, basic way to select N symbols before caret?
From what I read about ST2 (thank you for making me aware) is that ^+d either copies the selected text or if nothing is selected, copies the whole line.
Would this work?
TempCB = %ClipBoard% ; Park clipboard (text) content, Other content (format, images, etc.) will be lost.
ClipBoard = ; Clear clipboard
Send, ^c ; Grab selected text
Sleep, 100 ; Wait 0.1 seconds for clipboard (clipboard will not get filled if nothing is selected)
if (Clipboard = "") ; Nothing selected, thus copy whole line
{
Send, {Home}+{End}^c ; Select line and copy to clipbard
}
MoveBack := StrLen(ClipBoard)
MoveFwd := MoveBack
MoveBack++ ; Move one step back further back due to earlier step {right}
Send, {Right}{Left}^v{Right}{left %Moveback%}+{Right %MoveFwd%} ; Go to end of selected text (in MS notepad this is will jump over the first next char., thus a jump back as well), add a space and paste.
ClipBoard = %TempCB% ; Restore (text part) of previous clipboard content.
Return
I tested this in MS Notepad, other editors might behave differently (especially around jumping towards the end of the selected text).
The script now copies and pastes the selected text and highlights the newly pasted text.