8

Does anyone have an example for a search & replace lua script that I can use with TeXworks. I have a rather large document here (about 3'000 pages DIN A5) which I need to update continously. To change $to \$ and various other replacements I would like to run a 'replace-all' script which makes all the replacements in a single run.

This could be quite useful when one has to take text from e.g. MS Word or the WWW.

5
  • 2
    Would you be interested in a sed or perl solution?
    – cmhughes
    Nov 28, 2012 at 16:45
  • Nope, I would like to have one in Texworks' lua scripting. Nov 28, 2012 at 17:13
  • 1
    There is a menu item to do this with TeXworks from Search/Replace. However, I would advise you to quit TeXworks, restart, and open a new blank document to test this with first. Trying it with v4.4 on Mac hangs Texworks, and had to Force Quit to get out of this loop. Nov 28, 2012 at 18:21
  • @PeterGrill I know the menu command but there are various replacements I need to make, so a 'prepare for TeXing' script would be nice. It could aid a lot in the "get-text-from-somewhere-and-just-TeX" it process, replacing # => \#, & => \& and many more. Nov 28, 2012 at 19:34
  • @UweZiegenhagen Scripts and utilities are nice, danger when you start replacing automatically especially symbols like \& is you can end destroying some of your tables, although I guess in your case you want to clean the original MS Word document. However, in this case would be simpler to clean it in word before exporting. Nov 28, 2012 at 22:14

1 Answer 1

13

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:

Preferences

We just need to mark the checkbox. :)

Now, let's see where to put our script. Go to Scripts, Scripting TeXworks, Show Scripts Folder:

Scripts menu

The operating system file manager will appear with the folder we want. :)

Scripts folder

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:

New file

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:

Reload scripts

Done. :) Let's create a test file:

My document

Time to run our script. Simply go to Scripts and select Replace list:

Running the script

Now, the magic of TeXworks scripting API will appear. First, we will define a list of patterns to look for:

List of patterns

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:

Replacements

Of course, both lists have to have the very same size. :) After we click OK, our new text is presented:

New document

There we go! :) I hope my humble answer helps. :)

2
  • That looks really good and is accepted! I will try and adapt it so, that the replacement list is stored in the script itself. Nov 28, 2012 at 21:09
  • @Uwe: I added some comments to the Lua code. :) If you plan to hardcode the replacement list, I think the script will become more bulletproof - parsing the comma-separated list might be tricky, specially if special characters (used by Lua's regex) are used. Nov 28, 2012 at 22:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .