0

So, I'm trying to do some hacking related to the \bibhyperref command from the package biblatex. I want to modify this command because in line 552 of the file biblatex.def we would find

\DeclareFieldFormat{bibhyperref}{\bibhyperref{#1}}

In my naive understanding, I think this means that basically all hyper references in the biblatex are handled by the command \bibhyperref through some other commands like \printfield[bibhyperref]{...} or \printtext[bibhyperref]{...} which may then be expanded as \bibhyperref{...}.

So next I try to find the definition (source code) of the command \bibhyperref so that I can hack it. I have searched the tex directory, but it seems that there exists no something which looks like a definition \def\bibhyperref... or \newcommand\bibhyperref... et al.

enter image description here

So I'm very confused about where exactly (in which line of which file) is this command defined? Or maybe my naive understanding of how hyper references works in biblatex is wrong and I should find some other commands to hack?

Also, is there a good strategy to do this in the future when I again need to find the definition of a command? Does there exist some kind of index or manual that record those kinds of information?

  • 6
    it is defined in biblatex.sty, but the definition method is rather special as the command is only active inside biblatex commands. I don't think that you should hack it. Better ask a question about your real problem so that someone can tell you a saner solution. – Ulrike Fischer Nov 10 '21 at 10:17
  • So, my actual need is to add underline to the biblatex hyper references following this trick. I understand that there exist other, easier method to realize this using the border of the hyperref. – Qi Tianluo Nov 10 '21 at 10:54
  • 1
    Maybe there is https://tex.stackexchange.com/a/17840/250119 (texdef script) although I'm not sure if there's a good way for this case // alternatively check the source code documentation if it exists – user202729 Nov 10 '21 at 10:54
  • But, 1) I find that in Mac Preview this underline reduces to an ugly box, so I assume that this underline is actually not machine and application-independent. 2) if the title is too long such that line break is implemented in the Table of Contents, then some extra underline where no text exists will show up. – Qi Tianluo Nov 10 '21 at 10:57
  • 2
    I wouldn't use \uline to underline links. Links typically contain special chars and this is bound to break. Imho only lualatex + lua-ul would be safe here. Setting pdfborder has some drawbacks, but it is easier to use and it doesn't print. – Ulrike Fischer Nov 10 '21 at 11:09
  • So you mean that lua-ul may be a better solution to implement the line break of the hyperlink? – Qi Tianluo Nov 10 '21 at 11:13

1 Answers1

2

In general grepping for \def<commandname>, \let<commandname>, \newcommand<commandname>, \NewDocumentCommand<commandname> (possibly without and with curly braces around <commandname> in the latter two cases) is a good start to find out about a command, but LaTeX is fairly flexible in how it allows commands to be defined, so it is impossible to give a finite list of search strings to identify all possible ways in which <commandname> could be defined.

For \bibhyperref specifically Ulrike already gave the right hint in the comments. That command is only defined in a biblatex context and has a different name outside of these contexts. This makes sure that the command cannot be used when it does not make sense and avoids name clashes with other packages.

One could argue that the command is defined in ll. 11635-11636 of biblatex.sty (v3.16)

\blx@regimcs{%
  \bibhyperref \bibhyperlink \bibhypertarget \ifhyperref}

Roughly speaking, \blx@regimcs makes sure that \<commandname> has the meaning of \blx@imc@<commandname> in biblatex contexts. So bibhyperref is defined in terms of \blx@imc@bibhyperref.

\blx@imc@bibhyperref has two possible definitions depending on whether hyperref is loaded or not (ll. 11588-11633 of biblatex.sty (v3.16))

%  hyperref interface
\appto\blx@mkhyperref{%
  \protected\def\blx@imc@bibhyperref{%
    \@ifnextchar[%]
      {\blx@bibhyperref}
      {\blx@bibhyperref[\abx@field@entrykey]}}%
  \ifundef\hyper@natanchorstart
    {\long\def\blx@bibhyperref[#1]#2{%
       \blx@sfsave\hyperlink{cite.\the\c@refsection @#1}{\blx@sfrest
         #2%
       \blx@sfsave}\blx@sfrest}%
     \protected\long\def\blx@imc@bibhyperlink#1#2{%
       \blx@sfsave\hyperlink{cite.\the\c@refsection:#1}{\blx@sfrest
         #2%
       \blx@sfsave}\blx@sfrest}%
     \protected\long\def\blx@imc@bibhypertarget#1#2{%
       \blx@sfsave\hypertarget{cite.\the\c@refsection:#1}{\blx@sfrest
         #2%
       \blx@sfsave}\blx@sfrest}}%
    {\long\def\blx@bibhyperref[#1]#2{%
       \blx@sfsave\hyper@natlinkstart{\the\c@refsection @#1}\blx@sfrest
       #2%
       \blx@sfsave\hyper@natlinkend\blx@sfrest}%
     \protected\long\def\blx@imc@bibhyperlink#1#2{%
       \blx@sfsave\hyper@natlinkstart{\the\c@refsection:#1}\blx@sfrest
       #2%
       \blx@sfsave\hyper@natlinkend\blx@sfrest}%
     \protected\long\def\blx@imc@bibhypertarget#1#2{%
       \blx@sfsave\hyper@natanchorstart{\the\c@refsection:#1}\blx@sfrest
       #2%
       \blx@sfsave\hyper@natanchorend\blx@sfrest}}
  \let\blx@imc@ifhyperref\@firstoftwo
  \def\blx@sf{\spacefactor}%
  \def\blx@sfsave{%
    \blx@leavevmode
    \numgdef\blx@sf{\spacefactor}}%
  \def\blx@sfrest{%
    \ifhmode\spacefactor\blx@sf\relax\fi
    \gdef\blx@sf{\spacefactor}}}

\appto\blx@mknohyperref{% \protected\def\blx@imc@bibhyperref{@ifnextchar[\blx@nohyperref@firstofone}% \def\blx@nohyperref[#1]#2{#2}% \let\blx@imc@bibhyperlink@secondoftwo \let\blx@imc@bibhypertarget@secondoftwo \let\blx@imc@ifhyperref@secondoftwo}

I agree with Ulrike that it is probably not a great idea to try and manipulate this command directly.


I don't think there is a silver bullet for these kind of questions. A big chunk of cases can probably be dealt with if you just look for \def, \let, \newcommand and friends. But it is always possible that a package uses complex constructions to define the macro you are interested in. A script like latexdef (Where do I find out how a command/environment is defined?) can be helpful, but might not catch all the weird ways in which a package might define commands.

If you know which package defines your macro (e.g. because you can verify that with the documentation), you can narrow down your searches for that macro to files belonging to that package. So for \bibhyperref, where you can check that biblatex defines that command, you probably want to start grepping only in tex/latex/biblatex and not in style directories like tex/latex/biblatex-chicago.

From then on, there is no guaranteed way. I usually search for \<commandname> first and try to filter out which hits are uses of the macro and which look like they could be definitions. But sometimes it also helps to search for <commandname> without the leading backslash because there are several ways to define macros without giving the backslash in the definition. This can also turn up similarly named helper macros, which may or may not give you a sense where to look.

In the whole biblatex subtree there are only three hits for \bibhyperref. Two look like obvious uses of the macro. So the third one in \blx@regimcs is a candidate for the definition. To check if it is the right one, you'd need to check out the definition of \blx@regimcs and see what it does. From there you would find your way to \blx@imc@bibhyperref. But that may take a while and it definitely helps if you have some overall experience with the package you are dealing with.

moewe
  • 175,683