Scripting with Textadept
Tags: textadept, texteditor, emacs
Published: 2019-08-30 15:44:47

Yesterday on Hacker News, someone [commented](https://news.ycombinator.com/item?id=20829818)

> Other editor users simply have no concept of how easy it is to whip up some quick script to perform some task in emacs.

I think many Emacs users have this view, and as a long time Emacs user, I love the ability to write libraries of functions and interact with them from a text editor. Unfortunately, it's not an accurate statement. Other text editors do have that capability. Textadept - probably influenced by Emacs - is one that I've used extensively as a frontend for a programming language. [This](https://news.ycombinator.com/item?id=20830710) was my response

> I don't want to start a flamewar, but I moved most things I was doing in Emacs to Textadept a while back because I found Textadept more convenient. That's not to say TA does everything you can do in Emacs, but it replaced all of the scripting I was doing with Emacs.

> You have the full power of Lua inside TA. Emacs always has a lag when I start it up, whereas TA is instant. I slowly built up functionality inside TA to the point that I realized I could replace everything I was doing in Emacs.

> It's so small and lightweight that, just for fun, I wrote a "web browser" inside TA. It calls out to lynx and loads a readable text version of the page. I use a keyboard shortcut to open links. I have functions for searching the web, I can search YouTube and open the videos in VLC, and so on. This was a practical thing to do: I can use TA as a browser on really old laptops.

> It maybe isn't for everyone, but in Emacs when I was doing this[1] to duplicate a line:

> C-a C-SPACE C-n M-w C-y

> I asked why I wasn't using a better text editor. In TA, it's C-d. Just as Emacs is an interface for Emacs Lisp, TA is an interface for Lua, and with a lot less overhead.

> [1] https://stackoverflow.com/questions/88399/how-do-i-duplicate... 

That last bit wasn't important from the perspective of scripting. (But it's correct - Emacs is not a lightweight text editor, and you can end up going down rabbit holes when you try to change a key binding, unless you're willing to accept verbosity. Textadept, by just being a text editor out of the box, doesn't have that problem.)

I might post more on this topic in the future, but let me give you an example of one customization I've done with Textadept. First, some background on my workflow so you understand what I need to do. I have a lot of information flying at me during the day: a link I come across that is not of any particular use right now but that may be useful in the future, a few pieces of reference material someone sent me for a service project, a request for a meeting, an example that came to mind randomly that I want to incorporate into tomorrow's lecture, a minor comment from a coauthor about a problem with one of the figures in our paper, a clarification on a rule for the graduate program. It's an unending stream of a few big items and a lot of small items. 

There's simply no way I can properly organize the several dozen of these that come along each day while I'm working. After trying many different solutions, what I found works best is a file called capture.txt where I know everything will be safe until I have time to review each item, make a decision about what needs to be done, and take appropriate action. There's no time or mental energy available for an elaborate system while I'm working. I need to enter a few keystrokes and start typing.

So, how did I implement this system in Textadept? The first thing I did was add a menu item for opening the capture file if it's not already open. (I prefer a menu item because I don't do this task often and the cognitive overhead of a menu item is lower than a keyboard shortcut or calling a function.) I added this in the `menu.lua` file:

```
{_L['Open Capture'], function() io.open_file(_HOME .. "/capture.txt") end},
```

Upon restart, which is instantaneous, I had a menu item to open that file.

Just having the file open isn't enough. I might be in the middle of the document when a new item comes in. I wrote a function that moves to the top of the document, adds two line feeds, and moves the cursor to the beginning:

```
function new_capture()
	buffer.insert_text(0, "\n\n")
	buffer.goto_pos(0)
end
```

The `0` in the first line of the function body tells it to insert that text at the start of the document. The second line moves the cursor to the start of the document. I could have called that function by hitting Ctrl-e and typing

```
new_capture
```

That's inconvenient, so I bound that function to Alt-i (for insert). In my init.lua file, I added

```
keys.ai = new_capture
```

Now all I have to do is hit Alt-i and start typing. 

I quickly discovered that isn't a complete solution. If I just type, I'll soon have a file that's a big wall of text, and it's not easy to work with something like that when I'm processing everything at the end of the day. That led me to resist the processing, and the system's a failure if I'm not doing the processing on a daily basis.

The solution is to start each item with an identifier so I know what I'm dealing with. If it's a task I need to do, it starts with `%task`. If it's a note, it stars with `%note` followed by a timestamp, which I've learned is often useful information. I have several other identifiers that may change from time to time.

For notes, I have the following in my init.lua file:

```
snippets['n'] = '%%note ' .. '%<os.date("%x at %X")> '
```

To enter a new note with a timestamp, the total work I do is:

1. Hit Alt-i to make space at the top of the file for the note.
2. Hit n followed by tab to insert the snippet.
3. Get all the information out of my head.

The snippet puts something like this:

```
%note 08/30/2019 at 09:53:54 AM 
```

Of course you can do any of this with Emacs. The point is that you can do it in Textadept just as well, or even easier, and you might prefer a lightweight, extremely performant editor. It's not the case that you *have* to use Emacs to get this functionality. Anything you can do in Lua (which is a heck of a lot) or by calling out to a command line program (which might be written in Emacs Lisp) you can do in Textadept.