diff options
| author | Wayne-Cole <77279425+Wacky404@users.noreply.github.com> | 2024-07-30 00:37:33 -0500 |
|---|---|---|
| committer | Wayne-Cole <77279425+Wacky404@users.noreply.github.com> | 2024-07-30 00:37:33 -0500 |
| commit | 1769ac995d65d33893eadab3185d9a5b0e7d2af8 (patch) | |
| tree | 6f294db6421bc59f0771815433fd8df1dc54884a | |
| parent | 87ea211cb78f95b63ed4a0cef38110cd544631e5 (diff) | |
| download | wackys-dev-env-1769ac995d65d33893eadab3185d9a5b0e7d2af8.tar.xz wackys-dev-env-1769ac995d65d33893eadab3185d9a5b0e7d2af8.zip | |
chore: file update
40 files changed, 2292 insertions, 2 deletions
diff --git a/.config/nvim/init.lua b/.config/nvim/init.lua index 1e046e8..b12b9b7 100644 --- a/.config/nvim/init.lua +++ b/.config/nvim/init.lua @@ -17,3 +17,4 @@ require("cole.plugins.gitsigns") require("cole.plugins.formatter") require("cole.plugins.vimtex-setup") require("cole.plugins.linter-setup") +require("cole.plugins.dadbod-setup") diff --git a/.config/nvim/lua/cole/plugins-setup.lua b/.config/nvim/lua/cole/plugins-setup.lua index fd54dab..5284389 100644 --- a/.config/nvim/lua/cole/plugins-setup.lua +++ b/.config/nvim/lua/cole/plugins-setup.lua @@ -105,6 +105,26 @@ return packer.startup(function(use) end, }) + -- dadbod for Databases + use({ + "kristijanhusak/vim-dadbod-ui", + requires = { 'tpope/vim-dadbod' }, + dependencies = { + { 'kristijanhusak/vim-dadbod-completion', + ft = { 'sql' }, + cmd = { + 'DBUI', + 'DBUIToggle', + 'DBUIAddConnection', + 'DBUIFindBuffer', + }, + config = function() + -- place my small config changes here + vim.g.db_ui_use_nerd_fonts = 1 + end, + } }, + }) + -- auto closing use("windwp/nvim-autopairs") -- autoclose parens, brackets, quotes, etc... use({ "windwp/nvim-ts-autotag", after = "nvim-treesitter" }) -- autoclose tags diff --git a/.config/nvim/lua/cole/plugins/dadbod-setup.lua b/.config/nvim/lua/cole/plugins/dadbod-setup.lua new file mode 100644 index 0000000..7af9cd5 --- /dev/null +++ b/.config/nvim/lua/cole/plugins/dadbod-setup.lua @@ -0,0 +1,7 @@ +local status, db_ui = pcall(require, "dadbod-ui") +if not status then + return +end + +vim.g.db_ui_variable_prefix = 'DB_' + diff --git a/.config/nvim/plugin/packer_compiled.lua b/.config/nvim/plugin/packer_compiled.lua index e2c5b83..6410ebb 100644 --- a/.config/nvim/plugin/packer_compiled.lua +++ b/.config/nvim/plugin/packer_compiled.lua @@ -224,7 +224,7 @@ _G.packer_plugins = { url = "https://github.com/nvim-telescope/telescope.nvim" }, ["toggleterm.nvim"] = { - config = { "\27LJ\2\nf\0\0\3\0\4\0\a6\0\0\0'\2\1\0B\0\2\0029\0\2\0005\2\3\0B\0\2\1K\0\1\0\1\0\3\14direction\15horizontal\tsize\3\15\14autochdir\1\nsetup\15toggleterm\frequire\0" }, + config = { "\27LJ\2\nf\0\0\3\0\4\0\a6\0\0\0'\2\1\0B\0\2\0029\0\2\0005\2\3\0B\0\2\1K\0\1\0\1\0\3\tsize\3\15\14autochdir\1\14direction\15horizontal\nsetup\15toggleterm\frequire\0" }, loaded = true, path = "/Users/cole/.local/share/nvim/site/pack/packer/start/toggleterm.nvim", url = "https://github.com/akinsho/toggleterm.nvim" @@ -239,6 +239,16 @@ _G.packer_plugins = { path = "/Users/cole/.local/share/nvim/site/pack/packer/start/vim-ReplaceWithRegister", url = "https://github.com/inkarkat/vim-ReplaceWithRegister" }, + ["vim-dadbod"] = { + loaded = true, + path = "/Users/cole/.local/share/nvim/site/pack/packer/start/vim-dadbod", + url = "https://github.com/tpope/vim-dadbod" + }, + ["vim-dadbod-ui"] = { + loaded = true, + path = "/Users/cole/.local/share/nvim/site/pack/packer/start/vim-dadbod-ui", + url = "https://github.com/kristijanhusak/vim-dadbod-ui" + }, ["vim-maximizer"] = { loaded = true, path = "/Users/cole/.local/share/nvim/site/pack/packer/start/vim-maximizer", @@ -268,7 +278,7 @@ try_loadstring("\27LJ\2\n=\0\0\2\0\4\0\0056\0\0\0009\0\1\0005\1\3\0=\1\2\0K\0\1\ time([[Setup for markdown-preview.nvim]], false) -- Config for: toggleterm.nvim time([[Config for toggleterm.nvim]], true) -try_loadstring("\27LJ\2\nf\0\0\3\0\4\0\a6\0\0\0'\2\1\0B\0\2\0029\0\2\0005\2\3\0B\0\2\1K\0\1\0\1\0\3\14direction\15horizontal\tsize\3\15\14autochdir\1\nsetup\15toggleterm\frequire\0", "config", "toggleterm.nvim") +try_loadstring("\27LJ\2\nf\0\0\3\0\4\0\a6\0\0\0'\2\1\0B\0\2\0029\0\2\0005\2\3\0B\0\2\1K\0\1\0\1\0\3\tsize\3\15\14autochdir\1\14direction\15horizontal\nsetup\15toggleterm\frequire\0", "config", "toggleterm.nvim") time([[Config for toggleterm.nvim]], false) -- Load plugins in order defined by `after` time([[Sequenced loading]], true) diff --git a/.config/sketchybar/bar.lua b/.config/sketchybar/bar.lua new file mode 100644 index 0000000..659ccae --- /dev/null +++ b/.config/sketchybar/bar.lua @@ -0,0 +1,11 @@ +local colors = require("colors") + +-- Equivalent to the --bar domain +sbar.bar({ + topmost = "window", + height = 40, + -- changes the whole bar color + color = colors.transparent, + padding_right = 2, + padding_left = 2, +}) diff --git a/.config/sketchybar/colors.lua b/.config/sketchybar/colors.lua new file mode 100644 index 0000000..a664cfa --- /dev/null +++ b/.config/sketchybar/colors.lua @@ -0,0 +1,35 @@ +return { + -- in hex + black = 0xff181819, + white = 0xffe2e2e3, + red = 0xfffc5d7c, + blood = 0xFF8A0303, + green = 0xff9ed072, + blue = 0xff76cce0, + cog_blue = 0xff6a97b8, + yellow = 0xffe7c664, + orange = 0xfff39660, + orange_brown = 0xffC46210, + magenta = 0xffb39df3, + grey = 0xff7f8490, + pink = 0xffffc0cb, + transparent = 0x00000000, + + bar = { + bg = 0xf02c2e34, + border = 0xff2c2e34, + }, + popup = { + bg = 0xc02c2e34, + border = 0xff7f8490, + }, + bg1 = 0xff363944, + bg2 = 0xff414550, + + with_alpha = function(color, alpha) + if alpha > 1.0 or alpha < 0.0 then + return color + end + return (color & 0x00ffffff) | (math.floor(alpha * 255.0) << 24) + end, +} diff --git a/.config/sketchybar/default.lua b/.config/sketchybar/default.lua new file mode 100644 index 0000000..aec37a4 --- /dev/null +++ b/.config/sketchybar/default.lua @@ -0,0 +1,58 @@ +local settings = require("settings") +local colors = require("colors") +local sbar = require("sketchybar") + +-- Equivalent to the --default domain +sbar.default({ + updates = "when_shown", + icon = { + font = { + family = settings.font.text, + style = settings.font.style_map["Bold"], + size = 14.0, + }, + -- changed the applel logo & cpu + color = settings.apple_icon, + padding_left = settings.paddings, + padding_right = settings.paddings, + background = { image = { corner_radius = 9 } }, + }, + label = { + font = { + family = settings.font.text, + style = settings.font.style_map["Semibold"], + size = 13.0, + }, + -- text color for widgets + color = colors.white, + padding_left = settings.paddings, + padding_right = settings.paddings, + }, + background = { + height = 28, + corner_radius = 9, + border_width = 2, + -- changes border color for widgets + border_color = settings.widget_borders, + image = { + corner_radius = 9, + border_color = colors.grey, + border_width = 1, + }, + }, + popup = { + background = { + border_width = 2, + corner_radius = 9, + -- colors.popup.border + border_color = colors.popup.border, + -- colors.popup.bg + color = colors.popup.bg, + shadow = { drawing = true }, + }, + blur_radius = 50, + }, + padding_left = 5, + padding_right = 5, + scroll_texts = true, +}) diff --git a/.config/sketchybar/helpers/.gitignore b/.config/sketchybar/helpers/.gitignore new file mode 100644 index 0000000..ba077a4 --- /dev/null +++ b/.config/sketchybar/helpers/.gitignore @@ -0,0 +1 @@ +bin diff --git a/.config/sketchybar/helpers/app_icons.lua b/.config/sketchybar/helpers/app_icons.lua new file mode 100644 index 0000000..3487782 --- /dev/null +++ b/.config/sketchybar/helpers/app_icons.lua @@ -0,0 +1,210 @@ +return { + ["Typora"] = ":text:", + ["Orion"] = ":orion:", + ["Orion RC"] = ":orion:", + ["Grammarly Editor"] = ":grammarly:", + ["kitty"] = ":kitty:", + ["ClickUp"] = ":click_up:", + ["Iris"] = ":iris:", + ["PomoDone App"] = ":pomodone:", + ["qutebrowser"] = ":qute_browser:", + ["Raindrop.io"] = ":raindrop_io:", + ["Airmail"] = ":airmail:", + ["Affinity Publisher 2"] = ":affinity_publisher_2:", + ["Calendar"] = ":calendar:", + ["日历"] = ":calendar:", + ["Fantastical"] = ":calendar:", + ["Cron"] = ":calendar:", + ["Amie"] = ":calendar:", + ["Figma"] = ":figma:", + ["Element"] = ":element:", + ["Signal"] = ":signal:", + ["Mattermost"] = ":mattermost:", + ["Caprine"] = ":caprine:", + ["Microsoft To Do"] = ":things:", + ["Things"] = ":things:", + ["Godot"] = ":godot:", + ["Android Messages"] = ":android_messages:", + ["Zed"] = ":zed:", + ["Anytype"] = ":anytype:", + ["TeamSpeak 3"] = ":team_speak:", + ["LibreWolf"] = ":libre_wolf:", + ["neovide"] = ":neovide:", + ["Spotlight"] = ":spotlight:", + ["微信"] = ":wechat:", + ["Dropbox"] = ":dropbox:", + ["Transmit"] = ":transmit:", + ["TickTick"] = ":tick_tick:", + ["Parallels Desktop"] = ":parallels:", + ["Audacity"] = ":audacity:", + ["Rider"] = ":rider:", + ["JetBrains Rider"] = ":rider:", + ["DEVONthink 3"] = ":devonthink3:", + ["Docker"] = ":docker:", + ["Docker Desktop"] = ":docker:", + ["Matlab"] = ":matlab:", + ["VLC"] = ":vlc:", + ["Alacritty"] = ":alacritty:", + ["Pages"] = ":pages:", + ["Pages 文稿"] = ":pages:", + ["Bear"] = ":bear:", + ["Pine"] = ":pine:", + ["Affinity Designer 2"] = ":affinity_designer_2:", + ["Keyboard Maestro"] = ":keyboard_maestro:", + ["Joplin"] = ":joplin:", + ["mpv"] = ":mpv:", + ["zoom.us"] = ":zoom:", + ["Affinity Photo 2"] = ":affinity_photo_2:", + ["Music"] = ":music:", + ["音乐"] = ":music:", + ["League of Legends"] = ":league_of_legends:", + ["Tor Browser"] = ":tor_browser:", + ["Hyper"] = ":hyper:", + ["WhatsApp"] = ":whats_app:", + ["카카오톡"] = ":kakaotalk:", + ["Discord"] = ":discord:", + ["Discord Canary"] = ":discord:", + ["Discord PTB"] = ":discord:", + ["Neovide"] = ":vim:", + ["MacVim"] = ":vim:", + ["Vim"] = ":vim:", + ["VimR"] = ":vim:", + ["Keynote"] = ":keynote:", + ["Keynote 讲演"] = ":keynote:", + ["iTerm"] = ":iterm:", + ["IntelliJ IDEA"] = ":idea:", + ["Finder"] = ":finder:", + ["访达"] = ":finder:", + ["Xcode"] = ":xcode:", + ["GoLand"] = ":goland:", + ["Android Studio"] = ":android_studio:", + ["MoneyMoney"] = ":bank:", + ["Spotify"] = ":spotify:", + ["KeePassXC"] = ":kee_pass_x_c:", + ["Alfred"] = ":alfred:", + ["Color Picker"] = ":color_picker:", + ["数码测色计"] = ":color_picker:", + ["Microsoft Word"] = ":microsoft_word:", + ["Microsoft PowerPoint"] = ":microsoft_power_point:", + ["Notes"] = ":notes:", + ["备忘录"] = ":notes:", + ["Microsoft Edge"] = ":microsoft_edge:", + ["Sublime Text"] = ":sublime_text:", + ["Sequel Ace"] = ":sequel_ace:", + ["Folx"] = ":folx:", + ["DingTalk"] = ":dingtalk:", + ["钉钉"] = ":dingtalk:", + ["阿里钉"] = ":dingtalk:", + ["WebStorm"] = ":web_storm:", + ["Sequel Pro"] = ":sequel_pro:", + ["Skype"] = ":skype:", + ["网易云音乐"] = ":netease_music:", + ["PyCharm"] = ":pycharm:", + ["Canary Mail"] = ":mail:", + ["HEY"] = ":mail:", + ["Mail"] = ":mail:", + ["Mailspring"] = ":mail:", + ["MailMate"] = ":mail:", + ["邮件"] = ":mail:", + ["Default"] = ":default:", + ["App Store"] = ":app_store:", + ["Calibre"] = ":book:", + ["Todoist"] = ":todoist:", + ["Emacs"] = ":emacs:", + ["Messenger"] = ":messenger:", + ["Tower"] = ":tower:", + ["VSCodium"] = ":vscodium:", + ["Drafts"] = ":drafts:", + ["Cypress"] = ":cypress:", + ["GitHub Desktop"] = ":git_hub:", + ["Telegram"] = ":telegram:", + ["Firefox Developer Edition"] = ":firefox_developer_edition:", + ["Firefox Nightly"] = ":firefox_developer_edition:", + ["Min"] = ":min_browser:", + ["Sketch"] = ":sketch:", + ["Affinity Photo"] = ":affinity_photo:", + ["MAMP"] = ":mamp:", + ["MAMP PRO"] = ":mamp:", + ["Insomnia"] = ":insomnia:", + ["Bitwarden"] = ":bit_warden:", + ["Warp"] = ":warp:", + ["System Preferences"] = ":gear:", + ["System Settings"] = ":gear:", + ["系统设置"] = ":gear:", + ["Affinity Designer"] = ":affinity_designer:", + ["Live"] = ":ableton:", + ["Arc"] = ":arc:", + ["Chromium"] = ":google_chrome:", + ["Google Chrome"] = ":google_chrome:", + ["Google Chrome Canary"] = ":google_chrome:", + ["Jellyfin Media Player"] = ":jellyfin:", + ["Zulip"] = ":zulip:", + ["1Password"] = ":one_password:", + ["FaceTime"] = ":face_time:", + ["FaceTime 通话"] = ":face_time:", + ["Citrix Workspace"] = ":citrix:", + ["Citrix Viewer"] = ":citrix:", + ["Logseq"] = ":logseq:", + ["Reeder"] = ":reeder5:", + ["Code"] = ":code:", + ["Code - Insiders"] = ":code:", + ["Notion"] = ":notion:", + ["Final Cut Pro"] = ":final_cut_pro:", + ["Zotero"] = ":zotero:", + ["Safari"] = ":safari:", + ["Safari浏览器"] = ":safari:", + ["Safari Technology Preview"] = ":safari:", + ["Blender"] = ":blender:", + ["Affinity Publisher"] = ":affinity_publisher:", + ["Spark Desktop"] = ":spark:", + ["Zeplin"] = ":zeplin:", + ["Replit"] = ":replit:", + ["Podcasts"] = ":podcasts:", + ["播客"] = ":podcasts:", + ["NordVPN"] = ":nord_vpn:", + ["Notability"] = ":notability:", + ["Numbers"] = ":numbers:", + ["Numbers 表格"] = ":numbers:", + ["Nova"] = ":nova:", + ["Microsoft Excel"] = ":microsoft_excel:", + ["Trello"] = ":trello:", + ["Pi-hole Remote"] = ":pihole:", + ["Linear"] = ":linear:", + ["CleanMyMac X"] = ":desktop:", + ["GrandTotal"] = ":dollar:", + ["Receipts"] = ":dollar:", + ["Evernote Legacy"] = ":evernote_legacy:", + ["OmniFocus"] = ":omni_focus:", + ["Terminal"] = ":terminal:", + ["终端"] = ":terminal:", + ["Atom"] = ":atom:", + ["Kakoune"] = ":kakoune:", + ["Reminders"] = ":reminders:", + ["提醒事项"] = ":reminders:", + ["Tana"] = ":tana:", + ["OBS"] = ":obsstudio:", + ["VMware Fusion"] = ":vmware_fusion:", + ["Tweetbot"] = ":twitter:", + ["Twitter"] = ":twitter:", + ["Microsoft Teams"] = ":microsoft_teams:", + ["Yuque"] = ":yuque:", + ["语雀"] = ":yuque:", + ["Slack"] = ":slack:", + ["Vivaldi"] = ":vivaldi:", + ["Setapp"] = ":setapp:", + ["TIDAL"] = ":tidal:", + ["Miro"] = ":miro:", + ["Messages"] = ":messages:", + ["信息"] = ":messages:", + ["Nachrichten"] = ":messages:", + ["Brave Browser"] = ":brave_browser:", + ["Preview"] = ":pdf:", + ["预览"] = ":pdf:", + ["Skim"] = ":pdf:", + ["zathura"] = ":pdf:", + ["Obsidian"] = ":obsidian:", + ["Thunderbird"] = ":thunderbird:", + ["Firefox"] = ":firefox:", + ["WezTerm"] = ":wezterm:", + ["default"] = ":default:", +} diff --git a/.config/sketchybar/helpers/default_font.lua b/.config/sketchybar/helpers/default_font.lua new file mode 100644 index 0000000..fb1f16e --- /dev/null +++ b/.config/sketchybar/helpers/default_font.lua @@ -0,0 +1,13 @@ +return { + text = "SF Pro", -- Used for text + numbers = "SF Mono", -- Used for numbers + + -- Unified font style map + style_map = { + ["Regular"] = "Regular", + ["Semibold"] = "Semibold", + ["Bold"] = "Bold", + ["Heavy"] = "Heavy", + ["Black"] = "Black", + } +} diff --git a/.config/sketchybar/helpers/event_providers/cpu_load/cpu.h b/.config/sketchybar/helpers/event_providers/cpu_load/cpu.h new file mode 100644 index 0000000..413f70f --- /dev/null +++ b/.config/sketchybar/helpers/event_providers/cpu_load/cpu.h @@ -0,0 +1,58 @@ +#include <mach/mach.h> +#include <stdbool.h> +#include <unistd.h> +#include <stdio.h> + +struct cpu { + host_t host; + mach_msg_type_number_t count; + host_cpu_load_info_data_t load; + host_cpu_load_info_data_t prev_load; + bool has_prev_load; + + int user_load; + int sys_load; + int total_load; +}; + +static inline void cpu_init(struct cpu* cpu) { + cpu->host = mach_host_self(); + cpu->count = HOST_CPU_LOAD_INFO_COUNT; + cpu->has_prev_load = false; +} + +static inline void cpu_update(struct cpu* cpu) { + kern_return_t error = host_statistics(cpu->host, + HOST_CPU_LOAD_INFO, + (host_info_t)&cpu->load, + &cpu->count ); + + if (error != KERN_SUCCESS) { + printf("Error: Could not read cpu host statistics.\n"); + return; + } + + if (cpu->has_prev_load) { + uint32_t delta_user = cpu->load.cpu_ticks[CPU_STATE_USER] + - cpu->prev_load.cpu_ticks[CPU_STATE_USER]; + + uint32_t delta_system = cpu->load.cpu_ticks[CPU_STATE_SYSTEM] + - cpu->prev_load.cpu_ticks[CPU_STATE_SYSTEM]; + + uint32_t delta_idle = cpu->load.cpu_ticks[CPU_STATE_IDLE] + - cpu->prev_load.cpu_ticks[CPU_STATE_IDLE]; + + cpu->user_load = (double)delta_user / (double)(delta_system + + delta_user + + delta_idle) * 100.0; + + cpu->sys_load = (double)delta_system / (double)(delta_system + + delta_user + + delta_idle) * 100.0; + + cpu->total_load = cpu->user_load + cpu->sys_load; + } + + cpu->prev_load = cpu->load; + cpu->has_prev_load = true; +} diff --git a/.config/sketchybar/helpers/event_providers/cpu_load/cpu_load.c b/.config/sketchybar/helpers/event_providers/cpu_load/cpu_load.c new file mode 100644 index 0000000..ee97613 --- /dev/null +++ b/.config/sketchybar/helpers/event_providers/cpu_load/cpu_load.c @@ -0,0 +1,41 @@ +#include "cpu.h" +#include "../sketchybar.h" + +int main (int argc, char** argv) { + float update_freq; + if (argc < 3 || (sscanf(argv[2], "%f", &update_freq) != 1)) { + printf("Usage: %s \"<event-name>\" \"<event_freq>\"\n", argv[0]); + exit(1); + } + + alarm(0); + struct cpu cpu; + cpu_init(&cpu); + + // Setup the event in sketchybar + char event_message[512]; + snprintf(event_message, 512, "--add event '%s'", argv[1]); + sketchybar(event_message); + + char trigger_message[512]; + for (;;) { + // Acquire new info + cpu_update(&cpu); + + // Prepare the event message + snprintf(trigger_message, + 512, + "--trigger '%s' user_load='%d' sys_load='%02d' total_load='%02d'", + argv[1], + cpu.user_load, + cpu.sys_load, + cpu.total_load ); + + // Trigger the event + sketchybar(trigger_message); + + // Wait + usleep(update_freq * 1000000); + } + return 0; +} diff --git a/.config/sketchybar/helpers/event_providers/cpu_load/makefile b/.config/sketchybar/helpers/event_providers/cpu_load/makefile new file mode 100644 index 0000000..6366a0f --- /dev/null +++ b/.config/sketchybar/helpers/event_providers/cpu_load/makefile @@ -0,0 +1,5 @@ +bin/cpu_load: cpu_load.c cpu.h ../sketchybar.h | bin + clang -std=c99 -O3 $< -o $@ + +bin: + mkdir bin diff --git a/.config/sketchybar/helpers/event_providers/makefile b/.config/sketchybar/helpers/event_providers/makefile new file mode 100644 index 0000000..8c1ca39 --- /dev/null +++ b/.config/sketchybar/helpers/event_providers/makefile @@ -0,0 +1,3 @@ +all: + (cd cpu_load && $(MAKE)) + (cd network_load && $(MAKE)) diff --git a/.config/sketchybar/helpers/event_providers/network_load/makefile b/.config/sketchybar/helpers/event_providers/network_load/makefile new file mode 100644 index 0000000..e464482 --- /dev/null +++ b/.config/sketchybar/helpers/event_providers/network_load/makefile @@ -0,0 +1,5 @@ +bin/network_load: network_load.c network.h ../sketchybar.h | bin + clang -std=c99 -O3 $< -o $@ + +bin: + mkdir bin diff --git a/.config/sketchybar/helpers/event_providers/network_load/network.h b/.config/sketchybar/helpers/event_providers/network_load/network.h new file mode 100644 index 0000000..25175e5 --- /dev/null +++ b/.config/sketchybar/helpers/event_providers/network_load/network.h @@ -0,0 +1,90 @@ +#include <math.h> +#include <stdio.h> +#include <string.h> +#include <net/if.h> +#include <net/if_mib.h> +#include <sys/select.h> +#include <sys/sysctl.h> + +static char unit_str[3][6] = { { " Bps" }, { "KBps" }, { "MBps" }, }; + +enum unit { + UNIT_BPS, + UNIT_KBPS, + UNIT_MBPS +}; +struct network { + uint32_t row; + struct ifmibdata data; + struct timeval tv_nm1, tv_n, tv_delta; + + int up; + int down; + enum unit up_unit, down_unit; +}; + +static inline void ifdata(uint32_t net_row, struct ifmibdata* data) { + static size_t size = sizeof(struct ifmibdata); + static int32_t data_option[] = { CTL_NET, PF_LINK, NETLINK_GENERIC, IFMIB_IFDATA, 0, IFDATA_GENERAL }; + data_option[4] = net_row; + sysctl(data_option, 6, data, &size, NULL, 0); +} + +static inline void network_init(struct network* net, char* ifname) { + memset(net, 0, sizeof(struct network)); + + static int count_option[] = { CTL_NET, PF_LINK, NETLINK_GENERIC, IFMIB_SYSTEM, IFMIB_IFCOUNT }; + uint32_t interface_count = 0; + size_t size = sizeof(uint32_t); + sysctl(count_option, 5, &interface_count, &size, NULL, 0); + + for (int i = 0; i < interface_count; i++) { + ifdata(i, &net->data); + if (strcmp(net->data.ifmd_name, ifname) == 0) { + net->row = i; + break; + } + } +} + +static inline void network_update(struct network* net) { + gettimeofday(&net->tv_n, NULL); + timersub(&net->tv_n, &net->tv_nm1, &net->tv_delta); + net->tv_nm1 = net->tv_n; + + uint64_t ibytes_nm1 = net->data.ifmd_data.ifi_ibytes; + uint64_t obytes_nm1 = net->data.ifmd_data.ifi_obytes; + ifdata(net->row, &net->data); + + double time_scale = (net->tv_delta.tv_sec + 1e-6*net->tv_delta.tv_usec); + if (time_scale < 1e-6 || time_scale > 1e2) return; + double delta_ibytes = (double)(net->data.ifmd_data.ifi_ibytes - ibytes_nm1) + / time_scale; + double delta_obytes = (double)(net->data.ifmd_data.ifi_obytes - obytes_nm1) + / time_scale; + + double exponent_ibytes = log10(delta_ibytes); + double exponent_obytes = log10(delta_obytes); + + if (exponent_ibytes < 3) { + net->down_unit = UNIT_BPS; + net->down = delta_ibytes; + } else if (exponent_ibytes < 6) { + net->down_unit = UNIT_KBPS; + net->down = delta_ibytes / 1000.0; + } else if (exponent_ibytes < 9) { + net->down_unit = UNIT_MBPS; + net->down = delta_ibytes / 1000000.0; + } + + if (exponent_obytes < 3) { + net->up_unit = UNIT_BPS; + net->up = delta_obytes; + } else if (exponent_obytes < 6) { + net->up_unit = UNIT_KBPS; + net->up = delta_obytes / 1000.0; + } else if (exponent_obytes < 9) { + net->up_unit = UNIT_MBPS; + net->up = delta_obytes / 1000000.0; + } +} diff --git a/.config/sketchybar/helpers/event_providers/network_load/network_load.c b/.config/sketchybar/helpers/event_providers/network_load/network_load.c new file mode 100644 index 0000000..06afe95 --- /dev/null +++ b/.config/sketchybar/helpers/event_providers/network_load/network_load.c @@ -0,0 +1,42 @@ +#include <unistd.h> +#include "network.h" +#include "../sketchybar.h" + +int main (int argc, char** argv) { + float update_freq; + if (argc < 4 || (sscanf(argv[3], "%f", &update_freq) != 1)) { + printf("Usage: %s \"<interface>\" \"<event-name>\" \"<event_freq>\"\n", argv[0]); + exit(1); + } + + alarm(0); + // Setup the event in sketchybar + char event_message[512]; + snprintf(event_message, 512, "--add event '%s'", argv[2]); + sketchybar(event_message); + + struct network network; + network_init(&network, argv[1]); + char trigger_message[512]; + for (;;) { + // Acquire new info + network_update(&network); + + // Prepare the event message + snprintf(trigger_message, + 512, + "--trigger '%s' upload='%03d%s' download='%03d%s'", + argv[2], + network.up, + unit_str[network.up_unit], + network.down, + unit_str[network.down_unit]); + + // Trigger the event + sketchybar(trigger_message); + + // Wait + usleep(update_freq * 1000000); + } + return 0; +} diff --git a/.config/sketchybar/helpers/event_providers/sketchybar.h b/.config/sketchybar/helpers/event_providers/sketchybar.h new file mode 100644 index 0000000..b194d8a --- /dev/null +++ b/.config/sketchybar/helpers/event_providers/sketchybar.h @@ -0,0 +1,124 @@ +#pragma once + +#include <bootstrap.h> +#include <mach/arm/kern_return.h> +#include <mach/mach.h> +#include <mach/mach_port.h> +#include <mach/message.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> + +typedef char *env; + +#define MACH_HANDLER(name) void name(env env) +typedef MACH_HANDLER(mach_handler); + +struct mach_message { + mach_msg_header_t header; + mach_msg_size_t msgh_descriptor_count; + mach_msg_ool_descriptor_t descriptor; +}; + +struct mach_buffer { + struct mach_message message; + mach_msg_trailer_t trailer; +}; + +static mach_port_t g_mach_port = 0; + +static inline mach_port_t mach_get_bs_port() { + mach_port_name_t task = mach_task_self(); + + mach_port_t bs_port; + if (task_get_special_port(task, TASK_BOOTSTRAP_PORT, &bs_port) != + KERN_SUCCESS) { + return 0; + } + + char *name = getenv("BAR_NAME"); + if (!name) + name = "sketchybar"; + uint32_t lookup_len = 16 + strlen(name); + + char buffer[lookup_len]; + snprintf(buffer, lookup_len, "git.felix.%s", name); + + mach_port_t port; + if (bootstrap_look_up(bs_port, buffer, &port) != KERN_SUCCESS) + return 0; + return port; +} + +static inline bool mach_send_message(mach_port_t port, char *message, + uint32_t len) { + if (!message || !port) { + return false; + } + + struct mach_message msg = {0}; + msg.header.msgh_remote_port = port; + msg.header.msgh_local_port = 0; + msg.header.msgh_id = 0; + msg.header.msgh_bits = + MACH_MSGH_BITS_SET(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND, 0, + MACH_MSGH_BITS_COMPLEX); + + msg.header.msgh_size = sizeof(struct mach_message); + msg.msgh_descriptor_count = 1; + msg.descriptor.address = message; + msg.descriptor.size = len * sizeof(char); + msg.descriptor.copy = MACH_MSG_VIRTUAL_COPY; + msg.descriptor.deallocate = false; + msg.descriptor.type = MACH_MSG_OOL_DESCRIPTOR; + + kern_return_t err = + mach_msg(&msg.header, MACH_SEND_MSG, sizeof(struct mach_message), 0, + MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + + return err == KERN_SUCCESS; +} + +static inline uint32_t format_message(char *message, char *formatted_message) { + // This is not actually robust, switch to stack based messaging. + char outer_quote = 0; + uint32_t caret = 0; + uint32_t message_length = strlen(message) + 1; + for (int i = 0; i < message_length; ++i) { + if (message[i] == '"' || message[i] == '\'') { + if (outer_quote && outer_quote == message[i]) + outer_quote = 0; + else if (!outer_quote) + outer_quote = message[i]; + continue; + } + formatted_message[caret] = message[i]; + if (message[i] == ' ' && !outer_quote) + formatted_message[caret] = '\0'; + caret++; + } + + if (caret > 0 && formatted_message[caret] == '\0' && + formatted_message[caret - 1] == '\0') { + caret--; + } + formatted_message[caret] = '\0'; + return caret + 1; +} + +static inline void sketchybar(char *message) { + char formatted_message[strlen(message) + 2]; + uint32_t length = format_message(message, formatted_message); + if (!length) + return; + + if (!g_mach_port) + g_mach_port = mach_get_bs_port(); + if (!mach_send_message(g_mach_port, formatted_message, length)) { + g_mach_port = mach_get_bs_port(); + if (!mach_send_message(g_mach_port, formatted_message, length)) { + // No sketchybar instance running, exit. + exit(0); + } + } +} diff --git a/.config/sketchybar/helpers/init.lua b/.config/sketchybar/helpers/init.lua new file mode 100644 index 0000000..351531a --- /dev/null +++ b/.config/sketchybar/helpers/init.lua @@ -0,0 +1,4 @@ +-- Add the sketchybar module to the package cpath +package.cpath = package.cpath .. ";/Users/" .. os.getenv("USER") .. "/.local/share/sketchybar_lua/?.so" + +os.execute("(cd helpers && make)") diff --git a/.config/sketchybar/helpers/install.sh b/.config/sketchybar/helpers/install.sh new file mode 100755 index 0000000..cdde4ad --- /dev/null +++ b/.config/sketchybar/helpers/install.sh @@ -0,0 +1,17 @@ +# Packages +brew install lua +brew install switchaudio-osx +brew install nowplaying-cli + +brew tap FelixKratz/formulae +brew install sketchybar + +# Fonts +brew install --cask sf-symbols +brew install --cask homebrew/cask-fonts/font-sf-mono +brew install --cask homebrew/cask-fonts/font-sf-pro + +curl -L https://github.com/kvndrsslr/sketchybar-app-font/releases/download/v2.0.5/sketchybar-app-font.ttf -o $HOME/Library/Fonts/sketchybar-app-font.ttf + +# SbarLua +(git clone https://github.com/FelixKratz/SbarLua.git /tmp/SbarLua && cd /tmp/SbarLua/ && make install && rm -rf /tmp/SbarLua/) diff --git a/.config/sketchybar/helpers/makefile b/.config/sketchybar/helpers/makefile new file mode 100644 index 0000000..3246108 --- /dev/null +++ b/.config/sketchybar/helpers/makefile @@ -0,0 +1,3 @@ +all: + (cd event_providers && $(MAKE)) >/dev/null + (cd menus && $(MAKE)) >/dev/null diff --git a/.config/sketchybar/helpers/menus/makefile b/.config/sketchybar/helpers/menus/makefile new file mode 100644 index 0000000..0cb454e --- /dev/null +++ b/.config/sketchybar/helpers/menus/makefile @@ -0,0 +1,5 @@ +bin/menus: menus.c | bin + clang -std=c99 -O3 -F/System/Library/PrivateFrameworks/ -framework Carbon -framework SkyLight $< -o $@ + +bin: + mkdir bin diff --git a/.config/sketchybar/helpers/menus/menus.c b/.config/sketchybar/helpers/menus/menus.c new file mode 100644 index 0000000..2e77822 --- /dev/null +++ b/.config/sketchybar/helpers/menus/menus.c @@ -0,0 +1,248 @@ +#include <Carbon/Carbon.h> + +void ax_init() { + const void *keys[] = { kAXTrustedCheckOptionPrompt }; + const void *values[] = { kCFBooleanTrue }; + + CFDictionaryRef options; + options = CFDictionaryCreate(kCFAllocatorDefault, + keys, + values, + sizeof(keys) / sizeof(*keys), + &kCFCopyStringDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks ); + + bool trusted = AXIsProcessTrustedWithOptions(options); + CFRelease(options); + if (!trusted) exit(1); +} + +void ax_perform_click(AXUIElementRef element) { + if (!element) return; + AXUIElementPerformAction(element, kAXCancelAction); + usleep(150000); + AXUIElementPerformAction(element, kAXPressAction); +} + +CFStringRef ax_get_title(AXUIElementRef element) { + CFTypeRef title = NULL; + AXError error = AXUIElementCopyAttributeValue(element, + kAXTitleAttribute, + &title ); + + if (error != kAXErrorSuccess) return NULL; + return title; +} + +void ax_select_menu_option(AXUIElementRef app, int id) { + AXUIElementRef menubars_ref = NULL; + CFArrayRef children_ref = NULL; + + AXError error = AXUIElementCopyAttributeValue(app, + kAXMenuBarAttribute, + (CFTypeRef*)&menubars_ref); + if (error == kAXErrorSuccess) { + error = AXUIElementCopyAttributeValue(menubars_ref, + kAXVisibleChildrenAttribute, + (CFTypeRef*)&children_ref ); + + if (error == kAXErrorSuccess) { + uint32_t count = CFArrayGetCount(children_ref); + if (id < count) { + AXUIElementRef item = CFArrayGetValueAtIndex(children_ref, id); + ax_perform_click(item); + } + if (children_ref) CFRelease(children_ref); + } + if (menubars_ref) CFRelease(menubars_ref); + } +} + +void ax_print_menu_options(AXUIElementRef app) { + AXUIElementRef menubars_ref = NULL; + CFTypeRef menubar = NULL; + CFArrayRef children_ref = NULL; + + AXError error = AXUIElementCopyAttributeValue(app, + kAXMenuBarAttribute, + (CFTypeRef*)&menubars_ref); + if (error == kAXErrorSuccess) { + error = AXUIElementCopyAttributeValue(menubars_ref, + kAXVisibleChildrenAttribute, + (CFTypeRef*)&children_ref ); + + if (error == kAXErrorSuccess) { + uint32_t count = CFArrayGetCount(children_ref); + + for (int i = 1; i < count; i++) { + AXUIElementRef item = CFArrayGetValueAtIndex(children_ref, i); + CFTypeRef title = ax_get_title(item); + + if (title) { + uint32_t buffer_len = 2*CFStringGetLength(title); + char buffer[2*CFStringGetLength(title)]; + CFStringGetCString(title, buffer, buffer_len, kCFStringEncodingUTF8); + printf("%s\n", buffer); + CFRelease(title); + } + } + } + if (menubars_ref) CFRelease(menubars_ref); + if (children_ref) CFRelease(children_ref); + } +} + +AXUIElementRef ax_get_extra_menu_item(char* alias) { + pid_t pid = 0; + CGRect bounds = CGRectNull; + CFArrayRef window_list = CGWindowListCopyWindowInfo(kCGWindowListOptionAll, + kCGNullWindowID ); + char owner_buffer[256]; + char name_buffer[256]; + char buffer[512]; + int window_count = CFArrayGetCount(window_list); + for (int i = 0; i < window_count; ++i) { + CFDictionaryRef dictionary = CFArrayGetValueAtIndex(window_list, i); + if (!dictionary) continue; + + CFStringRef owner_ref = CFDictionaryGetValue(dictionary, + kCGWindowOwnerName); + + CFNumberRef owner_pid_ref = CFDictionaryGetValue(dictionary, + kCGWindowOwnerPID); + + CFStringRef name_ref = CFDictionaryGetValue(dictionary, kCGWindowName); + CFNumberRef layer_ref = CFDictionaryGetValue(dictionary, kCGWindowLayer); + CFDictionaryRef bounds_ref = CFDictionaryGetValue(dictionary, + kCGWindowBounds); + + if (!name_ref || !owner_ref || !owner_pid_ref || !layer_ref || !bounds_ref) + continue; + + long long int layer = 0; + CFNumberGetValue(layer_ref, CFNumberGetType(layer_ref), &layer); + uint64_t owner_pid = 0; + CFNumberGetValue(owner_pid_ref, + CFNumberGetType(owner_pid_ref), + &owner_pid ); + + if (layer != 0x19) continue; + bounds = CGRectNull; + if (!CGRectMakeWithDictionaryRepresentation(bounds_ref, &bounds)) continue; + CFStringGetCString(owner_ref, + owner_buffer, + sizeof(owner_buffer), + kCFStringEncodingUTF8); + + CFStringGetCString(name_ref, + name_buffer, + sizeof(name_buffer), + kCFStringEncodingUTF8); + snprintf(buffer, sizeof(buffer), "%s,%s", owner_buffer, name_buffer); + + if (strcmp(buffer, alias) == 0) { + pid = owner_pid; + break; + } + } + CFRelease(window_list); + if (!pid) return NULL; + + AXUIElementRef app = AXUIElementCreateApplication(pid); + if (!app) return NULL; + AXUIElementRef result = NULL; + CFTypeRef extras = NULL; + CFArrayRef children_ref = NULL; + AXError error = AXUIElementCopyAttributeValue(app, + kAXExtrasMenuBarAttribute, + &extras ); + if (error == kAXErrorSuccess) { + error = AXUIElementCopyAttributeValue(extras, + kAXVisibleChildrenAttribute, + (CFTypeRef*)&children_ref ); + + if (error == kAXErrorSuccess) { + uint32_t count = CFArrayGetCount(children_ref); + for (uint32_t i = 0; i < count; i++) { + AXUIElementRef item = CFArrayGetValueAtIndex(children_ref, i); + CFTypeRef position_ref = NULL; + CFTypeRef size_ref = NULL; + AXUIElementCopyAttributeValue(item, kAXPositionAttribute, + &position_ref ); + AXUIElementCopyAttributeValue(item, kAXSizeAttribute, + &size_ref ); + if (!position_ref || !size_ref) continue; + + CGPoint position = CGPointZero; + AXValueGetValue(position_ref, kAXValueCGPointType, &position); + CGSize size = CGSizeZero; + AXValueGetValue(size_ref, kAXValueCGSizeType, &size); + CFRelease(position_ref); + CFRelease(size_ref); + // The offset is exactly 8 on macOS Sonoma... + // printf("%f %f\n", position.x, bounds.origin.x); + if (error == kAXErrorSuccess + && fabs(position.x - bounds.origin.x) <= 10) { + result = item; + break; + } + } + } + } + + CFRelease(app); + return result; +} + +extern int SLSMainConnectionID(); +extern void SLSSetMenuBarVisibilityOverrideOnDisplay(int cid, int did, bool enabled); +extern void SLSSetMenuBarVisibilityOverrideOnDisplay(int cid, int did, bool enabled); +extern void SLSSetMenuBarInsetAndAlpha(int cid, double u1, double u2, float alpha); +void ax_select_menu_extra(char* alias) { + AXUIElementRef item = ax_get_extra_menu_item(alias); + if (!item) return; + SLSSetMenuBarInsetAndAlpha(SLSMainConnectionID(), 0, 1, 0.0); + SLSSetMenuBarVisibilityOverrideOnDisplay(SLSMainConnectionID(), 0, true); + SLSSetMenuBarInsetAndAlpha(SLSMainConnectionID(), 0, 1, 0.0); + ax_perform_click(item); + SLSSetMenuBarVisibilityOverrideOnDisplay(SLSMainConnectionID(), 0, false); + SLSSetMenuBarInsetAndAlpha(SLSMainConnectionID(), 0, 1, 1.0); + CFRelease(item); +} + +extern void _SLPSGetFrontProcess(ProcessSerialNumber* psn); +extern void SLSGetConnectionIDForPSN(int cid, ProcessSerialNumber* psn, int* cid_out); +extern void SLSConnectionGetPID(int cid, pid_t* pid_out); +AXUIElementRef ax_get_front_app() { + ProcessSerialNumber psn; + _SLPSGetFrontProcess(&psn); + int target_cid; + SLSGetConnectionIDForPSN(SLSMainConnectionID(), &psn, &target_cid); + + pid_t pid; + SLSConnectionGetPID(target_cid, &pid); + return AXUIElementCreateApplication(pid); +} + +int main (int argc, char **argv) { + if (argc == 1) { + printf("Usage: %s [-l | -s id/alias ]\n", argv[0]); + exit(0); + } + ax_init(); + if (strcmp(argv[1], "-l") == 0) { + AXUIElementRef app = ax_get_front_app(); + if (!app) return 1; + ax_print_menu_options(app); + CFRelease(app); + } else if (argc == 3 && strcmp(argv[1], "-s") == 0) { + int id = 0; + if (sscanf(argv[2], "%d", &id) == 1) { + AXUIElementRef app = ax_get_front_app(); + if (!app) return 1; + ax_select_menu_option(app, id); + CFRelease(app); + } else ax_select_menu_extra(argv[2]); + } + return 0; +} diff --git a/.config/sketchybar/icons.lua b/.config/sketchybar/icons.lua new file mode 100644 index 0000000..844b35c --- /dev/null +++ b/.config/sketchybar/icons.lua @@ -0,0 +1,92 @@ +local settings = require("settings") + +local icons = { + sf_symbols = { + plus = "", + loading = "", + apple = "", + gear = "", + cpu = "", + clipboard = "", + + switch = { + on = "", + off = "", + }, + volume = { + _100 = "", + _66 = "", + _33 = "", + _10 = "", + _0 = "", + }, + battery = { + _100 = "", + _75 = "", + _50 = "", + _25 = "", + _0 = "", + charging = "", + }, + wifi = { + upload = "", + download = "", + connected = "", + disconnected = "", + router = "", + }, + media = { + back = "", + forward = "", + play_pause = "", + }, + }, + + -- Alternative NerdFont icons + nerdfont = { + plus = "", + loading = "", + apple = "", + gear = "", + cpu = "", + clipboard = "Missing Icon", + + switch = { + on = "", + off = "", + }, + volume = { + _100 = "", + _66 = "", + _33 = "", + _10 = "", + _0 = "", + }, + battery = { + _100 = "", + _75 = "", + _50 = "", + _25 = "", + _0 = "", + charging = "", + }, + wifi = { + upload = "", + download = "", + connected = "", + disconnected = "", + router = "Missing Icon", + }, + media = { + back = "", + forward = "", + play_pause = "", + }, + }, +} + +if not (settings.icons == "NerdFont") then + return icons.sf_symbols +else + return icons.nerdfont +end diff --git a/.config/sketchybar/init.lua b/.config/sketchybar/init.lua new file mode 100644 index 0000000..e1bf892 --- /dev/null +++ b/.config/sketchybar/init.lua @@ -0,0 +1,16 @@ +-- Require the sketchybar module +sbar = require("sketchybar") + +-- Set the bar name, if you are using another bar instance than sketchybar +-- sbar.set_bar_name("bottom_bar") + +-- Bundle the entire initial configuration into a single message to sketchybar +sbar.begin_config() +require("bar") +require("default") +require("items") +sbar.end_config() + +-- Run the event loop of the sketchybar module (without this there will be no +-- callback functions executed in the lua module) +sbar.event_loop() diff --git a/.config/sketchybar/items/apple.lua b/.config/sketchybar/items/apple.lua new file mode 100644 index 0000000..00e9f44 --- /dev/null +++ b/.config/sketchybar/items/apple.lua @@ -0,0 +1,38 @@ +local colors = require("colors") +local icons = require("icons") +local settings = require("settings") +local sbar = require("sketchybar") + +-- Padding item required because of bracket +sbar.add("item", { width = 5 }) + +local apple = sbar.add("item", { + icon = { + font = { size = 16.0 }, + string = icons.apple, + padding_right = 8, + padding_left = 8, + }, + label = { drawing = false }, + background = { + -- was bg2 + color = settings.apple_background, + border_color = settings.apple_border, + border_width = 1, + }, + padding_left = 1, + padding_right = 1, + click_script = "$CONFIG_DIR/helpers/menus/bin/menus -s 0", +}) + +-- Double border for apple using a single item bracket +sbar.add("bracket", { apple.name }, { + background = { + color = colors.transparent, + height = 30, + border_color = colors.grey, + }, +}) + +-- Padding item required because of bracket +sbar.add("item", { width = 7 }) diff --git a/.config/sketchybar/items/calendar.lua b/.config/sketchybar/items/calendar.lua new file mode 100644 index 0000000..36ca093 --- /dev/null +++ b/.config/sketchybar/items/calendar.lua @@ -0,0 +1,50 @@ +local settings = require("settings") +local colors = require("colors") +local sbar = require("sketchybar") + +-- Padding item required because of bracket +sbar.add("item", { position = "right", width = settings.group_paddings }) + +local cal = sbar.add("item", { + icon = { + color = colors.white, + padding_left = 8, + font = { + style = settings.font.style_map["Black"], + size = 12.0, + }, + }, + label = { + color = colors.white, + padding_right = 8, + width = 49, + align = "right", + font = { family = settings.font.numbers }, + }, + position = "right", + update_freq = 30, + padding_left = 1, + padding_right = 1, + background = { + -- changes the color of background widget + color = settings.calendar_background, + border_color = settings.calendar_border, + border_width = 1, + }, +}) + +-- Double border for calendar using a single item bracket +sbar.add("bracket", { cal.name }, { + background = { + color = colors.transparent, + height = 30, + border_color = colors.grey, + }, +}) + +-- Padding item required because of bracket +sbar.add("item", { position = "right", width = settings.group_paddings }) + +cal:subscribe({ "forced", "routine", "system_woke" }, function(env) + cal:set({ icon = os.date("%a. %d %b."), label = os.date("%H:%M") }) +end) diff --git a/.config/sketchybar/items/front_app.lua b/.config/sketchybar/items/front_app.lua new file mode 100644 index 0000000..d7dab4b --- /dev/null +++ b/.config/sketchybar/items/front_app.lua @@ -0,0 +1,22 @@ +local settings = require("settings") +local sbar = require("sketchybar") + +local front_app = sbar.add("item", "front_app", { + display = "active", + icon = { drawing = false }, + label = { + font = { + style = settings.font.style_map["Black"], + size = 12.0, + }, + }, + updates = true, +}) + +front_app:subscribe("front_app_switched", function(env) + front_app:set({ label = { string = env.INFO } }) +end) + +front_app:subscribe("mouse.clicked", function(env) + sbar.trigger("swap_menus_and_spaces") +end) diff --git a/.config/sketchybar/items/init.lua b/.config/sketchybar/items/init.lua new file mode 100644 index 0000000..dad59fa --- /dev/null +++ b/.config/sketchybar/items/init.lua @@ -0,0 +1,7 @@ +require("items.apple") +require("items.menus") +require("items.spaces") +require("items.front_app") +require("items.calendar") +require("items.widgets") +require("items.media") diff --git a/.config/sketchybar/items/media.lua b/.config/sketchybar/items/media.lua new file mode 100644 index 0000000..8a9ef7d --- /dev/null +++ b/.config/sketchybar/items/media.lua @@ -0,0 +1,122 @@ +local icons = require("icons") +local colors = require("colors") +local sbar = require("sketchybar") + +local whitelist = { ["Spotify"] = true, ["Music"] = true, ["Sound Cloud"] = true } + +local media_cover = sbar.add("item", { + position = "right", + background = { + image = { + string = "media.artwork", + scale = 0.85, + }, + color = colors.transparent, + }, + label = { drawing = false }, + icon = { drawing = false }, + drawing = false, + updates = true, + popup = { + align = "center", + horizontal = true, + }, +}) + +local media_artist = sbar.add("item", { + position = "right", + drawing = false, + padding_left = 3, + padding_right = 0, + width = 0, + icon = { drawing = false }, + label = { + width = 0, + font = { size = 9 }, + color = colors.with_alpha(colors.white, 0.6), + max_chars = 18, + y_offset = 6, + }, +}) + +local media_title = sbar.add("item", { + position = "right", + drawing = false, + padding_left = 3, + padding_right = 0, + icon = { drawing = false }, + label = { + font = { size = 11 }, + width = 0, + max_chars = 16, + y_offset = -5, + }, +}) + +sbar.add("item", { + position = "popup." .. media_cover.name, + icon = { string = icons.media.back }, + label = { drawing = false }, + click_script = "nowplaying-cli previous", +}) +sbar.add("item", { + position = "popup." .. media_cover.name, + icon = { string = icons.media.play_pause }, + label = { drawing = false }, + click_script = "nowplaying-cli togglePlayPause", +}) +sbar.add("item", { + position = "popup." .. media_cover.name, + icon = { string = icons.media.forward }, + label = { drawing = false }, + click_script = "nowplaying-cli next", +}) + +local interrupt = 0 +local function animate_detail(detail) + if not detail then + interrupt = interrupt - 1 + end + if interrupt > 0 and not detail then + return + end + + sbar.animate("tanh", 30, function() + media_artist:set({ label = { width = detail and "dynamic" or 0 } }) + media_title:set({ label = { width = detail and "dynamic" or 0 } }) + end) +end + +media_cover:subscribe("media_change", function(env) + if whitelist[env.INFO.app] then + local drawing = (env.INFO.state == "playing") + media_artist:set({ drawing = drawing, label = env.INFO.artist }) + media_title:set({ drawing = drawing, label = env.INFO.title }) + media_cover:set({ drawing = drawing }) + + if drawing then + animate_detail(true) + interrupt = interrupt + 1 + sbar.delay(5, animate_detail) + else + media_cover:set({ popup = { drawing = false } }) + end + end +end) + +media_cover:subscribe("mouse.entered", function(env) + interrupt = interrupt + 1 + animate_detail(true) +end) + +media_cover:subscribe("mouse.exited", function(env) + animate_detail(false) +end) + +media_cover:subscribe("mouse.clicked", function(env) + media_cover:set({ popup = { drawing = "toggle" } }) +end) + +media_title:subscribe("mouse.exited.global", function(env) + media_cover:set({ popup = { drawing = false } }) +end) diff --git a/.config/sketchybar/items/menus.lua b/.config/sketchybar/items/menus.lua new file mode 100644 index 0000000..66cdd4a --- /dev/null +++ b/.config/sketchybar/items/menus.lua @@ -0,0 +1,78 @@ +local colors = require("colors") +local settings = require("settings") +local sbar = require("sketchybar") + +local menu_watcher = sbar.add("item", { + drawing = false, + updates = false, +}) +local space_menu_swap = sbar.add("item", { + drawing = false, + updates = true, +}) +sbar.add("event", "swap_menus_and_spaces") + +local max_items = 15 +local menu_items = {} +for i = 1, max_items, 1 do + local menu = sbar.add("item", "menu." .. i, { + padding_left = settings.paddings, + padding_right = settings.paddings, + drawing = false, + icon = { drawing = false }, + label = { + font = { + style = settings.font.style_map[i == 1 and "Heavy" or "Semibold"], + }, + padding_left = 6, + padding_right = 6, + }, + click_script = "$CONFIG_DIR/helpers/menus/bin/menus -s " .. i, + }) + + menu_items[i] = menu +end + +sbar.add("bracket", { "/menu\\..*/" }, { + background = { color = colors.bg1 }, +}) + +local menu_padding = sbar.add("item", "menu.padding", { + drawing = false, + width = 5, +}) + +local function update_menus(env) + sbar.exec("$CONFIG_DIR/helpers/menus/bin/menus -l", function(menus) + sbar.set("/menu\\..*/", { drawing = false }) + menu_padding:set({ drawing = true }) + id = 1 + for menu in string.gmatch(menus, "[^\r\n]+") do + if id < max_items then + menu_items[id]:set({ label = menu, drawing = true }) + else + break + end + id = id + 1 + end + end) +end + +menu_watcher:subscribe("front_app_switched", update_menus) + +space_menu_swap:subscribe("swap_menus_and_spaces", function(env) + local drawing = menu_items[1]:query().geometry.drawing == "on" + if drawing then + menu_watcher:set({ updates = false }) + sbar.set("/menu\\..*/", { drawing = false }) + sbar.set("/space\\..*/", { drawing = true }) + sbar.set("front_app", { drawing = true }) + else + menu_watcher:set({ updates = true }) + sbar.set("/space\\..*/", { drawing = false }) + sbar.set("front_app", { drawing = false }) + update_menus() + end +end) + +return menu_watcher diff --git a/.config/sketchybar/items/spaces.lua b/.config/sketchybar/items/spaces.lua new file mode 100644 index 0000000..100b050 --- /dev/null +++ b/.config/sketchybar/items/spaces.lua @@ -0,0 +1,186 @@ +local colors = require("colors") +local icons = require("icons") +local settings = require("settings") +local app_icons = require("helpers.app_icons") +local sbar = require("sketchybar") + +local spaces = {} + +for i = 1, 10, 1 do + local space = sbar.add("space", "space." .. i, { + space = i, + icon = { + font = { family = settings.font.numbers }, + string = i, + padding_left = 15, + padding_right = 8, + color = colors.white, + -- the highlighter color + highlight_color = settings.spaces_highlight, + }, + label = { + padding_right = 20, + -- icon coloring for spaces + color = settings.spaces_icon, + highlight_color = colors.white, + font = "sketchybar-app-font:Regular:16.0", + y_offset = -1, + }, + padding_right = 1, + padding_left = 1, + background = { + -- this is bg color for spaces + color = settings.spaces_background, + border_width = 1, + height = 26, + border_color = settings.spaces_border, + }, + popup = { background = { border_width = 5, border_color = colors.black } }, + }) + + spaces[i] = space + + -- Single item bracket for space items to achieve double border on highlight + local space_bracket = sbar.add("bracket", { space.name }, { + background = { + color = colors.transparent, + border_color = colors.bg2, + height = 28, + border_width = 2, + }, + }) + + -- Padding space + sbar.add("space", "space.padding." .. i, { + space = i, + script = "", + width = settings.group_paddings, + }) + + local space_popup = sbar.add("item", { + position = "popup." .. space.name, + padding_left = 5, + padding_right = 0, + background = { + drawing = true, + image = { + corner_radius = 9, + scale = 0.2, + }, + }, + }) + + space:subscribe("space_change", function(env) + local selected = env.SELECTED == "true" + local color = selected and colors.grey or colors.bg2 + space:set({ + icon = { highlight = selected }, + label = { highlight = selected }, + background = { border_color = selected and colors.black or colors.bg2 }, + }) + space_bracket:set({ + background = { border_color = selected and colors.grey or colors.bg2 }, + }) + end) + + space:subscribe("mouse.clicked", function(env) + if env.BUTTON == "other" then + space_popup:set({ background = { image = "space." .. env.SID } }) + space:set({ popup = { drawing = "toggle" } }) + else + local op = (env.BUTTON == "right") and "--destroy" or "--focus" + os.execute("yabai -m space " .. op .. " " .. env.SID) + -- sbar.exec() is acting weird + -- sbar.exec("yabai -m space " .. op .. " " .. env.SID) + end + end) + + space:subscribe("mouse.exited", function(_) + space:set({ popup = { drawing = false } }) + end) +end + +local space_window_observer = sbar.add("item", { + drawing = false, + updates = true, +}) + +local spaces_indicator = sbar.add("item", { + padding_left = -3, + padding_right = 0, + icon = { + padding_left = 8, + padding_right = 9, + -- changed coloring of selected app icon + color = settings.spaces_selected, + string = icons.switch.on, + }, + label = { + width = 0, + padding_left = 0, + padding_right = 8, + string = "Spaces", + -- bg1 + color = colors.bg1, + }, + background = { + -- grey + color = colors.with_alpha(colors.grey, 0.0), + border_color = colors.with_alpha(colors.bg1, 0.0), + }, +}) + +space_window_observer:subscribe("space_windows_change", function(env) + local icon_line = "" + local no_app = true + for app, count in pairs(env.INFO.apps) do + no_app = false + local lookup = app_icons[app] + local icon = ((lookup == nil) and app_icons["default"] or lookup) + icon_line = icon_line .. " " .. icon + end + + if no_app then + icon_line = " —" + end + sbar.animate("tanh", 10, function() + spaces[env.INFO.space]:set({ label = icon_line }) + end) +end) + +spaces_indicator:subscribe("swap_menus_and_spaces", function(env) + local currently_on = spaces_indicator:query().icon.value == icons.switch.on + spaces_indicator:set({ + icon = currently_on and icons.switch.off or icons.switch.on, + }) +end) + +spaces_indicator:subscribe("mouse.entered", function(env) + sbar.animate("tanh", 30, function() + spaces_indicator:set({ + background = { + color = { alpha = 1.0 }, + border_color = { alpha = 1.0 }, + }, + icon = { color = colors.bg1 }, + label = { width = "dynamic" }, + }) + end) +end) + +spaces_indicator:subscribe("mouse.exited", function(env) + sbar.animate("tanh", 30, function() + spaces_indicator:set({ + background = { + color = { alpha = 0.0 }, + border_color = { alpha = 0.0 }, + }, + icon = { color = colors.grey }, + label = { width = 0 }, + }) + end) +end) + +spaces_indicator:subscribe("mouse.clicked", function(env) + sbar.trigger("swap_menus_and_spaces") +end) diff --git a/.config/sketchybar/items/widgets/battery.lua b/.config/sketchybar/items/widgets/battery.lua new file mode 100644 index 0000000..13356f1 --- /dev/null +++ b/.config/sketchybar/items/widgets/battery.lua @@ -0,0 +1,117 @@ +local icons = require("icons") +local settings = require("settings") +local sbar = require("sketchybar") + +function os.capture(cmd, raw) + local file = assert(io.popen(cmd, "r")) + local output = assert(file:read("*a")) + file:close() + + if raw then + return output + end + + output = string.gsub(output, "^%s+", "") + output = string.gsub(output, "%s+$", "") + output = string.gsub(output, "[\n\r]+", "") + + return output +end + +local battery = sbar.add("item", "widgets.battery", { + position = "right", + icon = { + font = { + style = settings.font.style_map["Regular"], + size = 19.0, + }, + }, + label = { font = { family = settings.font.numbers } }, + update_freq = 180, + popup = { align = "center" }, +}) + +local remaining_time = sbar.add("item", { + position = "popup." .. battery.name, + icon = { + string = "Time remaining:", + width = 100, + align = "left", + }, + label = { + string = "??:??h", + width = 100, + align = "right", + }, +}) + +-- TODO: This is where the battery widget issue is occuring... +local function battery_update() + Color = settings.batt_color_default + + local batt_info = os.capture("pmset -g batt", false) + local icon = "!" + local label = "?" + + if batt_info:find("AC Power") then + icon = icons.battery.charging + else + local found, _, charge = batt_info:find("(%d+)%%") + if found then + charge = tonumber(charge) + label = charge .. "%" + end + + if found and charge > 80 then + icon = icons.battery._100 + elseif found and charge > 60 then + icon = icons.battery._75 + elseif found and charge > 40 then + icon = icons.battery._50 + elseif found and charge > 20 then + icon = icons.battery._25 + Color = settings.batt_color_25 + else + icon = icons.battery._0 + Color = settings.batt_color_0 + end + end + -- TODO: Add in charging percentage + local lead = "" + if label == "?" then + label = "W" + end + + battery:set({ + icon = { + string = icon, + color = Color, + }, + label = { string = lead .. label }, + }) +end + +battery:subscribe({ "routine", "power_source_change", "system_woke" }, battery_update) + +battery:subscribe("mouse.clicked", function(env) + local drawing = battery:query().popup.drawing + battery:set({ popup = { drawing = "toggle" } }) + + if drawing == "off" then + sbar.exec("pmset -g batt", function(batt_info) + local found, _, remaining = batt_info:find(" (%d+:%d+) remaining") + local label = found and remaining .. "h" or "No estimate" + remaining_time:set({ label = label }) + end) + end +end) + +sbar.add("bracket", "widgets.battery.bracket", { battery.name }, { + -- changes color of widget background + background = { color = settings.batt_background }, +}) + +sbar.add("item", "widgets.battery.padding", { + position = "right", + width = settings.group_paddings, +}) diff --git a/.config/sketchybar/items/widgets/cpu.lua b/.config/sketchybar/items/widgets/cpu.lua new file mode 100644 index 0000000..89b3647 --- /dev/null +++ b/.config/sketchybar/items/widgets/cpu.lua @@ -0,0 +1,71 @@ +local icons = require("icons") +local colors = require("colors") +local settings = require("settings") +local sbar = require("sketchybar") + +-- Execute the event provider binary which provides the event "cpu_update" for +-- the cpu load data, which is fired every 2.0 seconds. +sbar.exec("killall cpu_load >/dev/null; $CONFIG_DIR/helpers/event_providers/cpu_load/bin/cpu_load cpu_update 2.0") + +local cpu = sbar.add("graph", "widgets.cpu", 42, { + position = "right", + graph = { color = colors.blue }, + background = { + height = 22, + color = { alpha = 0 }, + border_color = { alpha = 0 }, + drawing = true, + }, + icon = { string = icons.cpu }, + label = { + string = "cpu ??%", + font = { + family = settings.font.numbers, + style = settings.font.style_map["Bold"], + size = 9.0, + }, + align = "right", + padding_right = 0, + width = 0, + y_offset = 4, + }, + padding_right = settings.paddings + 6, +}) + +cpu:subscribe("cpu_update", function(env) + -- Also available: env.user_load, env.sys_load + local load = tonumber(env.total_load) + cpu:push({ load / 100. }) + + local color = colors.blue + if load > 30 then + if load < 60 then + color = colors.yellow + elseif load < 80 then + color = colors.orange + else + color = colors.red + end + end + + cpu:set({ + graph = { color = color }, + label = "cpu " .. env.total_load .. "%", + }) +end) + +cpu:subscribe("mouse.clicked", function(env) + sbar.exec("open -a 'Activity Monitor'") +end) + +-- Background around the cpu item +sbar.add("bracket", "widgets.cpu.bracket", { cpu.name }, { + -- changes color of background widget + background = { color = settings.cpu_background }, +}) + +-- Background around the cpu item +sbar.add("item", "widgets.cpu.padding", { + position = "right", + width = settings.group_paddings, +}) diff --git a/.config/sketchybar/items/widgets/func_utils.lua b/.config/sketchybar/items/widgets/func_utils.lua new file mode 100644 index 0000000..b60176d --- /dev/null +++ b/.config/sketchybar/items/widgets/func_utils.lua @@ -0,0 +1,26 @@ +function os.capture(cmd, raw) + local file = assert(io.popen(cmd, "r")) + local output = assert(file:read("*a")) + file:close() + + if raw then + return output + end + + output = string.gsub(output, "^%s+", "") + output = string.gsub(output, "%s+$", "") + output = string.gsub(output, "[\n\r]+", "") + + return output +end + +-- testing battery info here... works +Batt_info = os.capture("pmset -g batt", false) +if Batt_info:find("AC Power") then + print("Found AC Power in the string.") +else + local found, _, charge = Batt_info:find("(%d+)%%") + print("found: " .. found) + print("_: " .. _) + print("charge: " .. charge) +end diff --git a/.config/sketchybar/items/widgets/init.lua b/.config/sketchybar/items/widgets/init.lua new file mode 100644 index 0000000..c919c76 --- /dev/null +++ b/.config/sketchybar/items/widgets/init.lua @@ -0,0 +1,4 @@ +require("items.widgets.battery") +require("items.widgets.volume") +require("items.widgets.wifi") +require("items.widgets.cpu") diff --git a/.config/sketchybar/items/widgets/volume.lua b/.config/sketchybar/items/widgets/volume.lua new file mode 100644 index 0000000..ff6a88b --- /dev/null +++ b/.config/sketchybar/items/widgets/volume.lua @@ -0,0 +1,157 @@ +local colors = require("colors") +local icons = require("icons") +local settings = require("settings") +local sbar = require("sketchybar") + +local popup_width = 250 + +local volume_percent = sbar.add("item", "widgets.volume1", { + position = "right", + icon = { drawing = false }, + label = { + string = "??%", + padding_left = -1, + font = { family = settings.font.numbers }, + }, +}) + +local volume_icon = sbar.add("item", "widgets.volume2", { + position = "right", + padding_right = -1, + icon = { + string = icons.volume._100, + width = 0, + align = "left", + color = colors.grey, + font = { + style = settings.font.style_map["Regular"], + size = 14.0, + }, + }, + label = { + width = 25, + align = "left", + font = { + style = settings.font.style_map["Regular"], + size = 14.0, + }, + }, +}) + +local volume_bracket = sbar.add("bracket", "widgets.volume.bracket", { + volume_icon.name, + volume_percent.name, +}, { + -- changes the background color of widget + background = { color = settings.volume_background }, + popup = { align = "center" }, +}) + +sbar.add("item", "widgets.volume.padding", { + position = "right", + width = settings.group_paddings, +}) + +local volume_slider = sbar.add("slider", popup_width, { + position = "popup." .. volume_bracket.name, + slider = { + highlight_color = colors.blue, + background = { + height = 6, + corner_radius = 3, + color = colors.bg2, + }, + knob = { + string = "", + drawing = true, + }, + }, + background = { color = colors.bg1, height = 2, y_offset = -20 }, + click_script = 'osascript -e "set volume output volume $PERCENTAGE"', +}) + +volume_percent:subscribe("volume_change", function(env) + local volume = tonumber(env.INFO) + local icon = icons.volume._0 + if volume > 60 then + icon = icons.volume._100 + elseif volume > 30 then + icon = icons.volume._66 + elseif volume > 10 then + icon = icons.volume._33 + elseif volume > 0 then + icon = icons.volume._10 + end + + local lead = "" + if volume < 10 then + lead = "0" + end + + volume_icon:set({ label = icon }) + volume_percent:set({ label = lead .. volume .. "%" }) + volume_slider:set({ slider = { percentage = volume } }) +end) + +local function volume_collapse_details() + local drawing = volume_bracket:query().popup.drawing == "on" + if not drawing then + return + end + volume_bracket:set({ popup = { drawing = false } }) + sbar.remove("/volume.device\\.*/") +end + +local current_audio_device = "None" +local function volume_toggle_details(env) + if env.BUTTON == "right" then + sbar.exec("open /System/Library/PreferencePanes/Sound.prefpane") + return + end + + local should_draw = volume_bracket:query().popup.drawing == "off" + if should_draw then + volume_bracket:set({ popup = { drawing = true } }) + sbar.exec("SwitchAudioSource -t output -c", function(result) + current_audio_device = result:sub(1, -2) + sbar.exec("SwitchAudioSource -a -t output", function(available) + current = current_audio_device + local color = colors.grey + local counter = 0 + + for device in string.gmatch(available, "[^\r\n]+") do + local color = colors.grey + if current == device then + color = colors.white + end + sbar.add("item", "volume.device." .. counter, { + position = "popup." .. volume_bracket.name, + width = popup_width, + align = "center", + label = { string = device, color = color }, + click_script = 'SwitchAudioSource -s "' + .. device + .. '" && sketchybar --set /volume.device\\.*/ label.color=' + .. colors.grey + .. " --set $NAME label.color=" + .. colors.white, + }) + counter = counter + 1 + end + end) + end) + else + volume_collapse_details() + end +end + +local function volume_scroll(env) + local delta = env.SCROLL_DELTA + sbar.exec('osascript -e "set volume output volume (output volume of (get volume settings) + ' .. delta .. ')"') +end + +volume_icon:subscribe("mouse.clicked", volume_toggle_details) +volume_icon:subscribe("mouse.scrolled", volume_scroll) +volume_percent:subscribe("mouse.clicked", volume_toggle_details) +volume_percent:subscribe("mouse.exited.global", volume_collapse_details) +volume_percent:subscribe("mouse.scrolled", volume_scroll) diff --git a/.config/sketchybar/items/widgets/wifi.lua b/.config/sketchybar/items/widgets/wifi.lua new file mode 100644 index 0000000..c403343 --- /dev/null +++ b/.config/sketchybar/items/widgets/wifi.lua @@ -0,0 +1,238 @@ +local icons = require("icons") +local colors = require("colors") +local settings = require("settings") +local sbar = require("sketchybar") + +-- Execute the event provider binary which provides the event "network_update" +-- for the network interface "en0", which is fired every 2.0 seconds. +sbar.exec( + "killall network_load >/dev/null; $CONFIG_DIR/helpers/event_providers/network_load/bin/network_load en0 network_update 2.0" +) + +local popup_width = 250 + +local wifi_up = sbar.add("item", "widgets.wifi1", { + position = "right", + padding_left = -5, + width = 0, + icon = { + padding_right = 0, + font = { + style = settings.font.style_map["Bold"], + size = 9.0, + }, + string = icons.wifi.upload, + }, + label = { + font = { + family = settings.font.numbers, + style = settings.font.style_map["Bold"], + size = 9.0, + }, + color = colors.red, + string = "??? Bps", + }, + y_offset = 4, +}) + +local wifi_down = sbar.add("item", "widgets.wifi2", { + position = "right", + padding_left = -5, + icon = { + padding_right = 0, + font = { + style = settings.font.style_map["Bold"], + size = 9.0, + }, + string = icons.wifi.download, + }, + label = { + font = { + family = settings.font.numbers, + style = settings.font.style_map["Bold"], + size = 9.0, + }, + color = colors.blue, + string = "??? Bps", + }, + y_offset = -4, +}) + +local wifi = sbar.add("item", "widgets.wifi.padding", { + position = "right", + label = { drawing = false }, +}) + +-- Background around the item +local wifi_bracket = sbar.add("bracket", "widgets.wifi.bracket", { + wifi.name, + wifi_up.name, + wifi_down.name, +}, { + -- changes the background color of widget + background = { color = settings.wifi_background }, + popup = { align = "center", height = 30 }, +}) + +local ssid = sbar.add("item", { + position = "popup." .. wifi_bracket.name, + icon = { + font = { + style = settings.font.style_map["Bold"], + }, + string = icons.wifi.router, + }, + width = popup_width, + align = "center", + label = { + font = { + size = 15, + style = settings.font.style_map["Bold"], + }, + max_chars = 18, + string = "????????????", + }, + background = { + height = 2, + color = colors.grey, + y_offset = -15, + }, +}) + +local hostname = sbar.add("item", { + position = "popup." .. wifi_bracket.name, + icon = { + align = "left", + string = "Hostname:", + width = popup_width / 2, + }, + label = { + max_chars = 20, + string = "????????????", + width = popup_width / 2, + align = "right", + }, +}) + +local ip = sbar.add("item", { + position = "popup." .. wifi_bracket.name, + icon = { + align = "left", + string = "IP:", + width = popup_width / 2, + }, + label = { + string = "???.???.???.???", + width = popup_width / 2, + align = "right", + }, +}) + +local mask = sbar.add("item", { + position = "popup." .. wifi_bracket.name, + icon = { + align = "left", + string = "Subnet mask:", + width = popup_width / 2, + }, + label = { + string = "???.???.???.???", + width = popup_width / 2, + align = "right", + }, +}) + +local router = sbar.add("item", { + position = "popup." .. wifi_bracket.name, + icon = { + align = "left", + string = "Router:", + width = popup_width / 2, + }, + label = { + string = "???.???.???.???", + width = popup_width / 2, + align = "right", + }, +}) + +sbar.add("item", { position = "right", width = settings.group_paddings }) + +wifi_up:subscribe("network_update", function(env) + local up_color = (env.upload == "000 Bps") and colors.grey or colors.red + local down_color = (env.download == "000 Bps") and colors.grey or colors.blue + wifi_up:set({ + icon = { color = up_color }, + label = { + string = env.upload, + color = up_color, + }, + }) + wifi_down:set({ + icon = { color = down_color }, + label = { + string = env.download, + color = down_color, + }, + }) +end) + +wifi:subscribe({ "wifi_change", "system_woke" }, function(env) + sbar.exec("ipconfig getifaddr en0", function(ip) + local connected = not (ip == "") + wifi:set({ + icon = { + string = connected and icons.wifi.connected or icons.wifi.disconnected, + color = connected and colors.white or colors.red, + }, + }) + end) +end) + +local function hide_details() + wifi_bracket:set({ popup = { drawing = false } }) +end + +local function toggle_details() + local should_draw = wifi_bracket:query().popup.drawing == "off" + if should_draw then + wifi_bracket:set({ popup = { drawing = true } }) + sbar.exec("networksetup -getcomputername", function(result) + hostname:set({ label = result }) + end) + sbar.exec("ipconfig getifaddr en0", function(result) + ip:set({ label = result }) + end) + sbar.exec("ipconfig getsummary en0 | awk -F ' SSID : ' '/ SSID : / {print $2}'", function(result) + ssid:set({ label = result }) + end) + sbar.exec("networksetup -getinfo Wi-Fi | awk -F 'Subnet mask: ' '/^Subnet mask: / {print $2}'", function(result) + mask:set({ label = result }) + end) + sbar.exec("networksetup -getinfo Wi-Fi | awk -F 'Router: ' '/^Router: / {print $2}'", function(result) + router:set({ label = result }) + end) + else + hide_details() + end +end + +wifi_up:subscribe("mouse.clicked", toggle_details) +wifi_down:subscribe("mouse.clicked", toggle_details) +wifi:subscribe("mouse.clicked", toggle_details) +wifi:subscribe("mouse.exited.global", hide_details) + +local function copy_label_to_clipboard(env) + local label = sbar.query(env.NAME).label.value + sbar.exec('echo "' .. label .. '" | pbcopy') + sbar.set(env.NAME, { label = { string = icons.clipboard, align = "center" } }) + sbar.delay(1, function() + sbar.set(env.NAME, { label = { string = label, align = "right" } }) + end) +end + +ssid:subscribe("mouse.clicked", copy_label_to_clipboard) +hostname:subscribe("mouse.clicked", copy_label_to_clipboard) +ip:subscribe("mouse.clicked", copy_label_to_clipboard) +mask:subscribe("mouse.clicked", copy_label_to_clipboard) +router:subscribe("mouse.clicked", copy_label_to_clipboard) diff --git a/.config/sketchybar/settings.lua b/.config/sketchybar/settings.lua new file mode 100644 index 0000000..bad1d71 --- /dev/null +++ b/.config/sketchybar/settings.lua @@ -0,0 +1,50 @@ +local colors = require("colors") +return { + -- widgets borders; cpu, wifi, vol, batt + widget_borders = colors.grey, + -- battery widget + batt_background = colors.black, + batt_color_default = colors.green, + batt_color_25 = colors.cog_blue, + batt_color_0 = colors.orange, + -- cpu widget + cpu_background = colors.black, + -- volume widget + volume_background = colors.black, + -- wifi widget + wifi_background = colors.black, + -- apple.lua + apple_icon = colors.white, + apple_background = colors.black, + apple_border = colors.black, + -- calendar.lua + calendar_background = colors.black, + calendar_border = colors.black, + -- spaces.lua + spaces_highlight = colors.pink, + spaces_icon = colors.grey, + spaces_background = colors.black, + spaces_border = colors.grey, + spaces_selected = colors.white, + + paddings = 3, + group_paddings = 5, + + icons = "sf-symbols", -- alternatively available: NerdFont + + -- This is a font configuration for SF Pro and SF Mono (installed manually) + font = require("helpers.default_font"), + + -- Alternatively, this is a font config for JetBrainsMono Nerd Font + -- font = { + -- text = "JetBrainsMono Nerd Font", -- Used for text + -- numbers = "JetBrainsMono Nerd Font", -- Used for numbers + -- style_map = { + -- ["Regular"] = "Regular", + -- ["Semibold"] = "Medium", + -- ["Bold"] = "SemiBold", + -- ["Heavy"] = "Bold", + -- ["Black"] = "ExtraBold", + -- }, + -- }, +} diff --git a/.config/sketchybar/sketchybarrc b/.config/sketchybar/sketchybarrc new file mode 100755 index 0000000..95ece11 --- /dev/null +++ b/.config/sketchybar/sketchybarrc @@ -0,0 +1,5 @@ +#!/usr/bin/env lua + +-- Load the sketchybar-package and prepare the helper binaries +require("helpers") +require("init") |
