Сап.Думаю, все слышали, что разработку Neofetch свернули. Да и честно говоря, он всегда меня бесил своей скоростью. Это же Bash, он под капотом спамит кучей процессов типа grep, awk и cut, чтобы просто узнать версию ядра или загрузку памяти. На старом железе это заметно тупит.Есть Fastfetch на C, он летает, но тащить бинарники и компилировать под каждую машину мне лень. Мне хотелось чего-то гибкого, скриптового, но чтобы работало так же быстро, как C.В итоге я выбрал LuaJIT. Многие забывают, что это не просто скрипты для игр. У него есть киллер-фича — FFI. По сути, я могу прямо из скрипта дергать функции ядра Linux и читать структуры памяти, минуя всякие медленные парсеры текста.Короче, написал свою утилиту. Работает моментально, весит копейки, выглядит как классика.Чтобы было красиво и поддерживаемо, завернул всё в нормальный OOP. Никакой лапши, всё по классам.Стек:* LuaJIT (для скорости и FFI)* Linux Kernel API (sysinfo, uname)Собственно, код (сохранять как luafetch.lua):
Установка:Всё тривиально. Ставим LuaJIT (он есть везде), кидаем скрипт в bin и даем права.
Теперь просто пишем luafetch в терминале.Для тех, кто сидит на Kali или любом другом Debian-based, подсчет пакетов будет моментальным, потому что я читаю напрямую файл базы dpkg, а не вызываю команду.Как вам такой подход? Если есть идеи, что еще можно вытащить через FFI — пишите.
Спойлер: Исходный код (LuaJIT)
Code:
#!/usr/bin/env luajitlocal ffi = require("ffi")ffi.cdef[[ struct utsname { char sysname[65]; char nodename[65]; char release[65]; char version[65]; char machine[65]; char domainname[65]; }; int uname(struct utsname *buf); struct sysinfo { long uptime; unsigned long loads[3]; unsigned long totalram; unsigned long freeram; unsigned long sharedram; unsigned long bufferram; unsigned long totalswap; unsigned long freeswap; unsigned short procs; unsigned long totalhigh; unsigned long freehigh; unsigned int mem_unit; char _f[20-2*sizeof(long)-sizeof(int)]; }; int sysinfo(struct sysinfo *info); char *getlogin(void);]]local System = {}System.__index = Systemfunction System.new() local self = setmetatable({}, System) self.uts = ffi.new("struct utsname") self.info = ffi.new("struct sysinfo") ffi.C.uname(self.uts) ffi.C.sysinfo(self.info) return selfendfunction System:get_user_host() local user = "root" local u_ptr = ffi.C.getlogin() if u_ptr ~= nil then user = ffi.string(u_ptr) end local host = ffi.string(self.uts.nodename) return user, hostendfunction System:get_os_arch() local distro = "Linux" local f = io.open("/etc/os-release", "r") if f then local c = f:read("*a") f:close() distro = c:match('PRETTY_NAME="(.-)"') or "Linux" end return distro .. " " .. ffi.string(self.uts.machine)endfunction System:get_kernel() return ffi.string(self.uts.release)endfunction System:get_uptime() local up = tonumber(self.info.uptime) local h = math.floor(up / 3600) local m = math.floor((up % 3600) / 60) return string.format("%d hours, %d mins", h, m)endfunction System:get_ram() local function to_mb(b, u) return math.floor((tonumber(b) * tonumber(u)) / 1048576) end local total = to_mb(self.info.totalram, self.info.mem_unit) local free = to_mb(self.info.freeram, self.info.mem_unit) return string.format("%dMiB / %dMiB", total - free, total)endfunction System:get_pkgs() local f = io.open("/var/lib/dpkg/status", "r") if not f then return "0 (nix)" end local count = 0 while true do local chunk = f:read(1048576) if not chunk then break end local _, n = chunk:gsub("Package: ", "") count = count + n end f:close() return count .. " (dpkg)"endfunction System:get_cpu() local f = io.open("/proc/cpuinfo", "r") if not f then return "Unknown" end for line in f:lines() do if line:match("^model name") then f:close() local name = line:match(": (.+)") return name:gsub("Intel%(R%) Core%(TM%) ", ""):gsub("CPU ", ""):gsub("AMD Ryzen ", "Ryzen ") end end f:close() return "Unknown"endfunction System:get_shell() local s = os.getenv("SHELL") or "/bin/sh" return s:match("^.+/(.+)$")endfunction System:get_wm() local wm = os.getenv("XDG_CURRENT_DESKTOP") or os.getenv("DESKTOP_SESSION") return wm and wm:upper() or "TTY"endlocal Display = {}Display.__index = Displayfunction Display.new(sys) local self = setmetatable({}, Display) self.sys = sys self.colors = { reset = "\27[0m", bold = "\27[1m", blue = "\27[34m", white = "\27[37m" } self.art = { [[. ]], [[ / , / ]], [[ ,/' /`' ]], [[ /(/`' _ ]], [[ f'/) ,-' ]], [[ / ,' itz ]], [[ f,/ / ]], [[ /" 7 ]], [[ / ,f / ]], [[ ) / / |J ]], [[ 7,( ;|j ]], [[ , (. "`/ (' ]], [[ ` )`-'/ l ` ]], [[ ( ( ) ' ' (_,' ) ]], [[ ( ,) 7` / /, (, ( ]], [[ , ) (,- `-' / (, -') ( ]], [[ (_ ( `-_(,_,'_(_(__ )_, _`-_, _ ]], [[ ]], [[ KALI LINUX ]] } return selfendfunction Display:render() local user, host = self.sys:get_user_host() local c = self.colors local header = string.format("%s%s@%s%s", user, c.reset, c.blue, host) local sep = string.rep("-", #user + #host + 1) local info = { string.format("%s%s%s%s%s", c.bold, c.blue, header, c.reset, c.bold), sep, self:fmt("OS", self.sys:get_os_arch()), self:fmt("Host", host), self:fmt("Kernel", self.sys:get_kernel()), self:fmt("Uptime", self.sys:get_uptime()), self:fmt("Packages", self.sys:get_pkgs()), self:fmt("Shell", self.sys:get_shell()), self:fmt("WM", self.sys:get_wm()), self:fmt("CPU", self.sys:get_cpu()), self:fmt("Memory", self.sys:get_ram()) } print("") for i = 1, math.max(#self.art, #info) do local a = self.art[i] or "" local pad = string.rep(" ", math.max(0, 38 - #a)) local l = info[i] or "" io.write(string.format(" %s%s%s%s%s %s\n", c.bold, c.blue, a, pad, c.reset, l)) end print("") self:draw_palette()endfunction Display:fmt(k, v) local c = self.colors return string.format("%s%s%s%s: %s%s", c.blue, c.bold, k, c.reset, c.white, v)endfunction Display:draw_palette() local function row(base) io.write(string.rep(" ", 42)) for i = 0, 7 do io.write(string.format("\27[%dm ", base + i)) end io.write(self.colors.reset .. "\n") end row(40) row(100) print("")endlocal sys = System.new()local app = Display.new(sys)app:render()
Code:
sudo apt install luajitsudo mv luafetch.lua /usr/local/bin/luafetchsudo chmod +x /usr/local/bin/luafetch
👍41
❤️7
🔥6
🤔7
😢9
LIMB