skratch/skratch.c

174 lines
3.5 KiB
C
Raw Permalink Normal View History

2026-03-20 17:14:30 -07:00
#include <dirent.h>
2026-03-20 16:58:04 -07:00
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
struct Flags
{
int use_v;
int use_s;
2026-03-21 14:55:32 -07:00
char *suffix; // file suffix
char skratch_path[4096]; // ~/.skratch
char file_path[4096]; // ~/.skratch/<filename><suffix>
char filename[255]; // skratch-XXXXXX
char editor[255]; // editor to open file with
2026-03-20 16:58:04 -07:00
};
2026-03-21 14:55:32 -07:00
// sets f.editor using env vars
2026-03-20 16:58:04 -07:00
void set_editor(struct Flags *f)
{
char *ed;
2026-03-20 18:20:24 -07:00
if (f->use_v)
2026-03-20 16:58:04 -07:00
ed = getenv("VISUAL");
else
ed = getenv("EDITOR");
2026-03-20 18:20:24 -07:00
if (ed)
2026-03-20 16:58:04 -07:00
strcpy(f->editor, ed);
2026-03-21 14:55:32 -07:00
else //no env vars set
2026-03-20 16:58:04 -07:00
strcpy(f->editor, "vi");
}
2026-03-21 14:55:32 -07:00
// sets f.file_path and makes a file in ~/.skratch if needed
2026-03-20 16:58:04 -07:00
int make_skratch_file(struct Flags *f)
{
char fp[4096];
int fd = 0;
2026-03-21 13:36:35 -07:00
if (!f->use_s) f->suffix = "";
snprintf(fp, sizeof(fp), "%s/%s%s", f->skratch_path, f->filename, f->suffix);
2026-03-21 00:57:28 -07:00
if (!strcmp(f->filename, "skratch-XXXXXX"))
2026-03-20 16:58:04 -07:00
{
2026-03-21 13:36:35 -07:00
int s_len = strlen(f->suffix);
fd = mkstemps(fp, s_len);
2026-03-20 16:58:04 -07:00
close(fd);
}
if (fd == -1)
{
printf("ERROR: Couldn't create skratch file!");
return 3;
}
strcpy(f->file_path, fp);
return 0;
}
2026-03-21 14:55:32 -07:00
// creates ~/.skratch if needed and sets f.skratch_path
2026-03-20 16:58:04 -07:00
int make_skratch_path(struct Flags *f)
{
char sp[4096];
char *home_path = getenv("HOME");
if (home_path == NULL)
{
printf("ERROR: No HOME variable set!");
return 1;
}
snprintf(sp, sizeof(sp), "%s/.skratch", home_path);
int result = mkdir(sp, 0755);
if (result < 0 && errno != EEXIST)
{
printf("ERROR: Couldn't create: %s\n", sp);
return 2;
}
strcpy(f->skratch_path, sp);
return 0;
}
2026-03-21 14:55:32 -07:00
// lists files in f.skratch_path, with option to delete
// this should likely have all delete logic inside delete_files()
2026-03-20 18:20:24 -07:00
int list_files(struct Flags *f, int delete)
2026-03-20 17:14:30 -07:00
{
DIR *d = opendir(f->skratch_path);
if (d == NULL) return 5;
struct dirent *dir;
if (d)
{
while ((dir = readdir(d)) != NULL)
2026-03-20 18:20:24 -07:00
{
char fn[4096];
strcpy(fn,dir->d_name);
if (!strcmp(".",fn) || !strcmp("..",fn))
{
continue;
}
if (delete)
{
char fp[4096];
snprintf(fp, sizeof(fp), "%s/%s", f->skratch_path, dir->d_name);
remove(fp);
}
else printf("%s\n", dir->d_name);
2026-03-20 17:14:30 -07:00
}
closedir(d);
}
return 0;
}
2026-03-21 14:55:32 -07:00
// menu confirmation for deleting files in f.skratch_path
// there is a bug if the user has no input
2026-03-20 18:20:24 -07:00
int delete_files(struct Flags *f)
{
list_files(f, 0);
printf("Delete the listed files? [y/N] ");
char choice = 'N';
scanf(" %c", &choice);
if (choice == 'y' || choice == 'Y')
{
list_files(f, 1);
}
return 0;
}
2026-03-21 14:55:32 -07:00
// handles arguments and runs the editor
2026-03-20 16:58:04 -07:00
int main(int argc, char *argv[])
{
2026-03-21 00:57:28 -07:00
int opt;
struct Flags f = {.use_v = 0, .filename="skratch-XXXXXX"};
2026-03-20 16:58:04 -07:00
make_skratch_path(&f);
2026-03-21 15:08:29 -07:00
//handle args
2026-03-21 00:57:28 -07:00
while ((opt = getopt(argc, argv, "cls:v")) != -1)
2026-03-20 16:58:04 -07:00
{
2026-03-21 00:57:28 -07:00
switch (opt)
2026-03-20 16:58:04 -07:00
{
2026-03-21 15:08:29 -07:00
case 'c': // delete ~/.skratch files
2026-03-20 18:20:24 -07:00
delete_files(&f);
return 0;
2026-03-21 15:08:29 -07:00
case 'l': // list ~/.skratch files
2026-03-21 00:57:28 -07:00
list_files(&f, 0);
2026-03-20 17:14:30 -07:00
return 0;
2026-03-21 15:08:29 -07:00
case 's': // use file suffix, like .txt
2026-03-21 00:57:28 -07:00
f.use_s = 1;
f.suffix = optarg;
break;
2026-03-21 15:08:29 -07:00
case 'v': // use visual editor
2026-03-20 18:20:24 -07:00
f.use_v = 1;
2026-03-20 16:58:04 -07:00
break;
default:
2026-03-21 00:57:28 -07:00
printf("error print usage");
}
}
2026-03-21 15:08:29 -07:00
// find optional filename if exists
2026-03-21 00:57:28 -07:00
for (int i = optind; i < argc; i++)
{
if (!strcmp(f.filename,"skratch-XXXXXX"))
{
strcpy(f.filename, argv[i]);
}
else
{
printf("ERROR: Too many file args");
return 1;
2026-03-20 16:58:04 -07:00
}
}
set_editor(&f);
2026-03-20 18:20:24 -07:00
make_skratch_file(&f);
2026-03-20 18:38:24 -07:00
char *args[3];
2026-03-20 16:58:04 -07:00
args[0] = f.editor;
args[1] = f.file_path;
2026-03-20 18:38:24 -07:00
args[2] = NULL;
2026-03-21 00:57:28 -07:00
execvp(f.editor, args);
return 0;
2026-03-20 16:58:04 -07:00
}