I want to replace all TeXish math $ $
in a tex file by LaTeXish \( \)
and also $$ $$
by \[ \]
. How can I do this cleverly?
Please beware that in TikZ environment, one can not replace $ $
by \( \)
.
editorsscripts
I want to replace all TeXish math $ $
in a tex file by LaTeXish \( \)
and also $$ $$
by \[ \]
. How can I do this cleverly?
Please beware that in TikZ environment, one can not replace $ $
by \( \)
.
Your question is very interesting, I promise to upvote it as soon as possible. As usual, I'm out of votes.
I'll try to write a humble answer. I'm really sorry if the solution might cause any trouble due to any bug or annoyance, I'm a Lua newbie. :)
First things first: we need to enable the scripting language plugin in TeXworks. We can do it by simply going to the Preferences
, in the Scripts
tab:
We just need to mark the checkbox. :)
Now, let's see where to put our script. Go to Scripts
, Scripting TeXworks
, Show Scripts Folder
:
The operating system file manager will appear with the folder we want. :)
In my Mac, it's under ~/Library/TeXworks/scripts
. Now, create a new file named replaceList.lua
and add the following content, as it is:
--[[TeXworksScript
Title: Replace list
Description: A replacement script
Author: Paulo Cereda
Version: 1.0
Date: 2012-11-28
Script-Type: standalone
Context: TeXDocument
]]
-- implements the 'strip' function in order to extract
-- elements from a string according to a specific
-- separator. The output is a table containing each
-- element from the input string.
-- Thanks to the http://lua-users.org/wiki/SplitJoin wiki.
string.split = function(str, pattern)
pattern = pattern or "[^%s]+"
if pattern:len() == 0 then
pattern = "[^%s]+"
end
local parts = {__index = table.insert}
setmetatable(parts, parts)
str:gsub(pattern, parts)
setmetatable(parts, nil)
parts.__index = nil
return parts
end
-- gets a string containing a list of patterns. This is
-- the first dialog window that appears in the script
-- execution.
local listOfPatterns = TW.getText(nil, "List of patterns to replace - 1/2", "Please, add a list of patterns to replace, separated by comma.")
-- gets a string containing a list of words to replace the
-- patterns obtainted in the previous step. This is the
-- second dialog window that appears in the script
-- execution
local listOfReplacements = TW.getText(nil, "List of patterns to replace - 2/2", "Please, add a list of replacements, separated by comma.")
-- checks if both inputs are valid
if (listOfPatterns ~= nil) and (listOfReplacements) then
-- split the patterns into elements of a table. In our
-- case, the separator is a comma.
local patternsToLook = string.split(listOfPatterns, "[^,%s]+")
-- split the values into elements of a table. In our case,
-- the separator is a comma.
local valuesToReplace = string.split(listOfReplacements, "[^,%s]+")
-- the number of elements of both tables must be equal
if (#patternsToLook == #valuesToReplace) then
-- iterate through the patterns table
for index, currentValue in ipairs(patternsToLook) do
-- select all the text from the current
-- document
TW.target.selectAll();
-- get all the selected text
local text = TW.target.selection
-- checks if there's actually a text
if (text ~= nil) then
-- replace all occurrences of the current
-- pattern by its corresponding value
local toReplace, _ = string.gsub(text, currentValue, valuesToReplace[index])
-- insert modified text into the
-- document
TW.target.insertText(toReplace)
end
end
end
end
My sincere apologies to Patrick, Taco and other Lua masters. :)
Now, we have a new file in our folder, replaceList.lua
:
Now, back to TeXworks, we need to reload our list of scripts. It's easy, we need to go to Scripts
, Scripting TeXworks
, Reload Scripts List
:
Done. :)
Let's create a test file:
Time to run our script. Simply go to Scripts
and select Replace list
:
Now, the magic of TeXworks scripting API will appear. First, we will define a list of patterns to look for:
Regex supported, I guess.
I'm telling our script to look for three words, separated by commas. After clicking OK
, a new window will appear, with a list of replacement words:
Of course, both lists have to have the very same size. :)
After we click OK
, our new text is presented:
There we go! :)
I hope my humble answer helps. :)
sed
The stream editing tool, sed
, would be a natural first choice, but the problem is that sed
can't match non-greedy regular expressions.
We need a non-greedy regular expression here- to clarify why, let's consider
sed -r 's/|(.*)|/\\abs{\1}/g' myfile.tex
If we apply this substitution to a file that contains something like
$|a|+|b|\geq|a+b|$
then we'll get
$\abs{a|+|b|\geq|a+b}$
which is clearly not what we want- regular expression matches like this are greedy by default.
To make it non-greedy, we typically use .*?
, but the problem is that sed
does not support this type of match. Happily (thanks Hendrik) we can use the following instead
sed -r 's/\|([^|]*)\|/\\abs{\1}/g' myfile.tex
Once you're comfortable that it does what you want, you can use
sed -ri.bak 's/\|([^|]*)\|/\\abs{\1}/g' myfile.tex
which will overwrite each file, and make a back up first, myfile.tex.bak
perl
We could, instead, use a little perl
one-liner:
perl -pe 's/\|(.*?)\|/\\abs{\1}/g' myfile.tex
When you're sure that you trust it is working correctly, you can use the following to overwrite myfile.tex
perl -pi -e 's/\|(.*?)\|/\\abs{\1}/g' myfile.tex
You can replace myfile.tex
with, for example, *.tex
to operate on all the .tex
files in the current working directory.
Details of perl
's switches are discussed here (for example): http://perldoc.perl.org/perlrun.html#Command-Switches
Best Answer
Here's a
perl
script to get you started,subDollars.pl
. As a disclaimer, you should test it significantly before using it on anything important. I can't guarantee the results, but it should get you started.You can use it in the following way
perl subDollars.pl test.tex
will simply output to the terminal with the substitutionsperl subDollars.pl -s test.tex
will not output to the terminalperl subDollars.pl -w test.tex
will overwritetest.tex
with the substitutions in placeperl subDollars.pl -o test.tex output.tex
will output tooutput.tex
with the substitutions in place.Any environments that you don't want it to operate on should be included in
This hash can consist of stand environments such as
tikzpicture
or any blocks of code that are not necessarily within an environment, but you can wrap them in a 'commented' environment, such as
The script won't account for
$...$
and$$...$$
split across lines- that's certainly doable, but a little more work.subDollars.pl
Here's a test file to test it on
before.tex
after.tex