shell functions

For rebase

Often I find the need to squash commits, especially those that don’t need to stand-alone. And so little a function, which is more an alias with arguments, is used for the job, so I don’t have to think. The git command I use for this in, say, master branch, looks like this:

git rebase -i origin/master~4 master

The -i switch makes it interactive, and in the (below) list it produces, I can mark lines selectively from pick to squash for items to be squashed, followed by :wq.1 If there are multiples marked up in the list, then git produces parent commits with an option to edit commit message(s) should you want to, and you can follow it up with :wq. Here’s an example of the list, in which, one can markup the first column as required.

pick fa77b22 # m:homepage updates
pick 04863ce # link titles update
squash c8fb9a8 # m:edit

# Rebase 69a0567..c8fb9a8 onto 69a0567 (3 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
...

I follow it up with a forced push like so — for sending it upstream. It’s only if the remote already has commits you’re trying to squash.

git push -u origin +master

fish shell

The rebase command feels a little tedious to type out at the prompt, and so this function (placed in ~/.config/fish/config.fish) helps me do the job quickly by running the command gr 4 master, which translates to the first command above:

function gr --description "Rebase e.g. gr 4 master"
    git rebase -i origin/$argv[2]~$argv[1] $argv[2]
end

Using two arguments for the freedom to define the number of commits, and the other being able to choose the branch.

For the push, I could write a function to run gpp master like so:

function gpp --description "Rebased push e.g. gpp master"
    git push -u origin +$argv[1]
end

bash shell

Of course, I have machines where bash is still the default. For those, the function (placed in, e.g., ~/.bashrc) becomes:

# bash function for rebase, e.g., gr 4 master
gr() {
    git rebase -i origin/"${2}~${1}" "$2"
}

And for the push in bash, the function would be:

# bash function for the push post rebase, e.g., gpp master
gpp() {
    git push -u origin +"$1"
}

Pulling from a force-pushed remote repository, say, origin/master needs some care. The right way is as follows:

git fetch origin
git reset --hard origin/master

Fish functions

This is a placeholder for my commonly used fish shell functions — saved as files under ~/.config/fish/functions/.

  1. For system information: sbcinf.fish

     function sbcinf --description "Print SBC vitals"
         set -l mem (free -h | awk '/Mem:/ {print $3 "/" $2}')
         set -l dsk (df -h | awk '/\/$/ {print $3 "/" $2}')
         set -l tem (vcgencmd measure_temp | grep -o -E '[[:digit:]].*')
         set -l pow (vcgencmd measure_volts | sed 's/volt=//g')
         set -l ipa (hostname -I | awk '{print $1}')
         set -l upt (uptime -p | sed 's/^up //')
    
         echo "Board temp: $tem"
         echo "Disk usage: $dsk"
         echo "IP address: $ipa"
         echo "Memory use: $mem"
         echo "Power cons: $pow"
         echo "Sys uptime: $upt"
     end
    
  2. For downloading a file from GitHub repo. with ghdl user/repo/file.ext. If specific about a branch, then this works too: ghdl user/repo@master/file.ext

     function ghdl --description "Download a file from repo e.g. ghdl user/repo/file.ext"
         if test (count $argv) -ne 1
             echo "Usage: ghdl user/repo[@branch]/path/to/file"
             return 1
         end
    
         set input $argv[1]
    
         # Split the input into repo and path
         set repo_part (echo $input | cut -d'/' -f1-2)
         set path_part (echo $input | cut -d'/' -f3-)
    
         # Extract user and repo (and optional branch)
         set user (echo $repo_part | cut -d'/' -f1)
         set repo_branch (echo $repo_part | cut -d'/' -f2)
    
         if string match -q '*@*' $repo_branch
             set repo (echo $repo_branch | cut -d'@' -f1)
             set branch (echo $repo_branch | cut -d'@' -f2)
         else
             set repo $repo_branch
             set branch "master"  # default fallback branch
         end
    
         if test -z "$user" -o -z "$repo" -o -z "$path_part"
             echo "Error: Must be in the form user/repo[@branch]/path/to/file"
             return 1
         end
    
         # Construct modern raw.githubusercontent.com URL
         set url "https://raw.githubusercontent.com/$user/$repo/refs/heads/$branch/$path_part"
    
         echo "Downloading from: $url"
         curl -LO $url
     end
    
  3. Push functions

     function gp --description "Push to remote e.g. gp master"
         git push -u origin $argv[1]
     end
     function gpp --description "Rebase push to remote e.g. gpp bb"
         git push -u origin +$argv[1]
     end
    
  4. Rebase function

     function gr --description "Rebase e.g. gr 4 master"
         git rebase -i origin/$argv[2]~$argv[1] $argv[2]
     end
    
  5. Get the latest release version of a GitHub repo.

     function glr --description 'Get latest release of a repo e.g. glr "ckunte/tce"' \
         --argument-names user_repo
         curl \
             --silent \
             "https://api.github.com/repos/$user_repo/releases/latest" \
         | string match --regex '"tag_name": "\K.*?(?=")'
     end
    
  6. Check file hash

     function check_hashes
         # Ensure the user provided a file argument
         if test (count $argv) -ne 1
             echo "Usage: check_hashes <file>"
             return 1
         end
         # Store the file path
         set file $argv[1]
         # Check if the file exists
         if not test -e $file
             echo "Error: File '$file' does not exist."
             return 1
         end
         echo "RMD160 hash:"
         printf "%s" "$file" | openssl dgst -rmd160
         echo "SHA256 hash:"
         printf "%s" "$file" | openssl dgst -sha256
     end
    
  7. Rename photos

     function renfoto --description "Rename photos e.g. renfoto ST-159"
         set prefix $argv[1]
         rename -N ...01 -X -e '$_ = $prefix . "-photo-$N"' *.png
     end
    
  8. Rename, compress and move screenshots

    This script assumes that the first two screenshots are location related, and the rest are photos.

     function renshots --argument ID
         # Check if ID was provided (e.g. renshots MCS-STRU-400)
         if test -z "$ID"
             echo "Usage: rename_shots <ID>"
             return 1
         end
    
         set -l COUNT 1
    
         # Glob everything starting with "Screenshot"
         for file in Screenshot*.png
             
             # Safety check if no files match
             if not test -e "$file"
                 echo "No files starting with 'Screenshot' found in this directory."
                 return 1
             end
    
             if test $COUNT -eq 1
                 set new_name "$ID-loc1.png"
             else if test $COUNT -eq 2
                 set new_name "$ID-loc2.png"
             else
                 set photo_num (math $COUNT - 2)
                 set new_name "$ID-photo-$photo_num.png"
             end
    
             mv "$file" "$new_name"
             printf "Renamed: %s -> %s \n" "$file" "$new_name"
             
             set COUNT (math $COUNT + 1)
         end
         # Compress images using house-keeping script
         make --file=~/scripts/hkp/hkp.make cpng
         #  Move screenshots to jt/img folder
         printf "Moving screenshots from compressed folder to jimg folder..."
         mv -f compressed/* .
         mv -f *.png ./jimg/.
         printf " done\n"
     end
    
  9. Toggle WiFi on/off using the custom command beam:

     function beam --description "Toggles Wi-Fi on/off"
         set wifi_status (nmcli radio wifi)
    
         if test "$wifi_status" = "enabled"
             printf "Turning Wi-Fi OFF... "
             nmcli radio wifi off
             printf "done.\n"
         else
             printf "Turning Wi-Fi ON... "
             nmcli radio wifi on
             printf "done.\n"
         end
     end
    
  10. Toggle ethernet on/off using the custom command lan:

     function lan --description "Toggles Ethernet (eth0) on/off"
         # Get the current state of eth0
         set eth_status (nmcli -t -f DEVICE,STATE device | grep "^eth0:" | cut -d: -f2)
    
         if test "$eth_status" = "connected"
             nmcli device disconnect eth0
         else
             nmcli device connect eth0
         end
     end
    
  1. Write and quit in Vim, which is my default git commit editor.