Bash (Perl, Python, Tcl/Tk and what not) Scripting from within OmegaT

Situation

So, right now you’re using quite a few scripts while working in OmegaT. Some of them are the ones included in the Scripting Plugin, others are taken from the Internet, several of them were written on your own, and a couple are still cooking in your head, promising to be something that will save you a couple hours of work everyday in future and now hindering you from concentrating on what is at hand. To run them from with a key shortcut you had to assign global key combinations, as from withing OmegaT you can run only 5 custom scripts with a key combo, and those are not just any scripts but the ones that the Scripting Plugin can run.

Problem

Now, with many other scripts and actions used elsewhere for your work/leisure you’re running out of available key combinations, plus you get more and more questions like, “Dad, what you just did doesn’t work on my computer. Do I press it wrong or what’s the matter?” from your elementary-school-aged son.
What you want is an ability to run any script from within OmegaT, not just the ones that the Scripting Plugin can run, as you don’t want to be limited to Java-like languages, but you look for a way to use anything that you’re comfortable with. Besides, these custom scripts should be aware of your current OmegaT project’s variables and settings (like project folders, language pairs etc.) Then at least you’ll be able to say to your son, “Boy, you don’t use OmegaT yet. Let me better show you this combo that you can use on your computer.”

Solution

A solution to the highly probable situation described above would be using a slightly modified version of one of Yu Tang’s groovy scrips that are now included in the Scripting Plugin. The modification will amount to including not only one of project variables (as in original scripts), but as many as you can think of, and passing them not to a text editor/file browser, but to an additional in-between script that can run as many other scripts/programs with or without all the passed variables as you may ever need.
So, here in this recipe we’ll have a groovy script bash_opener.groovy. It needs to be saved among other scripts for the plugin and assigned to one of the available key combinations (Ctrl+Shift+F5 here).
bash_opener
Here’s the text of this script (click to expand)

import javax.swing.JOptionPane;
import org.omegat.util.StaticUtils;
import java.util.Locale
def opener = 'otopener'
def prop = project.getProjectProperties()
if (prop == null) {
def title = "External launcher"
def msg = "Pass project variables to external launcher"
JOptionPane.showMessageDialog(null, msg, title,
JOptionPane.INFORMATION_MESSAGE);
} else {
//dirs
def projroot = prop.getProjectRoot()
def projint = prop.getProjectInternal()
def srcroot = prop.getSourceRoot()
def targroot = prop.getTargetRoot()
def tmroot = prop.getTMRoot()
def glosroot = prop.getGlossaryRoot()
def dictroot = prop.getDictRoot()
def configdir = StaticUtils.getConfigDir()
//files
//def projsav = prop.getProjectInternal() + "project_save.tmx"
def curfile = prop.getSourceRoot() + editor.getCurrentFile()
def writglos = prop.getWriteableGlossary()
//langs
def srclang = prop.getSourceLanguage()
def targlang = prop.getTargetLanguage()
def srclangcode = srclang.getLanguageCode()
def targlangcode = targlang.getLanguageCode()
def srccntrcode = srclang.getCountryCode()
def targcntrcode = targlang.getCountryCode()
def srclanghum = srclang.getDisplayName()
def targlanghum = targlang.getDisplayName()
//locale
def locale = Locale.getDefault() // Java VM's default locale.
def language = locale.getLanguage()
def country = locale.getCountry()
new ProcessBuilder(opener, projroot, projint, srcroot, targroot, tmroot,
glosroot, dictroot, curfile, writglos, configdir, srclangcode,
targlangcode, srccntrcode, targcntrcode, srclanghum, targlanghum,
language, country).start()
}
//  1.	Project Root
//  2.	Project's omegat/
//  3.	Source Root
//  4.	Target Root
//  5.	TM Root
//  6.	Glossary Root
//  7.	Dictionary Root
//  8.	Current file
//  9.	Writable Glossary
// 10.	Config Directory
// 11.	Source Language Code (e.g. EN)
// 12.	Target Language Code (e.g. UK)
// 13.	Source language Country Code (e.g. US)
// 14.	Target language Country Code (e.g. UA)
// 15.	Source language in Human readable form
// 16.	Target language in Human readable form
// 17.	Locale language
// 18.	Locale country

What it does is it passes a whole bunch of variables (18 so far, they are explained in the comment at the end of the above listing) to a script called otopener.
This otopener is a bash script (but, of course, it can be written in anything else in such a way that it is able to accept passed parameters). This bash script is located in $HOME/bin (can be anywhere else in $PATH, otherwise the whole path to the script should be provided in the groovy script above (line 4)) and made executable. Here’s the listing of it:

#!/bin/bash
if [ ! -d ${10}/script/openers/* ]; then
zenity --error --title="No actions available" \
--text="You don\'t have any actions set up for this script."
exit 0
fi
cd ${10}/script/openers
opener=$(ls | zenity --list --text="What do you want to do?" \
--column="Available actions")
./"$opener" "$@"

This bash opener simply looks inside your current OmegaT config directory for a directory named script/openers and lists every file there is, in a nifty list. Those files are in turn scripts too, and they can be of any complexity, either one-liners, like rm -R $1 (deletes the current project’s folder, run with care), or big multiple-action monstrosities that can do all your work for you and brew some coffee meanwhile (this one is in a raw alpha stage, so don’t get too excited yet). So, adding more action is as simple as dropping a new file to the script/openers subdirectory.
otopener window
Here’s open Directories script from this example which doesn’t add any additional functionality to what is already available but rather serves as a proof of concept.

#!/bin/sh
dir=`zenity --list --radiolist $ic --title "Open directory…" \
--text "Which directory do you want to open\?" \
--height="250" \
--column="Select" --column="Directory" \
"" "Config Directory" \
"" "Dictionary Root" \
"" "Glossary Root" \
"TRUE" "Project Root" \
"" "Source Root" \
"" "Target Root" \
"" "TM Root" \
`
if [ $? -eq "1" ]; then
zenity --error --title="Canceled" --text="Canceled" --timeout=1
exit 0
fi

case $dir in
	"Config Directory" )
	xdg-open ${10}
	;;
	"Project Root" )
	xdg-open $1
	;;
	"Source Root" )
	xdg-open $3
	;;
	"Target Root" )
	xdg-open $4
	;;
	"TM Root" )
	xdg-open $5
	;;
	"Glossary Root" )
	xdg-open $6
	;;
	"Dictionary Root" )
	xdg-open $7
	;;
esac

And here’s how it looks.
Open directory
For the bash scripts given in this recipe zenity is needed.
Other productivity related actions are yet to be posted. Update: Here’s OmegaT target file renamer that uses this approach. Comments and ideas, as well as examples and links to build upon this recipe, prove it pointless, show how this can be done better etc. are always welcome.


Good luck!

4 thoughts on “Bash (Perl, Python, Tcl/Tk and what not) Scripting from within OmegaT

  1. Very interesting. I’m a Windows user, so bash can not be my choice but probably I can use WSH, Windows PowerShell and .NET framework in the same way. Thank you for sharing this.

  2. Hi Kos,

    found a typo in the text: “What it does is it passes a whole bunch of variables (18 so far, they are explained in the comment at the end of the above listing) to a script called otpener.”
    Should be “otopener” as in bash_opener.groovy:
    def opener = ‘otopener’

    I encountered an issue with the groovy script on my system. although the otopener bash script was in my $PATH it could not be found and I got just errors in OmegaT:
    22433: Error: Caused by: org.apache.bsf.BSFException: exception from Groovy: java.io.IOException: Cannot run program “otopener”: java.io.IOException: error=2, No such file or directory

    I had to define the exact path in the groovy script like this:
    def opener = ‘/home/user/bin/otopener’

    Then all worked fine.

    Thank you!

    • Thanks for spotting the typo.
      $HOME/bin may not be in the $PATH for graphical apps, I’ve noticed that with some Display Managers and/or Desktop Environments you need to take extra steps to add $HOME/bin to $PATH, even though it might be specified in your .bashrc or .profile

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s