This is as days pass by, by Stuart Langridge

And this is More thoughts on Linglish, written , and concerning Software, Musings, Howtos, and Linux

I still don't have a decent name for "Linglish", the toy scripting language for the Linux desktop that I was playing around with a couple of days ago. I've added a couple more features to satisfy my curiosity about how hard it would be to do, and I've read the comments on the previous post with a great deal of interest. Thanks to everyone who chimed in with thoughts.

First, what Linglish can now do:

tell screensaver to lock A simple command: just tell one application to do one thing. ask banshee's engine for uri Request the value of something from an application. If you do this from the command-line, the value is printed out:
$ python linglish/runner.py -c "ask banshee's engine for uri"
file:///home/aquarius/Music/New%20Order%20-%20World%20in%20Motion).MP3
tell banshee's engine to pause tell screensaver to lock Run more than one command in a script tell tomboy to FindStartHereNote tell tomboy to displaynote with the result Call a command which returns something and then do something based on that: Tomboy has no "show the Start Here note" function, but this does it fine by getting a reference to the Start Here note and then displaying it. The latter command could also have been written as tell tomboy to displaynote it or tell tomboy to displaynote FindStartHereNote wait for banshee's eventchanged ask banshee for currenturi tell tomboy to createnote with it Wait for an application (Banshee) to send a signal (a song has stopped playing or started), then when it happens ask for the value of a property (the path to the currently-playing song), and finally call a different app (Tomboy) to create a note with that path as its name. This example will then exit: if you want to create a new note every time the song changes, then wait repeatedly for the signal rather than just waiting for it.

Next, some musings:

One thing that this has revealed to me is that there are quite a few apps which I'd like to interact over D-Bus with which don't provide an API to do so. The glaringly obvious example here is Nautilus (and indeed there is a bug requesting a D-Bus API), and a part (a small part) of why I've built this is that if there's an easy way to encourage people to write little programs controlling their desktop then that will encourage application developers to build APIs to their apps. Zenity doesn't have one either, which makes interaction from these little Linglish scripts a bit difficult; I suppose I could build "display dialog" commands into the language but that seems a bit off. On the other hand, one of the advantages here is that there's nothing stopping someone building a thing which is just a D-Bus API and which then calls out to Zenity to do the work. A second is that our D-Bus APIs are not necessarily brilliant. Picking a silly example, if you want to find Tomboy's version using Linglish you have to tell tomboy to version, which sounds rather stupid; it should be "ask tomboy for version", but Version() is a method rather than a property in Tomboy's D-Bus API. (I'm not picking on Tomboy here; they have a pretty comprehensive API, and I've been testing and developing Linglish using primarily Tomboy and Banshee.) Linglish is sort of designed with the conceit that methods are verbs, hence the "tell someapp to dosomething" syntax, which sounds deeply weird if your methods are not actually a verb. It's also jolly hard to work out what D-Bus APIs are actually available. Well, that's not true: if you're me, or a hacker like me, then you can use J5's fantastic D-Feet D-Bus browser. I think this problem is best solved with tools used to create the language rather than the language itself, although there's more on this in the future-development section below. There were plenty of comments on the last post saying that this was a stupid idea and that it made much more sense to have a syntax like screensaver/lock or screensaver.lock() rather than tell screensaver to lock. I, personally, do not agree with that. I'm not necessarily suggesting that I'm right and they're wrong, or that neophytes will indeed find my way easier: just that this is an alternative way. If you think that Python or Smalltalk or any one of a dozen others are a better approach, go for it: I'm certainly not stopping you.

Thirdly, questions about what it might do in the future and whether those things are a good idea:

The original conception I had for this in my head is now basically done. You can send commands to programs, you can tie programs together, you can get info out of a program and print it out. It would be able to do half the little scripty tasks I want to do on my desktop (assuming that the APIs existed to do them, which they mostly do not). Here are future things it could do, in rough order from small to big:
  1. Be cleverer about calling methods on applications with more than one object. At the moment you have to tell banshee's engine to pause, because Banshee exports more than one object. Since only one of those objects actually has a Pause() method, tell banshee to pause makes more sense.
  2. Have Linglish be able to document an application. ask linglish about tomboy which then prints out Tomboy commands you could use by introspecting Tomboy's D-Bus API would be pretty nice. One big problem with this is that for most apps they need to be running to find out what API they offer, so ask linglish about banshee would start it up.
  3. There are currently no control statements. This is a problem if you want to do anything even semi-complicated in a script, especially since the common approach to D-Bus signals in Linux apps seems to be to generate a SomethingHasChanged and then pass a whatchanged parameter; Banshee fires StateChanged('paused') and StateChanged('playing') rather than Playing and Paused signals. NetworkManager has something similar. It's understandable why: you get one signal in a few different flavours rather than a multitude of signals. Inconvenient for this, though, because to vary what the script does based on a parameter you have to have an if statement (or something similar). I've been thinking about this: I do not want to build a proper language. If you want that, learn Python. But...maybe it needs control statements. I don't know. I'm against it, but if this is useless without them then that's a strong argument that the effort is not worth it.
  4. A script editor. This would allow people to write scripts without having to know the names of any of the functions you need to call -- popup completions and the like. This is even more problematic than ask linglish about whatever, since there's no way of saying "which apps in the world offer a D-Bus API?" -- most apps do not install an activation file, which means they must be running for any script editor to even know they exist. It's also a lot of work, although most of the heavy lifting is done by GtkSourceView.
  5. Packaging and stuff. If this is likely to be useful I should make .debs of it and so on and make it easy for people to install and everything.

And finally...

The overarching question: is doing more of this a good idea and worth the effort? Your comments gratefully accepted.

Comments

ssam

I think it will also need to be able to do somethings without having to tell an application to do them.

copying and moving files

some flow control

starting applications

John Stowers

You seem to be at a junction where the limitations and quirks of various application DBus interfaces could make the language ugly.

I would keep the language as it is, and just maintain a quirks file that fixes said interfaces. You could even write the quirks file in linglish if you wanted :-)

The quirks file could fix the following errors

* convert functions to properties

e.g. "convert tomboy version function to property"

* rename functions

e.g. "rename tomboy FindStartNoteHere to getstartnote"

mike

I still believe it's great as seems to help gettings started much faster.

An interface would be nice though.

Maybe just a little thing to store such scripts (IconView like, maybe just in Nautilus).

sil

ssam: moving files is a job for Nautilus, which as mentioned doesn't have a D-Bus API. It should do, though, and then it'll work; I don't want to build that into linglish. (If you need it, write a shell script, no?) Starting apps is the same: if an app is D-Bus callable but doesn't have an activation file then that's a bug, in my opinion. Flow control...is discussed above, and I'm still not sure about it :)

John: I like the idea of the quirks file, but if the API needs fixing then I'm inclined to file bugs against the apps; no reason why linglish should have a nice API to write against and everyone else suffers, I think!

mike: not sure what you mean by "an interface" -- can you elaborate?

Lee

Sorry to be blunt, but as a language this isn't up to much, apart from looking cute initially (before the problems are encountered). I'd suggest looking at OS X's automater, if you want to see what others are doing in this area. It's also worth checking out ARexx, which is a more C-like language that was used a similar way, back in the Amiga's glory days. There is a unix implementation of Rexx too.

John Stowers

sil: The problem (ok, more pain than problem) is that fixing an applications DBus interface is really painful for other applications using the existing interface.

Speaking as Conduit developer I have encountered this many times. Application X changes its DBus interface which breaks conduit, but I still need to support the old version so I drag around a heap of hackish code for working with both interfaces.

The root course is that there are no strict ABI requirements for DBus interfaces in GNOME.

The closest thing we have to DBus ABI guarentee is people like me begging apps not to change DBus API willy-nilly.

ulrik

Looks very cool! Works directly out of the box.. :-) I'm much more inclined to use dbus like this, the first thing I thought was that I wanted that the apps tell about themselves, that would be awesome!

I say: Keep it simple, release it early, and if someone uses this it might even begin to influence the way d-bus interfaces are designed!

kerobaros

Oh, please, please continue with this. AppleScript is one of my very favorite things about the OS X desktop, and I would love to have something even better on Linux! I'm tracking current here, and will report any issues I have.

My main request at this point is the 'ask linglish about' functionality. Would definitely make things easier.

Also, would (or could) there be a way to run linglish in an interactive mode, like Python? Make that feature request #2 from this vector. You're awesome!

Chris

Yes,please continue with this. I've wanted something like this for a while -- I posted a comment in your previous blog entry today at probably around the same time you posted this :) I still like the name "Lingo" over "Linglish" - also what about users who aren't english native speakers? It might be beneficial to invest some time in a translation ability. Lastly, for something like tomboy Version() you could say "ask tomboy's version" or "tell tomboy's version" - this would be abstracting the methods as something belonging to tomboy.

ulrik

Another python suggestion.. just an idea, might not work.. but if you provide this functionality in a python module.. which you should anyway, it would for example be trivial to provide the above mentioned interactive prompt.

But, using functions like, linglish("tell rhythmbox's player to getplayinguri") you could put the whole control flow outside of linglish.. (even using tell("smon to smt") and ask("") etc..)

But I like it so far! "tell do to summon"

Chris

Another name idea: "Ping" :) Remember that penguin that would talk like it had marbles in it's mouth named "Pingu"? Might be kind of a tongue in cheek nod to Tux :P

John Stowers

One more suggestion, instead of

wait for banshee’s eventchanged

What about

when banshee’s eventchanged

Edgewise

Why not have Linglish monitor what apps are running, and ask all new ones "ask linglish about banshee", and remember the answer as if they had installed an activation file. If just that bit ran as a by default, all commonly used apps get picked up without starting them for that purpose. I think linglish is very cool even in its current state.

Jeff Schroeder

Since the syntax looks awful similar to applescript, why not name it penguinscript or pscript for short?

Osma

Regarding the scripting syntax itself, a domain-extensible simple language like Lua would be the ideal base for something like this, as the commands to applications could be embedded near-natively to the main application language. Ruby is similar in this regard, but Lua is even more easily embedded.

The approach you took reminds me of REXX; or in particular, the AmigaOS variant ARexx of it. Certainly similarities to AppleScript in it, too..

There's some benefit to investigating these previous approaches, especially how most of these languages and the applications which have made use of them have quickly leaped over from "an external scripting interpreter sending commands to applications" to having the language actually embedded in the applications themselves, and apps talking straight to each other, rather than through a command interpreter sitting somewhere on the system level.

Walther

+1 for ulrik's python suggestion.

If porting from linglish to python is trivial, you don't have to support flow control: as soon as a user's script gets too complicated they are probably involved enough to learn the basics of python.

kerobaros

Another +1 for that! 'import linglish' sounds like a lovely idea.

sil

John: this is what D-Bus interface names are *for*, no? If, say, Tomboy changed its D-Bus API, I'd expect it to provide an org.tomboy.RemoteControl2 interface and keep providing the old org.tomboy.RemoteControl interface but deprecate it, thus giving you a chance to upgrade. Lennart's just written something about this at http://0pointer.de/blog/projects/versioning-dbus.html.

John again: I liked "when app's signal" too, and "wait repeatedly for" would become "whenever app's signal" which is actually nicer, but I can't think of a sane way to do "wait 5 times for app's signal" in a "when" format. Perhaps "wait 5 times" is a stupid idea anyway. (It would obviously be solved if I implemented control flow statements, because then you'd just wrap it in a "repeat 5 times".)

Edgewise: the problem there is caching. If I have linglish ask tomboy for its D-Bus API and then save that data, how do I know if Tomboy has changed its API in the interim?

Jeff: I don't want to come *too* close to AppleScript; yes, I was pretty obviously inspired by it, but I'm avoiding reading too much about AS because I don't want this to be a copy, and I don't want people seeing it to think it's a copy either, 'cos it's not.

All: "import linglish" and an interactive shell are both excellent ideas. I'll add those to the list. ("import linglish already sort of works, but it's more fiddly than it needs to be.)

Félim Whiteley

I reckon you should call it Fencepost, so at some stage your computer can spit a "Fencepost Error" on the screen ;-)

One thing that would be good is if you could keep it DE agnostic. Or if you only write it for GTK do it in such a way the next person could write a QT interface easy enough.

sil

Félim: it *is* DE agnostic. It doesn't have any UI. All it does is talk to D-Bus. KDE apps that export a D-Bus API will work just as well with it.

Stu

Instead of control structures, just making it easy to use from other languages would probably be enough.

John Stowers

sil: Regarding control structures, I would limit it to IF and FOR. I hereby arbitrarily declare that will be sufficient and anything more complicated should be done in a proper language! Famous last words, I know. Anyway, and I would express them like the following.

wait for banshee’s eventchanged, and if paused

tell screensaver to lock

and

wait for banshee’s eventchanged, and the 5th time

tell screensaver to lock

In this example your choice of "wait for" is cleaner than "when" IMO.

Then you could do repeat type operations on a per lingish file basis. The first line could be "repeat 5 times", or "repeat forever".

Multi file and control structures could be mixed like this. File contents shown indented below;

main.linglish:

repeat forever

wait for banshee’s eventchanged, and the 5th time

tell linglish to lockscreensaver

lockscreensaver.linglish:

tell screensaver to lock

John Stowers

Ok, stripped the indentation, but needless to say the lines following .linglish: go in the named file

sil

John: hrm. Not sure about those syntaxes. tell commands can return values too, so you'd need something like

tell myapp to givemedata as a, b, c

if a is paused

...do something...

end if

tell otherapp to dosomething

and that all looks rather complex to me :(

sil

John: ah, hang on, you're proposing doing the inner content of an if in separate files? so

tell myapp to givemedata as a, b, c

if a is paused

run somefile

tell otherapp to dosomething

and ...do something... goes in somefile.linglish?

Hrm. Not sure what I think about that :)

Moses Palmér

Instead of typing "tell banshee's engine to pause", the interpreter could, as you suggest, be a bit more flexible and accept "tell banshee to pause". The method invocation "pause" could then perhaps be remembered, and at a later time "pause" would suffice.

But why let this simple Python script be the interface to the user? Your scripting language is similar enough to spoken language that that should be the interface! Is there no adequate speech recognition library available?

"Pause", I would say, and the music would stop!

Ingmar

How about something like:

wait until banshee's state changed to paused

wait until networkmanager connected to home

(Since I came here through an rss reader, I probably won't read a reply. Then again, they're just ideas for you to think about :) )

hop

I don't think putting efford into Linglish-the-language is a good idea. Look at how long Apple has been working on AppleScript-the-language and where it got them...

Let me explain:

I know exactly three kinds of Apple users: those that don't use AppleScript at all and have no need to, non-programmers that try to use it and programmers that curse it.

We don't have to talk about the first kind, obviously.

The non-programmers ("my mom") don't last longer than a view lines of code before they give up.

As a programmer you fall into the trap of assuming that the hard part for non-programmers is to translate their idea into code.

But a non-programmer often does not have a good algorithm in his head to begin with. Most of them are not used to thinking in the kind of structured way that programming requires.

How should Linglish accommodate someone who wants to "pause banshee" instead of "telling banshee to pause"? How about someone who "tells the the active application to pause" -- thinking it is banshee, because they can hear it right now -- while really they stall the download they just started a view seconds ago? How about someone who thinks the application OpenOffice is responsible for copying a file to a usb stick, because it's a spread sheet after all? I could go on...

Even if the user had a good representation of the necessary steps in her head, there is another problem: AppleScript and Linglish may look like the behave like natural languages, but they don't and they never will.

To you it is obvious how a Linglish statement should look like, but for every part of that statement there are uncountable alternatives to express the same thing. There are spelling errors, alternative names for things, different sentence structure, etc.

And that's just for simple statements, not for control structures!

If your goal is to present to the user a language that looks natural, you will frustrate them by forcing them to express themselves unnaturally strict.

Then there is the whole debugging issue. You as a programmer know how hard it can be to debug something where your mental model is not correct: none of the error messages make any sense if there even are any!

Now imagine a non-programmer with a Linglish script that is syntactically correct but does not follow their intent!

Or think about the 30 year old discussion about making error messages "more user friendly". Let me ask you: if it is easy -- or hard but manageable -- to design "user friendly" error messages, why do I still regularly hear complaints in that regard, even with otherwise well designed software?

In short: you cannot design a porgramming language that will help non-programmers to programme, unless they are the kind of person who can learn to programm with an "unnatural" programming language to begin with.

The third kind of AppleScript users are the programmers, and those are the ones who call AS the "read only language". 'Nuff said.

_BUT_

There is another angle to your project that I think would be worth the efford: bringing the app developers to making their applications scriptable and harmonizing those D-Bus interfaces and APIs.

This, combined with a bit of Python infrastructure would make scripting of applications much easier -- without requiring a new language.

Like the Apple Scripting Bridge [1], but better ;)

And for non-programmers it should be about as difficult to learn how to write three simple python statements in a row as it is to learn Linglish -- especially if they have well structured documentation and don't have to import the required modules, etc.

Speaking of documentation -- and this ties in with acquiring info from apps that are not currently running -- this is how AppleScript does it: Every app that is scriptable includes in its bundle a "dictionary" that can be read by the OS without starting the app -- or even requiring active registration by the app.

The documentation for an apps scripting API (what methods are available, what parameters go in, what comes out) is usually derived from the same dictionary.

Sorry for my long and rambling post, especially for any confusion caused by English not being my first language. This topic really should be discussed in a pub anyway ;)

[1] http://www.apple.com/applescript/features/scriptingbridge.html

hop

New Note 10

I don't think putting efford into Linglish-the-language is a good idea. Look at how long Apple has been working on AppleScript-the-language and where it got them...

Let me explain:

I know exactly three kinds of Apple users: those that don't use AppleScript at all and have no need to, non-programmers that try to use it and programmers that curse it.

We don't have to talk about the first kind, obviously.

The non-programmers ("my mom") don't last longer than a view lines of code before they give up.

As a programmer you fall into the trap of assuming that the hard part for non-programmers is to translate their idea into code.

But a non-programmer often does not have a good algorithm in his head to begin with. Most of them are not used to thinking in the kind of structured way that programming requires.

How should Linglish accommodate someone who wants to "pause banshee" instead of "telling banshee to pause"? How about someone who "tells the the active application to pause" -- thinking it is banshee, because they can hear it right now -- while really they stall the download they just started a view seconds ago? How about someone who thinks the application OpenOffice is responsible for copying a file to a usb stick, because it's a spread sheet after all? I could go on...

Even if the user had a good representation of the necessary steps in her head, there is another problem: AppleScript and Linglish may look like the behave like natural languages, but they don't and they never will.

To you it is obvious how a Linglish statement should look like, but for every part of that statement there are uncountable alternatives to express the same thing. There are spelling errors, alternative names for things, different sentence structure, etc.

And that's just for simple statements, not for control structures!

If your goal is to present to the user a language that looks natural, you will frustrate them by forcing them to express themselves unnaturally strict.

Then there is the whole debugging issue. You as a programmer know how hard it can be to debug something where your mental model is not correct: none of the error messages make any sense if there even are any!

Now imagine a non-programmer with a Linglish script that is syntactically correct but does not follow their intent!

Or think about the 30 year old discussion about making error messages "more user friendly". Let me ask you: if it is easy -- or hard but manageable -- to design "user friendly" error messages, why do I still regularly hear complaints in that regard, even with otherwise well designed software?

In short: you cannot design a porgramming language that will help non-programmers to programme, unless they are the kind of person who can learn to programm with an "unnatural" programming language to begin with.

The third kind of AppleScript users are the programmers, and those are the ones who call AS the "read only language". 'Nuff said.

_BUT_

There is another angle to your project that I think would be worth the efford: bringing the app developers to making their applications scriptable and harmonizing those D-Bus interfaces and APIs.

This, combined with a bit of Python infrastructure would make scripting of applications much easier -- without requiring a new language.

Like the Apple Scripting Bridge [1], but better ;)

And for non-programmers it should be about as difficult to learn how to write three simple python statements in a row as it is to learn Linglish -- especially if they have well structured documentation and don't have to import the required modules, etc.

Speaking of documentation -- and this ties in with acquiring info from apps that are not currently running -- this is how AppleScript does it: Every app that is scriptable includes in its bundle a "dictionary" that can be read by the OS without starting the app -- or even requiring active registration by the app.

The documentation for an apps scripting API (what methods are available, what parameters go in, what comes out) is usually derived from the same dictionary.

Sorry for my long and rambling post, especially for any confusion caused by English not being my first language. This topic really should be discussed in a pub anyway ;)

[1] http://www.apple.com/applescript/features/scriptingbridge.html

hop

sorry! firefox crashed when i first hit submit... just ignore the one of my comments, they are exactly the same!

John Stowers

@sil: You expanded my syntax beyond what I suggested. Firstly, I would never support multiple values returned, instead I would map a single function that returned multiple values into multiple differently named functions in the quirks file. Secondly, I really think a single IF that only executes the immediately following line is sufficient.

tell myapp to givemedata_a, and if paused

…do something…

If you want the else case then write another linglish file.... Also, regarding loading other linglish files, the statement

tell linglish to lockscreensaver

tells the linglish interpreter to open and execute lockscreensaver.linglish. If you wanted to keep the tell keyword separate, you could name this operation "speak linglish to lockscreensaver"

Thomas Thurman

Metacity deliberately isn't DBus-scriptable because it can be scripted using EWMH, like any other window manager. The idea has been raised of a script which DBus would call which would translate EWMH messages to mean you could say "tell desktop to show" or something. Would that be useful to you?

sil

Thomas: I thought about the EMWH stuff; there's potentially useful magic in "tell metacity to minimise " or whatever. I haven't thought about that in any huge detail; I was imagining linglish as more about controlling your applications than controlling your desktop, if you see what I mean.

ulrik

if there are doubts about linglish having a nishe at all, I think it at least makes sense at those points where an application may ask "what should I do when this happens?" and expects one line or two.. think of pidgin incoming message events or somesuch. Even non-programmers can use linglish in one-stanza format.

Chris

You could pick something with "meme" in for the name, for maximum web 2.0-ness. I'm surprised there isn't a /usr/bin/meme already, actually. ;-)

Peter Oliver

I suspect that this is more useful as an intellectual exercise that as something you'd want to inflict directly on end-users.

As things like Enso and Ubiquity become more popular, and effectively start to replace the shell, you'd expect people to want to start scripting using those syntaxes. Perhaps Linglish can influence the design of those languages to make this work well.

Simon

Name suggestion: Ubiquitous

;)

Simon

Ubiquitux

ulrik

What happens in the linglish world? I still find this interesting. Even more of the desktop is available on D-Bus now than half a year ago.

sil

ulrik: I haven't done anything with linglish since these posts. If you wanted to continue developing it, that'd be cool :)

This website belongs to Stuart Langridge. Contact details are available. Don't eat yellow snow. Valid HTML5, at least in theory, except for the bits that aren't because I'm that futuristic that I'm ahead of the spec, oh yes. HTML5 help from Bruce Lawson, among others. Fonts from the superb FontSquirrel. End.