Jordi Inglada

Posts tagged "emacs":

25 Mar 2015

Scripting in C++

Introduction

This quote of B. Klemens1 that I used in my previous post made me think a little bit:

"I spent much of my life ignoring the fundamentals of computing and just hacking together projects using the package or language of the month: C++, Mathematica, Octave, Perl, Python, Java, Scheme, S-PLUS, Stata, R, and probably a few others that I’ve forgotten."

Although much less skilled than M. Klemens, I have also wandered around the programming language landscape, out of curiosity, but also with particular needs in mind.

For example, I listed a set of features that I found useful for easily going from prototyping to operational code for remote sensing image processing. The main 3 bullet points were:

  1. OTB accessibility, which meant C++, Python or Java (and its derivatives as Clojure);
  2. Robust concurrent programming, which ruled out Python;
  3. Having a REPL, which led me to say silly things and even develop working code.

Before going the OTB-from-LISP-through-bindings route, I had looked for C++ interpreters to come close to a REPL, some are available, but, at least at the time, I didn't manage to get one running.

Since I started using C++11 a little bit, I find more and more pleasant to write C++ even for small things that I would usually use Python for. Add to that all the new things in the standard library, like threads, regular expressions, tuples and proper random number generators, just to name a few, and here I am wondering how to make the edit/compile/run loop shorter.

B. Klemens proposes crazy things like compiling via cut/paste, but this is too extreme even for me. Since I use emacs, I can compile from within the editor just by hitting C-c C-c which asks for a command to compile. I usually do things like:

export ITK_AUTOLOAD_PATH="" && cd ~/Dev/builds/otb-bv/ && make \
    && ctest -I 8,8 -VV && gnuplot ~/Dev/otb-bv/data/plot_bvMultiT.gpl

I am nearly there, but not yet.

Remember that I discovered Klemens because I was looking for statistical libs after watching some videos of the Coursera Data Science specialization? One of the courses is about reproducible research and they show how you can mix together R code and Markdown to produce executable research papers.

When I saw this R Markdown approach, I thought, well, that's nice, but inferior to org-babel. The main advantage of org-babel with respect to R Markdown or IPython is that in org-mode you can use different languages in the same document.

In a recent research report written in org-mode and exported to PDF, I used, in the same document, Python, bash, gnuplot and maxima. This is a real use case. Of course, these are all interpreted languages, so it is easy to embed them in documents and talk to the interpreter.

Well, 15 years after I started using emacs and more than 6 years after discovering org-mode, I found that compiled languages can be used with org-babel. At least, decent compiled languages, since there is no mention of Objective-C or Java2.

Setting up and testing

So how one does use C++ with org-babel? Just drop this into your emacs configuration:

Yes, don't forget the flag for C++11, since you want to be cool.

Now, let the fun begin. Open an org buffer and write:

#+begin_src C++ :includes <iostream>
std::cout << "Hello scripting world\n";
#+end_src

Go inside the code block and hit C-c C-c and you will magically see this appear just below the code block:

#+RESULTS:
: Hello scripting world

No problem. You are welcome. Good-bye.

If you want to go beyond the Hello world example keep reading.

Using the standard library

You have noticed that the first line of the code block says it is C++ and gives information about the header files to include. If you need to include more than one header file3, just make a list of them (remember, emacs is a LISP machine):

#+begin_src C++ :includes (list "<iostream>" "<vector>")
std::vector<int> v{1,2,3};
for(auto& val : v) std::cout << val << "\n";
#+end_src

#+RESULTS:
| 1 |
| 2 |
| 3 |

Do you see the nice formatted results? This is an org-mode table. More fun with the standard library and tables:

#+begin_src C++ :includes (list "<iostream>" "<string>" "<map>")
std::map<std::string, int> m{{"pizza",1},{"muffin",2},{"cake",3}};
for(auto& val : m) std::cout << val.first << " " << val.second << "\n";
#+end_src

#+RESULTS:
| cake   | 3 |
| muffin | 2 |
| pizza  | 1 |

Using other libraries

Sometimes, you may want to use other libraries than the C++ standard one4. Just give the header files as above and also the flags (here I split the header of the org-babel block in 2 lines for readability):

#+header: :includes (list "<gsl/gsl_fit.h>" "<stdio.h>") 
#+begin_src C++ :exports both :flags (list "-lgsl" "-lgslcblas")
int i, n = 4;
double x[4] = { 1970, 1980, 1990, 2000 };
double y[4] = {   12,   11,   14,   13 };
double w[4] = {  0.1,  0.2,  0.3,  0.4 };

double c0, c1, cov00, cov01, cov11, chisq;

gsl_fit_wlinear (x, 1, w, 1, y, 1, n, 
                 &c0, &c1, &cov00, &cov01, &cov11, 
                 &chisq);

printf ("# best fit: Y = %g + %g X\n", c0, c1);
printf ("# covariance matrix:\n");
printf ("# [ %g, %g\n#   %g, %g]\n", 
        cov00, cov01, cov01, cov11);
printf ("# chisq = %g\n", chisq);

for (i = 0; i < n; i++)
  printf ("data: %g %g %g\n", 
          x[i], y[i], 1/sqrt(w[i]));

printf ("\n");

for (i = -30; i < 130; i++)
  {
  double xf = x[0] + (i/100.0) * (x[n-1] - x[0]);
  double yf, yf_err;

  gsl_fit_linear_est (xf, 
                      c0, c1, 
                      cov00, cov01, cov11, 
                      &yf, &yf_err);

  printf ("fit: %g %g\n", xf, yf);
  printf ("hi : %g %g\n", xf, yf + yf_err);
  printf ("lo : %g %g\n", xf, yf - yf_err);
  }
#+end_src

#+RESULTS:
| #     | best       |    fit: |       Y | = | -106.6 | + | 0.06 | X |
| #     | covariance | matrix: |         |   |        |   |      |   |
| #     | [          |  39602, |   -19.9 |   |        |   |      |   |
| #     | -19.9,     |   0.01] |         |   |        |   |      |   |
| #     | chisq      |       = |     0.8 |   |        |   |      |   |

etc.

Defining things outside main

You may have noticed that we are really scripting like perl hackers, since there is no main() function in our code snippets. org-babel kindly generates all the boilerplate for us. Thank you.

But wait, what happens if I want to define or declare things outside main?

No problem, just tell org-babel not to generate a main():

#+begin_src C++ :includes <iostream> :main no
struct myStr{int i;};

int main()
{
myStr ms{2};
std::cout << "The value of the member is " << ms.i << std::endl;
}
#+end_src

#+RESULTS:
: The value of the member is 2

There are many other options you can play with and I suggest to read the documentation. Just 2 more useful things.

Using org-mode tables as data

You saw that org-mode has tables. They are very powerful and can even be used as a spreadsheet. Let's see how they can be used as input to C++ code.

Let's start by giving a name to our table:

#+tblname: somedata
|  sqr | noise |
|------+-------|
|  0.0 |  0.23 |
|  1.0 |  1.31 |
|  4.0 |  4.61 |
|  9.0 |  9.05 |
| 16.0 | 16.55 |

Now, we can refer to it from org-babel using variables:

#+header: :exports results :includes <iostream>
#+begin_src C++ :var somedata=somedata :var somedata_cols=2 :var somedata_rows=5
for (int i=0; i<somedata_rows; i++)
  {
  for (int j=0; j<somedata_cols; j++) 
    {
    std::cout << somedata[i][j]/2.0 << "\t";
    }
  std::cout << "\n";
  }
#+end_src

#+RESULTS:
|   0 | 0.115 |
| 0.5 | 0.655 |
|   2 | 2.305 |
| 4.5 | 4.525 |
|   8 | 8.275 |

Tangle when happy

Once you have scripted your solution to save the world from hunger5, you may want to get it out from org-mode and upload it to github6. You can of course copy and paste the code, but since you are using a superior editor, you can ask it to do that7 for you. Just tell it the name of your file using the tangle option:

#+begin_src C++ :tangle MyApp.cpp :main no :includes <iostream>
namespace ns {
    class MyClass {};
}

int main(int argc, char* argv[])
{
ns::MyClass{};
std::cout << "hi" << std::endl;
return 0;
}
#+end_src

If you the call org-babel-tangle from this block, it will generate a file with the right name containing this:

#include <iostream>
namespace ns {
    class MyClass {};
}

int main(int argc, char* argv[])
{
ns::MyClass{};
std::cout << "hi" << std::endl;
return 0;
}

Conclusion

Since reproducible research in emacs has entered the realm of scientific journals8, I will end as follows:

In this article, we have shown the feasibility of coding in C++ without writing much boilerplate and going through the edit/compile/run loop. With the advent of modern C++ standards and richer standard libraries, C++ is a good candidate to quickly write throw-away code. The integration of C++ in org-babel gets C++ even closer to the tasks for which scripting languages are used for.

Future work will include learning to use the C++ standard library (data structures and algorithms), browsing the catalog of BOOST libraries, trying to get good C++ developers to use emacs and C++11, and find a generic variadic-template-based solution to world hunger.

Footnotes:

1

Ben Klemens, Modeling with Data: Tools and Techniques for Scientific Computing, Princeton University Press, 2009, ISBN: 9780691133140.

2

Well, this is just trolling, since Java is in the list of supported languages, and I guess that you can use gcc for Objective-C.

3

This may happen if you are writing code for a nuclear power plant.

4

To guide nuclear missiles towards the nuclear power plant of the evil guys, for instance.

5

Just send some nuclear bombs to those who are hungry?

6

Isn't that cool, to be on the same cloud as all those Javascript programmers?

7

But tell it to make coffee first.

8

Eric Schulte, Dan Davison, Tom Dye, Carsten Dominik. A Multi-Language Computing Environment for Literate Programming and Reproducible Research Journal of Statistical Software http://www.jstatsoft.org/v46/i03

Tags: programming cpp linux emacs org-mode
27 Oct 2014

xdg-open or "computer, do what I mean"

Command line nerds1 say that graphical user interfaces are less efficient since the former use the keyboard and the latter tend to need the use of the mouse.

Graphical user interface fans say that command line based work-flows need the user to know more things about the system. Although I don't see why this would be an issue (what's the problem with getting to know better the system you use every day?), I can see one clear advantage to the point-and-click work-flow.

When the user wants to open a file, double-clicking on it just works. On the other hand, on the command line, the user needs to call the appropriate application and pass the file name as argument:

evince my_document.pdf

That means that the user has to know which is the application that is going to correctly deal with the given file. For example, this won't work:

evince my_movie.mp4

because evince is a document viewer and it only understands formats as pdf, postscript, dejavu or dvi, but it is not able to understand MPEG-4 videos.

So how can one replicate the point-and-click behavior on the command line? It would be nice to have something like:

open my_file

and that auto-magically the appropriate application was chosen.

It is of course possible, and it can be done in the same way as the graphical desktop environment does it: using xdg-utils.

Inside a desktop environment (e.g. GNOME, KDE, or Xfce), xdg-open simply passes the arguments to that desktop environment's file-opener application (gvfs-open, kde-open, or exo-open, respectively), which means that the associations are left up to the desktop environment. Therefore, on the command line, one can do:

xdg-open my_file.pdf

and the appropriate application will be used (evince on GNOME, okular on KDE, etc.).

When no desktop environment is detected (for example when one runs a standalone window manager, e.g. stumpwm), xdg-open will use its own configuration files.

Sometimes, the default associations between applications and file types may not suit the user. For instance, in my case, MPEG-4 videos were open with mplayer, but I prefer vlc. The xdg-mime tool is meant to help you change the default associations:

xdg-mime default vlc.desktop video/mp4

The vlc.desktop parameter is an xdg desktop file which describes the vlc applications. On my Debian GNU/Linux system, this files are located in /usr/share/applications. So I was able to look in there to see what applications xdg-open could use.

The parameter video/mp4 passed to xdg-mime is the type of file we want to associate the application with. In order to know what type of file we are dealing with, xdg-mime can query it for you:

xdg-mime query my_movie.mp4 

And the answer is:

video/mp4

Now, what happens if there is no desktop file for an application I want to use? For instance, remote sensing image visualization is not possible with the standard image viewers available on GNU/Linux. I personally use the OTB IceViewer, which is a lightweight application using the rendering engine developed for Monteverdi2.

In this case, I have to create a desktop file for the application. I my case, I have created the otbice.desktop file in /home/inglada/.local/share/applications/ with the following contents:

[Desktop Entry]
Type=Application
Name=OTB Ice Viewer
Exec=/home/inglada/OTB/builds/Ice/bin/otbiceviewer %U
Icon=otb-logo
Terminal=false
Categories=Graphics;2DGraphics;RasterGraphics;
MimeType=image/bmp;image/gif;image/x-portable-bitmap;image/x-portable-graymap;image/x-portable-pixmap;image/x-xbitmap;image/tiff;image/jpeg;image/png;image/x-xpixmap;image/jp2;image/jpeg2000;

The file has to be executable, so I have to do:

chmod +x /home/inglada/.local/share/applications/otbice.desktop

After that, I can associate the IceViewer with the image formats I want:

xdg-mime default otbice.desktop image/tiff

And it just works.

Footnotes:

1

And I am one. See here, here and here for example.

Tags: otb open-source emacs linux tricks note-to-self
19 Jul 2014

Reading RSS feeds with Emacs

I spend most of my time at the computer in GNU Emacs. I have previously given here hints about how I find key bindings for commands, how I watch Youtube videos in Emacs, and I have even considered Emacs Lisp as a general purpose programming language.

This post is about reading blogs using Emacs, or more generally, reading RSS and Atom feeds.

Gnus

After several years using View Mail as an e-mail tool inside Emacs, I switched to Gnus 3 years ago because View Mail was a little bit slow and I had some issues in dealing with large quantities of e-mails.

Gnus is a little bit daunting at first, mostly because it was designed for newsgroups and some concepts are different from what we are used to with classical mail user agents. But once these concepts are clear to you, Gnus is very efficient in dealing with e-mail, even with huge quantities of it.

One thing I like very much about Gnus is its scoring capability. You may have heard about or even use Gmail's priority inbox. Scoring is somewhat similar (but invented before …).

Another cool thing about reading e-mail inside Emacs is the integration with Org mode so that you can store links to and take quick notes about messages using org-capture. This is a keystone to efficiently implementing inbox zero.

But let's get back to the main topic. Gnus also allows to read RSS feeds. I have tried 3 different approaches for reading feeds in Gnus:

  1. The Gnus RSS back-end
  2. Reading feeds via a news server
  3. Downloading feeds and convert them to e-mail

The order above is the chronological order in which I have tried things.

RSS back-end

This is the straightforward way to use Gnus for RSS. You just add a new group by giving the link to the RSS feed. Unfortunately, this does not work for Atom feeds, but they can be converted using an external tool called atom2rss. In order to automate the conversion, I use this snippet in my Gnus configuration file:

(require 'mm-url)

(defadvice mm-url-insert (after DE-convert-atom-to-rss () )
  "Converts atom to RSS by calling xsltproc."
  (when (re-search-forward "xmlns=\"http://www.w3.org/.*/Atom\"" 
                           nil t)
    (goto-char (point-min))
    (message "Converting Atom to RSS... ")
    (call-process-region (point-min) (point-max) 
                         "xsltproc" 
                         t t nil 
                         (expand-file-name "~/.emacs.d/atom2rss.xsl") "-")
    (goto-char (point-min))
    (message "Converting Atom to RSS... done")))

(ad-activate 'mm-url-insert)

I started looking for an alternative to the RSS back-end because it can be slow, since polling all the feeds takes time.

Gwene

Gwene is a gateway which transforms feeds to newsgroups. It is maintained by Lars Ingebrigtsen (the creator of Gnus) himself!

The way of using Gwene in Gnus is really easy. Just add this to the configuration:

(add-to-list 'gnus-secondary-select-methods '(nntp "news.gwene.org"))

It is quicker than the RSS back-end. I don't really know why, but I guess that it is due to the fact that Gwene fetches the feeds in advance. Of course, if the feed you are looking for is not yet available in Gwene, you have to add it by using the web interface, but this only takes a couple of seconds.

The reason why I looked again for an alternative was again response time, since sometimes the Gwene server seems to be a little bit busy. This tends to block Emacs waiting for the server response.

Feed2Imap

Feed2Imap is an RSS/Atom feed aggregator. It downloads the feeds over http and then uploads them to a specified folder of an IMAP mail server or copies them to a local maildir. I only use this second way, since I read the feeds in the same computer where I download them, but the IMAP server solution could be interesting in order to synchronize the feeds between different devices, like a smart-phone and Emacs on my laptop.

The feeds to be fetched are stored into the .feed2imaprc file and look like this:

- name: GnusAnnounce
  url: http://rss.gmane.org/messages/complete/gmane.emacs.gnus.announce
  target: maildir:///home/inglada/RSSFeeds/gnus-announce
- name: BlogJI
  url: http://jordiinglada.net/sblog/rss.xml
  target: maildir:///home/inglada/RSSFeeds/blog-ji

For Gnus to be aware of this maildir folder, I use:

(add-to-list 'gnus-secondary-select-methods
       '(nnmaildir "RSSFeeds" 
                   (directory "/home/inglada/RSSFeeds")
                   (directory-files nnheader-directory-files-safe) 
                   (get-new-mail nil)))

And then I can subscribe to the different feeds from Gnus since the nnmaildir appears in the server list as {nnmaildir:RSSFeeds}.

Feed2Imap can be run from the command line or using a cron job. I prefer to run it manually from Emacs when I am online:

(defun ji-feed2imap ()
  (interactive)
  (start-process "feed2imap" "*feed2imap*" "/usr/bin/feed2imap" "-v"))

This function will run Feed2Imap in the background and generate a buffer named *feed2imap* where the log messages are stored just in case.

Actually, since I use OfflineImap1 to get my e-mail, I have this function:

(defun ji-get-feeds-email ()
  (interactive)
  (progn
    (ji-feed2imap)
    (offlineimap)))

which is bound like this:

(global-set-key (kbd "<f9> o") 'ji-get-feeds-email)

I am satisfied with this configuration which allows me to:

  1. Read feeds inside Gnus
  2. Fetch the feeds without blocking Emacs by pressing <f9> o
  3. Read the feeds when I am offline

Footnotes:

1

I use the Emacs package developed by J. Danjou.

Tags: emacs gnus feed2imap rss
09 Aug 2013

Watching YouTube without a browser

The other day I was curious about how many streaming video sites among those I usually visit had made the move from flash to HTML5.

The main reason is that my virtual Richard Stallman keeps telling me that I am evil, so I wanted to remove the flash plug-in from my machine.

An the fact is that many sites have not switched yet. As far as I understand, YouTube has, at least partially. Therefore, the title of this post is somewhat misleading.

I have been using youtube-dl for a while now in order to download videos from many sites as YouTube, Vimeo, etc. My first idea was therefore to pipe the output of youtube-dl to a video player supporting the appropriate format. Since I usually use vlc I just tried:

youtube-dl  -o - <url of the video> | vlc -

This works fine, but has the drawback of needing to manually type (or copy-paste) the URL of the video. So the command line on a terminal emulator is not what I find convenient.

Most of the video URLs I access come to me via e-mail, and I read e-mail with Gnus inside Emacs, I decided that an Emacs command would do the trick. So I put this inside my .emacs:

(defun play-youtube-video (url)
  
  (interactive "sURL: ")
  
  (shell-command
   
   (concat "youtube-dl  -o - " url " | vlc -")))

This way, M-x play-youtube-video, asks me for an URL and plays the video. So, when I have an URL for a video on an e-mail (or any other text document on Emacs) I just copy the URL with the appropriate Emacs key stroke and call this command. For convenience, I have mapped it to key binding:

(global-set-key (kbd "<f9> Y") 'play-youtube-video)

So this is good, though not yet frictionless.

Sometimes, the video URL will appear on an HTML buffer, either when I am browsing the web inside Emacs with w3m or when the e-mail I am reading is sent in HTML1. In this case, I don't need to manually copy the URL and I just can ask w3m to do the work.

(defun w3m-play-youtube-video ()

  (interactive)

  (play-youtube-video

   (w3m-print-this-url (point))))


(global-set-key (kbd "<f9> y") 'w3m-play-youtube-video)

So far, this has been working fine for me and I don't have the ugly non-free flash plug-in installed, and VRMS is happier than before.

Footnotes:

1

I use w3m as HTML renderer for Gnus with (setq mm-text-html-renderer 'w3m).

Tags: emacs free-software linux Lisp tricks
17 Jul 2013

Finding commands and key bindings in GNU/Emacs

Since I use GNU/Emacs for everything, I can't remember all the key bindings for all the different modes (org-mode, gnus, geiser, etc.). So I often use the command names using M-x command-name.

Sometimes, I don't even remember the exact name of the command and I will use the TAB completion to see suggestions. But for that, I need to remember the beginning of the name of the command. If I remember a part of the name of the command, say, find, typing M-x --find followed by TAB will propose all available commands whose name contains find.

So far so good.

If I don't know at all the name of the command, there are a couple of things that I can do. One would be browsing the menus in the menu bar, but since my menu bar is hidden1 in order to increase screen real estate, I would need to show it (M-x menu-bar-mode), and grab the mouse. Instead, pressing F10, a pop-up menu which can be keyboard driven appears and I can browse the menus.

I only would do this if I was bored, but this is rarely the case, so I prefer another possibility. I use C-h m, which is bound to the describe-mode command which displays the documentation for all active modes for the current buffer.

In this documentation there is a table showing all the available key bindings and the corresponding commands. When in an org-mode buffer I get this:

key             binding
---             -------

C-a             org-beginning-of-line
C-c             Prefix Command
C-e             org-end-of-line
TAB             org-cycle
C-j             org-return-indent
C-k             org-kill-line
RET             org-return
C-y             org-yank
ESC             Prefix Command
|               org-force-self-insert
...

Usually, this allows me to find the command I need and recall (at least for 5 minutes) the corresponding key binding.

If I am not sure if a command does what I need, I can always use the describe-function (bound to C-h f) command to get its documentation. If I invoke the command with the cursor on one of the commands of the table above, this will be used as default command to be described by describe-function.

Nice and efficient.

Footnotes:

1

I have (menu-bar-mode -1) in my .emacs.

Tags: emacs tricks
19 Aug 2012

Emacs Lisp as a general purpose language?

I live in Emacs

As you may already know if you read this blog (yes, you, the only one who reads this blog …) I live inside Emacs. I have been an Emacs user for more than 12 years now and I do nearly everything with it:

  • org-mode for organization and document writing (thanks to the export functionalities),
  • gnus for e-mail (I used to use VM before),
  • ERC and identica-mode for instant messaging and micro-blogging (things that I don't do much anymore),
  • this very post is written in Emacs and automatically uploaded to my blog using the amazing org2blog package,
  • dired as a file manager,
  • and of course all my programming tasks.

This has been a progressive shift from just using Emacs as a text editor to using it nearly as an operating system. An operating system with a very decent editor, despite of what some may claim!. It is not a matter of totalitarism or aesthetics, but a matter of efficiency: the keyboard is the most efficient user input method for me, so being able to use the same keyboard shortcuts for programming, writing e-mails, etc. is very useful.  

 

Looking for a Lisp

In a previous post I wrote about my thoughts on choosing a programming language for a particular project at work. My main criteria for the choice were:

  • availability of a REPL;
  • easy OTB access;
  • integrated concurrent programming constructs.

I finally chose Clojure, a language that had been on my radar for nearly a year by then. I had already started to learn the language and made some tests to access OTB Java bindings and I was satisfied with it. Since sometimes life happens, and in between there is real work too, I haven't really had the time to produce lots of code with it, and by now, I have only used it for things I would had done in Python before. That is, some glue code to access OTB, a PostGIS data base, and things like that. I also feel some kind of psychological barrier to commit to Clojure as a main language (more on this below). Added to that, has also been the recent evolution of the OTB application framework, which is very easy to use from the command line. In the last days of my vacation time, the thoughts about the choice of Clojure came back to me. I think that everything was triggered by a conversation with Tisham Dhar about his recent use of Scheme. It happened during IGARSS 2012 in Munich, and despite (or maybe thanks to?) the Bavarian beer I was analyzing pros and cons again. Actually, before starting to look at Clojure, when I was re-training myself about production systems, I had thought about GNU Guile (a particular implementation of Scheme) as an extension language for OTB applications, but finally gave up, since I thought that going the other way around was better (having the rule-based system around the image processing bits). When I thought that I was again settled with my choice of Clojure, I stumbled upon the announcement of elnode's latest version. Elnode is a web server written in Emacs Lisp. I then spent some hours reading Nic Ferrier's blog (the author of Elnode) and I saw that he advocates for the use of Emacs Lisp as a general purpose programming language. Elnode itself is a demonstration of this, of course. Therefore, I am forced to consider Emacs Lisp as an alternative.  

 

But what are the real needs?

  1. Availability of a REPL: well, Emacs not only has a REPL (M-x ielm), but any Emacs lisp code in any buffer can be evaluated on the fly (C-j on elisp buffers or C-x C-e in any other buffer). Actually, you can see Emacs, not as an editor, but as some sort of Smalltalk-like environment for Lisp which gets to be enriched and modified on the fly. So this need is more than fulfilled.
  2. Easy access to OTB: well, there are no bindings for Emacs lisp, but given the fact that the OTB applications are available on the command line, they can be easily wrapped with system calls which can even be asynchronous. The use of the querying facilities of the OTB application engine, should make easy this wrapping. So the solution is not so straightforward as using the Java bindings on Clojure, but seems feasible without a huge effort.
  3. Concurrency: this one hurts, since Emacs lisp does not have threads, so I don't think it is possible to do concurrency at the Lisp level. However, since much of the heavy processing is done at the OTB level, OTB multi-threading capabilities allow to cope with this.

For those who think that Emacs Lisp is only useful for text manipulation, a look at the Common Lisp extensions and to the object oriented CLOS-compatible library EIEIO may be useful.  

 

So why not Emacs lisp then?

The main problem I see for the use of Emacs Lisp is that I have been unable to find examples of relatively large programs using it for other things than extending Emacs. There are of course huge tools like org-mode and Gnus, but they have been designed to run interactively inside Emacs. There are other more technical limitations of Emacs Lisp which can make the development of large applications difficult, as for instance the lack of namespaces, and other little things like that. However, there are very cool things that could be done to make OTB development easier using Emacs. For instance, one thing which can be tedious when testing OTB applications on the command line is setting the appropriate parameters or even remembering the list of the available ones. It would nice to have an Emacs mode able to query the application registry and auto-complete or suggest the available options. This could consist of a set of Emacs Lisp functions using the comint mode to interact with the shell and the OTB application framework. This would also allow to parse the documentation strings for the different applications and present them to the user in a different buffer. Once we have that, it should be possible to build a set of macros to set-up a pipeline of applications and generate an Emacs Lisp source file to be run later on (within another instance of Emacs or as an asynchronous process). This would build a development environment for application users as opposed to a development environment for application developers. And since Lisp code is data, the generates Emacs Lisp code, could be easily read again and used as a staring point for other programs, but better than that, a graphical representation of the pipeline could be generated (think of Tikz or GraphViz). Yes I know, talk is cheap, show me the code, etc. I agree.  

 

Conclusion

Clojure has a thriving community and new libraries appear every week to address very difficult problems (core.logic, mimir, etc.). Added to that, all the Java libraries out there are at your fingertips. And this is very difficult to beat. I hear the criticisms about Clojure: it's just a hype, it's mainly promoted by a company, etc. Yes, I would like to be really cool and use Scheme or Haskell, but pragmatism counts. And, anyway, the programming language you are thinking of is not good enough either.  

 

Tags: emacs programming programming-languages
Other posts
Creative Commons License
jordiinglada.net by Jordi Inglada is licensed under a Creative Commons Attribution-ShareAlike 4.0 Unported License. RSS. Feedback: info /at/ jordiinglada.net Mastodon