Compare commits
No commits in common. "ff79dbcd648c3286701509532770a820fb5c9bfb" and "b1930d91750731a6acb9b0f9935a280a6e6ba389" have entirely different histories.
ff79dbcd64
...
b1930d9175
6 changed files with 132 additions and 179 deletions
14
README.md
14
README.md
|
@ -55,20 +55,18 @@ t: go to trash dir
|
||||||
-: go to previous dir
|
-: go to previous dir
|
||||||
z: refresh current dir
|
z: refresh current dir
|
||||||
:: go to a directory by typing
|
:: go to a directory by typing
|
||||||
|
u: sort files
|
||||||
|
|
||||||
.: toggle hidden files
|
.: toggle hidden files
|
||||||
A: show directory disk usage/block size
|
|
||||||
i: toggle file details
|
i: toggle file details
|
||||||
u: sort files
|
X: toggle executable
|
||||||
x: view file/dir attributes
|
|
||||||
e: show history
|
|
||||||
y: copy filename to clipboard
|
|
||||||
!: open shell in current dir
|
!: open shell in current dir
|
||||||
|
|
||||||
|
A: show directory disk usage/block size
|
||||||
|
|
||||||
f: new file
|
f: new file
|
||||||
n: new dir
|
n: new dir
|
||||||
r: rename
|
r: rename
|
||||||
X: toggle executable
|
|
||||||
|
|
||||||
space: mark file
|
space: mark file
|
||||||
a: mark all files in directory
|
a: mark all files in directory
|
||||||
|
@ -84,6 +82,10 @@ O: open file with a GUI program detached from file manager
|
||||||
|
|
||||||
/: search
|
/: search
|
||||||
|
|
||||||
|
x: view file/dir attributes
|
||||||
|
e: show history
|
||||||
|
y: copy filename to clipboard
|
||||||
|
|
||||||
c: copy
|
c: copy
|
||||||
m: move
|
m: move
|
||||||
s: symbolic link
|
s: symbolic link
|
||||||
|
|
10
ccc.1
10
ccc.1
|
@ -35,20 +35,18 @@ t: go to trash dir
|
||||||
-: go to previous dir
|
-: go to previous dir
|
||||||
z: refresh current dir
|
z: refresh current dir
|
||||||
:: go to a directory by typing
|
:: go to a directory by typing
|
||||||
|
u: sort files
|
||||||
|
|
||||||
.: toggle hidden files
|
.: toggle hidden files
|
||||||
A: show directory disk usage/block size
|
|
||||||
i: toggle file details
|
i: toggle file details
|
||||||
u: sort files
|
X: toggle executable
|
||||||
x: view file/dir attributes
|
|
||||||
e: show history
|
|
||||||
y: copy filename to clipboard
|
|
||||||
!: open shell in current dir
|
!: open shell in current dir
|
||||||
|
|
||||||
|
A: show directory disk usage/block size
|
||||||
|
|
||||||
f: new file
|
f: new file
|
||||||
n: new dir
|
n: new dir
|
||||||
r: rename
|
r: rename
|
||||||
X: toggle executable
|
|
||||||
|
|
||||||
space: mark file
|
space: mark file
|
||||||
a: mark all files in directory
|
a: mark all files in directory
|
||||||
|
|
251
ccc.c
251
ccc.c
|
@ -53,6 +53,7 @@ void mkdir_p(const char *destdir);
|
||||||
void populate_files(const char *path, int ftype, ArrayList **list);
|
void populate_files(const char *path, int ftype, ArrayList **list);
|
||||||
int get_directory_size(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf);
|
int get_directory_size(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf);
|
||||||
void add_file_stat(char *filename, char *path, int ftype);
|
void add_file_stat(char *filename, char *path, int ftype);
|
||||||
|
char *get_file_mode(mode_t mode);
|
||||||
void list_files(void);
|
void list_files(void);
|
||||||
void show_file_content(void);
|
void show_file_content(void);
|
||||||
void edit_file(void);
|
void edit_file(void);
|
||||||
|
@ -69,8 +70,6 @@ void create_file(void);
|
||||||
void delete_files(void);
|
void delete_files(void);
|
||||||
void start_shell(void);
|
void start_shell(void);
|
||||||
void yank_clipboard(void);
|
void yank_clipboard(void);
|
||||||
void view_file_attr(void);
|
|
||||||
void show_history(void);
|
|
||||||
void wpprintw(const char *fmt, ...);
|
void wpprintw(const char *fmt, ...);
|
||||||
void move_cursor(int row, int col);
|
void move_cursor(int row, int col);
|
||||||
int readch(void);
|
int readch(void);
|
||||||
|
@ -82,9 +81,9 @@ unsigned int focus = 0;
|
||||||
long sel_file = 0;
|
long sel_file = 0;
|
||||||
int file_picker = 1;
|
int file_picker = 1;
|
||||||
int to_open_file = 0;
|
int to_open_file = 0;
|
||||||
char argv_cp[PATH_MAX];
|
char *argv_cp;
|
||||||
char cwd[PATH_MAX];
|
char *cwd;
|
||||||
char p_cwd[PATH_MAX]; /* previous cwd */
|
char *p_cwd; /* previous cwd */
|
||||||
int half_width;
|
int half_width;
|
||||||
ArrayList *files;
|
ArrayList *files;
|
||||||
ArrayList *marked;
|
ArrayList *marked;
|
||||||
|
@ -115,7 +114,7 @@ int main(int argc, char **argv)
|
||||||
perror("ccc");
|
perror("ccc");
|
||||||
die("Error from chdir");
|
die("Error from chdir");
|
||||||
} else if (S_ISREG(st.st_mode)) {
|
} else if (S_ISREG(st.st_mode)) {
|
||||||
strcpy(argv_cp, argv[1]);
|
argv_cp = estrdup(argv[1]);
|
||||||
char *last_slash = strrchr(argv_cp, '/');
|
char *last_slash = strrchr(argv_cp, '/');
|
||||||
if (last_slash) {
|
if (last_slash) {
|
||||||
*last_slash = '\0';
|
*last_slash = '\0';
|
||||||
|
@ -161,7 +160,10 @@ int main(int argc, char **argv)
|
||||||
marked = arraylist_init(100);
|
marked = arraylist_init(100);
|
||||||
hashtable_init();
|
hashtable_init();
|
||||||
|
|
||||||
|
cwd = memalloc(PATH_MAX);
|
||||||
getcwd(cwd, PATH_MAX);
|
getcwd(cwd, PATH_MAX);
|
||||||
|
p_cwd = memalloc(PATH_MAX);
|
||||||
|
p_cwd[0] = '\0';
|
||||||
populate_files(cwd, 0, &files);
|
populate_files(cwd, 0, &files);
|
||||||
handle_sigwinch(-1);
|
handle_sigwinch(-1);
|
||||||
|
|
||||||
|
@ -190,27 +192,27 @@ int main(int argc, char **argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* go back */
|
/* go back */
|
||||||
case BACKSPACE:;
|
case BACKSPACE:
|
||||||
case ARROW_LEFT:;
|
case ARROW_LEFT:
|
||||||
case 'h':;
|
case 'h':
|
||||||
char dir[PATH_MAX];
|
|
||||||
strcpy(dir, cwd);
|
|
||||||
/* get parent directory */
|
/* get parent directory */
|
||||||
char *last_slash = strrchr(dir, '/');
|
strcpy(p_cwd, cwd);
|
||||||
if (last_slash) {
|
char *last_slash = strrchr(cwd, '/');
|
||||||
if (!strcmp(last_slash, dir)) {
|
if (last_slash != NULL) {
|
||||||
|
if (last_slash == cwd) {
|
||||||
change_dir("/", 0, 0);
|
change_dir("/", 0, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
*last_slash = '\0';
|
*last_slash = '\0';
|
||||||
change_dir(dir, 0, 0);
|
change_dir(cwd, 0, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* enter directory/open a file */
|
/* enter directory/open a file */
|
||||||
case ENTER:;
|
case ENTER:
|
||||||
case ARROW_RIGHT:;
|
case ARROW_RIGHT:
|
||||||
case 'l':;
|
case 'l':
|
||||||
|
strcpy(p_cwd, cwd);
|
||||||
file c_file = files->items[sel_file];
|
file c_file = files->items[sel_file];
|
||||||
|
|
||||||
/* Check if it is directory or a regular file */
|
/* Check if it is directory or a regular file */
|
||||||
|
@ -277,10 +279,10 @@ int main(int argc, char **argv)
|
||||||
/* '~' go to $HOME */
|
/* '~' go to $HOME */
|
||||||
case TILDE:;
|
case TILDE:;
|
||||||
char *home = getenv("HOME");
|
char *home = getenv("HOME");
|
||||||
if (!home) {
|
if (home == NULL) {
|
||||||
wpprintw("$HOME not defined (Press any key to continue)");
|
wpprintw("$HOME not defined");
|
||||||
readch();
|
|
||||||
} else {
|
} else {
|
||||||
|
strcpy(p_cwd, cwd);
|
||||||
change_dir(home, 0, 0);
|
change_dir(home, 0, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -288,9 +290,9 @@ int main(int argc, char **argv)
|
||||||
/* go to the trash dir */
|
/* go to the trash dir */
|
||||||
case 't':;
|
case 't':;
|
||||||
char *trash_dir = check_trash_dir();
|
char *trash_dir = check_trash_dir();
|
||||||
if (trash_dir) {
|
if (trash_dir != NULL) {
|
||||||
|
strcpy(p_cwd, cwd);
|
||||||
change_dir(trash_dir, 0, 0);
|
change_dir(trash_dir, 0, 0);
|
||||||
free(trash_dir);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -362,16 +364,6 @@ int main(int argc, char **argv)
|
||||||
yank_clipboard();
|
yank_clipboard();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'o':
|
|
||||||
case 'O':
|
|
||||||
case 'x':
|
|
||||||
view_file_attr();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'e':
|
|
||||||
show_history();
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* mark one file */
|
/* mark one file */
|
||||||
case SPACE:
|
case SPACE:
|
||||||
add_file_stat(files->items[sel_file].name, files->items[sel_file].path, 1);
|
add_file_stat(files->items[sel_file].name, files->items[sel_file].path, 1);
|
||||||
|
@ -437,6 +429,8 @@ void handle_sigwinch(int ignore)
|
||||||
|
|
||||||
void cleanup(void)
|
void cleanup(void)
|
||||||
{
|
{
|
||||||
|
if (argv_cp != NULL)
|
||||||
|
free(argv_cp);
|
||||||
if (files->length != 0) {
|
if (files->length != 0) {
|
||||||
arraylist_free(files);
|
arraylist_free(files);
|
||||||
}
|
}
|
||||||
|
@ -465,7 +459,7 @@ void show_help(void)
|
||||||
"\n\n?: show help\nq: exit with last dir written to file\n"
|
"\n\n?: show help\nq: exit with last dir written to file\n"
|
||||||
"ctrl+c exit without writing last dir"
|
"ctrl+c exit without writing last dir"
|
||||||
"\nPress any key to continue"
|
"\nPress any key to continue"
|
||||||
);
|
);
|
||||||
wpprintw("Visit https://github.com/night0721/ccc or use 'man ccc' for help");
|
wpprintw("Visit https://github.com/night0721/ccc or use 'man ccc' for help");
|
||||||
readch();
|
readch();
|
||||||
}
|
}
|
||||||
|
@ -502,18 +496,8 @@ char *check_trash_dir(void)
|
||||||
*/
|
*/
|
||||||
void change_dir(const char *buf, int selection, int ftype)
|
void change_dir(const char *buf, int selection, int ftype)
|
||||||
{
|
{
|
||||||
if (strcmp(cwd, buf) != 0) {
|
if (cwd != buf)
|
||||||
char tmp[PATH_MAX];
|
strcpy(cwd, buf);
|
||||||
strcpy(tmp, buf);
|
|
||||||
strcpy(p_cwd, cwd);
|
|
||||||
strcpy(cwd, tmp);
|
|
||||||
char history_path[PATH_MAX];
|
|
||||||
strcpy(history_path, "~/.cache/ccc/history");
|
|
||||||
replace_home(history_path);
|
|
||||||
FILE *history_file = fopen(history_path, "a");
|
|
||||||
fprintf(history_file, "%s\n", cwd);
|
|
||||||
fclose(history_file);
|
|
||||||
}
|
|
||||||
if (ftype == 0)
|
if (ftype == 0)
|
||||||
arraylist_free(files);
|
arraylist_free(files);
|
||||||
chdir(cwd);
|
chdir(cwd);
|
||||||
|
@ -527,11 +511,12 @@ void change_dir(const char *buf, int selection, int ftype)
|
||||||
*/
|
*/
|
||||||
void mkdir_p(const char *destdir)
|
void mkdir_p(const char *destdir)
|
||||||
{
|
{
|
||||||
char path[PATH_MAX], dir_path[PATH_MAX];
|
char *path = memalloc(PATH_MAX);
|
||||||
|
char dir_path[PATH_MAX] = "";
|
||||||
|
|
||||||
if (destdir[0] == '~') {
|
if (destdir[0] == '~') {
|
||||||
char *home = getenv("HOME");
|
char *home = getenv("HOME");
|
||||||
if (!home) {
|
if (home == NULL) {
|
||||||
wpprintw("$HOME not defined");
|
wpprintw("$HOME not defined");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -546,7 +531,7 @@ void mkdir_p(const char *destdir)
|
||||||
dir_path[0] = '/';
|
dir_path[0] = '/';
|
||||||
|
|
||||||
char *token = strtok(path, "/");
|
char *token = strtok(path, "/");
|
||||||
while (token) {
|
while (token != NULL) {
|
||||||
strcat(dir_path, token);
|
strcat(dir_path, token);
|
||||||
strcat(dir_path, "/");
|
strcat(dir_path, "/");
|
||||||
|
|
||||||
|
@ -559,10 +544,13 @@ void mkdir_p(const char *destdir)
|
||||||
}
|
}
|
||||||
|
|
||||||
wpprintw("mkdir failed: %s", strerror(errno));
|
wpprintw("mkdir failed: %s", strerror(errno));
|
||||||
|
free(path);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
token = strtok(NULL, "/");
|
token = strtok(NULL, "/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(path);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -575,13 +563,13 @@ void populate_files(const char *path, int ftype, ArrayList **list)
|
||||||
DIR *dp;
|
DIR *dp;
|
||||||
struct dirent *ep;
|
struct dirent *ep;
|
||||||
|
|
||||||
if ((dp = opendir(path))) {
|
if ((dp = opendir(path)) != NULL) {
|
||||||
if (ftype == 0) {
|
if (ftype == 0) {
|
||||||
tmp1 = arraylist_init(10);
|
tmp1 = arraylist_init(10);
|
||||||
tmp2 = arraylist_init(10);
|
tmp2 = arraylist_init(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((ep = readdir(dp))) {
|
while ((ep = readdir(dp)) != NULL) {
|
||||||
char *filename = estrdup(ep->d_name);
|
char *filename = estrdup(ep->d_name);
|
||||||
|
|
||||||
/* Filter out dotfiles */
|
/* Filter out dotfiles */
|
||||||
|
@ -598,7 +586,6 @@ void populate_files(const char *path, int ftype, ArrayList **list)
|
||||||
if (ftype == 0) {
|
if (ftype == 0) {
|
||||||
*list = arraylist_init(tmp1->length + tmp2->length);
|
*list = arraylist_init(tmp1->length + tmp2->length);
|
||||||
(*list)->length = tmp1->length + tmp2->length;
|
(*list)->length = tmp1->length + tmp2->length;
|
||||||
/* Need to see how to sort by date */
|
|
||||||
qsort(tmp1->items, tmp1->length, sizeof(file), sort_compare);
|
qsort(tmp1->items, tmp1->length, sizeof(file), sort_compare);
|
||||||
qsort(tmp2->items, tmp2->length, sizeof(file), sort_compare);
|
qsort(tmp2->items, tmp2->length, sizeof(file), sort_compare);
|
||||||
memcpy((*list)->items, tmp1->items, tmp1->length * sizeof(file));
|
memcpy((*list)->items, tmp1->items, tmp1->length * sizeof(file));
|
||||||
|
@ -635,29 +622,29 @@ void add_file_stat(char *filename, char *path, int ftype)
|
||||||
}
|
}
|
||||||
|
|
||||||
int type;
|
int type;
|
||||||
char icon_str[5];
|
char *icon_str = memalloc(8);
|
||||||
|
|
||||||
filename[strlen(filename)] = '\0';
|
filename[strlen(filename)] = '\0';
|
||||||
/* handle file without extension
|
/* handle file without extension
|
||||||
* ext is the extension if . exist in filename
|
* ext is the extension if . exist in filename
|
||||||
* otherwise is nothing and handled through tenery operator */
|
* otherwise is nothing and handled through tenery operator */
|
||||||
char *ext = strrchr(filename, '.');
|
char *ext = strrchr(filename, '.');
|
||||||
if (ext) {
|
if (ext != NULL) {
|
||||||
ext += 1;
|
ext += 1;
|
||||||
}
|
}
|
||||||
/* add file extension */
|
/* add file extension */
|
||||||
icon *ext_icon = hashtable_search(ext ? ext : filename);
|
icon *ext_icon = hashtable_search(ext != NULL ? ext : filename);
|
||||||
if (!ext_icon)
|
if (ext_icon == NULL)
|
||||||
memcpy(icon_str, "", 4);
|
memcpy(icon_str, "", 4);
|
||||||
else
|
else
|
||||||
memcpy(icon_str, ext_icon->icon, 4);
|
memcpy(icon_str, ext_icon->icon, 5);
|
||||||
|
|
||||||
int color = DEF_COLOR;
|
int color = DEF_COLOR;
|
||||||
|
|
||||||
if (S_ISDIR(file_stat.st_mode)) {
|
if (S_ISDIR(file_stat.st_mode)) {
|
||||||
type = DRY; /* dir */
|
type = DRY; /* dir */
|
||||||
color = DIR_COLOR;
|
color = DIR_COLOR;
|
||||||
memcpy(icon_str, "", 4);
|
memcpy(icon_str, "", 5);
|
||||||
} else if (S_ISREG(file_stat.st_mode)) {
|
} else if (S_ISREG(file_stat.st_mode)) {
|
||||||
type = REG; /* regular file */
|
type = REG; /* regular file */
|
||||||
color = REG_COLOR;
|
color = REG_COLOR;
|
||||||
|
@ -690,7 +677,7 @@ void add_file_stat(char *filename, char *path, int ftype)
|
||||||
|
|
||||||
/* get last modified time */
|
/* get last modified time */
|
||||||
size_t time_size = 17;
|
size_t time_size = 17;
|
||||||
char time[time_size];
|
char *time = memalloc(time_size);
|
||||||
/* Format last modified time to a string */
|
/* Format last modified time to a string */
|
||||||
strftime(time, time_size, "%Y-%m-%d %H:%M", localtime(&file_stat.st_mtime));
|
strftime(time, time_size, "%Y-%m-%d %H:%M", localtime(&file_stat.st_mtime));
|
||||||
|
|
||||||
|
@ -707,10 +694,10 @@ void add_file_stat(char *filename, char *path, int ftype)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* 4 before decimal + 1 dot + decimal_place (after decimal) +
|
/* 4 before decimal + 1 dot + decimal_place (after decimal) +
|
||||||
* unit length (1 for K, 3 for KiB, taking units[1] as B never changes) + 1 space + 1 null */
|
unit length (1 for K, 3 for KiB, taking units[1] as B never changes) + 1 space + 1 null */
|
||||||
static const char* units[] = {"B", "K", "M", "G", "T", "P"};
|
static const char* units[] = {"B", "K", "M", "G", "T", "P"};
|
||||||
int size_size = 4 + 1 + decimal_place + strlen(units[1]) + 1 + 1;
|
int size_size = 4 + 1 + decimal_place + strlen(units[1]) + 1 + 1;
|
||||||
char size[size_size];
|
char *size = memalloc(size_size);
|
||||||
int unit = 0;
|
int unit = 0;
|
||||||
while (bytes > 1024) {
|
while (bytes > 1024) {
|
||||||
bytes /= 1024;
|
bytes /= 1024;
|
||||||
|
@ -723,33 +710,46 @@ void add_file_stat(char *filename, char *path, int ftype)
|
||||||
sprintf(size, "%.*f%s", decimal_place, bytes, units[unit]);
|
sprintf(size, "%.*f%s", decimal_place, bytes, units[unit]);
|
||||||
}
|
}
|
||||||
/* get file mode string */
|
/* get file mode string */
|
||||||
char mode_str[11];
|
char *mode_str = get_file_mode(file_stat.st_mode);
|
||||||
mode_str[0] = S_ISDIR(file_stat.st_mode) ? 'd' : '-';
|
|
||||||
mode_str[1] = (file_stat.st_mode & S_IRUSR) ? 'r' : '-';
|
|
||||||
mode_str[2] = (file_stat.st_mode & S_IWUSR) ? 'w' : '-';
|
|
||||||
mode_str[3] = (file_stat.st_mode & S_IXUSR) ? 'x' : '-';
|
|
||||||
mode_str[4] = (file_stat.st_mode & S_IRGRP) ? 'r' : '-';
|
|
||||||
mode_str[5] = (file_stat.st_mode & S_IWGRP) ? 'w' : '-';
|
|
||||||
mode_str[6] = (file_stat.st_mode & S_IXGRP) ? 'x' : '-';
|
|
||||||
mode_str[7] = (file_stat.st_mode & S_IROTH) ? 'r' : '-';
|
|
||||||
mode_str[8] = (file_stat.st_mode & S_IWOTH) ? 'w' : '-';
|
|
||||||
mode_str[9] = (file_stat.st_mode & S_IXOTH) ? 'x' : '-';
|
|
||||||
mode_str[10] = 0;
|
|
||||||
|
|
||||||
if (mode_str[0] == '-' && (mode_str[3] == 'x' || mode_str[6] == 'x' || mode_str[9] == 'x')) {
|
if (mode_str[0] == '-' && (mode_str[3] == 'x' || mode_str[6] == 'x' || mode_str[9] == 'x')) {
|
||||||
color = EXE_COLOR;
|
color = EXE_COLOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* mode_str + time(17) + size_size + 2 spaces + 1 null */
|
/* mode_str(11) + time(17) + size_size + 2 spaces + 1 null */
|
||||||
size_t stat_size = 11 + 17 + size_size + 3;
|
size_t stat_size = 11 + time_size + size_size + 3;
|
||||||
char *total_stat = memalloc(stat_size);
|
char *total_stat = memalloc(stat_size);
|
||||||
sprintf(total_stat, "%s %s %-*s", mode_str, time, size_size, size);
|
snprintf(total_stat, stat_size, "%s %s %-*s", mode_str, time, size_size, size);
|
||||||
|
|
||||||
/* DIR if color is blue */
|
/* DIR if color is blue */
|
||||||
if (color == 34)
|
if (color == 34)
|
||||||
arraylist_add(tmp1, filename, path, total_stat, type, icon_str, color, 0, 0);
|
arraylist_add(tmp1, filename, path, total_stat, type, icon_str, color, 0, 0);
|
||||||
else
|
else
|
||||||
arraylist_add(tmp2, filename, path, total_stat, type, icon_str, color, 0, 0);
|
arraylist_add(tmp2, filename, path, total_stat, type, icon_str, color, 0, 0);
|
||||||
|
|
||||||
|
free(time);
|
||||||
|
free(size);
|
||||||
|
free(mode_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get file mode string from stat mode
|
||||||
|
* eg: drwxr-sr-x
|
||||||
|
*/
|
||||||
|
char *get_file_mode(mode_t mode)
|
||||||
|
{
|
||||||
|
char *mode_str = memalloc(11);
|
||||||
|
mode_str[0] = S_ISDIR(mode) ? 'd' : '-';
|
||||||
|
mode_str[1] = (mode & S_IRUSR) ? 'r' : '-';
|
||||||
|
mode_str[2] = (mode & S_IWUSR) ? 'w' : '-';
|
||||||
|
mode_str[3] = (mode & S_IXUSR) ? 'x' : '-';
|
||||||
|
mode_str[4] = (mode & S_IRGRP) ? 'r' : '-';
|
||||||
|
mode_str[5] = (mode & S_IWGRP) ? 'w' : '-';
|
||||||
|
mode_str[6] = (mode & S_IXGRP) ? 'x' : '-';
|
||||||
|
mode_str[7] = (mode & S_IROTH) ? 'r' : '-';
|
||||||
|
mode_str[8] = (mode & S_IWOTH) ? 'w' : '-';
|
||||||
|
mode_str[9] = (mode & S_IXOTH) ? 'x' : '-';
|
||||||
|
mode_str[10] = '\0';
|
||||||
|
return mode_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -796,11 +796,11 @@ void list_files(void)
|
||||||
if (num_marked > 0) {
|
if (num_marked > 0) {
|
||||||
/* Determine length of formatted string */
|
/* Determine length of formatted string */
|
||||||
int m_len = snprintf(NULL, 0, "[%ld] selected", num_marked);
|
int m_len = snprintf(NULL, 0, "[%ld] selected", num_marked);
|
||||||
char selected[m_len + 1];
|
char *selected = memalloc(m_len + 1);
|
||||||
|
|
||||||
snprintf(selected, m_len + 1, "[%ld] selected", num_marked);
|
snprintf(selected, m_len + 1, "[%ld] selected", num_marked);
|
||||||
wpprintw("(%ld/%ld) %s %s", sel_file + 1, files->length, selected, cwd);
|
wpprintw("(%ld/%ld) %s %s", sel_file + 1, files->length, selected, cwd);
|
||||||
} else {
|
} else {
|
||||||
wpprintw("(%ld/%ld) %s", sel_file + 1, files->length, cwd);
|
wpprintw("(%ld/%ld) %s", sel_file + 1, files->length, cwd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -810,8 +810,8 @@ void list_files(void)
|
||||||
/* check is file marked for action */
|
/* check is file marked for action */
|
||||||
int is_marked = arraylist_search(marked, files->items[i].path, 0) != -1;
|
int is_marked = arraylist_search(marked, files->items[i].path, 0) != -1;
|
||||||
move_cursor(i + 1, 1);
|
move_cursor(i + 1, 1);
|
||||||
if (is_marked) color = MAR_COLOR;
|
if (is_marked) color = 32;
|
||||||
bprintf("\033[30m\033[%dm%s\033[m\n",
|
bprintf("\033[30m\033[%dm%s\033[0m\n",
|
||||||
is_selected ? color + 10 : color, line);
|
is_selected ? color + 10 : color, line);
|
||||||
|
|
||||||
free(line);
|
free(line);
|
||||||
|
@ -885,7 +885,7 @@ void show_file_content(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
FILE *file = fopen(current_file.path, "r");
|
FILE *file = fopen(current_file.path, "r");
|
||||||
if (!file) {
|
if (file == NULL) {
|
||||||
bprintf("Unable to read %s", current_file.name);
|
bprintf("Unable to read %s", current_file.name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -919,7 +919,7 @@ void show_file_content(void)
|
||||||
char buffer[4096];
|
char buffer[4096];
|
||||||
int row = 1;
|
int row = 1;
|
||||||
FILE *stream = fdopen(pipe_fd[0], "r");
|
FILE *stream = fdopen(pipe_fd[0], "r");
|
||||||
while (fgets(buffer, sizeof(buffer), stream) && row <= rows - 1) {
|
while (fgets(buffer, sizeof(buffer), stream) != NULL && row <= rows - 1) {
|
||||||
buffer[strcspn(buffer, "\n")] = 0;
|
buffer[strcspn(buffer, "\n")] = 0;
|
||||||
|
|
||||||
if (buffer[0] == '\0' || strspn(buffer, " \t") == strlen(buffer)) {
|
if (buffer[0] == '\0' || strspn(buffer, " \t") == strlen(buffer)) {
|
||||||
|
@ -982,9 +982,9 @@ void show_file_content(void)
|
||||||
*/
|
*/
|
||||||
void edit_file(void)
|
void edit_file(void)
|
||||||
{
|
{
|
||||||
if (!strcmp(editor, "")) {
|
if (editor == NULL) {
|
||||||
editor = getenv("EDITOR");
|
editor = getenv("EDITOR");
|
||||||
if (!editor) {
|
if (editor == NULL) {
|
||||||
wpprintw("$EDITOR not defined");
|
wpprintw("$EDITOR not defined");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1011,23 +1011,21 @@ void toggle_executable(void)
|
||||||
file f = files->items[sel_file];
|
file f = files->items[sel_file];
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (stat(f.path, &st) == -1) {
|
if (stat(f.path, &st) == -1) {
|
||||||
wpprintw("stat failed: %s (Press any key to continue)", strerror(errno));
|
wpprintw("stat failed: %s", strerror(errno));
|
||||||
readch();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (f.type == DRY)
|
if (f.type == DRY)
|
||||||
return;
|
return;
|
||||||
/* chmod by xor executable bits */
|
/* chmod by xor executable bits */
|
||||||
if (chmod(f.path, st.st_mode ^ (S_IXUSR | S_IXGRP | S_IXOTH)) == -1) {
|
if (chmod(f.path, st.st_mode ^ (S_IXUSR | S_IXGRP | S_IXOTH)) == -1) {
|
||||||
wpprintw("Error toggling executable: %s (Press any key to continue)", strerror(errno));
|
wpprintw("Error toggling executable: %s", strerror(errno));
|
||||||
readch();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void replace_home(char *str)
|
void replace_home(char *str)
|
||||||
{
|
{
|
||||||
char *home = getenv("HOME");
|
char *home = getenv("HOME");
|
||||||
if (!home) {
|
if (home == NULL) {
|
||||||
wpprintw("$HOME not defined");
|
wpprintw("$HOME not defined");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1054,12 +1052,12 @@ int write_last_d(void)
|
||||||
strcpy(last_ddup, last_d);
|
strcpy(last_ddup, last_d);
|
||||||
|
|
||||||
char *last_d_dir = strrchr(last_ddup, '/');
|
char *last_d_dir = strrchr(last_ddup, '/');
|
||||||
if (last_d_dir) {
|
if (last_d_dir != NULL) {
|
||||||
*last_d_dir = '\0'; /* truncate string */
|
*last_d_dir = '\0'; /* truncate string */
|
||||||
}
|
}
|
||||||
mkdir_p(last_ddup);
|
mkdir_p(last_ddup);
|
||||||
FILE *last_d_file = fopen(last_d, "w");
|
FILE *last_d_file = fopen(last_d, "w");
|
||||||
if (!last_d_file) {
|
if (last_d_file == NULL) {
|
||||||
wpprintw("Cannot open last directory file (Press any key to continue)");
|
wpprintw("Cannot open last directory file (Press any key to continue)");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1128,8 +1126,7 @@ void rename_file(void)
|
||||||
if (!input) {
|
if (!input) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
char newfilename[PATH_MAX];
|
char *newfilename = estrdup(filename);
|
||||||
strcpy(newfilename, filename);
|
|
||||||
/* remove basename of newfilename */
|
/* remove basename of newfilename */
|
||||||
char *last_slash = strrchr(newfilename, '/');
|
char *last_slash = strrchr(newfilename, '/');
|
||||||
*last_slash = '\0';
|
*last_slash = '\0';
|
||||||
|
@ -1144,14 +1141,12 @@ void rename_file(void)
|
||||||
wpprintw("Renamed %s to %s", filename, newfilename);
|
wpprintw("Renamed %s to %s", filename, newfilename);
|
||||||
}
|
}
|
||||||
free(input);
|
free(input);
|
||||||
|
free(newfilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
void goto_dir(void)
|
void goto_dir(void)
|
||||||
{
|
{
|
||||||
char *input = get_panel_string("Goto dir: ");
|
char *input = get_panel_string("Goto dir: ");
|
||||||
if (!input) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (lstat(input, &st)) {
|
if (lstat(input, &st)) {
|
||||||
wpprintw("lstat failed: %s (Press any key to continue)", strerror(errno));
|
wpprintw("lstat failed: %s (Press any key to continue)", strerror(errno));
|
||||||
|
@ -1162,21 +1157,16 @@ void goto_dir(void)
|
||||||
wpprintw("chdir failed: %s (Press any key to continue)", strerror(errno));
|
wpprintw("chdir failed: %s (Press any key to continue)", strerror(errno));
|
||||||
readch();
|
readch();
|
||||||
}
|
}
|
||||||
char new_cwd[PATH_MAX];
|
getcwd(cwd, PATH_MAX);
|
||||||
getcwd(new_cwd, PATH_MAX);
|
change_dir(cwd, 0, 0);
|
||||||
change_dir(new_cwd, 0, 0);
|
|
||||||
free(input);
|
free(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_dir(void)
|
void create_dir(void)
|
||||||
{
|
{
|
||||||
char *input = get_panel_string("New dir: ");
|
char *input = get_panel_string("New dir: ");
|
||||||
if (!input) {
|
char *newfilename = memalloc(PATH_MAX);
|
||||||
return;
|
|
||||||
}
|
|
||||||
char newfilename[PATH_MAX];
|
|
||||||
snprintf(newfilename, PATH_MAX, "%s/%s", cwd, input);
|
snprintf(newfilename, PATH_MAX, "%s/%s", cwd, input);
|
||||||
|
|
||||||
if (access(newfilename, F_OK) != 0) {
|
if (access(newfilename, F_OK) != 0) {
|
||||||
mkdir_p(newfilename);
|
mkdir_p(newfilename);
|
||||||
change_dir(cwd, 0, 0);
|
change_dir(cwd, 0, 0);
|
||||||
|
@ -1185,14 +1175,12 @@ void create_dir(void)
|
||||||
wpprintw("Directory already exist");
|
wpprintw("Directory already exist");
|
||||||
}
|
}
|
||||||
free(input);
|
free(input);
|
||||||
|
free(newfilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_file(void)
|
void create_file(void)
|
||||||
{
|
{
|
||||||
char *input = get_panel_string("New file: ");
|
char *input = get_panel_string("New file: ");
|
||||||
if (!input) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
FILE *f = fopen(input, "w+");
|
FILE *f = fopen(input, "w+");
|
||||||
fclose(f);
|
fclose(f);
|
||||||
change_dir(cwd, 0, 0);
|
change_dir(cwd, 0, 0);
|
||||||
|
@ -1204,15 +1192,16 @@ void delete_files(void)
|
||||||
{
|
{
|
||||||
if (marked->length) {
|
if (marked->length) {
|
||||||
char *trash_dir = check_trash_dir();
|
char *trash_dir = check_trash_dir();
|
||||||
if (trash_dir) {
|
if (trash_dir != NULL) {
|
||||||
for (int i = 0; i < marked->length; i++) {
|
for (int i = 0; i < marked->length; i++) {
|
||||||
char new_path[PATH_MAX];
|
char *new_path = memalloc(PATH_MAX);
|
||||||
snprintf(new_path, PATH_MAX, "%s/%s", trash_dir, marked->items[i].name);
|
snprintf(new_path, PATH_MAX, "%s/%s", trash_dir, marked->items[i].name);
|
||||||
if (rename(marked->items[i].path, new_path)) {
|
if (rename(marked->items[i].path, new_path)) {
|
||||||
wpprintw("delete failed: %s", strerror(errno));
|
wpprintw("delete failed: %s", strerror(errno));
|
||||||
|
} else {
|
||||||
|
change_dir(cwd, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
change_dir(cwd, 0, 0);
|
|
||||||
for (int i = 0; i < marked->length; i++) {
|
for (int i = 0; i < marked->length; i++) {
|
||||||
arraylist_remove(marked, 0);
|
arraylist_remove(marked, 0);
|
||||||
}
|
}
|
||||||
|
@ -1264,44 +1253,6 @@ void yank_clipboard(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void view_file_attr(void)
|
|
||||||
{
|
|
||||||
bprintf("\033[2J");
|
|
||||||
move_cursor(1, 1);
|
|
||||||
pid_t pid = fork();
|
|
||||||
if (pid == 0) {
|
|
||||||
/* Child process */
|
|
||||||
execlp("stat", "stat", files->items[sel_file].name, NULL);
|
|
||||||
_exit(1); /* Exit if exec fails */
|
|
||||||
} else if (pid > 0) {
|
|
||||||
/* Parent process */
|
|
||||||
waitpid(pid, NULL, 0);
|
|
||||||
} else {
|
|
||||||
/* Fork failed */
|
|
||||||
wpprintw("fork failed: %s", strerror(errno));
|
|
||||||
}
|
|
||||||
readch();
|
|
||||||
}
|
|
||||||
|
|
||||||
void show_history(void)
|
|
||||||
{
|
|
||||||
bprintf("\033[2J");
|
|
||||||
move_cursor(1, 1);
|
|
||||||
char history_path[PATH_MAX];
|
|
||||||
strcpy(history_path, "~/.cache/ccc/history");
|
|
||||||
replace_home(history_path);
|
|
||||||
FILE *history_file = fopen(history_path, "r");
|
|
||||||
char buffer[PATH_MAX];
|
|
||||||
int row = 1;
|
|
||||||
while (fgets(buffer, sizeof(buffer), history_file) && row <= rows - 1) {
|
|
||||||
move_cursor(row++, 1);
|
|
||||||
bprintf(buffer);
|
|
||||||
|
|
||||||
}
|
|
||||||
fclose(history_file);
|
|
||||||
readch();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Print line to the panel
|
* Print line to the panel
|
||||||
*/
|
*/
|
||||||
|
|
1
config.h
1
config.h
|
@ -13,7 +13,6 @@ enum files_colors {
|
||||||
FIF_COLOR = 35, /* FIFO */
|
FIF_COLOR = 35, /* FIFO */
|
||||||
DEF_COLOR = 37, /* Default */
|
DEF_COLOR = 37, /* Default */
|
||||||
EXE_COLOR = 32, /* Executable file */
|
EXE_COLOR = 32, /* Executable file */
|
||||||
MAR_COLOR = 36, /* Marked files */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Set width offset for windows:
|
/* Set width offset for windows:
|
||||||
|
|
29
file.c
29
file.c
|
@ -23,6 +23,8 @@ void arraylist_free(ArrayList *list)
|
||||||
free(list->items[i].path);
|
free(list->items[i].path);
|
||||||
if (list->items[i].stats != NULL)
|
if (list->items[i].stats != NULL)
|
||||||
free(list->items[i].stats);
|
free(list->items[i].stats);
|
||||||
|
if (list->items[i].icon != NULL)
|
||||||
|
free(list->items[i].icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(list->items);
|
free(list->items);
|
||||||
|
@ -70,8 +72,7 @@ void arraylist_remove(ArrayList *list, long index)
|
||||||
*/
|
*/
|
||||||
void arraylist_add(ArrayList *list, char *name, char *path, char *stats, int type, char *icon, int color, int marked, int force)
|
void arraylist_add(ArrayList *list, char *name, char *path, char *stats, int type, char *icon, int color, int marked, int force)
|
||||||
{
|
{
|
||||||
file new_file = { name, path, type, stats, color };
|
file new_file = { name, path, type, stats, icon, color };
|
||||||
strcpy(new_file.icon, icon);
|
|
||||||
|
|
||||||
if (list->capacity != list->length) {
|
if (list->capacity != list->length) {
|
||||||
if (marked) {
|
if (marked) {
|
||||||
|
@ -105,27 +106,29 @@ void arraylist_add(ArrayList *list, char *name, char *path, char *stats, int typ
|
||||||
*/
|
*/
|
||||||
char *get_line(ArrayList *list, long index, int detail, int icons)
|
char *get_line(ArrayList *list, long index, int detail, int icons)
|
||||||
{
|
{
|
||||||
file f = list->items[index];
|
file file = list->items[index];
|
||||||
|
|
||||||
size_t length = strlen(f.name) + 1;
|
size_t name_len = strlen(file.name);
|
||||||
|
size_t length;
|
||||||
if (detail) {
|
if (detail) {
|
||||||
length += strlen(f.stats) + 1; /* 1 for space */
|
length = name_len + strlen(file.stats) + 7; /* 4 for icon, 2 for space and 1 for null */
|
||||||
}
|
} else {
|
||||||
if (icons) {
|
length = name_len + 6; /* 4 for icon, 1 for space and 1 for null */
|
||||||
length += 5; /* 4 for icon, 1 for space */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *line = memalloc(length);
|
char *line = memalloc(length);
|
||||||
line[0] = '\0';
|
line[0] = '\0';
|
||||||
if (detail) {
|
if (detail) {
|
||||||
strcat(line, f.stats);
|
strcat(line, file.stats);
|
||||||
strcat(line, " ");
|
strcat(line, " ");
|
||||||
}
|
}
|
||||||
if (icons) {
|
if (icons) {
|
||||||
strcat(line, f.icon);
|
char *tmp = memalloc(10);
|
||||||
strcat(line, " ");
|
snprintf(tmp, 10, "%s ", file.icon);
|
||||||
|
strcat(line, tmp);
|
||||||
|
free(tmp);
|
||||||
}
|
}
|
||||||
strcat(line, f.name);
|
strcat(line, file.name);
|
||||||
line[length] = '\0';
|
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
6
file.h
6
file.h
|
@ -13,16 +13,16 @@ enum ftypes {
|
||||||
FIF
|
FIF
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct file {
|
||||||
char *name; /* basename */
|
char *name; /* basename */
|
||||||
char *path; /* absolute path */
|
char *path; /* absolute path */
|
||||||
int type;
|
int type;
|
||||||
char *stats;
|
char *stats;
|
||||||
|
char *icon;
|
||||||
int color;
|
int color;
|
||||||
char icon[5];
|
|
||||||
} file;
|
} file;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct ArrayList {
|
||||||
size_t length;
|
size_t length;
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
file *items;
|
file *items;
|
||||||
|
|
Loading…
Reference in a new issue