From 93a4b7b9e444c0661dd03428e850ff1b356d5ccb Mon Sep 17 00:00:00 2001 From: mananapr Date: Mon, 31 Dec 2018 22:43:26 +0530 Subject: [PATCH] Added first release and README --- README.md | 25 ++++- cf.c | 313 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 337 insertions(+), 1 deletion(-) create mode 100644 cf.c diff --git a/README.md b/README.md index 74fdcd8..c2a0cea 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,25 @@ # cfiles -A ncurses file manager written in C +`cfiles` is a work in progress terminal file manager written in C using the ncurses +library. It aims to provide an interface like [ranger](https://github.com/ranger/ranger) while being lightweight, fast and +minimal. + +## Compiling and Installation +To compile, run + + `gcc cf.c -lncurses -o cf` + +To install, simply move the generated executable to a directory that is in your `$PATH` + +## Why C? +I wanted to improve my C and learn ncurses so I decided this would be an ideal project. + +Apart from this, I have always wanted an alternative to ranger that is faster while still having +a similar UI. + +## Todo +- [ ] Improve Upwards Scrolling +- [ ] Show sorted directories before files +- [ ] Fix the `G` keybinding +- [ ] Add basic operations like renaming, copying etc. +- [ ] Show more info in the statusbar +- [ ] Add file previews diff --git a/cf.c b/cf.c new file mode 100644 index 0000000..c492146 --- /dev/null +++ b/cf.c @@ -0,0 +1,313 @@ +// HEADERS +#include +#include +#include +#include +#include +#include +#include + + +/* + For qsort +*/ +int compare (const void * a, const void * b ) { + return strcmp(*(char **)a, *(char **)b); +} + + +/* + Creates a new window with dimensions `height` and `width` starting at `starty` and `startx` +*/ +WINDOW *create_newwin(int height, int width, int starty, int startx) +{ + WINDOW *local_win; + local_win = newwin(height, width, starty, startx); + return local_win; +} + + +/* + Returns number of files in `char* directory` +*/ +int getNumberofFiles(char* directory) +{ + int len=0; + DIR *pDir; + struct dirent *pDirent; + + pDir = opendir (directory); + if (pDir == NULL) { + return -1; + } + + while ((pDirent = readdir(pDir)) != NULL) { + // Skip hidden files + if(pDirent->d_name[0] != '.' ) + len++; + } + return len; +} + + +/* + Stores all the file names in `char* directory` to `char *target[]` +*/ +void getFiles(char* directory, char* target[]) +{ + int i = 0; + DIR *pDir; + struct dirent *pDirent; + + pDir = opendir (directory); + if (pDir == NULL) { + return; + } + + while ((pDirent = readdir(pDir)) != NULL) { + // Skip hidden files + if(pDirent->d_name[0] != '.') + target[i++] = strdup(pDirent->d_name); + } + + closedir (pDir); +} + + +int main(int argc, char* argv[]) +{ + // To store number of files in directory + int len=0; + // Counter variable + int i = 0; + // Direcotry to be opened + char* dir; + + // Get UID of user + uid_t uid = getuid(); + // Get home directory of user from UID + struct passwd *info = getpwuid(uid); + + // No Path is given in arguments + // Set Path as $HOME + if(argc == 1) + { + dir = info->pw_dir; + } + + // Path is given in arguments + // Set Path as the argument + else if(argc == 2) + { + dir = argv[1]; + + // Relative Path Given + if(dir[0] != '/') + { + // Add path of $HOME before the Relative Path + char temp[250] = ""; + strcat(temp,info->pw_dir); + strcat(temp,"/"); + strcat(temp,dir); + dir = temp; + } + } + + // Incorrect Useage + else + { + printf("Incorrect Useage\n"); + exit(0); + } + + // Stores number of files in the present directory + len = 0; + + // ncurses initialization + initscr(); + noecho(); + curs_set(0); + + + // Shows current directory + WINDOW *current_win; + // Shows child directory preview + WINDOW *preview_win; + // Shows status bar + WINDOW *status_win; + + int startx, starty, midx, midy, maxx, maxy; + + // Index of currently selected item in `char* directories` + int selection = 0; + char ch; + int start = 0; + + // Main Loop + do + { + // Get number of files in the home directory + len = getNumberofFiles(dir); + + // Array of all the files in the current directory + char* directories[len]; + getFiles(dir, directories); + // Sort files by name + qsort (directories, len, sizeof (char*), compare); + + // Get Size of terminal + getmaxyx(stdscr, maxy, maxx); + // Save last two rows for status_win + maxy = maxy - 2; + + // Make the two windows side-by-side + current_win = create_newwin(maxy, maxx/2+3, 0, 0); + preview_win = create_newwin(maxy, maxx/2 -1, 0, maxx/2 + 1); + status_win = create_newwin(2, maxx, maxy, 0); + + // Display Status + wmove(status_win,1,1); + wprintw(status_win, "%s@%s\t%s", getenv("USER"), getenv("HOSTNAME"), dir); + wrefresh(status_win); + + + // Print all the elements and highlight the selection + int t = 0; + for( i=start; i 0) + qsort(next_directories, len_preview, sizeof (char*), compare); + + // Selection is not a directory + if(len_preview != -1) + for( i=0; i maxy) + if(selection > maxy/2) + { + if(start == 0) + wclear(current_win); + else + { + start--; + wclear(current_win); + } + } + break; + case 'j': + selection++; + selection = ( selection > len-1 ) ? len-1 : selection; + // Scrolling + if(len > maxy) + if(selection - 1 > maxy/2) + { + if(start + maxy -2 != len) + { + start++; + wclear(current_win); + } + } + + break; + case 'l': + strcpy(dir, next_dir); + selection = 0; + start = 0; + break; + case 'h': + strcpy(dir, prev_dir); + selection = 0; + start = 0; + break; + case 'g': + selection = 0; + start = 0; + break; + case 'G': + selection = len - 1; + if(len > maxy - 2) + start = len - maxy - 1; + // Needs to be fixed + else + start = len - 1 - maxy - 4 + 3; + break; + } + + + // Free Memory + for( i=0; i