Is there a way to define a macro like {#1}/{#2} to abbreviate the command \frac{#1}{#2}?
- 760
3 Answers
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.
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}
- 506,678
-
2
-
Do you use LuaTeX as your default LaTeX system by now? (+1 --> Now 10 ;)) – Dr. Manuel Kuehner Jun 08 '18 at 19:48
-
2@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 08 '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 08 '18 at 19:57
-
Thanks!
LuaJITLaTeXseems to be very exotic since a Google search does not lead to a useful result :). No need to explain (I get the Just-in-Time-Compiler part) - I will not use it at the moment (still pdftex). – Dr. Manuel Kuehner Jun 08 '18 at 20:15 -
1I 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 08 '18 at 20:16
-
1
-
@Dr.ManuelKuehner -- For more on LuaJIT(La)TeX, see also When to use LuaJitTeX in favour of LuaTeX? – Mico Jun 09 '18 at 09:05
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.
- 3,635
-
2I think it's better to just make it math active:
\mathcode`\/="8000 \begingroup\lccode`\~=`\/\lowercase{\endgroup\let~\over}. – Manuel Jun 08 '18 at 17:39 -
-
1You 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 08 '18 at 17:42 -
1And just note that the outside
{..}are mandatory (otherwise unexpected results may arise). – Manuel Jun 08 '18 at 17:54 -
1other advantage of being only math active is that it still works in
\numexpr, even in math mode:\[{\the\numexpr 355/113\relax}\]– Jun 09 '18 at 21:15
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}
- 34,151


\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 08 '18 at 17:09pdftexis not an editor. – Mico Jun 08 '18 at 17:15/to always mean\fracin 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 08 '18 at 17:20a/bexpressions. :-) – Mico Jun 08 '18 at 17:28