Delete directory 'sketchybar'
This commit is contained in:
Vendored
BIN
Binary file not shown.
@@ -1,15 +0,0 @@
|
|||||||
local settings = require("config.settings")
|
|
||||||
|
|
||||||
sbar.bar({
|
|
||||||
topmost = "window",
|
|
||||||
height = settings.dimens.graphics.bar.height,
|
|
||||||
color = 0xff1e1e2e,
|
|
||||||
padding_right = settings.dimens.padding.right,
|
|
||||||
padding = settings.dimens.padding.bar,
|
|
||||||
padding_left = settings.dimens.padding.left,
|
|
||||||
margin = settings.dimens.padding.bar,
|
|
||||||
corner_radius = settings.dimens.graphics.background.corner_radius,
|
|
||||||
y_offset = settings.dimens.graphics.bar.offset,
|
|
||||||
-- blur_radius = settings.dimens.graphics.blur_radius,
|
|
||||||
border_width = 0,
|
|
||||||
})
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
bin
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
all:
|
|
||||||
(cd network_load && $(MAKE)) >/dev/null
|
|
||||||
(cd menus && $(MAKE)) >/dev/null
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
bin/menus: menus.c | bin
|
|
||||||
clang -std=c99 -O3 -F/System/Library/PrivateFrameworks/ -framework Carbon -framework SkyLight $< -o $@
|
|
||||||
|
|
||||||
bin:
|
|
||||||
mkdir bin
|
|
||||||
@@ -1,248 +0,0 @@
|
|||||||
#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;
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
bin/network_load: network_load.c network_load.h ../sketchybar.h | bin
|
|
||||||
clang -std=c99 -O3 $< -o $@
|
|
||||||
|
|
||||||
bin:
|
|
||||||
mkdir bin
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
#include "network_load.h"
|
|
||||||
#include "../sketchybar.h"
|
|
||||||
#include <unistd.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;
|
|
||||||
}
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
#include <math.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <net/if_mib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
#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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
local colors <const> = {
|
|
||||||
black = 0xff1e1e2e,
|
|
||||||
white = 0xffcdd6f4,
|
|
||||||
red = 0xfff38ba8,
|
|
||||||
green = 0xffa6e3a1,
|
|
||||||
blue = 0xff89b4fa,
|
|
||||||
yellow = 0xfff9e2af,
|
|
||||||
orange = 0xfffab387,
|
|
||||||
magenta = 0xffcba6f7,
|
|
||||||
purple = 0xffb4befe,
|
|
||||||
other_purple = 0xfff5c2e7,
|
|
||||||
cyan = 0xff94e2d5,
|
|
||||||
grey = 0xff6c7086,
|
|
||||||
dirty_white = 0xffa6adc8,
|
|
||||||
dark_grey = 0xff585b70,
|
|
||||||
transparent = 0xff1e1e2e,
|
|
||||||
bar = {
|
|
||||||
bg = 0xff1e1e2e,
|
|
||||||
border = 0xff1e1e2e,
|
|
||||||
},
|
|
||||||
popup = {
|
|
||||||
bg = 0xff1e1e2e,
|
|
||||||
border = 0xff2c2e34,
|
|
||||||
},
|
|
||||||
slider = {
|
|
||||||
bg = 0xff1e1e2e,
|
|
||||||
border = 0xff2c2e34,
|
|
||||||
},
|
|
||||||
bg1 = 0xff1e1e2e,
|
|
||||||
bg2 = 0xff302c45,
|
|
||||||
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
|
|
||||||
return colors
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
local padding <const> = {
|
|
||||||
background = 8,
|
|
||||||
icon = 10,
|
|
||||||
label = 8,
|
|
||||||
bar = 20,
|
|
||||||
left = 12,
|
|
||||||
right = 12,
|
|
||||||
item = 18,
|
|
||||||
popup = 8,
|
|
||||||
}
|
|
||||||
|
|
||||||
local graphics <const> = {
|
|
||||||
bar = {
|
|
||||||
height = 32,
|
|
||||||
offset = 6,
|
|
||||||
},
|
|
||||||
background = {
|
|
||||||
height = 24,
|
|
||||||
corner_radius = 9,
|
|
||||||
},
|
|
||||||
slider = {
|
|
||||||
height = 20,
|
|
||||||
},
|
|
||||||
popup = {
|
|
||||||
width = 200,
|
|
||||||
large_width = 300,
|
|
||||||
},
|
|
||||||
blur_radius = 30,
|
|
||||||
}
|
|
||||||
|
|
||||||
local text <const> = {
|
|
||||||
icon = 16.0,
|
|
||||||
label = 14.0,
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
padding = padding,
|
|
||||||
graphics = graphics,
|
|
||||||
text = text,
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
local dimens <const> = require("config.dimens")
|
|
||||||
|
|
||||||
return {
|
|
||||||
text = "Hack Nerd Font",
|
|
||||||
numbers = "Hack Nerd Font",
|
|
||||||
icons = function(size)
|
|
||||||
local font = "sketchybar-app-font:Regular"
|
|
||||||
return size and font .. ":" .. size or font .. ":" .. dimens.text.icon
|
|
||||||
end,
|
|
||||||
styles = {
|
|
||||||
regular = "Regular",
|
|
||||||
bold = "Bold",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,332 +0,0 @@
|
|||||||
local apps <const> = {
|
|
||||||
["Live"] = ":ableton:",
|
|
||||||
["Adobe Bridge 2024"] = ":adobe_bridge:",
|
|
||||||
["Affinity Designer"] = ":affinity_designer:",
|
|
||||||
["Affinity Designer 2"] = ":affinity_designer_2:",
|
|
||||||
["Affinity Photo"] = ":affinity_photo:",
|
|
||||||
["Affinity Photo 2"] = ":affinity_photo_2:",
|
|
||||||
["Affinity Publisher"] = ":affinity_publisher:",
|
|
||||||
["Affinity Publisher 2"] = ":affinity_publisher_2:",
|
|
||||||
["Airmail"] = ":airmail:",
|
|
||||||
["Alacritty"] = ":alacritty:",
|
|
||||||
["Alfred Preferences"] = ":alfred:",
|
|
||||||
["Android Messages"] = ":android_messages:",
|
|
||||||
["Android Studio"] = ":android_studio:",
|
|
||||||
["Anytype"] = ":anytype:",
|
|
||||||
["App Eraser"] = ":app_eraser:",
|
|
||||||
["App Store"] = ":app_store:",
|
|
||||||
["Arc"] = ":arc:",
|
|
||||||
["Atom"] = ":atom:",
|
|
||||||
["Audacity"] = ":audacity:",
|
|
||||||
["Bambu Studio"] = ":bambu_studio:",
|
|
||||||
["MoneyMoney"] = ":bank:",
|
|
||||||
["Bear"] = ":bear:",
|
|
||||||
["BetterTouchTool"] = ":bettertouchtool:",
|
|
||||||
["Bilibili"] = ":bilibili:",
|
|
||||||
["哔哩哔哩"] = ":bilibili:",
|
|
||||||
["Bitwarden"] = ":bit_warden:",
|
|
||||||
["Blender"] = ":blender:",
|
|
||||||
["BluOS Controller"] = ":bluos_controller:",
|
|
||||||
["Calibre"] = ":book:",
|
|
||||||
["Brave Browser"] = ":brave_browser:",
|
|
||||||
["Calculator"] = ":calculator:",
|
|
||||||
["Soulver 3"] = ":calculator:",
|
|
||||||
["Calculette"] = ":calculator:",
|
|
||||||
["Calendar"] = ":calendar:",
|
|
||||||
["日历"] = ":calendar:",
|
|
||||||
["Fantastical"] = ":calendar:",
|
|
||||||
["Cron"] = ":calendar:",
|
|
||||||
["Amie"] = ":calendar:",
|
|
||||||
["Calendrier"] = ":calendar:",
|
|
||||||
["Notion Calendar"] = ":calendar:",
|
|
||||||
["Caprine"] = ":caprine:",
|
|
||||||
["Citrix Workspace"] = ":citrix:",
|
|
||||||
["Citrix Viewer"] = ":citrix:",
|
|
||||||
["ClickUp"] = ":click_up:",
|
|
||||||
["Code"] = ":code:",
|
|
||||||
["Code - Insiders"] = ":code:",
|
|
||||||
["Color Picker"] = ":color_picker:",
|
|
||||||
["数码测色计"] = ":color_picker:",
|
|
||||||
["CotEditor"] = ":coteditor:",
|
|
||||||
["Cypress"] = ":cypress:",
|
|
||||||
["DataGrip"] = ":datagrip:",
|
|
||||||
["DataSpell"] = ":dataspell:",
|
|
||||||
["DaVinci Resolve"] = ":davinciresolve:",
|
|
||||||
["Default"] = ":default:",
|
|
||||||
["CleanMyMac X"] = ":desktop:",
|
|
||||||
["DEVONthink 3"] = ":devonthink3:",
|
|
||||||
["DingTalk"] = ":dingtalk:",
|
|
||||||
["钉钉"] = ":dingtalk:",
|
|
||||||
["阿里钉"] = ":dingtalk:",
|
|
||||||
["Discord"] = ":discord:",
|
|
||||||
["Discord Canary"] = ":discord:",
|
|
||||||
["Discord PTB"] = ":discord:",
|
|
||||||
["Docker"] = ":docker:",
|
|
||||||
["Docker Desktop"] = ":docker:",
|
|
||||||
["GrandTotal"] = ":dollar:",
|
|
||||||
["Receipts"] = ":dollar:",
|
|
||||||
["Double Commander"] = ":doublecmd:",
|
|
||||||
["Drafts"] = ":drafts:",
|
|
||||||
["Dropbox"] = ":dropbox:",
|
|
||||||
["Element"] = ":element:",
|
|
||||||
["Emacs"] = ":emacs:",
|
|
||||||
["Evernote Legacy"] = ":evernote_legacy:",
|
|
||||||
["FaceTime"] = ":face_time:",
|
|
||||||
["FaceTime 通话"] = ":face_time:",
|
|
||||||
["Figma"] = ":figma:",
|
|
||||||
["Final Cut Pro"] = ":final_cut_pro:",
|
|
||||||
["Finder"] = ":finder:",
|
|
||||||
["访达"] = ":finder:",
|
|
||||||
["Firefox"] = ":firefox:",
|
|
||||||
["Firefox Developer Edition"] = ":firefox_developer_edition:",
|
|
||||||
["Firefox Nightly"] = ":firefox_developer_edition:",
|
|
||||||
["Folx"] = ":folx:",
|
|
||||||
["Fusion"] = ":fusion:",
|
|
||||||
["System Preferences"] = ":gear:",
|
|
||||||
["System Settings"] = ":gear:",
|
|
||||||
["Systemeinstellungen"] = ":gear:",
|
|
||||||
["系统设置"] = ":gear:",
|
|
||||||
["Réglages Système"] = ":gear:",
|
|
||||||
["GitHub Desktop"] = ":git_hub:",
|
|
||||||
["Godot"] = ":godot:",
|
|
||||||
["GoLand"] = ":goland:",
|
|
||||||
["Chromium"] = ":google_chrome:",
|
|
||||||
["Google Chrome"] = ":google_chrome:",
|
|
||||||
["Google Chrome Canary"] = ":google_chrome:",
|
|
||||||
["Grammarly Editor"] = ":grammarly:",
|
|
||||||
["Home Assistant"] = ":home_assistant:",
|
|
||||||
["Hyper"] = ":hyper:",
|
|
||||||
["IntelliJ IDEA"] = ":idea:",
|
|
||||||
["Inkdrop"] = ":inkdrop:",
|
|
||||||
["Inkscape"] = ":inkscape:",
|
|
||||||
["Insomnia"] = ":insomnia:",
|
|
||||||
["Iris"] = ":iris:",
|
|
||||||
["iTerm"] = ":iterm:",
|
|
||||||
["iTerm2"] = ":iterm:",
|
|
||||||
["Jellyfin Media Player"] = ":jellyfin:",
|
|
||||||
["Joplin"] = ":joplin:",
|
|
||||||
["카카오톡"] = ":kakaotalk:",
|
|
||||||
["KakaoTalk"] = ":kakaotalk:",
|
|
||||||
["Kakoune"] = ":kakoune:",
|
|
||||||
["KeePassXC"] = ":kee_pass_x_c:",
|
|
||||||
["Secrets"] = ":one_password:",
|
|
||||||
["Keyboard Maestro"] = ":keyboard_maestro:",
|
|
||||||
["Keynote"] = ":keynote:",
|
|
||||||
["Keynote 讲演"] = ":keynote:",
|
|
||||||
["kitty"] = ":kitty:",
|
|
||||||
["League of Legends"] = ":league_of_legends:",
|
|
||||||
["LibreWolf"] = ":libre_wolf:",
|
|
||||||
["Adobe Lightroom"] = ":lightroom:",
|
|
||||||
["Lightroom Classic"] = ":lightroomclassic:",
|
|
||||||
["LINE"] = ":line:",
|
|
||||||
["Linear"] = ":linear:",
|
|
||||||
["LM Studio"] = ":lm_studio:",
|
|
||||||
["LocalSend"] = ":localsend:",
|
|
||||||
["Logic Pro"] = ":logicpro:",
|
|
||||||
["Logseq"] = ":logseq:",
|
|
||||||
["Canary Mail"] = ":mail:",
|
|
||||||
["HEY"] = ":mail:",
|
|
||||||
["Mail"] = ":mail:",
|
|
||||||
["Mailspring"] = ":mail:",
|
|
||||||
["MailMate"] = ":mail:",
|
|
||||||
["Superhuman"] = ":mail:",
|
|
||||||
["邮件"] = ":mail:",
|
|
||||||
["MAMP"] = ":mamp:",
|
|
||||||
["MAMP PRO"] = ":mamp:",
|
|
||||||
["Maps"] = ":maps:",
|
|
||||||
["Google Maps"] = ":maps:",
|
|
||||||
["Matlab"] = ":matlab:",
|
|
||||||
["Mattermost"] = ":mattermost:",
|
|
||||||
["Messages"] = ":messages:",
|
|
||||||
["信息"] = ":messages:",
|
|
||||||
["Nachrichten"] = ":messages:",
|
|
||||||
["Messenger"] = ":messenger:",
|
|
||||||
["Microsoft Edge"] = ":microsoft_edge:",
|
|
||||||
["Microsoft Excel"] = ":microsoft_excel:",
|
|
||||||
["Microsoft Outlook"] = ":microsoft_outlook:",
|
|
||||||
["Microsoft PowerPoint"] = ":microsoft_power_point:",
|
|
||||||
["Microsoft Remote Desktop"] = ":microsoft_remote_desktop:",
|
|
||||||
["Microsoft Teams"] = ":microsoft_teams:",
|
|
||||||
["Microsoft Teams (work or school)"] = ":microsoft_teams:",
|
|
||||||
["Microsoft Word"] = ":microsoft_word:",
|
|
||||||
["Min"] = ":min_browser:",
|
|
||||||
["Miro"] = ":miro:",
|
|
||||||
["MongoDB Compass"] = ":mongodb:",
|
|
||||||
["mpv"] = ":mpv:",
|
|
||||||
["Mullvad Browser"] = ":mullvad_browser:",
|
|
||||||
["Music"] = ":music:",
|
|
||||||
["音乐"] = ":music:",
|
|
||||||
["Musique"] = ":music:",
|
|
||||||
["Neovide"] = ":neovide:",
|
|
||||||
["neovide"] = ":neovide:",
|
|
||||||
["Neovim"] = ":neovim:",
|
|
||||||
["neovim"] = ":neovim:",
|
|
||||||
["nvim"] = ":neovim:",
|
|
||||||
["网易云音乐"] = ":netease_music:",
|
|
||||||
["Noodl"] = ":noodl:",
|
|
||||||
["Noodl Editor"] = ":noodl:",
|
|
||||||
["NordVPN"] = ":nord_vpn:",
|
|
||||||
["Notability"] = ":notability:",
|
|
||||||
["Notes"] = ":notes:",
|
|
||||||
["Notizen"] = ":notes:",
|
|
||||||
["备忘录"] = ":notes:",
|
|
||||||
["Notion"] = ":notion:",
|
|
||||||
["Nova"] = ":nova:",
|
|
||||||
["Numbers"] = ":numbers:",
|
|
||||||
["Numbers 表格"] = ":numbers:",
|
|
||||||
["Obsidian"] = ":obsidian:",
|
|
||||||
["OBS"] = ":obsstudio:",
|
|
||||||
["OmniFocus"] = ":omni_focus:",
|
|
||||||
["1Password"] = ":one_password:",
|
|
||||||
["ChatGPT"] = ":openai:",
|
|
||||||
["OpenVPN Connect"] = ":openvpn_connect:",
|
|
||||||
["Opera"] = ":opera:",
|
|
||||||
["OrcaSlicer"] = ":orcaslicer:",
|
|
||||||
["Orion"] = ":orion:",
|
|
||||||
["Orion RC"] = ":orion:",
|
|
||||||
["Pages"] = ":pages:",
|
|
||||||
["Pages 文稿"] = ":pages:",
|
|
||||||
["Parallels Desktop"] = ":parallels:",
|
|
||||||
["Parsec"] = ":parsec:",
|
|
||||||
["Preview"] = ":pdf:",
|
|
||||||
["预览"] = ":pdf:",
|
|
||||||
["Skim"] = ":pdf:",
|
|
||||||
["zathura"] = ":pdf:",
|
|
||||||
["Aperçu"] = ":pdf:",
|
|
||||||
["PDF Expert"] = ":pdf_expert:",
|
|
||||||
["Adobe Photoshop"] = ":photoshop:",
|
|
||||||
["Pi-hole Remote"] = ":pihole:",
|
|
||||||
["Pine"] = ":pine:",
|
|
||||||
["Podcasts"] = ":podcasts:",
|
|
||||||
["播客"] = ":podcasts:",
|
|
||||||
["PomoDone App"] = ":pomodone:",
|
|
||||||
["Postman"] = ":postman:",
|
|
||||||
["PrusaSlicer"] = ":prusaslicer:",
|
|
||||||
["SuperSlicer"] = ":prusaslicer:",
|
|
||||||
["PyCharm"] = ":pycharm:",
|
|
||||||
["QQ"] = ":qq:",
|
|
||||||
["QQ音乐"] = ":qqmusic:",
|
|
||||||
["QQMusic"] = ":qqmusic:",
|
|
||||||
["Quantumult X"] = ":quantumult_x:",
|
|
||||||
["qutebrowser"] = ":qute_browser:",
|
|
||||||
["Raindrop.io"] = ":raindrop_io:",
|
|
||||||
["Reeder"] = ":reeder5:",
|
|
||||||
["Reminders"] = ":reminders:",
|
|
||||||
["提醒事项"] = ":reminders:",
|
|
||||||
["Rappels"] = ":reminders:",
|
|
||||||
["Replit"] = ":replit:",
|
|
||||||
["Rider"] = ":rider:",
|
|
||||||
["JetBrains Rider"] = ":rider:",
|
|
||||||
["Safari"] = ":safari:",
|
|
||||||
["Safari浏览器"] = ":safari:",
|
|
||||||
["Safari Technology Preview"] = ":safari:",
|
|
||||||
["Sequel Ace"] = ":sequel_ace:",
|
|
||||||
["Sequel Pro"] = ":sequel_pro:",
|
|
||||||
["Setapp"] = ":setapp:",
|
|
||||||
["SF Symbols"] = ":sf_symbols:",
|
|
||||||
["Signal"] = ":signal:",
|
|
||||||
["Sketch"] = ":sketch:",
|
|
||||||
["Skype"] = ":skype:",
|
|
||||||
["Slack"] = ":slack:",
|
|
||||||
["Spark"] = ":spark:",
|
|
||||||
["Spotify"] = ":spotify:",
|
|
||||||
["Spotlight"] = ":spotlight:",
|
|
||||||
["Sublime Text"] = ":sublime_text:",
|
|
||||||
["Tana"] = ":tana:",
|
|
||||||
["TeamSpeak 3"] = ":team_speak:",
|
|
||||||
["Telegram"] = ":telegram:",
|
|
||||||
["Terminal"] = ":terminal:",
|
|
||||||
["终端"] = ":terminal:",
|
|
||||||
["Typora"] = ":text:",
|
|
||||||
["Microsoft To Do"] = ":things:",
|
|
||||||
["Things"] = ":things:",
|
|
||||||
["Thunderbird"] = ":thunderbird:",
|
|
||||||
["TickTick"] = ":tick_tick:",
|
|
||||||
["TIDAL"] = ":tidal:",
|
|
||||||
["Tiny RDM"] = ":tinyrdm:",
|
|
||||||
["Todoist"] = ":todoist:",
|
|
||||||
["Toggl Track"] = ":toggl_track:",
|
|
||||||
["Tor Browser"] = ":tor_browser:",
|
|
||||||
["Tower"] = ":tower:",
|
|
||||||
["Transmit"] = ":transmit:",
|
|
||||||
["Trello"] = ":trello:",
|
|
||||||
["Tweetbot"] = ":twitter:",
|
|
||||||
["Twitter"] = ":twitter:",
|
|
||||||
["MacVim"] = ":vim:",
|
|
||||||
["Vim"] = ":vim:",
|
|
||||||
["VimR"] = ":vim:",
|
|
||||||
["Vivaldi"] = ":vivaldi:",
|
|
||||||
["VLC"] = ":vlc:",
|
|
||||||
["VMware Fusion"] = ":vmware_fusion:",
|
|
||||||
["VSCodium"] = ":vscodium:",
|
|
||||||
["Warp"] = ":warp:",
|
|
||||||
["WebStorm"] = ":web_storm:",
|
|
||||||
["微信"] = ":wechat:",
|
|
||||||
["WeChat"] = ":wechat:",
|
|
||||||
["企业微信"] = ":wecom:",
|
|
||||||
["WeCom"] = ":wecom:",
|
|
||||||
["WezTerm"] = ":wezterm:",
|
|
||||||
["WhatsApp"] = ":whats_app:",
|
|
||||||
["WhatsApp"] = ":whats_app:",
|
|
||||||
["Xcode"] = ":xcode:",
|
|
||||||
["Яндекс Музыка"] = ":yandex_music:",
|
|
||||||
["Yuque"] = ":yuque:",
|
|
||||||
["语雀"] = ":yuque:",
|
|
||||||
["Zed"] = ":zed:",
|
|
||||||
["Zeplin"] = ":zeplin:",
|
|
||||||
["zoom.us"] = ":zoom:",
|
|
||||||
["Zotero"] = ":zotero:",
|
|
||||||
["Zulip"] = ":zulip:",
|
|
||||||
["default"] = ":default:",
|
|
||||||
["Ghostty"] = ":ghostty:"
|
|
||||||
}
|
|
||||||
|
|
||||||
local text <const> = {
|
|
||||||
nerdfont = {
|
|
||||||
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 = "",
|
|
||||||
},
|
|
||||||
slider = {
|
|
||||||
knob = ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
text = text.nerdfont,
|
|
||||||
apps = apps,
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
return require("config.settings")
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
local colors <const> = require("config.colors")
|
|
||||||
local fonts <const> = require("config.fonts")
|
|
||||||
local icons <const> = require("config.icons")
|
|
||||||
local dimens <const> = require("config.dimens")
|
|
||||||
|
|
||||||
return {
|
|
||||||
fonts = fonts,
|
|
||||||
dimens = dimens,
|
|
||||||
colors = colors,
|
|
||||||
icons = icons,
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
local events <const> = {
|
|
||||||
AEROSPACE_WORKSPACE_CHANGED = "aerospace_workspace_changed",
|
|
||||||
AEROSPACE_SWITCH = "aerospace_switch",
|
|
||||||
SWAP_MENU_AND_SPACES = "swap_menu_and_spaces",
|
|
||||||
FRONT_APP_SWITCHED = "front_app_switched",
|
|
||||||
UPDATE_WINDOWS = "update_windows",
|
|
||||||
SEND_MESSAGE = "send_message",
|
|
||||||
HIDE_MESSAGE = "hide_message",
|
|
||||||
}
|
|
||||||
|
|
||||||
local items <const> = {
|
|
||||||
SPACES = "workspaces",
|
|
||||||
MENU = "menu",
|
|
||||||
MENU_TOGGLE = "menu_toggle",
|
|
||||||
FRONT_APPS = "front_apps",
|
|
||||||
MESSAGE = "message",
|
|
||||||
VOLUME = "widgets.volume",
|
|
||||||
WIFI = "widgets.wifi",
|
|
||||||
BATTERY = "widgets.battery",
|
|
||||||
CALENDAR = "widgets.calendar",
|
|
||||||
}
|
|
||||||
|
|
||||||
local aerospace <const> = {
|
|
||||||
LIST_ALL_WORKSPACES = "aerospace list-workspaces --all",
|
|
||||||
GET_CURRENT_WORKSPACE = "aerospace list-workspaces --focused",
|
|
||||||
LIST_WINDOWS = "aerospace list-windows --workspace focused --format \"id=%{window-id}, name=%{app-name}\"",
|
|
||||||
GET_CURRENT_WINDOW = "aerospace list-windows --focused --format %{app-name}",
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
items = items,
|
|
||||||
events = events,
|
|
||||||
aerospace = aerospace,
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
local settings = require("config.settings")
|
|
||||||
|
|
||||||
sbar.default({
|
|
||||||
updates = "when_shown",
|
|
||||||
icon = {
|
|
||||||
font = {
|
|
||||||
family = settings.fonts.text,
|
|
||||||
style = settings.fonts.styles.regular,
|
|
||||||
size = settings.dimens.text.icon,
|
|
||||||
},
|
|
||||||
color = settings.colors.purple,
|
|
||||||
padding_left = settings.dimens.padding.icon,
|
|
||||||
padding_right = settings.dimens.padding.icon,
|
|
||||||
},
|
|
||||||
label = {
|
|
||||||
font = {
|
|
||||||
family = settings.fonts.text,
|
|
||||||
style = settings.fonts.styles.regular,
|
|
||||||
size = settings.dimens.text.label,
|
|
||||||
},
|
|
||||||
color = settings.colors.purple,
|
|
||||||
padding_left = settings.dimens.padding.label,
|
|
||||||
padding_right = settings.dimens.padding.label,
|
|
||||||
},
|
|
||||||
background = {
|
|
||||||
-- color = settings.colors.black,
|
|
||||||
height = settings.dimens.graphics.background.height,
|
|
||||||
corner_radius = settings.dimens.graphics.background.corner_radius,
|
|
||||||
border_width = 0,
|
|
||||||
image = {
|
|
||||||
corner_radius = settings.dimens.graphics.background.corner_radius
|
|
||||||
}
|
|
||||||
},
|
|
||||||
popup = {
|
|
||||||
y_offset = settings.dimens.padding.popup,
|
|
||||||
align = "center",
|
|
||||||
background = {
|
|
||||||
border_width = 0,
|
|
||||||
corner_radius = settings.dimens.graphics.background.corner_radius,
|
|
||||||
color = settings.colors.popup.bg,
|
|
||||||
shadow = { drawing = true },
|
|
||||||
padding_left = settings.dimens.padding.icon,
|
|
||||||
padding_right = settings.dimens.padding.icon,
|
|
||||||
},
|
|
||||||
blur_radius = settings.dimens.graphics.blur_radius,
|
|
||||||
},
|
|
||||||
slider = {
|
|
||||||
highlight_color = settings.colors.red,
|
|
||||||
background = {
|
|
||||||
height = settings.dimens.graphics.slider.height,
|
|
||||||
corner_radius = settings.dimens.graphics.background.corner_radius,
|
|
||||||
color = settings.colors.slider.bg,
|
|
||||||
border_color = settings.colors.slider.border,
|
|
||||||
border_width = 1,
|
|
||||||
},
|
|
||||||
knob = {
|
|
||||||
font = {
|
|
||||||
family = settings.fonts.text,
|
|
||||||
style = settings.fonts.styles.regular,
|
|
||||||
size = 32,
|
|
||||||
},
|
|
||||||
string = settings.icons.text.slider.knob,
|
|
||||||
drawing = false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
scroll_texts = true,
|
|
||||||
})
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
require("install.sbar")
|
|
||||||
|
|
||||||
sbar = require("sketchybar")
|
|
||||||
|
|
||||||
sbar.begin_config()
|
|
||||||
sbar.hotload(true)
|
|
||||||
|
|
||||||
require("constants")
|
|
||||||
require("config")
|
|
||||||
require("bar")
|
|
||||||
require("default")
|
|
||||||
require("items")
|
|
||||||
|
|
||||||
sbar.end_config()
|
|
||||||
sbar.event_loop()
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
require("install.sbar")
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
local sbarpath = "/Users/" .. os.getenv("USER") .. "/.local/share/sketchybar_lua/"
|
|
||||||
|
|
||||||
local function exists(file)
|
|
||||||
local ok, err, code = os.rename(file, file)
|
|
||||||
if not ok then
|
|
||||||
if code == 13 then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return ok, err
|
|
||||||
end
|
|
||||||
|
|
||||||
local function isdir(path)
|
|
||||||
return exists(path .. "/")
|
|
||||||
end
|
|
||||||
|
|
||||||
if not isdir(sbarpath) then
|
|
||||||
os.execute(
|
|
||||||
"git clone https://github.com/FelixKratz/SbarLua.git /tmp/SbarLua && cd /tmp/SbarLua && make install && rm -rf /tmp/SbarLua/"
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
package.cpath = package.cpath .. ";" .. sbarpath .. "?.so"
|
|
||||||
|
|
||||||
os.execute("(cd bridge && make)")
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
local settings = require("config.settings")
|
|
||||||
|
|
||||||
local apple = sbar.add("item", "apple", {
|
|
||||||
icon = { string = settings.icons.text.apple },
|
|
||||||
label = { drawing = false },
|
|
||||||
click_script = "$CONFIG_DIR/items/menus/bin/menus -s 0"
|
|
||||||
})
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
local constants = require("constants")
|
|
||||||
local settings = require("config.settings")
|
|
||||||
|
|
||||||
local frontApps = {}
|
|
||||||
|
|
||||||
sbar.add("bracket", constants.items.FRONT_APPS, {}, { position = "left" })
|
|
||||||
|
|
||||||
local frontAppWatcher = sbar.add("item", {
|
|
||||||
drawing = false,
|
|
||||||
updates = true,
|
|
||||||
})
|
|
||||||
|
|
||||||
local function selectFocusedWindow(frontAppName)
|
|
||||||
for appName, app in pairs(frontApps) do
|
|
||||||
local isSelected = appName == frontAppName
|
|
||||||
local color = isSelected and settings.colors.magenta or settings.colors.white
|
|
||||||
app:set(
|
|
||||||
{
|
|
||||||
label = { color = color },
|
|
||||||
icon = { color = color },
|
|
||||||
}
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function updateWindows(windows)
|
|
||||||
sbar.remove("/" .. constants.items.FRONT_APPS .. "\\.*/")
|
|
||||||
|
|
||||||
frontApps = {}
|
|
||||||
local foundWindows = string.gmatch(windows, "[^\n]+")
|
|
||||||
for window in foundWindows do
|
|
||||||
local parsedWindow = {}
|
|
||||||
for key, value in string.gmatch(window, "(%w+)=([%w%s]+)") do
|
|
||||||
parsedWindow[key] = value
|
|
||||||
end
|
|
||||||
|
|
||||||
local windowId = parsedWindow["id"]
|
|
||||||
local windowName = parsedWindow["name"]
|
|
||||||
local icon = settings.icons.apps[windowName] or settings.icons.apps["default"]
|
|
||||||
|
|
||||||
frontApps[windowName] = sbar.add("item", constants.items.FRONT_APPS .. "." .. windowName, {
|
|
||||||
label = {
|
|
||||||
padding_left = 0,
|
|
||||||
string = windowName,
|
|
||||||
},
|
|
||||||
icon = {
|
|
||||||
string = icon,
|
|
||||||
font = settings.fonts.icons(),
|
|
||||||
},
|
|
||||||
click_script = "aerospace focus --window-id " .. windowId,
|
|
||||||
})
|
|
||||||
|
|
||||||
frontApps[windowName]:subscribe(constants.events.FRONT_APP_SWITCHED, function(env)
|
|
||||||
selectFocusedWindow(env.INFO)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
sbar.exec(constants.aerospace.GET_CURRENT_WINDOW, function(frontAppName)
|
|
||||||
selectFocusedWindow(frontAppName:gsub("[\n\r]", ""))
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function getWindows()
|
|
||||||
sbar.exec(constants.aerospace.LIST_WINDOWS, updateWindows)
|
|
||||||
end
|
|
||||||
|
|
||||||
frontAppWatcher:subscribe(constants.events.UPDATE_WINDOWS, function()
|
|
||||||
getWindows()
|
|
||||||
end)
|
|
||||||
|
|
||||||
getWindows()
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
-- Left items
|
|
||||||
--require("items.apple")
|
|
||||||
require("items.menu_spaces_toggle")
|
|
||||||
require("items.menus")
|
|
||||||
require("items.spaces")
|
|
||||||
require("items.front_apps")
|
|
||||||
|
|
||||||
-- Right items
|
|
||||||
require("items.message")
|
|
||||||
require("items.widgets")
|
|
||||||
--require("items.media")
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
local colors = require("config.colors")
|
|
||||||
|
|
||||||
local whitelist = {
|
|
||||||
["Psst"] = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
local media_cover = sbar.add("item", {
|
|
||||||
position = "left",
|
|
||||||
background = {
|
|
||||||
image = {
|
|
||||||
string = "media.artwork",
|
|
||||||
scale = 0.80,
|
|
||||||
},
|
|
||||||
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 = "left",
|
|
||||||
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 = 24,
|
|
||||||
y_offset = 6,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
local media_title = sbar.add("item", {
|
|
||||||
position = "left",
|
|
||||||
drawing = false,
|
|
||||||
padding_left = 3,
|
|
||||||
padding_right = 0,
|
|
||||||
icon = { drawing = false },
|
|
||||||
label = {
|
|
||||||
font = { size = 11 },
|
|
||||||
width = 0,
|
|
||||||
max_chars = 35,
|
|
||||||
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)
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
local constants = require("constants")
|
|
||||||
local settings = require("config.settings")
|
|
||||||
|
|
||||||
sbar.add("event", constants.events.SWAP_MENU_AND_SPACES)
|
|
||||||
|
|
||||||
local function switchToggle(menuToggle)
|
|
||||||
local isShowingMenu = menuToggle:query().icon.value == settings.icons.text.switch.on
|
|
||||||
|
|
||||||
menuToggle:set({
|
|
||||||
icon = isShowingMenu and settings.icons.text.switch.off or settings.icons.text.switch.on,
|
|
||||||
label = isShowingMenu and "Menus" or "Spaces",
|
|
||||||
})
|
|
||||||
|
|
||||||
sbar.trigger(constants.events.SWAP_MENU_AND_SPACES, { isShowingMenu = isShowingMenu })
|
|
||||||
end
|
|
||||||
|
|
||||||
local function addToggle()
|
|
||||||
local menuToggle = sbar.add("item", constants.items.MENU_TOGGLE, {
|
|
||||||
icon = {
|
|
||||||
string = settings.icons.text.switch.on
|
|
||||||
},
|
|
||||||
label = {
|
|
||||||
width = 0,
|
|
||||||
color = settings.colors.bg1,
|
|
||||||
string = "Spaces",
|
|
||||||
},
|
|
||||||
background = {
|
|
||||||
color = settings.colors.with_alpha(settings.colors.purple, 0.0),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
sbar.add("item", constants.items.MENU_TOGGLE .. ".padding", {
|
|
||||||
width = settings.dimens.padding.label
|
|
||||||
})
|
|
||||||
|
|
||||||
menuToggle:subscribe("mouse.entered", function(env)
|
|
||||||
sbar.animate("tanh", 30, function()
|
|
||||||
menuToggle:set({
|
|
||||||
background = {
|
|
||||||
color = { alpha = 1.0 },
|
|
||||||
border_color = { alpha = 0.5 },
|
|
||||||
},
|
|
||||||
icon = { color = settings.colors.bg1 },
|
|
||||||
label = { width = "dynamic" }
|
|
||||||
})
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
|
|
||||||
menuToggle:subscribe("mouse.exited", function(env)
|
|
||||||
sbar.animate("tanh", 30, function()
|
|
||||||
menuToggle:set({
|
|
||||||
background = {
|
|
||||||
color = { alpha = 0.0 },
|
|
||||||
border_color = { alpha = 0.0 },
|
|
||||||
},
|
|
||||||
icon = { color = settings.colors.red },
|
|
||||||
label = { width = 0 }
|
|
||||||
})
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
|
|
||||||
menuToggle:subscribe("mouse.clicked", function(env)
|
|
||||||
switchToggle(menuToggle)
|
|
||||||
end)
|
|
||||||
|
|
||||||
menuToggle:subscribe(constants.events.AEROSPACE_SWITCH, function(env)
|
|
||||||
switchToggle(menuToggle)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
addToggle()
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
local constants = require("constants")
|
|
||||||
local settings = require("config.settings")
|
|
||||||
|
|
||||||
local maxItems <const> = 15
|
|
||||||
local menuItems = {}
|
|
||||||
local isShowingMenu = false
|
|
||||||
|
|
||||||
local frontAppWatcher = sbar.add("item", {
|
|
||||||
drawing = false,
|
|
||||||
updates = true,
|
|
||||||
})
|
|
||||||
|
|
||||||
local swapWatcher = sbar.add("item", {
|
|
||||||
drawing = false,
|
|
||||||
updates = true,
|
|
||||||
})
|
|
||||||
|
|
||||||
local function createPlaceholders()
|
|
||||||
for index = 1, maxItems, 1 do
|
|
||||||
local menu = sbar.add("item", constants.items.MENU .. "." .. index, {
|
|
||||||
drawing = false,
|
|
||||||
icon = { drawing = false },
|
|
||||||
width = "dynamic",
|
|
||||||
label = {
|
|
||||||
font = {
|
|
||||||
style = index == 1 and settings.fonts.styles.bold or settings.fonts.styles.regular,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
click_script = "$CONFIG_DIR/bridge/menus/bin/menus -s " .. index,
|
|
||||||
})
|
|
||||||
menuItems[index] = menu
|
|
||||||
end
|
|
||||||
|
|
||||||
sbar.add("bracket", { "/" .. constants.items.MENU .. "\\..*/" }, {
|
|
||||||
background = {
|
|
||||||
color = settings.colors.bg1,
|
|
||||||
padding_left = settings.dimens.padding.item,
|
|
||||||
padding_right = settings.dimens.padding.item,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
local function updateMenus()
|
|
||||||
sbar.set("/" .. constants.items.MENU .. "\\..*/", { drawing = false })
|
|
||||||
|
|
||||||
sbar.exec("$CONFIG_DIR/bridge/menus/bin/menus -l", function(menus)
|
|
||||||
local index = 1
|
|
||||||
for menu in string.gmatch(menus, '[^\r\n]+') do
|
|
||||||
if index < maxItems then
|
|
||||||
menuItems[index]:set(
|
|
||||||
{
|
|
||||||
width = "dynamic",
|
|
||||||
label = menu,
|
|
||||||
drawing = isShowingMenu
|
|
||||||
}
|
|
||||||
)
|
|
||||||
else
|
|
||||||
break
|
|
||||||
end
|
|
||||||
index = index + 1
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
sbar.set(constants.items.MENU .. ".padding", { drawing = isShowingMenu })
|
|
||||||
end
|
|
||||||
|
|
||||||
frontAppWatcher:subscribe(constants.events.FRONT_APP_SWITCHED, updateMenus)
|
|
||||||
|
|
||||||
swapWatcher:subscribe(constants.events.SWAP_MENU_AND_SPACES, function(env)
|
|
||||||
isShowingMenu = env.isShowingMenu == "on"
|
|
||||||
updateMenus()
|
|
||||||
end)
|
|
||||||
|
|
||||||
createPlaceholders()
|
|
||||||
Binary file not shown.
@@ -1,55 +0,0 @@
|
|||||||
local constants = require("constants")
|
|
||||||
local settings = require("config.settings")
|
|
||||||
|
|
||||||
local message = sbar.add("item", constants.items.MESSAGE, {
|
|
||||||
width = 0,
|
|
||||||
position = "center",
|
|
||||||
popup = { align = "center" },
|
|
||||||
label = {
|
|
||||||
padding_left = 0,
|
|
||||||
padding_right = 0,
|
|
||||||
},
|
|
||||||
background = {
|
|
||||||
padding_left = 0,
|
|
||||||
padding_right = 0,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
local messagePopup = sbar.add("item", {
|
|
||||||
position = "popup." .. message.name,
|
|
||||||
width = "dynamic",
|
|
||||||
label = {
|
|
||||||
padding_right = settings.dimens.padding.label,
|
|
||||||
padding_left = settings.dimens.padding.label,
|
|
||||||
},
|
|
||||||
icon = {
|
|
||||||
padding_left = 0,
|
|
||||||
padding_right = 0,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
local function hideMessage()
|
|
||||||
message:set({ popup = { drawing = false } })
|
|
||||||
end
|
|
||||||
|
|
||||||
local function showMessage(content, hold)
|
|
||||||
hideMessage()
|
|
||||||
|
|
||||||
message:set({ popup = { drawing = true } })
|
|
||||||
messagePopup:set({ label = { string = content } })
|
|
||||||
|
|
||||||
if hold == false then
|
|
||||||
sbar.delay(5, function()
|
|
||||||
if hold then return end
|
|
||||||
hideMessage()
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
message:subscribe(constants.events.SEND_MESSAGE, function(env)
|
|
||||||
local content = env.MESSAGE
|
|
||||||
local hold = env.HOLD ~= nil and env.HOLD == "true" or false
|
|
||||||
showMessage(content, hold)
|
|
||||||
end)
|
|
||||||
|
|
||||||
message:subscribe(constants.events.HIDE_MESSAGE, hideMessage)
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
local constants = require("constants")
|
|
||||||
local settings = require("config.settings")
|
|
||||||
|
|
||||||
local spaces = {}
|
|
||||||
|
|
||||||
local swapWatcher = sbar.add("item", {
|
|
||||||
drawing = false,
|
|
||||||
updates = true,
|
|
||||||
})
|
|
||||||
|
|
||||||
local currentWorkspaceWatcher = sbar.add("item", {
|
|
||||||
drawing = false,
|
|
||||||
updates = true,
|
|
||||||
})
|
|
||||||
|
|
||||||
-- Modify this file with Visual Studio Code - at least vim does have problems with the icons
|
|
||||||
-- copy "Icons" from the nerd fonts cheat sheet and replace icon and name accordingly below
|
|
||||||
-- https://www.nerdfonts.com/cheat-sheet
|
|
||||||
local spaceConfigs <const> = {
|
|
||||||
["1"] = { icon = "", name = "Main" },
|
|
||||||
["2"] = { icon = "", name = "Terminal" },
|
|
||||||
["3"] = { icon = "", name = "Code" },
|
|
||||||
["4"] = { icon = "", name = "Notes" },
|
|
||||||
["5"] = { icon = "", name = "Security" },
|
|
||||||
["D"] = { icon = "", name = "Discord" },
|
|
||||||
["S"] = { icon = "", name = "Music"},
|
|
||||||
}
|
|
||||||
|
|
||||||
local function selectCurrentWorkspace(focusedWorkspaceName)
|
|
||||||
for sid, item in pairs(spaces) do
|
|
||||||
if item ~= nil then
|
|
||||||
local isSelected = sid == constants.items.SPACES .. "." .. focusedWorkspaceName
|
|
||||||
item:set({
|
|
||||||
icon = { color = isSelected and settings.colors.bg1 or settings.colors.bg1 },
|
|
||||||
label = { color = isSelected and settings.colors.bg1 or settings.colors.bg1 },
|
|
||||||
background = { color = isSelected and settings.colors.magenta or settings.colors.purple },
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
sbar.trigger(constants.events.UPDATE_WINDOWS)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function findAndSelectCurrentWorkspace()
|
|
||||||
sbar.exec(constants.aerospace.GET_CURRENT_WORKSPACE, function(focusedWorkspaceOutput)
|
|
||||||
local focusedWorkspaceName = focusedWorkspaceOutput:match("[^\r\n]+")
|
|
||||||
selectCurrentWorkspace(focusedWorkspaceName)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function addWorkspaceItem(workspaceName)
|
|
||||||
local spaceName = constants.items.SPACES .. "." .. workspaceName
|
|
||||||
local spaceConfig = spaceConfigs[workspaceName]
|
|
||||||
|
|
||||||
spaces[spaceName] = sbar.add("item", spaceName, {
|
|
||||||
label = {
|
|
||||||
width = 0,
|
|
||||||
padding_left = 0,
|
|
||||||
string = spaceConfig.name,
|
|
||||||
},
|
|
||||||
icon = {
|
|
||||||
string = spaceConfig.icon or settings.icons.apps["default"],
|
|
||||||
color = settings.colors.white,
|
|
||||||
},
|
|
||||||
background = {
|
|
||||||
color = settings.colors.bg1,
|
|
||||||
},
|
|
||||||
click_script = "aerospace workspace " .. workspaceName,
|
|
||||||
})
|
|
||||||
|
|
||||||
spaces[spaceName]:subscribe("mouse.entered", function(env)
|
|
||||||
sbar.animate("tanh", 30, function()
|
|
||||||
spaces[spaceName]:set({ label = { width = "dynamic" } })
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
|
|
||||||
spaces[spaceName]:subscribe("mouse.exited", function(env)
|
|
||||||
sbar.animate("tanh", 30, function()
|
|
||||||
spaces[spaceName]:set({ label = { width = 0 } })
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
|
|
||||||
sbar.add("item", spaceName .. ".padding", {
|
|
||||||
width = settings.dimens.padding.label
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
local function createWorkspaces()
|
|
||||||
sbar.exec(constants.aerospace.LIST_ALL_WORKSPACES, function(workspacesOutput)
|
|
||||||
for workspaceName in workspacesOutput:gmatch("[^\r\n]+") do
|
|
||||||
addWorkspaceItem(workspaceName)
|
|
||||||
end
|
|
||||||
|
|
||||||
findAndSelectCurrentWorkspace()
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
swapWatcher:subscribe(constants.events.SWAP_MENU_AND_SPACES, function(env)
|
|
||||||
local isShowingSpaces = env.isShowingMenu == "off" and true or false
|
|
||||||
sbar.set("/" .. constants.items.SPACES .. "\\..*/", { drawing = isShowingSpaces })
|
|
||||||
end)
|
|
||||||
|
|
||||||
currentWorkspaceWatcher:subscribe(constants.events.AEROSPACE_WORKSPACE_CHANGED, function(env)
|
|
||||||
selectCurrentWorkspace(env.FOCUSED_WORKSPACE)
|
|
||||||
sbar.trigger(constants.events.UPDATE_WINDOWS)
|
|
||||||
end)
|
|
||||||
|
|
||||||
createWorkspaces()
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
local constants = require("constants")
|
|
||||||
local settings = require("config.settings")
|
|
||||||
|
|
||||||
local isCharging = false
|
|
||||||
|
|
||||||
local battery = sbar.add("item", constants.items.battery, {
|
|
||||||
position = "right",
|
|
||||||
update_freq = 60,
|
|
||||||
})
|
|
||||||
|
|
||||||
local batteryPopup = sbar.add("item", {
|
|
||||||
position = "popup." .. battery.name,
|
|
||||||
width = "dynamic",
|
|
||||||
label = {
|
|
||||||
padding_right = settings.dimens.padding.label,
|
|
||||||
padding_left = settings.dimens.padding.label,
|
|
||||||
},
|
|
||||||
icon = {
|
|
||||||
padding_left = 0,
|
|
||||||
padding_right = 0,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
battery:subscribe({ "routine", "power_source_change", "system_woke" }, function()
|
|
||||||
sbar.exec("pmset -g batt", function(batteryInfo)
|
|
||||||
local icon = "!"
|
|
||||||
local label = "?"
|
|
||||||
|
|
||||||
local found, _, charge = batteryInfo:find("(%d+)%%")
|
|
||||||
if found then
|
|
||||||
charge = tonumber(charge)
|
|
||||||
label = charge .. "%"
|
|
||||||
end
|
|
||||||
|
|
||||||
local color = settings.colors.green
|
|
||||||
local charging, _, _ = batteryInfo:find("AC Power")
|
|
||||||
|
|
||||||
isCharging = charging
|
|
||||||
|
|
||||||
if charging then
|
|
||||||
icon = settings.icons.text.battery.charging
|
|
||||||
else
|
|
||||||
if found and charge > 80 then
|
|
||||||
icon = settings.icons.text.battery._100
|
|
||||||
elseif found and charge > 60 then
|
|
||||||
icon = settings.icons.text.battery._75
|
|
||||||
elseif found and charge > 40 then
|
|
||||||
icon = settings.icons.text.battery._50
|
|
||||||
elseif found and charge > 30 then
|
|
||||||
icon = settings.icons.text.battery._50
|
|
||||||
color = settings.colors.yellow
|
|
||||||
elseif found and charge > 20 then
|
|
||||||
icon = settings.icons.text.battery._25
|
|
||||||
color = settings.colors.orange
|
|
||||||
else
|
|
||||||
icon = settings.icons.text.battery._0
|
|
||||||
color = settings.colors.red
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local lead = ""
|
|
||||||
if found and charge < 10 then
|
|
||||||
lead = "0"
|
|
||||||
end
|
|
||||||
|
|
||||||
battery:set({
|
|
||||||
icon = {
|
|
||||||
string = icon,
|
|
||||||
color = color
|
|
||||||
},
|
|
||||||
label = {
|
|
||||||
string = lead .. label,
|
|
||||||
padding_left = 0,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
|
|
||||||
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(batteryInfo)
|
|
||||||
local found, _, remaining = batteryInfo:find("(%d+:%d+) remaining")
|
|
||||||
local label = found and ("Time remaining: " .. remaining .. "h") or (isCharging and "Charging" or "No estimate")
|
|
||||||
batteryPopup:set({ label = label })
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
local constants = require("constants")
|
|
||||||
|
|
||||||
local calendar = sbar.add("item", constants.items.CALENDAR, {
|
|
||||||
position = "right",
|
|
||||||
update_freq = 1,
|
|
||||||
icon = { padding_left = 0, padding_right = 0 }
|
|
||||||
})
|
|
||||||
|
|
||||||
calendar:subscribe({ "forced", "routine", "system_woke" }, function(env)
|
|
||||||
calendar:set({
|
|
||||||
label = os.date("%a %d %b, %H:%M"),
|
|
||||||
})
|
|
||||||
end)
|
|
||||||
|
|
||||||
calendar:subscribe("mouse.clicked", function(env)
|
|
||||||
sbar.exec("open -a 'Calendar'")
|
|
||||||
end)
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
require("items.widgets.calendar")
|
|
||||||
require("items.widgets.battery")
|
|
||||||
require("items.widgets.volume")
|
|
||||||
require("items.widgets.wifi")
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
local constants = require("constants")
|
|
||||||
local settings = require("config.settings")
|
|
||||||
|
|
||||||
local currentAudioDevice = "None"
|
|
||||||
|
|
||||||
local volumeValue = sbar.add("item", constants.items.VOLUME .. ".value", {
|
|
||||||
position = "right",
|
|
||||||
label = {
|
|
||||||
string = "??%",
|
|
||||||
padding_left = 0,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
local volumeBracket = sbar.add("bracket", constants.items.VOLUME .. ".bracket", { volumeValue.name }, {
|
|
||||||
popup = {
|
|
||||||
align = "center"
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
local volumeSlider = sbar.add("slider", constants.items.VOLUME .. ".slider", settings.dimens.graphics.popup.width, {
|
|
||||||
position = "popup." .. volumeBracket.name,
|
|
||||||
click_script = 'osascript -e "set volume output volume $PERCENTAGE"'
|
|
||||||
})
|
|
||||||
|
|
||||||
volumeValue:subscribe("volume_change", function(env)
|
|
||||||
local icon = settings.icons.text.volume._0
|
|
||||||
local volume = tonumber(env.INFO)
|
|
||||||
|
|
||||||
sbar.exec("SwitchAudioSource -t output -c", function(result)
|
|
||||||
-- local currentOutputDevice = result:sub(1, -2)
|
|
||||||
-- if currentOutputDevice == "AirPods Max" then
|
|
||||||
-- icon = ""
|
|
||||||
-- elseif currentOutputDevice == "AirPods von Longdong Silver" or currentOutputDevice == "AirPods von Anna" then
|
|
||||||
-- icon = ""
|
|
||||||
-- elseif currentOutputDevice == "Arctis Nova Pro Wireless" then
|
|
||||||
-- icon = ""
|
|
||||||
-- elseif currentOutputDevice == "Ear (2)" then
|
|
||||||
-- icon = ""
|
|
||||||
-- elseif currentOutputDevice == "iD4" then
|
|
||||||
-- icon = ""
|
|
||||||
-- else
|
|
||||||
if volume > 60 then
|
|
||||||
icon = settings.icons.text.volume._100
|
|
||||||
elseif volume > 30 then
|
|
||||||
icon = settings.icons.text.volume._66
|
|
||||||
elseif volume > 10 then
|
|
||||||
icon = settings.icons.text.volume._33
|
|
||||||
elseif volume > 0 then
|
|
||||||
icon = settings.icons.text.volume._10
|
|
||||||
end
|
|
||||||
-- end
|
|
||||||
|
|
||||||
local lead = ""
|
|
||||||
if volume < 10 then
|
|
||||||
lead = "0"
|
|
||||||
end
|
|
||||||
|
|
||||||
-- volumeIcon:set({ label = icon })
|
|
||||||
volumeSlider:set({ slider = { percentage = volume } })
|
|
||||||
|
|
||||||
local hasVolume = volume ~= 0
|
|
||||||
volumeValue:set({
|
|
||||||
icon = icon,
|
|
||||||
label = {
|
|
||||||
string = hasVolume and lead .. volume .. "%" or "",
|
|
||||||
padding_right = hasVolume and 8 or 0,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
|
|
||||||
local function hideVolumeDetails()
|
|
||||||
local drawing = volumeBracket:query().popup.drawing == "on"
|
|
||||||
if not drawing then return end
|
|
||||||
volumeBracket:set({ popup = { drawing = false } })
|
|
||||||
sbar.remove("/" .. constants.items.VOLUME .. ".device\\.*/")
|
|
||||||
end
|
|
||||||
|
|
||||||
local function toggleVolumeDetails(env)
|
|
||||||
if env.BUTTON == "right" then
|
|
||||||
sbar.exec("open /System/Library/PreferencePanes/Sound.prefpane")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local shouldDraw = volumeBracket:query().popup.drawing == "off"
|
|
||||||
if shouldDraw then
|
|
||||||
volumeBracket:set({ popup = { drawing = true } })
|
|
||||||
|
|
||||||
sbar.exec("SwitchAudioSource -t output -c", function(result)
|
|
||||||
currentAudioDevice = result:sub(1, -2)
|
|
||||||
|
|
||||||
sbar.exec("SwitchAudioSource -a -t output", function(available)
|
|
||||||
local current = currentAudioDevice
|
|
||||||
local counter = 0
|
|
||||||
|
|
||||||
for device in string.gmatch(available, '[^\r\n]+') do
|
|
||||||
local color = settings.colors.grey
|
|
||||||
if current == device then
|
|
||||||
color = settings.colors.white
|
|
||||||
end
|
|
||||||
|
|
||||||
sbar.add("item", constants.items.VOLUME .. ".device." .. counter, {
|
|
||||||
position = "popup." .. volumeBracket.name,
|
|
||||||
align = "center",
|
|
||||||
label = { string = device, color = color },
|
|
||||||
click_script = 'SwitchAudioSource -s "' ..
|
|
||||||
device ..
|
|
||||||
'" && sketchybar --set /' .. constants.items.VOLUME .. '.device\\.*/ label.color=' ..
|
|
||||||
settings.colors.grey .. ' --set $NAME label.color=' .. settings.colors.white
|
|
||||||
|
|
||||||
})
|
|
||||||
counter = counter + 1
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
else
|
|
||||||
hideVolumeDetails()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function changeVolume(env)
|
|
||||||
local delta = env.SCROLL_DELTA
|
|
||||||
sbar.exec('osascript -e "set volume output volume (output volume of (get volume settings) + ' .. delta .. ')"')
|
|
||||||
end
|
|
||||||
|
|
||||||
volumeValue:subscribe("mouse.clicked", toggleVolumeDetails)
|
|
||||||
volumeValue:subscribe("mouse.scrolled", changeVolume)
|
|
||||||
-- volumeValue:subscribe("mouse.exited.global", hideVolumeDetails)
|
|
||||||
@@ -1,261 +0,0 @@
|
|||||||
local constants = require("constants")
|
|
||||||
local settings = require("config.settings")
|
|
||||||
|
|
||||||
local popupWidth <const> = settings.dimens.graphics.popup.width + 20
|
|
||||||
|
|
||||||
sbar.exec(
|
|
||||||
"killall network_load >/dev/null; $CONFIG_DIR/bridge/network_load/bin/network_load en0 network_update 2.0"
|
|
||||||
)
|
|
||||||
|
|
||||||
local wifiUp = sbar.add("item", constants.items.WIFI .. ".up", {
|
|
||||||
position = "right",
|
|
||||||
width = 0,
|
|
||||||
icon = {
|
|
||||||
padding_left = 0,
|
|
||||||
padding_right = 0,
|
|
||||||
font = {
|
|
||||||
style = settings.fonts.styles.bold,
|
|
||||||
size = 10.0,
|
|
||||||
},
|
|
||||||
string = settings.icons.text.wifi.upload,
|
|
||||||
},
|
|
||||||
label = {
|
|
||||||
font = {
|
|
||||||
family = settings.fonts.numbers,
|
|
||||||
style = settings.fonts.styles.bold,
|
|
||||||
size = 10.0,
|
|
||||||
},
|
|
||||||
color = settings.colors.orange,
|
|
||||||
string = "??? Bps",
|
|
||||||
},
|
|
||||||
y_offset = 4,
|
|
||||||
})
|
|
||||||
|
|
||||||
local wifiDown = sbar.add("item", constants.items.WIFI .. ".down", {
|
|
||||||
position = "right",
|
|
||||||
icon = {
|
|
||||||
padding_left = 0,
|
|
||||||
padding_right = 0,
|
|
||||||
font = {
|
|
||||||
style = settings.fonts.styles.bold,
|
|
||||||
size = 10.0,
|
|
||||||
},
|
|
||||||
string = settings.icons.text.wifi.download,
|
|
||||||
},
|
|
||||||
label = {
|
|
||||||
font = {
|
|
||||||
family = settings.fonts.numbers,
|
|
||||||
style = settings.fonts.styles.bold,
|
|
||||||
size = 10,
|
|
||||||
},
|
|
||||||
color = settings.colors.blue,
|
|
||||||
string = "??? Bps",
|
|
||||||
},
|
|
||||||
y_offset = -4,
|
|
||||||
})
|
|
||||||
|
|
||||||
local wifi = sbar.add("item", constants.items.WIFI .. ".padding", {
|
|
||||||
position = "right",
|
|
||||||
label = { drawing = false },
|
|
||||||
padding_right = 0,
|
|
||||||
})
|
|
||||||
|
|
||||||
local wifiBracket = sbar.add("bracket", constants.items.WIFI .. ".bracket", {
|
|
||||||
wifi.name,
|
|
||||||
wifiUp.name,
|
|
||||||
wifiDown.name
|
|
||||||
}, {
|
|
||||||
popup = { align = "center" }
|
|
||||||
})
|
|
||||||
|
|
||||||
local ssid = sbar.add("item", {
|
|
||||||
align = "center",
|
|
||||||
position = "popup." .. wifiBracket.name,
|
|
||||||
width = popupWidth,
|
|
||||||
height = 16,
|
|
||||||
icon = {
|
|
||||||
string = settings.icons.text.wifi.router,
|
|
||||||
font = {
|
|
||||||
style = settings.fonts.styles.bold
|
|
||||||
},
|
|
||||||
},
|
|
||||||
label = {
|
|
||||||
font = {
|
|
||||||
style = settings.fonts.styles.bold,
|
|
||||||
size = settings.dimens.text.label,
|
|
||||||
},
|
|
||||||
max_chars = 18,
|
|
||||||
string = "????????????",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
local hostname = sbar.add("item", {
|
|
||||||
position = "popup." .. wifiBracket.name,
|
|
||||||
background = {
|
|
||||||
height = 16,
|
|
||||||
},
|
|
||||||
icon = {
|
|
||||||
align = "left",
|
|
||||||
string = "Hostname:",
|
|
||||||
width = popupWidth / 2,
|
|
||||||
font = {
|
|
||||||
size = settings.dimens.text.label
|
|
||||||
},
|
|
||||||
},
|
|
||||||
label = {
|
|
||||||
max_chars = 20,
|
|
||||||
string = "????????????",
|
|
||||||
width = popupWidth / 2,
|
|
||||||
align = "right",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
local ip = sbar.add("item", {
|
|
||||||
position = "popup." .. wifiBracket.name,
|
|
||||||
background = {
|
|
||||||
height = 16,
|
|
||||||
},
|
|
||||||
icon = {
|
|
||||||
align = "left",
|
|
||||||
string = "IP:",
|
|
||||||
width = popupWidth / 2,
|
|
||||||
font = {
|
|
||||||
size = settings.dimens.text.label
|
|
||||||
},
|
|
||||||
},
|
|
||||||
label = {
|
|
||||||
align = "right",
|
|
||||||
string = "???.???.???.???",
|
|
||||||
width = popupWidth / 2,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
local router = sbar.add("item", {
|
|
||||||
position = "popup." .. wifiBracket.name,
|
|
||||||
background = {
|
|
||||||
height = 16,
|
|
||||||
},
|
|
||||||
icon = {
|
|
||||||
align = "left",
|
|
||||||
string = "Router:",
|
|
||||||
width = popupWidth / 2,
|
|
||||||
font = {
|
|
||||||
size = settings.dimens.text.label
|
|
||||||
},
|
|
||||||
},
|
|
||||||
label = {
|
|
||||||
align = "right",
|
|
||||||
string = "???.???.???.???",
|
|
||||||
width = popupWidth / 2,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
sbar.add("item", { position = "right", width = settings.dimens.padding.item })
|
|
||||||
|
|
||||||
wifiUp:subscribe("network_update", function(env)
|
|
||||||
local upColor = (env.upload == "000 Bps") and settings.colors.grey or settings.colors.orange
|
|
||||||
local downColor = (env.download == "000 Bps") and settings.colors.grey or settings.colors.blue
|
|
||||||
|
|
||||||
wifiUp:set({
|
|
||||||
icon = { color = upColor },
|
|
||||||
label = {
|
|
||||||
string = env.upload,
|
|
||||||
color = upColor
|
|
||||||
}
|
|
||||||
})
|
|
||||||
wifiDown:set({
|
|
||||||
icon = { color = downColor },
|
|
||||||
label = {
|
|
||||||
string = env.download,
|
|
||||||
color = downColor
|
|
||||||
}
|
|
||||||
})
|
|
||||||
end)
|
|
||||||
|
|
||||||
wifi:subscribe({ "wifi_change", "system_woke", "forced" }, function(env)
|
|
||||||
wifi:set({
|
|
||||||
icon = {
|
|
||||||
string = settings.icons.text.wifi.disconnected,
|
|
||||||
color = settings.colors.magenta,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
sbar.exec([[ipconfig getifaddr en0]], function(ip)
|
|
||||||
local ipConnected = not (ip == "")
|
|
||||||
|
|
||||||
local wifiIcon
|
|
||||||
local wifiColor
|
|
||||||
|
|
||||||
if ipConnected then
|
|
||||||
wifiIcon = settings.icons.text.wifi.connected
|
|
||||||
wifiColor = settings.colors.magenta
|
|
||||||
end
|
|
||||||
|
|
||||||
wifi:set({
|
|
||||||
icon = {
|
|
||||||
string = wifiIcon,
|
|
||||||
color = wifiColor,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
sbar.exec([[sleep 2; scutil --nwi | grep -m1 'utun' | awk '{ print $1 }']], function(vpn)
|
|
||||||
local isVPNConnected = not (vpn == "")
|
|
||||||
|
|
||||||
if isVPNConnected then
|
|
||||||
wifiIcon = settings.icons.text.wifi.vpn
|
|
||||||
wifiColor = settings.colors.green
|
|
||||||
end
|
|
||||||
|
|
||||||
wifi:set({
|
|
||||||
icon = {
|
|
||||||
string = wifiIcon,
|
|
||||||
color = wifiColor,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
|
|
||||||
local function hideDetails()
|
|
||||||
wifiBracket:set({ popup = { drawing = false } })
|
|
||||||
end
|
|
||||||
|
|
||||||
local function toggleDetails()
|
|
||||||
local shouldDrawDetails = wifiBracket:query().popup.drawing == "off"
|
|
||||||
|
|
||||||
if shouldDrawDetails then
|
|
||||||
wifiBracket: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 'Router: ' '/^Router: / {print $2}'", function(result)
|
|
||||||
router:set({ label = result })
|
|
||||||
end)
|
|
||||||
else
|
|
||||||
hideDetails()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function copyLabelToClipboard(env)
|
|
||||||
local label = sbar.query(env.NAME).label.value
|
|
||||||
sbar.exec("echo \"" .. label .. "\" | pbcopy")
|
|
||||||
sbar.set(env.NAME, { label = { string = settings.icons.text.clipboard, align = "center" } })
|
|
||||||
sbar.delay(1, function()
|
|
||||||
sbar.set(env.NAME, { label = { string = label, align = "right" } })
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
wifiUp:subscribe("mouse.clicked", toggleDetails)
|
|
||||||
wifiDown:subscribe("mouse.clicked", toggleDetails)
|
|
||||||
wifi:subscribe("mouse.clicked", toggleDetails)
|
|
||||||
|
|
||||||
ssid:subscribe("mouse.clicked", copyLabelToClipboard)
|
|
||||||
hostname:subscribe("mouse.clicked", copyLabelToClipboard)
|
|
||||||
ip:subscribe("mouse.clicked", copyLabelToClipboard)
|
|
||||||
router:subscribe("mouse.clicked", copyLabelToClipboard)
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
#!/usr/bin/env lua
|
|
||||||
|
|
||||||
require("init")
|
|
||||||
Reference in New Issue
Block a user