global !p
texMathZones = ['texMathZone'+x for x in ['A', 'AS', 'B', 'BS', 'C', 'CS', 'D', 'DS', 'E', 'ES', 'F', 'FS', 'G', 'GS', 'H', 'HS', 'I', 'IS', 'J', 'JS', 'K', 'KS', 'L', 'LS', 'DS', 'V', 'W', 'X', 'Y', 'Z']]

texIgnoreMathZones = ['texMathText']

texMathZoneIds = vim.eval('map('+str(texMathZones)+", 'hlID(v:val)')")
texIgnoreMathZoneIds = vim.eval('map('+str(texIgnoreMathZones)+", 'hlID(v:val)')")

ignore = texIgnoreMathZoneIds[0]

def math():
    synstackids = vim.eval("synstack(line('.'), col('.') - (col('.')>=2 ? 1 : 0))")
    try:
        first = next(
            i for i in reversed(synstackids)
            if i in texIgnoreMathZoneIds or i in texMathZoneIds
        )
        return first != ignore
    except StopIteration:
        return False


def smart_space(next_str, auto_str=" ", loose=False):
    next_word = ""

    if next_str:
        if loose == True:
            next_word = auto_str
        elif next_str[0] in [",", ".", "-", "!", "?", " "]:
            next_word = auto_str

    return next_word

def add_variable_numbers(*inputs, **kwargs):
    absolute = kwargs.pop("absolute", False)
    total = 0

    for t in inputs:
        try:
            i = int(t)
            if absolute is True:
                total += abs(i)
            else:
                total += i
        except ValueError:
            continue
    
    return total

endglobal

snippet template "Main template (that should work without relying with style files)" bi
\documentclass[class=memoir, crop=false, oneside, 14pt]{standalone}

% all of the packages to be used
\usepackage[nocomments]{standalone}
\usepackage[utf8]{inputenc}
\usepackage{fontawesome}
\usepackage[english]{babel}
\usepackage[rgb]{xcolor}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{amsthm}
\usepackage{tikz}
\usepackage{pgfplots}
\usepackage{fancyhdr}
\usepackage{minted}
\usepackage[most]{tcolorbox}
\usepackage[colorlinks=true, linkcolor=., urlcolor=blue]{hyperref}
\usepackage{kpfonts}

% using the fancy header package
% http://linorg.usp.br/CTAN/macros/latex/contrib/fancyhdr/fancyhdr.pdf
\pagestyle{fancy}

% fill the header with the format
\fancyhead[L]{\doctitle}
\fancyhead[R]{\nouppercase{\rightmark}}

% fill the footer with the format
\fancyfoot[C]{\nouppercase{\leftmark}}
\fancyfoot[R]{\thepage}

% set the width of the horizontal bars in the header
\renewcommand{\headrulewidth}{2pt}
\renewcommand{\footrulewidth}{1pt}

% set the paragraph formatting
\renewcommand{\baselinestretch}{1.35}

% set chapter style
\chapterstyle{bianchi}

% set chapter spacing for easier reading on digital screen
\setlength{\beforechapskip}{-\beforechapskip}

% document metadata
\author{${1:"Gabriel Arazas"}}
\title{${2:"New Title"}}
\date{`!p
`}

\begin{document}
% Frontmatter of the class note if it's compiled standalone
\renewcommand{\abstractname}{Summary}
\maketitle
\newpage

\frontmatter
\chapter{Preface}
$3
\newpage

\tableofcontents
\newpage

\listoffigures
\newpage

\mainmatter
% Core content (HINT: always start with chapter LaTeX tag)

$0
\end{document}
endsnippet

# Document structure tags
snippet chapter "Chapter element" bi
\chapter{$1}
\label{ch:$1}
$0
endsnippet

snippet section "Section tag" bi
\section{$1}
\label{sec:$1}
$0
endsnippet

snippet subsec "Subsection tag" bi
\subsection{$1}
\label{subsec:$1}
$0
endsnippet  

# Common commands
snippet pack "Use package command" bis
\usepackage`!p snip.rv=smart_space(t[2], "[",loose=True)`$2`!p snip.rv=smart_space(t[2], "]",loose=True)`{$1}
$0
endsnippet

snippet letter "Make at letter block" bis
\makeatletter
$1
\makeatother
$0
endsnippet

snippet label "Create a label" bi
\label{$1}
$0
endsnippet

snippet ref "Create a reference for a label" bi
\ref{${1:<label to be referenced>}} $0
endsnippet

snippet foot "Footnote" w
\footnote{${1:<text>}} $0
endsnippet

# Common environments
snippet begin "Simple empty environment" bi
\begin{$1}
$2
\end{$1}
$0
endsnippet

snippet ml "Math mode (inline)" i
$${1}$`!p smart_space(t[2])`$2
endsnippet

snippet mb "Math block" bi
\begin{equation*}
$1
\end{equation*}
$0
endsnippet

snippet equation "Equation environment for mathematical typesetting" biw
\begin{equation}
\label{eq:$1}
$2
\end{equation}
$0
endsnippet

snippet figure "Figure environment" biw
\begin{figure}
\centering
\label{fig:$1}
$2
\caption{${3:$1}}
\end{figure}
$0
endsnippet

snippet graph "Quickly make a graph" bi
\begin{figure}[${1:ht}]
\centering
\begin{tikzpicture}
    \begin{axis}[
    xlabel=${2:$x$},
    ylabel=${3:$y$},
    axis lines = middle,
    grid=major,
    axis equal=false,
    tick style={very thick},
    major tick style=thick,
    domain=${4:-10}:${5:10},`!p snip.rv = smart_space(t[6], "\n\t", loose=True)`$6
    ]
        \addplot[samples=${7:`!p snip.rv = add_variable_numbers(t[4], t[5], 1, absolute=True)`},$8]{${9:x}};
    \end{axis}
\end{tikzpicture}
\caption{$10}
\label{fig:${11:$10}}
\end{figure}
$0
endsnippet

snippet agraph "Quickly plot a graph without considering integers" bi
\begin{figure}[${1:ht}]
\centering
\begin{tikzpicture}
    \begin{axis}[
    xlabel=${2:$x$},
    ylabel=${3:$y$},
    axis lines = middle,
    grid=major,
    axis equal=false,
    tick style={very thick},
    major tick style=thick,
    minor tick num=2,
    domain=${4:-10}:${5:10},`!p snip.rv=smart_space(t[6], "\n\t", loose=True)`$6
    ]
        \addplot[samples=${7:`!p snip.rv=add_variable_numbers(t[4], t[5], absolute=True)`}, $8]{${9:x}};
    \end{axis}
\end{tikzpicture}
\caption{$10}
\label{fig:${11:$10}}
\end{figure}
$0
endsnippet

snippet plot "Add a plot line" i
\addplot[domain=$1:$2, samples=${3:`!p snip.rv=add_variable_numbers(t[1], t[2], 1, absolute=true)`}]`!p snip.rv=smart_space(t[4], ", ")`$4{${5: x}}
$0
endsnippet


# Common mathematical functions and symbols 
# Also take note that most expressions are prepended with 'M' to mean mathematical usage
snippet === "Equivalent to" iw
\equiv
endsnippet

snippet ~= "Congruent to" iw
\cong
endsnippet

snippet ~~ "Approximately equal to" iw
\approx
endsnippet

snippet p= "Proportional to" iw
\propto
endsnippet

snippet != "Not equal" iw
\neq
endsnippet

snippet <= "Greater than or equal to" iw
\geq
endsnippet

snippet !> "Not greater than" iw
\ngtr
endsnippet

snippet >= "Less than or equal to" iw
\leq
endsnippet

snippet !< "Not less than" iw
\nless
endsnippet

snippet <-- "Precedes symbol" iw
\prec
endsnippet

snippet =<- "Precedes or equals" iw
\preceq
endsnippet

snippet !<- "Not precedes" iw
\nprec
endsnippet

snippet --> "Succeeds symbol" iw
\succ
endsnippet

snippet =-> "Succeeds or equals" iw
\succeq
endsnippet

snippet !-> "Not succeeds" iw
\nsucc
endsnippet

snippet << "Less order than" iw
\ll
endsnippet

snippet >> "Greater order than" iw
\gg
endsnippet

context "math()"
snippet int "Integral symbol" iw
\int
endsnippet

context "math()"
snippet -int "Integral with values" iw
\int_{${1:<lower bound>}}^{${2:<upper bound}}$0
endsnippet

context "math()"
snippet OO "Empty set" iw
\O
endsnippet

context "math()"
snippet -sq "Square superscript" iw
^{2}$0
endsnippet

context "math()"
snippet -cb "Cube superscript" iw
^{3}$0
endsnippet

context "math()"
snippet -- "Superscript" iwA
^{$1}$0
endsnippet

context "math()"
snippet __ "Subscript" iwA
_{$1}$0
endsnippet

snippet ... "Ellipsis" iw
\ldots
endsnippet

snippet c.. "Centered ellipsis" iw
\cdots
endsnippet

snippet v.. "Vertical ellipsis" iw
\vdots
endsnippet

snippet d.. "Diagonal ellipsis" iw
\ddots
endsnippet

context "math()"
snippet Mbc "Mathematical because symbol" iw
\because
endsnippet

context "math()"
snippet Mth "Mathematical therefore symbol" iw
\therefore
endsnippet

context "math()"
snippet exp "Expression" iw
\exp(${1:x}} $0
endsnippet

context "math()"
snippet frac "Fraction" iw
\frac{${1:<enumerator>}{${2:<denominator}}
$0
endsnippet

context "math()"
snippet "-(\d+|\w+) over (\d+|\w+)-" "Quick fraction" riwA
`!p snip.rv = f"\\frac{{{match.group(1)}}}{{{match.group(2)}}}"`
$0
endsnippet

context "math()"
snippet "-(\d+|\w+) / (\d+|\w+)-" "Quick fraction" riwA
`!p snip.rv = f"\\frac{{{match.group(1)}}}{{{match.group(2)}}}"`
$0
endsnippet

context "math()"
snippet mod "Mod operator (as binary operator)" iw
\bmod $0
endsnippet

## Common notations
context "math()"
snippet sum "Sigma notation symbol" iw
\sum
endsnippet

context "math()"
snippet -sum "Sigma notation" iw
\sum_{${1:<lower bound>}^{${2:<upper bound>}} f(${3:<function expression>})
$0
endsnippet

context "math()"
snippet prod "Product notation symbol" iw
\prod
endsnippet

context "math()"
snippet -prod "Product notation" iw
\prod_{${1:<lower bound>}^{${2:upper bound}} f(${3:<function expression>})
$0
endsnippet

context "math()"
snippet lim "Limit keyword" iw
\lim
endsnippet

context "math()"
snippet -lim "Limit operator" iw
\lim\limits_{${1:x \to \infty}}
endsnippet

context "math()"
snippet ooo "Infinity symbol" iw
\infty
endsnippet

context "math()"
snippet inf "Infinity symbol" iw
\infty
endsnippet

context "math()"
snippet choose "Choose function" iw
\binom{${1:<range>}}{${2:<N>}}
$0
endsnippet

context "math()"
snippet "-(\d+|\w+) choose (\d+|\w+)-" "Quick choose function" riwA
`!p snip.rv = f"\\binom{{{match.group(1)}}}{{{match.group(2)}}}"`
$0
endsnippet

## Common sets of numbers
context "math()"
snippet SN "Set of natural numbers" iw
\N
endsnippet

context "math()"
snippet SZ "Set of integers" iw
\Z
endsnippet

context "math()"
snippet SQ "Set of rational numbers" iw
\Q
endsnippet

context "math()"
snippet SA "Set of algebraic numbers" iw
\mathbb{A}
endsnippet

context "math()"
snippet SR "Set of real numbers" iw
\R
endsnippet

context "math()"
snippet SC "Set of complex numbers" iw
\C
endsnippet

## Common mathematical logic symbols
context "math()"
snippet Lin "Logical in symbol" iw
\in
endsnippet

context "math()"
snippet L!in "Logical not in symbol" iw
\notin
endsnippet

context "math()"
snippet Lon "Logical owns symbol" iw
\ni
endsnippet

context "math()"
snippet LSu "Logical set union" iw
\cup
endsnippet

context "math()"
snippet LSi "Logical set interaction" iw
\cap
endsnippet

context "math()"
snippet LSd "Logical set difference" iw
\setminus
endsnippet

context "math()"
snippet Lex "There exists at least one" iw
\exists
endsnippet

context "math()"
snippet Lex! "There exists one and only one" iw
\exists!
endsnippet

context "math()"
snippet L!ex "Not exists" iw
\nexists
endsnippet

context "math()"
snippet Lfa "For all" iw
\forall
endsnippet

context "math()"
snippet Lor "Logical 'or' symbol" iw
\lor
endsnippet

context "math()"
snippet Land "Logical 'and' symbol" iw
\land
endsnippet

context "math()"
snippet Lnot "Logical 'not' symbol" iw
\neg
endsnippet

context "math()"
snippet => "Implies" Aiw
\implies
endsnippet

context "math()"
snippet =< "Implied by" Aiw
\impliedby
endsnippet

context "math()"
snippet <=> "If and only if" iw
\iff
endsnippet

context "math()"
snippet iff "If and only if" iw
\iff
endsnippet

context "math()"
snippet (( "Subset" iw
\subset
endsnippet

context "math()"
snippet !( "Not a proper subset" iw
\not\subset
endsnippet

context "math()"
snippet =( "Subset is equal to" iw
\subseteq
endsnippet

context "math()"
snippet !=( "Not a subset of" iw
\nsubseteq
endsnippet

context "math()"
snippet )) "A proper subset of" iw
\supset
endsnippet

context "math()"
snippet !) "Not a proper superset of" iw
\not\supset
endsnippet

context "math()"
snippet =) "A subset of" iw
\supseteq
endsnippet

context "math()"
snippet !=) "Not a superset of" iw
\nsupseteq
endsnippet

## Common functions
### Trigonometric functions
context "math()"
snippet Msin "Sine function" iw
\sin`!p snip.rv=smart_space(t[1], "(", loose=True)`$1`!p snip.rv=smart_space(t[1], ")", loose=True)` $0
endsnippet

context "math()"
snippet Mcos "Cosine function" iw
\cos`!p smart_space(t[1], "(", loose=True)`$1`!p smart_space(t[1], ")", loose=True)`
endsnippet

context "math()"
snippet Mtan "Tangent function" iw
\tan`!p snip.rv=smart_space(t[1], "(", loose=True)`$1`!p snip.rv=smart_space(t[1], ")", loose=True)` $0
endsnippet

context "math()"
snippet Mcsc "Cosecant function" iw
\csc`!p snip.rv=smart_space(t[1], "(", loose=True)`$1`!p snip.rv=smart_space(t[1], ")", loose=True)` $0
endsnippet

context "math()"
snippet Msec "Secant function" iw
\sec`!p snip.rv=smart_space(t[1], "(", loose=True)`$1`!p snip.rv=smart_space(t[1], ")", loose=True)` $0
endsnippet

context "math()"
snippet Mcot "Cotangent function" iw
\cot`!p snip.rv=smart_space(t[1], "(", loose=True)`$1`!p snip.rv=smart_space(t[1], ")", loose=True)` $0
endsnippet

### Inverse trigonometric functions
context "math()"
snippet M!sin "Inverse sine keyword" iw
\arcsin`!p snip.rv=smart_space(t[1], "(", loose=True)`$1`!p snip.rv=smart_space(t[1], ")", loose=True)` $0
endsnippet

context "math()"
snippet M!cos "Inverse cosine keyword" iw
\arccos`!p snip.rv=smart_space(t[1], "(", loose=True)`$1`!p snip.rv=smart_space(t[1], ")", loose=True)` $0
endsnippet

context "math()"
snippet M!tan "Inverse tangent keyword" iw
\arctan`!p snip.rv=smart_space(t[1], "(", loose=True)`$1`!p snip.rv=smart_space(t[1], ")", loose=True)` $0
endsnippet

context "math()"
snippet M!csc "Inverse cosecant keyword" iw
\arccsc`!p snip.rv=smart_space(t[1], "(", loose=True)`$1`!p snip.rv=smart_space(t[1], ")", loose=True)` $0
endsnippet

context "math()"
snippet M!sec "Inverse secant keyword" iw
\arcsec`!p snip.rv=smart_space(t[1], "(", loose=True)`$1`!p snip.rv=smart_space(t[1], ")", loose=True)` $0
endsnippet

context "math()"
snippet M!cot "Inverse cotangent" iw
\arccot`!p snip.rv=smart_space(t[1], "(", loose=True)`$1`!p snip.rv=smart_space(t[1], ")", loose=True)` $0
endsnippet

### Hyperbolic trigonometric functions
context "math()"
snippet Msinh "Hyperbolic sine" iw
\sinh`!p snip.rv=smart_space(t[1], "(", loose=True)`$1`!p snip.rv=smart_space(t[1], ")", loose=True)` $0
endsnippet

context "math()"
snippet Mcosh "Hyperbolic cosine" iw
\cosh`!p snip.rv=smart_space(t[1], "(", loose=True)`$1`!p snip.rv=smart_space(t[1], ")", loose=True)` $0
endsnippet

context "math()"
snippet Mtanh "Hyperbolic tangent" iw
\tanh`!p snip.rv=smart_space(t[1], "(", loose=True)`$1`!p snip.rv=smart_space(t[1], ")", loose=True)` $0
endsnippet

context "math()"
snippet Mcsch "Hyperbolic cosecant" iw
\operatorname{csch}`!p snip.rv=smart_space(t[1], "(", loose=True)`$1`!p snip.rv=smart_space(t[1], ")", loose=True)` $0
endsnippet

context "math()"
snippet Msech "Hyperbolic secant" iw
\operatorname{sech}`!p snip.rv=smart_space(t[1], "(", loose=True)`$1`!p snip.rv=smart_space(t[1], ")", loose=True)` $0
endsnippet

context "math()"
snippet Mcoth "Hyperbolic cotangent" iw
\coth`!p snip.rv=smart_space(t[1], "(", loose=True)`$1`!p snip.rv=smart_space(t[1], ")", loose=True)` $0
endsnippet

### Inverse hyperbolic trigonometric functions
context "math()"
snippet M!sinh "Inverse hyperbolic sine" iw
\operatorname{arsinh}`!p snip.rv=smart_space(t[1], "(", loose=True)`$1`!p snip.rv=smart_space(t[1], ")", loose=True)` $0
endsnippet

context "math()"
snippet M!cosh "Inverse hyperbolic cosine" iw
\operatorname{arcosh}`!p snip.rv=smart_space(t[1], "(", loose=True)`$1`!p snip.rv=smart_space(t[1], ")", loose=True)` $0
endsnippet

context "math()"
snippet M!tanh "Inverse hyperbolic tangent" iw
\operatorname{artanh}`!p snip.rv=smart_space(t[1], "(", loose=True)`$1`!p snip.rv=smart_space(t[1], ")", loose=True)` $0
endsnippet

context "math()"
snippet M!csch "Inverse hyperbolic cosecant" iw
\operatorname{arcsch}`!p snip.rv=smart_space(t[1], "(", loose=True)`$1`!p snip.rv=smart_space(t[1], ")", loose=True)` $0
endsnippet

context "math()"
snippet M!sech "Inverse hyperbolic secant" iw
\operatorname{arsech}`!p snip.rv=smart_space(t[1], "(", loose=True)`$1`!p snip.rv=smart_space(t[1], ")", loose=True)` $0
endsnippet

context "math()"
snippet M!coth "Inverse hyperbolic cotangent" iw
\operatorname{arcoth}`!p snip.rv=smart_space(t[1], "(", loose=True)`$1`!p snip.rv=smart_space(t[1], ")", loose=True)` $0
endsnippet

## Common symbols found in geometry
snippet Gov "Overline" iw
\overline{$1}
endsnippet

snippet ----- "Overline" iw
\overline{$1}
endsnippet

snippet Gra "Right arrow" iw
\overrightarrow{$1}
endsnippet

snippet ----> "Right arrow" iw
\overrightarrow{$1}
endsnippet

snippet Gang "Angle symbol" iw
\angle
endsnippet

snippet Gman "Measured angle symbol" iw
\measuredangle
endsnippet

snippet Gtri "Triangle" iw
\triangle
endsnippet

snippet Gpar "Parallel with" iw
\|
endsnippet

snippet G!par "Not parallel with" iw
\nparallel
endsnippet

snippet Gper "Perpendicular to" iw
\perp
endsnippet

snippet G!per "Not perpendicular to" iw
\not\perp
endsnippet

# Text formatting
snippet bf "Boldface text" iw
\textbf{$1}$0
endsnippet

snippet it "Italic text" iw
\emph{$1}$0
endsnippet

snippet tt "Teletype font" iw
\texttt{$1}$0
endsnippet

snippet ol "Enumerated list (ordered list)" iw
\begin{enumerate}
$1
\end{enumerate}
$0
endsnippet

snippet ul "Itemized list (unordered list)" iw
\begin{itemize}
$1
\end{itemize}
$0
endsnippet

snippet li "List item for the OL/UL lists" iw
\item{$1}
$0
endsnippet
    
snippet a "URL links (with description)" iw
\href{${1:<url>}{${2:<description>}}$0
endsnippet

snippet al "Reference links with label" iw
\autoref{${1:<label>}}$0
endsnippet

# Greek letters
context "math()"
snippet GAA "Uppercase Greek letter alpha" w
\Alpha
endsnippet

context "math()"
snippet GAa "Lowercase Greek letter alpha" w
\alpha
endsnippet

context "math()"
snippet GBB "Uppercase Greek letter beta" w
\Beta
endsnippet

context "math()"
snippet GBb "Lowercase Greek letter beta" w
\beta
endsnippet

context "math()"
snippet GCC "Uppercase Greek letter gamma" w
\Gamma
endsnippet

context "math()"
snippet GCc "Lowercase Greek letter gamma" w
\gamma
endsnippet

context "math()"
snippet GDD "Uppercase Greek letter delta" w
\Delta
endsnippet

context "math()"
snippet GDd "Lowercase Greek letter delta" w
\delta
endsnippet

context "math()"
snippet GEE "Uppercase Greek letter epsilon" w
\Epsilon
endsnippet

context "math()"
snippet GEe "Lowercase Greek letter epsilon" w
\epsilon
endsnippet

context "math()"
snippet GVEe "Variation Greek letter epsilon" w
\varepsilon
endsnippet

context "math()"
snippet GTT "Uppercase Greek letter theta" w
\Theta
endsnippet

context "math()"
snippet GTt "Lowercase Greek letter theta" w
\theta
endsnippet

context "math()"
snippet GLL "Uppercase Greek letter lambda" w
\Lambda
endsnippet

context "math()"
snippet GLl "Lowercase Greek letter lambda" w
\lambda
endsnippet

context "math()"
snippet GPP "Uppercase Greek letter pi" w
\Pi
endsnippet

context "math()"
snippet GPp "Lowercase Greek letter pi" w
\pi
endsnippet

context "math()"
snippet GVPp "Variation Greek letter pi" w
\varpi
endsnippet

context "math()"
snippet GSS "Uppercase Greek letter sigma" w
\Sigma
endsnippet

context "math()"
snippet GSs "Lowercase Greek letter sigma" w
\sigma
endsnippet

context "math()"
snippet GPH "Uppercase Greek letter phi" w
\Phi
endsnippet

context "math()"
snippet GPh "Lowercase Greek letter phi" w
\phi
endsnippet

context "math()"
snippet GVPh "Variation Greek letter phi" w
\varphi
endsnippet

context "math()"
snippet GPS "Uppercase Greek letter psi" w
\Psi
endsnippet

context "math()"
snippet GPs "Lowercase Greek letter psi" w
\psi
endsnippet

context "math()"
snippet GOO "Uppercase Greek letter omega" w
\Omega
endsnippet

context "math()"
snippet GOo "Lowercase Greek letter omega" w
\omega
endsnippet

# Custom commands and environment (for my class notes) w
snippet dnote "Doc note admonition block" iw
\begin{-doc-note}
$1
\end{-doc-note}
$0
endsnippet
    
snippet dinfo "Doc info admonition block" iw
\begin{-doc-info}
$1
\end{-doc-info}
$0
endsnippet

snippet dtheo "Doc theorem block" iw
\begin{-doc-theorem}
$1
\end{-doc-theorem}
$0
endsnippet

snippet ddef "Doc definition block" iw
\begin{-doc-definition}
$1
\end{-doc-definition}
$0
endsnippet

snippet dwarn "Doc warning callout block" iw
\begin{-doc-warning}
$1
\end{-doc-warning}
$0
endsnippet

snippet dcrit "Doc critical callout block" iw
\begin{-doc-critical}
$1
\end{-doc-critical}
$0
endsnippet

