24

I would like to use the Fira Code OTF font for code listings and verbatim blocks, which has beautiful ligatures. The font loads correctly using the following line:

\setmonofont{FiraCode-Regular}

But I cannot get the ligatures to work, no matter how many combinations of [Ligatures={X}] or [RawFeatures={X}] I try.

Is there any way to make them work with xelatex?

4
  • 1
    What is a ligature in a code listing?
    – A Feldman
    Commented Feb 17, 2016 at 3:38
  • 2
    @AFeldman You should have a look at the Fira Code font that he links to. It contains the examples of the ligature that this font introduces.
    – JP-Ellis
    Commented Feb 17, 2016 at 3:44
  • Welcome! Can you post a complete minimal example people can compile? Does LuaLaTeX work any better?
    – cfr
    Commented Feb 17, 2016 at 3:54
  • @JP-Ellis thanks, kind of freaky looking, but that's from a non-programmer's perspective.
    – A Feldman
    Commented Feb 17, 2016 at 3:54

2 Answers 2

34
+50

Firstly, you'll need to make sure that Fira Code is installed on your computer (which I'm sure you already do).

The font features that Fira Code uses aren't actually listed as ligatures within the OTF, but seems to be fall under Contextuals. In order to use these font features, it is just a matter of enabling the appropriate contextuals:

\documentclass{article}

\usepackage{fontspec}
\setmonofont[
  Contextuals={Alternate}
]{Fira Code}

\begin{document}
\begin{verbatim}
           .= .- := =:=
        == != === !== =/=

    <<- <-- <- <-> -> --> ->>
<=< <<= <==    <=> => ==> =>> >=>
    >>= >>- >-     -< -<< =<<
        <~~ <~ ~~~ ~> ~~>

     <<< << <= <>  >= >> >>>
            <| <|> |>

            <$ <$> $>
            <+ <+> +>
            <* <*> *>

       \\ \\\ {- -} // ///
          /* /** **/ */ 
      </ <!-- www  --> />
      0xF  9:45  m-x *ptr

       ;; ;;; :: ::: !! !!!
       ?? ??? %% %%% && &&& 
       || ||| .. ... ..< []
       -- --- ++ +++ ** ***

          ~= ~- -~ =~ ~@
        ^= ?= /= /== |= ||=
           ## ### ####
         #{ #[ #( #? #_ #_(


a*b a*A B*b A*B *a *A a* A*
a-b a-A B-b A-B -a -A a- A-
a+b a+A B+b A+B +a +A a+ A+
a:b a:A B:b A:B :a :A a: A:
\end{verbatim}
\end{document}

output

Note that I'm still trying to figure out why certain substitutions work (such as .=) but some others don't (such as .-). I suspect it may be do - being converted from the ASCII dash to some other dash.

Just for reference, the ligatures from Fira Code are:

reference

The “missing” ligatures can be obtained by removing the characters verbatim wants to treat in a special way because traditional TeX fonts have ligatures; by default, fontspec doesn't apply Ligatures=TeX to the monospaced font, so there's no risk in redefining \verbatim@noligs@list to empty.

\documentclass{article}

\usepackage{fontspec}

\setmonofont[
  Contextuals={Alternate}
]{Fira Code}

\makeatletter
\def\verbatim@nolig@list{}
\makeatother


\begin{document}

\begin{verbatim}
           .= .- := =:=
        == != === !== =/=

    <<- <-- <- <-> -> --> ->>
<=< <<= <==    <=> => ==> =>> >=>
    >>= >>- >-     -< -<< =<<
        <~~ <~ ~~~ ~> ~~>

     <<< << <= <>  >= >> >>>
            <| <|> |>

            <$ <$> $>
            <+ <+> +>
            <* <*> *>

       \\ \\\ {- -} // ///
          /* /** **/ */ 
      </ <!-- www  --> />
      0xF  9:45  m-x *ptr

       ;; ;;; :: ::: !! !!!
       ?? ??? %% %%% && &&& 
       || ||| .. ... ..< []
       -- --- ++ +++ ** ***

          ~= ~- -~ =~ ~@
        ^= ?= /= /== |= ||=
           ## ### ####
         #{ #[ #( #? #_ #_(


a*b a*A B*b A*B *a *A a* A*
a-b a-A B-b A-B -a -A a- A-
a+b a+A B+b A+B +a +A a+ A+
a:b a:A B:b A:B :a :A a: A:
\end{verbatim}
\end{document}

enter image description here

9
  • Worked great. Thanks! Out of curiosity, what tool did you use to analyze the OTF file? Commented Feb 17, 2016 at 7:25
  • I used fontforge to analyse the OTF file, that's how I figured that Fira Code implements these replacement.
    – JP-Ellis
    Commented Feb 17, 2016 at 9:01
  • 3
    The ligatures with the dashes don't work as the dash is in \verbatim@nolig@list, a command that \verb uses to suppress actively ligatures with these chars. Commented Mar 26, 2017 at 21:47
  • Very nice! +50 in a few days. Commented Dec 14, 2017 at 20:40
  • Thanks @egreg for the edit! Confirms my hunch and fixes most of the ligatures :) Interesting that there's still a couple of ligatures which don't appear (the ones I could notice: ~~~, {- -} =~).
    – JP-Ellis
    Commented Dec 15, 2017 at 4:06
6

It is also possible to use Fira Code in ConTeXt. However, not all ligatures seem to work there. Unfortunately I have no idea why.

\definefontfeature
  [firacode-ligs]
  [mode=node,
   calt=yes]

\starttypescriptcollection[firacode]

  \starttypescript [mono] [firacode]
    \definefontsynonym [FiraCodeBold]    [file:FiraCode-Bold.otf]    [features=firacode-ligs] 
    \definefontsynonym [FiraCodeLight]   [file:FiraCode-Light.otf]   [features=firacode-ligs] 
    \definefontsynonym [FiraCodeMedium]  [file:FiraCode-Medium.otf]  [features=firacode-ligs] 
    \definefontsynonym [FiraCodeRegular] [file:FiraCode-Regular.otf] [features=firacode-ligs] 
    \definefontsynonym [FiraCodeRetina]  [file:FiraCode-Retina.otf]  [features=firacode-ligs] 
  \stoptypescript

  \starttypescript [mono] [firacode] [name]
    \setups[font:fallback:mono]
    \definefontsynonym [Mono]     [FiraCodeRegular]
    \definefontsynonym [MonoBold] [FiraCodeBold]
  \stoptypescript

  \starttypescript [firacode]
    \definetypeface [\typescriptone] [rm] [serif] [modern]   [default] [features=default]
    \definetypeface [\typescriptone] [ss] [sans]  [modern]   [default] [features=default]
    \definetypeface [\typescriptone] [tt] [mono]  [firacode] [default]
    \definetypeface [\typescriptone] [mm] [math]  [modern]   [default] [features=default]
  \stoptypescript

\stoptypescriptcollection

\setupbodyfont[firacode]

\starttext

\starttyping
           .= .- := =:=
        == != === !== =/=

    <<- <-- <- <-> -> --> ->>
<=< <<= <==    <=> => ==> =>> >=>
    >>= >>- >-     -< -<< =<<
        <~~ <~ ~~~ ~> ~~>

     <<< << <= <>  >= >> >>>
            <| <|> |>

            <$ <$> $>
            <+ <+> +>
            <* <*> *>

       \\ \\\ {- -} // ///
          /* /** **/ */ 
      </ <!-- www  --> />
      0xF  9:45  m-x *ptr

       ;; ;;; :: ::: !! !!!
       ?? ??? %% %%% && &&& 
       || ||| .. ... ..< []
       -- --- ++ +++ ** ***

          ~= ~- -~ =~ ~@
        ^= ?= /= /== |= ||=
           ## ### ####
         #{ #[ #( #? #_ #_(


a*b a*A B*b A*B *a *A a* A*
a-b a-A B-b A-B -a -A a- A-
a+b a+A B+b A+B +a +A a+ A+
a:b a:A B:b A:B :a :A a: A:
\stoptyping

\stoptext

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .