pfetch/pfetch

1464 lines
46 KiB
Plaintext
Raw Normal View History

2019-09-24 09:33:23 +02:00
#!/bin/sh
#
# pfetch - Simple POSIX sh fetch script.
log() {
# End here if no data was found.
[ "$2" ] || return
2019-09-25 18:05:55 +02:00
# Store the value of '$1' as we reset the argument list below.
name=$1
# Use 'set --' as a means of stripping all leading and trailing
# white-space from the info string. This also normalizes all
2019-09-28 14:56:13 +02:00
# white-space inside of the string.
2019-09-25 18:05:55 +02:00
#
# Disable the shellcheck warning for word-splitting
# as it's safe and intended ('set -f' disables globbing).
# shellcheck disable=2046,2086
{
set -f
set +f -- $2
info=$*
}
2019-11-03 01:43:07 +01:00
align=$(printf '%*.s' "$((${#name}-info_length))" "")
2019-09-24 11:01:34 +02:00
# Construct the information string.
out="[3${PF_COL1-4};1m${name}"
out="$out${PF_SEP}${align}"
2020-01-26 21:24:34 +01:00
out="$out[3${PF_COL2-7}m${info}"
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
2019-09-30 08:25:39 +02:00
# to the 'id -un' command.
user=${USER:-$(id -un)}
2019-09-24 17:25:49 +02:00
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-27 09:31:41 +02:00
hostname=${HOSTNAME:-${hostname:-$(hostname)}}
2019-09-24 17:25:49 +02:00
2019-11-03 01:43:07 +01:00
log "[3${PF_COL3:-1}m${user}${c7}@[3${PF_COL3:-1}m${hostname}" " "
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-11-03 01:43:07 +01:00
log os "$distro"
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-10-03 09:18:34 +02:00
# Some Linux distributions (which are based on others)
2019-09-27 08:07:08 +02:00
# fail to identify as they **do not** change the upstream
2020-03-07 13:41:33 +01:00
# distribution's identification packages or files.
2019-09-27 08:07:08 +02:00
#
# It is senseless to add a special case in the code for
# each and every distribution (which _is_ technically no
# different from what it is based on) as they're either too
# lazy to modify upstream's identification files or they
2019-09-27 08:31:28 +02:00
# don't have the know-how (or means) to ship their own
# lsb-release package.
2019-09-27 08:07:08 +02:00
#
# This causes users to think there's a bug in system detection
# tools like neofetch or pfetch when they technically *do*
# function correctly.
2019-09-27 08:31:28 +02:00
#
# Exceptions are made for distributions which are independent,
# not based on another distribution or follow different
# standards.
#
# This applies only to distributions which follow the standard
# by shipping unmodified identification files and packages
# from their respective upstreams.
2019-09-27 08:07:08 +02:00
if command -v lsb_release; then
distro=$(lsb_release -sd)
2019-10-03 09:18:34 +02:00
# Android detection works by checking for the existence of
# the follow two directories. I don't think there's a simpler
# method than this.
elif [ -d /system/app ] && [ -d /system/priv-app ]; then
distro="Android $(getprop ro.build.version.release)"
2019-09-27 08:07:08 +02:00
else
# This used to be a simple '. /etc/os-release' but I believe
2019-09-30 22:38:24 +02:00
# this is insecure as we blindly executed whatever was in the
# file. This parser instead simply handles 'key=val', treating
# the file contents as plain-text.
while IFS='=' read -r key val; do
case $key in
PRETTY_NAME) distro=$val ;;
esac
done < /etc/os-release
2019-09-27 08:07:08 +02:00
fi
# 'os-release' and 'lsb_release' sometimes add quotes
# around the distribution name, strip them.
distro=${distro##[\"\']}
distro=${distro%%[\"\']}
2019-09-27 08:31:28 +02:00
# Special cases for (independent) distributions which
# don't follow any os-release/lsb standards whatsoever.
2019-09-29 12:20:27 +02:00
command -v crux && distro=$(crux)
command -v guix && distro='Guix System'
2020-03-07 16:52:25 +01:00
# Check to see if we're running Bedrock Linux which is
# very unique. This simply checks to see if the user's
# PATH contais a Bedrock specific value.
case $PATH in
*/bedrock/cross/*) distro='Bedrock Linux'
esac
2019-09-28 09:30:59 +02:00
# Check to see if Linux is running in Windows 10 under
2019-09-30 23:44:22 +02:00
# WSL1 (Windows subsystem for Linux [version 1]) and
# append a string accordingly.
2019-09-28 09:30:59 +02:00
#
# If the kernel version string ends in "-Microsoft",
2019-09-30 23:44:22 +02:00
# we're very likely running under Windows 10 in WSL1.
2019-09-28 09:30:59 +02:00
[ "${kernel%%*-Microsoft}" ] ||
2019-09-30 23:44:22 +02:00
distro="$distro on Windows 10 [WSL1]"
# Check to see if Linux is running in Windows 10 under
# WSL2 (Windows subsystem for Linux [version 2]) and
# append a string accordingly.
#
2019-09-30 23:49:54 +02:00
# This checks to see if '$WSLENV' is defined. This
# appends the Windows 10 string even if '$WSLENV' is
# empty. We only need to check that is has been _exported_.
distro="${distro}${WSLENV+ on Windows 10 [WSL2]}"
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
2019-09-25 09:35:16 +02:00
# version. The file is in the following format:
2019-09-25 08:45:22 +02:00
#
# <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
2019-09-25 09:34:16 +02:00
# Match 'ProductVersion' and read the next line
# directly as it contains the key's value.
ProductVersion)
IFS='<>' read -r _ _ mac_version _
2019-09-25 09:36:56 +02:00
break
2019-09-25 08:45:22 +02:00
;;
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.
2019-09-25 09:34:16 +02:00
case $mac_version in
2019-09-25 09:38:31 +02:00
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' ;;
10.15*) distro='macOS Catalina' ;;
*) distro='macOS' ;;
2019-09-25 08:45:22 +02:00
esac
2019-09-25 09:34:16 +02:00
distro="$distro $mac_version"
2019-09-24 19:35:03 +02:00
;;
2019-09-26 09:04:15 +02:00
Haiku)
# Haiku uses 'uname -v' for version information
2019-09-28 10:51:40 +02:00
# instead of 'uname -r' which only prints '1'.
distro=$(uname -sv)
2019-09-26 09:04:15 +02:00
;;
2019-09-29 15:20:16 +02:00
Minix|DragonFly)
2019-09-28 14:00:45 +02:00
distro="$os $kernel"
2019-09-29 15:20:16 +02:00
# Minix and DragonFly don't support the escape
# sequences used, clear the exit trap.
2019-09-28 14:00:45 +02:00
trap '' EXIT
;;
2019-09-30 05:10:00 +02:00
SunOS)
2019-09-30 19:08:27 +02:00
# Grab the first line of the '/etc/release' file
# discarding everything after '('.
2019-09-30 05:10:00 +02:00
IFS='(' read -r distro _ < /etc/release
;;
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
case $os in
2019-09-26 09:04:15 +02:00
# Don't print kernel output on some systems as the
2019-09-24 19:26:50 +02:00
# OS name includes it.
2020-03-09 11:27:53 +01:00
*BSD*|Haiku|Minix|IRIX*) ;;
2019-09-24 19:26:50 +02:00
*)
2019-09-25 09:16:25 +02:00
# '$kernel' is the cached output of 'uname -r'.
2019-11-03 01:43:07 +01:00
log kernel "$kernel"
2019-09-24 19:26:50 +02:00
;;
esac
2019-09-24 09:46:56 +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
2019-09-29 15:20:16 +02:00
Darwin*|FreeBSD*|DragonFly*)
2019-09-24 20:05:15 +02:00
host=$(sysctl -n hw.model)
;;
2019-09-25 17:50:00 +02:00
NetBSD*)
2019-09-25 18:05:55 +02:00
host=$(sysctl -n machdep.dmi.system-vendor \
machdep.dmi.system-product)
2019-09-25 17:50:00 +02:00
;;
2020-03-09 07:29:35 +01:00
*BSD*|Minix)
2019-09-25 18:05:55 +02:00
host=$(sysctl -n hw.vendor hw.product)
2019-09-24 20:05:15 +02:00
;;
2019-09-24 12:06:41 +02:00
esac
2019-09-27 09:08:07 +02:00
# Turn the host string into an argument list so we can iterate
# over it and remove OEM strings and other information which
# shouldn't be displayed.
#
# Disable the shellcheck warning for word-splitting
# as it's safe and intended ('set -f' disables globbing).
# shellcheck disable=2046,2086
{
set -f
set +f -- $host
host=
}
# Iterate over the host string word by word as a means of stripping
# unwanted and OEM information from the string as a whole.
#
# This could have been implemented using a long 'sed' command with
# a list of word replacements, however I want to show that something
# like this is possible in pure sh.
#
# This string reconstruction is needed as some OEMs either leave the
# identification information as "To be filled by OEM", "Default",
# "undefined" etc and we shouldn't print this to the screen.
for word; do
# This works by reconstructing the string by excluding words
# found in the "blacklist" below. Only non-matches are appended
# to the final host string.
case $word in
To | [Bb]e | [Ff]illed | [Bb]y | O.E.M. | OEM |\
2019-09-27 09:08:07 +02:00
Not | Applicable | Specified | System | Product | Name |\
2019-10-03 11:29:31 +02:00
Version | Undefined | Default | string | INVALID | <20> | os )
2019-09-27 09:08:07 +02:00
continue
2019-09-27 09:11:56 +02:00
;;
2019-09-27 09:08:07 +02:00
esac
host="$host$word "
done
2019-09-25 18:08:22 +02:00
# '$arch' is the cached output from 'uname -m'.
2019-11-03 01:43:07 +01:00
log host "${host:-$arch}"
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-28 12:11:49 +02:00
Linux*|Minix*)
2019-09-24 09:46:56 +02:00
IFS=. read -r s _ < /proc/uptime
;;
2019-09-24 19:35:03 +02:00
2019-09-29 15:28:43 +02:00
Darwin*|*BSD*|DragonFly*)
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-26 09:04:15 +02:00
Haiku)
# The boot time is returned in microseconds, convert it to
# regular seconds.
s=$(($(system_time) / 1000000))
;;
2019-09-30 05:10:00 +02:00
SunOS)
2019-09-30 19:08:27 +02:00
# Split the output of 'kstat' on '.' and any white-space
# which exists in the command output.
#
# The output is as follows:
# unix:0:system_misc:snaptime 14809.906993005
#
# The parser extracts: ^^^^^
2019-09-30 05:10:00 +02:00
IFS=' .' read -r _ s _ <<-EOF
$(kstat -p unix:0:system_misc:snaptime)
EOF
;;
2020-03-09 11:27:53 +01:00
IRIX*)
2020-03-09 21:57:10 +01:00
# Grab the uptime in a pretty format. Usually,
# 00:00:00 from the 'ps' command.
t=$(LC_ALL=POSIX ps -o etime= -p 1)
# Split the pretty output into days or hours
# based on the uptime.
case $t in
*-*) d=${t%%-*} t=${t#*-} ;;
*:*:*) h=${t%%:*} t=${t#*:} ;;
esac
h=${h#0} t=${t#0}
# Convert the split pretty fields back into
# seconds so we may re-convert them to our format.
s=$((${d:-0}*86400 + ${h:-0}*3600 + ${t%%:*}*60 + ${t#*:}))
2020-03-09 11:27:53 +01: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-11-03 01:43:07 +01:00
log uptime "${uptime:-0m}"
2019-09-24 09:46:56 +02:00
}
2019-09-24 13:41:20 +02:00
get_pkgs() {
2019-09-28 06:25:20 +02:00
# This is just a simple wrapper around 'command -v' to avoid
# spamming '>/dev/null' throughout this function.
has() { command -v "$1" >/dev/null; }
# This works by first checking for which package managers are
2019-09-26 19:55:16 +02:00
# installed 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-28 06:25:20 +02:00
has bonsai && bonsai list
2019-10-06 11:21:59 +02:00
has crux && pkginfo -i
2019-09-28 06:25:20 +02:00
has pacman-key && pacman -Qq
has dpkg && dpkg-query -f '.\n' -W
has rpm && rpm -qa
has xbps-query && xbps-query -l
has apk && apk info
2019-09-28 11:57:23 +02:00
has guix && guix package --list-installed
2019-11-10 11:39:18 +01:00
has opkg && opkg list-installed
# Directories containing packages.
2019-09-29 11:24:18 +02:00
has kiss && printf '%s\n' /var/db/kiss/installed/*/
2019-09-28 06:25:20 +02:00
has brew && printf '%s\n' "$(brew --cellar)/"*
has emerge && printf '%s\n' /var/db/pkg/*/*/
has pkgtool && printf '%s\n' /var/log/packages/*
2019-11-18 16:56:21 +01:00
has eopkg && printf '%s\n' /var/lib/eopkg/package/*
2019-09-24 21:43:46 +02:00
2019-09-30 22:37:36 +02:00
# 'nix' requires two commands.
2019-09-28 06:25:20 +02:00
has nix-store && {
2019-09-25 09:14:46 +02:00
nix-store -q --requisites /run/current-system/sw
nix-store -q --requisites ~.nix-profile
}
;;
2019-09-24 19:40:28 +02:00
Darwin*)
# Commands which print packages one per line.
2019-09-28 06:25:20 +02:00
has pkgin && pkgin list
2019-09-24 19:40:28 +02:00
# Directories containing packages.
2019-09-28 06:25:20 +02:00
has brew && printf '%s\n' /usr/local/Cellar/*
2019-10-01 22:24:26 +02:00
# 'port' prints a single line of output to 'stdout'
# when no packages are installed and exits with
# success causing a false-positive of 1 package
# installed.
#
# 'port' should really exit with a non-zero code
# in this case to allow scripts to cleanly handle
# this behavior.
has port && {
pkg_list=$(port installed)
[ "$pkg_list" = "No ports are installed." ] ||
printf '%s\n' "$pkg_list"
}
2019-09-24 19:40:28 +02:00
;;
2019-09-24 19:45:58 +02:00
2019-09-29 15:20:16 +02:00
FreeBSD*|DragonFly*)
2019-09-25 09:29:02 +02:00
pkg info
2019-09-24 19:45:58 +02:00
;;
2019-09-25 09:29:02 +02:00
OpenBSD*)
printf '%s\n' /var/db/pkg/*/
;;
NetBSD*)
pkg_info
2019-09-24 19:45:58 +02:00
;;
2019-09-26 09:04:15 +02:00
Haiku)
printf '%s\n' /boot/system/package-links/*
;;
2019-09-28 12:11:49 +02:00
Minix)
printf '%s\n' /usr/pkg/var/db/pkg/*/
;;
2019-09-30 05:10:00 +02:00
SunOS)
2019-09-30 09:32:54 +02:00
has pkginfo && pkginfo -i
has pkg && pkg list
2019-09-30 05:10:00 +02:00
;;
2020-03-09 11:27:53 +01:00
IRIX*)
# TODO: result - 3.
versions -b
;;
esac | wc -l
2019-09-25 07:53:47 +02:00
`
2019-09-24 12:06:41 +02:00
2019-11-03 01:43:07 +01:00
[ "$packages" -gt 1 ] && log pkgs "$packages"
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-29 15:27:45 +02:00
# Used memory is calculated using the following "formula":
2019-09-24 10:03:33 +02:00
# 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'.
2019-09-28 16:18:18 +02:00
while IFS=':k ' read -r key val _; do
2019-09-24 10:03:33 +02:00
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-29 15:27:45 +02:00
# Used memory is calculated using the following "formula":
2019-09-25 09:19:37 +02:00
# (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
2019-10-03 20:06:51 +02:00
*' wired'*|*' active'*|*' occupied'*)
2019-09-25 07:07:42 +02:00
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*)
mem_full=$(($(sysctl -n hw.physmem) / 1024 / 1024))
2019-09-25 14:43:39 +02:00
# This is a really simpler parser for 'vmstat' which grabs
# the used memory amount in a lazy way. 'vmstat' prints 3
# lines of output with the needed value being stored in the
2019-09-26 20:08:30 +02:00
# final line.
2019-09-25 14:43:39 +02:00
#
# This loop simply grabs the 3rd element of each line until
# the EOF is reached. Each line overwrites the value of the
2019-09-26 20:08:30 +02:00
# previous one so we're left with what we wanted. This isn't
# slow as only 3 lines are parsed.
2019-09-25 14:43:39 +02:00
while read -r _ _ line _; do
mem_used=${line%%M}
# Using '<<-EOF' is the only way to loop over a command's
# output without the use of a pipe ('|').
# This ensures that any variables defined in the while loop
# are still accessible in the script.
done <<-EOF
$(vmstat)
EOF
2019-09-24 20:03:06 +02:00
;;
2019-09-29 15:27:45 +02:00
# Used memory is calculated using the following "formula":
# mem_full - ((inactive + free + cache) * page_size / 1024)
2019-09-29 15:20:16 +02:00
FreeBSD*|DragonFly*)
2019-09-24 20:03:06 +02:00
mem_full=$(($(sysctl -n hw.physmem) / 1024 / 1024))
2019-09-25 16:41:38 +02:00
# Use 'set --' to store the output of the command in the
# argument list. POSIX sh has no arrays but this is close enough.
#
# Disable the shellcheck warning for word-splitting
# as it's safe and intended ('set -f' disables globbing).
# shellcheck disable=2046
{
set -f
set +f -- $(sysctl -n hw.pagesize \
vm.stats.vm.v_inactive_count \
vm.stats.vm.v_free_count \
vm.stats.vm.v_cache_count)
}
2019-09-25 16:44:39 +02:00
# Calculate the amount of used memory.
2019-09-25 16:41:38 +02:00
# $1: hw.pagesize
# $2: vm.stats.vm.v_inactive_count
# $3: vm.stats.vm.v_free_count
# $4: vm.stats.vm.v_cache_count
2019-09-29 15:27:45 +02:00
mem_used=$((mem_full - (($2 + $3 + $4) * $1 / 1024 / 1024)))
2019-09-24 20:03:06 +02:00
;;
2019-09-25 09:48:38 +02:00
NetBSD*)
mem_full=$(($(sysctl -n hw.physmem64) / 1024 / 1024))
# NetBSD implements a lot of the Linux '/proc' filesystem,
# this uses the same parser as the Linux memory detection.
2019-09-29 15:59:08 +02:00
while IFS=':k ' read -r key val _; do
2019-09-25 09:48:38 +02:00
case $key in
MemFree)
mem_free=$((val / 1024))
break
;;
esac
done < /proc/meminfo
mem_used=$((mem_full - mem_free))
;;
2019-09-26 09:11:57 +02:00
Haiku)
# Read the first line of 'sysinfo -mem' splitting on
# '(', ' ', and ')'. The needed information is then
2019-09-26 09:15:49 +02:00
# stored in the 5th and 7th elements. Using '_' "consumes"
2019-09-26 09:11:57 +02:00
# an element allowing us to proceed to the next one.
#
# The parsed format is as follows:
# 3501142016 bytes free (used/max 792645632 / 4293787648)
IFS='( )' read -r _ _ _ _ mem_used _ mem_full <<-EOF
$(sysinfo -mem)
EOF
mem_used=$((mem_used / 1024 / 1024))
mem_full=$((mem_full / 1024 / 1024))
;;
2019-09-28 12:11:49 +02:00
Minix)
# Minix includes the '/proc' filesystem though the format
# differs from Linux. The '/proc/meminfo' file is only a
# single line with space separated elements and elements
# 2 and 3 contain the total and free memory numbers.
read -r _ mem_full mem_free _ < /proc/meminfo
mem_used=$(((mem_full - mem_free) / 1024))
mem_full=$(( mem_full / 1024))
;;
2019-09-30 05:10:00 +02:00
SunOS)
hw_pagesize=$(pagesize)
2019-09-30 22:16:03 +02:00
# 'kstat' outputs memory in the following format:
# unix:0:system_pages:pagestotal 1046397
# unix:0:system_pages:pagesfree 885018
#
# This simply uses the first "element" (white-space
# separated) as the key and the second element as the
# value.
#
# A variable is then assigned based on the key.
2019-09-30 09:32:54 +02:00
while read -r key val; do
case $key in
2019-09-30 19:08:27 +02:00
*total) pages_full=$val ;;
2019-09-30 09:32:54 +02:00
*free) pages_free=$val ;;
esac
2019-09-30 05:10:00 +02:00
done <<-EOF
$(kstat -p unix:0:system_pages:pagestotal \
unix:0:system_pages:pagesfree)
EOF
2019-09-30 19:08:27 +02:00
mem_full=$((pages_full * hw_pagesize / 1024 / 1024))
2019-09-30 05:10:00 +02:00
mem_free=$((pages_free * hw_pagesize / 1024 / 1024))
mem_used=$((mem_full - mem_free))
;;
2020-03-09 11:27:53 +01:00
IRIX*)
2020-03-09 21:48:23 +01:00
# Read the memory information from the 'top' command. Parse
# and split each line until we reach the line starting with
# "Memory".
#
# Example output: Memory: 160M max, 147M avail, .....
while IFS=' :' read -r label mem_full _ mem_free _; do
case $label in
Memory)
mem_full=${mem_full%M}
mem_free=${mem_free%M}
break
;;
esac
done <<-EOF
$(top -n)
EOF
mem_used=$((mem_full - mem_free))
2020-03-09 11:27:53 +01:00
;;
2019-09-24 10:03:33 +02:00
esac
2019-11-03 01:43:07 +01:00
log memory "${mem_used:-?}M / ${mem_full:-?}M"
2019-09-24 10:03:33 +02:00
}
2019-09-30 23:18:58 +02:00
get_wm() {
case $os in
# Don't display window manager on macOS.
Darwin*) ;;
*)
# xprop can be used to grab the window manager's properties
# which contains the window manager's name under '_NET_WM_NAME'.
#
# The upside to using 'xprop' is that you don't need to hardcode
# a list of known window manager names. The downside is that
# not all window managers conform to setting the '_NET_WM_NAME'
# atom..
#
# List of window managers which fail to set the name atom:
2019-10-19 23:00:02 +02:00
# catwm, fvwm, dwm, 2bwm, monster, wmaker and sowm [mine! ;)].
2019-09-30 23:18:58 +02:00
#
# The final downside to this approach is that it does _not_
# support Wayland environments. The only solution which supports
# Wayland is the 'ps' parsing mentioned below.
#
# A more naive implementation is to parse the last line of
# '~/.xinitrc' to extract the second white-space separated
# element.
#
# The issue with an approach like this is that this line data
# does not always equate to the name of the window manager and
# could in theory be _anything_.
#
# This also fails when the user launches xorg through a display
# manager or other means.
#
#
# Another naive solution is to parse 'ps' with a hardcoded list
# of window managers to detect the current window manager (based
# on what is running).
#
# The issue with this approach is the need to hardcode and
# maintain a list of known window managers.
#
# Another issue is that process names do not always equate to
# the name of the window manager. False-positives can happen too.
#
# This is the only solution which supports Wayland based
# environments sadly. It'd be nice if some kind of standard were
# established to identify Wayland environments.
#
# pfetch's goal is to remain _simple_, if you'd like a "full"
# implementation of window manager detection use 'neofetch'.
#
# Neofetch use a combination of 'xprop' and 'ps' parsing to
# support all window managers (including non-conforming and
# Wayland) though it's a lot more complicated!
# Don't display window manager if X isn't running.
[ "$DISPLAY" ] || return
# This is a two pass call to xprop. One call to get the window
# manager's ID and another to print its properties.
command -v xprop && {
# The output of the ID command is as follows:
# _NET_SUPPORTING_WM_CHECK: window id # 0x400000
#
# To extract the ID, everything before the last space
# is removed.
id=$(xprop -root -notype _NET_SUPPORTING_WM_CHECK)
id=${id##* }
# The output of the property command is as follows:
# _NAME 8t
# _NET_WM_PID = 252
# _NET_WM_NAME = "bspwm"
# _NET_SUPPORTING_WM_CHECK: window id # 0x400000
# WM_CLASS = "wm", "Bspwm"
#
# To extract the name, everything before '_NET_WM_NAME = \"'
# is removed and everything after the next '"' is removed.
wm=$(xprop -id "$id" -notype -len 25 -f _NET_WM_NAME 8t)
2019-10-02 14:36:09 +02:00
# Handle cases of a window manager _not_ populating the
# '_NET_WM_NAME' atom. Display nothing in this case.
case $wm in
*'_NET_WM_NAME = '*)
wm=${wm##*_NET_WM_NAME = \"}
wm=${wm%%\"*}
;;
2019-10-19 23:00:02 +02:00
*)
# Fallback to checking the process list
# for the select few window managers which
# don't set '_NET_WM_NAME'.
#
# TODO: This is currently limited to 'grep'
# implementations providing the '-o'
# flag. This needs to be replaced with
# a command which searches for a list
# of strings and returns _only_ the
# first match's contents (also ensuring
# the search itself isn't matched).
#
# A generic parser isn't possible as
# the output of 'ps' is _not_ the same
# between implementations and across
# operating systems.
#
# The simple search method above works
# regardless of 'ps' implementation.
#
# Disable the shellcheck warning about using
# 'pgrep' instead of 'ps | grep' as 'pgrep'
# is not always available.
# shellcheck disable=2009
wm=$(ps x | grep -o \
-e '[c]atwm' \
-e '[f]vwm' \
-e '[d]wm' \
-e '[2]bwm' \
-e '[m]onsterwm' \
-e '[w]maker' \
-e '[s]owm')
;;
2019-10-02 14:36:09 +02:00
esac
2019-09-30 23:18:58 +02:00
}
;;
esac
2019-11-03 01:43:07 +01:00
log wm "$wm"
2019-09-30 23:18:58 +02:00
}
2019-09-30 23:00:27 +02:00
get_de() {
# This only supports Xorg related desktop environments though
# this is fine as knowing the desktop envrionment on Windows,
# macOS etc is useless (they'll always report the same value).
#
# Display the value of '$XDG_CURRENT_DESKTOP', if it's empty,
# display the value of '$DESKTOP_SESSION'.
2019-11-03 01:43:07 +01:00
log de "${XDG_CURRENT_DESKTOP:-$DESKTOP_SESSION}"
2019-09-30 23:00:27 +02:00
}
2019-09-30 22:53:25 +02:00
get_shell() {
# Display the basename of the '$SHELL' environment variable.
2019-11-03 01:43:07 +01:00
log shell "${SHELL##*/}"
2019-09-30 22:53:25 +02:00
}
get_editor() {
# Display the value of '$VISUAL', if it's empty, display the
# value of '$EDITOR'.
2019-11-03 01:43:07 +01:00
log editor "${VISUAL:-$EDITOR}"
2019-09-30 22:53:25 +02:00
}
2019-09-27 20:49:44 +02:00
get_palette() {
# Print the first 8 terminal colors. This uses the existing
# sequences to change text color with a sequence prepended
# to reverse the foreground and background colors.
#
# This allows us to save hardcoding a second set of sequences
# for background colors.
palette="$c1 $c1 $c2 $c2 $c3 $c3 $c4 $c4 $c5 $c5 $c6 $c6 "
2019-09-27 20:49:44 +02:00
# Print the palette with a new-line before and afterwards.
printf '\n' >&6
log "$palette
" " "
2019-09-27 20:49:44 +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-26 20:04:18 +02:00
# POSIX sh has no 'var+=' so 'var=${var}append' is used. What's
# interesting is that 'var+=' _is_ supported inside '$(())'
# (arithmetic) though there's no support for 'var++/var--'.
#
# There is also no $'\n' to add a "literal"(?) newline to the
# string. The simplest workaround being to break the line inside
# the string (though this has the caveat of breaking indentation).
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}\\ \\
2020-01-26 21:33:51 +01:00
${c4}\\
2019-09-24 17:00:47 +02:00
EOF
2019-09-24 15:40:41 +02:00
;;
2019-10-01 08:50:08 +02:00
[Aa]ndroid*)
read_ascii 2 <<-EOF
${c2} ;, ,;
2020-01-26 21:33:51 +01:00
${c2} ';,.-----.,;'
${c2} ,' ',
${c2} / O O \\
${c2}| |
${c2}'-----------------'
2019-10-01 08:50:08 +02:00
EOF
;;
2019-09-24 15:40:41 +02:00
[Aa]rch*)
2019-09-24 21:14:24 +02:00
read_ascii 4 <<-EOF
2020-03-07 13:48:17 +01:00
${c6} /\\
${c6} / \\
${c6} /\\ \\
${c4} / \\
${c4} / ,, \\
${c4} / | | -\\
${c4} /_-'' ''-_\\
2019-09-24 17:00:47 +02:00
EOF
2019-09-24 15:40:41 +02:00
;;
2019-09-24 21:14:24 +02:00
[Aa]rco*)
read_ascii 4 <<-EOF
${c4} /\\
2020-01-26 21:33:51 +01:00
${c4} / \\
${c4} / /\\ \\
${c4} / / \\ \\
${c4} / / \\ \\
${c4} / / _____\\ \\
${c4}/_/ \`----.\\_\\
2019-09-24 21:14:24 +02:00
EOF
;;
2019-09-24 21:12:20 +02:00
[Aa]rtix*)
read_ascii 6 <<-EOF
${c4} /\\
2020-01-26 21:33:51 +01:00
${c4} / \\
${c4} /\`'.,\\
${c4} / ',
${c4} / ,\`\\
${c4} / ,.'\`. \\
${c4}/.,'\` \`'.\\
2019-09-24 21:12:20 +02:00
EOF
;;
[Bb]edrock*)
read_ascii 4 <<-EOF
${c7}__
${c7}\\ \\___
${c7} \\ _ \\
${c7} \\___/
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} _____
2020-01-26 21:33:51 +01:00
${c1} / __ \\
${c1}| / |
${c1}| \\___-
${c1}-_
${c1} --_
2019-09-24 17:00:47 +02:00
EOF
2019-09-24 15:40:41 +02:00
;;
2019-09-29 15:20:16 +02:00
[Dd]ragon[Ff]ly*)
2019-09-28 15:50:49 +02:00
read_ascii 1 <<-EOF
,${c1}_${c7},
('-_${c1}|${c7}_-')
>--${c1}|${c7}--<
(_-'${c1}|${c7}'-_)
${c1}|
2020-01-26 21:33:51 +01:00
${c1}|
${c1}|
2019-09-28 15:50:49 +02:00
EOF
;;
2019-09-24 21:47:11 +02:00
[Ee]lementary*)
read_ascii <<-EOF
${c7} _______
2020-01-26 21:33:51 +01:00
${c7} / ____ \\
${c7}/ | / /\\
${c7}|__\\ / / |
${c7}\\ /__/ /
${c7}\\_______/
2019-09-24 21:47:11 +02:00
EOF
;;
2020-01-03 08:48:20 +01:00
[Ee]ndeavour*)
read_ascii 4 <<-EOF
2020-03-07 13:48:17 +01:00
${c1}/${c4}\\
${c1}/${c4}/ \\${c6}\\
${c1}/${c4}/ \\ ${c6}\\
${c1}/ ${c4}/ _) ${c6})
${c1}/_${c4}/___-- ${c6}__-
${c6}/____--
2020-01-03 08:48:20 +01:00
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-10-03 12:59:36 +02:00
${c1}/\\,-'''''-,/\\
2020-01-26 21:33:51 +01:00
${c1}\\_) (_/
${c1}| |
${c1}| |
${c1}; ;
${c1}'-_____-'
2019-09-24 17:00:47 +02:00
EOF
2019-09-24 15:40:41 +02:00
;;
[Gg]entoo*)
read_ascii 5 <<-EOF
2019-09-24 17:00:47 +02:00
${c5} _-----_
2020-01-26 21:33:51 +01:00
${c5}( \\
${c5}\\ 0 \\
2019-09-24 17:00:47 +02:00
${c7} \\ )
2020-01-26 21:33:51 +01:00
${c7} / _/
${c7}( _-
${c7}\\____-
2019-09-24 17:00:47 +02:00
EOF
2019-09-24 15:40:41 +02:00
;;
2019-10-01 14:05:42 +02:00
[Gg]uix[Ss][Dd]*|[Gg]uix*)
2019-09-24 21:43:46 +02:00
read_ascii 3 <<-EOF
${c3}|.__ __.|
2020-01-26 21:33:51 +01:00
${c3}|__ \\ / __|
${c3}\\ \\ / /
${c3}\\ \\ / /
${c3}\\ \\ / /
${c3}\\ \\/ /
${c3}\\__/
2019-09-24 21:43:46 +02:00
EOF
;;
2019-09-26 10:21:03 +02:00
[Hh]aiku*)
2019-09-26 10:21:35 +02:00
read_ascii 3 <<-EOF
2019-09-26 11:30:15 +02:00
${c3} ,^,
2020-01-26 21:38:04 +01:00
${c3} / \\
${c3}*--_ ; ; _--*
${c3}\\ '" "' /
${c3}'. .'
${c3}.-'" "'-.
${c3}'-.__. .__.-'
${c3}|_|
2019-09-26 10:21:03 +02:00
EOF
;;
2019-09-24 21:36:45 +02:00
[Hh]yperbola*)
read_ascii <<-EOF
${c7} |\`__.\`/
2020-01-26 21:38:04 +01:00
${c7} \____/
${c7} .--.
${c7} / \\
${c7} / ___ \\
${c7}/ .\` \`.\\
${c7}/.\` \`.\\
2019-09-24 21:36:45 +02:00
EOF
;;
2020-03-09 11:27:53 +01:00
[Ii]rix*)
read_ascii 4 <<-EOF
TODO
EOF
;;
2019-10-01 14:06:37 +02:00
[Ll]inux*[Ll]ite*|[Ll]ite*)
2019-09-24 21:53:52 +02:00
read_ascii 3 <<-EOF
${c3} /\\
2020-01-26 21:38:04 +01:00
${c3} / \\
${c3} / ${c7}/ ${c3}/
${c3}> ${c7}/ ${c3}/
${c3}\\ ${c7}\\ ${c3}\\
${c3}\\_${c7}\\${c3}_\\
2019-09-24 21:53:52 +02:00
${c7} \\
EOF
;;
2019-09-24 20:52:01 +02:00
[Ll]inux*[Mm]int*|[Mm]int)
read_ascii 2 <<-EOF
${c2} ___________
2020-01-26 21:38:04 +01:00
${c2}|_ \\
${c2}| ${c7}| _____ ${c2}|
${c2}| ${c7}| | | | ${c2}|
${c2}| ${c7}| | | | ${c2}|
${c2}| ${c7}\\__${c7}___/ ${c2}|
${c2}\\_________/
2019-09-24 20:52:01 +02:00
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} ___
2020-01-26 21:38:04 +01:00
${c4}(${c7}.. ${c4}|
${c4}(${c5}<> ${c4}|
${c4}/ ${c7}__ ${c4}\\
${c4}( ${c7}/ \\ ${c4}/|
2019-09-24 17:00:47 +02:00
${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} .:'
2020-01-26 21:38:04 +01:00
${c1} _ :'_
2019-09-24 17:00:47 +02:00
${c2} .'\`_\`-'_\`\`.
2020-01-26 21:38:04 +01:00
${c2}:________.-'
2019-09-24 17:00:47 +02:00
${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} *
2020-01-26 21:44:05 +01:00
${c6} *
${c6} **
2019-09-24 21:34:28 +02:00
${c7} /\\__/\\
2020-01-26 21:44:05 +01:00
${c7}/ \\
${c7}\\ /
${c7} \\____/
2019-09-24 21:34:28 +02:00
EOF
;;
[Mm]anjaro*)
read_ascii 2 <<-EOF
${c2}||||||||| ||||
2020-01-26 21:44:05 +01:00
${c2}||||||||| ||||
${c2}|||| ||||
${c2}|||| |||| ||||
${c2}|||| |||| ||||
${c2}|||| |||| ||||
${c2}|||| |||| ||||
2019-09-24 21:34:28 +02:00
EOF
;;
2019-09-28 13:31:10 +02:00
[Mm]inix*)
read_ascii 4 <<-EOF
${c4} ,, ,,
2020-01-26 21:44:05 +01:00
${c4};${c7},${c4} ', ,' ${c7},${c4};
${c4}; ${c7}',${c4} ',,' ${c7},'${c4} ;
${c4}; ${c7}',${c4} ${c7},'${c4} ;
${c4}; ${c7};, '' ,;${c4} ;
${c4}; ${c7};${c4};${c7}',,'${c4};${c7};${c4} ;
${c4}', ${c7};${c4};; ;;${c7};${c4} ,'
${c4} '${c7};${c4}' '${c7};${c4}'
2019-09-28 13:31:10 +02:00
EOF
;;
2019-09-24 21:32:09 +02:00
[Mm][Xx]*)
read_ascii <<-EOF
${c7} \\\\ /
2020-01-26 21:44:05 +01:00
${c7} \\\\/
${c7} \\\\
${c7} /\\/ \\\\
${c7} / \\ /\\
${c7} / \\/ \\
${c7}/__________\\
2019-09-24 21:32:09 +02:00
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} \\\\
2020-01-26 21:44:05 +01:00
${c7} \\\\
${c7} \\\\
2019-09-24 21:06:14 +02:00
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} \\\\ \\\\ //
2020-01-26 21:44:05 +01:00
${c4} ==\\\\__\\\\/ //
${c4} // \\\\//
${c4}==// //==
${c4} //\\\\___//
${c4}// /\\\\ \\\\==
${c4} // \\\\ \\\\
2019-09-24 17:00:47 +02:00
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} _____
2020-01-26 21:44:05 +01:00
${c3} \\- -/
${c3} \\_/ \\
${c3} | ${c7}O O${c3} |
${c3} |_ < ) 3 )
${c3} / \\ /
${c3} /-_____-\\
2019-09-24 17:00:47 +02:00
EOF
2019-09-24 15:12:08 +02:00
;;
2020-01-26 21:44:05 +01:00
[Oo]pen[Ss][Uu][Ss][Ee]*|[Oo]pen*SUSE*|SUSE*|suse*)
2019-09-24 20:58:54 +02:00
read_ascii 2 <<-EOF
${c2} _______
2020-01-26 21:44:05 +01:00
${c2}__| __ \\
${c2} / .\\ \\
${c2} \\__/ |
${c2} _______|
${c2} \\_______
${c2}__________/
2019-09-24 20:58:54 +02:00
EOF
;;
2020-01-26 21:17:23 +01:00
[Oo]pen[Ww]rt*)
read_ascii 1 <<-EOF
${c1} _______
2020-01-26 21:44:05 +01:00
${c1}| |.-----.-----.-----.
${c1}| - || _ | -__| |
${c1}|_______|| __|_____|__|__|
${c1} ________|__| __
${c1}| | | |.----.| |_
${c1}| | | || _|| _|
${c1}|________||__| |____|
2020-01-26 21:17:23 +01:00
EOF
;;
2019-09-24 21:27:07 +02:00
[Pp]arabola*)
read_ascii 5 <<-EOF
${c5} __ __ __ _
2020-01-26 21:44:05 +01:00
${c5}.\`_//_//_/ / \`.
${c5} / .\`
${c5} / .\`
${c5} /.\`
${c5} /\`
2019-09-24 21:27:07 +02:00
EOF
;;
2019-09-24 21:24:57 +02:00
[Pp]op!_[Oo][Ss]*)
read_ascii 6 <<-EOF
${c6}______
2020-01-26 21:44:05 +01:00
${c6}\\ _ \\ __
${c6}\\ \\ \\ \\ / /
${c6}\\ \\_\\ \\ / /
${c6}\\ ___\\ /_/
${c6} \\ \\ _
${c6} __\\_\\__(_)_
${c6}(___________)
2019-09-24 21:24:57 +02:00
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} _____________
2020-01-26 21:44:05 +01:00
${c7}| _________ |
${c7}| | | |
${c7}| | | |
${c7}| |_________| |
${c7}|_____________|
2019-09-24 21:21:34 +02:00
EOF
;;
[Ss]lackware*)
read_ascii 4 <<-EOF
${c4} ________
2020-01-26 21:44:05 +01:00
${c4} / ______|
${c4} | |______
${c4} \\______ \\
${c4} ______| |
${c4}| |________/
${c4}|____________
2019-09-24 21:21:34 +02:00
EOF
;;
2019-10-01 14:09:43 +02:00
[Ss]un[Oo][Ss]|[Ss]olaris*)
read_ascii 3 <<-EOF
${c3} . .; .
2020-01-26 21:44:05 +01:00
${c3} . :; :: ;: .
${c3} .;. .. .. .;.
${c3}.. .. .. ..
${c3} .;, ,;.
EOF
;;
2019-09-29 11:21:07 +02:00
[Uu]buntu*)
read_ascii 3 <<-EOF
${c3} _
2020-01-26 21:44:05 +01:00
${c3} ---(_)
${c3} _/ --- \\
${c3}(_) | |
${c3} \\ --- _/
${c3} ---(_)
2019-09-29 11:21:07 +02:00
EOF
;;
2019-09-24 15:40:41 +02:00
[Vv]oid*)
read_ascii 2 <<-EOF
2019-09-24 17:00:47 +02:00
${c2} _______
2020-01-26 21:44:05 +01:00
${c2} _ \\______ -
${c2}| \\ ___ \\ |
${c2}| | / \ | |
${c2}| | \___/ | |
${c2}| \\______ \\_|
${c2} -_______\\
2019-09-24 17:00:47 +02:00
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.
2019-09-24 17:20:37 +02:00
while read -r line; do
2019-09-28 13:49:34 +02:00
# This was a ternary operation but they aren't supported in
2019-09-28 14:00:45 +02:00
# Minix's shell.
2019-09-28 13:49:34 +02:00
[ "${#line}" -gt "${ascii_width:-0}" ] &&
ascii_width=${#line}
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
2019-10-18 20:10:15 +02:00
$(printf %s "$ascii" | sed 's/\[3.m//g')
2019-09-24 13:59:14 +02:00
EOF
2019-09-24 13:33:15 +02:00
# Add a gap between the ascii art and the information.
2019-09-28 13:41:57 +02:00
ascii_width=$((ascii_width + 4))
2019-09-24 11:01:34 +02:00
}
2019-09-24 09:33:23 +02:00
main() {
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
2020-01-26 21:08:57 +01:00
# Allow the user to execute their own script and modify or
# extend pfetch's behavior.
# shellcheck source=/dev/null
. "${PF_SOURCE:-/dev/null}" ||:
2019-10-14 08:04:15 +02:00
# Ensure that the 'TMPDIR' is writable as heredocs use it and
# fail without the write permission. This was found to be the
# case on Android where the temporary directory requires root.
[ -w "${TMPDIR:-/tmp}" ] || export TMPDIR=~
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
}
2020-01-26 21:26:35 +01:00
# Avoid text-wrapping from wrecking the program output.
#
# Some terminals don't support these sequences, nor do they
# silently conceal them if they're printed resulting in
# partial sequences being printed to the terminal!
[ "$TERM" = dumb ] ||
[ "$TERM" = minix ] ||
[ "$TERM" = cons25 ] || {
2020-01-26 21:26:35 +01:00
# Disable line-wrapping.
2020-01-26 21:24:34 +01:00
printf '[?7l' >&6
2020-01-26 21:26:35 +01:00
# Enable line-wrapping again on exit.
2020-01-26 21:24:34 +01:00
trap 'printf [?7h >&6' EXIT
}
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-25 18:08:22 +02:00
read -r os kernel arch <<-EOF
$(uname -srm)
2019-09-24 13:59:14 +02:00
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
2019-11-03 02:42:45 +01:00
# Grab the ascii art if the user has enabled it. This simply
# populates the '$ascii' variable.
2019-11-03 01:45:53 +01:00
case $@ in *ascii*) get_ascii; shift; esac
2019-11-03 01:43:07 +01:00
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-28 13:49:34 +02:00
command -v "get_$info" >/dev/null || continue
# This was a ternary operation but they aren't supported in
2019-09-28 14:00:45 +02:00
# Minix's shell.
2019-09-28 13:49:34 +02:00
[ "${#info}" -gt "${info_length:-0}" ] &&
info_length=${#info}
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.
2019-09-28 13:41:57 +02:00
info_length=$((info_length + 1))
2019-09-24 17:53:33 +02:00
2019-11-03 01:45:53 +01:00
while IFS= read -r line || [ "$1" ]; do
2019-11-03 01:43:07 +01:00
"get_$1"
shift "$(($# ? 1 : 0))"
printf '%*.s%s\r%s\n' "$ascii_width" "" "$out" "$line" >&6
out=
done <<-EOF
$ascii
EOF
2019-09-24 13:04:43 +02:00
}
2019-09-24 09:33:23 +02:00
}
main "$@"