add utils into repo

This commit is contained in:
randomuser 2023-07-07 14:55:35 -05:00
commit ea581aa433
49 changed files with 2152 additions and 0 deletions

10
.gitignore vendored
View File

@ -18,3 +18,13 @@ tridactyl/tridactyl
nvim/autoload/plug.vim.old nvim/autoload/plug.vim.old
nvim/spell/ nvim/spell/
nvim/plugin nvim/plugin
utils/*.swp
utils/*.tmp
utils/c/scream
utils/c/xgetnewwindow
utils/c/timer
utils/c/boid
utils/c/a.out
utils/c/anaconda
utils/c/colors
utils/c/tmessage

1
.merging_helper Normal file
View File

@ -0,0 +1 @@
test

75
utils/Makefile Normal file
View File

@ -0,0 +1,75 @@
include config.mk
all: mkc
install: man sh c all
.PHONY: man sh mkc c
man:
mkdir -p $(DESTDIR)$(PREFIX)/man/man1
cp -f man/* $(DESTDIR)$(PREFIX)/man/man1
sh:
mkdir -p $(DESTDIR)$(PREFIX)/bin
cp -f sh/paste $(DESTDIR)$(PREFIX)/bin
cp -f sh/snapcad $(DESTDIR)$(PREFIX)/bin
cp -f sh/sfeed_yt_add $(DESTDIR)$(PREFIX)/bin
cp -f sh/disp $(DESTDIR)$(PREFIX)/bin
cp -f sh/wallpaper $(DESTDIR)$(PREFIX)/bin
cp -f sh/connect $(DESTDIR)$(PREFIX)/bin
cp -f sh/nws $(DESTDIR)$(PREFIX)/bin
cp -f sh/vol $(DESTDIR)$(PREFIX)/bin
cp -f sh/pco $(DESTDIR)$(PREFIX)/bin
cp -f sh/git-survey $(DESTDIR)$(PREFIX)/bin
cp -f sh/vim-swap-handler $(DESTDIR)$(PREFIX)/bin
cp -f sh/status $(DESTDIR)$(PREFIX)/bin
cp -f sh/statusbar $(DESTDIR)$(PREFIX)/bin
cp -f sh/cfg $(DESTDIR)$(PREFIX)/bin
cp -f sh/fire $(DESTDIR)$(PREFIX)/bin
cp -f sh/pash-dmenu $(DESTDIR)$(PREFIX)/bin
cp -f sh/pash-dmenu-backend $(DESTDIR)$(PREFIX)/bin
cp -f sh/tmenu $(DESTDIR)$(PREFIX)/bin
cp -f sh/tmenu-backend $(DESTDIR)$(PREFIX)/bin
cp -f sh/tmenu_run $(DESTDIR)$(PREFIX)/bin
cp -f sh/ss $(DESTDIR)$(PREFIX)/bin
cp -f sh/net $(DESTDIR)$(PREFIX)/bin
cp -f sh/bspwm-toggle-gaps $(DESTDIR)$(PREFIX)/bin
cp -f sh/machine $(DESTDIR)$(PREFIX)/bin
cp -f sh/brightness $(DESTDIR)$(PREFIX)/bin
cp -f sh/git-credential-gitpass $(DESTDIR)$(PREFIX)/bin
cp -f sh/capture $(DESTDIR)$(PREFIX)/bin
cp -f sh/toggle-contingency-mode $(DESTDIR)$(PREFIX)/bin
cp -f sh/keyboard $(DESTDIR)$(PREFIX)/bin
ln -sf $(DESTDIR)$(PREFIX)/bin/tmenu_run $(DESTDIR)$(PREFIX)/bin/regenerate
cp -f sh/discord $(DESTDIR)$(PREFIX)/bin
check:
shellcheck sh/*
mkc: c/scream c/timer c/boid c/anaconda c/colors c/xgetnewwindow c/tmessage
c/boid:
cc c/boid.c -o c/boid -lm -lX11
c/anaconda:
cc c/anaconda.c -o c/anaconda -lm -lX11
c/xgetnewwindow:
cc c/xgetnewwindow.c -o c/xgetnewwindow -lX11
c:
cp -f c/scream $(DESTDIR)$(PREFIX)/bin
cp -f c/timer $(DESTDIR)$(PREFIX)/bin
cp -f c/boid $(DESTDIR)$(PREFIX)/bin
cp -f c/anaconda $(DESTDIR)$(PREFIX)/bin
cp -f c/colors $(DESTDIR)$(PREFIX)/bin
cp -f c/xgetnewwindow $(DESTDIR)$(PREFIX)/bin
cp -f c/tmessage $(DESTDIR)$(PREFIX)/bin
clean:
rm -f c/scream
rm -f c/timer
rm -f c/boid
rm -f c/anaconda
rm -f c/colors
rm -f c/simplestatus
rm -f c/xgetnewwindow
rm -f c/tmessage

5
utils/TODO Normal file
View File

@ -0,0 +1,5 @@
TODO LIST
---------
- fix paste
- make the c programs less buggy and let them not suck as much

247
utils/c/anaconda.c Normal file
View File

@ -0,0 +1,247 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <X11/Xlib.h>
typedef struct point {
double x;
double y;
struct point *next;
} point;
typedef struct anaconda {
int score;
double rot;
struct point *chain;
} anaconda;
Display *d;
Window w;
XEvent e;
int s;
GC gc;
void xinit(void) {
d = XOpenDisplay(NULL);
s = DefaultScreen(d);
w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 100, 100, 1,
BlackPixel(d, s), WhitePixel(d, s));
XSelectInput(d, w, ExposureMask | KeyPressMask | PointerMotionMask);
XMapWindow(d, w);
gc = XCreateGC(d, w, 0, NULL);
}
/* thanks to
* https://stackoverflow.com/questions/3838329/how-can-i-check-if-two-segments-intersect/9997374#9997374
* for functions ccw and intersect
*/
int ccw(point *a, point *b, point *c) {
return (c->y - a->y) * (b->x - a->x) >
(b->y - a->y) * (c->x - a->x);
}
int intersect(point *a, point *b, point *c, point *d) {
return (ccw(a, c, d) != ccw(b, c, d)) && (ccw(a, b, c) != ccw(a, b, d));
}
int randrange(int b, int s) {
return rand() % (b - s + 1) + s;
}
int eucliddist(point *a, point *b) {
return sqrt(pow(a->x - b->x, 2) + pow(a->y - b->y, 2));
}
point *mkPoint(double x, double y) {
point *ret = malloc(sizeof *ret);
ret->x = x;
ret->y = y;
ret->next = NULL;
return ret;
}
point *rotate(point *p, double rot) {
double rad = rot * M_PI/180;
return mkPoint(
p->x * cos(rad) - p->y * sin(rad),
p->x * sin(rad) + p->y * cos(rad)
);
}
void appendPoint(point *dest, point *origin) {
while(dest->next) dest = dest->next;
dest->next = origin;
}
int updateAnaconda(anaconda *anaconda, point *basepoint, int w, int h, point *apple) {
point *temp, *new, *ptr;
new = anaconda->chain;
temp = rotate(basepoint, anaconda->rot);
new = mkPoint(
new->x + temp->x,
new->y + temp->y
);
new->next = anaconda->chain;
anaconda->chain = new;
free(temp);
if(eucliddist(new, apple) <= 30) {
anaconda->score += 30;
apple->x = randrange(20, w / 2);
apple->y = randrange(20, h / 2);
} else {
ptr = new;
while(1) {
if(ptr->next) {
if(ptr->next->next) ptr = ptr->next;
else break;
} else break;
}
free(ptr->next);
ptr->next = NULL;
}
ptr = anaconda->chain;
for(int i = 0; i < 3; i++) {
if(ptr->next) ptr = ptr->next;
else return 1; /* we're fine, the snake is too short to intersect itself */
}
while(ptr->next) {
if(intersect(new, new->next, ptr, ptr->next)) return 0;
ptr = ptr->next;
}
if(
new->x >= w || new->x <= 0 ||
new->y >= h || new->y <= 0
) return 0;
if(eucliddist(new, apple) <= 30) {
anaconda->score += 30;
apple->x = randrange(20, w / 2);
apple->y = randrange(20, h / 2);
}
return 1;
}
void freeAnaconda(anaconda *anaconda) {
point *current = anaconda->chain;
point *next = NULL;
for(;;) {
if(!current) break;
next = current->next;
free(current);
current = next;
}
free(anaconda);
return;
}
point *generateChain(int length) {
point *ret = mkPoint(100, 100);
point *head = ret;
for(int i = 1; i < length - 1; i++) {
ret->next = mkPoint(
10 * i + 100,
5 * i + 100
);
ret = ret->next;
}
return head;
}
anaconda *mkAnaconda(point *point, double rot) {
anaconda *ret = malloc(sizeof *ret);
ret->chain = point;
ret->rot = rot;
ret->score = 0;
return ret;
}
int main(void) {
anaconda *anaconda = mkAnaconda(generateChain(30), 0);
point *basepoint = mkPoint(10, 0);
char scorebuffer[30];
xinit();
srand(time(0));
int width = DisplayWidth(d, s);
int height = DisplayHeight(d, s);
point *apple = mkPoint(randrange(20, width / 2 - 20), randrange(20, height / 2 - 20));
int exposed = 0;
while(1) {
if(exposed) {
if(!updateAnaconda(anaconda, basepoint, width, height, apple)) {
freeAnaconda(anaconda);
free(apple);
free(basepoint);
return 0;
}
XClearWindow(d, w);
point *ptr = anaconda->chain;
while(ptr->next) {
XDrawLine(d, w, gc, ptr->x, ptr->y, ptr->next->x, ptr->next->y);
ptr = ptr->next;
}
XDrawArc(d, w, gc, apple->x - (5/2), apple->y - (5/2), 5, 5, 0, 360*64);
int len = snprintf(&scorebuffer, 30, "%i", anaconda->score);
XDrawString(d, w, gc, 25, 25, &scorebuffer, len);
}
while(XPending(d)) {
XNextEvent(d, &e);
switch(e.type) {
case KeyPress:
switch(e.xkey.keycode) {
case 113: /* left arrow key */
anaconda->rot += 10;
break;
case 114: /* right arrow key */
anaconda->rot -= 10;
break;
}
break;
case Expose:
/* hold off drawing until we get an expose event */
exposed = 1;
width = e.xexpose.width;
height = e.xexpose.height;
if(apple->x > width) {
free(apple);
apple = mkPoint(randrange(20, width / 2 - 20), randrange(20, height / 2 - 20));
} else if (apple->y > height) {
free(apple);
apple = mkPoint(randrange(20, width / 2 - 20), randrange(20, height / 2 - 20));
}
break;
}
}
usleep(100000);
}
freeAnaconda(anaconda);
free(apple);
free(basepoint);
return 0;
}

206
utils/c/boid.c Normal file
View File

@ -0,0 +1,206 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <X11/Xlib.h>
#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
const double sprite[][2] = {
{0, 1},
{-0.5, -1},
{0, -0.5},
{0.5, -1},
};
#define SIZE sizeof sprite / sizeof sprite[0]
double buffer[SIZE][2];
int boidcounter = 0;
Display *d;
Window w;
XEvent e;
int s;
GC gc;
typedef struct point {
double x;
double y;
} point;
typedef struct boid {
int id;
point *p;
double rot;
struct boid *next;
} boid;
void xinit(void) {
d = XOpenDisplay(NULL);
s = DefaultScreen(d);
w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 100, 100, 1,
BlackPixel(d, s), WhitePixel(d, s));
XSelectInput(d, w, ExposureMask | KeyPressMask | PointerMotionMask);
XMapWindow(d, w);
gc = XCreateGC(d, w, 0, NULL);
}
int sign(double x) {
return (x > 0) - (x < 0);
}
point *rotate(double x, double y, double rot) {
point *ret = malloc(sizeof ret);
double rad = rot * M_PI/180;
ret->x = x * cos(rad) - y * sin(rad);
ret->y = x * sin(rad) + y * cos(rad);
return ret;
}
double distance(point *a, point *b) {
return sqrt(pow(a->x - b->x, 2) + pow(a->y - b->y, 2));
}
void calculateRender(
double x,
double y,
double rot,
int scale
) {
memcpy(&buffer, &sprite, SIZE);
for(int i = 0; i < SIZE; i++) {
point *p = rotate(sprite[i][0], sprite[i][1], rot);
buffer[i][0] = p->x * scale + x;
buffer[i][1] = p->y * scale + y;
free(p);
}
}
void renderBuffer(void) {
for(int i = 0; i < SIZE - 1; i++) {
XDrawLine(d, w, gc,
buffer[i][0], buffer[i][1],
buffer[i + 1][0], buffer[i + 1][1]);
}
XDrawLine(d, w, gc,
buffer[0][0], buffer[0][1],
buffer[SIZE - 1][0], buffer[SIZE - 1][1]);
}
void renderBoid(boid *boid) {
calculateRender(
boid->p->x,
boid->p->y,
boid->rot,
5
);
renderBuffer();
}
boid *mkBoid(double x, double y, double rot) {
boid *b = malloc(sizeof b);
point *p = malloc(sizeof p);
b->p = p;
b->p->x = x;
b->p->y = y;
b->rot = rot;
b->next = NULL;
b->id = boidcounter++;
return b;
}
void appendBoid(boid *destination, boid *source) {
destination->next = source;
}
double averageHeading(boid *b) {
boid *c = b;
double sum;
int count;
while(c) {
sum += c->rot;
count++;
c = c->next;
}
return sum / count;
}
void randomBoids(boid *b, int num) {
srand(time(0));
boid *ptr = b;
for(int i = 0; i < num; i++) {
int w = rand() % DisplayWidth(d, s) + 1;
int h = rand() % DisplayHeight(d, s) + 1;
int deg = rand() % 360;
appendBoid(ptr, mkBoid(w, h, deg));
ptr = ptr->next;
}
}
void updateBoid(boid *b, boid *chain, int id, double average) {
point *p = rotate(5, 0, b->rot + 90);
b->p->x = b->p->x + p->x;
b->p->y = b->p->y + p->y;
double toTurn = 0;
boid *c = chain;
while(c) {
if(c->id != id) {
int dist = distance(c->p, b->p);
if(dist < 50) toTurn += dist / 75;
}
int w = DisplayWidth(d, s);
int h = DisplayHeight(d, s);
int centerw = w / 2 - b->p->x;
int centerh = h / 2 - b->p->y;
double deg = atan((double)centerh / (double)centerw) * 180/M_PI;
toTurn += sign(deg) * 0.5;
toTurn += (average - c->rot) * 0.4;
if(b->p->x > w) b->p->x = 0;
else if(b->p->x < 0) b->p->x = w;
if(b->p->y > h) b->p->y = 0;
else if(b->p->y < 0) b->p->y = h;
toTurn = MIN(toTurn / 4, 30);
b->rot += toTurn;
c = c->next;
}
free(p);
}
int main() {
xinit();
boid *b = mkBoid(100, 100, 0);
randomBoids(b, 100);
while(1) {
XClearWindow(d, w);
boid *ptr = b;
while(ptr) {
updateBoid(ptr, b, ptr->id, averageHeading(b));
renderBoid(ptr);
XFlush(d);
ptr = ptr->next;
}
while(XPending(d)) {
XNextEvent(d, &e);
switch(e.type) {
case KeyPress:
break;
}
}
usleep(50000);
}
return 0;
}

286
utils/c/colors.c Normal file
View File

@ -0,0 +1,286 @@
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <errno.h>
#include <time.h>
#include <stddef.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
struct color {
int r;
int g;
int b;
};
void init_random(void) {
srand(time(0));
}
int rand_range(int u, int l) {
return (rand() % (u - l + 1)) + l;
}
void exec_with_stdout(char *file, char *args[], char *buf, int length) {
int pfds[2];
pipe(pfds);
int status = fork();
if(status == 0) {
close(1);
dup(pfds[1]);
close(pfds[0]);
execvp(file, args);
} else {
if(!buf) return; /* don't read anything */
int readin = read(pfds[0], buf, length - 1);
buf[readin] = '\0';
}
}
void imagemagick(char *filename, char *buffer, int size) {
char *execargs[] = {
"convert",
filename,
"-resize",
"25%",
"-colors",
"16",
"-unique-colors",
"-quiet",
"txt:-",
NULL
};
char *name = "convert";
exec_with_stdout(name, execargs, buffer, size);
}
struct color *get_raw_colors(char *image) {
char buf[2048];
imagemagick(image, (char *)&buf, 2048);
int hcount = 0;
char cbuf[3][3];
static struct color colors[16];
for(int i = 0; (unsigned int)i < sizeof buf; i++) {
if(buf[i] == '#') {
hcount++; /* we have to ignore a comment, that's why there's a special case */
if(hcount >= 2 && hcount - 2 < 16 && (unsigned int)(i + 6) < sizeof buf) {
memcpy((char *)&cbuf[0], buf + i + 1, 2);
memcpy((char *)&cbuf[1], buf + i + 3, 2);
memcpy((char *)&cbuf[2], buf + i + 5, 2);
cbuf[0][2] = '\0';
cbuf[1][2] = '\0';
cbuf[2][2] = '\0';
colors[hcount - 2].r = (int)strtol((char *)&cbuf[0], NULL, 16);
colors[hcount - 2].g = (int)strtol((char *)&cbuf[1], NULL, 16);
colors[hcount - 2].b = (int)strtol((char *)&cbuf[2], NULL, 16);
}
}
}
return (struct color *)&colors;
}
void blend_color(struct color *a, struct color *b, struct color *c) {
c->r = (int)(0.5 * a->r + 0.5 * b->r);
c->g = (int)(0.5 * a->g + 0.5 * b->g);
c->b = (int)(0.5 * a->b + 0.5 * b->b);
}
void darken_color(struct color *a, struct color *b, double percentage) {
b->r = (int)(a->r * (1 - percentage));
b->g = (int)(a->g * (1 - percentage));
b->b = (int)(a->b * (1 - percentage));
}
void adjust_colors(struct color *colors) {
/* #eeeeee */
struct color e = {238, 238, 238};
/* if top digit != 0 */
if(colors[0].r > 15)
darken_color(&colors[0], &colors[0], 0.40);
blend_color(&colors[7], &e, &colors[7]);
darken_color(&colors[7], &colors[8], 0.30);
blend_color(&colors[15], &e, &colors[15]);
}
int check_colors(struct color *colors) {
int j = 0;
for(int i = 0; i < 16; i++) {
if(colors[i].r + colors[i].g + colors[i].b == 0) j++;
}
if(j > 0) return 0;
return 1;
}
struct color *get_colors(char *filename) {
/* check for permission */
if(access(filename, F_OK | R_OK) != 0) {
errno = ENOENT;
return NULL;
}
struct color *col = get_raw_colors(filename);
adjust_colors(col);
return col;
}
/* generalized function ,
* used by get_conf_file and get_wal_dir */
char *get_file_gen(char *initvar, char *backvar, char *postfix, char *file) {
static char buffer[256];
int extension = 0;
char *path = getenv(initvar);
if(!path) {
path = getenv(backvar);
extension = 1;
}
if(!path) {
fprintf(stderr, "error: both initvar and backvar are undefined.\n");
exit(1);
}
snprintf(buffer, 256, "%s%s/%s", path, extension ? postfix : "", file);
return buffer;
}
char *get_conf_file(char *file) {
return get_file_gen("XDG_CONFIG_HOME", "HOME", "/.config/cwal", file);
}
/* pass NULL to get the base dir name, not specific file */
char *get_wal_dir(char *file) {
if(!file) file = "";
return get_file_gen("XDG_DATA_HOME", "HOME", "/.local/share/wallpapers", file);
}
char *select_random_rel(void) {
DIR *dir = opendir(get_wal_dir(NULL));
struct dirent *file;
/* probably should move hardcoded constants somewhere that makes sense */
static char names[50][256];
int i = 0, random;
init_random();
while(file = readdir(dir)) {
if(i == 50) break;
if(file->d_type != DT_REG) continue;
memcpy(&names[i], file->d_name, 256);
i++;
}
random = rand_range(i - 1, 0);
return names[random];
}
void print_color(struct color *color) {
printf("#%02x%02x%02x\n", color->r, color->g, color->b);
}
void run_handler(struct color *colors, char *wal) {
char chars[16][8];
char *argv[19];
for(int i = 0; i < 16; i++) {
snprintf(&chars[i], 8, "#%02x%02x%02x", colors[i].r, colors[i].g, colors[i].b);
}
for(int i = 0; i < 16; i++) {
argv[i + 1] = &chars[i];
}
argv[17] = wal;
argv[18] = NULL;
char *conf = get_conf_file("handler");
argv[0] = "handler";
if(access(conf, F_OK | R_OK | X_OK) != 0) {
printf("couldn't find %s!\n", conf);
return;
}
exec_with_stdout(conf, argv, NULL, 0);
}
struct settings {
int h:1; /* running hooks or not */
int e:1; /* echo colors */
int c:1; /* enable color check */
int f:1; /* print filename used */
char *wal; /* custom file if provided */
} settings = {
.h = 1,
.e = 0,
.c = 0,
.f = 0,
.wal = NULL,
};
char *select_random_file(char *file) {
if(!file) file = select_random_rel();
static char ret[256];
file = get_wal_dir(file);
memcpy(&ret, file, 256);
return ret;
}
int main(int argc, char **argv) {
int c;
while((c = getopt(argc, argv, "hefcw:")) != -1) {
switch(c) {
case 'h':
settings.h = 0;
break;
case 'w':
settings.wal = optarg;
break;
case 'e':
settings.e = 1;
break;
case 'c':
settings.c = 1;
break;
case 'f':
settings.f = 1;
break;
}
}
if(settings.h == 0) settings.e = 1;
char *file = select_random_file(settings.wal);
struct color *colors = get_colors(file);
if(settings.f) printf("%s\n", file);
if(settings.e) {
for(int i = 0; i < 16; i++) {
print_color(&colors[i]);
}
}
if(settings.c) {
c = check_colors(colors);
if(c == 0) {
return 1;
}
}
if(settings.h) run_handler(colors, file);
return 0;
}

21
utils/c/scream.c Normal file
View File

@ -0,0 +1,21 @@
#include <stdio.h>
#include <ctype.h>
/* written on new year's eve 2020
* good night and good riddance */
char newchar(char c, int i) {
if(i % 2) {
if(islower(c)) return c - 32;
} else if(isupper(c)) return c + 32;
if(c == 33) return -2;
return c;
}
int main(void) {
char c;
int i = 0;
while((c = getchar()) != EOF) {
putchar(newchar(c, i));
i++;
}
}

174
utils/c/timer.c Normal file
View File

@ -0,0 +1,174 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <poll.h>
#include <string.h>
struct timer {
int s; /* seconds */
int d; /* data storage */
void (*u)(struct timer *t); /* update function */
int (*c)(struct timer *t); /* stop check function */
int (*p)(struct timer *t); /* pause check function */
};
struct settings {
unsigned int e:1; /* use escape (v assumed) */
unsigned int v:1; /* verbose */
unsigned int d:1; /* count down/up (1/0) */
unsigned int b:1; /* ascii bel when done */
unsigned int f:1; /* display hours */
unsigned int t:1; /* tomato timer */
unsigned int p:1; /* stop after tomato timer cycle finished */
int s; /* seconds */
} s = {
.e = 0,
.v = 0,
.d = 0,
.b = 0,
.f = 0,
.t = 0,
.p = 0,
.s = 0
};
void timerdec(struct timer *t) { if (t->s) t->s--; }
void timerinc(struct timer *t) { t->s++; }
void timerupdate(struct timer *t) { if(t->u) t->u(t); }
int timerstate(int (*f)(struct timer *t), struct timer *t) {
if(f) {
if(f(t)) return 1;
else return 0;
}
return 0;
}
int timerstop(struct timer *t) { return timerstate(t->c, t); }
int timerpause(struct timer *t) { return timerstate(t->p, t); }
int timerzero(struct timer *t) {
if(!t->s) return 1;
return 0;
}
int seconds(int t) { return t % 60; }
int minutes(int t) { return (t / 60) % 60; }
int minute(int t) { return t / 60; }
int hours(int t) { return (t / 60) / 60; }
struct timer *timerinit(void) {
struct timer *t = malloc(sizeof *t);
t->s = 0;
t->d = 0;
t->u = NULL;
t->c = NULL;
t->p = NULL;
return t;
}
int timerissettings(struct timer *t) {
if(!t->s) return 0;
if(s.s == t->s) return 1;
return 0;
}
int tomatotimer(struct timer *t) {
if(t->s) return 0;
if(t->d % 2) t->s = s.s / 2;
else t->s = s.s;
t->d++;
if(s.b) putchar('\a');
if(s.p) return 0;
return 1;
}
char *timerdisp(struct timer *t) {
char *str = malloc(20);
if(s.f) snprintf(str, 20, "%02i:%02i:%02i",
hours(t->s), minutes(t->s), seconds(t->s));
/* TODO: give minute(...) and minutes(...) better names */
else snprintf(str, 20, "%02i:%02i", minute(t->s), seconds(t->s));
return str;
}
void defaultSettings(struct settings s) {
s.e = 1;
s.b = 1;
s.f = 1;
}
void timerloop() {
struct timer *t = timerinit();
if(s.d) {
t->u = timerdec;
t->s = s.s;
t->c = timerzero;
} else {
t->u = timerinc;
t->c = timerissettings;
}
if(s.t) {
t->u = timerdec;
if(s.s == 0) s.s = 20 * 60;
t->s = s.s;
t->d = 1;
t->p = tomatotimer;
t->c = NULL;
}
char *c;
int e;
struct pollfd p = { .fd = STDIN_FILENO, .events = POLLIN };
for(;;) {
poll(&p, 1, 60);
if((e = (p.revents == POLLIN)) || timerpause(t)) {
/* TODO: make this nicer */
if(e) getchar();
if(s.e) {
c = timerdisp(t);
if(e) printf("\r\e[1A* %s", c);
else printf("\r* %s", c);
}
getchar();
/* TODO: stop relying on hard assumptions */
if(s.e) printf("\r\e[1A \r");
}
c = timerdisp(t);
if(s.e) {
printf("%s\r", c);
fflush(stdout);
}
else if(s.v) printf("%s\n", c);
if(timerstop(t)) break;
free(c);
timerupdate(t);
sleep(1);
}
if(s.b) putchar('\a');
free(t);
free(c);
}
int main(int argc, char **argv) {
char c;
while((c = getopt(argc, argv, "evdbftpzh:m:s:")) != -1) {
switch(c) {
break; case 'e': s.e = 1;
break; case 'v': s.v = 1;
break; case 'd': s.d = 1;
break; case 'b': s.b = 1;
break; case 'f': s.f = 1;
break; case 't': s.t = 1;
break; case 'p': s.p = 1;
break; case 'z': s.e = 1; s.b = 1; s.f = 1;
break; case 'h': s.s = s.s + (atoi(optarg) * 3600);
break; case 'm': s.s = s.s + (atoi(optarg) * 60);
break; case 's': s.s = s.s + atoi(optarg);
break; case '?': return 1;
break; default: abort();
}
}
timerloop();
return 0;
}

148
utils/c/tmessage.c Normal file
View File

@ -0,0 +1,148 @@
#include <sys/ioctl.h>
#include <ctype.h>
#include <termios.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#define ESC_CLEAR "\033[2J"
#define ESC_CUSHOME "\033[H"
#define ESC_NEWLINE "\033[E\033[1C"
const char MSG_OK[] = "(O)k";
const char MSG_CANCEL[] = "(C)ancel";
typedef struct winsize ws;
int lines, cols;
char *message;
size_t message_len;
struct termios original_termios;
void render(char *message, int message_len, int lines, int cols);
void rawmode_start() {
tcgetattr(STDIN_FILENO, &original_termios);
struct termios raw = original_termios;
raw.c_lflag &= ~(ECHO | ICANON);
tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
}
void rawmode_stop() {
tcsetattr(STDIN_FILENO, TCSAFLUSH, &original_termios);
printf("\n\n");
fflush(stdout);
}
ws *getWinSize(void) {
/* we're only going to use these values once per invocation,
* so it's fine that it's static. */
static ws w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
return &w;
}
void handler(int signal, siginfo_t *info, void *context) {
ws *w = getWinSize();
lines = w->ws_row;
cols = w->ws_col;
render(message, message_len, lines, cols);
return;
}
void termhandler(int signal, siginfo_t *info, void *context) {
rawmode_stop();
return;
}
int calculate_number_of_lines(int length, int cols) {
/* cols - 1 accounts for right padding */
return length / (cols - 1) + 1;
}
void go_to_initial_message_printing_pos(void) {
printf(ESC_CUSHOME "\033[1B\033[1C");
}
void print_message(char *message, int messagelen, int cols) {
int linecount = calculate_number_of_lines(messagelen, cols);
int adjcols = cols - 2;
int offset = 1;
for(int character = 0; character < messagelen; character++) {
if(character == adjcols * offset) {
printf(ESC_NEWLINE);
offset++;
}
putchar(message[character]);
}
}
void render(char *message, int messagelen, int lines, int cols) {
int cancel_length = sizeof(MSG_CANCEL) / sizeof(MSG_CANCEL[0]);
/* print the stuff */
printf(ESC_CLEAR "" ESC_CUSHOME);
go_to_initial_message_printing_pos();
print_message(message, message_len, cols);
printf(ESC_NEWLINE);
printf(ESC_NEWLINE);
printf("%s", MSG_OK);
printf("\033[1D\033[%iC\033[%iD%s", cols, cancel_length, MSG_CANCEL);
fflush(stdout);
}
int main(int argc, char **argv) {
int cancel_length = strlen(MSG_CANCEL);
char c;
struct sigaction resizeaction = {};
struct sigaction termaction = {};
ws *w;
/* check if we have a message */
if(argc > 1) {
message = argv[1]; /* second argument's a message */
message_len = strlen(message);
} else {
return 1;
}
/* setup sigaction handlers */
resizeaction.sa_sigaction = &handler;
if(sigaction(SIGWINCH, &resizeaction, NULL) == -1) {
return 1;
}
termaction.sa_sigaction = &termhandler;
if(sigaction(SIGTERM, &termaction, NULL) == -1) {
return 1;
}
rawmode_start();
/* get window properties */
w = getWinSize();
lines = w->ws_row;
cols = w->ws_col;
render(message, message_len, lines, cols);
for(;;) {
read(STDIN_FILENO, &c, 1);
if(c == 'o') {
return 2;
rawmode_stop();
} else if(c == 'c') {
return 3;
rawmode_stop();
}
}
return 0;
}

29
utils/c/xgetnewwindow.c Normal file
View File

@ -0,0 +1,29 @@
#include <X11/Xlib.h>
#include <stdio.h>
int main(void) {
Display* display = XOpenDisplay(NULL);
if(!display) {
printf("Error: Unable to open display.\n");
return 1;
}
int screen = DefaultScreen(display);
Window root = RootWindow(display, screen);
/* SubstructureNotifyMask allows us to be notified of CreateNotify events */
XSelectInput(display, root, SubstructureNotifyMask);
XEvent event;
for(;;) {
XNextEvent(display, &event);
if(event.type == CreateNotify) {
/* print window id */
printf("0x%x\n", event.xcreatewindow.window);
break;
}
}
XCloseDisplay(display);
return 0;
}

2
utils/config.mk Normal file
View File

@ -0,0 +1,2 @@
DESTDIR=$(HOME)/.local

View File

@ -0,0 +1,26 @@
import httplib2
import json
import math
import time
# fun fact: i got bored so made this on a southwest flight
while True:
request = httplib2.Http()
# you have to look in the network tab in 'inspect element', and find the '_' parameter, and paste that in
# of course, you have to be connected to southwest's onboard wifi
_param = "fill this in"
data = request.request("https://getconnected.southwestwifi.com/fp3d_fcgi-php/portal/public/index.php?_url=/index/getFile&path=last&_=" + _param)
data = json.loads(data[1])
print("-- Update --")
print("Nautical Miles: " + str(data["distanceToDestinationNauticalMiles"]))
print("Phase: " + data["presentPhase"])
print("Speed: " + str(data["groundSpeedKnots"]) + "kts")
seconds = data['timeToDestination']
minutes = math.floor(seconds / 60)
seconds = seconds % 60
print("Minutes: " + str(minutes) + " Seconds: " + str(seconds))
print("Flight Number: " + data["flightNumber"] + " Registration: " + data["tailNumber"])
time.sleep(3)
print('\033[H\033[2J')

32
utils/man/colors.1 Normal file
View File

@ -0,0 +1,32 @@
.TH COLORS 1 colors
.SH NAME
colors \- generate colorscheme and run hooks
.SH SYNOPSIS
.B colors [-hefc] [-w path]
.SH OPTIONS
.TP
.B -h
disable running hooks (implies -e)
.TP
.B -e
echo colors to stdout
.TP
.B -c
check colors using color checking algorithm
.TP
.B -f
print wallpaper filename to stdout
.TP
.B -w
provide wallpaper path
.SH HOOKS
When -h is not used, a program at ~/.config/cwal/handler is executed. The first sixteen arguments are the colors in the colorscheme, and the seventeenth argument is the filename.
.SH EXIT CODES
.TP
.B 0
Normal exit code
.TP
.B 1
check_colors(...) failed.
.SH AUTHOR
randomuser

11
utils/man/rndutils.1 Normal file
View File

@ -0,0 +1,11 @@
.TH RNDUTILS 1 rndutils
.SH NAME
rndutils \- simple shell script utilities
.SH INSTALLATION
.B make install
.SH LICENSE
The author, randomuser (randomuser at tilde dot club) hereby
releases the software in this distribution and all
accompanying texts into the public domain, thereby relieving
him of any warranty of any kind.

87
utils/man/timer.1 Normal file
View File

@ -0,0 +1,87 @@
.TH TIMER 1 timer
.SH NAME
timer \- simple command line timer program
.SH SYNOPSIS
.B timer [-evdbft] [-h int] [-m int] [-s int]
.SH OPTIONS
.TP
.B -e
enable usage of vt100 escape sequences for timer rendering (overrides -v)
.TP
.B -v
enable printing of timer status
.TP
.B -d
count down; when timer reaches 00:00, finish (use -h, -m, -s to set ending time)
.TP
.B -b
ASCII BEL when timer finish state reached
.TP
.B -f
timer display contains hour slot
.TP
.B -t
use a tomato timer (use -h, -m, -s to set work cycle time, rest cycle time is assumed to be half of the working time)
.TP
.B -p
disable pausing after finishing tomato timer cycle (required -t to work)
.TP
.B -z
enable build-specific runtime settings (default -ebf)
.TP
.B "-h int"
specify number of hours for timer parameters
.TP
.B "-m int"
specify number of minutes for timer parameters
.TP
.B "-s int"
specify number of seconds for timer parameters
.SH INTERACTIVE USAGE
.TP
.B pausing
a timer is paused when an astrisk prefixes the display (with -e) and/or when the timer ceases to update, e.g. count up or down. you can use the enter key to pause/unpause it (refer to the below example)
.nf
$ timer -e
* 05:45
.fi
.TP
.B stopping a timer
should you wish to stop a timer prematurely, or a timer which has no specified end condition, you may press the key combination that sends a killing signal to the program (e.g. a la SIGTERM) in your shell, which is usually ^C. the timer has no major places to clean up. however, memory leaks might occur on some operating systems due to no free()ing of resources.
.SH EXIT CODES/TERMINATION SIGNALS
.TP
.B 0
timer finished successfully
.TP
.B 1 / SIGABRT
error parsing arguments
.SH EXAMPLES
.B start a ten minute timer, counting up:
.nf
$ timer -m 10
.fi
.B show the vt100 interface, too:
.nf
$ timer -em 10
.fi
.B start a one hour sixty-two minute fourty-nine second timer counting down (with vt100 interface):
.nf
$ timer -edh 1 -m 62 -s 49
.fi
.B start a tomato timer with a work interval of fourty minutes and a rest interval of twenty minutes:
.nf
$ timer -etm 40
.fi
.SH REQUIRED HEADERS
.nf
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <poll.h>
#include <string.h>
.fi
.SH BUGS
- when passing -p each tomato timer cycle is cut short one second
send email to random user at-sign tilde dot club
.SH AUTHOR
randomuser

30
utils/man/trss.1 Normal file
View File

@ -0,0 +1,30 @@
.TH TRSS 1 trss
.SH NAME
trss \- command oriented feed reader powered by sfeed
.SH SYNOPSIS
.B trss
.SH INTERFACE
.TP
.B ls
list all feed names in the 'feed home', or within a feed, list all items within
.TP
.B cd
focus another feed. in order to go back to the 'feed home', use 'cd' or 'cd ..'
.TP
.B sync
with no arguments and in the 'feed home', syncs all feeds. if in a specific feed, syncs that feed. a feed can be specified in an argument.
.TP
.B cat
open all feeds whose titles contain text as specified by an argument in 'lynx'
.SH trss-yt-id
this script is designed to allow one to obtain an rss feed for the uploads of a youtube channel. this command takes the homepage of the youtube channel in question as an argument and then returns the rss feed for that channel.
.SH BUGS
- when in a feed, you can't cd to another directly, you must go to to the 'feed home' and then cd
.SH DEPENDS
sfeed
.SH AUTHOR
randomuser <random user at tilde dot club>

10
utils/man/xgetnewwindow.1 Normal file
View File

@ -0,0 +1,10 @@
.TH XGETNEWWINDOW 1 xgetnewwindow
.SH NAME
xgetnewwindow
.SH SYNOPSIS
xgetnewwindow blocks until it recieves a CreateNotify event; that is, until a new window is created within the current Xorg instance. Once a new window is created, xgetnewwindow prints the window id (in hexadecimal) to stdout and exits.
.SH EXIT CODES
1 for abnormal termination, 0 for success.
.SH AUTHOR
randomuser

4
utils/sh/brightness Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
brightness=$(printf "250\n500\n1000\n2000\n3000\n4000\n" | tmenu)
st -c st-gpg-menu -e sh -c "sudo sh -c \"echo $brightness >> /sys/class/backlight/intel_backlight/brightness\""

11
utils/sh/bspwm-toggle-gaps Executable file
View File

@ -0,0 +1,11 @@
#!/bin/sh
gaps="$(bspc config top_padding)"
if [ "$gaps" -eq 20 ]; then
bspc config window_gap 0
bspc config top_padding 18
else
bspc config window_gap 3
bspc config top_padding 20
fi

60
utils/sh/capture Executable file
View File

@ -0,0 +1,60 @@
#!/bin/sh
# get screen info and temporary file
tmp=$(mktemp)
res=$(xrandr |
grep ' connected' |
awk -F' ' '{print $1 " " $4}' |
awk -F'+' '{print $1}' |
fzy |
awk -F' ' '{print $2}' )
# still or motion
medium=$(printf ".mp4\n.png\n" | fzy)
output="$tmp$medium"
# capture
case "$medium" in
*mp4*)
printf "> starting video capture...\n"
ffmpeg -video_size "$res" -f x11grab -framerate 60 -i $DISPLAY -preset ultrafast -pix_fmt yuv420p "$output"
;;
*png*)
printf "> taking screenshot...\n"
# for a screenshot, we usually want an a s t h e t i c
ffmpeg -f x11grab -video_size "$res" -i $DISPLAY -vframes 1 "$output" -loglevel quiet # be quiet
;;
*)
printf "not a choice\n"
exit 1
esac
# what to do with the capture?
printf "> written to %s\n" "$output"
while true; do
result=$(printf "delete\nmove to home directory\nupload to pastebin\nreview footage\nquit\n" | fzy --prompt="what next? ")
case "$result" in
*upload*)
paste "$output" | xclip -i
printf "> pasted! check your clipboard\n"
;;
*review*)
[ "$medium" = ".mp4" ] && mpv "$output" && continue
feh "$output"
;;
*delete*)
printf "> removing target file...\n"
rm "$output"
exit 1
;;
*home*)
printf "> warping your capture to home...\n"
name=$(echo "capture$medium" | fzy --prompt="name please? ")
mv "$output" "$HOME/$name"
exit 1
;;
*quit*)
exit 1
;;
esac
done

6
utils/sh/cfg Executable file
View File

@ -0,0 +1,6 @@
#!/bin/sh
sel="$(find -L ~/.config 2>/dev/null | fzy)"
[ "$?" -eq 1 ] && exit 1
nvim "$sel"

44
utils/sh/connect Executable file
View File

@ -0,0 +1,44 @@
#!/bin/sh
[ "$(pgrep -c NetworkManager)" -eq 1 ] &&
printf "NetworkManager is already running!\n" &&
exit
case $1 in
"c"*)
wpa_supplicant -iwlp3s0 -c/etc/wpa_supplicant/wpa_supplicant.conf -B
dhcpcd wlp3s0
# make tor and nohup shut up in a posix-compliant way
nohup tor >/dev/null 2>&1
;;
"d"*)
killall -15 wpa_supplicant dhcpcd tor
;;
"r"*)
sh "$0" d
sh "$0" c
;;
"t"*)
[ "$(pgrep -c wpa_supplicant)" -eq 1 ] && sh "$0" d && exit
sh "$0" c
;;
"l"*)
iw dev wlp3s0 scan | \
grep 'SSID\|signal' | \
grep -v 'SSID List' | \
awk -F': ' '{print $2}' | \
sed 'N;s/\n/ /' | \
grep -v '\x00'
;;
*)
echo "
simple wrapper for connecting to a network
${0} toggle to toggle wifi connection
${0} restart to restart wifi
${0} disconnect to disconnect
${0} connect to connect to network
${0} list to list networks
"
;;
esac
exit 0

3
utils/sh/discord Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
chromium --app=https://discord.com/login --profile-directory="Profile 1"

27
utils/sh/disp Executable file
View File

@ -0,0 +1,27 @@
#!/bin/sh
exists() {
xrandr | grep ' connected' | grep -c "${1}"
}
bspc monitor -d 1 2 3 4 5 6 7 8 9
if [ "$(exists "HDMI-2")" -eq 1 ] && [ "$(exists "LVDS-1")" -eq 1 ]; then
printf "two"
xrandr --output HDMI-2 --right-of LVDS-1 --auto
xrandr --output VGA-1 --off --auto
bspc monitor LVDS-1 -d 1 2 3 4 5 6 7 8 9
bspc monitor HDMI-2 -d 1 2 3 4 5 6 7 8 9
exit 0
fi
if [ "$(exists "HDMI-1")" -eq 1 ] && [ "$(exists "LVDS-1")" -eq 1 ]; then
printf "two"
xrandr --output HDMI-1 --right-of LVDS-1 --auto
xrandr --output VGA-1 --off --auto
bspc monitor LVDS-1 -d 1 2 3 4 5 6 7 8 9
bspc monitor HDMI-1 -d 1 2 3 4 5 6 7 8 9
exit 0
fi
# default configuration's fine

3
utils/sh/fire Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
HOME="/home/usr/.local/share/firefox" firefox "$@"

41
utils/sh/firew Executable file
View File

@ -0,0 +1,41 @@
#!/bin/sh
# wrapper script to make firefox suck less
RHOME="${HOME}"
firefox_data_location="$HOME/firefoxdumpster"
[ -z "$3" ] || url="$3"
# start a profile chooser
if [ -z "$2" ]; then
profile=$(printf "programming\nschool\ntmp-school\ntmp\nchromium\n" | tmenu)
else
profile="$2"
fi
[ -z "$profile" ] && exit
if [ "$profile" = "tmp" ]; then
# firefox doesn't start in a directory within /tmp
# so we create one in $HOME/.cache
tmp=$(basename $(mktemp))
mkdir -p "${RHOME}/.cache/${tmp}"
rm -r "/tmp/$tmp"
HOME="/home/$(whoami)/.local/share/firefox" firefox --profile "${RHOME}/.cache/${tmp}" --no-remote "$url"
rm -r "${RHOME}/.cache/${tmp}"
exit
fi
if [ "$profile" = "chromium" ]; then
HOME="/home/$(whoami)/.local/share/firefox" chromium
exit
fi
# start firefox
mkdir -p "${firefox_data_location}/profile"
HOME="/home/$(whoami)/.local/share/firefox" firefox --profile "${firefox_data_location}/${profile}" --no-remote "$url"
exit
printf "failed to specify a profile. exiting.\n"
exit 1

View File

@ -0,0 +1,3 @@
#!/bin/sh
printf "password=%s\n" "$(pash s tildegit)"

12
utils/sh/git-survey Executable file
View File

@ -0,0 +1,12 @@
#!/bin/sh
for i in *; do
cd "$i" || continue
exists=$(
git status |
grep -c 'Your branch is ahead of '
)
[ "$exists" -eq 0 ] || printf "> %s\n" "$i"
cd ..
done

7
utils/sh/keyboard Executable file
View File

@ -0,0 +1,7 @@
#!/bin/sh
setxkbmap -option caps:super
killall xcape
xcape -e 'Super_L=Escape'
xset -q | grep "Caps Lock:\s*on" && xdotool key Caps_Lock
xset r rate 200 40

18
utils/sh/machine Executable file
View File

@ -0,0 +1,18 @@
#!/bin/sh
host="$(hostname)"
case "$host" in
"mlg")
exit 1
;;
"toaster")
exit 2
;;
"fish")
exit 3
;;
"think")
exit 4
;;
esac

4
utils/sh/net Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
# designed to be called from sxhkd (x session)
pgrep NetworkManager && st -e nmtui

104
utils/sh/nws Executable file
View File

@ -0,0 +1,104 @@
#!/bin/sh
[ -z "${XDG_CONFIG_DIR}" ] && XDG_CONFIG_DIR="${HOME}/.config"
[ -z "${NWS_CONFIG}" ] && NWS_CONFIG="${XDG_CONFIG_DIR}/nws"
[ -n "${NWS_ZONE}" ] || \
[ -e "${NWS_CONFIG}" ] && NWS_ZONE=$(cat "${NWS_CONFIG}") ||
NWS_ZONE="KGYX"
[ -z "${NWS_GIF}" ] && NWS_GIF="mpv --loop"
[ -z "${NWS_TORIFY}" ] && NWS_TORIFY=""
info () {
printf %s "\
nws - wrapper for the National Weather Service's website
=> [n]ational - View national weather mosaic
=> [l]ocal - View local weather mosaic
=> [r]ivers - View local river conditions
=> [w]eather - View local weather observations
=> [m]osaic [id] - View a given area's weather mosaic
=> [s]et [id] - Set local zone
=> [t]ext [id] - View text messages by catagory
Default zone: export NWS_ZONE=<zone>
GIF player: export NWS_GIF=<command>
Configuration: export NWS_CONFIG=<file>
Torify wrapper: export NWS_TORIFY=<command>
"
}
err () {
printf "err: %s\n" "${1}"
[ -z "${2}" ] && exit 1
exit "${2}"
}
kstrip () {
printf %s "$1" | sed 's/^K\(.*\)/\1/'
}
national () {
mosaic CONUS-LARGE
}
# name interestingly to avoid keyword collision
localradar () {
mosaic ${NWS_ZONE}
}
mosaic () {
${NWS_GIF} "https://radar.weather.gov/ridge/standard/${1}_loop.gif"
}
setzone () {
printf "%s" "${1}" > "${NWS_CONFIG}"
}
river () {
textmessage "RVA"
}
weather () {
textmessage "ZFP"
}
textmessage () {
curl --silent --fail "https://forecast.weather.gov/product.php?site=NWS&issuedby=$(kstrip ${NWS_ZONE})&product=${1}&format=TXT&version=1" | \
sed -n '/<!-- \/\/ CONTENT STARTS HERE -->/,/<\/pre>/p' | \
grep -v "a href" | \
grep -v '<!-- // CONTENT STARTS HERE -->' | \
grep -v '<\/pre>' || \
printf "${1} data not found for zone %s" ${NWS_ZONE}
}
case $1 in
"n"*)
national
;;
"l"*)
localradar
;;
"r"*)
river
;;
"w"*)
weather
;;
"m"*)
if [ "$#" -eq 2 ]; then
mosaid "$2"
else
err "two args required"
fi
;;
"s"*)
if [ "$#" -eq 2 ]; then
setzone "$2"
else
err "two args required"
fi
;;
"t"*)
if [ "$#" -eq 2 ]; then
textmessage "$2"
else
err "two args required"
fi
;;
*)
info
;;
esac
exit 0

7
utils/sh/pash-dmenu Executable file
View File

@ -0,0 +1,7 @@
#!/bin/sh
sel="$(pash l | tmenu)"
[ "$?" -eq 1 ] && exit 0
# requires bspc rule -a st-gpg-menu state=floating
st -c st-gpg-menu -e pash-dmenu-backend "$sel"

5
utils/sh/pash-dmenu-backend Executable file
View File

@ -0,0 +1,5 @@
#!/bin/sh
pash c "$1"
bspc node -d '^9'
sleep 15

4
utils/sh/paste Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
[ "$1" = "" ] && exit 1
[ -f "$1" ] && curl -F"file=@${1}" https://0x0.st && exit 0

88
utils/sh/pco Executable file
View File

@ -0,0 +1,88 @@
#!/bin/sh
# script for interfacing with planning center online
appid=$(cat "$HOME/.local/share/pco/appid")
token=$(cat "$HOME/.local/share/pco/token")
userid=$(cat "$HOME/.local/share/pco/userid")
get_blockouts_online () {
curl -su "$appid:$token" "https://api.planningcenteronline.com/services/v2/people/$userid/blockouts" | \
jq .data[].attributes.ends_at | \
awk -F'"|-|T' '
function y(x) {
if (x == 1) return "Jan"
if (x == 2) return "Feb"
if (x == 3) return "Mar"
if (x == 4) return "Apr"
if (x == 5) return "May"
if (x == 6) return "Jun"
if (x == 7) return "Jul"
if (x == 8) return "Aug"
if (x == 9) return "Sep"
if (x == 10) return "Oct"
if (x == 11) return "Nov"
if (x == 12) return "Dec"
return "Unk"
}
{print y($3) " " $4 " " $2}' | \
tr '\n' '|' | \
sed 's/.\{1\}$//'
}
get_blockouts_local () {
grep "MSG Blockout date" "$DOTREMINDERS" | \
awk -F' ' '{print $2 " " $3 " " $4}'
}
get_blockouts () {
all_dates=$(get_blockouts_online)
OLDIFS="$IFS"
IFS="|"
for i in $all_dates; do
results=$(grep -c "^REM $i MSG Blockout date" "$DOTREMINDERS")
[ "$results" -eq 0 ] && \
printf "REM %s MSG Blockout date\n" "$i" >> "$DOTREMINDERS" && \
printf "added %s to calendar\n" "$i" || \
printf "omitted %s from the calendar, it's already there\n" "$i"
done
IFS="$OLDIFS"
}
push_blockouts () {
file=$(mktemp)
get_blockouts_online | tr '|' '\n' >> "$file"
local=$(get_blockouts_local)
# don't mess with the spacing
OLDIFS=$IFS
IFS="
"
printf "temp file: %s\n" "$file"
for i in $local; do
count=$(grep -c "^$i$" "$file")
if [ "$count" -eq 0 ]; then
printf "push: %s\n" "$i"
stddate=$(date --date="$i" "+%Y-%m-%dT06:00:00Z")
curl -X POST -H "Content-Type: application/json" -d "
{
\"data\": {
\"attributes\": {
\"reason\": \"n/a\",
\"repeat_frequency\": \"no_repeat\",
\"starts_at\": \"$stddate\",
\"ends_at\": \"$stddate\"
}
}
}" -su "$appid:$token" "https://api.planningcenteronline.com/services/v2/people/$userid/blockouts"
fi
done
IFS=$OLDIFS
rm "$file"
}
get_blockouts
push_blockouts

23
utils/sh/sfeed_yt_add Executable file
View File

@ -0,0 +1,23 @@
#!/bin/sh
[ -z "$1" ] && exit 1
[ -z "$2" ] && exit 1
printf "[info] this utility is used for adding youtube urls as rss feeds\n"
feed="$(curl "$1" -s | \
grep 'youtube/www\.youtube\.com/channel/.\{24\}' -o | \
awk -F'/' '{print "https://www.youtube.com/feeds/videos.xml?channel_id=" $NF}' | \
sed 1q)"
[ -z "$feed" ] && printf "[err] error processing the feed. are you sure it's *www*.youtube.com and not youtube.com?\n" && exit 1
sfeedrc="$HOME/.config/sfeed/sfeedrc"
ed "$sfeedrc" <<EOF
/feeds
a
feed "$2" "$feed"
.
w
EOF

4
utils/sh/snapcad Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
# opens snapcad
wine ~/.wine/drive_c/Program\ Files\ \(x86\)/VEX\ Robotics/SnapCAD/SnapCAD.exe

12
utils/sh/ss Executable file
View File

@ -0,0 +1,12 @@
#!/bin/sh
scripts="$(
find /home/usr/git/utils/sh /home/usr/git/utils/c -type f |
grep -v '\.git' |
xargs file |
grep 'C source \|POSIX shell script' |
awk -F':' '{print $1}' |
fzy
)"
[ -z "$scripts" ] || nvim "$scripts"

100
utils/sh/status Executable file
View File

@ -0,0 +1,100 @@
#!/bin/sh
power_prefix="/sys/class/power_supply/"
[ -d "${power_prefix}sbs-20-000b" ] && bat="sbs-20-000b"
[ -d "${power_prefix}BAT0" ] && bat="BAT0"
[ "$(pgrep -c pulseaudio)" -eq 1 ] && ss="pulse" || ss="alsa"
mod_bspwm () {
used_desk=$(bspc query -D -d .occupied --names | tr '\n' ' ')
current_desk=$(bspc query -D -d .focused --names)
final_string=""
current_printed=0
cur_char='>'
for i in $used_desk; do
[ "$i" = "$current_desk" ] && \
final_string=${final_string}"$cur_char$i " && \
current_printed=1 || \
final_string=${final_string}"$i "
done
[ $current_printed -eq 0 ] &&
final_string=${final_string}"$cur_char$current_desk "
printf "%s" "$final_string"
}
mod_period () {
nextclass
}
mod_sensors () {
sensors | grep 'Core 0' | awk -F' ' '{print $3}' | tr -d '\n'
}
mod_power () {
[ -z "$bat" ] ||
tr -d '\n' < /sys/class/power_supply/$bat/capacity
sed 's/Charging/↑/g;s/Not charging/-/g;s/Discharging/↓/g;s/Full/-/g' < /sys/class/power_supply/$bat/status
}
mod_vol () {
[ "$ss" = "pulse" ] && pactl list sinks | awk -F' ' '$1 == "Volume:" {print "pv" $5}'
[ "$ss" = "alsa" ] && amixer | grep '^ Front' | awk -F'[' '{ORS = ""; print "av" substr($2, 1, 3); exit}'
}
mod_date_time () {
date '+%m%d-%H:%M' | tr '\n' ' '
}
update_mod () {
output="$(eval "mod_$1")"
eval "output_$1=\"$output\""
}
get_mod () {
eval "printf '%s' \${output_$1}"
}
echo_bar () {
left="$(get_mod "bspwm")"
right="$(get_mod "date_time")$(get_mod "period") $(get_mod "sensors") $(get_mod "power") $(get_mod "vol")"
width="$(tput cols)"
rightwidth="${#right}"
# print left side
printf "\033[2J\033[H%s" "$left"
# print right side
printf "\033[1;%if%s" "$((width - rightwidth + 1))" "$right"
}
register_sigs () {
trap "update_mod vol" USR2
trap "update_mod bspwm" USR1
}
update_all () {
update_mod power
update_mod vol
update_mod bspwm
update_mod date_time
update_mod period
update_mod sensors
}
tput civis
register_sigs
update_all
i=0
while true; do
sleep 0.25
[ "$i" -eq $((29 * 4)) ] && update_all && i=0
echo_bar
i="$((i + 1))"
done

23
utils/sh/statusbar Executable file
View File

@ -0,0 +1,23 @@
#!/bin/sh
barwidth=20
# remove all current statusbars
# pgrep doesn't handle arguments for running commands
# shellcheck disable=2009
processes="$(ps aux | grep 'st -c' | grep 'status' | awk -F' ' '{print $2}')"
for i in $processes; do
pkill -P "$i" >/dev/null 2>&1
kill "$i"
done
# get all screens
screens="$(xrandr | grep ' connected' | sed 's/ primary//g' | awk -F' ' '{print $1 " " $3}')"
# for every screen, create a statusbar
IFS="
"
for i in $screens; do
screenstring=$(echo "$i" | awk -v a="$barwidth" -F'[ x+]' '{print $2 "x" a "+" $4 "+" $5}')
st -c statusbar -p -g "$screenstring" -e status &
done

8
utils/sh/tmenu Executable file
View File

@ -0,0 +1,8 @@
#!/bin/sh
file=$(mktemp)
cat - > "$file"
st -c tmenu-prompt -g 40x10+0+0 -e tmenu-backend "$file"
cat "$file"
rm "$file"

6
utils/sh/tmenu-backend Executable file
View File

@ -0,0 +1,6 @@
#!/bin/sh
printf "%s" "$1"
fzy < "$1" > "${1}a"
mv "${1}a" "${1}"

18
utils/sh/tmenu_run Executable file
View File

@ -0,0 +1,18 @@
#!/bin/sh
tmenu_path () {
IFS=" :"
for i in $PATH; do
for j in "$i"/*; do
[ -f "$j" ] && [ -x "$j" ] && printf "%s\n" "$j" | xargs basename
done
done
}
if [ "$1" = "-g" ] || [ "$(basename $0)" = "regenerate" ]; then
mkdir -p $HOME/.local/share
tmenu_path > $HOME/.local/share/tmenu_cache
xmessage "regeneration complete"
else
cat $HOME/.local/share/tmenu_cache | tmenu | ${SHELL:-"/bin/sh"} &
fi

View File

@ -0,0 +1,28 @@
#!/bin/sh
pid=$(pgrep sxhkd)
for i in $pid; do
inv_id=$(cat /proc/$i/cmdline | awk -F'\0' '{print $3}')
echo $inv_id
[ -z "$inv_id" ] && contingency_mode="off"
[ "$inv_id" = *"contingency" ] && contingency_mode="on"
done
killall sxhkd
trackpoint=$(xinput | grep "TrackPoint" | awk -F'\t' '{print $2}' | awk -F'=' '{print $2}')
touchpad=$(xinput | grep "TouchPad" | awk -F'\t' '{print $2}' | awk -F'=' '{print $2}')
if [ "$contingency_mode" = "off" ]; then
sxhkd -c $HOME/.config/sxhkd/contingency &
xinput disable "$trackpoint"
xinput disable "$touchpad"
xmessage "contingency mode enabled."
else
sxhkd &
xinput enable "$trackpoint"
xinput enable "$touchpad"
killall xmessage
fi

28
utils/sh/vim-swap-handler Executable file
View File

@ -0,0 +1,28 @@
#!/bin/sh
# when the vim SwapExists autocommand is fired, this script is
# called with the path of the file in question.
# mad props to daniel conway for having this big brain idea
# note to self: protect $1 from expansion as it can contain a
# ~
[ "$#" -eq 0 ] && exit 2
window=$(
xdotool search --name "$1" | \
sed 1q
)
desk=$(
xdotool get_desktop_for_window "$window" 2>/dev/null || printf "none"
)
[ "$desk" = "none" ] && exit 1
desk=$((desk + 1))
bspc desktop -f "^${desk}"
killall -10 simplestatus
xdotool set_window --urgency 1 "$window"
exit 0

19
utils/sh/vol Executable file
View File

@ -0,0 +1,19 @@
#!/bin/sh
pulse=$(pgrep -c pulseaudio)
[ "$1" = "inc" ] && sign="+"
[ "$1" = "dec" ] && sign="-"
[ "$#" -eq 0 ] && exit 1
if [ "$pulse" -eq 1 ]; then
for SINK in $(pacmd list-sinks | grep 'index:' | cut -b12-)
do
pactl set-sink-volume "$SINK" "${sign}5%"
done
else
amixer -c 0 set Master "5%${sign}"
fi
killall -12 status

32
utils/sh/wallpaper Executable file
View File

@ -0,0 +1,32 @@
#!/bin/sh
WALLDIR="${HOME}/.local/share/wallpapers"
BASECMD="feh --no-fehbg --bg-fill"
generate_wall () {
GENWALL=$( \
ls "$WALLDIR" | \
grep "." | \
shuf -n 1
)
GENWALL="${WALLDIR}/${GENWALL}"
}
wall () {
generate_wall
while [ "${GENWALL}" = "${1}" ]; do
generate_wall
done
}
displays () {
displays=$(xrandr | grep -c ' connected')
}
cmd=""
displays
for i in $(seq 1 "$displays"); do
wall "${tmp}"
tmp="${GENWALL}"
cmd="${cmd} ${GENWALL}"
done
eval "${BASECMD}" "${cmd}"
exit 0