Content AND Presentation

(Note to English-speaking readers: the links entitled Komentarze na tej stronie lead to comment pages.)

2015-08-01 case-intern trick

When coding in Elisp, sometimes it happens that you want to branch depending on the value of some variable, which can hold a few possible values. The C way would be to use an enum; the lispy way is to use symbols and case. However, sometimes you have strings and not symbols. If you can arrange things so that you have symbols, it’s fine; sometimes you can’t, though, especially if you use someone else’s code. For instance, when writing an Org-mode exporter, you might want to dispatch on link types; however, (org-element-property :type link) is a string (one of a few enumerated in the org-link-types variable).

Of course, you can just use cond:

(cond
 ((string= (org-element-property :type link) "http") (do-something))
 ((string= (org-element-property :type link) "file") (do-something-else))
 (t (do-something-else-yet)))

This is far from elegant, though.

Here is one possible solution. While Elisp doesn’t have a case form, cl (the package implementing many Common Lisp features) has cl-case (conveniently aliased to case). However, it uses eql to compare keys. Since (eql "foo" "foo") evaluates to nil (because these two strings are different objects in memory), case‘ing on strings doesn’t make sense.

The solution is to use intern. Basically, it may be considered as a “type cast from strings to symbols”. (This is just a bit more complicated, but never mind.) For instance, (eql (intern "foo") (intern "foo")) evaluates to t, as expected. This means that the above construct may be rewritten much more elegantly as

(case (intern (org-element-property :type link))
  (http (do-something))
  (file (do-something-else))
  (t (do-something-else-yet)))

Worth remembering.

CategoryEnglish, CategoryBlog, CategoryEmacs, CategoryOrgMode

Komentarze na tej stronie

2015-07-25 Multiple indices in a LaTeX document with splitidx

An often requested feature in a book is multiple indices. Typically, there are separate indices of notions and theorems, of people’s names, and/or of symbols. Unfortunately (and unsurprisingly, I regret to say), standard LaTeX provides only one bare-bones index. There are of course a few tools to solve this problem. One of them is the splitidx package.

Let’s start with its main disadvantage, so that we have that said and don’t have to repeat it: it either lets create only a limited number of indices, or needs a separate external program. The reason for that is simple: standard LaTeX can’t open too many files simultaneously, so if you have too many indices (each made using a separate idx file), you’re out of luck. Then, splitidx can just write all the entries to one common file, which is then postprocessed using the SplitIndex program in order to divide the indices.

The consequence of that is also obvious: if you are on a real operating system, you just run the Perl script (there are also a few other versions: a C one, a Java one, a Lua one and a TeX one, though the latter is limited in its possibilities) and that’s it. If you’re on Windows, though, it is also possible to use splitidx, but you have to figure it out yourself, and I won’t help you; most probably, though, you’ll have Java installed anyway, so you could go that route. Consult the manual for details.

So let’s get to business now. How to use splitidx? Basically, instead of \usepackage{makeidx} you just say \usepackage{splitidx} (with option [split], if you don’t have too many indices and want to avoid the SplitIndex program). Then, you can use \printindex* to typeset all the indices automatically.

Let us see a simple example. Let’s make an indices-example.tex file like this:

\documentclass{article}

\usepackage[split]{splitidx}
\makeindex
\newindex[Index of notions and theorems]{idx}
\newindex[Index of symbols]{isy}

\begin{document}
We will first define the notion of a~\emph{metric space}\sindex{space!metric}, which we will usually denote by $(X,d)$\sindex[isy]{Xd@$(X,d)$}.

\printindex*
\end{document}

Compiling it will generate two idx files: indices-example.idx and indices-example-isy.idx. Of course, you’ll have to run makeindex (or texindy) more than once – once for each idx file. Then, you recompile your LaTeX file and that’s it!

Let us stop for a moment yet, and do one more thing, which is not trivial with splitidx. Assume that we want to start each index with a short introductory text. It turns out that it’s easy, if you know how to do it. Here’s an example. This time – just for the sake of demonstration – we won’t use the [split] option. Again, assume that these are the contents of the indices-example.tex file.

\documentclass{article}

\usepackage{splitidx}
\makeindex
\newindex{idx}
\newindex{isy}

\begin{document}
We will first define the notion of a~\emph{metric space}\sindex{space!metric}, which we will usually denote by $(X,d)$\sindex[isy]{Xd@$(X,d)$}.  Then we will define a~\emph{ball}\sindex{ball}, which we will denote by $B(x_0,r)$\sindex[isy]{Bx0r@$B(x_0,r)$}.

\twocolumn[\section*{Index of notions and theorems}Here is the index of notions, with page number referring to the place where the relevant notion is defined, and theorems.]
\printsubindex[idx][]

\twocolumn[\section*{Index of symbols}Here is the index of symbols, in (roughly) alphabetic order -- for instance, $B(x_0,r)$ is before $(X,d)$.]
\printsubindex[isy][]
\end{document}

After compiling it, I called splitindex indices-example from the command line (I could as well call splitindex.pl indices-example, or java splitindex indices-example, or even tex splitindex. In the last case, I would have to enter the filename (indices-example) from the keyboard, ad then run makeindex manually on indices-example-idx and indices-example-isy. Then, I can compile indices-example again and that’s it!

Now that’s pretty much enough if you are satisfied with documents in English. Assume, however, that you write in some other language (in my case, Polish), and want to sort index entries according to Polish rules (that means that the order is not ASCII, but UTF-8-aware, so that “ą” comes between “a” and “b”, for example). Since splitindex calls makeindex itself, we can either use the [split] option again and run texindy with proper arguments ourselves, or instruct splitindex to do that. Here’s how you can do it:

splitindex -m texindy -- indices-example -L polish -C utf8

It works like this: the -m option defines the name of the makeindex replacement, the filename is after --, and everything after that is passed to the index generating program (in this case, texindy). Quite a mouthful.

Of course, you have even more options than that. For instance, you can write out section numbers instead of page numbers into the index. Also, you can play around with running headers and/or one- and twocolumn typesetting. All these are covered by splitidx’s documentation, so if you are interested in those options, read the friendly manual.

Happy TeXing!

CategoryEnglish, CategoryBlog, CategoryTeX, CategoryLaTeX

Komentarze na tej stronie

2015-07-18 TLM vs EWOC, or there and back again

I am currently working on an application in Emacs, which will (in particular) display some tabular data – very much like Dired or list-processes. Since I expected that the problem of displaying such tables is already solved and there’s no need to reinvent the wheel, I asked on the Emacs mailing list about such a utility. It turned out that there are two of them built in Emacs.

The first one is called Tabulated List Mode. It is used for listing packages in package.el, for listing processes and for the buffer list. The other one is EWOC, which is used by Emacs’ Version Control module and for ERT (which, I have to admit, I know nothing about – I’ll try to fix that some day).

So, which one is better?

As is often the case for programming questions, it depends. I first decided to use EWOC for my application, then switched to Tabulated List Mode (which I’ll call TLM for short from now on)… only to get back to EWOC next. Why did I do that? Read on.

The main features of both tools are quite similar. Both can be given a set of data (records with some fields, so to speak), display them in a given buffer, and – when the point is somewhere in this table – determine which record the point is on (although TLM’s functions to do that are undocumented – I filed a bug report about that). The main differences are: data structures used to keep the records and the printing routines.

While TLM uses a plain old list (either kept in a variable, or generated dynamically by a function), EWOC uses an ad-hoc two-directional list, made from CL-like structs. This is a bit strange, especially that the set of atomic operations on that list implemented in EWOC is rather small. Basically, you can only enter a new element to the list and delete an element from the list. In particular, you can’t easily split the list into two – that you have to implement yourself – so one of the most natural sorting algorithms, MergeSort, is neither implemented nor trivial to add. You can, however, collect all entries satisfying some predicate into a (usual) list and remove entries satisfying some predicate from the list. This way, you can implement a (probably not the most effective) sort by copying the EWOC into a list, emptying it, sorting the list (using the built-in sort) and generating the EWOC again. Since in my use the number of entries is at most two-digit, I didn’t care for any attempts at faster sorting.

On the other hand, TLM shines at sorting: sorting by any column (field) is already implemented, using string< by default, but allowing for custom predicates (or disabling sorting by any particular column altogether).

This leads to another difference: the display. TLM displays a fixed header with column titles and an arrow showing which column is used for sorting (and in which direction). EWOC has a more free-form look-and-feel: it is the programmer who is responsible for setting up the header (and footer), displayed above and below the table. They are also not confined to one line. (In fact, this was one of the main reasons I switched to EWOC: I completely don’t care about sorting by different columns, I only have two fields which are really useful for sorting, and one of them need not be displayed anyway.)

The next main difference is in fact the scope of both packages. While TLM (as the name suggests) is a complete major mode (derived from Special Mode), EWOC deals only with displaying the table – the user is completely responsible for setting up the mode, defining the keymap etc.

Last but not least, EWOC has a tiny but complete example in the docs; for an example of using TLM, I read portions of simple.el, where the functions responsible for process lists are implemented.

So which should you choose for your application? If you want something simpler to set up, and not necessarily extremely customizable, TLM may be the way to go. If, on the other hand, you want more control over the display (in particular, the header and footer), and you don’t expect having to sort long lists of entries (like, say, maybe several hundred), and you don’t mind coding a bit more things yourself, EWOC might be better.

Happy hacking!

CategoryEnglish, CategoryBlog, CategoryEmacs

Komentarze na tej stronie

Więcej...

(Więcej means More in Polish; click it to see older entries.)

CategoryEnglish, CategoryBlog