neofetch/neofetch
2016-10-21 16:26:34 +11:00

3322 lines
99 KiB
Bash
Executable file
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# set -x
# vim: fdm=marker:noai:ts=4:sw=4
#
# Neofetch info about your system
# https://github.com/dylanaraps/neofetch
#
# Created by Dylan Araps
# https://github.com/dylanaraps/
version="${BASH_VERSION/.*}"
SYS_LOCALE="${LANG:-C}"
XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-${HOME}/.config}"
# Speed up script by not using unicode
export LC_ALL=C
export LANG=C
# Set no case match.
shopt -s nocasematch
# Gather Info {{{
# Operating System {{{
getos() {
case "$(uname)" in
"Linux") os="Linux" ;;
"Darwin") os="$(sw_vers -productName)" ;;
*"BSD" | "DragonFly" | "Bitrig") os="BSD" ;;
"CYGWIN"*) os="Windows" ;;
"SunOS") os="Solaris" ;;
*) printf "%s\n" "Unknown OS detected: $(uname)"; exit 1 ;;
esac
}
# }}}
# Model {{{
getmodel() {
case "$os" in
"Linux")
if [ -f /sys/devices/virtual/dmi/id/product_name ] ||\
[ -f /sys/devices/virtual/dmi/id/product_version ]; then
model="$(cat /sys/devices/virtual/dmi/id/product_{name,version} 2>/dev/null)"
model="${model/To Be Filled*}"
elif [ -f /sys/firmware/devicetree/base/model ]; then
model="$(< /sys/firmware/devicetree/base/model)"
elif [ -f /tmp/sysinfo/model ]; then
model="$(< /tmp/sysinfo/model)"
fi
;;
"Mac OS X") model="$(sysctl -n hw.model)" ;;
"iPhone OS")
case "${ios_model:-$(uname -m)}" in
"iPad1,1") model="iPad" ;;
"iPad2,"[1-4]) model="iPad2" ;;
"iPad3,"[1-3]) model="iPad3" ;;
"iPad3,"[4-6]) model="iPad4" ;;
"iPad4,"[1-3]) model="iPad Air" ;;
"iPad5,"[3-4]) model="iPad Air 2" ;;
"iPad6,"[7-8]) model="iPad Pro (12.9 Inch)" ;;
"iPad6,"[3-4]) model="iPad Pro (9.7 Inch)" ;;
"iPad2,"[5-7]) model="iPad mini" ;;
"iPad4,"[4-6]) model="iPad mini 2" ;;
"iPad4,"[7-9]) model="iPad mini 3" ;;
"iPad5,"[1-2]) model="iPad mini 4" ;;
"iPhone1,1") model="iPhone" ;;
"iPhone1,2") model="iPhone 3G" ;;
"iPhone2,1") model="iPhone 3GS" ;;
"iPhone3,"[1-3]) model="iPhone 4" ;;
"iPhone4,1") model="iPhone 4S" ;;
"iPhone5,"[1-2]) model="iPhone 4" ;;
"iPhone5,"[3-4]) model="iPhone 5c" ;;
"iPhone6,"[1-2]) model="iPhone 5s" ;;
"iPhone7,2") model="iPhone 6" ;;
"iPhone7,1") model="iPhone 6 Plus" ;;
"iPhone8,1") model="iPhone 6s" ;;
"iPhone8,2") model="iPhone 6s Plus" ;;
"iPhone8,4") model="iPhone SE" ;;
"iPod1,1") model="iPod touch" ;;
"ipod2,1") model="iPod touch 2G" ;;
"ipod3,1") model="iPod touch 3G" ;;
"ipod4,1") model="iPod touch 4G" ;;
"ipod5,1") model="iPod touch 5G" ;;
"ipod7,1") model="iPod touch 6G" ;;
esac
;;
"BSD")
model="$(sysctl -n hw.vendor hw.product 2>/dev/null)"
;;
"Windows")
model="$(wmic computersystem get manufacturer,model /value)"
model="${model/Manufacturer'='}"
model="${model/Model'='}"
model="${model//*To Be Filled*}"
;;
"Solaris")
model="$(prtconf -b | awk -F':' '/banner-name/ {printf $2}')"
;;
esac
}
# }}}
# Distro {{{
getdistro() {
[ "$distro" ] && return
case "$os" in
"Linux" )
if grep -q 'Microsoft' /proc/version >/dev/null 2>&1 || \
grep -q 'Microsoft' /proc/sys/kernel/osrelease >/dev/null 2>&1; then
case "$distro_shorthand" in
"on") distro="$(lsb_release -sir 2>/dev/null) [Windows 10]" ;;
"tiny") distro="Windows 10" ;;
*) distro="$(lsb_release -sd 2>/dev/null) on Windows 10" ;;
esac
ascii_distro="Windows 10"
elif type -p lsb_release >/dev/null 2>&1; then
case "$distro_shorthand" in
"on") distro="$(lsb_release -sir 2>/dev/null)" ;;
"tiny") distro="$(lsb_release -si 2>/dev/null)" ;;
*) distro="$(lsb_release -sd 2>/dev/null)" ;;
esac
elif type -p guix >/dev/null 2>&1; then
distro="GuixSD"
elif type -p crux >/dev/null 2>&1; then
distro="$(crux)"
case "$distro_shorthand" in
"on") distro="${distro//version}" ;;
"tiny") distro="${distro//version*}" ;;
esac
else
# Workarounds are included in every shorthand option
case "$distro_shorthand" in
"on")
distro="$(awk -F'=' '/^NAME|VERSION_ID=/ {print $2; exit}' /etc/*ease /usr/lib/*ease)"
[ -z "$distro" ] && distro="$(awk -F'=' '/^DISTRIB_ID|DISTRIB_RELEASE=/ {print $2}' /etc/openwrt_release)"
;;
"tiny")
distro="$(awk -F'=' '/^NAME=/ {print $2; exit}' /etc/*ease /usr/lib/*ease)"
[ -z "$distro" ] && distro="$(awk -F'=' '/^TAILS_PRODUCT_NAME=/ {print $2}' /etc/*ease)"
[ -z "$distro" ] && distro="$(awk -F'=' '/^DISTRIB_ID=/ {print $2}' /etc/openwrt_release)"
;;
*)
distro="$(awk -F'=' '/^PRETTY_NAME=/ {print $2; exit}' /etc/*ease /usr/lib/*ease)"
[ -z "$distro" ] && distro="$(awk -F'=' '{print $2}' /etc/*ease)"
[ -z "$distro" ] && distro="$(awk '/BLAG/ {print $1; exit}' /etc/*ease)"
[ -z "$distro" ] && distro="$(awk -F'=' '/^DISTRIB_DESCRIPTION=/ {print $2}' /etc/openwrt_release)"
;;
esac
fi
distro="${distro//\"}"
distro="${distro//\'}"
;;
"Mac OS X")
osx_version="$(sw_vers -productVersion)"
osx_build="$(sw_vers -buildVersion)"
case "$osx_version" in
"10.4"*) codename="Mac OS X Tiger" ;;
"10.5"*) codename="Mac OS X Leopard" ;;
"10.6"*) codename="Mac OS X Snow Leopard" ;;
"10.7"*) codename="Mac OS X Lion" ;;
"10.8"*) codename="OS X Mountain Lion" ;;
"10.9"*) codename="OS X Mavericks" ;;
"10.10"*) codename="OS X Yosemite" ;;
"10.11"*) codename="OS X El Capitan" ;;
"10.12"*) codename="macOS Sierra" ;;
*) codename="macOS" ;;
esac
distro="$codename $osx_version $osx_build"
case "$distro_shorthand" in
"on") distro="${distro/ ${osx_build}}" ;;
"tiny")
case "$osx_version" in
"10."[4-7]*) distro="${distro/${codename}/Mac OS X}" ;;
"10."[8-9]* | "10.1"[0-1]*) distro="${distro/${codename}/OS X}" ;;
"10.12"*) distro="${distro/${codename}/macOS}" ;;
esac
distro="${distro/ ${osx_build}}"
;;
esac
;;
"iPhone OS")
distro="iOS $(sw_vers -productVersion)"
# "uname -m" doesn't print architecture on iOS so we force it off.
os_arch="off"
;;
"BSD")
distro="$(uname -s)"
distro="${distro/DragonFly/DragonFlyBSD}"
# Workaround for PCBSD as uname still displays FreeBSD.
[ -f "/etc/pcbsd-lang" ] && distro="PCBSD"
# Workaround for PacBSD as uname displays FreeBSD.
[ -f "/etc/pacbsd-release" ] && distro="PacBSD"
;;
"Windows")
distro="$(wmic os get Caption /value)"
# Strip crap from the output of wmic
distro="${distro/Caption'='}"
distro="${distro/Microsoft }"
;;
"Solaris")
case "$distro_shorthand" in
"on" | "tiny") distro="$(awk 'NR==1{print $1 " " $2;}' /etc/release)" ;;
*) distro="$(awk 'NR==1{print $1 " " $2 " " $3;}' /etc/release)" ;;
esac
;;
esac
# Get architecture
[ "$os_arch" == "on" ] && \
distro+=" $(uname -m)"
[ "${ascii_distro:-auto}" == "auto" ] && \
ascii_distro="$(trim "$distro")"
}
# }}}
# Title {{{
gettitle() {
title="${USER:-$(whoami || printf "%s" "${HOME/*\/}")}@${HOSTNAME:-$(hostname)}"
}
# }}}
# Kernel {{{
getkernel() {
case "$kernel_shorthand" in
"on") kernel="$(uname -r)" ;;
"off") kernel="$(uname -srm)" ;;
esac
}
# }}}
# Uptime {{{
getuptime() {
case "$os" in
"Linux" | "Windows")
case "$distro" in
*"Puppy"* | "Quirky Werewolf"* | "Alpine Linux"* | "OpenWRT"* | "Windows"*)
uptime="$(uptime | awk -F ':[0-9]{2}+ |(, ){1}+' '{printf $2}')"
;;
"openSUSE"*)
uptime="$(uptime | awk -F ':[0-9]{2}+[a-z][a-z] |(, ){1}+' '{printf $2}')"
;;
*)
uptime="$(uptime -p)"
[ "$uptime" == "up " ] && uptime="up $(awk -F'.' '{print $1}' /proc/uptime) seconds"
;;
esac
;;
"Mac OS X" | "iPhone OS" | "BSD")
# Get boot time in seconds
boot="$(sysctl -n kern.boottime)"
boot="${boot/'{ sec = '}"
boot="${boot/,*}"
# Get current date in seconds
now="$(date +%s)"
uptime="$((now - boot))"
# Convert uptime to days/hours/mins
minutes="$((uptime / 60%60))"
hours="$((uptime / 3600%24))"
days="$((uptime / 86400))"
case "$minutes" in
1) minutes="1 minute" ;;
0) unset minutes ;;
*) minutes="$minutes minutes" ;;
esac
case "$hours" in
1) hours="1 hour" ;;
0) unset hours ;;
*) hours="$hours hours" ;;
esac
case "$days" in
1) days="1 day" ;;
0) unset days ;;
*) days="$days days" ;;
esac
[ "$hours" ] && \
[ "$minutes" ] && \
hours+=","
[ "$days" ] && \
[ "$hours" ] && \
days+=","
uptime="up $days $hours $minutes"
;;
"Solaris")
uptime="$(uptime | /usr/xpg4/bin/awk -F ':[0-9]{2}+[a-z][a-z] |(, ){1}+' '{printf $2}')"
;;
esac
# Make the output of uptime smaller.
case "$uptime_shorthand" in
"on")
uptime="${uptime/up }"
uptime="${uptime/minutes/mins}"
uptime="${uptime/minute/min}"
uptime="${uptime/seconds/secs}"
;;
"tiny")
uptime="${uptime/up }"
uptime="${uptime/ days/d}"
uptime="${uptime/ day/d}"
uptime="${uptime/ hours/h}"
uptime="${uptime/ hour/h}"
uptime="${uptime/ minutes/m}"
uptime="${uptime/ minute/m}"
uptime="${uptime/ seconds/s}"
uptime="${uptime/,}"
;;
esac
}
# }}}
# Package Count {{{
getpackages() {
case "$os" in
"Linux" | "iPhone OS")
type -p pacman >/dev/null 2>&1 && \
packages="$(pacman -Qq --color never | wc -l)"
type -p dpkg >/dev/null 2>&1 && \
packages="$((packages+=$(dpkg --get-selections | grep -cv deinstall$)))"
type -p /sbin/pkgtool >/dev/null 2>&1 && \
packages="$((packages+=$(ls -1 /var/log/packages | wc -l)))"
type -p rpm >/dev/null 2>&1 && \
packages="$((packages+=$(rpm -qa | wc -l)))"
type -p xbps-query >/dev/null 2>&1 && \
packages="$((packages+=$(xbps-query -l | wc -l)))"
type -p pkginfo >/dev/null 2>&1 && \
packages="$((packages+=$(pkginfo -i | wc -l)))"
type -p pisi >/dev/null 2>&1 && \
packages="$((packages+=$(pisi list-installed | wc -l)))"
type -p pkg >/dev/null 2>&1 && \
packages="$((packages+=$(ls -1 /var/db/pkg | wc -l)))"
type -p emerge >/dev/null 2>&1 && \
packages="$((packages+=$(ls -d /var/db/pkg/*/* | wc -l)))"
type -p nix-env >/dev/null 2>&1 && \
packages="$((packages+=$(ls -d -1 /nix/store/*/ | wc -l)))"
type -p guix >/dev/null 2>&1 && \
packages="$((packages+=$(ls -d -1 /gnu/store/*/ | wc -l)))"
type -p apk >/dev/null 2>&1 && \
packages="$((packages+=$(apk info | wc -l)))"
type -p opkg >/dev/null 2>&1 && \
packages="$((packages+=$(opkg list-installed | wc -l)))"
type -p pacman-g2 >/dev/null 2>&1 && \
packages="$((packages+=$(pacman-g2 -Q | wc -l)))"
type -p cave >/dev/null 2>&1 && \
packages="$((packages+=$(ls -d -1 /var/db/paludis/repositories/cross-installed/*/data/* /var/db/paludis/repositories/installed/data/* | wc -l)))"
;;
"Mac OS X")
[ -d "/usr/local/bin" ] && \
packages="$(($(ls -l /usr/local/bin/ | grep -v "\(../Cellar/\|brew\)" | wc -l) - 1))"
type -p port >/dev/null 2>&1 && \
packages="$((packages + $(port installed 2>/dev/null | wc -l) - 1))"
type -p brew >/dev/null 2>&1 && \
packages="$((packages + $(find /usr/local/Cellar -maxdepth 1 2>/dev/null | wc -l) - 1))"
type -p pkgin >/dev/null 2>&1 && \
packages="$((packages + $(pkgin list 2>/dev/null | wc -l)))"
;;
"BSD")
case "$distro" in
# PacBSD has both pacman and pkg, but only pacman is used
"PacBSD"*) packages="$(pacman -Qq --color never | wc -l)" ;;
*)
if type -p pkg_info >/dev/null 2>&1; then
packages="$(pkg_info | wc -l)"
elif type -p pkg >/dev/null 2>&1; then
packages="$(pkg info | wc -l)"
fi
;;
esac
;;
"Windows")
packages="$(cygcheck -cd | wc -l)"
# Count chocolatey packages
[ -d "/cygdrive/c/ProgramData/chocolatey/lib" ] && \
packages="$((packages+=$(ls -1 /cygdrive/c/ProgramData/chocolatey/lib | wc -l)))"
;;
"Solaris")
packages="$(pkg list | wc -l)"
;;
esac
}
# }}}
# Shell {{{
getshell() {
case "$shell_path" in
"on") shell="$SHELL" ;;
"off") shell="${SHELL##*/}" ;;
esac
if [ "$shell_version" == "on" ]; then
shell+=" "
case "$shell" in
*"bash"*)
shell+="$(bash --version | head -n 1)"
shell="${shell/ *, version}"
;;
*"zsh"*)
shell+="$(zsh --version)"
shell="${shell/ zsh}"
;;
*"mksh"* | *"ksh")
shell+="$("$SHELL" -c 'printf "%s" "$KSH_VERSION"')"
shell="${shell/ * KSH}"
;;
*"tcsh"* | *"csh"*)
shell+="$("$SHELL" --version)"
shell="${shell/tcsh}"
shell="${shell/\(*}"
;;
*"fish"*)
shell+="$("$SHELL" -c 'printf "%s" "$FISH_VERSION"')"
;;
esac
shell="${shell/\(*\)}"
fi
}
# }}}
# Desktop Environment {{{
getde() {
case "$os" in
"Mac OS X") de="Aqua" ;;
*)
de="${XDG_CURRENT_DESKTOP/i3}"
de="${de/'X-'}"
;;
esac
if [ -n "$DISPLAY" ] && [ -z "$de" ]; then
de="$(xprop -root | awk '/KDE_SESSION_VERSION|^_MUFFIN|xfce4|xfce5/' 2>/dev/null)"
case "$de" in
"KDE_SESSION_VERSION"*) de="KDE${de/* = }" ;;
*"TDE_FULL_SESSION"*) de="Trinity" ;;
*"MUFFIN"*) de="$(cinnamon --version 2>/dev/null)"; de="${de:-Cinnamon}" ;;
*"xfce4"*) de="XFCE4" ;;
*"xfce5"*) de="XFCE5" ;;
esac
fi
}
# }}}
# Window Manager {{{
getwm() {
if [ -n "$DISPLAY" ] && [ "$os" != "Mac OS X" ]; then
id="$(xprop -root -notype | awk '$1=="_NET_SUPPORTING_WM_CHECK:"{print $5}' 2>/dev/null)"
wm="$(xprop -id "$id" -notype -f _NET_WM_NAME 8t 2>/dev/null)"
wm="${wm/*_NET_WM_NAME = }"
wm="${wm/\"}"
wm="${wm/\"*}"
# Fallback for Wayland wms
case "$wm" in
"xwlc") wm="$(ps -e | grep -m 1 -oE "sway|orbment|velox|orbital")" ;;
esac
else
case "$os" in
"Mac OS X") wm="Quartz Compositor" ;;
"Windows")
wm="$(tasklist | grep -m 1 -o "bugn\|Windawesome\|blackbox\|emerge\|litestep")"
[ "$wm" == "blackbox" ] && wm="bbLean (Blackbox)"
if [ "$wm" ]; then
wm="$wm, Explorer"
else
wm="Explorer"
fi
;;
esac
fi
# Don't uppercase i3
[ "$version" -ge 4 ] && \
[ "$wm" != "i3" ] && \
wm="${wm^}"
}
# }}}
# Window Manager Theme {{{
getwmtheme() {
[ -z "$wm" ] && getwm
[ -z "$de" ] && getde
case "$wm" in
'BudgieWM') wmtheme="$(gsettings get org.gnome.desktop.wm.preferences theme)" ;;
'E16') wmtheme="$(awk -F "= " '/theme.name/ {print $2}' "$HOME/.e16/e_config--0.0.cfg")";;
'Sawfish') wmtheme="$(awk -F ")" '/\(quote default-frame-style/ {print $2}' "$HOME/.sawfish/custom")" ;;
'Cinnamon' | 'Muffin' | 'Mutter (Muffin)')
detheme="$(gsettings get org.cinnamon.theme name)"
wmtheme="$(gsettings get org.cinnamon.desktop.wm.preferences theme)"
wmtheme="$detheme (${wmtheme})"
;;
'Compiz' | 'Mutter'* | 'GNOME Shell' | 'Gala')
if type -p gsettings >/dev/null 2>&1; then
wmtheme="$(gsettings get org.gnome.shell.extensions.user-theme name)"
[ -z "$wmtheme" ] && \
wmtheme="$(gsettings get org.gnome.desktop.wm.preferences theme)"
elif type -p gconftool-2 >/dev/null 2>&1; then
wmtheme="$(gconftool-2 -g /apps/metacity/general/theme)"
fi
;;
'Metacity'*)
if [ "$de" == "Deepin" ]; then
wmtheme="$(gsettings get com.deepin.wrap.gnome.desktop.wm.preferences theme 2>/dev/null)"
else
wmtheme="$(gconftool-2 -g /apps/metacity/general/theme 2>/dev/null)"
fi
;;
'E17' | 'Enlightenment')
if type -p eet >/dev/null 2>&1; then
wmtheme="$(eet -d "$HOME/.e/e/config/standard/e.cfg" config | awk '/value \"file\" string.*.edj/ {print $4}')"
wmtheme="${wmtheme##*/}"
wmtheme="${wmtheme%.*}"
fi
;;
'Fluxbox')
[ -f "$HOME/.fluxbox/init" ] && \
wmtheme="$(awk -F "/" '/styleFile/ {print $NF}' "$HOME/.fluxbox/init")"
;;
'IceWM'*)
[ -f "$HOME/.icewm/theme" ] && \
wmtheme="$(awk -F "[\",/]" '!/#/ {print $2}' "$HOME/.icewm/theme")"
;;
'Openbox')
if [ "$de" == "LXDE" ] && [ -f "${HOME}/.config/openbox/lxde-rc.xml" ]; then
ob_file="lxde-rc"
elif [ -f "${HOME}/.config/openbox/rc.xml" ]; then
ob_file="rc"
fi
wmtheme="$(awk -F "[<,>]" '/<theme/ {getline; print $3}' "$XDG_CONFIG_HOME/openbox/${ob_file}.xml")";
;;
'PekWM')
[ -f "$HOME/.pekwm/config" ] && \
wmtheme="$(awk -F "/" '/Theme/ {gsub(/\"/,""); print $NF}' "$HOME/.pekwm/config")"
;;
'Xfwm4')
[ -f "${HOME}/.config/xfce4/xfconf/xfce-perchannel-xml/xfwm4.xml" ] && \
wmtheme="$(xfconf-query -c xfwm4 -p /general/theme)"
;;
'KWin'*)
kdeconfigdir
kde_config_dir="${kde_config_dir%/}"
if [ -f "$kde_config_dir/share/config/kwinrc" ]; then
wmtheme="$(awk '/PluginLib=kwin3_/{gsub(/PluginLib=kwin3_/,"",$0); print $0; exit}' "$kde_config_dir/share/config/kwinrc")"
elif [ -f "$kde_config_dir/share/config/kdebugrc" ]; then
wmtheme="$(awk '/(decoration)/ {gsub(/\[/,"",$1); print $1; exit}' "$kde_config_dir/share/config/kdebugrc")"
fi
;;
'Quartz Compositor')
wmtheme="$(/usr/libexec/PlistBuddy -c "Print AppleAquaColorVariant" ~/Library/Preferences/.GlobalPreferences.plist)"
if [ -z "$wmtheme" ] || [ "$wmtheme" == "1" ]; then
wmtheme="Blue"
else
wmtheme="Graphite"
fi
;;
*'Explorer')
path="/proc/registry/HKEY_CURRENT_USER/Software/Microsoft"
path+="/Windows/CurrentVersion/Themes/CurrentTheme"
wmtheme="$(head -n1 "$path" 2>/dev/null)"
wmtheme="${wmtheme##*\\}"
wmtheme="${wmtheme%.*}"
;;
'Blackbox' | "bbLean"*)
path="$(wmic process get ExecutablePath | grep "blackbox")"
path="${path//'\'/'/'}"
wmtheme="$(grep "^session\.styleFile:" ${path/\.exe/.rc})"
wmtheme="${wmtheme/'session.styleFile: '}"
wmtheme="${wmtheme##*\\}"
wmtheme="${wmtheme%.*}"
;;
esac
wmtheme="${wmtheme//\'}"
[ "$version" -ge 4 ] && wmtheme="${wmtheme^}"
}
# }}}
# CPU {{{
getcpu() {
# NetBSD emulates the linux /proc filesystem instead of using sysctl for hw
# information so we have to use this block below which temporarily sets the
# OS to 'Linux' for the duration of this function.
case "$distro" in
"NetBSD"*) local os="Linux" ;;
esac
case "$os" in
"Linux" | "Windows")
# Get cpu name
cpu="$(awk -F ': | @' '/model name/ {printf $2; exit}' /proc/cpuinfo)"
cpu_dir="/sys/devices/system/cpu/cpu0/cpufreq"
# Get cpu speed
if [ -d "$cpu_dir" ]; then
case "$speed_type" in
current) speed_type="scaling_cur_freq" ;;
min) speed_type="scaling_min_freq" ;;
max) speed_type="scaling_max_freq" ;;
bios) speed_type="bios_limit" ;;
scaling_current) speed_type="scaling_cur_freq" ;;
scaling_min) speed_type="scaling_min_freq" ;;
scaling_max) speed_type="scaling_max_freq" ;;
esac
# Fallback to cpuinfo_max_freq if $speed_type fails
read -t 1 -r speed < "${cpu_dir}/${speed_type}" || \
read -t 1 -r speed < "${cpu_dir}/cpuinfo_max_freq"
speed="$((speed / 100000))"
else
speed="$(awk -F ': |\\.' '/cpu MHz/ {printf $2; exit}' /proc/cpuinfo)"
speed="$((speed / 100))"
fi
# Show/hide hyperthreaded cores
case "$cores_ht" in
"on") cores="$(grep -c ^processor /proc/cpuinfo)" ;;
"off") cores="$(grep "^core id" /proc/cpuinfo | sort -u | wc -l)" ;;
esac
# Fix for speeds under 1ghz
if [ -z "${speed:1}" ]; then
speed="0.${speed}"
else
speed="${speed:0:1}.${speed:1}"
fi
cpu="$cpu @ ${speed}GHz"
;;
"Mac OS X")
cpu="$(sysctl -n machdep.cpu.brand_string)"
# Show/hide hyperthreaded cores
case "$cores_ht" in
"on") cores="$(sysctl -n hw.logicalcpu_max)" ;;
"off") cores="$(sysctl -n hw.physicalcpu_max)" ;;
esac
;;
"iPhone OS")
case "${ios_model:-$(uname -m)}" in
"iPhone1,1" | "iPhone1,2" | "iPod1,1")
cpu="Samsung S5L8900 @ 412MHz"
cores="1"
;;
"iPhone2,1")
cpu="Samsung S5PC100 @ 600MHz"
cores="1"
;;
"iPhone3,1" | "iPhone3,2" | "iPhone3,3" | "iPod4,1")
cpu="Apple A4 @ 800MHz"
cores="1"
;;
"iPhone4,1" | "iPod5,1")
cpu="Apple A5 @ 800MHz"
cores="2"
;;
"iPhone5,1" | "iPhone5,2" | "iPhone5,3" | "iPhone5,4")
cpu="Apple A6 @ 1.3GHz"
cores="2"
;;
"iPhone6,1" | "iPhone6,2")
cpu="Apple A7 @ 1.3GHz"
cores="2"
;;
"iPhone7,1" | "iPhone7,2")
cpu="Apple A8 @ 1.4GHz"
cores="2"
;;
"iPhone8,1" | "iPhone8,2" | "iPhone8,4")
cpu="Apple A9 @ 1.85GHz"
cores="2"
;;
"iPod2,1")
cpu="Samsung S5L8720 @ 533MHz"
cores="1"
;;
"iPod3,1")
cpu="Samsung S5L8922 @ 600MHz"
cores="1"
;;
"iPod7,1")
cpu="Apple A8 @ 1.1GHz"
cores="2"
;;
"iPad1,1")
cpu="Apple A4 @ 1GHz"
cores="1"
;;
"iPad2,1" | "iPad2,2" | "iPad2,3" | "iPad2,4" | "iPad2,5" | "iPad2,6" | "iPad2,7")
cpu="Apple A5 @ 1GHz"
cores="2"
;;
"iPad3,1" | "iPad3,2" | "iPad3,3")
cpu="Apple A5X @ 1GHz"
cores="2"
;;
"iPad3,4" | "iPad3,5" | "iPad3,6")
cpu="Apple A6X @ 1.4GHz"
cores="2"
;;
"iPad4,1" | "iPad4,2" | "iPad4,3")
cpu="Apple A7 @ 1.4GHz"
cores="2"
;;
"iPad4,4" | "iPad4,5" | "iPad4,6" | "iPad4,7" | "iPad4,8" | "iPad4,9")
cpu="Apple A7 @ 1.4GHz"
cores="2"
;;
"iPad5,1" | "iPad5,2")
cpu="Apple A8 @ 1.5GHz"
cores="2"
;;
"iPad5,3" | "iPad5,4")
cpu="Apple A8X @ 1.5GHz"
cores="3"
;;
"iPad6,3" | "iPad6,4")
cpu="Apple A9X @ 2.16GHz"
cores="2"
;;
"iPad6,7" | "iPad6,8")
cpu="Apple A9X @ 2.26GHz"
cores="2"
;;
esac
;;
"BSD")
# Get cpu name
cpu="$(sysctl -n hw.model)"
cpu="${cpu/[0-9]\.*}"
cpu="${cpu/ @*}"
# Get cpu speed
speed="$(sysctl -n hw.cpuspeed)"
[ -z "$speed" ] && speed="$(sysctl -n hw.clockrate)"
speed="$((speed / 100))"
# Get cpu cores
cores="$(sysctl -n hw.ncpu)"
# Fix for speeds under 1ghz
if [ -z "${speed:1}" ]; then
speed="0.${speed}"
else
speed="${speed:0:1}.${speed:1}"
fi
cpu="$cpu @ ${speed}GHz"
;;
"Solaris")
# Get cpuname
cpu="$(psrinfo -pv | tail -1)"
cpu="${cpu/[0-9]\.*}"
cpu="${cpu/ @*}"
# Get cpu speed
speed="$(psrinfo -v | awk '/operates at/ {print $6}')"
speed="$((speed / 100))"
# Get cpu cores
cores="$(kstat -m cpu_info | grep -c "chip_id")"
# Fix for speeds under 1ghz
if [ -z "${speed:1}" ]; then
speed="0.${speed}"
else
speed="${speed:0:1}.${speed:1}"
fi
cpu="$cpu @ ${speed}GHz"
;;
esac
# Remove uneeded patterns from cpu output
# This is faster than sed/gsub
cpu="${cpu//(tm)}"
cpu="${cpu//(TM)}"
cpu="${cpu//(r)}"
cpu="${cpu//(R)}"
cpu="${cpu//CPU}"
cpu="${cpu//Processor}"
cpu="${cpu//Six-Core}"
cpu="${cpu//Eight-Core}"
cpu="${cpu//Dual-Core}"
cpu="${cpu//Quad-Core}"
cpu="${cpu//with Radeon HD Graphics}"
# Add cpu cores to output
[ "$cpu_cores" == "on" ] && [ "$cores" ] && \
cpu="${cpu/@/(${cores}) @}"
# Make the output of cpu shorter
case "$cpu_shorthand" in
"name") cpu="${cpu/@*}" ;;
"speed") cpu="${cpu#*@ }" ;;
"on" | "tiny")
cpu="${cpu/Intel }"
cpu="${cpu/Core }"
cpu="${cpu/Core? Duo }"
cpu="${cpu/AMD }"
case "$cpu_shorthand" in
"tiny") cpu="${cpu/@*}" ;;
esac
;;
esac
}
# }}}
# CPU Usage {{{
getcpu_usage() {
case "$os" in
"Windows")
cpu_usage="$(wmic cpu get loadpercentage /value)"
cpu_usage="${cpu_usage/LoadPercentage'='}"
cpu_usage="${cpu_usage//[[:space:]]}"
;;
"Linux" | "Mac OS X" | "iPhone OS" | "BSD" | "Solaris")
# Get cores if unset
if [ -z "$cores" ]; then
case "$os" in
"Linux") cores="$(awk -F ': ' '/siblings/ {printf $2; exit}' /proc/cpuinfo)" ;;
"Mac OS X" | "BSD") cores="$(sysctl -n hw.ncpu)" ;;
"Solaris") cores="$(kstat -m cpu_info | grep "chip_id" | wc -l | tr -d ' ')"
esac
fi
cpu_usage="$(ps aux | awk 'BEGIN {sum=0} {sum+=$3 }; END {print sum}')"
cpu_usage="$((${cpu_usage/\.*} / ${cores:-1}))"
;;
esac
# Print the bar
case "$cpu_display" in
"bar") cpu_usage="$(bar $cpu_usage 100)" ;;
"infobar") cpu_usage="${cpu_usage}% $(bar $cpu_usage 100)" ;;
"barinfo") cpu_usage="$(bar $cpu_usage 100) ${cpu_usage}%" ;;
*) cpu_usage="${cpu_usage}%" ;;
esac
}
# }}}
# GPU {{{
getgpu() {
case "$os" in
"Linux")
gpu="$(PATH="/sbin:$PATH" lspci | grep -F "3D")"
# If a GPU with a prefix of '3D' doesn't exist
# fallback to looking for a prefix of 'VGA'
[ -z "$gpu" ] && \
gpu="$(PATH="/sbin:$PATH" lspci | grep -F "VGA")"
gpu="${gpu//??':'??'.'?}"
# Count the number of GPUs
count="$(printf "%s" "$gpu" | uniq -c)"
count="${count/ VGA*}"
count="${count/ 3D*}"
# If there's more than one gpu
# Display the count.
if [ "$count" -gt 1 ]; then
count=" x $count"
else
unset count
fi
# Format the output
gpu="${gpu/* VGA compatible controller: }"
gpu="${gpu/* 3D controller: }"
gpu="${gpu/(rev*)}"
case "$gpu" in
intel*)
gpu="Intel Integrated Graphics"
;;
advanced*)
gpu="${gpu/Advanced Micro Devices, Inc\. }"
gpu="${gpu/'[AMD/ATI]' }"
gpu="${gpu/Tahiti PRO}"
gpu="${gpu/XTX}"
gpu="${gpu/ OEM}"
gpu="${gpu/ \[}"
gpu="${gpu/\]}"
gpu="${gpu/*Radeon/Radeon}"
brand="AMD "
;;
nvidia*)
gpu="${gpu/NVIDIA Corporation }"
gpu="${gpu/G????M }"
gpu="${gpu/G???? }"
gpu="${gpu/\[}"
gpu="${gpu/\] }"
brand="NVIDIA "
;;
*virtualbox*)
gpu="VirtualBox Graphics Adapter"
;;
esac
gpu="${brand}${gpu}"
;;
"Mac OS X")
# Use cache if it exists
if [ -f "/Library/Caches/neofetch/gpu" ]; then
source "/Library/Caches/neofetch/gpu"
else
gpu="$(system_profiler SPDisplaysDataType | awk -F': ' '/^\ *Chipset Model:/ {printf $2 ", "}')"
gpu="${gpu//'/ $'}"
gpu="${gpu%,*}"
cache "gpu" "$gpu" "/Library/Caches/"
fi
;;
"iPhone OS")
ios_model="${ios_model:-"$(uname -m)"}"
case "$ios_model" in
"iPhone1,1" | "iPhone1,2")
gpu="PowerVR MBX Lite 3D"
;;
"iPhone2,1" | "iPhone3,1" | "iPhone3,2" | "iPhone3,3" | "iPod3,1" | "iPod4,1" | "iPad1,1")
gpu="PowerVR SGX535"
;;
"iPhone4,1" | "iPad2,1" | "iPad2,2" | "iPad2,3" | "iPad2,4" | "iPad2,5" | "iPad2,6" | "iPad2,7" | "iPod5,1")
gpu="PowerVR SGX543MP2"
;;
"iPhone5,1" | "iPhone5,2" | "iPhone5,3" | "iPhone5,4")
gpu="PowerVR SGX543MP3"
;;
"iPhone6,1" | "iPhone6,2" | "iPad4,1" | "iPad4,2" | "iPad4,3" | "iPad4,4" | "iPad4,5" | "iPad4,6" | "iPad4,7" | "iPad4,8" | "iPad4,9")
gpu="PowerVR G6430"
;;
"iPhone7,1" | "iPhone7,2" | "iPod7,1" | "iPad5,1" | "iPad5,2")
gpu="PowerVR GX6450"
;;
"iPhone8,1" | "iPhone8,2" | "iPhone8,4")
gpu="PowerVR GT7600"
;;
"iPod1,1" | "iPod2,1")
gpu="PowerVR MBX Lite"
;;
"iPad3,1" | "iPad3,2" | "iPad3,3")
gpu="PowerVR SGX534MP4"
;;
"iPad3,4" | "iPad3,5" | "iPad3,6")
gpu="PowerVR SGX554MP4"
;;
"iPad5,3" | "iPad5,4")
gpu="PowerVR GXA6850"
;;
"iPad6,3" | "iPad6,4" | "iPad6,7" | "iPad6,8")
gpu="PowerVR 7XT"
;;
esac
;;
"BSD" | "Solaris")
case "$distro" in
"FreeBSD"*)
gpu="$(pciconf -lv 2>/dev/null | grep -B 4 "VGA" | grep "device")"
gpu="${gpu/*device*= }"
gpu="${gpu//\'}"
;;
*)
gpu="$(glxinfo | grep -F 'OpenGL renderer string')"
gpu="${gpu/'OpenGL renderer string: '}"
;;
esac
;;
"Windows")
gpu="$(wmic path Win32_VideoController get caption /value)"
gpu="${gpu/Caption'='}"
;;
esac
case "$gpu_shorthand" in
"on" | "tiny")
gpu="${gpu// Rev\. ?}"
gpu="${gpu//AMD*\/ATI\]/AMD}"
gpu="${gpu// Tahiti}"
gpu="${gpu// PRO}"
gpu="${gpu// OEM}"
gpu="${gpu// Mars}"
gpu="${gpu// Series}"
gpu="${gpu// Controller}"
gpu="${gpu/\/*}"
case "$gpu_shorthand" in
"tiny")
gpu="${gpu/Graphics }"
gpu="${gpu/GeForce }"
gpu="${gpu/Radeon }"
;;
esac
;;
esac
if [ "$gpu_brand" == "off" ]; then
gpu="${gpu/AMD}"
gpu="${gpu/NVIDIA}"
gpu="${gpu/Intel}"
fi
gpu="${gpu}${count}"
}
# }}}
# Memory {{{
getmemory() {
case "$os" in
"Linux" | "Windows")
if grep -F "MemAvail" /proc/meminfo >/dev/null 2>&1; then
mem=($(awk -F ':| kB' '/MemTotal|MemAvail/ {printf $2}' /proc/meminfo))
memused="$((mem[0] - mem[1]))"
else
mem=($(awk -F ':| kB' '/MemTotal|MemFree|Buffers|Cached/ {printf $2}' /proc/meminfo) 0 0)
memused="$((mem[0] - mem[1] - mem[2] - mem[3]))"
fi
memused="$((memused / 1024))"
memtotal="$((mem[0] / 1024))"
;;
"Mac OS X" | "iPhone OS")
memtotal="$(($(sysctl -n hw.memsize) / 1024 / 1024))"
memwired="$(vm_stat | awk '/wired/ { print $4 }')"
memactive="$(vm_stat | awk '/active / { printf $3 }')"
memcompressed="$(vm_stat | awk '/occupied/ { printf $5 }')"
memused="$(((${memwired//.} + ${memactive//.} + ${memcompressed//.}) * 4 / 1024))"
;;
"BSD")
case "$distro" in
"NetBSD"*) memfree="$(($(awk -F ':|kB' '/MemFree:/ {printf $2}' /proc/meminfo) / 1024))" ;;
*) memfree="$(($(vmstat | awk 'END{printf $5}') / 1024))" ;;
esac
case "$distro" in
"NetBSD"*) memtotal="$(($(sysctl -n hw.physmem64) / 1024 / 1024))" ;;
*) memtotal="$(($(sysctl -n hw.physmem) / 1024 / 1024))" ;;
esac
memused="$((memtotal - memfree))"
;;
"Solaris")
memtotal="$(prtconf | grep Memory | head -1 | awk 'BEGIN {FS=" "} {print $3}')"
memfree="$(($(sar -r 1 1 | tail -1 | awk 'BEGIN {FS=" "} {print $2}') / 1024))"
memused="$((memtotal - memfree))"
;;
esac
memory="${memused}MB / ${memtotal}MB"
# Progress bars
case "$memory_display" in
"bar") memory="$(bar "${memused}" "${memtotal}")" ;;
"infobar") memory="${memory} $(bar "${memused}" "${memtotal}")" ;;
"barinfo") memory="$(bar "${memused}" "${memtotal}") ${memory}" ;;
esac
}
# }}}
# Song {{{
getsong() {
if mpc version >/dev/null 2>&1; then
song="$(mpc current 2>/dev/null)"
state="$(mpc | awk -F '\\[|\\]' '/\[/ {printf $2}' 2>/dev/null)"
elif [ -n "$(ps x | awk '!(/awk/) && /cmus/')" ]; then
IFS=$'\n'
song=("$(cmus-remote -Q | grep "tag artist \|title \|status" 2>/dev/null | sort)")
artist="${song[1]/tag artist }"
title="${song[2]/tag title }"
state="${song[0]/status }"
song="$artist - $title"
elif pgrep "mocp" >/dev/null 2>&1; then
song="$(mocp -Q "%artist - %song" 2>/dev/null)"
state="$(mocp -Q "%state" 2>/dev/null)"
elif [ -n "$(ps x | awk '!(/awk/) && /spotify/')" ]; then
case "$os" in
"Linux")
# This command is way too long
song="$(\
dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 \
org.freedesktop.DBus.Properties.Get string:'org.mpris.MediaPlayer2.Player' string:'Metadata' |\
awk -F 'string "' '/string|array/ {printf "%s",$2; next}{print ""}' |\
awk -F '"' '/artist|title/ {printf $2 " - "}'
)"
song="${song% - }"
song="${song/'('*}"
song="${song//'['*}"
;;
"Mac OS X")
song="$(osascript -e 'tell application "Spotify" to artist of current track as string & " - " & name of current track as string')"
state="$(osascript -e 'tell application "Spotify" to player state as string')"
;;
esac
elif [ -n "$(ps x | awk '!(/awk/ || /Helper/) && /Google Play Music Desktop Player/')" ] && type -p gpmdp-remote >/dev/null 2>&1; then
song="$(gpmdp-remote current)"
state="$(gpmdp-remote status)"
elif [ -n "$(ps x | awk '!(/awk/ || /Helper/ || /Cache/) && /iTunes.app/')" ]; then
song="$(osascript -e 'tell application "iTunes" to artist of current track as string & " - " & name of current track as string')"
state="$(osascript -e 'tell application "iTunes" to player state as string')"
elif [ -n "$(ps x | awk '!(/awk/) && /rhythmbox/')" ]; then
song="$(rhythmbox-client --print-playing)"
# Well, what can you expect? It's dbus after all.
state="$(dbus-send --print-reply --dest=org.mpris.MediaPlayer2.rhythmbox /org/mpris/MediaPlayer2 \
org.freedesktop.DBus.Properties.Get string:'org.mpris.MediaPlayer2.Player' string: 'PlayBackStatus' |\
awk -F 'string "' '{printf $2}')"
state="${state//\"}"
elif [ -n "$(ps x | awk '!(/awk/) && /banshee/')" ]; then
artist="$(banshee --query-artist | awk -F':' '{print $2}')"
title="$(banshee --query-title | awk -F':' '{print $2}')"
song="$artist - $title"
state="$(banshee --query-current-state | awk -F':' '{print $2}')"
elif [ -n "$(ps x | awk '!(/awk/) && /amarok/')" ]; then
artist="$(qdbus org.kde.amarok /Player GetMetadata | awk -F':' '/^artist/ {print $2}')"
title="$(qdbus org.kde.amarok /Player GetMetadata | awk -F':' '/title/ {print $2}')"
song="$artist - $title"
elif [ -n "$(ps x | awk '!(/awk/) && /deadbeef/')" ]; then
song="$(deadbeef --nowplaying '%a - %t')"
else
song="Not Playing"
fi
case "$state" in
"paused" | "PAUSE" | "Paused")
song="Paused"
;;
"stopped" | "STOP" | "Stopped")
song="Stopped"
;;
esac
# Display Artist and Title on seperate lines.
if [ "$song_shorthand" == "on" ]; then
artist="${song/ -*}"
song="${song/$artist - }"
if [ "$song" != "$artist" ]; then
prin "Artist" "$artist"
prin "Song" "$song"
else
prin "$subtitle" "$song"
fi
unset song
fi
}
# }}}
# Resolution {{{
getresolution() {
case "$os" in
"Linux" | "BSD" | "Solaris")
if type -p xrandr >/dev/null 2>&1; then
case "$refresh_rate" in
"on") resolution="$(xrandr --nograb --current | awk 'match($0,/[0-9]*\.[0-9]*\*/) {printf $1 " @ " substr($0,RSTART,RLENGTH) "Hz, "}')" ;;
"off") resolution="$(xrandr --nograb --current | awk '/\*/ {printf $1 ", "}')" ;;
esac
resolution="${resolution//\*}"
resolution="${resolution//\.[0-9][0-9]}"
elif type -p xdpyinfo >/dev/null 2>&1; then
resolution="$(xdpyinfo 2>/dev/null | awk '/dimensions:/ {printf $2}')"
fi
;;
"Mac OS X")
if type -p screenresolution >/dev/null 2>&1; then
resolution="$(screenresolution get 2>&1 | awk '/Display/ {printf $6 "Hz, "}')"
resolution="${resolution//x??@/ @ }"
else
resolution="$(system_profiler SPDisplaysDataType |\
awk '/Resolution:/ {printf $2"x"$4" @ "$6"Hz, "}')"
fi
scale_factor="$(/usr/libexec/PlistBuddy -c "Print DisplayAnyUserSets:0:0:Resolution" /Library/Preferences/com.apple.windowserver.plist)"
[ "${scale_factor%.*}" == "2" ] && \
resolution="${resolution// @/@2x @}"
if [ "$refresh_rate" == "off" ]; then
resolution="${resolution// @ [0-9][0-9]Hz}"
resolution="${resolution// @ [0-9][0-9][0-9]Hz}"
fi
[[ "$resolution" =~ "0Hz" ]] && \
resolution="${resolution// @ 0Hz}"
;;
"Windows")
width="$(wmic path Win32_VideoController get CurrentHorizontalResolution /value 2>/dev/null)"
width="${width/CurrentHorizontalResolution'='/}"
height="$(wmic path Win32_VideoController get CurrentVerticalResolution /value 2>/dev/null)"
height="${height/CurrentVerticalResolution'='/}"
[ "$width" ] && \
resolution="${width}x${height}"
;;
esac
resolution="${resolution%,*}"
}
# }}}
# Theme/Icons/Font {{{
getstyle() {
# Fix weird output when the function
# is run multiple times.
unset gtk2theme gtk3theme theme path
case "$1" in
theme)
name="gtk-theme-name"
gsettings="gtk-theme"
gconf="gtk_theme"
xfconf="/Net/ThemeName"
kde="widgetStyle"
;;
icons)
name="gtk-icon-theme-name"
gsettings="icon-theme"
gconf="icon_theme"
xfconf="/Net/IconThemeName"
kde="Theme"
;;
font)
name="gtk-font-name"
gsettings="font-name"
gconf="font_theme"
xfconf="/Gtk/FontName"
kde="font"
;;
esac
if [ -n "$DISPLAY" ] && [ "$os" != "Mac OS X" ]; then
# Get DE if user has disabled the function.
[ -z "$de" ] && getde
case "$de" in
"KDE"*)
kdeconfigdir
if [ -f "${kde_config_dir}/share/config/kdeglobals" ]; then
kde_config_file="${kde_config_dir}/share/config/kdeglobals"
theme="$(grep "^[^#]*$kde" "$kde_config_file")"
theme="${theme/${kde}*=}"
[ "$version" -ge 4 ] && theme="${theme^}"
gtk_shorthand="on"
return
fi
;;
*"Cinnamon")
if type -p gsettings >/dev/null 2>&1; then
gtk3theme="$(gsettings get org.cinnamon.desktop.interface "$gsettings")"
gtk2theme="${gtk3theme}"
fi
;;
"Gnome"* | "Unity"* | "Budgie")
if type -p gsettings >/dev/null 2>&1; then
gtk3theme="$(gsettings get org.gnome.desktop.interface "$gsettings")"
gtk2theme="${gtk3theme}"
elif type -p gconftool-2 >/dev/null 2>&1; then
gtk2theme="$(gconftool-2 -g /desktop/gnome/interface/"$gconf")"
fi
;;
"Mate"*)
gtk3theme="$(gsettings get org.mate.interface "$gsettings")"
gtk2theme="${gtk3theme}"
;;
"Xfce"*)
type -p xfconf-query >/dev/null 2>&1 && \
gtk2theme="$(xfconf-query -c xsettings -p "$xfconf")"
;;
esac
# Check for gtk2 theme
if [ -z "$gtk2theme" ]; then
if [ -f "${GTK2_RC_FILES:-$HOME/.gtkrc-2.0}" ]; then
gtk2theme="$(grep "^[^#]*$name" "${GTK2_RC_FILES:-$HOME/.gtkrc-2.0}")"
elif [ -f "/usr/share/gtk-2.0/gtkrc" ]; then
gtk2theme="$(grep "^[^#]*$name" /usr/share/gtk-2.0/gtkrc)"
elif [ -f "/etc/gtk-2.0/gtkrc" ]; then
gtk2theme="$(grep "^[^#]*$name" /etc/gtk-2.0/gtkrc)"
fi
gtk2theme="${gtk2theme/${name}*=}"
fi
# Check for gtk3 theme
if [ -z "$gtk3theme" ]; then
if [ -f "$XDG_CONFIG_HOME/gtk-3.0/settings.ini" ]; then
gtk3theme="$(grep "^[^#]*$name" "$XDG_CONFIG_HOME/gtk-3.0/settings.ini")"
elif type -p gsettings >/dev/null 2>&1; then
gtk3theme="$(gsettings get org.gnome.desktop.interface $gsettings)"
elif [ -f "/usr/share/gtk-3.0/settings.ini" ]; then
gtk3theme="$(grep "^[^#]*$name" /usr/share/gtk-3.0/settings.ini)"
elif [ -f "/etc/gtk-3.0/settings.ini" ]; then
gtk3theme="$(grep "^[^#]*$name" /etc/gtk-3.0/settings.ini)"
fi
gtk3theme="${gtk3theme/${name}*=}"
fi
# Remove quotes
gtk2theme=${gtk2theme//\"}
gtk2theme=${gtk2theme//\'}
gtk3theme=${gtk3theme//\"}
gtk3theme=${gtk3theme//\'}
# Uppercase the first letter of each gtk theme
if [ "$version" -ge 4 ]; then
gtk2theme="${gtk2theme^}"
gtk3theme="${gtk3theme^}"
fi
# Toggle visibility of gtk themes.
[ "$gtk2" == "off" ] && unset gtk2theme
[ "$gtk3" == "off" ] && unset gtk3theme
# Format the string based on which themes exist
if [ "$gtk2theme" ] && [ "$gtk2theme" == "$gtk3theme" ]; then
gtk3theme+=" [GTK2/3]"
unset gtk2theme
elif [ "$gtk2theme" ] && [ "$gtk3theme" ]; then
gtk2theme+=" [GTK2], "
gtk3theme+=" [GTK3] "
else
[ "$gtk2theme" ] && gtk2theme+=" [GTK2] "
[ "$gtk3theme" ] && gtk3theme+=" [GTK3] "
fi
# Final string
theme="${gtk2theme}${gtk3theme}"
# Make the output shorter by removing "[GTKX]" from the string
if [ "$gtk_shorthand" == "on" ]; then
theme="${theme/ '[GTK2]'}"
theme="${theme/ '[GTK3]'}"
theme="${theme/ '[GTK2/3]'}"
fi
fi
}
gettheme() {
getstyle theme
}
geticons() {
getstyle icons
icons="$theme"
}
getfont() {
getstyle font
font="$theme"
}
# }}}
# Terminal Emulator {{{
getterm() {
# Check $PPID for terminal emulator.
case "$os" in
"Mac OS X")
# Workaround for macOS systems that
# don't support the block below.
case "$TERM_PROGRAM" in
"iTerm.app") term="iTerm2" ;;
"Terminal.app") term="Apple Terminal" ;;
*) term="${TERM_PROGRAM/\.app}" ;;
esac
return
;;
"Windows")
parent="$(ps -p ${1:-$PPID} | awk '{printf $2}')"
parent="${parent/'PPID'}"
name="$(ps -p $parent | awk '{printf $8}')"
name="${name/'COMMAND'}"
name="${name/*\/}"
;;
*)
parent="$(ps -p ${1:-$PPID} -o ppid=)"
name="$(ps -p $parent -o comm=)"
;;
esac
case "${name// }" in
"${SHELL/*\/}" | *"sh" | "tmux"* | "screen") getterm "$parent" ;;
"login" | "init") term="$(tty)" ;;
"ruby" | "1" | "systemd" | "sshd"* | "python"*) unset term ;;
"gnome-terminal-") term="gnome-terminal" ;;
*) term="${name##*/}" ;;
esac
[ "$version" -ge 4 ] && term="${term^}"
}
# }}}
# Terminal Emulator Font {{{
gettermfont() {
[ -z "$term" ] && getterm
case "$term" in
"urxvt" | "urxvtd" | "xterm")
termfont="$(grep -i "${term/d}\*font" <<< $(xrdb -query))"
termfont="${termfont/*font: }"
# Xresources has two different font syntax, this checks which
# one is in use and formats it accordingly.
case "$termfont" in
"xft:"*)
termfont="${termfont/xft:}"
termfont="${termfont/:*}"
;;
"-"*) termfont="$(awk -F '\\-' '{printf $3}' <<< "$termfont")" ;;
esac
;;
"xfce4-terminal")
termfont="$(awk -F '=' '!/^($|\/\/)/ && /FontName/ {printf $2}' "${XDG_CONFIG_HOME}/xfce4/terminal/terminalrc")"
;;
"termite")
termfont="$(awk -F '= ' '!/^($|#|;)/ && /font/ {printf $2; exit}' "${XDG_CONFIG_HOME}/termite/config")"
;;
"mintty")
termfont="$(awk -F '=' '!/^($|#)/ && /Font/ {printf $2; exit}' "${HOME}/.minttyrc")"
;;
"Apple_Terminal")
termfont="$(osascript -e 'tell application "Terminal" to font name of window frontmost')"
;;
"terminology")
termfont="$(strings ${XDG_CONFIG_HOME}/terminology/config/standard/base.cfg | awk '/^font\.name$/{print a}{a=$0}')"
termfont="${termfont/.pcf}"
termfont="${termfont/:*}"
;;
esac
[ "$version" -ge 4 ] && termfont="${termfont^}"
}
# }}}
# Disk Usage {{{
getdisk() {
# df flags
case "$os" in
"Linux" | "iPhone OS" | "Windows" | "Solaris")
df_flags="-h -l --total"
df_dir="total"
case "$distro" in
"OpenWRT"*) df_flags="-h"; df_dir="rootfs" ;;
esac
;;
"Mac OS X" | "BSD")
case "$distro" in
"FreeBSD"* | *"OS X"* | "Mac"* )
df_flags="-l -H /"
df_dir="/"
;;
*) return ;;
esac
;;
esac
# Get the disk info
disk="$(df $df_flags 2>/dev/null | awk -v dir="$df_dir" '$0 ~ dir {print $2 ":" $3 ":" $5}')"
# Format the output
disk_used="${disk#*:}"
disk_used="${disk_used%%:*}"
disk_total="${disk%%:*}"
disk_total_per="${disk#*:*:}"
# Put it all together
disk="${disk_used} / ${disk_total} (${disk_total_per})"
# Add info bar
disk_used="${disk_used/G}"
disk_total="${disk_total/G}"
# Convert Terabytes to Gigabytes.
if [ "$disk_display" != "off" ]; then
disk_used="${disk_used/\.}"
disk_total="${disk_total/\.}"
[ "${disk_used: -1}" == "T" ] && \
disk_used="$((${disk_used/T} * 100))"
[ "${disk_total: -1}" == "T" ] && \
disk_total="$((${disk_total/T} * 100))"
fi
case "$disk_display" in
"bar") disk="$(bar "${disk_used/'.'*}" "${disk_total/'.'*}")" ;;
"infobar") disk+=" $(bar "${disk_used/'.'*}" "${disk_total/'.'*}")" ;;
"barinfo") disk="$(bar "${disk_used/'.'*}" "${disk_total/'.'*}") $disk" ;;
"perc") disk="$disk_total_per $(bar "${disk_used/'.'*}" "${disk_total/'.'*}")" ;;
esac
}
# }}}
# Battery Usage {{{
getbattery() {
case "$os" in
"Linux")
if [ "$(ls /sys/class/power_supply/)" ]; then
# Set the index to the battery number.
case "$battery_num" in
"all") battery_num="*" index=0 ;;
*) index="$battery_num" ;;
esac
batteries=("$(cat /sys/class/power_supply/BAT$battery_num/capacity)")
battery_state=("$(cat /sys/class/power_supply/BAT${battery_num}/status)")
# Get the subtitle and reassign it so it doesn't change.
title="$subtitle"
# If shorthand is on, print each value on the same line
if [ "$battery_shorthand" == "on" ]; then
battery="${batteries[*]}"
battery="${battery// /%, }"
battery="${battery}%"
else
if [ "${#batteries[@]}" -gt 1 ]; then
unset battery
# Print each battery on a separate line.
for bat in "${batteries[@]}"; do
case "$battery_display" in
"bar") prin "${title}${index:-0}" "$(bar "${bat/'%'}" 100)" ;;
"infobar") prin "${title}${index:-0}" "${bat}% $(bar "${bat/'%'}" 100)" ;;
"barinfo") prin "${title}${index:-0}" "$(bar "${bat/'%'}" 100) ${bat}%" ;;
*) prin "${title}${index:-0}" "${bat}%" ;;
esac
index="$((index+=1))"
done
return
fi
battery="${batteries[0]}%"
fi
fi
;;
"BSD")
case "$distro" in
"FreeBSD"* | "DragonFly"*)
battery="$(acpiconf -i 0 | awk -F ':\t' '/Remaining capacity/ {print $2}')"
battery_state="$(acpiconf -i 0 | awk -F ':\t\t\t' '/State/ {print $2}')"
;;
"NetBSD"*)
battery="$(envstat | awk '\\(|\\)' '/charge:/ {print $2}')"
battery="${battery/\.*/%}"
;;
"OpenBSD"* | "Bitrig"*)
battery0full="$(sysctl -n hw.sensors.acpibat0.watthour0)"
battery0full="${battery0full/ Wh*}"
battery0now="$(sysctl -n hw.sensors.acpibat0.watthour3)"
battery0now="${battery0now/ Wh*}"
[ "$battery0full" ] && \
battery="$((100 * ${battery0now/\.} / ${battery0full/\.}))%"
;;
esac
;;
"Mac OS X")
battery="$(pmset -g batt | grep -o '[0-9]*%')"
battery_state="$(pmset -g batt | awk 'NR==2 {print $3}')"
;;
"Windows")
battery="$(wmic Path Win32_Battery get EstimatedChargeRemaining /value)"
battery="${battery/EstimatedChargeRemaining'='}"
[ "$battery" ] && \
battery+="%"
;;
esac
case "$battery_state" in
"charging"*) battery+=" Charging" ;;
esac
case "$battery_display" in
"bar") battery="$(bar "${battery/'%'*}" 100)" ;;
"infobar") battery="${battery} $(bar "${battery/'%'*}" 100)" ;;
"barinfo") battery="$(bar "${battery/'%'*}" 100) ${battery}" ;;
esac
}
# }}}
# IP Address {{{
getlocalip() {
case "$os" in
"Linux")
localip="$(ip route get 1 | awk '{print $NF;exit}')"
;;
"Mac OS X" | "iPhone OS")
localip="$(ipconfig getifaddr en0)"
[ -z "$localip" ] && localip="$(ipconfig getifaddr en1)"
;;
"BSD" | "Solaris")
localip="$(ifconfig | awk '/broadcast/ {print $2}')"
;;
"Windows")
localip="$(ipconfig | awk -F ': ' '/IPv4 Address/ {printf $2}')"
;;
esac
}
getpublicip() {
if type -p dig >/dev/null 2>&1; then
publicip="$(dig +time=1 +tries=1 +short myip.opendns.com @resolver1.opendns.com 2>/dev/null)"
fi
if [ -z "$publicip" ] && type -p curl >/dev/null 2>&1; then
publicip="$(curl --max-time 10 -w '\n' "$public_ip_host" 2>/dev/null)"
fi
if [ -z "$publicip" ] && type -p wget >/dev/null 2>&1; then
publicip="$(wget -T 10 -qO- "$public_ip_host" 2>/dev/null; printf "%s")"
fi
}
# }}}
# Logged In Users {{{
getusers() {
users="$(who | awk '!seen[$1]++ {printf $1 ", "}')"
users="${users%\,*}"
}
# }}}
# Birthday {{{
getbirthday() {
case "$os" in
"linux" | "iPhone OS")
birthday="$(ls -alct --full-time / | awk '/lost\+found|private/ {printf $6 " " $7}')"
date_cmd="$(date -d"$birthday" "$birthday_format")"
;;
"Mac OS X")
birthday="$(ls -lUT /var/log/install.log | awk '{printf $6 " " $7 " " $9 " " $8}')"
# Split the string into Date + time
time="${birthday/*???? }"
birthday="${birthday/$time}"
case "${time/:*}" in
0? | 10 | 11) time+=" AM" ;;
*) time+=" PM" ;;
esac
birthday+="$time"
birthday_shorthand="on"
;;
"BSD")
case "$distro" in
"OpenBSD"* | "Bitrig"*)
birthday="$(ls -alctT / | awk '/lost\+found/ {printf $6 " " $7 " " $9 " " $8}')"
birthday_shorthand="on"
;;
"FreeBSD"*)
birthday="$(ls -alctT /etc/hostid | awk '{printf $6 " " $7 " " $9 " " $8}')"
date_cmd="$(date -j -f "%b %d %Y" "$birthday" "$birthday_format")"
;;
"NetBSD"* | "DragonFly"*)
birthday="$(ls -alctT /etc/defaults/rc.conf | awk '{printf $6 " " $7 " " $9 " " $8}')"
birthday_shorthand="on"
;;
esac
;;
"Windows")
birthday="$(ls -alct --full-time /cygdrive/c/Windows/explorer.exe | awk '{printf $8 " " $9}')"
date_cmd="$(date -d"$birthday" "$birthday_format")"
;;
"Solaris")
birthday="$(ls -alct --full-time /var/sadm/system/logs/install_log | awk '{printf $6 " " $7}')"
date_cmd="$(date -d"$birthday" "$birthday_format")"
;;
esac
# Strip seconds from time output
birthday="${birthday/:?? / }"
# Pretty output
[ "$birthday_shorthand" == "off" ] && \
birthday="${date_cmd//+( )/ }"
# Toggle showing the time
[ "$birthday_time" == "off" ] && \
birthday="${birthday/??:??*}"
}
# }}}
# Terminal colors {{{
getcols() {
if [ "$color_blocks" == "on" ]; then
# Convert the width to space chars.
block_width="$(printf "%${block_width}s")"
block_width="${block_width// /█}"
# Generate the string.
while [ $start -le $end ]; do
case "$start" in
[0-6]) blocks+="${reset}\033[3${start}m\033[4${start}m${block_width}" ;;
7) blocks+="${reset}\033[3${start}m\033[4${start}m${block_width}" ;;
*) blocks2+="\033[38;5;${start}m\033[48;5;${start}m${block_width}" ;;
esac
start="$((start+=1))"
done
# Convert height into spaces.
spaces="$(printf "%${block_height}s")"
# Convert the spaces into rows of blocks.
[ "$blocks" ] && cols+="${spaces// /${blocks}${reset}nl}"
[ "$blocks2" ] && cols+="${spaces// /${blocks2}${reset}nl}"
# Add newlines to the string.
cols="${cols%%'nl'}"
cols="${cols//nl/\\n${padding}}"
fi
}
# }}}
# }}}
# Images {{{
# Wallpaper {{{
getwallpaper() {
case "$os" in
"Linux" | "BSD")
if type -p feh >/dev/null 2>&1 && [ -f "$HOME/.fehbg" ]; then
img="$(awk -F\' '/feh/ {printf $2}' "$HOME/.fehbg")"
elif type -p nitrogen >/dev/null 2>&1; then
img="$(awk -F'=' '/file/ {printf $2;exit;}' "$XDG_CONFIG_HOME/nitrogen/bg-saved.cfg")"
elif type -p gsettings >/dev/null 2>&1; then
# Get DE if user has disabled the function.
[ -z "$de" ] && getde
case "$de" in
"MATE"*) img="$(gsettings get org.mate.background picture-filename 2>/dev/null)" ;;
*) img="$(gsettings get org.gnome.desktop.background picture-uri 2>/dev/null)" ;;
esac
# Strip quotes etc from the path.
img="${img/'file://'}"
img="${img//\'}"
img="${img//\%20/ }"
fi
;;
"Mac OS X")
img="$(osascript -e 'tell application "System Events" to picture of current desktop')"
;;
"Windows")
case "$distro" in
"Windows XP")
img="/cygdrive/c/Documents and Settings/${USER}"
img+="/Local Settings/Application Data/Microsoft"
img+="/Wallpaper1.bmp"
;;
"Windows"*)
img="$APPDATA/Microsoft/Windows/Themes"
img+="/TranscodedWallpaper.jpg"
;;
esac
;;
esac
# If img is an xml file don't use it.
[ "${img/*\./}" == "xml" ] && img=""
# Error msg
[ -z "$img" ] && err "Wallpaper detection failed, falling back to ascii mode."
}
# }}}
# Ascii {{{
getascii() {
if [ ! -f "$ascii" ] || [ "$ascii" == "distro" ]; then
# Error message
[ "$ascii" != "distro" ] && \
[ ! -f "$ascii" ] && err "Ascii file not found, using distro ascii"
# Lowercase the distro name
if [ "$version" -le 3 ]; then
ascii="$(tr '[:upper:]' '[:lower:]' <<< "$ascii_distro")"
else
ascii="${ascii_distro,,}"
fi
if [ "$ascii_logo_size" == "small" ]; then
ascii="${ascii/ *}_small"
prompt_loc="3"
fi
if [ -f "/usr/share/neofetch/ascii/distro/${ascii/ *}" ]; then
ascii="/usr/share/neofetch/ascii/distro/${ascii/ *}"
elif [ -f "/usr/local/share/neofetch/ascii/distro/${ascii/ *}" ]; then
ascii="/usr/local/share/neofetch/ascii/distro/${ascii/ *}"
else
getscriptdir 2>/dev/null
# If the ascii file doesn't exist fallback to text mode.
if [ ! -f "$script_dir/ascii/distro/${ascii/ *}" ]; then
padding="\033[0C"
image="off"
err "Ascii file not found, falling back to text mode."
return
fi
ascii="$script_dir/ascii/distro/${ascii/ *}"
fi
fi
# Eval colors
print="$(eval printf "$(<"$ascii")")"
# Set locale to get correct padding
export LC_ALL="$SYS_LOCALE"
# Turn the file into a variable and strip escape codes.
ascii_strip="$(<"$ascii")"
ascii_strip="${ascii_strip//\$\{??\}}"
ascii_strip="${ascii_strip//'\\'/ }"
ascii_strip="${ascii_strip//'\'}"
# Get lines/columns of the ascii file in pure bash.
ascii_length=0
lines=1
while IFS='\n' read -r line 2>/dev/null; do
[ ${#line} -gt "$ascii_length" ] && ascii_length=${#line}
lines=$((lines+=1))
done <<< "$ascii_strip"
padding="\033[$((ascii_length + gap))C"
printf "%b%s" "$print"
export LC_ALL=C
}
# }}}
# Image {{{
getimage() {
# Fallback to ascii mode if imagemagick isn't installed.
type -p convert >/dev/null 2>&1 || image="ascii"
case "$image" in
"wall") getwallpaper ;;
"ascii") getascii; return ;;
*)
if [ -d "$image" ]; then
files=("${image%/}"/*.{png,jpg,jpeg})
img="$(printf "%s" "${files[RANDOM % (${#files[@]} - 1)]}")"
else
img="$image"
fi
;;
esac
# Get terminal width and height
if [ -n "$TMUX" ]; then
printf "%b%s" "\033Ptmux;\033\033[14t\033\033[c\033\\"
read_flags="-d c"
elif [ "$image_backend" == "tycat" ]; then
printf "%b%s" "\033}qs\000"
else
printf "%b%s" "\033[14t\033[c"
read_flags="-d c"
fi
# The escape code above prints the output AFTER the prompt so this
builtin read -s -t 1 ${read_flags} -r term_size
# Split the string
if [ "$image_backend" == "tycat" ]; then
term_size=(${term_size//;/ })
term_width="$((term_size[2] * term_size[0]))"
term_height="$((term_size[3] * term_size[1]))"
else
term_size="${term_size//'['}"
term_size="${term_size/';'}"
term_size="${term_size/$'\E4'}"
term_size="${term_size/t*}"
term_height="${term_size/';'*}"
term_width="${term_size/*';'}"
fi
# If $img isn't a file or the terminal doesn't support xterm escape sequences,
# fallback to ascii mode.
if [ ! -f "$img" ] || ([ "${#term_size}" -le 5 ] && [ "$image_backend" != "tycat" ]); then
image="ascii"
getascii
# Error messages
[ ! -f "$img" ] && err "\$img, isn't a file, falling back to ascii mode."
[ "${#term_size}" -le 5 ] && err "Your terminal doesn't support \\\033[14t, falling back to ascii mode."
return
else
clear
fi
# Get terminal lines and columns
term_blocks="$(stty size)"
columns="${term_blocks/* }"
lines="${term_blocks/ *}"
# Calculate font size
font_width="$((term_width / columns))"
font_height="$((term_height / lines))"
# Image size is half of the terminal
case "$image_size" in
"auto")
image_size="$((columns * font_width / 2))"
term_height="$((term_height - term_height / 4))"
[ "$term_height" -lt "$image_size" ] && \
image_size="$term_height"
;;
*"%")
percent="${image_size/\%}"
image_size="$((percent * term_width / 100))"
[ "$((percent * term_height / 50))" -lt "$image_size" ] && \
image_size="$((percent * term_height / 100))"
;;
"none")
# Get image size so that we can do a better crop
size="$(identify -format "%w %h" "$img")"
width="${size%% *}"
height="${size##* }"
crop_mode="none"
;;
*) image_size="${image_size/px}" ;;
esac
# Fallback if width / height are empty.
width="${width:-$image_size}"
height="${height:-$image_size}"
# Padding is half the terminal width + gap
padding="\033[$((width / font_width + gap + xoffset/font_width))C"
# Make the directory if it doesn't exist
mkdir -p "$thumbnail_dir"
# Check to see if the image has a file extension, if it doesn't
# then add one.
case "${img##*/}" in
*"."*) imgname="$crop_mode-$crop_offset-$width-$height-${img##*/}" ;;
*) imgname="$crop_mode-$crop_offset-$width-$height-${img##*/}.jpg" ;;
esac
# Check to see if the thumbnail exists before we do any cropping.
if [ ! -f "$thumbnail_dir/$imgname" ]; then
# Get image size so that we can do a better crop
if [ -z "$size" ]; then
size="$(identify -format "%w %h" "$img")"
og_width="${size%% *}"
og_height="${size##* }"
# This checks to see if height is geater than width
# so we can do a better crop of portrait images.
size="$og_height"
[ "$og_height" -gt "$og_width" ] && size="$og_width"
fi
case "$crop_mode" in
fit)
c="$(convert "$img" \
-colorspace srgb \
-format "%[pixel:p{0,0}]" info:)"
convert \
"$img" \
-trim +repage \
-gravity south \
-background "$c" \
-extent "$size"x"$size" \
-scale "$width"x"$height" \
"$thumbnail_dir/$imgname"
;;
fill)
convert \
"$img" \
-trim +repage \
-scale "$width"x"$height"^ \
-extent "$width"x"$height" \
"$thumbnail_dir/$imgname"
;;
none) cp "$img" "$thumbnail_dir/$imgname" ;;
*)
convert \
"$img" \
-gravity $crop_offset \
-crop "$size"x"$size"+0+0 \
-quality 95 \
-scale "$width"x"$height" \
"$thumbnail_dir/$imgname"
;;
esac
fi
# The final image
img="$thumbnail_dir/$imgname"
}
# }}}
# Find w3m-img {{{
# Find w3mimgdisplay automatically
getw3m_img_path() {
if [ -x "$w3m_img_path" ]; then
return
elif [ -x "/usr/lib/w3m/w3mimgdisplay" ]; then
w3m_img_path="/usr/lib/w3m/w3mimgdisplay"
elif [ -x "/usr/libexec/w3m/w3mimgdisplay" ]; then
w3m_img_path="/usr/libexec/w3m/w3mimgdisplay"
elif [ -x "/usr/lib64/w3m/w3mimgdisplay" ]; then
w3m_img_path="/usr/lib64/w3m/w3mimgdisplay"
elif [ -x "/usr/libexec64/w3m/w3mimgdisplay" ]; then
w3m_img_path="/usr/libexec64/w3m/w3mimgdisplay"
else
image="ascii"
err "w3m-img wasn't found on your system, falling back to ascii mode."
fi
}
# }}}
# Display image {{{
displayimage() {
if [ "$image" != "ascii" ]; then
case "$image_backend" in
"w3m")
# Add a tiny delay to fix issues with images not
# appearing in specific terminal emulators.
sleep 0.05
printf "%b%s\n" "0;1;$xoffset;$yoffset;$width;$height;;;;;$img\n4;\n3;" |\
$w3m_img_path 2>/dev/null || padding="\033[0C"
;;
"iterm2")
printf "%b%s\a\n" "\033]1337;File=width=${width}px;height=${height}px;inline=1:$(base64 < "$img")"
;;
"tycat")
tycat "$img"
;;
esac
fi
}
# }}}
# Get image backend {{{
getimagebackend() {
if [ -n "$ITERM_PROFILE" ]; then
image_backend="iterm2"
elif [ "$(tycat 2>/dev/null)" ]; then
image_backend="tycat"
else
image_backend="w3m"
fi
}
# }}}
# Screenshot {{{
takescrot() {
$scrot_cmd "${scrot_dir}${scrot_name}"
[ "$scrot_upload" == "on" ] && scrot_upload
}
# }}}
# Screenshot Upload {{{
scrot_upload() {
if ! type -p curl >/dev/null 2>&1; then
printf "%s\n" "[!] Install curl to upload images"
return
fi
image_file="${scrot_dir}${scrot_name}"
printf "%s\n" "Uploading image..."
case "$image_host" in
"teknik")
image_url="$(curl -sf -F file="@${image_file}" "https://api.teknik.io/v1/Upload")"
image_url="$(awk -F 'url:|,' '{printf $2}' <<< "${image_url//\"}")"
;;
"imgur")
image_url="$(curl -sH "Authorization: Client-ID $imgur_client_id" -F image="@${image_file}" "https://api.imgur.com/3/upload")"
image_url="$(awk -F 'id:|,' '{printf $2}' <<< "${image_url//\"}")"
[ "$image_url" ] && image_url="https://i.imgur.com/${image_url}.png"
;;
esac
if [ "$image_url" ]; then
printf "%s\n" "$image_url"
else
printf "%s\n" "[!] Image failed to upload"
fi
}
# }}}
# }}}
# Text Formatting {{{
# Info {{{
info() {
# $1 is the subtitle
subtitle="$1"
# Call the function and update variable
if [ -z "$2" ]; then
"get$1" 2>/dev/null
eval output="\$${1}"
else
"get$2" 2>/dev/null
eval output="\$${2}"
fi
# If the output is empty, don't print anything
[ -z "$output" ] && return
# Trim whitespace
output="$(trim "$output")"
case "$1" in
title)
string="${title_color}${bold}${output}"
string="${string/@/${at_color}@${title_color}${bold}}"
length="${#output}"
;;
underline)
string="${underline_color}${output}"
;;
*)
string="${subtitle_color}${bold}${subtitle}${reset}"
string+="${colon_color}: ${info_color}${output}"
length="$((${#subtitle} + ${#output} + 2))"
;;
esac
# If there's no subtitle don't print one
[ -z "$2" ] && string="${string/*: }"
# Print the string
printf "%b%s\n" "${padding}${string}${reset} "
# Calculate info height
info_height="$((info_height+=1))"
# Fix rendering issues with w3m and lines that
# wrap to the next line by adding a max line
# length.
if [ "$image" != "off" ] && [ "$image" != "ascii" ] && [ "$1" != "cols" ]; then
padding_num="${padding/\\033\[}"
output="$(printf "%.$((columns - ${padding_num/C} - gap - ${#subtitle}))s" "$output")"
fi
}
# }}}
# Prin {{{
prin() {
string="$1${2:+: $2}"
# If $2 doesn't exist we format $1 as info
if [ -z "$2" ]; then
subtitle_color="$info_color"
bold=
fi
# Format the output
string="${string/:/${reset}${colon_color}:${info_color}}"
string="${subtitle_color}${bold}${string}"
# Trim whitespace
string="$(trim "$string")"
# Print the info
printf "%b%s\n" "${padding}${string}${reset} "
# Calculate info height
info_height="$((info_height+=1))"
# Fix rendering issues with w3m and lines that
# wrap to the next line by adding a max line
# length.
if [ "$image" != "off" ] && [ "$image" != "ascii" ]; then
padding_num="${padding/\\033\[}"
string="$(printf "%.$((columns - ${padding_num/C} - gap))s" "$string")"
fi
}
# }}}
# Underline {{{
getunderline() {
case "$underline_enabled" in
"on")
underline="$(printf %"$length"s)"
underline="${underline// /$underline_char}"
;;
"off") underline="" ;;
esac
}
# }}}
# Colors {{{
colors() {
# Reset colors/bold
reset="\033[0m"
# Change color of logo based on distro
case "$ascii_distro" in
"Arch"* | "Antergos"*)
setcolors 6 4
;;
"CentOS"*)
setcolors 3 2 4 5 7
;;
"CRUX"* | "Chakra"* | "gNewSense"* | "SailfishOS"* | "Alpine"* | "Ubuntu-GNOME"* | "Qubes"*)
setcolors 4 5 7 6
;;
"Chrom"*)
setcolors 2 1 3 4 7
ascii_distro="chrome"
;;
"Debian"* | "Ubuntu"* | "DragonFly"* | "PacBSD"* | "Oracle"*)
setcolors 1 7 3
;;
"FreeBSD"* | "PCBSD"*)
setcolors 1 7 3
ascii_distro="freebsd"
;;
"Red"*)
setcolors 1 7 3
ascii_distro="redhat"
;;
"Kogaion"* | "Elementary"* | "GalliumOS"* | "Rosa"* | "OpenWrt"*)
setcolors 4 7
;;
"Fedora"* | "Sabayon"* | "Frugalware"* | "Exherbo"*)
setcolors 4 7 1
;;
"Gentoo"* | "Funtoo"* | "SteamOS"* | "Devuan"*)
setcolors 5 7
;;
"KDE"*)
setcolors 2 7
ascii_distro="kde"
;;
"Kali"*)
setcolors 4 8
;;
*"OS X"* | *"iOS"* | "Mac" | *"macOS"*)
setcolors 2 3 1 1 5 4
ascii_distro="mac"
;;
"OpenMandriva"*)
setcolors 4 3
;;
"Mageia"*)
setcolors 6 7
;;
"Peppermint"*)
setcolors 1 7
;;
*"Mint"*)
setcolors 2 7
ascii_distro="mint"
;;
"LMDE"* | "Chapeau"* | "Bitrig"*)
setcolors 2 7
;;
"NetBSD"* | "Parabola"* | "Tails"* | "BLAG"*)
setcolors 5 7
;;
"OpenBSD"* | "GuixSD"*)
setcolors 3 7 6 1 8
;;
"OpenSuse"* | "Manjaro"* | "Deepin"*)
setcolors 2 7
;;
"PCLinuxOS"* | "Slackware"* | "KaOS"* | "Kubuntu"* | "Lubuntu"* | "Xubuntu"* | "OpenIndiana"*)
setcolors 4 7 1
;;
"Puppy"* | "Quirky Werewolf"* | "Precise Puppy"*)
setcolors 4
ascii_distro="puppy"
;;
"Sparky"*)
setcolors 1 7
ascii_distro="sparky"
;;
"Scientific"*)
setcolors 4 1 7
;;
"Solus"*)
setcolors 7 4 0
;;
"Trisquel"* | "NixOS"* | "Zorin"*)
setcolors 4 6
;;
"Travis")
setcolors 1 2 3 4 5 6
;;
"void"*)
setcolors 2 8
;;
"Windows 8"* | "Windows 10"*)
setcolors 6
ascii_distro="windows10"
;;
"Windows"*)
setcolors 1 2 4 3
;;
"Raspbian"* | *)
setcolors 2 1
;;
esac
# Overwrite distro colors if '$ascii_colors' doesn't
# equal 'distro'.
[ "${ascii_colors[0]}" != "distro" ] && \
setcolors ${ascii_colors[@]}
}
setcolors() {
c1="$(color "$1")${ascii_bold}"
c2="$(color "$2")${ascii_bold}"
c3="$(color "$3")${ascii_bold}"
c4="$(color "$4")${ascii_bold}"
c5="$(color "$5")${ascii_bold}"
c6="$(color "$6")${ascii_bold}"
if [ "${colors[0]}" == "distro" ]; then
title_color="$c1"
at_color="$reset"
underline_color="$reset"
subtitle_color="$c2"
colon_color="$reset"
info_color="$reset"
# If the second color is white use the first for the subtitle
[ "$2" == 7 ] && subtitle_color="$(color "$1")"
[ "$1" == 7 ] && title_color="$reset"
else
title_color="$(color "${colors[0]}")"
at_color="$(color "${colors[1]}")"
underline_color="$(color "${colors[2]}")"
subtitle_color="$(color "${colors[3]}")"
colon_color="$(color "${colors[4]}")"
info_color="$(color "${colors[5]}")"
fi
if [ "$progress_color_elapsed" == "distro" ]; then
progress_color_elapsed="$(color fg)"
else
progress_color_elapsed="$(color "$progress_color_elapsed")"
fi
case "$progress_color_total $1" in
distro\ [736]) progress_color_total="$c2" ;;
distro\ [0-9]) progress_color_total="$c1" ;;
*) progress_color_total="$(color "$progress_color_total")" ;;
esac
}
color() {
case "$1" in
[0-7]) printf "%b%s" "${reset}\033[3${1}m" ;;
"fg") printf "%b%s" "$reset" ;;
*) printf "%b%s" "\033[38;5;${1}m" ;;
esac
}
# }}}
# Bold {{{
bold() {
case "$ascii_bold" in
"on") ascii_bold="\033[1m" ;;
"off") ascii_bold="" ;;
esac
case "$bold" in
"on") bold="\033[1m" ;;
"off") bold="" ;;
esac
}
# }}}
# Linebreak {{{
getlinebreak() {
linebreak=" "
}
# }}}
# Trim whitespace {{{
# When a string is passed to 'echo' all trailing and leading
# whitespace is removed and inside the string multiple spaces are
# condensed into single spaces.
#
# The 'set -f/+f' is here so that 'echo' doesn't cause any expansion
# of special characters.
#
# The whitespace trim doesn't work with multiline strings so we use
# '${1//[[:space:]]/ }' to remove newlines beofre we trim the whitespace.
trim() {
set -f
builtin echo -E ${1//[[:space:]]/ }
set +f
}
# }}}
# }}}
# Other {{{
# Error {{{
err() {
err+="$(color 1)[!]\033[0m $1
"
}
# }}}
# Check for old flags {{{
checkoldflags() {
[ -n "$osx_buildversion" ] && err "\$osx_buildversion is deprecated, use \$distro_shorthand instead."
[ -n "$osx_codename" ] && err "\$osx_codename is deprecated, use \$distro_shorthand instead."
}
# }}}
# Get script directory {{{
getscriptdir() {
[ "$script_dir" ] && return
# Use $0 to get the script's physical path.
cd "${0%/*}" || exit
script_dir="${0##*/}"
# Iterate down a (possible) chain of symlinks.
while [ -L "$script_dir" ]; do
script_dir="$(readlink "$script_dir")"
cd "${script_dir%/*}" || exit
script_dir="${script_dir##*/}"
done
# Final directory
script_dir="$(pwd -P)"
}
# }}}
# Source default config {{{
getdefaultconfig() {
if [ -f "/usr/share/neofetch/config" ]; then
default_config="/usr/share/neofetch/config"
elif [ -f "/usr/local/share/neofetch/config" ]; then
default_config="/usr/local/share/neofetch/config"
else
getscriptdir
default_config="${script_dir}/config/config"
fi
if source "$default_config"; then
err "Sourced default config ($default_config)"
else
err "Default config not found, continuing..."
fi
}
# }}}
# Source config {{{
getuserconfig() {
# Check $config_file
if [ -f "$config_file" ]; then
source "$config_file"
err "Sourced user config ($config_file)"
return
fi
mkdir -p "$XDG_CONFIG_HOME/neofetch/"
# Check $XDG_CONFIG_HOME/neofetch and create the
# dir/files if they don't exist.
if [ -f "$XDG_CONFIG_HOME/neofetch/config" ]; then
config_file="$XDG_CONFIG_HOME/neofetch/config"
elif [ -f "/usr/share/neofetch/config" ]; then
cp "/usr/share/neofetch/config" "$XDG_CONFIG_HOME/neofetch"
config_file="$XDG_CONFIG_HOME/neofetch/config"
elif [ -f "/usr/local/share/neofetch/config" ]; then
cp "/usr/local/share/neofetch/config" "$XDG_CONFIG_HOME/neofetch"
config_file="$XDG_CONFIG_HOME/neofetch/config"
else
getscriptdir
cp "$script_dir/config/config" "$XDG_CONFIG_HOME/neofetch"
config_file="$XDG_CONFIG_HOME/neofetch/config"
fi
source "$config_file"
err "Sourced user config ($config_file)"
}
# }}}
# Progress bars {{{
bar() {
# Get the values
elapsed="$(($1 * progress_length / $2))"
# Create the bar with spaces
prog="$(printf %"$elapsed"s)"
total="$(printf %"$((progress_length - elapsed))"s)"
# Set the colors and swap the spaces for $progress_char
bar+="${progress_color_elapsed}${prog// /$progress_char_elapsed}"
bar+="${progress_color_total}${total// /$progress_char_total}"
# Borders
if [ "$progress_border" == "on" ]; then
bar+="$(color fg)]"
bar="$(color fg)[$bar"
fi
printf "%b%s\n" "${bar}${info_color}"
}
# }}}
# Cache {{{
cache() {
mkdir -p "$3/neofetch"
echo "${1/*-}=\"$2\"" > "$3/neofetch/${1/*-}"
}
# }}}
# KDE config directory {{{
kdeconfigdir() {
if [ -n "$KDE_CONFIG_DIR" ]; then
kde_config_dir="$KDE_CONFIG_DIR"
elif type -p kde5-config >/dev/null 2>&1; then
kde_config_dir="$(kde5-config --localprefix)"
elif type -p kde4-config >/dev/null 2>&1; then
kde_config_dir="$(kde4-config --localprefix)"
elif type -p kde-config >/dev/null 2>&1; then
kde_config_dir="$(kde-config --localprefix)"
fi
}
# }}}
# Dynamic prompt location {{{
dynamicprompt() {
# Calculate image height in terminal cells.
# The '+ 4' adds a gap between the prompt and the content.
[ "$image" != "ascii" ] && [ "$image" != "off" ] && \
lines="$((${height:-1} / ${font_height:-1} + 4))"
# If the info is higher than the ascii/image place the prompt
# based on the info height instead of the ascii/image height.
if [ "${lines:-0}" -lt "${info_height:-0}" ]; then
lines="0"
else
lines="$((lines - info_height - 4))"
fi
# Set the prompt location
[ "$image" != "off" ] && printf "\033[${lines/-*/0}B"
# Add some padding if the lines are above 0
if [ "$lines" -gt 0 ]; then
printf "\n\n"
fi
}
# }}}
# Scrot args {{{
scrot_args() {
scrot="on"
case "$2" in
"-"* | "") ;;
*)
scrot_name="${2##*/}"
scrot_dir="${2/$scrot_name}"
;;
esac
}
# }}}
# }}}
# Usage {{{
usage() { cat << EOF
usage: neofetch --option "value" --option "value"
NOTE: There's also a config option for each flag below.
Info:
--disable infoname Allows you to disable an info line from appearing
in the output.
NOTE: You can supply multiple args. eg.
'neofetch --disable cpu gpu disk shell'
--os_arch on/off Hide/Show OS architecture.
--speed_type type Change the type of cpu speed to display.
Possible values: current, min, max, bios,
scaling_current, scaling_min, scaling_max
NOTE: This only support Linux with cpufreq.
--cpu_shorthand type Shorten the output of CPU
Possible values: name, speed, tiny, on, off
--cpu_cores on/off Whether or not to display the number of CPU cores
--distro_shorthand on/off Shorten the output of distro (tiny, on, off)
NOTE: This is only possible on Linux, macOS, and Solaris
--kernel_shorthand on/off Shorten the output of kernel
--uptime_shorthand on/off Shorten the output of uptime (tiny, on, off)
--refresh_rate on/off Whether to display the refresh rate of each monitor
Unsupported on Windows
--gpu_shorthand on/off Shorten the output of GPU (tiny, on, off)
--gpu_brand on/off Enable/Disable GPU brand in output. (AMD/NVIDIA/Intel)
--gtk_shorthand on/off Shorten output of gtk theme/icons
--gtk2 on/off Enable/Disable gtk2 theme/icons output
--gtk3 on/off Enable/Disable gtk3 theme/icons output
--shell_path on/off Enable/Disable showing \$SHELL path
--shell_version on/off Enable/Disable showing \$SHELL version
--battery_num num Which battery to display, default value is 'all'
--battery_shorthand on/off Whether or not each battery gets its own line/title
--ip_host url Url to ping for public IP
--song_shorthand on/off Print the Artist/Title on seperate lines
--birthday_shorthand on/off Shorten the output of birthday
--birthday_time on/off Enable/Disable showing the time in birthday output
--birthday_format format Format the birthday output. (Uses 'date' cmd format)
Text Formatting:
--colors x x x x x x Changes the text colors in this order:
title, @, underline, subtitle, colon, info
--underline on/off enable/disable the underline.
--underline_char char Character to use when underlining title
--bold on/off Enable/Disable bold text
Color Blocks:
--color_blocks on/off Enable/Disable the color blocks
--block_width num Width of color blocks in spaces
--block_height num Height of color blocks in lines
--block_range start end Range of colors to print as blocks
Progress Bars:
--progress_char 'elapsed char' 'total char'
Characters to use when drawing progress bars.
--progress_border on/off Whether or not to surround the bar with '[]'
--progress_length num Length in spaces to make the progress bars.
--progress_colors num num Colors to make the progress bar.
Set in this order: elapsed, total
--cpu_display mode Progress bar mode.
Takes: bar, infobar, barinfo, off
--memory_display mode Progress bar mode.
Takes: bar, infobar, barinfo, off
--battery_display mode Progress bar mode.
Takes: bar, infobar, barinfo, off
--disk_display mode Progress bar mode.
Takes: bar, infobar, barinfo, off
Image:
--image type Image source. Where and what image we display.
Possible values: wall, ascii,
/path/to/img, /path/to/dir/, off
--size 00px | --size 00% How to size the image.
Possible values: auto, 00px, 00%, none
--crop_mode mode Which crop mode to use
Takes the values: normal, fit, fill
--crop_offset value Change the crop offset for normal mode.
Possible values: northwest, north, northeast,
west, center, east, southwest, south, southeast
--xoffset px How close the image will be to the left edge of the
window. This only works with w3m.
--yoffset px How close the image will be to the top edge of the
window. This only works with w3m.
--gap num Gap between image and text.
NOTE: --gap can take a negative value which will
move the text closer to the left side.
--clean Remove all cropped images
Ascii:
--ascii value Where to get the ascii from, Possible values:
distro, /path/to/ascii
--ascii_colors x x x x x x Colors to print the ascii art
--ascii_distro distro Which Distro's ascii art to print
--ascii_logo_size Size of ascii logo.
Supported distros: Arch, Gentoo, Crux, OpenBSD.
--ascii_bold on/off Whether or not to bold the ascii logo.
--logo | -L Hide the info text and only show the ascii logo.
Screenshot:
--scrot | -s /path/to/img Take a screenshot, if path is left empty the screen-
shot function will use \$scrot_dir and \$scrot_name.
--upload | -su /pth/t/img Same as --scrot but uploads the scrot to a website.
--image_host Website to upload scrots to. Takes: imgur, teknik
--scrot_cmd cmd Screenshot program to launch
Other:
--config /path/to/config Specify a path to a custom config file
--config none Launch the script without a config file
--help Print this text and exit
--version Show neofetch version
--test Launch the script with all functions / options enabled.
This should only be used for testing purposes, ie Travis.CI.
-v Display error messages.
-vv Display a verbose log for error reporting.
EOF
exit 1
}
# }}}
# Args {{{
getargs() {
# Check the commandline flags early for '--config none/off'
case "$@" in
*"--config off"* | *'--config "off"'* | *"--config 'off'"* | \
*"--config none"* | *'--config "none"'* | *"--config 'none'"*)
config="off"
;;
*"--config -"*) ;;
*"--config"*) config="off" ;;
esac
[ "${config:-on}" == "on" ] && getuserconfig 2>/dev/null
while [ "$1" ]; do
case $1 in
# Info
--os_arch) os_arch="$2" ;;
--cpu_cores) cpu_cores="$2" ;;
--speed_type) speed_type="$2" ;;
--distro_shorthand) distro_shorthand="$2" ;;
--kernel_shorthand) kernel_shorthand="$2" ;;
--uptime_shorthand) uptime_shorthand="$2" ;;
--cpu_shorthand) cpu_shorthand="$2" ;;
--gpu_shorthand) gpu_shorthand="$2" ;;
--gpu_brand) gpu_brand="$2" ;;
--refresh_rate) refresh_rate="$2" ;;
--gtk_shorthand) gtk_shorthand="$2" ;;
--gtk2) gtk2="$2" ;;
--gtk3) gtk3="$2" ;;
--shell_path) shell_path="$2" ;;
--shell_version) shell_version="$2" ;;
--battery_num) battery_num="$2" ;;
--battery_shorthand) battery_shorthand="$2" ;;
--ip_host) public_ip_host="$2" ;;
--song_shorthand) song_shorthand="$2" ;;
--birthday_shorthand) birthday_shorthand="$2" ;;
--birthday_time) birthday_time="$2" ;;
--birthday_format) birthday_format="$2" ;;
--disable)
for func in "$@"; do
case "$func" in
"--disable") continue ;;
"-"*) return ;;
*) unset -f "get$func" ;;
esac
done
;;
# Text Colors
--colors)
unset colors
for arg in "$2" "$3" "$4" "$5" "$6" "$7"; do
case "$arg" in
"-"*) break ;;
*) colors+=($arg)
esac
done
colors+=(7 7 7 7 7 7)
;;
# Text Formatting
--underline) underline_enabled="$2" ;;
--underline_char) underline_char="$2" ;;
--bold) bold="$2" ;;
# Color Blocks
--color_blocks) color_blocks="$2" ;;
--block_range) start="$2"; end="$3" ;;
--block_width) block_width="$2" ;;
--block_height) block_height="$2" ;;
# Progress Bars
--progress_char)
progress_char_elapsed="$2"
progress_char_total="$3"
;;
--progress_border) progress_border="$2" ;;
--progress_length) progress_length="$2" ;;
--progress_colors)
progress_color_elapsed="$2"
progress_color_total="$3"
;;
--cpu_display) cpu_display="$2" ;;
--memory_display) memory_display="$2" ;;
--battery_display) battery_display="$2" ;;
--disk_display) disk_display="$2" ;;
# Image
--image)
image="$2"
case "$2" in "-"* | "") image="ascii" ;; esac
;;
--image_size | --size) image_size="$2" ;;
--crop_mode) crop_mode="$2" ;;
--crop_offset) crop_offset="$2" ;;
--xoffset) xoffset="$2" ;;
--yoffset) yoffset="$2" ;;
--gap) gap="$2" ;;
--clean)
rm -rf "$thumbnail_dir"
rm -rf "/Library/Caches/neofetch/"
exit
;;
# Ascii
--ascii)
image="ascii"
ascii="$2"
case "$2" in "-"* | "") ascii="distro" ;; esac
;;
--ascii_colors)
unset ascii_colors
for arg in "$2" "$3" "$4" "$5" "$6" "$7"; do
case "$arg" in
"-"*) break ;;
*) ascii_colors+=($arg)
esac
done
ascii_colors+=(7 7 7 7 7 7)
;;
--ascii_distro)
ascii_distro="$2"
case "$2" in "-"* | "") ascii_distro="$distro" ;; esac
;;
--ascii_logo_size) ascii_logo_size="$2" ;;
--ascii_bold) ascii_bold="$2" ;;
--logo | -L)
image="ascii"
printinfo() { info linebreak; }
;;
# Screenshot
--scrot | -s)
scrot_args "$@"
;;
--upload | -su)
scrot_upload="on"
scrot_args "$@"
;;
--image_host) image_host="$2" ;;
--scrot_cmd) scrot_cmd="$2" ;;
# Other
--config)
case "$2" in
"none" | "off") config="off" ;;
*) config_file="$2"; config="on"; getuserconfig 2>/dev/null ;;
esac
;;
--test)
info=(title underline model distro kernel uptime packages shell resolution de wm wmtheme theme icons cpu cpu_usage gpu memory font disk battery song localip publicip users birthday term termfont)
refresh_rate="on"
shell_version="on"
cpu_display="infobar"
memory_display="infobar"
disk_display="infobar"
printinfo() {
if [ "$TRAVIS_OS_NAME" ]; then
info linebreak
info linebreak
fi
for func in "${info[@]}"; do
info "$(tr '[:lower:]' '[:upper:]' <<< "$func")" "$func"
done
info linebreak
info cols
info linebreak
printf "%b%s" "\033[$(tput lines)H"
}
;;
-v) verbose="on" ;;
-vv) set -x; verbose="on" ;;
--help) usage ;;
--version) printf "%s\n" "Neofetch 1.9"; exit ;;
esac
shift
done
}
# }}}
# Call Functions and Finish Up {{{
main() {
getos
getdefaultconfig 2>/dev/null
checkoldflags
getargs "$@"
getdistro
# Get colors and bold
bold
colors
# Restore cursor and clear screen on ctrl+c
trap 'printf "\033[?25h"; clear; exit' 2
# If the script exits for any reason, unhide the cursor.
trap 'printf "\033[?25h"' EXIT
# Hide the cursor and disable line wrap
printf "\033[?25l\033[?7l"
# Display the image
if [ "$image" != "off" ]; then
getimagebackend
# Find w3mimgdisplay
[ "$image_backend" == "w3m" ] && \
[ "$image" != "ascii" ] && \
getw3m_img_path
# Get the image src
getimage
# Display the image if enabled
displayimage
fi
# Set cursor position next to ascii art
printf "\033[$((${lines:-4} - ${prompt_loc:-4}))A"
# Reset horizontal cursor position
printf "\033[9999999D"
# Print the info
printinfo
dynamicprompt
# Re-enable line wrap
printf "%b%s" "\033[?7h"
[ "$scrot" == "on" ] && takescrot
# Show error messages
[ "$verbose" == "on" ] && printf "%b%s" "$err"
# Reset exit status of the tests above
printf "%s"
}
main "$@"
# }}}