Tag: zsh

  • Get OctoPrint Status via Bash

    Get OctoPrint Status via Bash

    I’m working on a module to add OctoPrint status to my zsh prompt, which I’ll probably write about in the future as a bigger post about my prompt customizations.

    To start with that though, I need to play around with accessing the API via curl.

    So here’s my super alpha version that will request the current status via HTTP and output it:

    #!/bin/bash
    
    OCTOPRINT_API="hunter2"
    BASE_URL="http://octoprint.example.com"
    JOB_ENDPOINT="${BASE_URL}/api/job"
    CURL_TIMEOUT="0.5"
    
    # Fetch the JSON from OctoPrint
    response="$(curl --max-time ${CURL_TIMEOUT} --silent --fail \
      --header "X-Api-Key: ${OCTOPRINT_API}" \
      "${JOB_ENDPOINT}")"
    
    # Extract fields with jq
    file_name=$(jq -r '.job.file.display' <<< "$response")
    completion=$(jq -r '.progress.completion' <<< "$response")
    state=$(jq -r '.state' <<< "$response")
    time_elapsed=$(jq -r '.progress.printTime' <<< "$response")
    time_left=$(jq -r '.progress.printTimeLeft' <<< "$response")
    
    # Round the completion percentage to two decimals
    completion_str=$(printf "%.2f" "$completion")
    
    # Convert seconds to H:MM:SS
    function fmt_time() {
      local total_seconds="$1"
      local hours=$((total_seconds / 3600))
      local minutes=$(((total_seconds % 3600) / 60))
      local seconds=$((total_seconds % 60))
      printf "%02d:%02d:%02d" "$hours" "$minutes" "$seconds"
    }
    
    # Convert the times
    time_elapsed_str=$(fmt_time "$time_elapsed")
    time_left_str=$(fmt_time "$time_left")
    
    # Print a readable summary
    echo "File: ${file_name}"
    echo "State: ${state}"
    echo "Completion: ${completion_str}%"
    echo "Time Elapsed: ${time_elapsed_str}"
    echo "Time Left: ${time_left_str}"
    Code language: Bash (bash)

    Do with this what you will.

  • Quick Tip: Add Screen Name to Bash Prompt

    Quick Tip: Add Screen Name to Bash Prompt

    I often SSH into servers to get some work done, and one of the things I discovered recently is that I may not always know or remember if I’m in a screen session.

    So I had the bright idea to just add it to my shell prompt!

    Simply just add one of these to your RC file of choice:

    Bash

    # Add Screen name to PS1 if we're in a screen.
    if [ -n "$STY" ]; then
    	PS1="\[\e[1m\](Screen: $STY)\[\e[0m\]\n$PS1"
    fiCode language: PHP (php)

    ZSH

    # Add Screen name to PROMPT if we're in a screen.
    if [[ -n "$STY" ]]; then
    	PROMPT="%B(Screen: $STY)%b"$'\n'"$PROMPT"
    fiCode language: PHP (php)

    And remember, if you’re asking yourself if you should run something in a screen, you’re already too late!

  • Macbook Battery Stats in Your ZSH Terminal Prompt

    Macbook Battery Stats in Your ZSH Terminal Prompt

    As a power user of my Macbook, I’ve found that I often overlook the small battery icon on my menu bar, especially when I’m immersed in a fun project. This minor inconvenience sparked a thought: why not incorporate the battery status directly into my terminal prompt? Thus, I embarked on a fun exploration into ZSH scripting. With a bit of coding magic, I was able to enhance my terminal prompt to dynamically display my Macbook’s battery percentage. Let me guide you through the process.

    We start by loading the ZSH hook module. This module allows us to add functions that run before and/or after each command, giving us the ability to update our battery status prompt in real-time.

    autoload -U add-zsh-hookCode language: Bash (bash)

    The Battery Status Function

    Next, I crafted a function, terminal_battery_stats, that retrieves battery information and displays it in the terminal prompt. Here’s how it works:

    function terminal_battery_stats {
        # Retrieve battery statistics using the pmset command. This is a macOS
        # command that allows power management and battery status retrieval.
        # The awk command is used to format the output into a useful string.
        bat_info=$(pmset -g batt | awk 'NR==2 {gsub(/;/,""); print $3 " " $4}')
        
        # Extract the battery percentage and state from the bat_info string.
        bat_percent=$(echo $bat_info | cut -d' ' -f1 | tr -d '%')
        bat_state=$(echo $bat_info | cut -d' ' -f2)
    
        # Check if the battery is charging or on AC power.
        if [ $bat_state = 'charging' ] || [ $bat_state = 'AC' ] || [ $bat_state = 'charged' ] || [ $bat_state = 'finishing' ]; then
            # If the battery is over 66%, don't display a battery prompt.
            if [ $bat_percent -gt 66 ]; then
                bat_prompt=""
            else
                # Otherwise, set the battery icon to a plug, and the color to green.
                bat_icon='🔌'
                bat_color='%F{green}'
                # Format the prompt with the battery color, percentage, and icon.
                bat_prompt="〔$bat_color$bat_percent%% $bat_icon%f〕"
            fi
        else
            # If the battery is discharging, choose a battery icon and color based on the battery level.
            if [ $bat_percent -le 33 ]; then
                bat_icon='🪫'
                bat_color='%F{red}'
            elif [ $bat_percent -gt 66 ]; then
                bat_icon='🔋'
                bat_color='%F{green}'
            else
                bat_icon='🔋'
                bat_color='%F{yellow}'
            fi
            # Format the prompt with the battery color, percentage, and icon.
            bat_prompt="〔$bat_color$bat_percent%% $bat_icon%f〕"
        fi
    
        # Check if the current prompt already contains a battery status.
        if [[ "$PROMPT" == *"〔"* ]]; then
            # If it does, remove the existing battery status from the prompt.
            PROMPT=${PROMPT#*"〕"}
        fi
    
        # Add the new battery status to the prompt.
        PROMPT="${bat_prompt}${PROMPT}"
    }Code language: Bash (bash)

    To get some basic understanding of the magic behind ZSH scripting and manipulating the terminal prompt, check this helpful resource.

    Applying the Battery Status Function

    After creating the function, I added terminal_battery_stats to the command prompt via ZSH’s pre-command hook. Now, my function runs before each command entered in the terminal, keeping the battery stats up-to-date.

    add-zsh-hook precmd terminal_battery_statsCode language: Bash (bash)

    All the above code is added to my ~/.zshrc file, turning my terminal prompt into a dynamic display of my Macbook’s battery status. The resulting terminal prompt looks like this:

    Conclusion

    Through the power of ZSH scripting magic, my terminal now offers real-time updates of my Macbook’s battery status after every command. I set it to disappear once the battery reaches 67%, a level I consider to be within the safe zone. This is an excellent example of how minor inconveniences can lead to innovative solutions that enhance productivity.

    Here’s the full script ready to drop in to your own ~/.zshrc file:


    # Load the zsh hook module. This is a module that allows adding functions
    # that get run before and/or after each command.
    autoload -U add-zsh-hook
    
    # Function to retrieve and display battery statistics in the terminal prompt.
    # Uses the pmset command to retrieve battery information, and awk to format
    # it into a useful string. Depending on the battery's state and level, 
    # different icons and colors will be displayed in the terminal prompt.
    # 
    # @return void
    function terminal_battery_stats {
        # Retrieve battery statistics using the pmset command. This is a macOS
        # command that allows power management and battery status retrieval.
        # The awk command is used to format the output into a useful string.
        bat_info=$(pmset -g batt | awk 'NR==2 {gsub(/;/,""); print $3 " " $4}')
        
        # Extract the battery percentage and state from the bat_info string.
        bat_percent=$(echo $bat_info | cut -d' ' -f1 | tr -d '%')
        bat_state=$(echo $bat_info | cut -d' ' -f2)
    
        # Check if the battery is charging or on AC power.
        if [ $bat_state = 'charging' ] || [ $bat_state = 'AC' ] || [ $bat_state = 'charged' ] || [ $bat_state = 'finishing' ]; then
            # If the battery is over 66%, don't display a battery prompt.
            if [ $bat_percent -gt 66 ]; then
                bat_prompt=""
            else
                # Otherwise, set the battery icon to a plug, and the color to green.
                bat_icon='🔌'
                bat_color='%F{green}'
                # Format the prompt with the battery color, percentage, and icon.
                bat_prompt="〔$bat_color$bat_percent%% $bat_icon%f〕"
            fi
        else
            # If the battery is discharging, choose a battery icon and color based on the battery level.
            if [ $bat_percent -le 33 ]; then
                bat_icon='🪫'
                bat_color='%F{red}'
            elif [ $bat_percent -gt 66 ]; then
                bat_icon='🔋'
                bat_color='%F{green}'
            else
                bat_icon='🔋'
                bat_color='%F{yellow}'
            fi
            # Format the prompt with the battery color, percentage, and icon.
            bat_prompt="〔$bat_color$bat_percent%% $bat_icon%f〕"
        fi
    
        # Check if the current prompt already contains a battery status.
        if [[ "$PROMPT" == *"〔"* ]]; then
            # If it does, remove the existing battery status from the prompt.
            PROMPT=${PROMPT#*"〕"}
        fi
    
        # Add the new battery status to the prompt.
        PROMPT="${bat_prompt}${PROMPT}"
    }
    
    # Adds the function terminal_battery_stats to the command prompt 
    # meaning it will be run before each command entered in the terminal. 
    add-zsh-hook precmd terminal_battery_stats
    
    Code language: Bash (bash)

    Good luck!

  • Command Timing in ZSH

    Command Timing in ZSH

    I’ve had a few snippets in my .zshrc file for a while now that will output how long a command takes to process.

    First off, I’d like to say that I did not come up with this idea, and I didn’t really write the code. I’ve snipped it from somewhere and modified it over time, so I am very sorry to the original author for not being able to give full credit. I didn’t save where I got it from–so if anyone comes across this in the future and might know where the idea came from, drop it in the comments.

    Now, on to the fun:

    The original script only went down to the second, but I wanted more granularity than that, so I went down to the millisecond.

    You’ll likely need to install gdate (brew install gdate) for this to work properly.

    The code (added to ~/.zshrc):

    function preexec() {
    	timer=$(($(gdate +%s%0N)/1000000))
    }
    
    function precmd() {
    	if [ "$timer" ]; then
    		now=$(($(gdate +%s%0N)/1000000))
    		elapsed=$now-$timer
    
    		reset_color=$'\e[00m'
    		RPROMPT="%F{cyan} $(converts "$elapsed") %{$reset_color%}"
    		export RPROMPT
    		unset timer
    	fi
    }
    
    converts() {
    	local t=$1
    
    	local d=$((t/1000/60/60/24))
    	local h=$((t/1000/60/60%24))
    	local m=$((t/100/60%60))
    	local s=$((t/1000%60))
    	local ms=$((t%1000))
    
    	if [[ $d -gt 0 ]]; then
    			echo -n " ${d}d"
    	fi
    	if [[ $h -gt 0 ]]; then
    			echo -n " ${h}h"
    	fi
    	if [[ $m -gt 0 ]]; then
    			echo -n " ${m}m"
    	fi
    	if [[ $s -gt 0 ]]; then
    		echo -n " ${s}s"
    	fi
    	if [[ $ms -gt 0 ]]; then
    		echo -n " ${ms}ms"
    	fi
    	echo
    }Code language: PHP (php)