6

Is there a way to define a macro like {#1}/{#2} to abbreviate the command \frac{#1}{#2}?

  • 1
    Which engine do you use? It should be pretty easy to do with LuaLaTeX and pattern-matching in a text processing callback. – TeXnician Jun 8 '18 at 17:06
  • I generally use pdftex. Is there a solution with that? – Subhajit Paul Jun 8 '18 at 17:08
  • 1
    With pdftex it's pretty hard to do without a control-word (something like \f{#1}/{#2}, but then you could also write \frac. Maybe you could do it by making an active "start-fraction" character, an active "end-fraction" character and turn slash into an active character as well. – TeXnician Jun 8 '18 at 17:09
  • 1
    what editor are you using? maybe you can define short cuts for your needs – naphaneal Jun 8 '18 at 17:11
  • 2
    @SubhajitPaul If you want / to always mean \frac in that sense, you can do \mathcode`\/="8000 \begingroup\lccode`\~=`\/\lowercase{\endgroup\let~\over}. Then you just use {x/y} (never forget the outer {..}). But the construction might be fragile if you don't know what you want. – Manuel Jun 8 '18 at 17:20
16

The OP has indicated a preference for a pdfLaTeX-based solution. However, since I don't know how to provide such a solution, I'm providing a LuaLaTeX-based solution instead. Maybe readers who don't mind using (or actually prefer to use!) LuaLaTeX will find it useful.

enter image description here

The Lua function is set up to capture and process expressions of the form

{...}/{...}

The mandatory elements for a pattern match to occur are (a) two pairs of matching curly braces, (b) the / symbol, and (c) no whitespace to the left and right of /. If these three elements aren't found, no pattern match occurs, and no `\frac{...}{...} expression is produced.

Edit: The function can now handle nested expressions such as {{a}/{b}}/{{c}/{d}}; that'll produce \frac{\frac{a}{b}}{\frac{c}{d}}.

The code shown below also sets up two LaTeX macros: \InlineToFracStart and \InlineToFracStop. The former activates the Lua function, the latter disables it. Having these macros may be useful, as running the Lua function imposes some overhead in terms of scanning and processing the input lines. For instance, if it's known that the document contains expressions of the form {a}/{b} in sections 2 and 3, but not elsewhere, one could run \InlineToFracStart at the start of section 2 and rund \InlineToFracStop at the end of section 3. (Of course, if you don't mind or care about incurring overhead and just want to have the Lua function cover the entire document, simply run \InlineToFracStart just before or after the \begin{document} statement.)

% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{luacode}
%% Lua-side code
\begin{luacode}
function inline2frac ( s )
   s = s:gsub ( "(%b{})/(%b{})" , function (x,y)
                    x = inline2frac ( x )
                    y = inline2frac ( y )            
                    return "\\frac{"..x.."}{"..y.."}"  
                end ) 
   return s
end
\end{luacode}
%% TeX-side code: macros to enable and disable the Lua function
\newcommand\InlineToFracStart{\directlua{luatexbase.add_to_callback(
   "process_input_buffer", inline2frac, "inline2frac" )}}
\newcommand\InlineToFracStop{\directlua{luatexbase.remove_from_callback(
   "process_input_buffer", "inline2frac" )}}

\begin{document}
\InlineToFracStart % enable the Lua function

$\displaystyle {a}/{b} \quad {{a}/{c}}/{b} 
  \quad {{a}/{b}}/{{u}/{{v}/{{w}/{{x}/{y}}}}} \quad a/b$
\end{document}
  • 1
    Nice, +1. Doesn't nest, but well... (try {{a}/{c}}/{b}) – Rmano Jun 8 '18 at 18:56
  • 1
    @Rmano - Nice suggestion to make the function handle nested inline-style fractional expressions! I've updated the code to make the Lua function (self-)recursive. As a result, it can now handle nested expressions such as your example, viz., {{a}/{c}}/{b}. – Mico Jun 8 '18 at 19:56
  • 1
    @Dr.ManuelKuehner - For my own stuff, I indeed do pretty much everything with LuaLaTeX these days. (Actually, I've recently switched to LuaJITLaTeX, as it has become quite stable and appears to be significantly faster than LuaLaTeX.) For papers I submit to journals, though, it's still mostly pdfLaTeX. Sob... – Mico Jun 8 '18 at 19:57
  • 1
    I posted a new note app in the chat - maybe it is interesting for you since you use a lot of code. – Dr. Manuel Kuehner Jun 8 '18 at 20:16
  • 1
    @Dr.ManuelKuehner - I'll take a look at the boostnote app. – Mico Jun 8 '18 at 20:35
10

Without LuaTeX, as the OP indicates as preference, you could use the primitive \over command: {a\over b}. You can then use this to do (almost) exactly what you propose:

Edit: @Manuel points out that making it math active is better:

\documentclass{article}
\begin{document}
\mathcode`\/="8000
{\catcode`/=13\global\let/\over}
A/B % <- no effect
\[ {over the line/under the line} \]
\end{document}

Remember to enclose the slash with braces: {}. E.g. {abc/def} works, but abc/def will probably not work as expected, because everything on the right of the / will now in mathmode become a fraction, unless you use the braces {./.}.

Previous answer:

\documentclass{article}
\begin{document}
\catcode`/=13
\def/{\ifmmode\over\else\char`\/\fi}
A/B \[ {over the line/under the line} \]
\end{document}

Beware. In both cases, you'd always get a fraction with the slash operator in math mode.

  • 2
    I think it's better to just make it math active: \mathcode`\/="8000 \begingroup\lccode`\~=`\/\lowercase{\endgroup\let~\over}. – Manuel Jun 8 '18 at 17:39
  • I believe you that it is probably better, but why? – Andreas Storvik Strauman Jun 8 '18 at 17:40
  • 1
    You just avoid defining it outside math mode, plus it keeps its catcode in case it's useful for something else, e.g., \numexpr 2/4\relax. – Manuel Jun 8 '18 at 17:42
  • 1
    And just note that the outside {..} are mandatory (otherwise unexpected results may arise). – Manuel Jun 8 '18 at 17:54
  • 1
    other advantage of being only math active is that it still works in \numexpr, even in math mode: \[{\the\numexpr 355/113\relax}\] – user4686 Jun 9 '18 at 21:15
1

In addition to Mico's version, there is another approach to do this with LuaTeX: Instead of manipulating the input, the actual math noads can be modified before they are typeset. Here the rules for braces are similar to subscripts: If you only have a single math node, no braces are needed. A normal slash can be inserted with //.

\documentclass{article}
\usepackage{luacode,amsmath}
\begin{luacode*}
local mathchar = node.id'math_char'
local transform
local function kernel_transform(list)
  if list and list.id == 25 then
    list.head = transform(list.head)
  end
end
function transform(list)
  node.slide(list)
  for n in node.traverse(list) do
    local cur = n
    if n.nucleus and n.nucleus.id == mathchar and n.nucleus.fam == 1 and n.nucleus.char == 61 then
      local prev, next = node.getboth(n)
      if prev and next then
        if next.nucleus and next.nucleus.id == mathchar and next.nucleus.fam == 1 and next.nucleus.char == 61 then
           prev.next = next
           n.next = next.next
        else
          local new = node.new'fraction'
          new.num = node.new'sub_mlist'
          new.denom = node.new'sub_mlist'
          new.num.head = prev
          new.denom.head = next
          new.width = 0x40000000
          new.attr = node.copy_list(n.attr)
          local noad = new
          noad.prev = n.prev.prev
          noad.next = n.next.next
          if prev.prev then
            prev.prev.next = noad
          else
            list = noad
          end
          if next.next then
            next.next.prev = noad
          end
          prev.next = nil
          next.next = nil
          n.next = noad.next
          cur = new
        end
      end
    end
    kernel_transform(cur.nucleus)
    kernel_transform(cur.sub)
    kernel_transform(cur.sup)
    kernel_transform(cur.num)
    kernel_transform(cur.denom)
    kernel_transform(cur.accent)
    kernel_transform(cur.bot_accent)
    kernel_transform(cur.display)
    kernel_transform(cur.text)
    kernel_transform(cur.script)
    kernel_transform(cur.scriptscript)
    kernel_transform(cur.degree)
  end
  return list
end
luatexbase.add_to_callback('mlist_to_hlist', function(list, type, pen)
  list = transform(list)
  return node.mlist_to_hlist(list, type, pen)
end,
'fraction_slash')
\end{luacode*}
\begin{document}

$\displaystyle a/b/c/d/e \quad a/\text{abc} \quad a/c/b 
\quad a/b/{u/{v/{w/{x/y}}}} \quad a//b$
\end{document}

enter image description here

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.