#!/bin/sh # shellcheck source=/dev/null # # pfetch - Simple POSIX sh fetch script. log() { # The 'log()' function handles the printing of information. # In 'pfetch' (and 'neofetch'!) the printing of the ascii art and info # happen independently of each other. # # The size of the ascii art is stored and the ascii is printed first. # Once the ascii is printed, the cursor is located right below the art # (See marker $[1]). # # Using the stored ascii size, the cursor is then moved to marker $[2]. # This is simply a cursor up escape sequence using the "height" of the # ascii art. # # 'log()' then moves the cursor to the right the "width" of the ascii art # with an additional amount of padding to add a gap between the art and # the information (See marker $[3]). # # When 'log()' has executed the cursor is then located at marker $[4]. # When 'log()' is run a second time, the next line of information is # printed, moving the cursor to marker $[5]. # # Markers $[4] and $[5] repeat all the way down through the ascii art # until there is no more information left to print. # # Every time 'log()' is called the script keeps track of how many lines # were printed. When printing is complete the cursor is then manually # placed below the information and the art according to the "heights" # of both. # # The math is simple: move cursor down $((ascii_height - info_height)). # If the aim is to move the cursor from marker $[5] to marker $[6], # plus the ascii height is 8 while the info height is 2 it'd be a move # of 6 lines downwards. # # Once the cursor is at marker $[6], the script exits. This is the gist # of how this "dynamic" printing and layout works. # # This method allows ascii art to be stored without markers for info # and it allows for easy swapping of info order and amount. # # $[2] ___ $[3] goldie@KISS # $[4](.· | $[5] os KISS Linux # (<> | # / __ \ # ( / \ /| # _/\ __)/_) # \/-____\/ # $[1] # # $[6] /home/goldie $ # # PF_COL1: Control color of info name. # PF_SEP: Control the separator between info name and info data. # PF_COL2: Control color of info data. # # '\033[14C': Move cursor 14 characters to the right. # TODO: Base this on ASCII art width. # # '\033[3%s': Color formatting. # '\033[m': Reset formatting. # # '\033[%sD': Move cursor '${#1}' characters to the left. # This allows for aligned info names and data. # # '\033[6C': Move cursor 6 characters to the right. # This aligns the info. printf '\033[14C\033[3%s;1m%s\033[m%s\033[3%sm\033[%sD\033[6C%s\033[m\n' \ "${PF_COL1:-5}" "$1" "${PF_SEP:- }" "${PF_COL2:-7}" "${#1}" "${2:-?}" # Keep track of the number of times 'log()' has been run. log=$((log + 1)) } die() { printf '\033[31;1merror\033[m: %s.\n' "$@" >&2 exit 1 } get_title() { case $kernel_name in Linux*|GNU*) read -r hostname < /proc/sys/kernel/hostname ;; esac # Username is retrieved by first checking '$USER' with a fallback # to the 'whoami' command. # # Hostname is retrieved by first checking '$HOSTNAME' with a fallback # to the OS specific detection above and finally an additional fallback # to the 'hostname' command. # # PF_SEP and PF_COL{1,2} change printing options in the 'log()' function. # # Disable the warning about '$HOSTNAME' being undefined in POSIX sh as # it is intended for allowing the user to overwrite the value on invocation. # shellcheck disable=SC2039 PF_SEP=@ PF_COL1=1 PF_COL2='3;1' \ log "${USER:-$(whoami)}" "${HOSTNAME:-${hostname:-$(hostname)}}" } get_distro() { case $kernel_name in Linux*|GNU*) . /etc/os-release && distro=$PRETTY_NAME ;; esac log os "$distro" } get_kernel() { log kernel "$kernel_version" } get_uptime() { # Uptime works by retrieving the data in total seconds and then # converting that data into days, hours and minutes using simple # math. case $kernel_name in Linux*|GNU*) IFS=. read -r s _ < /proc/uptime ;; esac # Convert the uptime from seconds into days, hours and minutes. d=$((s / 60 / 60 / 24)) h=$((s / 60 / 60 % 24)) m=$((s / 60 % 60)) # Only append days, hours and minutes if they're non-zero. [ "$d" = 0 ] || uptime="${uptime}${d}d " [ "$h" = 0 ] || uptime="${uptime}${h}h " [ "$m" = 0 ] || uptime="${uptime}${m}m " log uptime "${uptime:-0m}" } get_memory() { case $kernel_name in # Used memory is calculated using the following "formula" (Linux): # MemUsed = MemTotal + Shmem - MemFree - Buffers - Cached - SReclaimable # Source: https://github.com/KittyKatt/screenFetch/issues/386 Linux*|GNU*) # Parse the '/proc/meminfo' file splitting on ':' and 'k'. # The format of the file is 'key: 000kB' and an additional # split is used on 'k' to filter out 'kB'. while IFS=:k read -r key val _; do case $key in MemTotal) mem_used=$((mem_used + val)) mem_total=$val ;; Shmem) mem_used=$((mem_used + val)) ;; MemFree|Buffers|Cached|SReclaimable) mem_used=$((mem_used - val)) ;; esac done < /proc/meminfo mem_used=$((mem_used / 1024)) mem_total=$((mem_total / 1024)) ;; esac log memory "${mem_used}MiB / ${mem_total}MiB" } get_ascii() { case $kernel_name in Linux*|GNU*) ascii="\ ${c4} ___ (${c7}.· ${c4}| (${c5}<> ${c4}| / ${c7}__ ${c4}\\ ( ${c7}/ \\ ${c4}/| ${c5}_${c4}/\\ ${c7}__)${c4}/${c5}_${c4}) ${c5}\/${c4}-____${c5}\/ " ;; esac # Store the height of the ascii art for cursor positioning. # This script prints to the screen *almost* like a TUI does. # It uses escape sequences to allow dynamic printing of the # information through user configuration. ascii_height=$(printf %s "$ascii" | wc -l) # Print the ascii art and position the cursor back where we # started prior to printing it. # '\e[?25l': Hide the cursor. # '\033[1m': Print the ascii in bold. # '\033[m': Clear bold. # '\033[%sA: Move the cursor up '$ascii_height' amount of lines. printf '\e[?25l\033[1m%s\033[m\033[%sA' "$ascii" "$ascii_height" } main() { # Hide 'stderr' unless the first argument is '-v'. This saves # polluting the script with '2>/dev/null'. [ "$1" = -v ] || exec 2>/dev/null # Generic color list. # Disable warning about unused variables. # shellcheck disable=2034 { c1=; c2= c3=; c4= c5=; c6= c7=; c8= } # Store the output of 'uname' to avoid calling it multiple times # throughout the script. 'read <