\documentclass{article}
\usepackage{luaquotes}
\usepackage{verbatim}
\usepackage{xcolor}
\usepackage{longtable}
\definecolor{darkspringgreen}{rgb}{0.09, 0.45, 0.27}
\definecolor{dsg}{rgb}{0.09, 0.45, 0.27}
\usepackage[hidelinks]{hyperref}
\usepackage{hologo}
\usepackage[british]{babel}
\usepackage[useregional]{datetime2}
\DTMlangsetup[en-GB]{ord=omit}
\definecolor{LightGray}{gray}{0.9}
%\usepackage{mathpazo}
\IfFontExistsTF{Palatine Parliamentary}{\setromanfont[RawFeature={+onum,+pnum},%
BoldFont={Palatine Parliamentary Bold},
ItalicFont={Palatine Parliamentary Italic}]{Palatine Parliamentary Regular}
}{\setromanfont[RawFeature={+onum,+pnum}]{TeX Gyre PagellaX}}
\setmonofont[Scale=.9]{Source Code Pro}
%\newfontface\primeback[Scale=1.01]{Libertinus Serif}
\newcommand{\primeback}{}

\newfontface\boxy{DejaVu Sans}
\newcommand{\thebox}{{\boxy ▯}}
%\usepackage[firstnumber=last]{fancyvrb}
\usepackage{minted}
\date{\today\\\smallskip\ttfamily Version \luaquotesversionnumber}
\author{Elijah Z Granet\thanks{e-mail: \href{mailto:ezg21@cantab.ac.uk}{\ttfamily ezg21@cantab.ac.uk}}}

\title{\texttt{LuaQuotes}:\\A package for smart quotation marks}

\begin{document}
\maketitle
\tableofcontents
\clearpage
\section{Overview}
\subsection{Purpose}
This package provides a function to automatically have 'smart quotes' in \hologo{LuaLaTeX}.  By 'smart quotes', I refer to the automatic insertion of curved or 'typographer's' quotation marks when the user types straight quotation marks.  The below figure illustrates the distinction in English typography:
\begin{center}
\renewcommand{\arraystretch}{2}
\begin{tabular}{ccc}
\ttfamily User input &\color{red} Smart Quotes Off & \color{darkspringgreen}Smart Quotes On\\
\LARGE\texttt{"Howdy!"}%
& \LARGE\textcolor{red}{\sqtworight}Howdy!\sqtworight%
& \LARGE "Howdy!"\\
\LARGE\texttt{'Don't!'}%
& \LARGE\textcolor{red}{\sqoneright}%
Don\sqoneright t!\sqoneright%
& \LARGE 'Don't!'

\end{tabular}
\end{center}

\section{Smart quotes}



\subsection{Options}
 The default option, for English quotation marks, is called by:
   \begin{minted}[
frame=lines,
framesep=2mm,
baselinestretch=1.2,
bgcolor=LightGray,
fontsize=\footnotesize,
breaklines,
]
{latex}
\usepackage{luaquotes}
\end{minted}
The French, German, German (guillemets), and Swiss German options, for those languages' punctuation, are called by the following respective commands.  
\begin{minted}[
frame=lines,
framesep=2mm,
baselinestretch=1.2,
bgcolor=LightGray,
fontsize=\footnotesize,
breaklines,
]
{latex}
\usepackage[fr]{luaquotes} %French
\usepackage[de]{luaquotes} % German
\usepackage[degm]{luaquotes} % German with guillemets
\usepackage[dech]{luaquotes} %Swiss German
\end{minted}
\subsubsection{English Features}
The English features are designed to smartly recognise English punctuation:
\begin{center}
\renewcommand{\arraystretch}{2}
\begin{tabular}{ccc}
\ttfamily Feature & User input & Output\\
 Double Quotes &  \LARGE\texttt{"Hello!"}%
& 
\LARGE "Hello"\\
Single Quotes& \LARGE\texttt{'Hello!'}%
&  \LARGE 'Hello' \\
Contractions & \LARGE \texttt{Don't} & \LARGE Don't\\
\end{tabular}
\end{center}

\subsubsection{French option}
The French option produces the following output, including the extra space around punctuation prescribed by French typography:
\begin{center}
\renewcommand{\arraystretch}{2}
\begin{tabular}{cc}
\ttfamily User input &Output\\
\LARGE\texttt{"Salut!"}%
&  \LARGE \glmtl Salut!\glmtr\\
\LARGE\texttt{'Salut!'}%
&  \LARGE \sglmtl Salut!\sglmtr\\

\end{tabular}
\end{center}
\subsubsection{The German option}
The German option produces the following output:

\begin{center}
\renewcommand{\arraystretch}{2}
\begin{tabular}{cc}
\ttfamily User input &Output\\
\LARGE\texttt{"Hallo!"}%
&  \LARGE \dedouble Hallo!\sqtwoleft\\
\LARGE\texttt{'Hallo!'}%
&  \LARGE \desingle Hallo!\sqoneleft\\

\end{tabular}
\end{center}
\subsubsection{The German (guillemets) option}
The German (guillemets) option produces the following output:

\begin{center}
\renewcommand{\arraystretch}{2}
\begin{tabular}{cc}
\ttfamily User input &Output\\
\LARGE\texttt{"Hallo!"}%
&  \LARGE \degmdouble Hallo!\degmtr\\
\LARGE\texttt{'Hallo!'}%
&  \LARGE \degmsingle Hallo!\desgmtr\\

\end{tabular}
\end{center}

\subsubsection{The Swiss German option}
The Swiss German option produces the following output:

\begin{center}
\renewcommand{\arraystretch}{2}
\begin{tabular}{cc}
\ttfamily User input &Output\\
\LARGE\texttt{"Hallo!"}%
&  \LARGE \glmtl Hallo!\glmtr\\
\LARGE\texttt{'Hallo!'}%
&  \LARGE \sglmtl Hallo!\sglmtr\\

\end{tabular}
\end{center}

\subsection{Activation and De-activation}
The package automatically activates the smart quotes function at the beginning of the document. To deactivate the smart quotes function within a document, the following commands are used:
\begin{minted}[
frame=lines,
framesep=2mm,
baselinestretch=1.2,
bgcolor=LightGray,
fontsize=\footnotesize,
breaklines,
]
{latex}
\dumbquotes %English
\frdumbquotes %French
\dedumbquotes %German
\degmdumbquotes %German with French-style quotes
\end{minted}

The following commands re-activate the smart quotes function:
\begin{minted}[
frame=lines,
framesep=2mm,
baselinestretch=1.2,
bgcolor=LightGray,
fontsize=\footnotesize,
breaklines,
]
{latex}
\smartquotes %English
\frsmartquotes %French
\desmartquotes % German
\degmsmartquotes % German with French-style quotes
\end{minted}

A limitation on the (de-)activation of the package is that the Lua filters will not deactivate within the same paragraph, so the function can only be changed across paragraphs.

\subsection{Monospace}
As a general rule, smart quotes are rather undesirable in monospace text, and therefore, within the \color{darkspringgreen} \verb!\texttt!\color{black}\ environment the package does not apply smart quotes. Thus, the same input produces in roman face \textcolor{darkspringgreen}{"Hello World"} but in monospace \texttt{"Hello World"}.
	
	As the example above shows, the default behaviour of this package forces straight quotes in monospace, and disables \TeX\ quote ligatures (but not other \TeX\ ligatures) to do so, on the assumption that any form of curved quotes are undesirable.  
	
	For extended periods of monospaced text called by {\color{darkspringgreen}\verb!\ttfamily!}, the activation and de-activation methods above should be used.  I considered altering the {\color{darkspringgreen}\verb!\ttfamily!} command to always call on {\color{darkspringgreen}\verb!\dumbquotes!}, but I thought it best to avoid messing with the command.  This may change in future development. 
	
	
	If a user desires to disable the smart quotes for other faces, this is easily done globally by adding the following line to the font's configuration in {\color{darkspringgreen}\texttt{fontspec}}:
	\begin{minted}[
frame=lines,
framesep=2mm,
baselinestretch=1.2,
bgcolor=LightGray,
fontsize=\footnotesize,
breaklines,
]
{latex}
RawFeature={+qtbye}
\end{minted}
This will, however, result in the font using straight quotes rather than the standard \TeX\ quote ligatures, making it a distinct option than the activation and de-activation options \textit{supra}.
\section{Auxiliary Punctuation}
The smart quotes feature covers the 'standard' usage of quotes, but there are many instances where quotation mark or quote-mark like features are needed outside the automatic formatting. The package provides several commands for this.
\subsection{Standalone quotes}
The marks in this section are the set of quotation marks used generally in writing and require little explanation.  However, it should be noted that the  commands {\color{dsg}\verb!\sqoneright!} and {\color{dsg}\verb!\apost!} (which produce identical output) are very useful for aphetic words by which the first syllable is clipped, as in the sequence {\color{dsg}\texttt{'bout}} the smart quotes function will incorrectly produce an opening quote instead of the correct closing quote to indicate the elision.  Thus, the incorrect result of {\color{red} 'bout} is produced.  The solution is to use the code {\color{dsg}\verb!\apost bout!} which produces \textcolor{dsg}{\apost bout}.

\begin{center}
\renewcommand{\arraystretch}{4}
\begin{longtable}{p{3cm}p{1.5cm}p{2cm}p{2.5cm}}
\textbf{Name} & \textbf{UTF-8} & \textbf{Command} & \textbf{Produces}\\
Single low quote & \ttfamily U+201A & \verb!\desingle! & \Huge\desingle\thebox\\
	Double low quote & \ttfamily U+201E & \verb!\dedouble! & \Huge\dedouble\thebox
\\
	Single straight quote & \ttfamily U+0027 & \verb!\dqone! & \Huge\dqone\thebox\\
		Double straight quote & \ttfamily U+0022 & \verb!\dqtwo! & \Huge\dqtwo\thebox\\
		Left single quote & \ttfamily U+2018 & \verb!\sqoneleft! & \Huge\sqoneleft\thebox\\
		Right single quote & \ttfamily U+2019 & \verb!\sqoneright! & \Huge\thebox\sqoneright\\
				Apostrophe & \ttfamily U+2019 & \verb!\apost! & \Huge\thebox\apost\\
		Left double quote & \ttfamily U+201C & \verb!\sqtwoleft! & \Huge\sqtwoleft\thebox\\
		Right double quote & \ttfamily U+201D & \verb!\sqtworight! & \Huge\thebox\sqtworight\\
		Left guillemet [w/ space]& \ttfamily U+00AB & \verb!\glmtl! & \Huge\glmtl\thebox\\
Right guillemet [w/ space]& \ttfamily U+00BB & \verb!\glmtr! & \Huge\thebox\glmtr\\
		\texttt{degm} left guillemet & \ttfamily U+00BB & \verb!\degmtl! & \Huge\degmtl\thebox\\
		\texttt{degm} right guillemet & \ttfamily U+00AB & \verb!\degmtr! & \Huge\thebox\degmtr\\
		Single left guillemet [w/ space]& \ttfamily U+2039 & \verb!\sglmtl! & \Huge\sglmtl\thebox\\
		Single right guillemet [w/ space]& \ttfamily U+203A & \verb!\sglmtr! & \Huge\thebox\sglmtr\\
		\texttt{degm} single left guillemet & \ttfamily U+203A & \verb!\desgmtl! & \Huge\desgmtl\thebox\\
		\texttt{degm} single right guillemet & \ttfamily U+2039 & \verb!\desgmtr! & \Huge\thebox\desgmtr\\

\end{longtable}
	\end{center}

\subsection{Additional symbols}
These are quote like symbols which are useful for precise punctuation, since standard smart quotation marks do not work well in their specialised use cases.  


\begin{center}
\begin{longtable}{p{3cm}p{1.5cm}p{2cm}p{2.5cm}}
\textbf{Name} & \textbf{UTF-8} & \textbf{Command} & \textbf{Produces}\\
	Backtick & \ttfamily U+0060 & \verb!\bcktck! & \Huge\bcktck\thebox
\end{longtable}
		\end{center}
For typesetting US/Imperial measurements like feet and inches, the correct symbol is a prime and double prime.  Many modern typefaces have these symbols, and they are thus useful for typesetting feet and inch measurements (like 6\primeback\lqprime\normalfont 4\primeback\lqdoubleprime ). 


\begin{center}
\begin{longtable}{p{3cm}p{1.5cm}p{2.4cm}p{2.5cm}}
\textbf{Name} & \textbf{UTF-8} & \textbf{Command} & \textbf{Produces}\\
	Single Prime & \ttfamily U+2032 & \verb!\lqprime! & \Huge\thebox\lqprime\\
		Double Prime & \ttfamily U+2033 & \verb!\lqdoubleprime! & \Huge\thebox\lqdoubleprime
\end{longtable}
		\end{center}

%\newcommand{\lqprime}{′}
%\newcommand{\lqdoubleprime}{″}




For certain Polynesian languages, a letter called the \okina Okina is used; while this appears identical to a left single quotation mark in many fonts, it is encoded differently in Unicode because it is properly a letter, not a punctuation mark. 

	
	
	
	\begin{center}
\begin{longtable}{p{3cm}p{1.5cm}p{2cm}p{2.5cm}}
\textbf{Name} & \textbf{UTF-8} & \textbf{Command} & \textbf{Produces}\\
	Okina & \ttfamily U+022B & \verb!\okina! & \Huge\okina\thebox\\\


\end{longtable}
\end{center}
	
	
	
	
	\section{Future Development and Localisation}
	The package's online repository is the best place to report bugs, feature requests, or other contributions, and is located at: \\\url{https://github.com/ezgranet/luaquotes}. 
	
	One obvious point of future development is the addition of other language localisations; this is technologically easy in principle but difficult for me to accomplish without assistance because it requires detailed knowledge of typographic conventions for any given language standard, and therefore the aid of contributors and collaborators.  	\section{Licence}
	This project is licensed under the Latex Public Project Licence version 1.3\textit{c}. This documentation is copyright of the author but licensed under CC-BY-SA 3.0. 
	
	
	\clearpage\section{Implementation}
	
\begin{minted}[
frame=lines,
baselinestretch=1.2,
fontsize=\footnotesize,
linenos,
breaklines,
firstnumber=last
]
{latex}


\def\luaquotesversionnumber{1.4.0}
\ProvidesPackage{luaquotes}
  [2023/01/25\luaquotesversionnumber smart quotes with lua]
  % !TeX program = lualatex                                   
% !TeX encoding = utf8
% This work may be distributed and/or modified under the 
% conditions of the LaTeX Project Public License, either version 1.3c
% of this license or (at your option) any later version.
% The latest version of this license is in
%   http://www.latex-project.org/lppl.txt
% and version 1.3c or later is part of all distributions of LaTeX 
% version 2005/12/01 or later.
%
% This work has the LPPL maintenance status `maintained'.
%
% The Current Maintainer of this work is Elijah Z Granet

  %%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% to show the package only works with Lua
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
  \RequirePackage{iftex}
  \ifPDFTeX {
    \PackageError{luaquotes}
      {You are using pdfTeX but this package only works 
      \MessageBreak with LuaTeX}{}
  }
\else\ifXeTeX{    \PackageError{luaquotes}
      {You are using XeTeX but this package only works 
      \MessageBreak with LuaTeX}{}
}\fi\fi
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Dependency
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
  \RequirePackage{luacode} 
  %%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% fontspec for the auxiliary 
% quotes where tligs need
% to be disabled
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
  \RequirePackage{fontspec}
  %%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% removing the effects for monospace
%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{luacode}
local uchar = unicode.utf8.char
  fonts.handlers.otf.addfeature{
    name = "qtbye",
    type = "substitution",
    data =
    {
   “ = 0x0022,
” = 0x0022,
’ = 0x0027,
« = 0x0022,
» = 0x0022,
‹ = 0x0027,
› = 0x0027
 },
  }
  \end{luacode}
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Code here and throughout similar 
%functions  partly adapted from TeX.SE user
% Mico 
% https://tex.stackexchange.com/questions/499953/how-to-generate-correct-single-and-double-quotes-in-tex
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%

\luaexec{
function doublequotes ( s )
           return ( s:gsub ( '"(..-)"' , "“\%1”" ) )
         end}

         %%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Assuming ' at the start of the line means an opening quotation mark not an apostrophe
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
\luaexec{function singlequotelinestart ( s )
           return (s:gsub ("^'","‘" )  )
        end}
         

 
% \luaexec{
% function abbrevsingle ( s )
%            return ( s:gsub ( " '(..-) " , " ’\%1 " ) )
%          end}        

\luaexec{function singlequotes ( s )
           return ( s:gsub ( " '"," ‘" ) )
         end}
         
         
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% parentheses
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newcommand{\sqoneleft}{{\addfontfeature{RawFeature={-qtbye,-tlig}}‘}}

\luaexec{function psinglequotes ( s )
           return ( s:gsub ( "\%('",[[(\sqoneleft]] ) )
         end}

\newcommand\singlequotespon{\directlua{
luatexbase.add_to_callback (
   "process_input_buffer" , psinglequotes , "psinglequotes" )
   }}
\newcommand\singlequotespoff{\directlua{luatexbase.remove_from_callback (
   "process_input_buffer" , "psinglequotes" )}}

      
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% DE parentheses
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%\newcommand{\sqoneleft}{{\addfontfeature{RawFeature={-qtbye,-tlig}}‘}}

\luaexec{function depsinglequotes ( s )
           return ( s:gsub ( "\%('",[[(‚]] ) )
         end}

\newcommand\desinglequotespon{\directlua{
luatexbase.add_to_callback (
   "process_input_buffer" , depsinglequotes , "depsinglequotes" )
   }}
\newcommand\desinglequotespoff{\directlua{luatexbase.remove_from_callback (
   "process_input_buffer" , "depsinglequotes" )}}

\luaexec{function depsinglequotesclose ( s )
           return ( s:gsub ( "'\%)",[[\sqoneleft)]] ) )
         end}

\newcommand\desinglequotespcloseon{\directlua{
luatexbase.add_to_callback (
   "process_input_buffer" , depsinglequotesclose , "depsinglequotesclose" )
   }}
\newcommand\desinglequotespcloseoff{\directlua{luatexbase.remove_from_callback (
   "process_input_buffer" , "depsinglequotesclose" )}}



%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% FR Parentheses
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newcommand{\sglmtlp}{{\addfontfeature{RawFeature={-qtbye,-tlig}}‹\hskip .16667em}}
\newcommand{\sglmtrp}{{\addfontfeature{RawFeature={-qtbye,-tlig}}\hskip .16667em›}}

\luaexec{function frpsinglequotes ( s )
           return ( s:gsub ( "\%('",[[(\sglmtlp]] ) )
         end}
\luaexec{function frpsinglequotesclose ( s )
           return ( s:gsub ( "'\%)",[[\sglmtrp)]] ) )
         end}

\newcommand\frsinglequotespon{\directlua{
luatexbase.add_to_callback (
   "process_input_buffer" , frpsinglequotes , "frpsinglequotes" )
   }}
\newcommand\frsinglequotespoff{\directlua{luatexbase.remove_from_callback (
   "process_input_buffer" , "frpsinglequotes" )}}
\newcommand\frsinglequotespcloseon{\directlua{
luatexbase.add_to_callback (
   "process_input_buffer" , frpsinglequotesclose , "frpsinglequotesclose" )
   }}
\newcommand\frsinglequotespcloseoff{\directlua{luatexbase.remove_from_callback (
   "process_input_buffer" , "frpsinglequotesclose" )}}

%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% DECH Parentheses
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newcommand{\sglmtlpdech}{{\addfontfeature{RawFeature={-qtbye,-tlig}}‹}}
\newcommand{\sglmtrpdech}{{\addfontfeature{RawFeature={-qtbye,-tlig}}›}}

\luaexec{function dechpsinglequotes ( s )
           return ( s:gsub ( "\%('",[[(\sglmtlpdech]]) )
         end}
\luaexec{function dechpsinglequotesclose ( s )
           return ( s:gsub ( "'\%)",[[\sglmtrpdech)]]) )
         end}

\newcommand\dechsinglequotespon{\directlua{
luatexbase.add_to_callback (
   "process_input_buffer" , dechpsinglequotes , "dechpsinglequotes" )
   }}
\newcommand\dechsinglequotespoff{\directlua{luatexbase.remove_from_callback (
   "process_input_buffer" , "dechpsinglequotes" )}}
\newcommand\dechsinglequotespcloseon{\directlua{
luatexbase.add_to_callback (
   "process_input_buffer" , dechpsinglequotesclose , "dechpsinglequotesclose" )
   }}
\newcommand\dechsinglequotespcloseoff{\directlua{luatexbase.remove_from_callback (
   "process_input_buffer" , "dechpsinglequotesclose" )}}

%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% activation and deactivation
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newcommand\doublequoteson{\directlua{luatexbase.add_to_callback (
   "process_input_buffer" , 
   doublequotes , 
   "doublequotes" )}}
\newcommand\doublequotesoff{\directlua{luatexbase.remove_from_callback (
   "process_input_buffer" , 
   "doublequotes" )}}
% \newcommand\abbrevsingleon{\directlua{luatexbase.add_to_callback (
%    "process_input_buffer" , 
%    abbrevsingle , 
%    "abbrevsingle" )}}
% \newcommand\abbrevsingleoff{\directlua{luatexbase.remove_from_callback (
%    "process_input_buffer" , 
%    "abbrevsingle" )}}

\newcommand\singlequotelinestarton{\directlua{
luatexbase.add_to_callback (
   "process_input_buffer" , singlequotelinestart , "singlequotelinestart" )
   }}
\newcommand\singlequotelinestartoff{\directlua{
luatexbase.remove_from_callback (
   "process_input_buffer" , "singlequotelinestart" )
   }}
\newcommand\singlequoteson{\directlua{
luatexbase.add_to_callback (
   "process_input_buffer" , singlequotes , "singlequotes" )
   }}
\newcommand\singlequotesoff{\directlua{luatexbase.remove_from_callback (
   "process_input_buffer" , "singlequotes" )}}
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% global functions, useful for things like this
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
   \newcommand{\smartquotes}{%
\doublequoteson%
\singlequotelinestarton%
% \abbrevsingleon%
\singlequoteson
\singlequotespon}
   \newcommand{\dumbquotes}{
   \doublequotesoff
% \abbrevsingleoff
   \singlequotelinestartoff
   \singlequotesoff
   \singlequotespoff
   }
   
       \DeclareOption{en}{
\AtBeginDocument{\dechsmartquotes\dechdumbquotes\frsmartquotes\frdumbquotes\desmartquotes\dedumbquotes\degmsmartquotes\degmdumbquotes\smartquotes}
\renewcommand{\texttt}[1]{{\ttfamily\addfontfeature{RawFeature={+qtbye,-tlig}} #1}}
    }

%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% auxiliary punctuation
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Essentially to be used where the
% thing fails to provide the 
% quotation or 
% quote like punctuation
% needed 
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% German quotations
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newcommand{\desingle}{{\addfontfeature{RawFeature={-qtbye,-tlig}}\symbol{"201A}}}
\newcommand{\dedouble}{{\addfontfeature{RawFeature={-qtbye,-tlig}}\symbol{"201E}}}
\newcommand{\degmsingle}{{\addfontfeature{RawFeature={-qtbye,-tlig}}\symbol{"203A}}}
\newcommand{\degmdouble}{{\addfontfeature{RawFeature={-qtbye,-tlig}}\symbol{"00BB}}}
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% backtick
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newcommand{\bcktck}{{\addfontfeature{RawFeature={-qtbye,-tlig}}`}}
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Straight double 
% and single quotes
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%

\newcommand{\dqone}{{\addfontfeature{RawFeature={-qtbye,-tlig}}\symbol{"0027}}}
\newcommand{\dqtwo}{{\addfontfeature{RawFeature={-qtbye,-tlig}}\symbol{"0022}}}
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Prime, mostly for 
% Feet and inches
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newcommand{\lqprime}{′}
\newcommand{\lqdoubleprime}{″}
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% The Okina, for typing 
% Hawaiʻi
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newcommand{\okina}{ʻ}
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% The individual smart quotes
% 
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newcommand{\sqtwoleft}{{\addfontfeature{RawFeature={-qtbye,-tlig}}“}}
\newcommand{\sqtworight}{{\addfontfeature{RawFeature={-qtbye,-tlig}}”}}
\newcommand{\sqoneright}{{\addfontfeature{RawFeature={-qtbye,-tlig}}’}}
\newcommand{\apost}{{\addfontfeature{RawFeature={-qtbye,-tlig}}’}}
%sqoneleft  command moved because order mattered
\newcommand{\glmtl}{{\addfontfeature{RawFeature={-qtbye,-tlig}}«\,}}
\newcommand{\glmtr}{{\addfontfeature{RawFeature={-qtbye,-tlig}}\,»}}
\newcommand{\sglmtl}{{\addfontfeature{RawFeature={-qtbye,-tlig}}‹\,}}
\newcommand{\sglmtr}{{\addfontfeature{RawFeature={-qtbye,-tlig}}\,›}}

\newcommand{\degmtl}{{\addfontfeature{RawFeature={-qtbye,-tlig}}»}}
\newcommand{\degmtr}{{\addfontfeature{RawFeature={-qtbye,-tlig}}«}}
\newcommand{\desgmtl}{{\addfontfeature{RawFeature={-qtbye,-tlig}}›}}
\newcommand{\desgmtr}{{\addfontfeature{RawFeature={-qtbye,-tlig}}‹}}
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% DEUTSCH
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
\luaexec{function dedoublequotes ( s )
           return ( s:gsub ( '"(..-)"' , "„\%1“" ) )
         end}
\luaexec{function desinglequotelinestart ( s )
           return (s:gsub ("^'","‚" )  )
        end}
\luaexec{function desinglequotesclose( s )
return ( s:gsub ( " '(..-)'", " ‚\%1`" ) )
         end}

%% Two utility macros to activate/deactivate the Lua function:
\newcommand\dedoublequoteson{\directlua{luatexbase.add_to_callback (
   "process_input_buffer" , dedoublequotes , "dedoublequotes" )}}
\newcommand\dedoublequotesoff{\directlua{luatexbase.remove_from_callback (
   "process_input_buffer" , "dedoublequotes" )}}
\newcommand\desinglequotelinestarton{\directlua{luatexbase.add_to_callback (
   "process_input_buffer" , desinglequotelinestart , "desinglequotelinestart" )}}
\newcommand\desinglequotelinestartoff{\directlua{luatexbase.remove_from_callback (
   "process_input_buffer" , "desinglequotelinestart" )}}
   \newcommand\desinglequotescloseon{\directlua{luatexbase.add_to_callback (
   "process_input_buffer" , desinglequotesclose , "desinglequotesclose" )}}
\newcommand\desinglequotescloseoff{\directlua{luatexbase.remove_from_callback (
   "process_input_buffer" , "desinglequotesclose" )}}
   \newcommand{\desmartquotes}{\dedoublequoteson
\desinglequotelinestarton
\desinglequotescloseon
\desinglequotespon
\desinglequotespcloseon
}
   \newcommand{\dedumbquotes}{\dedoublequotesoff
\desinglequotelinestartoff
\desinglequotescloseoff
\desinglequotespoff
\desinglequotespcloseoff
}
   \DeclareOption{de}{
\AtBeginDocument{
\dechsmartquotes\dechdumbquotes
\frsmartquotes
\frdumbquotes
\smartquotes
\dumbquotes\dumbquotes
\desmartquotes}
\renewcommand{\texttt}[1]{{\ttfamily\addfontfeature{RawFeature={+qtbye,-tlig}} #1}}
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% SCHÖNERES DEUTSCH
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
\luaexec{function degmdoublequotes ( s )
           return ( s:gsub ( '"(..-)"' , "»\%1«" ) )
         end}
\luaexec{function degmsinglequotelinestart ( s )
           return (s:gsub ("^'","›" )  )
        end}
\luaexec{function degmsinglequotesclose( s )
return ( s:gsub ( " '(..-)'", " ‚\%1‹" ) )
         end}

%% Two utility macros to activate/deactivate the Lua function:
\newcommand\degmdoublequoteson{\directlua{luatexbase.add_to_callback (
   "process_input_buffer" , degmdoublequotes , "degmdoublequotes" )}}
\newcommand\degmdoublequotesoff{\directlua{luatexbase.remove_from_callback (
   "process_input_buffer" , "degmdoublequotes" )}}
\newcommand\degmsinglequotelinestarton{\directlua{luatexbase.add_to_callback (
   "process_input_buffer" , degmsinglequotelinestart , "degmsinglequotelinestart" )}}
\newcommand\degmsinglequotelinestartoff{\directlua{luatexbase.remove_from_callback (
   "process_input_buffer" , "degmsinglequotelinestart" )}}
   \newcommand\degmsinglequotescloseon{\directlua{luatexbase.add_to_callback (
   "process_input_buffer" , degmsinglequotesclose , "degmsinglequotesclose" )}}
\newcommand\degmsinglequotescloseoff{\directlua{luatexbase.remove_from_callback (
   "process_input_buffer" , "degmsinglequotesclose" )}}
   \newcommand{\degmsmartquotes}{\degmdoublequoteson
\degmsinglequotelinestarton
\degmsinglequotescloseon}
   \newcommand{\degmdumbquotes}{\degmdoublequotesoff
\degmsinglequotelinestartoff
\degmsinglequotescloseoff}
   \DeclareOption{degm}{
\AtBeginDocument{
\dechsmartquotes\dechdumbquotes
\frsmartquotes
\frdumbquotes
\smartquotes
\dumbquotes\dumbquotes
\degmsmartquotes}
\renewcommand{\texttt}[1]{{\ttfamily\addfontfeature{RawFeature={+qtbye,-tlig}} #1}}
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Français
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
\luaexec{function frdoublequotes ( s )
           return ( s:gsub ( '"(..-)"' , "«\\,\%1\\,»" ) )
         end}


\luaexec{function frsinglequotelinestart ( s )
           return (s:gsub ("^'","'" )  )
        end}
\luaexec{function frsinglequotesclose( s )
return ( s:gsub ( " '(..-)'", " ‹\\,\%1\\,›" ) )
         end}

%% Two utility macros to activate/deactivate the Lua function:
\newcommand\frdoublequoteson{\directlua{luatexbase.add_to_callback (
   "process_input_buffer" ,frdoublequotes , "frdoublequotes" )}}
\newcommand\frdoublequotesoff{\directlua{luatexbase.remove_from_callback (
   "process_input_buffer" , "frdoublequotes" )}}
\newcommand\frsinglequotelinestarton{\directlua{luatexbase.add_to_callback (
   "process_input_buffer" ,frsinglequotelinestart , "frsinglequotelinestart" )}}
\newcommand\frsinglequotelinestartoff{\directlua{luatexbase.remove_from_callback (
   "process_input_buffer" , "frsinglequotelinestart" )}}
   \newcommand\frsinglequotescloseon{\directlua{luatexbase.add_to_callback (
   "process_input_buffer" ,frsinglequotesclose , "frsinglequotesclose" )}}
\newcommand\frsinglequotescloseoff{\directlua{luatexbase.remove_from_callback (
   "process_input_buffer" , "frsinglequotesclose" )}}
   \newcommand{\frsmartquotes}{\frdoublequoteson
   \frsinglequotespon
   \frsinglequotespcloseon
\frsinglequotelinestarton
\frsinglequotescloseon}
   \newcommand{\frdumbquotes}{\frdoublequotesoff
   \frsinglequotespoff
   \frsinglequotespcloseoff
\frsinglequotelinestartoff
\frsinglequotescloseoff}
   \DeclareOption{fr}{
\AtBeginDocument{\dechsmartquotes\dechdumbquotes\desmartquotes\dedumbquotes\degmsmartquotes\degmdumbquotes\smartquotes\dumbquotes\dumbquotes\frsmartquotes}
\renewcommand{\texttt}[1]{{\ttfamily\addfontfeature{RawFeature={+qtbye,-tlig}} #1}}


}

%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Deutsch (Schweiz) 
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
\luaexec{function dechdoublequotes ( s )
           return ( s:gsub ( '"(..-)"' , "«\%1»" ) )
         end}


\luaexec{function dechsinglequotelinestart ( s )
           return (s:gsub ("^'","'" )  )
        end}
\luaexec{function dechsinglequotesclose( s )
return ( s:gsub ( " '(..-)'", " ‹\%1›" ) )
         end}
%% Two utility macros to activate/deactivate the Lua function:
\newcommand\dechdoublequoteson{\directlua{luatexbase.add_to_callback (
   "process_input_buffer" ,dechdoublequotes , "dechdoublequotes" )}}
\newcommand\dechdoublequotesoff{\directlua{luatexbase.remove_from_callback (
   "process_input_buffer" , "dechdoublequotes" )}}
\newcommand\dechsinglequotelinestarton{\directlua{luatexbase.add_to_callback (
   "process_input_buffer" ,dechsinglequotelinestart , "dechsinglequotelinestart" )}}
\newcommand\dechsinglequotelinestartoff{\directlua{luatexbase.remove_from_callback (
   "process_input_buffer" , "dechsinglequotelinestart" )}}
   \newcommand\dechsinglequotescloseon{\directlua{luatexbase.add_to_callback (
   "process_input_buffer" ,dechsinglequotesclose , "dechsinglequotesclose" )}}
\newcommand\dechsinglequotescloseoff{\directlua{luatexbase.remove_from_callback (
   "process_input_buffer" , "dechsinglequotesclose" )}}
   \newcommand{\dechsmartquotes}{\dechdoublequoteson
   \dechsinglequotespon
   \dechsinglequotespcloseon
\dechsinglequotelinestarton
\dechsinglequotescloseon}
   \newcommand{\dechdumbquotes}{\dechdoublequotesoff
   \dechsinglequotespoff
   \dechsinglequotespcloseoff
\dechsinglequotelinestartoff
\dechsinglequotescloseoff}
   \DeclareOption{dech}{
\AtBeginDocument{\desmartquotes\dedumbquotes\degmsmartquotes\degmdumbquotes\smartquotes\dumbquotes\dumbquotes\frsmartquotes\frdumbquotes\dechsmartquotes}
\renewcommand{\texttt}[1]{{\ttfamily\addfontfeature{RawFeature={+qtbye,-tlig}} #1}}


}


%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Default option is English
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
\ExecuteOptions{en}% 
  \ProcessOptions*



  

  
\end{minted}
\section{Version History}
\subsection*{\normalfont\texttt{1.4.0}}
\ttfamily Added support for Swiss German options, on user request


\subsection*{\normalfont\texttt{1.3.0}}
\ttfamily 15 January 2023 fixed single quotes and parentheses


\subsection*{\normalfont\texttt{1.2.2}}
\ttfamily Added the "degm" option

\subsection*{\normalfont\texttt{1.2.1}}
\ttfamily Suspended automatic elision support due to implementation issues

\subsection*{\normalfont\texttt{1.1.0}}
\ttfamily 25 October 2022: Added support for elision


\subsection*{\normalfont\texttt{1.0.1}}



\ttfamily 30 August 2022: Further corrections to bug preventing non-English usage

\subsection*{\normalfont\texttt{1.0.1}}

\ttfamily 28 August 2022: Change bug preventing non-English usage


\subsection*{\normalfont\texttt{1.0.0}}

\ttfamily 21 August 2022: Package creation

	
\end{document}