pfetch/pfetch

882 lines
25 KiB
Plaintext
Raw Normal View History

2019-09-24 09:33:23 +02:00
#!/bin/sh
#
# pfetch - Simple POSIX sh fetch script.
log() {
2019-09-24 11:47:47 +02:00
# 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]).
#
2019-09-24 17:30:44 +02:00
# When 'log()' has executed, the cursor is then located at marker $[4].
2019-09-24 11:47:47 +02:00
# 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.
#
2019-09-24 17:32:27 +02:00
# However, if the information printed is "taller" (takes up more lines)
# than the ascii art, the cursor isn't moved at all!
#
2019-09-24 11:47:47 +02:00
# Once the cursor is at marker $[6], the script exits. This is the gist
# of how this "dynamic" printing and layout works.
#
2019-09-24 11:59:56 +02:00
# This method allows ascii art to be stored without markers for info
# and it allows for easy swapping of info order and amount.
2019-09-24 11:47:47 +02:00
#
# $[2] ___ $[3] goldie@KISS
# $[4](.· | $[5] os KISS Linux
# (<> |
# / __ \
# ( / \ /|
# _/\ __)/_)
# \/-____\/
# $[1]
#
# $[6] /home/goldie $
2019-09-24 19:17:57 +02:00
# Move the cursor to the right, the width of the ascii art with an
# additional gap for text spacing.
printf '[%sC' "${ascii_width--1}"
# Print the info name and color the text.
printf '[3%s;1m%s' "${PF_COL1-4}" "$1"
# Print the info name and info data separator.
printf '%s' "$PF_SEP"
# Move the cursor backward the length of the *current* info name and
# then move it forwards the length of the *longest* info name. This
# aligns each info data line.
printf '[%sD[%sC' "${#1}" "${PF_ALIGN-$info_length}"
# Print the info data, color it and strip all leading whitespace
# from the string.
printf '[3%sm%s\n' "${PF_COL2-7}" "${2#${2%%[![:space:]]*}}"
2019-09-24 11:01:34 +02:00
# Keep track of the number of times 'log()' has been run.
2019-09-24 17:22:24 +02:00
: $((info_height+=1))
2019-09-24 09:33:23 +02:00
}
2019-09-24 10:13:40 +02:00
get_title() {
# Username is retrieved by first checking '$USER' with a fallback
# to the 'whoami' command.
2019-09-24 17:25:49 +02:00
user=${USER:-$(whoami)}
2019-09-24 10:13:40 +02:00
# Hostname is retrieved by first checking '$HOSTNAME' with a fallback
# to the 'hostname' command.
#
2019-09-24 10:25:06 +02:00
# Disable the warning about '$HOSTNAME' being undefined in POSIX sh as
2019-09-24 22:02:50 +02:00
# the intention for using it is allowing the user to overwrite the
# value on invocation.
2019-09-24 10:13:40 +02:00
# shellcheck disable=SC2039
2019-09-24 17:25:49 +02:00
host=${HOSTNAME:-${hostname:-$(hostname)}}
2019-09-25 07:45:23 +02:00
log "[3${PF_COL3:-1}m${user}${c7}@[3${PF_COL3:-1}m${host}" >&6
2019-09-24 10:13:40 +02:00
}
get_os() {
2019-09-24 15:40:41 +02:00
# This function is called twice, once to detect the distribution name
# for the purposes of picking an ascii art early and secondly to display
# the distribution name in the info output (if enabled).
#
# On first run, this function displays _nothing_, only on the second
# invocation is 'log()' called.
[ "$distro" ] && {
2019-09-25 07:45:23 +02:00
log os "$distro" >&6
2019-09-24 15:40:41 +02:00
return
}
2019-09-24 12:34:05 +02:00
case $os in
2019-09-24 15:15:35 +02:00
Linux*)
2019-09-25 07:45:23 +02:00
command -v lsb_release && distro=$(lsb_release -sd)
2019-09-25 07:26:34 +02:00
2019-09-24 14:01:41 +02:00
# Disable warning about shellcheck not being able
# to read '/etc/os-release'. This is fine.
# shellcheck source=/dev/null
2019-09-25 07:45:23 +02:00
. /etc/os-release && distro=$PRETTY_NAME
2019-09-24 20:17:25 +02:00
2019-09-24 21:43:46 +02:00
# Special cases for distributions which don't follow.
# the '/etc/os-release' "standard".
2019-09-25 07:45:23 +02:00
command -v crux && distro=$(crux)
command -v guix && distro='Guix System'
2019-09-24 09:33:23 +02:00
;;
2019-09-24 15:43:28 +02:00
2019-09-24 19:35:03 +02:00
Darwin*)
2019-09-25 08:45:22 +02:00
# Parse the SystemVersion.plist file to grab the macOS
# versions. The file is in the following format:
#
# <key>ProductVersion</key>
# <string>10.14.6</string>
#
# 'IFS' is set to '<>' to enable splitting between the
# keys and a second 'read' is used to operate on the
# next line directly after a match.
2019-09-25 08:55:37 +02:00
#
# '_' is used to nullify a field. '_ _ line _' basically
# says "populate $line with the third field's contents".
2019-09-25 08:45:22 +02:00
while IFS='<>' read -r _ _ line _; do
case $line in
# To avoid duplicating code, we use the name of
2019-09-25 08:59:07 +02:00
# the key (eg ProductVersion) as the name of the
2019-09-25 08:45:22 +02:00
# shell variable containing the value.
ProductVersion|ProductBuildVersion)
IFS='<>' read -r _ _ "${line?}" _
;;
esac
done < /System/Library/CoreServices/SystemVersion.plist
# Use the ProductVersion to determine which macOS/OS X codename
# the system has. As far as I'm aware there's no "dynamic" way
# of grabbing this information.
case ${ProductVersion?} in
10.4*) distro="Mac OS X Tiger" ;;
10.5*) distro="Mac OS X Leopard" ;;
10.6*) distro="Mac OS X Snow Leopard" ;;
10.7*) distro="Mac OS X Lion" ;;
10.8*) distro="OS X Mountain Lion" ;;
10.9*) distro="OS X Mavericks" ;;
10.10*) distro="OS X Yosemite" ;;
10.11*) distro="OS X El Capitan" ;;
10.12*) distro="macOS Sierra" ;;
10.13*) distro="macOS High Sierra" ;;
10.14*) distro="macOS Mojave" ;;
2019-09-25 08:52:31 +02:00
10.15*) distro="macOS Catalina" ;;
2019-09-25 08:45:22 +02:00
*) distro="macOS" ;;
esac
distro="$distro ${ProductVersion?} ${ProductBuildVersion?}"
2019-09-24 19:35:03 +02:00
;;
2019-09-24 15:43:28 +02:00
*)
# Catch all to ensure '$distro' is never blank.
2019-09-24 19:35:03 +02:00
# This also handles the BSDs.
2019-09-24 19:26:50 +02:00
distro="$os $kernel"
2019-09-24 15:43:28 +02:00
;;
2019-09-24 09:33:23 +02:00
esac
}
2019-09-24 09:46:56 +02:00
get_kernel() {
2019-09-24 19:26:50 +02:00
# '$kernel' is the cached output of 'uname -r'.
case $os in
2019-09-24 19:35:38 +02:00
# Don't print kernel output on BSD systems as the
2019-09-24 19:26:50 +02:00
# OS name includes it.
2019-09-24 20:05:15 +02:00
*BSD*) ;;
2019-09-24 19:26:50 +02:00
*)
2019-09-25 07:45:23 +02:00
log kernel "$kernel" >&6
2019-09-24 19:26:50 +02:00
;;
esac
2019-09-24 09:46:56 +02:00
}
2019-09-24 21:52:13 +02:00
get_shell() {
2019-09-25 07:45:23 +02:00
log shell "${SHELL##*/}" >&6
2019-09-24 21:52:13 +02:00
}
2019-09-24 12:06:41 +02:00
get_host() {
2019-09-24 12:34:05 +02:00
case $os in
2019-09-24 15:15:35 +02:00
Linux*)
2019-09-24 12:50:28 +02:00
# Despite what these files are called, version doesn't
# always contain the version nor does name always contain
# the name.
read -r name < /sys/devices/virtual/dmi/id/product_name
read -r version < /sys/devices/virtual/dmi/id/product_version
read -r model < /sys/firmware/devicetree/base/model
host="$name $version $model"
2019-09-24 12:06:41 +02:00
;;
2019-09-24 20:05:15 +02:00
Darwin*)
host=$(sysctl -n hw.model)
;;
*BSD*)
host=$(sysctl -n hw.vendor hw.product)
;;
2019-09-24 12:06:41 +02:00
esac
2019-09-25 07:45:23 +02:00
log host "$host" >&6
2019-09-24 12:06:41 +02:00
}
2019-09-24 09:46:56 +02:00
get_uptime() {
2019-09-24 09:53:49 +02:00
# Uptime works by retrieving the data in total seconds and then
# converting that data into days, hours and minutes using simple
# math.
2019-09-24 12:34:05 +02:00
case $os in
2019-09-24 15:15:35 +02:00
Linux*)
2019-09-24 09:46:56 +02:00
IFS=. read -r s _ < /proc/uptime
;;
2019-09-24 19:35:03 +02:00
2019-09-24 20:05:15 +02:00
Darwin*|*BSD*)
2019-09-24 19:56:29 +02:00
s=$(sysctl -n kern.boottime)
2019-09-24 19:35:03 +02:00
# Extract the uptime in seconds from the following output:
# [...] { sec = 1271934886, usec = 667779 } Thu Apr 22 12:14:46 2010
s=${s#*=}
s=${s%,*}
# The uptime format from 'sysctl' needs to be subtracted from
# the current time in seconds.
2019-09-24 19:36:15 +02:00
s=$(($(date +%s) - s))
2019-09-24 19:35:03 +02:00
;;
2019-09-24 09:46:56 +02:00
esac
2019-09-24 09:53:49 +02:00
# Convert the uptime from seconds into days, hours and minutes.
2019-09-24 09:46:56 +02:00
d=$((s / 60 / 60 / 24))
h=$((s / 60 / 60 % 24))
m=$((s / 60 % 60))
2019-09-24 09:53:49 +02:00
# Only append days, hours and minutes if they're non-zero.
2019-09-24 09:46:56 +02:00
[ "$d" = 0 ] || uptime="${uptime}${d}d "
[ "$h" = 0 ] || uptime="${uptime}${h}h "
[ "$m" = 0 ] || uptime="${uptime}${m}m "
2019-09-25 07:45:23 +02:00
log uptime "${uptime:-0m}" >&6
2019-09-24 09:46:56 +02:00
}
2019-09-24 13:41:20 +02:00
get_pkgs() {
# This works by first checking for which package managers are
# isntalled and finally by printing each package manager's
# package list with each package one per line.
#
# The output from this is then piped to 'wc -l' to count each
# line, giving us the total package count of whatever package
# managers are installed.
2019-09-25 07:53:47 +02:00
#
# Backticks are *required* here as '/bin/sh' on macOS is
# 'bash 3.2' and it can't handle the following:
#
# var=$(
# code here
# )
#
# shellcheck disable=2006
packages=`
2019-09-24 12:34:05 +02:00
case $os in
2019-09-24 15:15:35 +02:00
Linux*)
# Commands which print packages one per line.
2019-09-25 07:45:23 +02:00
command -v kiss && kiss l
command -v bonsai && bonsai list
command -v pacman-key && pacman -Qq
command -v dpkg && dpkg-query -f '.\n' -W
command -v rpm && rpm -qa
command -v xbps-query && xbps-query -l
command -v apk && apk info
# Directories containing packages.
2019-09-25 07:45:23 +02:00
command -v brew && printf '%s\n' "$(brew --cellar)/"*
command -v emerge && printf '%s\n' /var/db/pkg/*/*/
2019-09-24 21:43:46 +02:00
# GUIX requires two commands.
2019-09-25 09:11:58 +02:00
command -v guix && {
2019-09-25 07:45:23 +02:00
guix package -p /run/current-system/profile -I
guix package -I
}
;;
2019-09-24 19:40:28 +02:00
Darwin*)
# Commands which print packages one per line.
2019-09-25 07:45:23 +02:00
command -v pkgin && pkgin list
command -v port && port installed
2019-09-24 19:40:28 +02:00
# Directories containing packages.
2019-09-25 07:45:23 +02:00
command -v brew && printf '%s\n' /usr/local/Cellar/*
2019-09-24 19:40:28 +02:00
;;
2019-09-24 19:45:58 +02:00
2019-09-24 20:08:33 +02:00
FreeBSD*)
2019-09-24 19:45:58 +02:00
# Commands which print packages one per line.
2019-09-25 07:45:23 +02:00
command -v pkg && pkg info
2019-09-24 19:45:58 +02:00
;;
2019-09-24 20:05:15 +02:00
*BSD*)
2019-09-24 19:45:58 +02:00
# Commands which print packages one per line.
2019-09-25 07:45:23 +02:00
command -v pkginfo && pkginfo -i
command -v pkg && pkg list
command -v pkg_info && pkg_info
2019-09-24 19:45:58 +02:00
;;
esac | wc -l
2019-09-25 07:53:47 +02:00
`
2019-09-24 12:06:41 +02:00
2019-09-25 07:45:23 +02:00
log pkgs "$packages" >&6
2019-09-24 12:06:41 +02:00
}
2019-09-24 10:03:33 +02:00
get_memory() {
2019-09-24 12:34:05 +02:00
case $os in
2019-09-24 10:03:33 +02:00
# Used memory is calculated using the following "formula" (Linux):
# MemUsed = MemTotal + Shmem - MemFree - Buffers - Cached - SReclaimable
# Source: https://github.com/KittyKatt/screenFetch/issues/386
2019-09-24 15:15:35 +02:00
Linux*)
2019-09-24 10:03:33 +02:00
# 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))
2019-09-24 19:46:50 +02:00
mem_full=$val
2019-09-24 10:03:33 +02:00
;;
Shmem)
mem_used=$((mem_used + val))
;;
MemFree|Buffers|Cached|SReclaimable)
mem_used=$((mem_used - val))
;;
esac
done < /proc/meminfo
mem_used=$((mem_used / 1024))
2019-09-24 19:46:50 +02:00
mem_full=$((mem_full / 1024))
2019-09-24 10:03:33 +02:00
;;
2019-09-24 19:56:29 +02:00
2019-09-25 07:07:42 +02:00
# Used memory is calculated using the following "formula" (MacOS):
# wired + active + occupied * 4 / 1024
2019-09-24 19:56:29 +02:00
Darwin*)
mem_full=$(($(sysctl -n hw.memsize) / 1024 / 1024))
2019-09-25 07:07:42 +02:00
# Parse the 'vmstat' file splitting on ':' and '.'.
# The format of the file is 'key: 000.' and an additional
# split is used on '.' to filter it out.
while IFS=:. read -r key val; do
case $key in
*wired*|*active*|*occupied*)
mem_used=$((mem_used + ${val:-0}))
;;
esac
# Using '<<-EOF' is the only way to loop over a command's
2019-09-25 09:04:42 +02:00
# output without the use of a pipe ('|').
2019-09-25 07:07:42 +02:00
# This ensures that any variables defined in the while loop
# are still accessible in the script.
done <<-EOF
2019-09-25 08:00:40 +02:00
$(vm_stat)
2019-09-25 07:07:42 +02:00
EOF
mem_used=$((mem_used * 4 / 1024))
2019-09-24 19:56:29 +02:00
;;
2019-09-24 20:03:06 +02:00
OpenBSD*)
# If you run OpenBSD and can send me the full output of
# 'vm_stat' I'll be able to add full support here.
mem_full=$(($(sysctl -n hw.physmem) / 1024 / 1024))
;;
2019-09-24 20:08:33 +02:00
FreeBSD*)
# If you run FreeBSD and can help me get
2019-09-24 20:03:06 +02:00
# the used memory amount, I'll be able to add support here.
mem_full=$(($(sysctl -n hw.physmem) / 1024 / 1024))
;;
2019-09-24 10:03:33 +02:00
esac
2019-09-25 07:45:23 +02:00
log memory "${mem_used:-?}MiB / ${mem_full:-?}MiB" >&6
2019-09-24 10:03:33 +02:00
}
2019-09-24 11:01:34 +02:00
get_ascii() {
2019-09-24 17:00:47 +02:00
# This is a simple function to read the contents of
# an ascii file from 'stdin'. It allows for the use
# of '<<-EOF' to prevent the break in indentation in
# this source code.
2019-09-25 09:00:25 +02:00
#
# This function also sets the text colors according
# to the ascii color.
2019-09-24 17:00:47 +02:00
read_ascii() {
# 'PF_COL1': Set the info name color according to ascii color.
# 'PF_COL3': Set the title color to some other color. ¯\_(ツ)_/¯
2019-09-24 21:32:09 +02:00
PF_COL1=${PF_COL1:-${1:-7}}
PF_COL3=${PF_COL3:-$((${1:-7}%8+1))}
2019-09-24 17:00:47 +02:00
while IFS= read -r line; do
ascii="$ascii$line
"
done
}
# This checks for ascii art in the following order:
# '$1': Argument given to 'get_ascii()' directly.
# '$PF_ASCII': Environment variable set by user.
# '$distro': The detected distribution name.
# '$os': The name of the operating system/kernel.
#
# NOTE: Each ascii art below is indented using tabs, this
# allows indentation to continue naturally despite
# the use of '<<-EOF'.
2019-09-24 15:40:41 +02:00
case ${1:-${PF_ASCII:-${distro:-$os}}} in
[Aa]lpine*)
read_ascii 4 <<-EOF
2019-09-24 17:00:47 +02:00
${c4} /\\ /\\
/${c7}/ ${c4}\\ \\
/${c7}/ ${c4}\\ \\
/${c7}// ${c4}\\ \\
${c7}// ${c4}\\ \\
\\
EOF
2019-09-24 15:40:41 +02:00
;;
[Aa]rch*)
2019-09-24 21:14:24 +02:00
read_ascii 4 <<-EOF
2019-09-24 17:00:47 +02:00
${c6} /\\
/^^\\
/\\ \\
/${c7} __ \\
/ ( ) \\
/ __| |__\\\\
/// \\\\\\
EOF
2019-09-24 15:40:41 +02:00
;;
2019-09-24 21:14:24 +02:00
[Aa]rco*)
read_ascii 4 <<-EOF
${c4} /\\
/ \\
/ /\\ \\
/ / \\ \\
/ / \\ \\
/ / _____\\ \\
/_/ \`----.\\_\\
EOF
;;
2019-09-24 21:12:20 +02:00
[Aa]rtix*)
read_ascii 6 <<-EOF
${c4} /\\
/ \\
/\`'.,\\
/ ',
/ ,\`\\
/ ,.'\`. \\
/.,'\` \`'.\\
EOF
;;
2019-09-24 21:03:18 +02:00
[Cc]ent[Oo][Ss]*)
read_ascii 5 <<-EOF
${c2} ____${c3}^${c5}____
${c2} |\\ ${c3}|${c5} /|
${c2} | \\ ${c3}|${c5} / |
${c5}<---- ${c4}---->
${c4} | / ${c2}|${c3} \\ |
${c4} |/__${c2}|${c3}__\\|
${c2} v
EOF
;;
2019-09-24 15:40:41 +02:00
[Dd]ebian*)
read_ascii 1 <<-EOF
2019-09-24 17:00:47 +02:00
${c1} _____
/ __ \\
| / |
| \\___-
-_
--_
EOF
2019-09-24 15:40:41 +02:00
;;
2019-09-24 21:47:11 +02:00
[Ee]lementary*)
read_ascii <<-EOF
${c7} _______
/ ____ \\
/ | / /\\
|__\\ / / |
\\ /__/ /
\\_______/
EOF
;;
2019-09-24 15:40:41 +02:00
[Ff]edora*)
read_ascii 4 <<-EOF
2019-09-24 17:00:47 +02:00
${c7} _____
/ __)${c4}\\${c7}
| / ${c4}\\ \\${c7}
${c4}__${c7}_| |_${c4}_/ /${c7}
${c4}/ ${c7}(_ _)${c4}_/${c7}
${c4}/ /${c7} | |
${c4}\\ \\${c7}__/ |
${c4}\\${c7}(_____/
EOF
2019-09-24 15:40:41 +02:00
;;
[Ff]ree[Bb][Ss][Dd]*)
read_ascii 1 <<-EOF
2019-09-24 17:00:47 +02:00
${c1} /\\ _____ /\\
\\_) (_/
/ \\
| |
| |
\ /
--_____--
EOF
2019-09-24 15:40:41 +02:00
;;
[Gg]entoo*)
read_ascii 5 <<-EOF
2019-09-24 17:00:47 +02:00
${c5} _-----_
( \\
\\ 0 \\
${c7} \\ )
/ _/
( _-
\\____-
EOF
2019-09-24 15:40:41 +02:00
;;
2019-09-24 21:43:46 +02:00
[Gg]uix[Ss][Dd]*|guix*)
read_ascii 3 <<-EOF
${c3}|.__ __.|
|__ \\ / __|
\\ \\ / /
\\ \\ / /
\\ \\ / /
\\ \\/ /
\\__/
EOF
;;
2019-09-24 21:36:45 +02:00
[Hh]yperbola*)
read_ascii <<-EOF
${c7} |\`__.\`/
\____/
.--.
/ \\
/ ___ \\
/ .\` \`.\\
/.\` \`.\\
EOF
;;
2019-09-24 21:53:52 +02:00
[Ll]inux*[Ll]ite*)
read_ascii 3 <<-EOF
${c3} /\\
/ \\
/ ${c7}/ ${c3}/
> ${c7}/ ${c3}/
\\ ${c7}\\ ${c3}\\
\\_${c7}\\${c3}_\\
${c7} \\
EOF
;;
2019-09-24 20:52:01 +02:00
[Ll]inux*[Mm]int*|[Mm]int)
read_ascii 2 <<-EOF
${c2} ___________
${c2}|_ \\
${c2} | ${c7}| _____ ${c2}|
${c2} | ${c7}| | | | ${c2}|
${c2} | ${c7}| | | | ${c2}|
${c2} | ${c7}\\__${c7}___/ ${c2}|
${c2} \\_________/
EOF
;;
2019-09-24 21:18:43 +02:00
2019-09-24 15:40:41 +02:00
[Ll]inux*)
read_ascii 4 <<-EOF
2019-09-24 17:00:47 +02:00
${c4} ___
(${c7}.· ${c4}|
(${c5}<> ${c4}|
/ ${c7}__ ${c4}\\
( ${c7}/ \\ ${c4}/|
${c5}_${c4}/\\ ${c7}__)${c4}/${c5}_${c4})
${c5}\/${c4}-____${c5}\/
EOF
2019-09-24 11:01:34 +02:00
;;
2019-09-24 15:06:10 +02:00
2019-09-24 19:35:03 +02:00
[Mm]ac[Oo][Ss]*|[Dd]arwin*)
read_ascii 1 <<-EOF
2019-09-24 17:00:47 +02:00
${c1} .:'
_ :'_
${c2} .'\`_\`-'_\`\`.
:________.-'
${c3}:_______:
${c4} :_______\`-;
${c5} \`._.-._.'
EOF
2019-09-24 15:40:41 +02:00
;;
2019-09-24 21:34:28 +02:00
[Mm]ageia*)
read_ascii 2 <<-EOF
${c6} *
*
**
${c7} /\\__/\\
/ \\
\\ /
\\____/
EOF
;;
[Mm]anjaro*)
read_ascii 2 <<-EOF
${c2}||||||||| ||||
||||||||| ||||
|||| ||||
|||| |||| ||||
|||| |||| ||||
|||| |||| ||||
|||| |||| ||||
EOF
;;
2019-09-24 21:32:09 +02:00
[Mm][Xx]*)
read_ascii <<-EOF
${c7} \\\\ /
\\\\/
\\\\
/\\/ \\\\
/ \\ /\\
/ \\/ \\
/__________\\
EOF
;;
2019-09-24 21:06:14 +02:00
[Nn]et[Bb][Ss][Dd]*)
read_ascii 3 <<-EOF
${c7}\\\\${c3}\`-______,----__
${c7} \\\\ ${c3}__,---\`_
${c7} \\\\ ${c3}\`.____
${c7} \\\\${c3}-______,----\`-
${c7} \\\\
\\\\
\\\\
EOF
;;
2019-09-24 15:40:41 +02:00
[Nn]ix[Oo][Ss]*)
read_ascii 4 <<-EOF
2019-09-24 17:00:47 +02:00
${c4} \\\\ \\\\ //
==\\\\__\\\\/ //
// \\\\//
==// //==
//\\\\___//
// /\\\\ \\\\==
// \\\\ \\\\
EOF
2019-09-24 15:40:41 +02:00
;;
2019-09-24 15:15:35 +02:00
[Oo]pen[Bb][Ss][Dd]*)
read_ascii 3 <<-EOF
2019-09-24 17:00:47 +02:00
${c3} _____
\\- -/
\\_/ \\
| ${c7}O O${c3} |
|_ < ) 3 )
/ \\ /
/-_____-\\
EOF
2019-09-24 15:12:08 +02:00
;;
2019-09-25 08:50:28 +02:00
openSUSE*|open*SUSE*|SUSE*|suse*)
2019-09-24 20:58:54 +02:00
read_ascii 2 <<-EOF
${c2} _______
__| __ \\
/ .\\ \\
\\__/ |
_______|
\\_______
__________/
EOF
;;
2019-09-24 21:27:07 +02:00
[Pp]arabola*)
read_ascii 5 <<-EOF
${c5} __ __ __ _
.\`_//_//_/ / \`.
/ .\`
/ .\`
/.\`
/\`
EOF
;;
2019-09-24 21:24:57 +02:00
[Pp]op!_[Oo][Ss]*)
read_ascii 6 <<-EOF
${c6}______
\\ _ \\ __
\\ \\ \\ \\ / /
\\ \\_\\ \\ / /
\\ ___\\ /_/
\\ \\ _
__\\_\\__(_)_
(___________)
EOF
;;
2019-09-24 21:21:34 +02:00
[Pp]ure[Oo][Ss]*)
2019-09-24 21:32:09 +02:00
read_ascii <<-EOF
2019-09-24 21:21:34 +02:00
${c7} _____________
| _________ |
| | | |
| | | |
| |_________| |
|_____________|
EOF
;;
[Ss]lackware*)
read_ascii 4 <<-EOF
${c4} ________
/ ______|
| |______
\\______ \\
______| |
| |________/
|____________
EOF
;;
2019-09-24 15:40:41 +02:00
[Vv]oid*)
read_ascii 2 <<-EOF
2019-09-24 17:00:47 +02:00
${c2} _______
_ \\______ -
| \\ ___ \\ |
| | / \ | |
| | \___/ | |
| \\______ \\_|
-_______\\
EOF
2019-09-24 15:40:41 +02:00
;;
2019-09-24 15:06:10 +02:00
*)
2019-09-24 15:40:41 +02:00
# On no match of a distribution ascii art, this function calls
# itself again, this time to look for a more generic OS related
# ascii art (KISS Linux -> Linux).
[ "$1" ] || {
get_ascii "$os"
return
}
2019-09-25 07:45:23 +02:00
printf 'error: %s is not currently supported.\n' "$os" >&6
printf 'error: Open an issue for support to be added.\n' >&6
2019-09-24 15:06:10 +02:00
exit 1
;;
2019-09-24 11:01:34 +02:00
esac
2019-09-24 13:33:15 +02:00
# Store the "width" (longest line) and "height" (number of lines)
# of the ascii art for 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.
#
# Iterate over each line of the ascii art to retrieve the above
2019-09-24 17:56:03 +02:00
# information. The 'sed' is used to strip 'm' color codes from
2019-09-24 13:33:15 +02:00
# the ascii art so they don't affect the width variable.
#
# The " " acts as the padding between the ascii art and the text as
# it appends 3 spaces to the end of each line.
2019-09-24 17:20:37 +02:00
while read -r line; do
2019-09-24 13:33:15 +02:00
ascii_height=$((ascii_height + 1))
ascii_width=$((${#line} > ascii_width ? ${#line} : ascii_width))
2019-09-25 07:07:42 +02:00
# Using '<<-EOF' is the only way to loop over a command's
2019-09-25 09:04:42 +02:00
# output without the use of a pipe ('|').
2019-09-25 07:07:42 +02:00
# This ensures that any variables defined in the while loop
# are still accessible in the script.
2019-09-24 13:59:14 +02:00
done <<-EOF
$(printf %s "$ascii" | sed 's/\[3.m//g')
EOF
2019-09-24 13:33:15 +02:00
# Add a gap between the ascii art and the information.
2019-09-24 17:20:37 +02:00
: $((ascii_width+=4))
2019-09-24 11:01:34 +02:00
# Print the ascii art and position the cursor back where we
# started prior to printing it.
2019-09-24 17:56:03 +02:00
# '[?7l': Disable line-wrapping.
# '[?25l': Hide the cursor.
# '[1m': Print the ascii in bold.
# '[m': Clear bold.
2019-09-25 08:52:31 +02:00
# '[%sA': Move the cursor up '$ascii_height' amount of lines.
2019-09-25 07:45:23 +02:00
printf '[?7l[?25l%s[%sA' "$ascii" "$ascii_height" >&6
2019-09-24 11:01:34 +02:00
}
2019-09-24 09:33:23 +02:00
main() {
2019-09-24 19:17:57 +02:00
# Leave the terminal how we found it on exit or Ctrl+C.
# '[?7h': Enable line-wrapping.
# '[?25h': Un-hide the cursor.
2019-09-25 07:45:23 +02:00
trap 'printf [?7h[?25h >&6' EXIT
2019-09-24 19:17:57 +02:00
2019-09-24 11:26:34 +02:00
# Hide 'stderr' unless the first argument is '-v'. This saves
# polluting the script with '2>/dev/null'.
[ "$1" = -v ] || exec 2>/dev/null
2019-09-25 07:45:23 +02:00
# Hide 'stdout' and selectively print to it using '>&6'.
# This gives full control over what it displayed on the screen.
exec 6>&1 >/dev/null
2019-09-24 11:01:34 +02:00
# Generic color list.
# Disable warning about unused variables.
# shellcheck disable=2034
{
2019-09-24 12:27:33 +02:00
c1=''; c2=''
c3=''; c4=''
c5=''; c6=''
c7=''; c8=''
2019-09-24 11:01:34 +02:00
}
2019-09-24 09:33:23 +02:00
# Store the output of 'uname' to avoid calling it multiple times
# throughout the script. 'read <<EOF' is the simplest way of reading
# a command into a list of variables.
2019-09-24 13:59:14 +02:00
read -r os kernel <<-EOF
$(uname -sr)
EOF
2019-09-24 09:33:23 +02:00
# Always run 'get_os' for the purposes of detecting which ascii
2019-09-24 15:40:41 +02:00
# art to display.
get_os
2019-09-24 15:40:41 +02:00
2019-09-24 13:04:43 +02:00
# Allow the user to specify the order and inclusion of information
# functions through the 'PF_INFO' environment variable.
# shellcheck disable=2086
{
# Disable globbing and set the positional parameters to the
# contents of 'PF_INFO'.
set -f
set +f ${PF_INFO-ascii title os host kernel uptime pkgs memory}
2019-09-24 13:41:20 +02:00
# Iterate over the info functions to determine the lengths of the
# "info names" for output alignment. The option names and subtitles
# match 1:1 so this is thankfully simple.
for info; do
2019-09-24 14:11:55 +02:00
command -v "get_$info" >/dev/null &&
info_length=$((${#info} > info_length ? ${#info} : info_length))
2019-09-24 13:41:20 +02:00
done
2019-09-24 13:04:43 +02:00
2019-09-24 17:53:33 +02:00
# Add an additional space of length to act as a gap.
: $((info_length+=1))
2019-09-24 13:04:43 +02:00
# Iterate over the above list and run any existing "get_" functions.
2019-09-24 20:12:31 +02:00
for info; do "get_$info"; done
2019-09-24 13:04:43 +02:00
}
2019-09-24 11:01:34 +02:00
2019-09-24 12:32:06 +02:00
# Position the cursor below both the ascii art and information lines
# according to the height of both. If the information exceeds the ascii
# art in height, don't touch the cursor, else move it down N lines.
2019-09-24 19:17:57 +02:00
cursor_pos=$((info_height > ascii_height ? 0 : ascii_height - info_height))
# Print '$cursor_pos' amount of newlines. Using cursor down doesn't scroll
# the screen correctly if this causes the cursor to hit the bottom of the
# window. Using '0' gives us an extra iteration, adding a bottom line gap.
2019-09-25 07:45:23 +02:00
printf '%0.s\n' $(seq 0 "$cursor_pos") >&6
2019-09-24 09:33:23 +02:00
}
main "$@"