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