Is it possible to use AutoHotKey to facilitate LaTeX document authoring? In which ways? Is there any off the shelf AutoHotKey script for this purpose?
5 Answers
In general, I'm very inaccurate when typing things like "\", "{", "$" etc. It's especially cumbersome to navigate text with the Left, Right, Up and Down keys and you do all of these things constantly when typing tex.
I haven't spent much time learning how to write scripts with AHK, but I did write a few things to make a few shortcuts and to save the amount of which my wrists have to bend while typing tex.
For example, these I wrote for my preference.
^space:: Send {{}{}}{Left}
CapsLock:: Send {$}{$}{Left}
^9:: Send {(}{)}{Left}
^l:: Send {Right}
^j:: Send {Left}
^i:: Send {Up}
^m:: Send {Down}
^k:: Send {Down}
+^l:: Send +{Right}
+^j:: Send +{Left}
+^i:: Send +{Up}
+^m:: Send +{Down}
+^k:: Send +{Down}
^f:: Send {^}
^p:: Send \pause{Enter}{Enter}
^h:: Send \
^n:: Send \{{}\{}}{Left}{Left}
^;:: Send {End}
^Backspace:: Send {Delete}
^=:: Send {&}={&}
I came here because I too was wondering if someone with professional knowledge of AHK had written something useful for writing tex.
Here is a script I created over time and improve occasionally for my personal use.
Features:
Instant completion for single brackets
(
,[
,{
. You can also delete surrounding characters with[Shift] + [Backspace]
As requested by Mr.Robot, you can now jump between bullets, which are included in some of the autocompletion commands. This can be done via
[Ctrl] + Space
- A lot of autocompletions, I will not list here. Feel free to have a look at the code. It is mostly commented.
Code (new version):
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
#a::Suspend, Toggle ; pause script
#Hotstring EndChars `t ; [Tab] triggers Hotstrings
; Reset Hotstring for CTRL+Backspace and CTRL+A (otherwise hostrings won't trigger)
Ctrl & Backspace::
SendInput ^`b
Hotstring("Reset")
Return
Ctrl & a::
SendInput ^a
Hotstring("Reset")
Return
; :o: omit ending character
; :?: triggers hotstring even between characters
; :c: case sensitive
; :*: no trigger
; ^ ctrl
; + shift
; <! left alt
; /// 1. BRACKETS //////////////////////////////////////////////////////////////////////////////////
; instant complete (), [], {}
:o*?:(::(){Left}
:o*?:[::[]{Left}
:o*?:{::{{}{}}{Left}
:o:abs::\left| \right| {Left 9} ; Absolut Value: \left| \right|
:o:abs2::\left| \right|{^}2 {Left 11} ; Absolut Value: \left| \right|
^4:: Send $${Left} ; $$
; \left* \right*
; (instruction: place the cursor between the opening and the closing symbol, then hit ctrl+7)
^7::
SendInput, {Left}\left{Right} \right{Left 7}
Return
; put brackets around selection
; (warning: this might not work in some applications!)
^8::
ClipBackup := ClipboardAll
clipboard := ""
SendInput, ^x
SendInput, (){Left}
SendInput, ^v
SendInput, {Right}
Sleep 1000
Clipboard := ClipBackup
Return
^9::
ClipBackup := ClipboardAll
clipboard := ""
SendInput, ^x
SendInput, []{Left}
SendInput, ^v
SendInput, {Right}
Sleep 1000
Clipboard := ClipBackup
Return
^0::
ClipBackup := ClipboardAll
clipboard := ""
SendInput, ^x
SendInput, {{}{}}{Left}
SendInput, ^v
SendInput, {Right}
Sleep 1000
Clipboard := ClipBackup
Return
; /// 2. OTHER /////////////////////////////////////////////////////////////////////////////////////
; Jump to first occurance of • in the current line. (Continues search in the next line.)
^Space::
ClipBackup := ClipboardAll
clipboard := ""
SendInput, {Home}+{End}
SendInput, ^c
Sleep 50 ; increase this number, if it doesn't work
SearchedText := clipboard
; MsgBox, %SearchedText%
StringGetPos, pos, SearchedText, •
if (pos >= 0)
; MsgBox, %Target% was found at %pos%.
SendInput, {Home}{Right %pos%}+{Right}
else
SendInput, {Down}
SendInput, {Home}+{End}
SendInput, ^c
Sleep 50 ; increase this number, if it doesn't work
SearchedText := clipboard
; MsgBox, %SearchedText%
StringGetPos, pos, SearchedText, •
if (pos >= 0)
; MsgBox, %Target% was found at %pos%.
SendInput, {Home}{Right %pos%}+{Right}
else
SendInput, {End}
Clipboard := ClipBackup
Return
; Comfort
+Backspace:: Send,{BackSpace}{Delete} ; delete surrounding characters
^Enter:: Send,{End}{Enter} ; instant create new line, even from within words.
; Shift+Space: escape to the right and insert a space
+Space::
SendInput, {Right}{Space}
Return
; Whitespaces
:o:qd::\quad
:o:qq::\qquad
:o?: ::\{Space}{Space}
:o?:,::\,
:o:clp::\clearpage
; Environments
:o:bg::
InputBox, OutputVar, Environment,,, 200, 120,,,,, align
SendInput, \begin{{}%OutputVar%{}}`r`r\end{{}%OutputVar%{}}{Up}`t
Return
:o:bga::\begin{{}align{}}`r`r\end{{}align{}}{Up}`t ; align
:o:bgas::\begin{{}align{}}\begin{{}split{}}`r`r\end{{}split{}}\end{{}align{}}{Up}`t ; align with split
:o:itmz::\begin{{}itemize{}}`r{Home}`r\end{{}itemize{}}{Up}`t\item{Space} ; align
:o:itm::\item{Space}
; /// 3. TEXT FORMATTING ///////////////////////////////////////////////////////////////////////////
; Sections
:o:sc::\section{{}•{}}{Left}+{Left} ; \section
:o:ss::\subsection{{}•{}}{Left}+{Left} ; \subsection
:o:sss::\subsubsection*{{}•{}}{Left}+{Left} ; \subsubsection*
; Text
:o:tx::\text{{}•{}}{Left}+{Left} ; \text
:o:tbf::\textbf{{}•{}}{Left}+{Left} ; \textbf
:o:tit::\textit{{}•{}}{Left}+{Left} ; \textit
:o:em::\emph{{}•{}}{Left}+{Left} ; \emph
:o:sf::\textsf{{}•{}}{Left}+{Left} ; sans serif
:o:sc::\textsc{{}•{}}{Left}+{Left} ; small caps
:o:bf::\mathbf{{}•{}}{Left}+{Left} ; \mathbf
:o:cal::\mathcal{{}•{}}{Left}+{Left} ; \mathcal
:o:scr::\mathscr{{}•{}}{Left}+{Left} ; \mathscr
:o:bb::\mathbb{{}•{}}{Left}+{Left} ; \mathbb
:o:bbm::\mathbbm{{}•{}}{Left}+{Left} ; \mathbbm
; /// 4. MATH STUFF ////////////////////////////////////////////////////////////////////////////////
; Common Operations
:o:fr::\frac{Space} ; \frac
:o:fra::\frac{{}•{}}{{}•{}}{Left 4}+{Left} ; \frac{•}{•}
:o:tfr::\tfrac{Space} ; \tfrac
:o:su::\sum{Space} ; \sum
:o:sum::\sum_{{}•{}}{^}{{}•{}}{Left 5}+{Left} ; \sum_{•}^{•}
:o:pro::\prod_{{}•{}}{^}{{}•{}}{Left 5}+{Left} ; \prod_{•}^{•}
:o:in::\int{Space} ; \int
:o:oin::\oint{Space} ; \oint
:o:int::\int_{{}•{}}{^}{{}•{}}{Left 5}+{Left} ; \int_{•}^{•}
:o:sq::\sqrt{{}•{}}{Left}+{Left} ; \sqrt{ } \sqrt{}
; alt+^ instantly yields ^{•}
<!^::
SendInput, {^}{{}•{}}{Left}+{Left}
Return
; Relations
:o:<=>::\Leftrightarrow ; <=>
:o:=>::\Rightarrow ; =>
:o:<=::\Leftarrow ; <=
:o?:-->::\longrightarrow ; -->
:o:->::\rightarrow ; ->
:o:!=::\overset{{}{!}{}}{{}={}}{Space} ; ! over =
:o?:=::\ =\{Space}
:o:eq::\ \equiv\{Space}
:o:~::\sim
; Other / Symbols
:o:cnc::\cancel{{}•{}}{Left}+{Left} ; \cancel{}
:o:del::\partial
:o:dell::\frac{{}\partial{}}{{}\partial •{}}{Left}+{Left}
:o:ovs::\overset{{}•{}}{{}•{}}{Left 4}+{Left}
:o:inf::\infty
:o:°::{^}\circ
:o:cd::\cdot{Space}
:o:dg::{^}\dagger
:o:dd::\text{{}d{}}•+{Left} ; used for differentials e.g. dx
; /// 5. MATRICES //////////////////////////////////////////////////////////////////////////////////
; Matrices
:o:pm2::\begin{{}pmatrix{}}`r• & • \\`r• & • \\`r\end{{}pmatrix{}}{Left 13}{Up}`t{Left}{Up}`t+{Right}
:o:bm2::\begin{{}bmatrix{}}`r• & • \\`r• & • \\`r\end{{}bmatrix{}}{Left 13}{Up}`t{Left}{Up}`t+{Right}
:o:pm3::\begin{{}pmatrix{}}`r• & • & • \\`r• & • & • \\`r• & • & • \\`r\end{{}pmatrix{}}{Left 13}{Up}`t{Left}{Up}`t{Left}{Up}`t+{Right}
:o:bm3::\begin{{}bmatrix{}}`r• & • & • \\`r• & • & • \\`r• & • & • \\`r\end{{}bmatrix{}}{Left 13}{Up}`t{Left}{Up}`t{Left}{Up}`t+{Right}
:o:pm4::\begin{{}pmatrix{}}`r• & • & • & • \\`r• & • & • & • \\`r• & • & • & • \\`r• & • & • & • \\`r\end{{}pmatrix{}}{Left 13}{Up}`t{Left}{Up}`t{Left}{Up}`t{Left}{Up}`t+{Right}
:o:bm4::\begin{{}bmatrix{}}`r0 & 0 & 0 & 0 \\`r0 & 0 & 0 & 0 \\`r0 & 0 & 0 & 0 \\`r0 & 0 & 0 & 0 \\`r\end{{}bmatrix{}}{Left 13}{Up}`t{Left}{Up}`t{Left}{Up}`t{Left}{Up}`t+{Right}
; LGS
:o:lgs::\begin{{}matrix{}}`r• &=& • \\`r• &=& • \\`r\end{{}matrix{}}{Left 12}{Up}`t{Left}{Up}`t+{Right}
; Vectors
:o:v2::\begin{{}pmatrix{}}`r• \\`r• \\`r\end{{}pmatrix{}}{Left 13}{Up}`t{Left}{Up}`t+{Right}
:o:v3::\begin{{}pmatrix{}}`r• \\`r• \\`r• \\`r\end{{}pmatrix{}}{Left 13}{Up}`t{Left}{Up}`t{Left}{Up}`t+{Right}
:o:v4::\begin{{}pmatrix{}}`r• \\`r• \\`r• \\`r• \\`r\end{{}pmatrix{}}{Left 13}{Up}`t{Left}{Up}`t{Left}{Up}`t{Left}{Up}`t+{Right}
; /// 6. GREEK /////////////////////////////////////////////////////////////////////////////////////
:o:a::\alpha
:o:b::\beta
:o:c::\chi
:oc:d::\delta
:oc:D::\Delta
:o:e::\epsilon
:o:ve::\varepsilon
:oc:f::\phi
:oc:F::\Phi
:o:vf::\varphi
:oc:g::\gamma
:oc:G::\Gamma
:o:h::\eta
:o:i::\iota
:o:k::\kappa
:oc:l::\lambda
:oc:L::\Lambda
:o:m::\mu
:o:n::\nu
:oc:p::\pi
:oc:P::\Pi
:oc:q::\theta
:oc:Q::\Theta
:o:vq::\vartheta
:o:r::\rho
:oc:s::\sigma
:oc:S::\Sigma
:o:t::\tau
:oc:u::\upsilon
:oc:U::\Upsilon
:o:v::\digamma
:oc:w::\omega
:oc:W::\Omega
:oc:x::\xi
:oc:X::\Xi
:oc:y::\psi
:oc:Y::\Psi
:o:z::\zeta
Old version from my original answer:
; /// HEAD /////////////////////////////////////////////////////////////////////
; :o: omit ending character
; :?: triggers hotstring even between characters
; :c: case sensitive
; ^ CTRL
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
#a::Suspend, Toggle ; toggle suspend script
#Hotstring EndChars `t ; [Tab] triggers Hotstrings
; Reset Hotstring for CTRL+Backspace and CTRL+A (otherwise hostrings won't trigger)
Ctrl & Backspace::
SendInput ^`b
Hotstring("Reset")
Return
Ctrl & a::
SendInput ^a
Hotstring("Reset")
Return
; /// COMFORT //////////////////////////////////////////////////////////////////
+Backspace:: Send,{BackSpace}{Delete} ; delete surrounding characters
^Enter:: Send,{End}{Enter} ; instant jump to new line, even from between characters
; /// BRACKETS /////////////////////////////////////////////////////////////////
; instant complete std brackets
:o*?:(::(){Left}
:o*?:[::[]{Left}
:o*?:{::{{}{}}{Left}
; left right brackets
^8:: Send \left( \right) {Left 9} ; \left( \right)
^9:: Send \left[ \right] {Left 9} ; \left[ \right]
^<:: Send \left< \right> {Left 9} ; \left< \right>
^7:: Send \left\{{} \right\{}} {Left 10} ; \left{ \right}
^4:: Send $${Left} ; $$
:o:abs::\left| \right| {Left 9} ; Absolut Value: \left| \right|
; /// GENERAL SHORTS ///////////////////////////////////////////////////////////
:o:baln::\begin{{}align{}}`r`r\end{{}align{}}{Up}`t ; align
:o:bgas::\begin{{}align{}}\begin{{}split{}}`r`r\end{{}split{}}\end{{}align{}}{Up}`t ; align with split
:o:sc::\section{{}•{}}{Left}+{Left} ; \section
:o:ss::\subsection{{}•{}}{Left}+{Left} ; \subsection
:o:clp::\clearpage
; Text
:o:tx::\text{{}•{}}{Left}+{Left} ; \text
:o:tbf::\textbf{{}•{}}{Left}+{Left} ; \textbf
:o:tit::\textit{{}•{}}{Left}+{Left} ; \textit
:o:em::\emph{{}•{}}{Left}+{Left} ; \emph
:o:bf::\mathbf{{}•{}}{Left}+{Left} ; \mathbf
:o:cal::\mathcal{{}•{}}{Left}+{Left} ; \mathcal
:o:scr::\mathscr{{}•{}}{Left}+{Left} ; \mathscr
:o:bb::\mathbb{{}•{}}{Left}+{Left} ; \mathbb
:o:bbm::\mathbbm{{}•{}}{Left}+{Left} ; \mathbbm
; Operations, Symbols, Relations
:o:fra::\frac{Space} ; frac
:o:sum::\sum_{{}•{}}{^}{{}•{}}{Left 5}+{Left} ; \sum
:o:pro::\prod_{{}•{}}{^}{{}•{}}{Left 5}+{Left} ; \prod
:o:int::\int_{{}•{}}{^}{{}•{}}{Left 5}+{Left} ; \int
:o:del::\partial
:o:ovs::\overset
:o:inf::\infty
:o:°::{^}\circ
:o:cd::\cdot
:o:dg::{^}\dagger
:o:dd::\text{{}d{}}
:o:qd::\quad
:o:qq::\qquad
:o:<=>::\Leftrightarrow
:o:=>::\Rightarrow
:o:->::\rightarrow
:o:!=::\overset{{}{!}{}}{{}={}}
:o?:=::\ =\{Space}
:o:eq::\ \equiv\{Space}
:o:~::\sim
; /// MATRICES & VECTORS ///////////////////////////////////////////////////////
; Matrices
:o:pm2::\begin{{}pmatrix{}}`r0 & 0 \\`r0 & 0 \\`r\end{{}pmatrix{}}{Left 13}{Up}`t{Left}{Up}`t
:o:bm2::\begin{{}bmatrix{}}`r0 & 0 \\`r0 & 0 \\`r\end{{}bmatrix{}}{Left 13}{Up}`t{Left}{Up}`t
:o:pm3::\begin{{}pmatrix{}}`r0 & 0 & 0 \\`r0 & 0 & 0 \\`r0 & 0 & 0 \\`r\end{{}pmatrix{}}{Left 13}{Up}`t{Left}{Up}`t{Left}{Up}`t
:o:bm3::\begin{{}bmatrix{}}`r0 & 0 & 0 \\`r0 & 0 & 0 \\`r0 & 0 & 0 \\`r\end{{}bmatrix{}}{Left 13}{Up}`t{Left}{Up}`t{Left}{Up}`t
:o:pm4::\begin{{}pmatrix{}}`r0 & 0 & 0 & 0 \\`r0 & 0 & 0 & 0 \\`r0 & 0 & 0 & 0 \\`r0 & 0 & 0 & 0 \\`r\end{{}pmatrix{}}{Left 13}{Up}`t{Left}{Up}`t{Left}{Up}`t{Left}{Up}`t
:o:bm4::\begin{{}bmatrix{}}`r0 & 0 & 0 & 0 \\`r0 & 0 & 0 & 0 \\`r0 & 0 & 0 & 0 \\`r0 & 0 & 0 & 0 \\`r\end{{}bmatrix{}}{Left 13}{Up}`t{Left}{Up}`t{Left}{Up}`t{Left}{Up}`t
; LGS
:o:lgs::\begin{{}cases{}}\;`r\begin{{}matrix{}}`rf & = & a & b \\`rf & = & c & d \\`r\end{{}matrix{}}`r\end{{}cases{}}{Left 11}{Up 2}`t{Left}{Up}`t
; Vectors
:o:v2::\begin{{}pmatrix{}}`r0 \\`r0 \\`r\end{{}pmatrix{}}{Left 13}{Up}`t{Left}{Up}`t
:o:v3::\begin{{}pmatrix{}}`r0 \\`r0 \\`r0 \\`r\end{{}pmatrix{}}{Left 13}{Up}`t{Left}{Up}`t{Left}{Up}`t
:o:v4::\begin{{}pmatrix{}}`r0 \\`r0 \\`r0 \\`r0 \\`r\end{{}pmatrix{}}{Left 13}{Up}`t{Left}{Up}`t{Left}{Up}`t{Left}{Up}`t
; /// GREEK ////////////////////////////////////////////////////////////////////
:o:a::\alpha
:o:b::\beta
:o:c::\chi
:oc:d::\delta
:oc:D::\Delta
:o:e::\epsilon
:o:ve::\varepsilon
:oc:f::\phi
:oc:F::\Phi
:o:vf::\varphi
:oc:g::\gamma
:oc:G::\Gamma
:o:h::\eta
:o:i::\iota
:o:k::\kappa
:oc:l::\lambda
:oc:L::\Lambda
:o:m::\mu
:o:n::\nu
:oc:p::\pi
:oc:P::\Pi
:oc:q::\theta
:oc:Q::\Theta
:o:vq::\vartheta
:o:r::\rho
:oc:s::\sigma
:oc:S::\Sigma
:o:t::\tau
:oc:u::\upsilon
:oc:U::\Upsilon
:o:v::\digamma
:oc:w::\omega
:oc:W::\Omega
:oc:x::\xi
:oc:X::\Xi
:oc:y::\psi
:oc:Y::\Psi
:o:z::\zeta
-
Thank you for your sharing! I find this script extremely useful when I typeset math using markdown, where standard LaTeX-like alias is not allowed. However, I am wondering if there is efficient to jump between bullets in many of the commands you wrote?– Mr.RobotCommented Oct 10, 2019 at 19:15
-
@Mr.Robot Thanks, happy to hear that you found it useful! Currently it is not possible to jump between bullets. You could use Texmaker for now, which has this functionality build in (by pressing
tab
). If I can do it, I might add this feature in the future, but my AHK skills are very limited.– scaviCommented Oct 12, 2019 at 12:57 -
@Mr.Robot I just implement jumping between bullets! Have a look on the updated answer. It's done via ctrl+space.– scaviCommented Oct 24, 2019 at 1:28
-
By accident I found this question and also by accident I found an answer a long time ago:
http://uweziegenhagen.de/?tag=autohotkey
The guy there, Mr. Ziegenhagen, blogs some useful scripts in order to make the LaTeX life easier. Some examples:
!e::
InputBox, UserEnv, Environment, Please enter an environment!, , 240, 120
If ErrorLevel
return
Else
if( RegExMatch(UserEnv, "(.*?)(\d+)$", splitted) ) {
Send \begin{{}%splitted1%{}}{Enter}
Loop %splitted2% {
Send \item {Enter}
}
Send \end{{}%splitted1%{}}{Up}
count2 := splitted2 - 1
Loop %count2% {
Send {Up}
}
}
Else
Send \begin{{}%UserEnv%{}}{Enter 2}\end{{}%UserEnv%{}}{Up}
return
If you press Alt+e
and enter e. g. itemize3
then the script will insert
\begin{itemize}
\item
\item
\item
\end{itemize}
I think that's great! Here are some more examples:
:*:ch#::\chapter{{}{}}{LEFT}
:*:s#::\section{{}{}}{LEFT}
:*:ss#::\subsection{{}{}}{LEFT}
:*:sss#::\subsubsection{{}{}}{LEFT}
:*:b#::\begin{{}{}}{LEFT}
:*:e#::\end{{}{}}{LEFT}
:*:bf#::\textbf{{}{}}{LEFT}
:*:tt#::\texttt{{}{}}{LEFT}
:*:it#::\textit{{}{}}{LEFT}
:*:desc#::\begin{{}description{}}`r\item[]`r\item[]`r\item[]`r\end{{}description{}}{UP 3}{LEFT}
:*:enum#::\begin{{}enumerate{}}`r\item `r\item `r\item `r\end{{}enumerate{}}{UP 3}
:*:item#::\begin{{}itemize{}}`r\item `r\item `r\item `r\end{{}itemize{}}{UP 3}
See also this question. Here are more examples from Mr. Ziegenhagen's blog:
You can use AutoHotKeys to define a bunch of keyboard shortcuts for the most often used LaTeX commands:
\begin{<input your environment name>}
\end{<AutoHotKeys automatically closes it with the same environment name>}
\begin{itemize}
\item <cursor is put here>
\item
\end{itemize}
\section{foo}
\alpha,\beta,...
etc.
But if you're willing to invest time in learning a tool to ease LaTeX document authoring, I suggest emacs and the good AUCTeX extension. It has many well-thought keyboard shortcuts, syntax highlighting (including bold for \section), jump to the point of compilation error, table of content navigation, etc. http://www.gnu.org/software/auctex/features.html
Works under Linux, Windows and Mac.
-
How do I get Autohotkey to close the current environment automatically. So far I use
b#
to expand to\begin{}
but I am looking for a more sophisticated solution. Commented Sep 25, 2013 at 23:25 -
This comment should be converted to a full question, about autoHotKeys (and this not on TeX.SE).– jrouquieCommented Sep 26, 2013 at 8:49
-
1@UweZiegenhagen I know this is an old comment, but you could use an InputBox for this. I updated my answer to provide an example.– scaviCommented Oct 24, 2019 at 14:03
Script for converting LaTeX-like input to unicode characters
"Ctrl+Alt+Shift+U" toggles it on and off (look at the bottom right icon to see it's in suspense mode (icon S) of active mode (icon H).
Test: αβΓ∞¹₂ℝ∫
(la|con)?tex(t)?
(given that the language supports executing system commands). Unless you mean implementing TeX in AutoHotKey. That'd be a feat.