commit
5f6c4ee903
5 changed files with 193 additions and 45 deletions
26
Makefile
26
Makefile
|
@ -1,26 +1,30 @@
|
|||
.POSIX:
|
||||
.SUFFIXES:
|
||||
|
||||
CC = cc
|
||||
VERSION = 1.0
|
||||
TARGET = ccc
|
||||
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
|
||||
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
|
||||
CC=cc
|
||||
PREFIX ?= /usr/local
|
||||
CONF = config.h
|
||||
|
||||
BINDIR = $(PREFIX)/bin
|
||||
MANDIR = $(PREFIX)/share/man/man1
|
||||
|
||||
.PHONY: all install uninstall clean
|
||||
SRC = ccc.c util.c file.c $(CONF)
|
||||
|
||||
$(TARGET): $(SRC)
|
||||
$(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)
|
||||
mkdir -p $(DESTDIR)$(BINDIR)
|
||||
|
@ -36,3 +40,7 @@ uninstall:
|
|||
|
||||
clean:
|
||||
$(RM) $(TARGET)
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
.PHONY: all dist install uninstall clean
|
||||
|
|
82
ccc.c
82
ccc.c
|
@ -39,6 +39,7 @@ void draw_border_title(WINDOW *window, bool active);
|
|||
/* global variables */
|
||||
unsigned int focus = 0;
|
||||
long current_selection = 0;
|
||||
bool dir_mode = BLOCK_SIZE;
|
||||
char *cwd;
|
||||
int half_width;
|
||||
WIN_STRUCT windows[5];
|
||||
|
@ -84,7 +85,7 @@ int main(int argc, char** argv)
|
|||
init_pair(4, COLOR_YELLOW, -1); /* BLK */
|
||||
init_pair(5, COLOR_BLUE, -1); /* DIR */
|
||||
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 */
|
||||
|
||||
half_width = COLS / 2;
|
||||
|
@ -238,8 +239,16 @@ int main(int argc, char** argv)
|
|||
}
|
||||
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 */
|
||||
case SPACE:
|
||||
case SPACE:;
|
||||
add_file_stat(get_filepath(current_selection), 1);
|
||||
highlight_current_line();
|
||||
break;
|
||||
|
@ -392,12 +401,16 @@ long add_file_stat(char *filepath, int ftype)
|
|||
|
||||
/* get file size */
|
||||
double bytes = file_stat.st_size;
|
||||
|
||||
if (!dir_mode) {
|
||||
/* dir_mode is 0, so disk usage mode, calculate disk usage */
|
||||
if (S_ISDIR(file_stat.st_mode)) {
|
||||
/* 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 */
|
||||
char *size = memalloc(25 * sizeof(char));
|
||||
int unit = 0;
|
||||
|
@ -443,8 +456,15 @@ long add_file_stat(char *filepath, int ftype)
|
|||
free(type);
|
||||
free(size);
|
||||
free(time);
|
||||
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));
|
||||
snprintf(total_stat, 45, "%-18s %-10s", time, size);
|
||||
total_stat[strlen(total_stat)] = '\0';
|
||||
|
@ -495,6 +515,15 @@ void highlight_current_line()
|
|||
|
||||
/* update the 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();
|
||||
if (num_marked > 0) {
|
||||
/* Determine length of formatted string */
|
||||
|
@ -502,24 +531,36 @@ void highlight_current_line()
|
|||
char *selected = memalloc((m_len + 1) * sizeof(char));
|
||||
|
||||
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 {
|
||||
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 */
|
||||
char *line = get_line(i);
|
||||
int color = get_color(i);
|
||||
|
||||
/* print the whole directory with colors */
|
||||
/* 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));
|
||||
}
|
||||
|
||||
if (overflow > 0)
|
||||
mvwprintw(directory_content, line_count, 0, "%s", line);
|
||||
else
|
||||
mvwprintw(directory_content, i, 0, "%s", line);
|
||||
|
||||
wattroff(directory_content, A_REVERSE);
|
||||
if (marked) {
|
||||
wattroff(directory_content, COLOR_PAIR(7));
|
||||
} else {
|
||||
wattroff(directory_content, COLOR_PAIR(color));
|
||||
}
|
||||
|
||||
wattroff(directory_content, A_REVERSE);
|
||||
free(line);
|
||||
line_count++;
|
||||
}
|
||||
|
@ -539,16 +580,30 @@ void show_file_content()
|
|||
wclear(preview_content);
|
||||
file *current_file = get_file((long) current_selection);
|
||||
if (strncmp(current_file->type, "DIR", 3) == 0) return;
|
||||
FILE *file = fopen(current_file->path, "rb");
|
||||
if (file) {
|
||||
FILE *file = fopen(current_file->path, "r");
|
||||
if (file == NULL) {
|
||||
mvwprintw(preview_content, 0, 0, "Unable to read %s", current_file->path);
|
||||
return;
|
||||
}
|
||||
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 && length < 4096) {
|
||||
if (length != 0) {
|
||||
fseek(file, 0, SEEK_SET); /* set cursor back to start of file */
|
||||
char *buffer = memalloc(length * sizeof(char));
|
||||
fread(buffer, 1, length, 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 {
|
||||
|
@ -556,7 +611,6 @@ void show_file_content()
|
|||
}
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Opens $EDITOR to edit the file
|
||||
|
@ -611,7 +665,7 @@ void init_windows()
|
|||
|
||||
/* draw border around windows */
|
||||
draw_border_title(directory_border, true);
|
||||
draw_border_title(preview_border, false);
|
||||
draw_border_title(preview_border, true);
|
||||
|
||||
scrollok(directory_content, true);
|
||||
/* window location y, x */
|
||||
|
|
6
config.h
6
config.h
|
@ -1,7 +1,7 @@
|
|||
#define CTRLD 0x04
|
||||
#define ENTER 0xA
|
||||
#define CTRLU 0x15
|
||||
#define ESC 0x1B /* \e or \033 */
|
||||
#define ESC 0x1B
|
||||
#define SPACE 0x20
|
||||
#define TILDE 0x7E
|
||||
#define DOWN 0x102
|
||||
|
@ -11,3 +11,7 @@
|
|||
#define BACKSPACE 0x107
|
||||
#define PH 1 /* panel height */
|
||||
#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 */
|
||||
|
|
82
file.c
82
file.c
|
@ -1,5 +1,6 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <libgen.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()
|
||||
{
|
||||
file *tmp;
|
||||
while (files != NULL) {
|
||||
tmp = files;
|
||||
files = files->next;
|
||||
free(tmp);
|
||||
free_file(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,7 +73,7 @@ void clear_marked()
|
|||
while (marked != NULL) {
|
||||
tmp = marked;
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
file *current = marked;
|
||||
|
@ -107,20 +142,63 @@ long add_marked(char *filepath, char *type)
|
|||
}
|
||||
new_file->path = buf;
|
||||
new_file->type = buf2;
|
||||
new_file->stats = NULL;
|
||||
new_file->color = 0;
|
||||
new_file->next = NULL;
|
||||
if (current == NULL) {
|
||||
marked = new_file;
|
||||
return 0;
|
||||
}
|
||||
|
||||
long index = 1;
|
||||
while (current->next != NULL) {
|
||||
if (strcmp(current->path, new_file->path) == 0) {
|
||||
remove_marked(current);
|
||||
free_file(new_file);
|
||||
return -1;
|
||||
}
|
||||
current = current->next;
|
||||
index++;
|
||||
}
|
||||
if (strcmp(current->path, new_file->path) == 0){
|
||||
remove_marked(current);
|
||||
free_file(new_file);
|
||||
return -1;
|
||||
}
|
||||
current->next = new_file;
|
||||
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 *current = files;
|
||||
|
|
4
file.h
4
file.h
|
@ -11,10 +11,14 @@ typedef struct file {
|
|||
|
||||
long files_len();
|
||||
long marked_len();
|
||||
void free_file(file *toremove);
|
||||
void clear_files();
|
||||
void clear_marked();
|
||||
long add_file(char *filepath, char *stats, char *type, int color);
|
||||
void remove_marked(file *marked_file);
|
||||
long add_marked(char *filepath, char *type);
|
||||
file *get_marked(long index);
|
||||
bool in_marked(char *path);
|
||||
file *get_file(long index);
|
||||
char *get_filepath(long index);
|
||||
int get_color(long index);
|
||||
|
|
Loading…
Reference in a new issue