commit
5f6c4ee903
5 changed files with 193 additions and 45 deletions
26
Makefile
26
Makefile
|
@ -1,26 +1,30 @@
|
||||||
.POSIX:
|
.POSIX:
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
|
|
||||||
|
CC = cc
|
||||||
|
VERSION = 1.0
|
||||||
TARGET = ccc
|
TARGET = ccc
|
||||||
MANPAGE = ccc.1
|
MANPAGE = ccc.1
|
||||||
SRC = ccc.c util.c file.c config.h
|
CONF = config.h
|
||||||
|
PREFIX ?= /usr/local
|
||||||
|
BINDIR = $(PREFIX)/bin
|
||||||
|
MANDIR = $(PREFIX)/share/man/man1
|
||||||
|
|
||||||
# Flags
|
# Flags
|
||||||
LDFLAGS = $(shell pkg-config --libs ncurses)
|
LDFLAGS = $(shell pkg-config --libs ncurses)
|
||||||
CFLAGS = -march=native -mtune=native -O3 -pipe -s -std=c99 -pedantic $(shell pkg-config --cflags ncurses) -Wall # -Wextra -Werror
|
CFLAGS = -march=native -mtune=native -O3 -pipe -s -std=c99 -pedantic $(shell pkg-config --cflags ncurses) -Wall # -Wextra -Werror
|
||||||
CC=cc
|
|
||||||
PREFIX ?= /usr/local
|
|
||||||
CONF = config.h
|
|
||||||
|
|
||||||
BINDIR = $(PREFIX)/bin
|
SRC = ccc.c util.c file.c $(CONF)
|
||||||
MANDIR = $(PREFIX)/share/man/man1
|
|
||||||
|
|
||||||
.PHONY: all install uninstall clean
|
|
||||||
|
|
||||||
$(TARGET): $(SRC)
|
$(TARGET): $(SRC)
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) $(SRC) -o $@
|
$(CC) $(CFLAGS) $(LDFLAGS) $(SRC) -o $@
|
||||||
|
|
||||||
all: $(TARGET)
|
dist:
|
||||||
|
mkdir -p $(TARGET)-$(VERSION)
|
||||||
|
cp -R README.md $(MANPAGE) $(TARGET) $(TARGET)-$(VERSION)
|
||||||
|
tar -cf $(TARGET)-$(VERSION).tar $(TARGET)-$(VERSION)
|
||||||
|
gzip $(TARGET)-$(VERSION).tar
|
||||||
|
rm -rf $(TARGET)-$(VERSION)
|
||||||
|
|
||||||
install: $(TARGET)
|
install: $(TARGET)
|
||||||
mkdir -p $(DESTDIR)$(BINDIR)
|
mkdir -p $(DESTDIR)$(BINDIR)
|
||||||
|
@ -36,3 +40,7 @@ uninstall:
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(RM) $(TARGET)
|
$(RM) $(TARGET)
|
||||||
|
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
.PHONY: all dist install uninstall clean
|
||||||
|
|
114
ccc.c
114
ccc.c
|
@ -39,6 +39,7 @@ void draw_border_title(WINDOW *window, bool active);
|
||||||
/* global variables */
|
/* global variables */
|
||||||
unsigned int focus = 0;
|
unsigned int focus = 0;
|
||||||
long current_selection = 0;
|
long current_selection = 0;
|
||||||
|
bool dir_mode = BLOCK_SIZE;
|
||||||
char *cwd;
|
char *cwd;
|
||||||
int half_width;
|
int half_width;
|
||||||
WIN_STRUCT windows[5];
|
WIN_STRUCT windows[5];
|
||||||
|
@ -84,7 +85,7 @@ int main(int argc, char** argv)
|
||||||
init_pair(4, COLOR_YELLOW, -1); /* BLK */
|
init_pair(4, COLOR_YELLOW, -1); /* BLK */
|
||||||
init_pair(5, COLOR_BLUE, -1); /* DIR */
|
init_pair(5, COLOR_BLUE, -1); /* DIR */
|
||||||
init_pair(6, COLOR_MAGENTA, -1); /* */
|
init_pair(6, COLOR_MAGENTA, -1); /* */
|
||||||
init_pair(7, COLOR_CYAN, -1); /* */
|
init_pair(7, COLOR_CYAN, -1); /* MARKED FILES */
|
||||||
init_pair(8, COLOR_WHITE, -1); /* REG */
|
init_pair(8, COLOR_WHITE, -1); /* REG */
|
||||||
|
|
||||||
half_width = COLS / 2;
|
half_width = COLS / 2;
|
||||||
|
@ -238,8 +239,16 @@ int main(int argc, char** argv)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* a to toggle between DISK_USAGE and BLOCK SIZE */
|
||||||
|
case 'a':
|
||||||
|
dir_mode = !dir_mode;
|
||||||
|
clear_files();
|
||||||
|
populate_files(cwd);
|
||||||
|
highlight_current_line();
|
||||||
|
break;
|
||||||
|
|
||||||
/* mark files by space */
|
/* mark files by space */
|
||||||
case SPACE:
|
case SPACE:;
|
||||||
add_file_stat(get_filepath(current_selection), 1);
|
add_file_stat(get_filepath(current_selection), 1);
|
||||||
highlight_current_line();
|
highlight_current_line();
|
||||||
break;
|
break;
|
||||||
|
@ -392,11 +401,15 @@ long add_file_stat(char *filepath, int ftype)
|
||||||
|
|
||||||
/* get file size */
|
/* get file size */
|
||||||
double bytes = file_stat.st_size;
|
double bytes = file_stat.st_size;
|
||||||
if (S_ISDIR(file_stat.st_mode)) {
|
|
||||||
/* at most 15 fd opened */
|
if (!dir_mode) {
|
||||||
total_dir_size = 0;
|
/* dir_mode is 0, so disk usage mode, calculate disk usage */
|
||||||
nftw(filepath, &get_directory_size, 15, FTW_PHYS);
|
if (S_ISDIR(file_stat.st_mode)) {
|
||||||
bytes = total_dir_size;
|
/* at most 15 fd opened */
|
||||||
|
total_dir_size = 0;
|
||||||
|
nftw(filepath, &get_directory_size, 15, FTW_PHYS);
|
||||||
|
bytes = total_dir_size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* max 25 chars due to long, space, suffix and null */
|
/* max 25 chars due to long, space, suffix and null */
|
||||||
char *size = memalloc(25 * sizeof(char));
|
char *size = memalloc(25 * sizeof(char));
|
||||||
|
@ -443,7 +456,14 @@ long add_file_stat(char *filepath, int ftype)
|
||||||
free(type);
|
free(type);
|
||||||
free(size);
|
free(size);
|
||||||
free(time);
|
free(time);
|
||||||
return index;
|
if (index != -1) {
|
||||||
|
/* just marked */
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
/* already marked */
|
||||||
|
return -1;
|
||||||
|
/* -1 does nothing, just function required to return something */
|
||||||
|
|
||||||
}
|
}
|
||||||
char *total_stat = memalloc(45 * sizeof(char));
|
char *total_stat = memalloc(45 * sizeof(char));
|
||||||
snprintf(total_stat, 45, "%-18s %-10s", time, size);
|
snprintf(total_stat, 45, "%-18s %-10s", time, size);
|
||||||
|
@ -495,6 +515,15 @@ void highlight_current_line()
|
||||||
|
|
||||||
/* update the panel */
|
/* update the panel */
|
||||||
wclear(panel);
|
wclear(panel);
|
||||||
|
|
||||||
|
/* showing dir_mode requires 26 characters */
|
||||||
|
char *dir_mode_line = memalloc(27 * sizeof(char));
|
||||||
|
if (dir_mode)
|
||||||
|
strncpy(dir_mode_line, "Directory Mode: Block Size", 27);
|
||||||
|
else
|
||||||
|
strncpy(dir_mode_line, "Directory Mode: Disk Usage", 27);
|
||||||
|
|
||||||
|
/* check for marked files */
|
||||||
long num_marked = marked_len();
|
long num_marked = marked_len();
|
||||||
if (num_marked > 0) {
|
if (num_marked > 0) {
|
||||||
/* Determine length of formatted string */
|
/* Determine length of formatted string */
|
||||||
|
@ -502,24 +531,36 @@ void highlight_current_line()
|
||||||
char *selected = memalloc((m_len + 1) * sizeof(char));
|
char *selected = memalloc((m_len + 1) * sizeof(char));
|
||||||
|
|
||||||
snprintf(selected, m_len + 1, "(%ld selected)", num_marked);
|
snprintf(selected, m_len + 1, "(%ld selected)", num_marked);
|
||||||
wprintw(panel, "(%ld/%ld) %s %s", current_selection + 1, files_len(), selected, cwd);
|
wprintw(panel, "(%ld/%ld) %s %s %s", current_selection + 1, files_len(), selected, cwd, dir_mode_line);
|
||||||
} else {
|
} else {
|
||||||
wprintw(panel, "(%ld/%ld) %s", current_selection + 1, files_len(), cwd);
|
wprintw(panel, "(%ld/%ld) %s %s", current_selection + 1, files_len(), cwd, dir_mode_line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* print the actual filename and stats */
|
/* print the actual filename and stats */
|
||||||
char *line = get_line(i);
|
char *line = get_line(i);
|
||||||
int color = get_color(i);
|
int color = get_color(i);
|
||||||
|
/* check is file marked for action */
|
||||||
|
bool marked = in_marked(get_filepath(i));
|
||||||
|
if (marked) {
|
||||||
|
/* show file is selected */
|
||||||
|
wattron(directory_content, COLOR_PAIR(7));
|
||||||
|
} else {
|
||||||
|
/* print the whole directory with default colors */
|
||||||
|
wattron(directory_content, COLOR_PAIR(color));
|
||||||
|
}
|
||||||
|
|
||||||
/* print the whole directory with colors */
|
|
||||||
wattron(directory_content, COLOR_PAIR(color));
|
|
||||||
if (overflow > 0)
|
if (overflow > 0)
|
||||||
mvwprintw(directory_content, line_count, 0, "%s", line);
|
mvwprintw(directory_content, line_count, 0, "%s", line);
|
||||||
else
|
else
|
||||||
mvwprintw(directory_content, i, 0, "%s", line);
|
mvwprintw(directory_content, i, 0, "%s", line);
|
||||||
|
|
||||||
|
if (marked) {
|
||||||
|
wattroff(directory_content, COLOR_PAIR(7));
|
||||||
|
} else {
|
||||||
|
wattroff(directory_content, COLOR_PAIR(color));
|
||||||
|
}
|
||||||
|
|
||||||
wattroff(directory_content, A_REVERSE);
|
wattroff(directory_content, A_REVERSE);
|
||||||
wattroff(directory_content, COLOR_PAIR(color));
|
|
||||||
free(line);
|
free(line);
|
||||||
line_count++;
|
line_count++;
|
||||||
}
|
}
|
||||||
|
@ -539,23 +580,36 @@ void show_file_content()
|
||||||
wclear(preview_content);
|
wclear(preview_content);
|
||||||
file *current_file = get_file((long) current_selection);
|
file *current_file = get_file((long) current_selection);
|
||||||
if (strncmp(current_file->type, "DIR", 3) == 0) return;
|
if (strncmp(current_file->type, "DIR", 3) == 0) return;
|
||||||
FILE *file = fopen(current_file->path, "rb");
|
FILE *file = fopen(current_file->path, "r");
|
||||||
if (file) {
|
if (file == NULL) {
|
||||||
draw_border_title(preview_border, true);
|
mvwprintw(preview_content, 0, 0, "Unable to read %s", current_file->path);
|
||||||
fseek(file, 0, SEEK_END);
|
return;
|
||||||
long length = ftell(file);
|
|
||||||
/* check if file isn't empty */
|
|
||||||
if (length != 0 && length < 4096) {
|
|
||||||
fseek(file, 0, SEEK_SET); /* set cursor back to start of file */
|
|
||||||
char *buffer = memalloc(length * sizeof(char));
|
|
||||||
fread(buffer, 1, length, file);
|
|
||||||
mvwprintw(preview_content, 0, 0, "%s", buffer);
|
|
||||||
free(buffer);
|
|
||||||
} else {
|
|
||||||
wclear(preview_content);
|
|
||||||
}
|
|
||||||
fclose(file);
|
|
||||||
}
|
}
|
||||||
|
draw_border_title(preview_border, true);
|
||||||
|
|
||||||
|
int c;
|
||||||
|
/* check binary */
|
||||||
|
while ((c=fgetc(file)) != EOF) {
|
||||||
|
if (c == '\0') {
|
||||||
|
mvwprintw(preview_content, 0, 0, "binary");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
long length = ftell(file);
|
||||||
|
/* check if file isn't empty */
|
||||||
|
if (length != 0) {
|
||||||
|
fseek(file, 0, SEEK_SET); /* set cursor back to start of file */
|
||||||
|
int max_length = (LINES - 3) * (COLS / 2 - 2);
|
||||||
|
char *buffer = memalloc(max_length * sizeof(char));
|
||||||
|
fread(buffer, 1, max_length, file);
|
||||||
|
mvwprintw(preview_content, 0, 0, "%s", buffer);
|
||||||
|
free(buffer);
|
||||||
|
} else {
|
||||||
|
wclear(preview_content);
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -611,7 +665,7 @@ void init_windows()
|
||||||
|
|
||||||
/* draw border around windows */
|
/* draw border around windows */
|
||||||
draw_border_title(directory_border, true);
|
draw_border_title(directory_border, true);
|
||||||
draw_border_title(preview_border, false);
|
draw_border_title(preview_border, true);
|
||||||
|
|
||||||
scrollok(directory_content, true);
|
scrollok(directory_content, true);
|
||||||
/* window location y, x */
|
/* window location y, x */
|
||||||
|
|
6
config.h
6
config.h
|
@ -1,7 +1,7 @@
|
||||||
#define CTRLD 0x04
|
#define CTRLD 0x04
|
||||||
#define ENTER 0xA
|
#define ENTER 0xA
|
||||||
#define CTRLU 0x15
|
#define CTRLU 0x15
|
||||||
#define ESC 0x1B /* \e or \033 */
|
#define ESC 0x1B
|
||||||
#define SPACE 0x20
|
#define SPACE 0x20
|
||||||
#define TILDE 0x7E
|
#define TILDE 0x7E
|
||||||
#define DOWN 0x102
|
#define DOWN 0x102
|
||||||
|
@ -11,3 +11,7 @@
|
||||||
#define BACKSPACE 0x107
|
#define BACKSPACE 0x107
|
||||||
#define PH 1 /* panel height */
|
#define PH 1 /* panel height */
|
||||||
#define JUMP_NUM 14 /* how long ctrl + u/d jump are */
|
#define JUMP_NUM 14 /* how long ctrl + u/d jump are */
|
||||||
|
#define BLOCK_SIZE true
|
||||||
|
#define DISK_USAGE false
|
||||||
|
|
||||||
|
static const char *editor = "nvim"; /* default text editor */
|
||||||
|
|
84
file.c
84
file.c
|
@ -1,5 +1,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
@ -45,13 +46,24 @@ long marked_len()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void free_file(file *toremove)
|
||||||
|
{
|
||||||
|
if (toremove->type != NULL)
|
||||||
|
free(toremove->type);
|
||||||
|
if (toremove->path != NULL)
|
||||||
|
free(toremove->path);
|
||||||
|
if (toremove->stats != NULL)
|
||||||
|
free(toremove->stats);
|
||||||
|
free(toremove);
|
||||||
|
}
|
||||||
|
|
||||||
void clear_files()
|
void clear_files()
|
||||||
{
|
{
|
||||||
file *tmp;
|
file *tmp;
|
||||||
while (files != NULL) {
|
while (files != NULL) {
|
||||||
tmp = files;
|
tmp = files;
|
||||||
files = files->next;
|
files = files->next;
|
||||||
free(tmp);
|
free_file(tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +73,7 @@ void clear_marked()
|
||||||
while (marked != NULL) {
|
while (marked != NULL) {
|
||||||
tmp = marked;
|
tmp = marked;
|
||||||
files = marked->next;
|
files = marked->next;
|
||||||
free(tmp);
|
free_file(tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,6 +108,29 @@ long add_file(char *filepath, char *stats, char *type, int color)
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void remove_marked(file *marked_file)
|
||||||
|
{
|
||||||
|
/* If the head node itself is marked for removal */
|
||||||
|
if (marked == marked_file) {
|
||||||
|
marked = marked->next;
|
||||||
|
free_file(marked_file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Search for the marked file node in the list */
|
||||||
|
file* temp = marked;
|
||||||
|
while (temp != NULL && temp->next != marked_file) {
|
||||||
|
temp = temp->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the marked file node is found, remove it from the list */
|
||||||
|
if (temp != NULL) {
|
||||||
|
temp->next = marked_file->next;
|
||||||
|
free_file(marked_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
long add_marked(char *filepath, char *type)
|
long add_marked(char *filepath, char *type)
|
||||||
{
|
{
|
||||||
file *current = marked;
|
file *current = marked;
|
||||||
|
@ -107,20 +142,63 @@ long add_marked(char *filepath, char *type)
|
||||||
}
|
}
|
||||||
new_file->path = buf;
|
new_file->path = buf;
|
||||||
new_file->type = buf2;
|
new_file->type = buf2;
|
||||||
|
new_file->stats = NULL;
|
||||||
|
new_file->color = 0;
|
||||||
new_file->next = NULL;
|
new_file->next = NULL;
|
||||||
if (current == NULL) {
|
if (current == NULL) {
|
||||||
marked = new_file;
|
marked = new_file;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
long index = 1;
|
long index = 1;
|
||||||
while (current->next != NULL) {
|
while (current->next != NULL) {
|
||||||
|
if (strcmp(current->path, new_file->path) == 0) {
|
||||||
|
remove_marked(current);
|
||||||
|
free_file(new_file);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
current = current->next;
|
current = current->next;
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
if (strcmp(current->path, new_file->path) == 0){
|
||||||
|
remove_marked(current);
|
||||||
|
free_file(new_file);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
current->next = new_file;
|
current->next = new_file;
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
file *get_marked(long index)
|
||||||
|
{
|
||||||
|
file *current = marked;
|
||||||
|
if (index == 0) {
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
if (index > files_len()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
for (long i = 0; i < index; i++) {
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool in_marked(char *path)
|
||||||
|
{
|
||||||
|
file *tmp = marked;
|
||||||
|
if (tmp == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
while (tmp != NULL) {
|
||||||
|
if (strcmp(path, tmp->path) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
file *get_file(long index)
|
file *get_file(long index)
|
||||||
{
|
{
|
||||||
file *current = files;
|
file *current = files;
|
||||||
|
@ -160,7 +238,7 @@ int get_color(long index)
|
||||||
}
|
}
|
||||||
return color;
|
return color;
|
||||||
} else {
|
} else {
|
||||||
return 8; /* white */
|
return 8; /* white */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
4
file.h
4
file.h
|
@ -11,10 +11,14 @@ typedef struct file {
|
||||||
|
|
||||||
long files_len();
|
long files_len();
|
||||||
long marked_len();
|
long marked_len();
|
||||||
|
void free_file(file *toremove);
|
||||||
void clear_files();
|
void clear_files();
|
||||||
void clear_marked();
|
void clear_marked();
|
||||||
long add_file(char *filepath, char *stats, char *type, int color);
|
long add_file(char *filepath, char *stats, char *type, int color);
|
||||||
|
void remove_marked(file *marked_file);
|
||||||
long add_marked(char *filepath, char *type);
|
long add_marked(char *filepath, char *type);
|
||||||
|
file *get_marked(long index);
|
||||||
|
bool in_marked(char *path);
|
||||||
file *get_file(long index);
|
file *get_file(long index);
|
||||||
char *get_filepath(long index);
|
char *get_filepath(long index);
|
||||||
int get_color(long index);
|
int get_color(long index);
|
||||||
|
|
Loading…
Reference in a new issue