Hacking Fish Script In Emacs
Published: 2021-10-07 12:41:04

What tools do you use when generate Insert SQL by CSV, calculate some data?
There're a lot of ways, like using text editor macros, writing shell scripts, typing manually.
Terms of reproducibility, I always write shell scripts in the junk file and share code as needed.

I think bash script is the most written script in the world, but the grammar is so old.
These days, [zx](https://github.com/google/zx) script which grammar like JavaScript had published by google.
But we cannot use zx as a login shell, so I think we should not use it.

Fish script which grammar like Ruby is easy to learn and people who use it as a login shell is a lot.
It's easy to execute code by copy code and paste into REPL.

This time, I write the article how to hack fish shell in Emacs.

My Emacs config is below.
https://github.com/takeokunn/.emacs.d

## Packages

### fish-mode

https://github.com/wwwjfy/emacs-fish

```lisp
(leaf fish-mode
  :ensure t
  :setq
  (fish-enable-auto-indent . t)
  :mode ("\\.fish$"))
```

`fish-mode` is an Emacs major mode.
This package has features of syntax highlight and indent calculation.

It should enable `fish-enable-auto-indent` flag that can indent automatically when insert `end` or `else` or `case`.


### company-shell
https://github.com/Alexander-Miller/company-shell/

```lisp
(leaf company-shell
  :ensure t
  :config
  (push 'company-fish-shell company-backends))
```

`company-shell` is a `company-mode` plugin, which is completion library.


Internally, the implementation of insert candidates is fetching fish script's functions by `functions -a` `builtin -n`.

2021/09/26 Today, It's heavy to show completions.
https://github.com/Alexander-Miller/company-shell/issues/15

It's seems that `whatis` command is slow, and it's not necessary information.
So I tried to fork this repository and create `company-shell-meta-enable` variable to disable it.

Let you clone my repository by `el-get`.
https://github.com/takeokunn/company-shell/commit/c35f0b90596d971f9b0d2cc1de586969f02c6c32

```lisp
(leaf company-shell
  :el-get (company-shell
           :url "https://github.com/takeokunn/company-shell.git"
           :features company-shell)
  :config
  (push 'company-shell company-backends)
  (push 'company-shell-env company-backends)
  (push 'company-fish-shell company-backends))
```

### fish-repl
https://github.com/takeokunn/fish-repl.el

```lisp
(leaf fish-repl
  :el-get (fish-repl.el
           :url "https://github.com/takeokunn/fish-repl.el.git"))
```

This REPL library is my work.
This repository enables you to do REPL driven development.

It can send codes in buffer to Fish REPL.
It's still a work in progress, so I want to develop based on [nodejs-repl](https://github.com/abicky/nodejs-repl.el).

### org-babel

```lisp
(leaf ob-fish
  :el-get (ob-fish
           :url "https://github.com/takeokunn/ob-fish.git"))

(leaf ob-babel
  :after (ob-fish)
  :config
  (org-babel-do-load-languages 'org-babel-load-languages
                               '((fish . t))))
```


This library is my work too.

I store some org files which I wrote fish script in the past.

```org
#+begin_src fish
function say_hello
    echo Hello $argv
end

say_hello "world"
#+end_src

#+RESULTS:
  : Hello world
```

### yasnippet

https://github.com/joaotavora/yasnippet

`yasnippet` is power-full snippet plugin.
`yasnippet-snippets` plugin has a lot of `fish-mode` snippets.

https://github.com/AndreaCrotti/yasnippet-snippets/tree/master/snippets/fish-mode

I recommend that you may manage snippet by org file.

https://takeokunn.xyz/blog/post/emacs-yasnippet-setup

## Conclusion

Fish script is easy to learn and write, so why don't you use it?