Running Programs in Next

Next gives you the power to extend its capabilities by invoking other programs. This allows you to chain Lisp functions and operations with any programs of your choosing.

A Practical Example: Download Youtube Videos

Let's consider the following situation: you are watching a Youtube video, but wait! You have somewhere to be! Why not download the video so you can watch it on the train where your internet access will be limited? Sounds good right? Let's see what options there are.

A quick search on the internet reveals a very convenient program called youtube-dl. Youtube-dl is invoked via the command line like this youtube-dl "url-to-download. Of course there are other flags and arguments, but let's consider the simplest case.

You could simply copy the URL and paste it into the terminal. That's not really cool though. Let's automate it:

(define-comand youtube-dl-current-page ()
"Download a youtube video in the currently open buffer"
  (let ((url (interface:web-view-get-url (view *active-buffer*))))
    (uiop:run-program
     (list "youtube-dl" url))))

Just like that! Instant youtube downloader script. If you want, bind it to a keybinding

(define-key *global-map* (kbd "C-c d")
  'youtube-dl-current-page)

Now whenever you want to download a youtube video simply "C-c d" and you'll have it on your computer!

"Shell" Mode

That was cool, but it doesn't really show the true power of Next. An example that is more illustrative is a very basic "shell" implementation. It is not really a shell because it doesn't have variables, piping, or anything else a shell really has, but it can run programs.

Simply put: shell mode is an extension for running simple one liner shell commands and seeing the output. There is no history or variables. Use to enter and to enter a command and to clear the command output.

(defvar *shell-mode-map* (make-hash-table :test 'equalp))

(defclass shell-mode (mode) ())

(defun shell-mode ()
  (make-instance 'application-mode
         :name "shell-mode"
         :keymap *shell-mode-map*))

(defparenstatic clear-shell-output
    (setf (ps:chain document body inner-h-t-m-l) ""))

(defparen append-output (output)
  (setf (ps:chain document body inner-h-t-m-l)
        (ps:chain document body inner-h-t-m-l
                  (concat (ps:lisp
                           (concatenate 'string output "<br />"))))))

(defun run-shell-command (input)
  (interface:web-view-execute
   (view *active-buffer*)
   (append-output
    (uiop:run-program input :force-shell t :output :string))))

(defun open-new-shell ()
  (set-visible-active-buffer
   (generate-new-buffer "*shell*" (shell-mode))))

(define-key *shell-mode-map* (kbd "c")
  (:input *minibuffer* run-shell-command))

(define-key *shell-mode-map* (kbd "k")
  #'clear-shell-output)

(define-key *global-map* (kbd "C-x s")
  #'open-new-shell)

Within 30 lines of Lisp we've managed to make a completely new mode that allows us to execute commands, view the output on screen, and even clear the screen.

The Take Away

Next can be extended with any program of any type as long as it accepts some form of IPC. This means that you can chain any process you want on your computer. Of course, this application has bounds of reason, you shouldn't imagine that Next will turn into your system shell, process manager- even though it could.

Thanks for reading!

Get Started with Next-browser:

Previous post