5

I want to use "Hack" as the default font for source code. Unfortunately the font is missing some glyphs I use. If I use a glyphs that is missing in "Hack", I want it to be displayed automatically in another font (e.g. "Symbola") instead.

\documentclass{article}
\usepackage{fontspec}
\usepackage{verbatim}
\setmonofont{Hack}
%\setmonofont{Symbola} % use Symbola if glyph is missing in Hack
\begin{document}
\begin{verbatim}
- 📂 project-root
    - 🗎 .gitignore (sub)
    - 🖺 README.md (sub)
\end{verbatim}
\end{document}

I use this in a continuous integration process with Pandoc, so I don't know what glyphs are needed. Therefore, a general solution is needed.

So far I have only found a solution for specific glyphs.

3

This is what I could come up with:

\documentclass{article}
\usepackage{fontspec}
\setmonofont{Hack}
\usepackage{verbatim}

\newfontface\Symbola{Symbola}
{\Symbola\global\expandafter\let\expandafter\fallbackfont\the\font}
\usepackage{luacode}
\begin{luacode}
local fontcharacters = { }
local nullfont       = 0
local glyph_t        = nodes.nodecodes.glyph
local fallbackfont   = font.id("fallbackfont")
table.setmetatableindex(fontcharacters, function (t, k)
  if k == true then
    return fontcharacters[currentfont()]
  else
    local tfmdata = fonts.hashes.identifiers[k]
    if not tfmdata then --- unsafe
      tfmdata = font.fonts[k]
      if not (tfmdata and type (tfmdata) == "table") then
        return false
      end
    end
    local characters = tfmdata.characters
    t[k] = characters
    return characters
  end
end)
local nodeprocessor = function (head)
  local lastfont, characters = nil, nil
  for n in node.traverse_id(glyph_t, head) do
    local currfont = n.font
    local char = n.char
    if currfont ~= lastfont and currfont ~= nullfont then
      characters = fontcharacters[currfont]
    end
    if characters ~= false then
      lastfont = currfont
      if not characters[char] then
        n.font = fallbackfont
        if fontcharacters[fallbackfont][char] then
          node.remove(head,node.next(n)) -- remove .notdef char (new in luaotfload 2.98)
        end
      end
    end
  end
  return head, false
end
luatexbase.add_to_callback("pre_linebreak_filter", nodeprocessor, "replace missing glyphs")
\end{luacode}

\begin{document}
\begin{verbatim}
- 📂 project-root
    - 🗎 .gitignore (sub)
    - 🖺 README.md (sub)
\end{verbatim}
\end{document}

result

  • @MarcelKrüger Thanks for your comment, makes sense. And I was wondering how to disable the notdef feature (should check the documentation more often...) – Robert Nov 5 '19 at 0:12
6

While this doesn't use fontspec, you can use Ulrike Fischer's experimental combofont package. This uses luaotfload's built-in support for combining fonts:

\documentclass{article}
\usepackage{verbatim}
\usepackage{combofont}
% Define a combofont for every font in the family
\setupcombofont{hack-symbola-regular}{
  {Hack:\combodefaultfeat} at #1pt,
  {Symbola:\combodefaultfeat} at #1pt
}{
  {},
  fallback
}

\setupcombofont{hack-symbola-bold}{
  {Hack/B:\combodefaultfeat} at #1pt,
  {Symbola:\combodefaultfeat} at #1pt
}{
  {},
  fallback
}

\setupcombofont{hack-symbola-italic}{
  {Hack/I:\combodefaultfeat} at #1pt,
  {Symbola:\combodefaultfeat} at #1pt
}{
  {},
  fallback
}

\setupcombofont{hack-symbola-bolditalic}{
  {Hack/BI:\combodefaultfeat} at #1pt,
  {Symbola:\combodefaultfeat} at #1pt
}{
  {},
  fallback
}

% Now set up the family
\DeclareFontFamily{TU}{hack-symbola}{}
\DeclareFontShape{TU}{hack-symbola}{m}{n} {<->combo*hack-symbola-regular}{}
\DeclareFontShape{TU}{hack-symbola}{bx}{n} {<->combo*hack-symbola-bold}{}
\DeclareFontShape{TU}{hack-symbola}{m}{it} {<->combo*hack-symbola-italic}{}
\DeclareFontShape{TU}{hack-symbola}{bx}{it} {<->combo*hack-symbola-bolditalic}{}
\renewcommand \ttdefault {hack-symbola}

\begin{document}
\begin{verbatim}
- 📂 project-root
    - 🗎 .gitignore (sub)
    - 🖺 README.md (sub)
\end{verbatim}
\end{document}

This sets up the entire family of Hack, if you only need the regular one (This is the only one used by verbatim as far as I know) you can make it much shorter:

\documentclass{article}
\usepackage{verbatim}
\usepackage{combofont}
% Define a combofont for every font in the family
\setupcombofont{hack-symbola-regular}{
  {Hack:\combodefaultfeat} at #1pt,
  {Symbola:\combodefaultfeat} at #1pt
}{
  {},
  fallback
}

% Now set up the family
\DeclareFontFamily{TU}{hack-symbola}{}
\DeclareFontShape{TU}{hack-symbola}{m}{n} {<->combo*hack-symbola-regular}{}
\renewcommand \ttdefault {hack-symbola}

\begin{document}
\begin{verbatim}
- 📂 project-root
    - 🗎 .gitignore (sub)
    - 🖺 README.md (sub)
\end{verbatim}
\end{document}

enter image description here

  • Works very well, thank you! I accepted Robert's solution because it works with fontspec. If you don't need it, yours is perfect. – Benjamin Buch Nov 6 '19 at 13:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.