add utils into repo
This commit is contained in:
commit
ea581aa433
|
@ -18,3 +18,13 @@ tridactyl/tridactyl
|
|||
nvim/autoload/plug.vim.old
|
||||
nvim/spell/
|
||||
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
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
test
|
|
@ -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
|
|
@ -0,0 +1,5 @@
|
|||
TODO LIST
|
||||
---------
|
||||
|
||||
- fix paste
|
||||
- make the c programs less buggy and let them not suck as much
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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++;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
DESTDIR=$(HOME)/.local
|
||||
|
|
@ -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')
|
|
@ -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
|
|
@ -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.
|
||||
|
|
@ -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
|
|
@ -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>
|
|
@ -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
|
||||
|
|
@ -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\""
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,6 @@
|
|||
#!/bin/sh
|
||||
|
||||
sel="$(find -L ~/.config 2>/dev/null | fzy)"
|
||||
[ "$?" -eq 1 ] && exit 1
|
||||
|
||||
nvim "$sel"
|
|
@ -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
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
chromium --app=https://discord.com/login --profile-directory="Profile 1"
|
|
@ -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
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
HOME="/home/usr/.local/share/firefox" firefox "$@"
|
|
@ -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
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
printf "password=%s\n" "$(pash s tildegit)"
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,18 @@
|
|||
#!/bin/sh
|
||||
|
||||
host="$(hostname)"
|
||||
|
||||
case "$host" in
|
||||
"mlg")
|
||||
exit 1
|
||||
;;
|
||||
"toaster")
|
||||
exit 2
|
||||
;;
|
||||
"fish")
|
||||
exit 3
|
||||
;;
|
||||
"think")
|
||||
exit 4
|
||||
;;
|
||||
esac
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
# designed to be called from sxhkd (x session)
|
||||
|
||||
pgrep NetworkManager && st -e nmtui
|
|
@ -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
|
|
@ -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"
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/sh
|
||||
|
||||
pash c "$1"
|
||||
bspc node -d '^9'
|
||||
sleep 15
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
|
||||
[ "$1" = "" ] && exit 1
|
||||
[ -f "$1" ] && curl -F"file=@${1}" https://0x0.st && exit 0
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
# opens snapcad
|
||||
|
||||
wine ~/.wine/drive_c/Program\ Files\ \(x86\)/VEX\ Robotics/SnapCAD/SnapCAD.exe
|
|
@ -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"
|
|
@ -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
|
|
@ -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
|
|
@ -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"
|
|
@ -0,0 +1,6 @@
|
|||
#!/bin/sh
|
||||
|
||||
printf "%s" "$1"
|
||||
|
||||
fzy < "$1" > "${1}a"
|
||||
mv "${1}a" "${1}"
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue