abbreviations.fish The Abbreviations Configuration

The abbreviations the file goes into ~/.config/fish/conf.d/.

Abbreviations are sort of like aliases except fish will expand them once you hit space or enter. If, for example, you enter nb ~ when you hit the space-bar fish will replace nb with nikola bulid. This makes them more transparent than functions, although they're also less powerful.

According to this github issue the files you put into conf.d/ get read before config.fish so whatever you put in there is usable in config.fish (and using config.fish) at all is optional.

Nikola

Abbreviations to hopefully make working with Nikola a little quicker.

abbr --add -- n "nikola"

New Posts and Pages

I only use org-mode so these are the commands to make new posts and pages.

abbr --add -- post nikola new_post --format orgmode --title
abbr --add -- page nikola new_page --format orgmode --title

They actually look like the same files are produced, just one gets put into your pages folder and one gets put into your posts folder. Which is nice, I guess, in that we can move things back and forth between the blog and the web-pages as we need to.

Build, Serve, and Develop

These are the ones I use the most when making posts and pages.

abbr --add -- nb "nikola build"
abbr --add -- nbs 'nikola build; nikola serve'
abbr --add -- nauto "nikola auto"

auto will build and reload the page for you anytime it sees any changes. This can be convenient sometimes, but sometimes it detects changes to often (maybe when something is making a temporary backup) and it can end up reloading while you're reading the page so I don't use it as much as I used to.

Deploy to Github

And once it's ready…

abbr --add -- deploy "nikola github_deploy"

Git

abbr --add -- g "git"

Add, Commit, Push Stuff

Adding Files

abbr --add -- add "git add"
abbr --add -- gaa "git add -A"

Are you ready for a commitment?

abbr --add -- commit "git commit"
abbr --add -- gcm "git commit --message"
abbr --add -- amend "git commit --amend"

Speak To The Gods On High

sync is a builtin command (it writes caches to disk) so I went with gsync for the abbreviation.

abbr --add -- push "git push"
abbr --add -- gsy "legit sync"
abbr --add -- publish "legit publish"
abbr --add -- fetch "git fetch --prune"

The State of Things

status gives you information about the fish-shell. This is the only thing I ever see, though.

status
This is not a login shell
Job control: Only on interactive jobs

But, anyway, I went with gstat to not block it in case it's really needed at some point.

Note: Look at the SSH Agent Config Fragment post to see status in use. It's probably meant for programming, not as a command-line command.

abbr --add -- state "git status -sb"
abbr --add -- gstat "git status"

Branch Work

switch is a built-in fish command to conditionally decide what to execute (like a chain of if-else statements).

abbr --add -- branches "legit branches"
abbr --add -- branch "legit switch"
abbr --add -- brls "git ls-tree --name-only -r"
abbr --add -- brlog "git log --oneline --abbrev-commit" \
    " --all --graph --decorate --color"
abbr --add -- brlogall "git log --branches --graph"
abbr --add -- renamebranch "git branch -m"
abbr --add -- merge "git merge"
abbr --add -- cob "git checkout -b"
abbr --add -- destroy "git branch -d"
abbr --add -- destroythegods "git push origin -d"

Checkout Files

abbr --add -- usetheirs "git checkout --theirs"
abbr --add -- useours "git checkout --ours"

My, How Things Have Changed

abbr --add -- codechanges "git log -p"
abbr --add -- logdiff "git log -p"
abbr --add -- gdiff "git diff"
abbr --add -- gdiffn "git diff --name-status"

Pass

For pass the password-manager. I was doing the pull and push commands but decided to use the git sync alias which is actuall calling legit sync, which I think does pretty much the same as what I was doing. It does other stuff like stashing uncommitted changes, but that should never happen when using pass. Anyway. Sync.

abbr --add -- p "pass"
abbr --add -- pgs "pass git sync"

Grep

abbr --add -- grepr "grep --color=always"

Proton VPN

abbr --add -- vdc "protonvpn-cli disconnect; protonvpn-cli connect"
abbr --add -- fastestvpn "protonvpn-cli disconnect;protonvpn-cli connect --fastest; protonvpn-cli status"

Rsync

Rsyncer

abbr --add -- rsyncer "rsync --progress --archive --compress"

Rsyncerd

abbr --add -- rsyncerd "rsync --progress --archive --compress --delete"

Rsyncerf

Creates the folder structure but doesn't copy the files over.

abbr --add -- rsyncerf 'rsync --progress --archive --delete --include="*/" --exclude="*"'

Rsyncery

Does a dry-run to show what would be done without actually transferring files. I made this because for some reason the Raspeberry Pi with Debian 11 on it has some kind of bug that makes rsync fail if the transfers take too long. I don't really know the cause, but it doesn't happen with newer ubuntu versions so it seem like either it's a bug in the creation of the LUKs drive (since I'm creating it on the Raspberry Pi) or in the running of rsync (when the error actually occurs), but in either case, I sometimes need to do sub-folders one at a time instead of just syncing the top folder in order to keep the transfers shorter and running this lets me see what folders need to be synced.

abbr --add -- drysync "rsync --verbose --archive --delete --dry-run"

Links

Rsync

  • Server Fault: Answer explaining the --archive option (I was using it before but also adding other flags that were redundant to it).
  • Server Fault answer: explaining how to create the folder structure but not copy the files.

config.fish The Fish Configuration

This is the fish configuration file. It goes into ~/.config/fish/config.fish.

Environment Variables

The --export flag exports the shell variable to child processes, making it an "environment variable".

Emacs

Sets us up to use the emacs client as the default editor.

  • --create-frame tells emacs to create a new frame instead of continuing in the current one (if it's already open).
  • --alternate-editor: what to fall back to if the emacs-client server isn't running.
set --export ALTERNATE_EDITOR ""
set --export EDITOR "emacsclient --create-frame"
set --export VISUAL "emacsclient --create-frame --alternate-editor emacs"

The Rest

# for extra docker build features (like smarter pip caching)
set --export DOCKER_BUILDKIT 1

# R Downloads
set --export R_LIBS ~/.local/lib/R/library/

Proton VPN

The current command-line interface is deprecated so it gets uninstalled when you install the GUI, but the GUI was having problems so I uninstalled it and went back to using the CLI, but depending on what is installed this may or may not work (and it is kind of slow so it may not be a good idea anyway). Everytime you open a shell this will run (e.g. a byobu window or SSH session).

# check the vpn (requires the installation of the proton-vpn command-line command)
if status --is-interactive
  protonvpn-cli status
end

rst2org Function

function rst2org -d "Convert text file to org" --argument-names sourcefile
    set target $(path change-extension org $sourcefile)
    pandoc --standalone $sourcefile --output $target --wrap=none
end

This function will convert a text file to an org file using pandoc. I called it rst2org because I created it specifically to convert restructured text, but since pandoc can infer it from the file extension it can be any input type that pandoc recognizes, I suppose.

What It's Doing

The first thing the function does is change the file extension from whatever it is to "org". So whatever gets passed in as the argument should have an extension like ".rst". Then it runs pandoc.

  • --standalone: by default pandoc strips out the header and footer, this option tells it to keep it (useful for nikola and most other thing I would imagine)
  • --output: The output file name which pandoc also uses to guess the format we want to use.
  • --wrap=none: by default pandoc will insert line-breaks to keep the lines within their default width, adding this argument keeps long lines as single lines.

Links

  • mb21. Answer to “Word to Markdown via pandoc: prevent line breaks in paragraphs” [Internet]. Stack Overflow. 2020 [cited 2023 Jun 22]. Available from: https://stackoverflow.com/a/62990248

The first option documented in the options section of the pandoc documentation is --from which then lists all the languages that pandoc can take as an input.

las: Colored List All

function las
    ls --almost-all \
       --color \
       --dereference-command-line \
       --human-readable \
       -l $argv | \
        less --RAW-CONTROL-CHARS
end

The point of this function is to show all the files in the directory (including hidden files) and pipe them to less so they won't go scrolling off the screen while keeping the color highlighting.

The Parts

The ls Arguments

  • --almost-all: don't list the . and .. files
  • --color: Color the output when (defaults to "always" but you can set to "auto" or "never")
  • --dereference-command-line: follow symbolic links listed on the command line
  • --human-readable: Put file sizes into units that make sense (when using -l)
  • -l: Long listing format.

The less Argument

  • --RAW-CONTROL-CHARS: Keep colors and hyperlink sequences.

There is also a --raw-control-chars option which will include all escape sequences, but they say this might cause less to not be able to control the appearance of the screen so they don't recommend using it. Also, you can set the LESS environment variable to pass in options, so if this is useful enough it might make sense to put it in there instead.

Choose Function

Choose

An alias function that will pick a random line (or lines) out of a text file.

The Function Declaration

Our alias function (choose) takes one required argument that we'll assign to the variable filename and one optional argument lines to indicate the number of lines to pull.

function choose -d "Random line from a file." --argument-names filename lines

The Error String

I'm setting a string-format variable that I'll use to color error messages in bold red.

set ERROR "\x1b[31;1m\t%s\n\n\x1b[0m"

See this stack overflow answer for more explanation of the codes. Basically the 31;1m part turns on red (31) and bold (1) and 0m resets it back to unbolded black text.

The Okay Variable

This is getting a little convoluted but I added another check for the second argument to make sure it's a number so this flag is just there to indicate that it did or didn't look like right.

set OKAY 0

I'm setting it to False so that it has to pass the checks in order to be unset.

Check the Number of Lines

Unlike random, shuf will let you pick multiple lines so I added a second (optional) argument to indicate the number of lines to output. If none is passed in then it's set to one, if something other than an integer is passed in then we'll set a flag so we know to skip calling the shuf command later on.

  • test -n "$lines" will return True if lines is non-empty so I negated it with ! to return True if it's empty.
if ! test -n "$lines"
  set lines 1
  set OKAY 1
else if ! test (string match --regex "^[0-9]+\$" $lines)
  set OKAY 0
  printf $ERROR "Not a valid number of lines: '$lines'"
else
  set OKAY 1
end

If It's a Text File, Use It

We'll be grabbing a line using the shuf command. shuf will hang if no filename is given and it will try and read binary files so first we have to test the filename to make sure it's a text file.

To do the check I'm using the file command which will have the word "text" in the output if we give it a text file. Then I feed the output from file to the string match command. This command defaults to only return true if the whole string matches so I added a glob to both ends of the "text" string to match any string that contains it. So, in order to pass the test filename has to have the name of a text file or we won't match the output of the file command.

First, though, we check if the lines argument was okay and if it was and filename passes its test then we can feed it to shuf.

if test $OKAY -ne 0; and test (string match "*text*" (file "$filename"))
   shuf -n $lines $filename
  • test $OKAY -ne 0 will return True if OKAY != 0. It will return an error if OKAY holds something other than a number.
  • the ; and syntax is a short-circuit syntax that won't run the second test if the first one fails.

Handle the Errors

If the number of lines wasn't okay or the filename wasn't valid then we'll emit a help message. Since we emitted any error message about the number

else
  if ! test -n "$filename"
    printf $ERROR  "**Missing Filename**"
  else if test $OKAY -ne 0
    printf $ERROR "Invalid File: '$filename'"
  end
  set OKAY 0
end # check filename

Emit a Help Message

If it had a valid number of lines and a valid filename then OKAY will have a value of 1, otherwise it will have a value of 0 and we'll emit the help message.

if test $OKAY -eq 0     
  printf "\t%s\n" \
         "Output a random line or lines from a text file." \ \
         "Usage:" \ \
         "    choose <filename> [<number of lines>]"
end # help message

One Last Thing

If the user passes in a flag as a filename this will get passed to the file command and in some cases this will cause it to emit a help message which will get passed to the shuf command. It's probably not a good idea to let that happen, but this was only supposed to be an alias so I wouldn't have to remember the syntax for shuf, so hopefully it'll work okay.

Sources

Random Hex

The randomdhex Function

This an alias function to output a random hexadecimal number. There are many ways to do this but I took this from a StackOverFlow answer.

The Function Header

I'm going to create a function named randomhex that takes one optional argument named digits.

function randomhex -d "random hex string" --argument-names digits

Argument Check

The first thing to do is to check if the user passed in an argument and handle it if they did or use a default if they didn't.

Check For An Argument

The first check uses the test command to see if the user passed in an argument. the -n flag tells it to check if there's a string with one or more characters in it in our digits variable.

if test -n "$digits" # then an argument was passed in

Check If The Argument Is An Integer

If the user did pass in an argument but it can't be coerced to be an integer then our function won't work right so we need to see if the argument is made up of nothing but digits using the string match command and a regular expression to make sure it's only made up of one or more digits.

if test (string match --regex "^[0-9]+\$" $digits)

Set the Argument Value

If the argument was an integer then we'll set the BYTES variable to half of whatever the user passed in, because each byte is represented by two hexadecimal digits (8 bits gives values from 0 to 255 in decimal, 00 to FF in hexadecimal). The argument is a string so we need to pass our division expression ($digits/2) to the math command in order for it to be evaluated as a number. Additionally, the division operator will return a float if the user's input isn't evenly divisible so I'll use the ceil argument to round up to the nearest integer.

set BYTES $(math ceil $digits/2)

Error Message

If the user passed in an argument but it doesn't look like an integer then we'll output a help message. I got the idea of using printf this way from this StackOverflow answer.

  • Each line after the first gets passend into the first string, substituted where %s is
  • One backslash continues the input
  • Two backslashes with a space in-between them will insert an extra line and continue the input
  • The space between the backslashes is important - fish will throw an error if you put \\ instead of \ \
else # the argument isn't an integer
  printf "\t%s\n" \
   "Output a random hexadecimal number" \ \
   "Usage:" \ \
   "randomhex <digits>" \ \
   "Optional argument:" \
   " - Number of digits (will round up to even number)" \
   "   Argument must be an integer (default=8)."
   return
end # if is-integer check

Use The Default

If the user didn't pass in an argument then use a default of 8 hexadecimal digits.

else # Set our bytes so we have 8 digits (double the bytes)
  set BYTES 4
end # setting the number of bytes

Output the Random Hexadecimal

Finally we output the random hexadecimal number that openssl generates.

echo $(openssl rand -hex $BYTES)

Sources