2

To re-edit a document in a constructed language (latino sine flexione), I need "French" punctuation spacing without side effects.

More specifically, I want a small non-breaking space before any double punctuation marks -- : ; ! ? -- and a regular non-breaking space after an opening or before a closing quotation mark (guillemet) -- « and ».

9
  • 1
    Which TeX engine do you employ to compile your document: pdf(La)TeX, Xe(La)TeX, or Lua(La)TeX? And, do please tell us how the guillemets -- « and » -- are entered: directly as such, or via some macro?
    – Mico
    Commented Feb 3, 2020 at 20:32
  • I currently use pdflatex. It doesn't matter about the quotation marks, I will adapt my input to the solution.
    – user152057
    Commented Feb 3, 2020 at 20:34
  • Are you willing to switch to LuaLaTeX?
    – Mico
    Commented Feb 3, 2020 at 20:34
  • 1
    I don't mind changing compiler.
    – user152057
    Commented Feb 3, 2020 at 20:35
  • 1
    I thought it was clear enough
    – user152057
    Commented Feb 4, 2020 at 10:26

2 Answers 2

2

For pdflatex you can use solution based on changing category code of characters:

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
% saving original quotes representation
\let\gll\guillemotleft
\let\glr\guillemotright
% new quotes representation
\def\frenchguillemotleft{\gll~}
\def\frenchguillemotright{~\glr}
{
    \catcode`\:=\active
    \catcode`\;=\active
    \catcode`\?=\active
    \catcode`\!=\active
    \gdef\frenchpunct{%
        \catcode`\:=\active \def:{\thinspace\char`\: }
        \catcode`\;=\active \def;{\thinspace\char`\; }
        \catcode`\?=\active \def?{\thinspace\char`\? }
        \catcode`\!=\active \def!{\thinspace\char`\! }
        \let\guillemotleft\frenchguillemotleft
        \let\guillemotright\frenchguillemotright
    }
}
\def\nofrenchpunct{%
    \catcode`\:=12
    \catcode`\;=12
    \catcode`\?=12
    \catcode`\!=12
    \let\guillemotleft\gll
    \let\guillemotright\glr
}
\begin{document}
french: french; french? french!
«french»

\frenchpunct
french: french; french? french!
«french»

\nofrenchpunct
french: french; french? french!
«french»
\end{document}

enter image description here

Command \frenchpunct make characters :, ;, ? and ! active and then define them according to desired behaviour: unbreakable thin space before character. Also this command redefine commands \guillemotleft and \guillemotright those are declared by inputenc package.

Command \nofrencpunct change all back.

Remark: the above \frenchpunct command is local. Therefore being enclosed by groping characters {} it take off its effect after leaving group. If you need global command that is canceled only by \nofrenchpunct add \global before all \def (or use \gdef that is alias for \global\def), \catcode and \let in \frenchpunct definition:

\gdef\frenchpunct{%
    \global\catcode`\:=\active \gdef:{\thinspace\char`\: }
    \global\catcode`\;=\active \gdef;{\thinspace\char`\; }
    \global\catcode`\?=\active \gdef?{\thinspace\char`\? }
    \global\catcode`\!=\active \gdef!{\thinspace\char`\! }
    \global\let\guillemotleft\frenchguillemotleft
    \global\let\guillemotright\frenchguillemotright
}

And make same for \nofrenchpunct:

\def\nofrenchpunct{%
    \global\catcode`\:=12
    \global\catcode`\;=12
    \global\catcode`\?=12
    \global\catcode`\!=12
    \global\let\guillemotleft\gll
    \global\let\guillemotright\glr
}
1
  • 2
    In case the tex input file already contains whitespace before :, ;, !, ?, and » or after «, you may want to insert an \unskip directive before \thinspace and change the definitions of \frenchguillemotleft and \frenchguillemotlright to include \ignorespaces and \unskip directives, respectively.
    – Mico
    Commented Feb 4, 2020 at 10:49
7

Here's a LuaLaTeX-based solution. It consists of a Lua function called french_punctuation_spacing that does all of the work and two LaTeX utility macros called \FrenchPunctuationSpacingOn and \FrenchPunctuationSpacingOff, respectively, which activate and deactivate the Lua function.

enter image description here

% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{luacode}  % for 'luacode' environment
\begin{luacode}
function french_punctuation_spacing ( s )
  s = s:gsub ( "[:;!?]" , "\\,%0" )
  s = s:gsub ( "«" , "«~" )
  s = s:gsub ( "»" , "~»" )
  return s
end
\end{luacode}
\newcommand\FrenchPunctuationSpacingOn{\directlua{%
  luatexbase.add_to_callback ( "process_input_buffer",
  french_punctuation_spacing , "frenchpunctuationspacing" )}}
\newcommand\FrenchPunctuationSpacingOff{\directlua{%
  luatexbase.remove_from_callback ( "process_input_buffer",
  "frenchpunctuationspacing" )}}

%\usepackage{fontspec} % optional

\begin{document}
bonjour: monde; oui? non! «aujourd'hui»

\FrenchPunctuationSpacingOn % activate the Lua function
bonjour: monde; oui? non! «aujourd'hui»

\FrenchPunctuationSpacingOff % deactivate the Lua function
bonjour: monde; oui? non! «aujourd'hui»
\end{document}
1
  • 1
    Interesting solution! I definitely upvoted it.
    – user152057
    Commented Feb 3, 2020 at 21:01

You must log in to answer this question.