Scripts for Quick LaTeX, scrot, and GraphViz Processing
Quick \(\LaTeX\) processing
Motivation
As is the case with my \(\LaTeX\) input method script, this script was motivated by the desire to typeset math for use in online discussions1 (held on a platform like Discord or Slack). This script was written after the previously-mentioned Unicode input script after I realized that using Unicode characters in free text was sometimes insufficient for proper math discussion, especially when summations, gratuitous super- or subscripts, and fractions are involved. This script operates like many Discord \(\LaTeX\) bots: it captures input in the form of \(\LaTeX\) source code, compiles it using \(\LaTeX\), converts the output into an image, and gives it to the user for insertion into the discussion. Since, however, this script operates outside of any online discussion platform. it can be used anywhere: places without a \(\LaTeX\) bot, DMs, and other messaging platforms.
Use
To use this script, I write \(\LaTeX\) source code in the composition box of
whichever online messaging platform I'm using,
select and copy the source code to the clipboard,
and type Super+`.
This takes the contents of the clipboard,
inserts a \(\LaTeX\) document template around it,
opens a floating xterm
window in which the code is compiled,
converts the result to an image, and copies that image to the clipboard.
I then paste the image in the message and send it.
The terminal window acts as a progress indication; once it closes, the process
is complete.
If an error occurs, the xterm
window stays open with the \(\LaTeX\)
log output.
To do this, my window manager i3
is configured to run
xterm -class TexifyCont -e texify.zsh
whenever Super+~`~ is pressed, and contains the line
for_window [class="TexifyCont"] floating enable
,
which allows the newly-opened terminal to float.
scrot
to clipboard
Drawing from the texify.zsh
script, which outputs an image of typeset
\(\LaTeX\) text to the clipboard,
I wrote scr
, a similar script that ran scrot
, an X11 screenshot tool,
and sent its output to the clipboard.
Here, scrot
is called with -l mode=edge
to work around an odd bug that would
otherwise occur under certain conditions when taking a screenshot of part of the
screen.
Quick GraphViz processing
During Computibility and Complexity class discussions,
I frequently needed to write state machine diagrams and present them to
classmates.
Typically, I would write the diagrams in
GraphViz/~dot~ format in a
Logseq2 code block.
Thus, I wrote dotify.zsh
to allow me to copy the contents of that code block,
feed it to dot
, and display the result (unlike texify.zsh
, which copies the
result to the clipboard).
It's much simpler than texify.zsh
, due to the fact that dot
is less inclined
to throw errors and already outputs image files.
I have my window manager configured to launch it when I press Super+Shift+`.
Security considerations
This program accepts and compiles \(\LaTeX\) input without sanitization,
modification, sandboxing, or limitation.
\(\LaTeX\) is a Turing-complete programming language3
and is capable of reading arbitrary files, executing arbitrary commands
(with \write18{xterm}
, for example), writing arbitrary files, and doing other
things.
Thus, this script should never be run on untrusted input,
and should never be used as part of an automated system.
Source code
For texify.zsh
There are several things worth noting here:
first, signal()
uses xgamma
to rapidly blink the screen twice to signal to
the user that something is happening; it's not useful given that texify.zsh
always runs in a terminal now.
The interrupt()
function is similar, but it does still serve a purpose:
if an error occurs, it pauses and waits for the user to press Enter,
thus keeping the terminal open.
Second, the grab()
, putimg()
, and putprim()
functions allow the user to
substitute in their own X11 copy/paste program.
1#!/usr/bin/env zsh
2
3signal()
4{
5 if [[ ! tty ]]
6 then
7 xgamma -gamma 0.1
8 sleep 0.1
9 xgamma -gamma 1
10 fi
11}
12
13#grab() {xclip -selection CLIPBOARD -o}
14grab() {xcopy -b -r}
15#putimg() {xclip -selection CLIPBOARD -t $1}
16putimg() {nohup xcopy -b -a $1}
17putprim() {xcopy}
18cleanup()
19{
20 cd /
21 rm -r $tmpdir
22}
23
24interrupt()
25{
26 local ep=$?
27 if tty
28 then
29 read a
30 elif [[ -e $1 ]]
31 then
32 xterm -e less $1 &
33 else
34 signal
35 sleep 0.2
36 signal
37 sleep 0.2
38 signal
39 sleep 0.2
40 fi
41 cleanup
42 exit $ep
43}
44
45signal
46tmpdir=$(mktemp -d)
47cd $tmpdir
48grab | putprim
49cat - >textemp.tex <<EOF
50\documentclass{article}
51\pagenumbering{gobble}
52
53$(cat $(dirname $(realpath $0))/../stempl_math.tex)
54
55\begin{document}
56\begin{flushleft}
57$(grab)
58\end{flushleft}
59\end{document}
60EOF
61latex -halt-on-error textemp.tex || interrupt textemp.log
62dvipng -D 300 -T tight --png textemp.dvi || interrupt
63(convert textemp1.png -bordercolor white -border 50 png:- \
64 | putimg image/png) || interrupt
65signal
66cleanup
For stempl_math.tex
1% Almost always used
2\usepackage{amsmath,amssymb,pdfsync}
3
4% Discretionary
5\usepackage[normalem]{ulem} % Strikethrough
6\usepackage{siunitx}\sisetup{per-mode = symbol}
7\usepackage{mathtools}
8
9\newcommand{\Rls}{\mathbb{R}}
10\newcommand{\Int}{\mathbb{Z}}
11\newcommand{\Rxi}{\mathbb{C}}
12\newcommand{\Rat}{\mathbb{Q}}
13\newcommand{\Nat}{\mathbb{N}}
14\newcommand{\rInt}[1]{\Int/#1\Int}
15\newcommand{\rpt}{\mathrm{Re}}
16\newcommand{\ipt}{\mathrm{Im}}
17\newcommand{\setei}[1]{\setcounter{enumi}{#1}\addtocounter{enumi}{-1}}
18
19% Prof Zajj's shortcuts
20%% Old amatrix env't
21%\newenvironment{amatrix}[1]{%
22% \left(\begin{array}{@{}*{#1}{c}|c@{}}
23%}{%
24% \end{array}\right)
25%}
26
27%% Generalized amatrix environment: optional argument is number of columns after
28%% pipe (default 1); req'd argument is number of columns before.
29\newenvironment{amatrix}[2][1]{%
30 \left(\begin{array}{@{}*{#2}{c}|*{#1}{c}@{}}
31}{%
32 \end{array}\right)
33}
34
35% System of equations
36\newenvironment{sys}{%
37 \left\{\begin{array}{@{}r@{\ }l}
38}{%
39 \end{array}\right.
40}
41
42\newenvironment{ans}{\medskip \color{black} \paragraph*{\emph{Answer}.}}
43 {\hfill \break $~\!\!$ \dotfill \medskip }
44
45% Miscellaneous time-saving things
46\newcommand{\uu}{\textbf{u}}
47\newcommand{\vv}{\textbf{v}}
48\newcommand{\ww}{\textbf{w}}
49
50% Compatability additions
51\newcommand{\RR}{\Rls}
52\newcommand{\CC}{\Rxi}
For scr
(a ZSH script)
1#!/usr/bin/env zsh
2#putimg() {nohup xcopy -b -a $1}
3putimg() {nohup xclip -selection clipboard -i -t $1}
4scrot -l mode=edge $@ - | putimg image/png
For dotify.zsh
1#!/usr/bin/env zsh
2xclip -o | dot -Gdpi=600 -Tpng | feh -. -g 900x900 --class DotifyRend -
The relevant parts of i3.conf
1for_window [class="TexifyCont"] floating enable
2for_window [class="FloatingTerm"] floating enable
3for_window [class="DotifyRend"] floating enable
4for_window [class="DotifyCont"] floating enable
5
6bindsym $mod+Shift+grave exec --no-startup-id zsh -c 'dotify.zsh'
7bindsym $mod+grave exec xterm -class TexifyCont -e texify.zsh
That I talk about math online with my friends often enough to justify writing this script says a lot about me and my friends. They're great, and quite nerdy.
Some day, I will write another post about Logseq and all the things
it's done for me.
Today is not that day—I have been writing late into the night to take advantage
of my sudden motivation to write two write-ups of shell scripts I wrote,
but cannot justify spending more extra work and study time sleeping time
writing that post.