Command Line Programs

Command Line Programs

Running Programs in Nyxt

Nyxt 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-command youtube-dl-current-page ()
  "Download a Youtube video in the currently open buffer."
  (with-result (url (buffer-get-url))
     (list "youtube-dl" url))))

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

(define-key "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 Nyxt. 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 C-x s to enter *shell-mode* and c to enter a command and k to clear the command output.

(define-mode shell-mode ()
    "A basic shell prompt."
      (let ((map (make-keymap)))
        (define-key :keymap map
          "c" 'run-shell-command
          "k" 'clear-shell)
        (list :emacs map
              :vi-normal map)))))

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

(define-command clear-shell (shell-mode)
  "Clear the output in the shell buffer."
   *interface* (active-buffer *interface*)

(define-parenscript 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
                           (format nil "<pre><code>~a</code></pre><br/>" output))))))

(define-command run-shell-command (shell-mode)
  "Run a shell command."
      (input (read-from-minibuffer
              (minibuffer *interface*)
              :input-prompt "Run in shell:"))
     *interface* (active-buffer *interface*)
      (uiop:run-program input :force-shell t :output :string)))))

(define-command shell ()
  "Open a shell buffer."
  (set-active-buffer *interface* (make-buffer :name "*shell*" :default-modes '(shell-mode))))

(define-key "C-x s" #'shell)

Within 40 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

Nyxt 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 Nyxt will turn into your system shell, process manager- even though it could.

Thanks for reading!