Common Lisp tool for automating tasks for Unix power-users.
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
old
.gitignore
CHANGELOG.md
LICENSE
README.org
powerlisp.lisp

README.org

Powerlisp

Common Lisp tool for automating tasks for Unix power-users.

Abstract

Powerlisp is a simple and flexible tool which helps you automate your work. With the aid of dmenu or rofi, this Lisp script allows you to:

  • Navigate directly to your favorite websites, in your favorite browser (including incognito mode);
  • Search the web on your favorite search engine (and switch search engines as well);
  • Use flexible configuration files written on Lisp, provided by hygienic user bindings;
  • Create your own menus, submenus and input, while allowing you to extend it from within the user bindings, in any way you want;
  • Hack it any way you’d want and make it yours!

This tool is written with dmenu and/or rofi in mind, plus notify-send for desktop notifications, and only runs using the sbcl compiler. While it is certainly possible to use other implementations, those may require implementation-specific extensions, which is what I am using.

I opted for this instead of using any external, cross-implementation package (such as Quicklisp) for performance reasons.

Motivation

Back in the day, I used to have a simple tool written in Bash which would allow me to open menus and nest them just like you see. The purpose was just to store my favorite websites and perform searches on the internet, without directly opening the browser in order to do so.

Turns out this approach wasn’t very flexible, and extremely hackish; this made me realize that bash is also not a language you would want to mess up with, when things get heated, due to its lack of easy support to trivial tasks such as string manipulation and this sort of thing.

At this point, there were two things I could do: either switch to a shell which gives me better scripting capabilities, or use an actual programming language to rewrite this tool altogether. As you can see, I chose the latter.

So, why Lisp? Well, because I could, and also to prove a point. Most tools nowadays are written in Javascript or Python, two languages which can be much slower than Common Lisp at times. However, Common Lisp is a perfectly functional and powerful language, albeit a little old. Plus, I just did not want to choose those languages, since we see them running everywhere, even though sometimes it is not the best use case. Instead, I went ahead and start taking advantage of CL’s scripting support, something that was already being used on tools such as Roswell, for example.

And so the first version of this tool arised, though it was a bit lacking; but little by little, I started adding things to my taste, which I felt would improve my workflow.

Usage

All you need to do is invoke the script using a command line:

sbcl --script /path/to/powerlisp.lisp --no-linedit

You can input this command on your favorite tool for managing keybindings, which is native on window managers such as openbox, for example. On my end, I use sxhkd for configuring keybindings, and so I have a shortcut which spawns this very line of code.

Make sure you have Steel Bank Common Lisp (sbcl) installed. It should work on any newer version (currently runs well under version 1.4.10).

Make sure you have dmenu installed as well. You can also use rofi, though using it will require a few lines of configuration; see the Wiki for examples.

Hacking it

As stated before, Powerlisp is highly hackable.

There are some functions, macros and variables which any user may want to change; they will be better documented on the Wiki, so make sure you check it out. Below I’ve listed all of them in their order of appearance and cathegory, for a quick reference.

Breaking changes have been stated on the CHANGELOG file, so you should probably look at it as well.

;;; Global, customizable variables
*browser-command*
*browser-incognito-flag*
*notify-command*
*launcher-prompt*
*launcher-command*
*launcher-on-bottom*
*launcher-rofi-emulate-dmenu*
*launcher-font*
*launcher-bg*
*launcher-fg*
*launcher-sel-bg*
*launcher-sel-fg*
*default-search-engine*
*rerun-main-menu* ; only change when using submenus

;;; Runtime variables, do not change directly
*search-engines*
*favorite-websites*
*subcommands*
*incognito-mode*

;;; User customization API
;; Functions
(powerlisp-add-favorite atom url)
(powerlisp-add-multi-favorites favorites-list)
(powerlisp-add-search-engine atom query-parts)
(powerlisp-add-multi-search-engines engines-list)
(powerlisp-add-command command callback)
(powerlisp-add-multi-commands commands-list)
(powerlisp-spawn-menu prompt alist)
(powerlisp-notify text &optional title)
(powerlisp-call-browser website)
(powerlisp-call-external program-path &rest arguments...)

;; Macros
(powerlisp-request-user-input &optional prompt)
(with-powerlisp-user-input (&optional prompt) &body body...)
(with-powerlisp-options-menu (prompt alist) &body body...)
(with-powerlisp-menu (prompt alist) &body body...)