Function: PDF Pages

This is a function to make it easier to extract pages from a PDF using qpdf.

The Function Declaration

function pdfpages --argument-names source_pdf target_pdf pages -d "Extract pages from a pdf"

The Command Call

This uses qpdf (GitHub Repsitory) to extract pages from a PDF. It's a function not an abbreviation because you intersperse your arguments within their syntax, rather than just pasting it all after the call.

qpdf --empty --pages $source_pdf $pages -- $target_pdf

Error Handling

if test $status -ne 0
    echo "source_pdf = $source_pdf"
    echo "target_pdf = $target_pdf"
    echo "pages = $pages"
end

Alternate Key-Bindings

Table of Contents

Alt-Backspace

Fish decided to override the Unix/emacs behavior for alt-backspace in favor of (I think) the Common-User-Access (CUA) behavior which deletes all arguments to a command instead of the previous emacs-like behavior of deleting word by word. There's an alternate keybinding but I keep forgetting about it and end up wiping out entire paths or strings when trying to correct errors so I'm putting the prior behavior back.

Here's what I'm adding to the fish configuration:

bind alt-backspace backward-kill-word

This was taken from user rski's comment, which also had some other keybindings which I'm not putting in since I don't normally use them anyway, but I'll document them here in case I decide I need them later.

bind ctrl-alt-h backward-kill-word
bind ctrl-backspace backward-kill-token
bind alt-delete kill-word
bind ctrl-delete kill-token

From Fish's bind documentation:

backward-kill-word

Move the word to the left of the cursor to the killring, until the start of the current word (like vim’s db)

backward-kill-token

Move the argument to the left of the cursor to the killring

I don't know why you'd want to set ctrl-backspace to delete one token when backspace all by itself alread does this… peculiar.

Lowercase Word

While I'm at it - the default behavior for alt-l is to do a directory listing. Besides being redundant with ls it is a little counter-intuitive if you're used to emacs with uses this keybinding to change a word to lowercase. Oddly, the default for alt-u is to change a word to uppercase like you might expect. I'm not sure why alt-l was made the way it is, but I guess I'll change it to make words lowercase.

bind alt-l "downcase-word"

downcase-word

Make the current word lowercase.

Links

PDF Functions

Table of Contents

Dump Bookmarks

This uses PDFTK to dump bookmarks (so it's not compatible with cpdf).

function pdfbookmarks -d "Dump bookmarks from a PDF (pdftk format)" --argument-names SOURCEFILE OUTFILE
    if set --query OUTFILE
        set OUTFILE "bookmarks.txt"
    end
    pdftk $SOURCEFILE dump_data_utf8 output $OUTFILE
end

See the PDF TK section of the Tealdeer post for (a little) more information.

Upgrade Function

The Function

This is a function to upgrade the various packages. It might, perhaps be better as an abbreviation…

function upgrade --description "Upgrade packages."

Bold Blue

This is a helper function to set lines (specifically headlines in this case) to be bold and blue. If this gets done enough maybe it should be a standalone function, but for now it's embedded in the upgrade function.

function boldblue
    set_color --bold blue
    echo $argv
    set_color normal
end

Apt Calls

These are calls to update the debian-based packages.

Update

These calls update the database and then show us what is upgradable.

boldblue Checking apt
sudo apt-fast update --yes
sudo apt-get --just-print upgrade

I was initially using apt to list the upgradable packages, but installing more as a pager causes its output to get piped to it, stopping progress until I quit it. Looking into how to get around it I read that apt is a front-end to other packages to make them easier to use, and that apt-get is better for non-interactive use (and is one of the things that apt is using behind the scenes anyway).

Upgrade and Autoremove

Now we run the upgrade. upgrade will upgrade installed packages and install any dependencies that are needed, but not uninstall any already installed packages. If upgrading needs to a removal it won't do the upgrade. full-upgrade will do what upgrade does but will remove any installed packages if needed to upgrade an installed package. So, we're going with full-upgrade.

I'm also auto-removing any packages that get orphaned as dependencies by an upgrade.

boldblue Upgrading apt
sudo apt-fast full-upgrade --yes
sudo apt-get autoremove --yes

Snap

Snaps should update themselves. But let's see what happens if we do it.

boldblue Updating snaps
sudo snap refresh

Flatpak

Update

boldblue Updating flatpak
flatpak update --assumeyes

type checks how a name would be interpreted (function, bultin, or file ). It returns 0 if it isn't defined. query suppresses the output.

Note: I was running this with --noninteractive but for some reason this still emitted messages that something needed to be fixed but suppressed the message telling me which package needed to be fixed, so it seems better not to use that option.

Uninstall

boldblue Uninstalling unused flatpaks
flatpak uninstall --unused --assumeyes

Some Messages

Phased Updates

The following upgrades have been deferred due to phasing:
  alsa-ucm-conf

This message is referring to Phased Updating. That is, there is an update that is being rolled out in stages to see if it is stable before it's given out to everybody. So the update exists, but you won't get it until the developers decide it's okay to roll it out to everybody.

Tealdeer Pages

Note: As of February 18, 2026, tealdeer via apt is out of date. They changed the URL used for updating the cache (see https://github.com/tealdeer-rs/tealdeer/issues/459) so versions older than 1.8 throw an error (apt currently installs 1.7.2-1). To get 1.8 I used the Cargo Installation Instructions (which necessitated installing cargo and rust…).

This is for configuring tealdeer, a command-line help system.

  • The expected folder in this repository to put these pages is dingehaufen/tealdeer/pages/.
  • The default location that tealdeer will look for the pages is \(~/.local/share/tealdeer/pages/~\) so maybe symlink it there.
  • The pages that come with tealdeer are at \(~/.cache/tealdeer/tldr-pages/pages/\) (look here for examples)

Patches

These are patches which extend existing help pages rather than replacing them. If you want to add a new command or replace the existing tealdeer help you would use pages instead (they go in the same folder, there's just a different file-name convention).

Screen

Name the Screen

- Give the screen a name

`<Ctrl-a> A`

Ghostscript (gs)

This is for ghost script.

Black and White PDF

This is to convert a PDF's text and vector images to Black and White to make it easier to read when printed. From a Ask Ubunt (Stack Exchange) answer.

In the cases I've tried this doesn't convert raster images.

- Convert PDF text to black and white (not grayscale)

`gs -sDEVICE=pdfwrite -dBlackText -dBlackVector -dNOPAUSE -dBATCH -sOutputFile={{output-file-name}} {{pdf-input-file-name}}`

Black and White PDF and No Images

This is the previous command (Black and White) but it removes all images, leaving only vectors-based items. This is for the case where someone used a background image and all you're interested in is the text and tables.

Removes all images.

- Convert PDF text to black and white (not grayscale) and remove all images

`gs -sDEVICE=pdfwrite -dFILTERIMAGE -dBlackText -dBlackVector -dNOPAUSE -dBATCH -sOutputFile={{output-file-name}} {{pdf-input-file-name}}`

Compress For Ebook

This adds some extra flags to the compression help that comes with tealdeer.

- Reduce PDF File Size, possibly more than the version up above

`gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook -dNOPAUSE -dQUIET -dBATCH -dDetectDuplicateImages -dCompressFonts=true -sOutputFile={{output-file-name}} {{input-file-name}}`
  • See : Optimizing PDFs - From the Ghostscript Blog. This notes that DetectDuplicateImages is actually on by default so you only need to use it if you want to turn it off, but I didn't read that until after using it. It might make sense to experiment with it on and off. The same might go for the CompatibilityLevel.

Convert To Grayscale

Sometimes images are RGB even though they are of black and white or gray images. Adding these flags will convert them to grayscale only. This actually doesn't save a huge amount of space most of the time (although it might if the image really was color and you're converting it tq gray) but I add the flags to the Black and White settings above to squeeze out a little more. It sometimes makes them look nicer as well.

I've only tested this with images, not vector graphics, but I think that it will strip the color from both, not just the images. Should test that out eventually…

- Convert color to grayscale

`gs -sProcessColorModel=DeviceGray -sColorConversionStrategy=Gray -sOutputFile={{output-file-name}} {{input-file-name}}`

Source: Stack Overflow - Convert PDF to grayscale without rasterization?

Resize (to Letter)

Evince no longer has the "Scale to Printable Area" option when printing PDFs, so this is something to use to get the PDF to letter-sized before printing. (from Stack Overflow: Resizing a PDF Using Ghostscript)

- Convert to Letter sized

`gs -sDEVICE=pdfwrite -dNOPAUSE -dBATCH -dCompatibilityLevel=1.4 -sPAPERSIZE=letter -dFIXEDMEDIA -dPDFFitPage -sOutputFile={{output-file-name}} {{input-file-name}}`

Virtual Fish

Check The Environment

This adds the build-state for the virtual-environments managed by virtualfish.

- List Environments and the Current State (do they need to be rebuilt?):

`vf ls --details`

Rebuild the Environment

This is the command to use after an Ubuntu upgrade where they change the python version and all the virtual environments are broken.

- Rebuild the current environment (e.g. after Ubuntu changes pip):

`vf upgrade --rebuild`

You can also rebuild a specific environment (not necessarily the one you're in).

- Rebuild a specific environment

`vf upgrade --rebuild {{virtualenv-name}}`

If the environments are broken by an update, pipx is likely broken too, run this too, maybe:

  • pipx reinstall-all
  • pip install setuptools --upgrade

pdfjam

Resize to Letter

- Resize PDF document to letter-paper size

`pdfjam {{input-file}} --paper letter --outfile {{output-file-name}}`

`pdfjam {{input-file}} --papersize 8.5in,11in --outfile {{output-file-name}}`

Emacs

Open File With Sudo

Got this from a Stack Overflow Question. The user's question is asking for an alternative way to do this, but the answers tell him that it's the best way to do it after all (he thought it was using SSH but it uses a sub-shell).

- Open a (local) file with sudo.

`C-x C-f /sudo::/path/to/file`

Use a Different Init.el

This is to use a different init.el file (presumably for debugging).

- Use a different initialization file when starting up:

`emacs --init-directory={{path/to/directory-with-init/}}`

Image Magick

Remove PDF Background

This assumes a image "density" for the background and converts the pages to images so the output file will likely be much larger. It might be best to use this for printing and then deleting the converted PDF.

- Remove background of PDF assuming the image density

`magick convert -density 300 {{path/to/input.pdf}} -white-threshold 80% {{path/to/output.pdf}}`

I also tried removing the background color specifically but doing that eats into everything that sits above the background as well (removes the anti-aliasing overlap, I assume).

PDF TK

Export Bookmarks

Export bookmarks from a PDF. I normally use cpdf for bookmarks, but in the case of Wanderhome, when I reduced the resolution to get a smaller PDF it removed the bookmarks so I had to copy them from the original and for some reason cpdf couldn't dump them, but pdftk could.

Pdftk uses a human-readable format that isn't compatible with cpdf. For Example:

BookmarkBegin
BookmarkTitle: wanderhome.pdf
BookmarkLevel: 1
BookmarkPageNumber: 0
BookmarkBegin
BookmarkTitle: Copyright
BookmarkLevel: 2
BookmarkPageNumber: 0
BookmarkBegin
BookmarkTitle: Table of Contents
BookmarkLevel: 2
BookmarkPageNumber: 0

Taken from PDFLabs Export and Import PDF Bookmarks.

- Export existing bookmarks from a pdf (UTF-8 Version)

`pdftk {{input.pdf}} dump_data_utf8 output {{bookmarks.txt}}`

Import Bookmarks

Import bookmarks dumped from another PDF. The prompt for this was that I reduced the resolution/size of a pdf and lost the bookmarks in the original and restored them by copying them over.

- Import pdftk-formatted bookmarks (from dump_data_utf8)

`pdftk {{to-update.pdf}} update_info_utf8 {{bookmarks.txt}} output {{updated.pdf}}`

exiftool

exiftool is a metadata editor. It handles many file types but I used it for PDFs.

Title

- Change the title for the file
- Note: The option needs the "=" between the name and the argument, spaces make it think you're passing in another input file.

`exiftool -Title="{{new title}}" {{input-file}}`

Pages

These are pages - whatever you put in a page file will be the starting point for the tealdeer entry - these will either start a new tealdeer entry or will clobber any exsting one that came with tealdeer. The thing that tells tealdeer that it's a page and not a patch is that the filename ends with page.md instead of patch.md. Otherwise the contents look the same.

Keychron K12 Keyboard

Although this is hardware, I thought it'd be helpful to put something in here in case I forget things.

Bluetooth Pairing

- Enable pairing (also needs the side-switch to be moved from USB to bluetooth). Q is QWERTY-based.

`fn1-Q (hold until LED lights up)`

MakeMKV Command Line

The makemkvcon command has a --help output, which is somewhat vague. I got the information for this from a developers text file usage.txt on makemkv.com/developers. Normally I use the GUI but sometimes it crashes due to errors specific to the GUI so the command line interface is useful to work around those cases.

List Drives

This lists the drives as makemkvcon sees them.

- List drives - DRV:index,visible,enabled,flags,drive name,disc name

`makemkvcon --robot --cache=1 info disc:9999`
Option Description
--robot Meant for automation, tells the program to output the information to the screen
--cache=1 Reduce the cache size (optional)
info The sub-command to print information
disc:9999 Show discs (not files, etc.)

The output looks something like:

MSG:1005,0,1,"MakeMKV v1.18.2 linux(x64-release) started","%1 started","MakeMKV v1.18.2 linux(x64-release)"
DRV:0,2,999,1,"DVD+R-DL HL-DT-ST DVDRAM GSA-T50N RQ01 KWF9AEJ1028","MAD_MAX_FURY_ROAD","/dev/sr0"

With more lines below it. The second line is the one I'm interested in. It has the format:

DRV:index,visible,enabled,flags,drive name,disc name

This table shows what their text file says the fields mean.

Field Description
DRV This is a drive
index The number we'll use to refer to the drive
visible 1 if drive is present
enabled 1 if drive is accessible
flags media flags (see AP_DskFsFlagXXX in apdefs.h)
drive name drive name string
disc name disc name string

Looking at the sample output, it has 2 for "visible" and 999 for "enabled", which doesn't match the expected values so I just ignore everything but the drive name to find the right entry in the output and the index for use in invoking makemkvcon.

Copy Disc As MKV Files

- Save disk to the current directory as MKV files

`makemkvcon mkv disc:{{index}} all .`

- Save disk to another directory as MKV files

`makemkvcon mkv disc:{{index}} all {{/absolute-path-to-folder/}}`

The sample shows the output being copied to c:\folder which is a DOS format (I think). It didn't seem to work when I used a relative path (other than the current directory) so I assume you need to use the full path starting from /home/.

Function: To Avif

This converts files passed in as arguments to the avif format. It requires avifenc to be installed. In Ubuntu you can install it with

sudo apt install libavif-bin

To AVIF

function toavif --description 'Convert image files to avif with avifenc'

    for SOURCE_IMAGE in $argv
        set OUTPUT (path change-extension avif $SOURCE_IMAGE)
        avifenc $SOURCE_IMAGE -o $OUTPUT
    end
end

Function: Host Grep

The Function

This is a function to check what we have set-up as a hostname for the times that I forget an IP address for a device on the LAN. It checks the hosts file and the ssh-config. The hosts file has the IP address, but sometimes I can't remember the host-name, just the user-name, in which case checking the SSH config file can sometimes be helpful.

function hostgrep --argument-names HOST --description "Look for a hostname."

The Parts

Check Hosts

First check the /etc/hosts file.

grep $HOST /etc/hosts

Check SSH

Now Check the ssh configuration.

grep --after-context 3 $HOST $HOME/.ssh/config

To Webp Functions

Table of Contents

To Webp

A simple for loop to make using globs easier with cwebp.

function towebp -d "Convert image files to web with cweb"

    for SOURCE_IMAGE in $argv
        set OUTPUT (path change-extension webp $SOURCE_IMAGE)
        cwebp $SOURCE_IMAGE -o $OUTPUT
    end
end

I'm pretty sure I saw a one-liner to do this (using pipes) but it was hard to understand so I thought this would make it clearer to myself what is going on, rather than just copying a command I can't figure out.

Lossless Webp

The previous function used the default compression (lossy). This uses the lossless conversion with maximum compression and quality.

I looked in the source code (from Google's libwebp git repository) and the -z flag is equivalent to using -lossless -m 6 -q 10 (or whatever the max is for both of them), although for some reason it seemed to do better when I was testing it earlier…

function losslesswebp --description 'Convert image files to lossless webp'

    for SOURCE_IMAGE in $argv
        set OUTPUT (path change-extension .z9.webp $SOURCE_IMAGE)
        cwebp -z 9 $SOURCE_IMAGE -o $OUTPUT
    end
end

Abbreviations: Mother Ship

Table of Contents

This tangle is for extra configurations that are meant for PCs with a GUI that a user interacts with directly (as opposed to a server) and it has stuff that aren't going to be used on servers.

I'm putting it in dingehaufen/conf.d/ so it should be linked to in .config/fish/conf.d/ for PCs that need it.

Mount Drives

This is an abbreviation that mounts both the cryfs folders and the external (LUKs) drive.

abbr --add -- md "mountcryfs; mount-data"