AdSense Mobile Ad

Showing posts with label zsh. Show all posts
Showing posts with label zsh. Show all posts

Monday, January 1, 2018

tm-cleanup.sh: A Shell Script to Delete Old Time Machine Backups Now Features an Interactive Interface

More than two years ago I wrote tm-cleanup.sh, a shell script to delete Time Machine backups. During this time it has proven very useful to me, and it's been serving its purpose as it is, with barely any modification at all.

However, I've been asked for help and clarifications quite a number of times by non-tech-savvy users who had some issues using the CLI. For this reason I thought that adding an interactive, dialog-based interface to this script may help people "visualise" what's going on when running tm-cleanup.sh.

The new interface has been added in v. 2.0.0, and can be opened by simply issuing the following command with no options:

$ sudo tm-cleanup.sh

The interactive interface opens a menu where the backup deletion operation can be triggered. The user is then presented the list of existing Time Machine backups and they can be individually selected and then deleted. Here's a screenshot of the interface showing the existing backups:


The documentation of the repository describes in detail both interfaces. I hope people will find it useful.

Thursday, December 21, 2017

Starting an Emacs Daemon Automatically and Transparently using ZSH

If GNU Emacs is one of your editors of choice, then you may want to consider running Emacs as a server. Using an Emacs server is very convenient, especially if you open many Emacs processes (as it happens when the EDITOR variable is set to emacs in your shell). The reasons why you would use an Emacs server are manifold, and the most important are:
  • Using an Emacs server results in a great increase in speed and responsiveness of Emacs.
  • The fact that sharing the same Emacs process implies sharing buffers, command history, and many other information.

Starting an Emacs Server

An Emacs server can be started in two ways:
  • Running Emacs as a daemon, using the --daemon option:
$ emacs --daemon
  • By launching it from inside an Emacs process using the server-start function:
M-x server-start

Once an Emacs server is running, you can use the emacsclient program to tell a running Emacs server to visit a file. The server and the client are quite sophisticated, and you can use them for example to connect a client to a server running on a remote machine. Most of the time, however, you'll be running the daemon and the client on the same host.

A question I get often is: how to start the server if it's not running and then connect to it? I've seen a lot of solutions to this problem, and probably one of the commonest is starting an Emacs server at login, and then using emacsclient to connect to it.

There's a fundamental thing I don't like about it: it's not transparent. However, since it's a very common approach, I'll quickly document how it's accomplished on macOS.

Starting an Emacs Daemon on macOS at Login

The canonical way to start a process when a user logs in on macOS is using launchd. launchd is the "system wide and per-user daemon/agent manager" and it "manages processes, both for the system as a whole and for individual users" (launchd(8) man page). The processes to be started at user login are called launch agents and are defined in plist files in the ~/Library/LaunchAgents directory.

The easiest way to start an Emacs server, then, is to launch emacs with the --daemon option. The corresponding launch agent file is the following:


Note: the emacs path and the UserName element must contain correct values for your system.

Once the launch agent descriptor has been created, it can be loaded using the following command:

# launchctl load -w /Library/LaunchAgents/gnu.emacs.daemon.plist

This solution is fine, but it has two major disadvantages: it requires a configuration, and the configuration is non-portable.

Starting an Emacs Daemon On-Demand and Transparently

A simpler and portable solution (provided you're using ZSH) is leveraging emacsclient's ability to start a daemon if none is found in a ZSH function. Instead of having to explicitly use emacsclient after a server has been started, wouldn't it be nice to always use the same command, start a server if none is running, and connect to it transparently? Assuming we can do that, why not just calling this command emacs?

Fortunately, this is very easy to accomplish with emacsclient and ZSH:
  • emacsclient is able to start an Emacs daemon if none is running using the -a option with an empty argument.
  • emacsclient can be invoked without a file name when the -c option is used, in which case a new frame showing the *scratch* buffer is created, mimicking emacs behaviour.
  • ZSH lets us easily create "aliases on steroids" using a function such as the following:


Now, every time you invoke emacs in ZSH, the shell will run the emacs() function instead, which will run emacsclient -c -a= and will forward all its arguments to it.

When using an Emacs daemon there are some things to take into account. And that's what the official documentation is for. I will only say that since you are now sharing a single Emacs process, its frames and its buffers, you may now want to use C-x # when done with a buffer (or C-x C-k). This way you will kill the buffer and it won't be left hanging around.