Lotsa improvements.

This commit is contained in:
Bruce Hill 2019-01-03 04:38:27 -08:00
parent 0adbd9b687
commit d46ea384aa
4 changed files with 239 additions and 115 deletions

View File

@ -17,5 +17,6 @@ install: nuke
if [[ ! $$prefix ]]; then \
prefix="/usr/local"; \
fi; \
mkdir -pv $$prefix/bin; \
cp -v nuke $$prefix/bin/
mkdir -pv $$prefix/bin $$prefix/share/man/man1 \
&& cp -v nuke $$prefix/bin/ \
&& cp -v doc/nuke.1 $$prefix/share/man/man1/

37
doc/nuke.1 Normal file
View File

@ -0,0 +1,37 @@
.\" Manpage for nuke.
.\" Contact bruce@bruce-hill.com to correct errors or typos.
.TH man 8 "3 January 2019" "1.0" "nuke man page"
.SH NAME
nuke \- nuke files from orbit
.SH SYNOPSIS
.B nuke
[
.I files...
]
.SH DESCRIPTION
Sometimes, deleting a file isn't enough. \fBnuke\fR will nuke them from orbit.
.SH INPUT
.TP
\fBnuke\fR will recursively delete all files and directories you provide it.
It will ask for confirmation before deleting.
.SH OPTIONS
.B \--help
Print the command line usage.
.SH EXAMPLES
.TP
.B
nuke node-v10.14.0/
Nukes the directory node-v10.14.0/
.TP
.B
nuke tame_porn/ risque_porn/ outlandish_porn/
Nukes all three directories
.TP
.B
sudo nuke /
Uh, you might not want to try that one.
.SH AUTHOR
Bruce Hill (bruce@bruce-hill.com)

75
globe.h
View File

@ -50,14 +50,14 @@ static double mix(double a, double b, double amount)
return (1.-amount)*a + amount*b;
}
void draw_stars()
void draw_stars(double t)
{
int rows,cols;
getmaxyx(stdscr,rows,cols);
attron(COLOR_PAIR(WHITE));
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
double n = hillnoise(r*100,c*200);
double n = hillnoise(r*1,c*2+(t*.04));
if (n > .8) {
mvaddch(r,c,n > .9 ? '*' : '.');
}
@ -66,11 +66,16 @@ void draw_stars()
attroff(COLOR_PAIR(WHITE));
}
static double get_rotation(double t)
{
return t * (2*M_PI)/60. + M_PI;
}
void draw_globe(double t, double zoom)
{
int rows,cols;
getmaxyx(stdscr,rows,cols);
double rotation = t * (2*M_PI)/10. + M_PI;
double rotation = get_rotation(t);
const double rho = rows/2.;
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
@ -114,15 +119,16 @@ void draw_globe(double t, double zoom)
}
}
void draw_scorch(double t, double zoom, int *targetr, int *targetc)
// return 1 if visible, else 0
int get_target_pos(double t, double zoom, int *targetr, int *targetc)
{
int rows,cols;
getmaxyx(stdscr,rows,cols);
double rotation = t * (2*M_PI)/10. + M_PI*1.4;
double rotation = get_rotation(t);
const double rho = rows/2.;
double theta = M_PI/2*1.1;
double phi = M_PI + rotation;
double theta = M_PI/2*1.00;
double phi = M_PI + rotation + 2.3;
double x = rho*sin(theta)*cos(phi);
double y = rho*sin(theta)*sin(phi);
double z = rho*cos(theta);
@ -130,58 +136,5 @@ void draw_scorch(double t, double zoom, int *targetr, int *targetc)
int c = y / (.5/zoom) + cols/2;
*targetr = r;
*targetc = c;
attron(COLOR_PAIR(BLACK) | A_BOLD);
mvprintw(r-1,c-1,"****");
mvprintw(r,c-2, "******");
mvprintw(r+1,c-1,"****");
attroff(COLOR_PAIR(BLACK) | A_BOLD);
}
void draw_target(double t, double zoom, int *targetr, int *targetc)
{
int rows,cols;
getmaxyx(stdscr,rows,cols);
double rotation = t * (2*M_PI)/10. + M_PI*1.4;
const double rho = rows/2.;
double theta = M_PI/2*1.1;
double phi = M_PI + rotation;
double x = rho*sin(theta)*cos(phi);
double y = rho*sin(theta)*sin(phi);
double z = rho*cos(theta);
int r = z / (1.0/zoom) + rows/2;
int c = y / (.5/zoom) + cols/2;
*targetr = r;
*targetc = c;
if (x < 0) {
attron(COLOR_PAIR(YELLOW));
mvaddch(r,c, '*' | A_BOLD);
attroff(COLOR_PAIR(YELLOW));
}
double wobble = t > 2.5 ? 0. : 2.5 - t;
if (wobble > .01) {
r = mix(r, rows*hillnoise(784,5.*t), wobble);
c = mix(c, cols*hillnoise(-784,5.*t), wobble);
}
int attr = COLOR_PAIR(RED);
attron(attr);
mvaddch(r-1,c-2,ACS_ULCORNER | A_BOLD);
mvaddch(r-1,c-1,ACS_HLINE | A_BOLD);
//mvaddch(r-1,c-0,ACS_HLINE | A_BOLD);
mvaddch(r-1,c+1,ACS_HLINE | A_BOLD);
mvaddch(r-1,c+2,ACS_URCORNER | A_BOLD);
//mvaddch(r-0,c+2,ACS_VLINE | A_BOLD);
mvaddch(r+1,c+2,ACS_LRCORNER | A_BOLD);
mvaddch(r+1,c+1,ACS_HLINE | A_BOLD);
//mvaddch(r+1,c+0,ACS_HLINE | A_BOLD);
mvaddch(r+1,c-1,ACS_HLINE | A_BOLD);
mvaddch(r+1,c-2,ACS_LLCORNER | A_BOLD);
//mvaddch(r+0,c-2,ACS_VLINE | A_BOLD);
mvaddch(r,c,'X' | A_BOLD);
attroff(attr);
return x < 0;
}

237
nuke.c
View File

@ -15,7 +15,7 @@
#include <string.h>
#include <unistd.h>
#define NUM_FRAMES 120
#define NUM_FRAMES 100
#define NUM_BLOBS 800
#define PERSPECTIVE 50.0
#define ESCDELAY 10
@ -120,6 +120,13 @@ int rmrf(char *path)
int main(int argc, char *argv[])
{
if (argc > 1 && strcmp(argv[1], "--help") == 0) {
printf("nuke: Nuke files from orbit.\nUsage: nuke [files...]\n");
return EXIT_SUCCESS;
}
char *failure_message = "Did not delete.";
int rows,cols;
int delay=1E5;
spaceblob *blobs;
@ -178,79 +185,196 @@ int main(int argc, char *argv[])
curs_set(0); /* hide text cursor */
noecho();
keypad(stdscr, 1);
// First frame
erase();
int max_line = 0;
for (int f = 0; f < num_files; f++) {
int len = strlen(files[f]);
if (len > max_line) max_line = len;
}
for (int f = 0; f < num_files; f++) {
mvprintw(rows/2-num_files/2+f, cols/2-max_line/2, "%s", files[f]);
erase();
int padwidth = max_line < cols*3/4 ? max_line : cols*3/4;
int padheight = num_files < rows*3/4 ? num_files : rows*3/4;
int padframer = rows/2-padheight/2-1;
int padframec = cols/2-padwidth/2-1;
WINDOW *padframe = newwin(padheight+2, padwidth+2, padframer, padframec);
if (!padframe) {
failure_message = "Couldn't create pad frame";
goto exit_failure;
}
refresh();
wattron(padframe, COLOR_PAIR(YELLOW) | A_BOLD);
box(padframe, 0, 0);
WINDOW *pad = newpad(padheight, max_line);
if (!pad) {
failure_message = "Couldn't create pad";
goto exit_failure;
}
/* Display confirmation */
attron(COLOR_PAIR(BLACK_ON_RED));
const char confirm[] = " FIRE NUKE? y/n ";
mvprintw((rows*3)/4, cols/2 - strlen(confirm)/2, "%s", confirm);
attroff(COLOR_PAIR(BLACK_ON_RED));
char description[] = " TARGET: ";
if (num_files > 1) {
description[13] = 'S', description[14] = ':';
}
mvprintw(padframer-2, cols/2 - strlen(description)/2, "%s", description);
attron(COLOR_PAIR(BLACK_ON_RED) | A_BLINK);
const char confirm[] = " FIRE NUKE? y/n ";
mvprintw(padframer+padheight+3, cols/2 - strlen(confirm)/2, "%s", confirm);
attroff(COLOR_PAIR(BLACK_ON_RED) | A_BLINK);
refresh();
//immedok(pad, 1);
int scrollx = 0, scrolly = 0;
timeout(10);
while (1) {
// Draw scroll bar
if (padheight < num_files) {
mvaddch(padframer, padframec+padwidth+2, ACS_UARROW);
mvaddch(padframer+padheight+1, padframec+padwidth+2, ACS_DARROW);
for (int i = 1; i <= padheight; i++)
mvaddch(padframer+i, padframec+padwidth+2, ACS_VLINE);
for (int i = scrolly*padheight/num_files; i <= scrolly*padheight/num_files+padheight*padheight/num_files; i++)
mvaddch(padframer+1+i, padframec+padwidth+2, ACS_CKBOARD);
}
box(padframe, 0, 0);
if (wrefresh(padframe) == ERR) goto exit_failure;
// Redo this each time so that pad doesn't have to hold everything in memory
werase(pad);
for (int f = scrolly; f < scrolly+padheight; f++) {
mvwprintw(pad,f-scrolly,0,"%s",files[f]);
}
if (prefresh(pad, 0, scrollx, padframer+1, padframec+1, padframer+padheight, padframec+padwidth) == ERR)
goto exit_failure;
//prefresh(pad, scrolly, scrollx, 1, 1, 1+padheight, 1+padwidth);
//prefresh(pad, scrolly, scrollx, rows/2-padheight/2, cols/2-padwidth/2, rows/2+padheight/2, cols/2+padwidth/2);
refresh();
get_input:
switch(getch()) {
case 'y':
goto do_the_nuking;
case 'n': case 'q': case 27:
goto exit_failure;
case KEY_DOWN: case 'j': case ' ':
scrolly++;
break;
case KEY_UP: case 'k':
scrolly--;
break;
case KEY_RIGHT: case 'l':
scrollx++;
break;
case KEY_LEFT: case 'h':
scrollx--;
break;
case 'J': case KEY_NPAGE:
scrolly += num_files/20+1;
break;
case 'K': case KEY_PPAGE:
scrolly -= num_files/20+1;
break;
case KEY_SRIGHT: case 'L':
scrollx += 10;
break;
case KEY_SLEFT: case 'H':
scrollx -= 10;
break;
case KEY_HOME: case 'g':
scrolly = 0;
break;
case KEY_END: case 'G':
scrolly = num_files-padheight;
break;
default:
goto get_input;
}
if (scrolly < 0) scrolly = 0;
if (scrolly > num_files-padheight) scrolly = num_files-padheight;
if (scrollx < 0) scrollx = 0;
if (scrollx > max_line-padwidth) scrollx = max_line-padwidth;
}
do_the_nuking: ;
double zoom = .8; // percent of viewport globe will fill
/*
timeout(10);
chtype line[cols+1];
for (int f = 0; 1; f = (f + 1) % num_files) {
int i;
for (i = 0; files[f][i]; i++) {
line[i] = files[f][i];
}
for (; i < max_line; i++) line[i] = ' ';
line[i] = '\0';
//mvprintw(rows/2, cols/2-max_line/2, "%s", files[f]);
mvaddchstr(rows/2, cols/2-max_line/2,line);
refresh();
int ch = getch();
if (ch == -1)
usleep(33333); // 30 FPS
else if (ch != 'y')
goto exit_failure;
else break;
}
*/
if (getch() != 'y') {
goto exit_failure;
}
timeout(10);
const double targeting_time = 2.5;
const double anticipation = 0.5;
const double firing_time = 1.0;
const double nuking_time = .5;
const double aftermath = 1.0;
int f = 0;
int targetr, targetc;
for (int i=0; i<30*3; i++) {
double t = 0.0;
for (; t < targeting_time + anticipation + firing_time; t += 1./30.) {
erase();
draw_stars();
draw_globe((double)i/30., zoom);
draw_target((double)i/30, zoom, &targetr, &targetc);
attron(COLOR_PAIR(RED));
mvaddch(targetr-1,targetc+1,'/');
attroff(COLOR_PAIR(RED));
attron(COLOR_PAIR(BLACK_ON_RED));
mvprintw(targetr-2,targetc+2,"%s", argv[f+1]);
attroff(COLOR_PAIR(BLACK_ON_RED));
f = (f + 1) % (argc - 1);
draw_stars(t);
draw_globe(t, zoom);
if (get_target_pos(t, zoom, &targetr, &targetc)) {
// If visible draw '*' on globe
attron(COLOR_PAIR(YELLOW));
mvaddch(targetr,targetc, '*' | A_BOLD);
attroff(COLOR_PAIR(YELLOW));
}
// Draw crosshair
double wobble = t > targeting_time ? 0. : targeting_time - t;
int r = targetr, c = targetc;
if (wobble > .01) {
r = mix(r, rows*hillnoise(784,5.*t), wobble);
c = mix(c, cols*hillnoise(-784,5.*t), wobble);
}
int attr = COLOR_PAIR(RED);
attron(attr);
mvaddch(r-1,c-2,ACS_ULCORNER | A_BOLD);
mvaddch(r-1,c-1,ACS_HLINE | A_BOLD);
mvaddch(r-1,c+1,ACS_HLINE | A_BOLD);
mvaddch(r-1,c+2,ACS_URCORNER | A_BOLD);
mvaddch(r+1,c+2,ACS_LRCORNER | A_BOLD);
mvaddch(r+1,c+1,ACS_HLINE | A_BOLD);
mvaddch(r+1,c-1,ACS_HLINE | A_BOLD);
mvaddch(r+1,c-2,ACS_LLCORNER | A_BOLD);
mvaddch(r,c,'X' | A_BOLD);
attroff(attr);
// Draw label
if (get_target_pos(t, zoom, &targetr, &targetc)) {
attron(COLOR_PAIR(RED));
mvaddch(targetr-1,targetc+1,'/');
attroff(COLOR_PAIR(RED));
attron(COLOR_PAIR(BLACK_ON_RED));
mvprintw(targetr-2,targetc+2,"%s", argc > 1 ? argv[f+1] : "target");
attroff(COLOR_PAIR(BLACK_ON_RED));
if (argc > 2)
f = (f + 1) % (argc - 1);
}
// Draw nuke
if (t > targeting_time + anticipation) {
double k = (t-targeting_time-anticipation)/firing_time;
int nuker = mix(rows, targetr, k), nukec = mix(cols/2, targetc, k);
attron(COLOR_PAIR(WHITE) | A_BOLD);
mvaddch(nuker, nukec, "=-. "[(int)(k*4.)]);
attroff(COLOR_PAIR(WHITE) | A_BOLD);
}
refresh();
// Check for input
int ch = getch();
if (ch == 'q' || ch == 27) {
goto exit_success;
if (t <= targeting_time + anticipation) {
goto exit_failure;
} else {
goto exit_success;
}
}
usleep(33333); // 30 FPS
}
t += nuking_time;
for (int i=1; i<NUM_FRAMES; i++) {
draw_frame(i, targetc, targetr, blobs);
refresh();
@ -262,16 +386,24 @@ int main(int argc, char *argv[])
usleep(33333); // 30 FPS
}
for (int i=30*3.5; i < 30*5; i++) {
for (; t < targeting_time + anticipation + firing_time + nuking_time + aftermath; t += 1./30.) {
erase();
draw_stars();
draw_globe((double)i/30., zoom);
draw_scorch((double)i/30, zoom, &targetr, &targetc);
draw_stars(t);
draw_globe(t, zoom);
// Draw crater
if (get_target_pos(t, zoom, &targetr, &targetc)) {
attron(COLOR_PAIR(BLACK) | A_BOLD);
mvprintw(targetr-1,targetc-1,"****");
mvprintw(targetr,targetc-2, "** **");
mvprintw(targetr+1,targetc-1,"****");
attroff(COLOR_PAIR(BLACK) | A_BOLD);
}
// Draw label
attron(COLOR_PAIR(GREEN));
mvaddch(targetr-1,targetc+1,'/');
attroff(COLOR_PAIR(GREEN));
attron(COLOR_PAIR(BLACK_ON_GREEN));
mvprintw(targetr-2,targetc+2," <GONE> ");
mvprintw(targetr-2,targetc+2," DELETED ");
attroff(COLOR_PAIR(BLACK_ON_GREEN));
refresh();
int ch = getch();
@ -297,5 +429,6 @@ exit_success:
exit_failure:
curs_set(1); /* unhide cursor */
endwin(); /* Exit ncurses */
printf("%s\n",failure_message);
return EXIT_FAILURE;
}