Compare commits

..
3 Commits
Author SHA1 Message Date
odweta 489e81282e update: wm 2026-09-27 11:36:52 +02:00
odweta 79b852ff48 update: os birthdate 2026-09-17 20:42:00 +02:00
odweta f3286932b2 fix: fetch height based on INFO_LINES now instead of LOGO_LINES 2026-09-17 20:38:59 +02:00
20 changed files with 202 additions and 376 deletions
+7 -17
View File
@@ -1,19 +1,9 @@
PREFIX ?= /usr/local
BINDIR := $(PREFIX)/bin
LIBDIR := $(PREFIX)/lib/ofetch
.PHONY: install uninstall
DIR := /usr/bin
OUTPUT_FILE_NAME := ofetch
USER := imp
install:
install -d "$(DESTDIR)$(BINDIR)" "$(DESTDIR)$(LIBDIR)/modules"
install -m 644 ofetch.lua "$(DESTDIR)$(LIBDIR)/ofetch.lua"
install -m 644 modules/*.lua "$(DESTDIR)$(LIBDIR)/modules/"
printf '%s\n' '#!/bin/sh' \
'LUA_PATH="$(LIBDIR)/?.lua;;" exec lua "$(LIBDIR)/ofetch.lua" "$$@"' \
> "$(DESTDIR)$(BINDIR)/ofetch"
chmod 755 "$(DESTDIR)$(BINDIR)/ofetch"
uninstall:
rm -f "$(DESTDIR)$(BINDIR)/ofetch"
rm -rf "$(DESTDIR)$(LIBDIR)"
mkdir -p $(DIR)
cp $(OUTPUT_FILE_NAME).sh $(DIR)/$(OUTPUT_FILE_NAME)
chmod 744 $(DIR)/$(OUTPUT_FILE_NAME)
chown $(USER):$(USER) $(DIR)/$(OUTPUT_FILE_NAME)
-10
View File
@@ -1,10 +0,0 @@
local util = require("modules/util")
local function get_system_age()
local install_time = 1793894400 -- Choose your own install time (unix timestamp)
local now = tonumber(util.process_get_one_line("date +%s"))
return util.format_time(now - install_time)
end
return { name = "age", cmd = get_system_age }
-64
View File
@@ -1,64 +0,0 @@
local M = { color = {}, separator = {} }
-- Color definitions (ANSI escape sequences)
M.color.reset = "\27[0m"
M.color.gray = "\27[38;2;102;92;84m"
M.color.cyan = "\27[38;2;125;174;163m"
M.color.white = "\27[38;2;235;219;178m"
M.color.byellow_bold = "\27[1;38;2;250;189;47m"
M.color.bwhite_bold = "\27[1;38;2;235;219;178m"
M.color.dimyellow_italic = "\27[3;38;2;215;153;33m"
M.color.aqua = "\27[38;2;142;192;124m"
-- Info field colors
M.color.info_name = M.color.cyan
M.color.info_value = M.color.dimyellow_italic
-- Horizontal separator color (under username @ hostname)
M.color.horizontal_separator = M.color.dimyellow_italic
-- User and hostname definitions for the header
M.user = require("modules/user").user
M.hostname = require("modules/hostname").hostname
-- Separator of the logo and the info fields
M.separator.logo_char = " | "
M.separator.logo = M.color.gray ..
M.separator.logo_char .. M.color.reset
-- Separator of the info name and value
M.separator.info_char = " : "
M.separator.info = M.color.dimyellow_italic ..
M.separator.info_char .. M.color.reset
-- Horizontal separator under the heading
M.separator.horizontal_char = "-"
M.separator.horizontal = M.color.dimyellow_italic ..
string.rep(
M.separator.horizontal_char,
(#M.user + #M.hostname + 3)
) .. M.color.reset
-- Logo definition
M.logo = {
" ",
M.color.cyan .. " /\\ /\\ ",
M.color.cyan .. " // \\ \\ ",
M.color.cyan .. " // \\ \\ ",
M.color.cyan .. " /// \\ \\ ",
M.color.cyan .. " // \\ \\",
M.color.cyan .. " \\ ",
" "
}
return M
-16
View File
@@ -1,16 +0,0 @@
local util = require("modules/util")
-- CPU modelname
local function get_cpu_modelname()
local name = util.grep("/proc/cpuinfo", "^model name%s*:%s*(.+)") or
util.grep("/proc/cpuinfo", "^Hardware%s*:%s*(.+)")
-- Shorter modelname for Intel i3/i5/i7/i9 CPUs
if name then
name = name:match("([iI][3579]%-[%d]+[A-Za-z]*)") or name
end
return name
end
return { name = "cpu", cmd = get_cpu_modelname }
-7
View File
@@ -1,7 +0,0 @@
local util = require("modules/util")
local function get_distro()
return util.grep("/etc/os-release", "%s*NAME%s*=%s*\"(.*)\"")
end
return { name = "distro", cmd = get_distro }
-5
View File
@@ -1,5 +0,0 @@
-- Reads /etc/hostname and returns the first line
local util = require("modules/util")
return { hostname = os.getenv("HOSTNAME") or util.cat_first_line("/etc/hostname") }
-7
View File
@@ -1,7 +0,0 @@
local util = require("modules/util")
local function get_system_kernel()
return util.cat_first_line("/proc/sys/kernel/osrelease")
end
return { name = "kernel", cmd = get_system_kernel }
-11
View File
@@ -1,11 +0,0 @@
local util = require("modules/util")
local function get_num_installed_pkgs()
local distros = {}
distros.alpine = "apk list --installed | wc -l"
-- Choose and/or add your own distro
return util.process_get_one_line(distros.alpine)
end
return { name = "pkgs", cmd = get_num_installed_pkgs }
-29
View File
@@ -1,29 +0,0 @@
local util = require("modules/util")
-- RAM amount in GB
local function get_ram_gb()
local free, total, avail
util.for_line_in_file("/proc/meminfo", function(line)
local total_match = line:match("^MemTotal%s*:%s*(.+)%s*[kK][bB]")
local avail_match = line:match("^MemAvailable%s*:%s*(.+)%s*[kK][bB]")
if total_match then
total = tonumber(total_match)
end
if avail_match then
avail = tonumber(avail_match)
end
if total and avail then
free = string.format("%.1f GB", (total - avail) / 1000000)
end
return free ~= nil
end)
return free
end
return { name = "ram", cmd = get_ram_gb }
-6
View File
@@ -1,6 +0,0 @@
local function get_current_shell()
local shell = os.getenv("SHELL") or "unknown"
return shell:match("([^/]*)$")
end
return { name = "shell", cmd = get_current_shell }
-43
View File
@@ -1,43 +0,0 @@
local M = { }
local util = require("modules/util")
function M.modules(modules, config_)
local config = config_ or require("modules/config")
local info_name_padding_amount = util.longest_info_name_length(modules)
M.header =
config.logo[1] .. config.separator.logo ..
config.color.cyan .. config.user ..
config.color.gray .. " @ " ..
config.color.white .. config.hostname
-- Optional plus above the info separator
-- config.separator.horizontal = string.rep("-", info_name_padding_amount + 1) ..
-- "+" .. string.rep("-", ((#config.user + 1 + #config.hostname) - info_name_padding_amount))
M.horizontal_separator =
config.logo[2] .. config.separator.logo .. config.separator.horizontal
print(M.header)
print(M.horizontal_separator)
for i, info in ipairs(modules) do
print(
(config.logo[i+2] or "[! OUT OF LOGO !]") ..
config.separator.logo ..
config.color.cyan .. info.name ..
string.rep(" ", (info_name_padding_amount - #info.name)) ..
config.color.dimyellow_italic ..
config.separator.info ..
config.color.dimyellow_italic ..
info.cmd() ..
config.color.reset
)
end
end
return M
-5
View File
@@ -1,5 +0,0 @@
local function get_current_terminal()
return os.getenv("TERM") or "unknown"
end
return { name = "term", cmd = get_current_terminal }
-12
View File
@@ -1,12 +0,0 @@
local util = require("modules/util")
local function get_current_gtk_theme()
local theme = util.grep(
(os.getenv("HOME") or "~") .. "/.config/gtk-4.0/settings.ini",
"^gtk%-theme%-name%s*=%s*(.*)"
) or "unknown"
return theme:gsub("%-", " ")
end
return { name = "theme", cmd = get_current_gtk_theme }
-7
View File
@@ -1,7 +0,0 @@
local util = require("modules/util")
local function get_system_uptime()
return util.format_time(tonumber(util.grep("/proc/uptime", "^(%S+)")))
end
return { name = "uptime", cmd = get_system_uptime }
-1
View File
@@ -1 +0,0 @@
return { user = os.getenv("USER") }
-95
View File
@@ -1,95 +0,0 @@
local M = {}
-- Helper functions
function M.format_time(time)
local seconds = time
local days = math.floor(seconds / 86400)
local hours = math.floor(seconds % 86400 / 3600)
local minutes = math.floor(seconds % 3600 / 60)
local result = ""
if days > 0 then
result = result .. days .. "d "
end
if hours > 0 then
result = result .. hours .. "h "
end
if minutes > 0 then
result = result .. minutes .. "m"
end
return result
end
-- Capture the first line of an invoked system process
-- (discards of error messages of the last command (the
-- one after the last pipe ('|')))
function M.process_get_one_line(proc)
local pipe = io.popen(proc .. " 2>/dev/null", "r")
if not pipe then return nil end
local data = pipe:read("*l")
pipe:close()
return data
end
-- Get the lenght of the longest info name (for padding)
function M.longest_info_name_length(modules)
local longest = 0
for _, mod in ipairs(modules) do
if type(mod.name) == "string" and #mod.name > longest then
longest = #mod.name
end
end
return longest
end
--[[
-- Loop through a file and for each line perform
-- a callback function, if it returns true, the
-- loop can end prematurely (this is wanted)
--]]
function M.for_line_in_file(filename, callback)
local file = io.open(filename, "r")
if not file then return nil end
for line in file:lines() do
if callback(line) then
file:close()
return true
end
end
file:close()
return false
end
-- filter a file line-by-line and return the given match
function M.grep(filename, regex)
local capture
M.for_line_in_file(filename, function(line)
capture = line:match(regex)
return capture ~= nil
end)
return capture
end
-- Returns the contents of the first line in a file
function M.cat_first_line(filename)
local file = io.open(filename, "r")
if not file then return nil end
local line = file:read("*l")
file:close()
return line
end
return M
-11
View File
@@ -1,11 +0,0 @@
local function get_current_wm()
if os.getenv("SWAYSOCK") then
return "sway"
elseif os.getenv("HYPRLAND_INSTANCE_SIGNATURE") then
return "hyprland"
else
return "unknown"
end
end
return { name = "wm", cmd = get_current_wm }
-30
View File
@@ -1,30 +0,0 @@
#!/usr/bin/lua
local config = require("modules/config")
local show = require("modules/show")
-- Optionally override config defaults like the logo and separator appearance
-- e.g.: to change the separator character from the default to ' / '
-- config.separator.logo_char = " / "
-- config.separator.logo = config.color.gray ..
-- config.separator.logo_char .. config.color.reset
-- Put your desired modules in the table below
local modules = {
require("modules/distro"),
require("modules/theme"),
require("modules/age"),
require("modules/pkgs"),
require("modules/wm"),
require("modules/terminal"),
-- require("modules/cpu"),
-- require("modules/ram"),
-- require("modules/uptime"),
-- require("modules/kernel"),
-- require("modules/shell"),
}
-- Show the logo and fields
show.modules(modules, config)
Executable
+107
View File
@@ -0,0 +1,107 @@
#!/bin/bash
# color definitions
C_RESET=$'\e[0m'
C_GRAY=$'\e[90m'
C_CYAN=$'\e[36m'
C_WHITE=$'\e[97m'
C_BYELLOW_BOLD=$'\e[1;93m'
C_BWHITE_BOLD=$'\e[1;97m'
C_DIMYELLOW_ITALIC=$'\e[3;93m'
# logo definition
LOGO_ARCH=" $C_GRAY/$C_RESET
$C_CYAN /\\ $C_GRAY/$C_RESET
$C_CYAN / \\ $C_GRAY/$C_RESET
$C_CYAN / \\ $C_GRAY/$C_RESET
$C_CYAN / \\ $C_GRAY/$C_RESET
$C_CYAN / ,, \\ $C_GRAY/$C_RESET
$C_CYAN / | | \\ $C_GRAY/$C_RESET
$C_CYAN /_-'' ''-_\\ $C_GRAY/$C_RESET
$C_GRAY/$C_RESET"
LOGO_DEVUAN=" $C_GRAY/$C_RESET
$C_CYAN ..:::. $C_GRAY/$C_RESET
$C_CYAN ..-==- $C_GRAY/$C_RESET
$C_CYAN .+#: $C_GRAY/$C_RESET
$C_CYAN =@@ $C_GRAY/$C_RESET
$C_CYAN :+%@#: $C_GRAY/$C_RESET
$C_CYAN .:=+#@@%*: $C_GRAY/$C_RESET
$C_CYAN #@@@#=: $C_GRAY/$C_RESET
$C_GRAY/$C_RESET"
LOGO=" $C_GRAY/$C_RESET
$C_CYAN _____ $C_GRAY/$C_RESET
$C_CYAN / __ \\ $C_GRAY/$C_RESET
$C_CYAN | / | $C_GRAY/$C_RESET
$C_CYAN | \\___- $C_GRAY/$C_RESET
$C_CYAN -_ $C_GRAY/$C_RESET
$C_CYAN --_ $C_GRAY/$C_RESET
$C_GRAY/$C_RESET
$C_GRAY/$C_RESET"
LOGO_GENTOO=" $C_GRAY/$C_RESET
$C_WHITE _-----_ $C_GRAY/$C_RESET
$C_WHITE ( \ $C_GRAY/$C_RESET
$C_WHITE \ 0 \ $C_GRAY/$C_RESET
$C_WHITE \ ) $C_GRAY/$C_RESET
$C_WHITE / _/ $C_GRAY/$C_RESET
$C_WHITE ( _- $C_GRAY/$C_RESET
$C_WHITE \____- $C_GRAY/$C_RESET
$C_GRAY/$C_RESET"
# all the info fields
USER=$USER
HOSTNAME=$(cat /etc/hostname)
CPU_MODELNAME=$(cat /proc/cpuinfo | awk -F ":" '/model name/ {print $2}' | awk -F " " '{print $3}' | head -1)
CPU_THREADS_NUM=$(nproc)
RAM_TOTAL=$(awk '/MemTotal:/ { printf "%.1f\n", $2 / 1000000 }' /proc/meminfo)
RAM_FREE=$(awk '/MemAvailable:/ { printf "%.1f\n", $2 / 1000000 }' /proc/meminfo)
RAM="$(awk -v total="${RAM_TOTAL}" -v free="${RAM_FREE}" 'BEGIN { print (total - free) }') G / ${RAM_TOTAL} G"
installed="Tue Aug 18 17:45:01 2026"
installed_ts=$(date -d "$installed" +%s)
now_ts=$(date +%s)
diff=$((now_ts - installed_ts))
TIME_SINCE_LAST_REINSTALL=$(d=$(( $(date +%s) - $(date -d 'Thu Sep 17 18:18:15 2026' +%s) )); printf '%d days, %d hours, %d minutes, %d seconds\n' $((d/86400)) $((d%86400/3600)) $((d%3600/60)) $((d%60))
)
UPTIME=$(awk '{ s=int($1); printf "%d days, %d hours, %d minutes, %d seconds\n", s/86400, (s%86400)/3600, (s%3600)/60, (s%60) }' /proc/uptime)
KERNEL=$(uname -r)
WM="dwm"
TERM=$TERM
SHELL=$(echo -n $SHELL | awk -F "/" '{print $NF}')
horizontal_n=$((${#USER} + ${#HOSTNAME} + 3))
horizontal_separator_char="-"
HORIZONTAL_SEPARATOR=$(printf '%*s' "$horizontal_n" ' ' | tr ' ' "$horizontal_separator_char")
# -----
# output login
# convert the logo into an array of "lines" (strings)
mapfile -t LOGO_LINES <<< "$LOGO"
# array of strings as well for the info fields
INFO_LINES=(
"${C_BYELLOW_BOLD}$USER${C_BWHITE_BOLD} @ ${C_BYELLOW_BOLD}$HOSTNAME${C_RESET}"
${C_GRAY}$HORIZONTAL_SEPARATOR${C_RESET}
"${C_CYAN}cpu ${C_DIMYELLOW_ITALIC} : $CPU_MODELNAME ($CPU_THREADS_NUM threads)${C_RESET}"
"${C_CYAN}ram ${C_DIMYELLOW_ITALIC} : $RAM${C_RESET}"
"${C_CYAN}age ${C_DIMYELLOW_ITALIC} : $TIME_SINCE_LAST_REINSTALL${C_RESET}"
"${C_CYAN}uptime${C_DIMYELLOW_ITALIC} : $UPTIME${C_RESET}"
"${C_CYAN}kernel${C_DIMYELLOW_ITALIC} : $KERNEL${C_RESET}"
"${C_CYAN}wm ${C_DIMYELLOW_ITALIC} : $WM${C_RESET}"
"${C_CYAN}term ${C_DIMYELLOW_ITALIC} : $TERM${C_RESET}"
)
#for i in "${!LOGO_LINES[@]}"; do
for i in "${!INFO_LINES[@]}"; do
# 15 chars is the length of the logo
printf "%-15s" "${LOGO_LINES[$i]}"
# only print info if it exists for this line
[ $i -lt ${#INFO_LINES[@]} ] && printf " %s" "${INFO_LINES[$i]}"
printf "\n"
done
printf "${C_RESET}"
+88
View File
@@ -0,0 +1,88 @@
#!/bin/bash
# color definitions
C_RESET=$'\e[0m'
C_GRAY=$'\e[90m'
C_CYAN=$'\e[36m'
C_WHITE=$'\e[97m'
C_BYELLOW_BOLD=$'\e[1;93m'
C_BWHITE_BOLD=$'\e[1;97m'
C_DIMYELLOW_ITALIC=$'\e[3;93m'
# logo definition
LOGO=" $C_GRAY/$C_RESET
$C_CYAN /\\ $C_GRAY/$C_RESET
$C_CYAN / \\ $C_GRAY/$C_RESET
$C_CYAN / \\ $C_GRAY/$C_RESET
$C_CYAN / \\ $C_GRAY/$C_RESET
$C_CYAN / ,, \\ $C_GRAY/$C_RESET
$C_CYAN / | | \\ $C_GRAY/$C_RESET
$C_CYAN /_-'' ''-_\\ $C_GRAY/$C_RESET
$C_GRAY/$C_RESET"
LOGO_GENTOO=" $C_GRAY/$C_RESET
$C_WHITE _-----_ $C_GRAY/$C_RESET
$C_WHITE ( \ $C_GRAY/$C_RESET
$C_WHITE \ 0 \ $C_GRAY/$C_RESET
$C_WHITE \ ) $C_GRAY/$C_RESET
$C_WHITE / _/ $C_GRAY/$C_RESET
$C_WHITE ( _- $C_GRAY/$C_RESET
$C_WHITE \____- $C_GRAY/$C_RESET
$C_GRAY/$C_RESET"
# all the info fields
USER=$USER
HOSTNAME=$(cat /etc/hostname)
CPU_MODELNAME=$(cat /proc/cpuinfo | awk -F ":" '/model name/ {print $2}' | awk -F " " '{print $3}' | head -1)
CPU_THREADS_NUM=$(nproc)
RAM_TOTAL=$(awk '/MemTotal:/ { printf "%.1f\n", $2 / 1000000 }' /proc/meminfo)
RAM_FREE=$(awk '/MemAvailable:/ { printf "%.1f\n", $2 / 1000000 }' /proc/meminfo)
RAM="$(awk -v total="${RAM_TOTAL}" -v free="${RAM_FREE}" 'BEGIN { print (total - free) }') G / ${RAM_TOTAL} G"
installed="Tue Aug 18 17:45:01 2026"
installed_ts=$(date -d "$installed" +%s)
now_ts=$(date +%s)
diff=$((now_ts - installed_ts))
TIME_SINCE_LAST_REINSTALL=$(d=$(( $(date +%s) - $(date -d 'Tue Aug 18 17:45:01 2026' +%s) )); printf '%d days, %02d hours, %02d minutes, %02d seconds\n' $((d/86400)) $((d%86400/3600)) $((d%3600/60)) $((d%60))
)
UPTIME=$(awk '{ s=int($1); printf "%dd %dh %dm\n", s/86400, (s%86400)/3600, (s%3600)/60 }' /proc/uptime)
KERNEL=$(uname -r)
WM="xfwm"
TERM=$TERM
SHELL=$(echo -n $SHELL | awk -F "/" '{print $NF}')
horizontal_n=$((${#USER} + ${#HOSTNAME} + 3))
horizontal_separator_char="-"
HORIZONTAL_SEPARATOR=$(printf '%*s' "$horizontal_n" ' ' | tr ' ' "$horizontal_separator_char")
# -----
# output login
# convert the logo into an array of "lines" (strings)
mapfile -t LOGO_LINES <<< "$LOGO"
# array of strings as well for the info fields
INFO_LINES=(
"${C_BYELLOW_BOLD}$USER${C_BWHITE_BOLD} @ ${C_BYELLOW_BOLD}$HOSTNAME${C_RESET}"
${C_GRAY}$HORIZONTAL_SEPARATOR${C_RESET}
"${C_CYAN}${C_DIMYELLOW_ITALIC} : $CPU_MODELNAME ($CPU_THREADS_NUM threads)${C_RESET}"
"${C_CYAN}${C_DIMYELLOW_ITALIC} : $RAM${C_RESET}"
#"GPU: $GPU"
"${C_CYAN}${C_DIMYELLOW_ITALIC} : $UPTIME${C_RESET}"
"${C_CYAN}${C_DIMYELLOW_ITALIC} : $KERNEL${C_RESET}"
"${C_CYAN}${C_DIMYELLOW_ITALIC} : $WM${C_RESET}"
"${C_CYAN}${C_DIMYELLOW_ITALIC} : $TERM${C_RESET}"
"${C_CYAN}${C_DIMYELLOW_ITALIC} : $SHELL${C_RESET}"
)
for i in "${!LOGO_LINES[@]}"; do
# 15 chars is the length of the logo
printf "%-15s" "${LOGO_LINES[$i]}"
# only print info if it exists for this line
[ $i -lt ${#INFO_LINES[@]} ] && printf " %s" "${INFO_LINES[$i]}"
printf "\n"
done
printf "${C_RESET}"