(2013-12-10) Cede A C Line Based Text Editor

Okay, so this is a really long overdue update -- I've been getting worse at doing them. I've just been really busy over the last few months.

If you've checked my Github page at any point in the last 2 months, you may have noticed a few extra projects built in C (you may also have noticed my tny.li updates as well, but more on that later).

While most of the stuff I've done has been trival at best (a very basic calculator and a basic temperature converter [that does Kelvin, Rankine, Delisle and Newton]), I had also worked a fair amount on a line based text editor.

Because I am still very new to C, doing a full, visual, character by character editor would have probably been a bit much. So I opted for an "ed" inspired editor which, while vastly less powerful than ed, seems to work pretty well.

I came up with some really random internal shortcuts for it, but the general usage is fairly simple. I managed to total around 750-1000 lines of code for it and I'm sure there are ways of improving, but still... I like it!

So, because pasting all the code here is a little ridiculous, I'll just list the highlights.

Firstly, the prototype functions:

~~~~
void clear_string ( char s[BUFSIZ] );
void error ( int i );
void check_return ( int i );
int show_help ( void );
int command_file_temp_create ( char f[BUFSIZ] );
int command_file_temp_remove ( char f[BUFSIZ] );
int command_file_temp_save ( char f[BUFSIZ] );
int command_internal_line_count ( char f[BUFSIZ] );
int command_internal_list_all ( char f[BUFSIZ] );
int command_internal_list_all_silent ( char f[BUFSIZ] );
int command_internal_list_single ( char u[BUFSIZ], char f[BUFSIZ] );
int command_internal_write_all ( char u[BUFSIZ], char f[BUFSIZ] );
int command_internal_write_single ( char u[BUFSIZ], char f[BUFSIZ] );
int command_internal_purge_all ( char f[BUFSIZ] );
int command_internal_purge_single ( char u[BUFSIZ], char f[BUFSIZ] );
int command_internal_shell_passthru ( char u[BUFSIZ] );
int command_internal_discard ( char f[BUFSIZ] );
int command_internal_save ( char f[BUFSIZ] );
int command_internal_delete ( char f[BUFSIZ] );
int command_internal_append_single ( char u[BUFSIZ], char f[BUFSIZ] );
int command_internal_search_keyword ( char u[BUFSIZ], char f[BUFSIZ] );
int command_internal_search_keyword_count ( char u[BUFSIZ], char f[BUFSIZ] );
~~~~

That should give you an idea of the posibilities avaliable within the tool itself (the help screen is obviously more effective).

One of the functions I really like is the internal_search_keyword function. You specify a word and the function lists all the lines that the word appear on (colours / styles are not yet included, so there's no way of "bolding" the keyword).

~~~~
int command_internal_search_keyword ( char u[BUFSIZ], char f[BUFSIZ] ) {
        FILE *temp;
        char file_temp[BUFSIZ];
        char line[BUFSIZ];
        char word[BUFSIZ];
        char d[BUFSIZ], e[BUFSIZ];
        int i = 1, j = 0, c = 0, x = 0, l, k, m, n;
        char *ptr;
        clear_string ( file_temp );
        clear_string ( line );
        clear_string ( u );
        clear_string ( word );
        strcat ( file_temp, f );
        strcat ( file_temp, ".tmp" );
        l = command_internal_line_count ( f );
        clear_string ( d );
        sprintf ( d, "%d", l );
        k = strlen ( d );
        scanf ( "%[^\t\n]", u );
        while ( getchar () != ( int ) '\n' );
        if ( u[0] == '\0' ) {
                x = 2;
        } else {
                while ( u[c] != '\0' ) {
                        u[c] = u[c+1];
                        c++;
                }
                temp = fopen ( file_temp, "r" );
                if ( temp == NULL ) {
                        x = 1;
                } else {
                        while ( fgets ( line, BUFSIZ, temp ) ) {
                                if ( ( ptr = strstr ( line, u ) ) != NULL ) {
                                        clear_string ( e );
                                        sprintf ( e, "%d", i );
                                        n = strlen ( e );
                                        m = k - n;
                                        switch ( m ) {
                                                case 1:
                                                        printf ( "0" );
                                                        break;
                                                case 2:
                                                        printf ( "00" );
                                                        break;
                                                case 3:
                                                        printf ( "000" );
                                                        break;
                                                case 4:
                                                        printf ( "0000" );
                                                        break;
                                                case 5:
                                                        printf ( "00000" );
                                                        break;
                                                case 6:
                                                        printf ( "000000" );
                                                        break;
                                                default:
                                                        break;
                                        }
                                        j++;
                                        printf ( "%i|%s", i, line );
                                }
                                i++;
                        }
                        if ( fclose ( temp ) != 0 ) {
                                x = 1;
                        }
                }
        }
        return ( x );
}
~~~~

The thing I really like about this function is the line numbering aligning itself to the total line count of the file. It's not elegant, but it feels much nicer when working with large files.

I've also included that simple switch on printing the full file as well, so you get a better feel for where things are.

You can check out the full source code on Github: here

Here's the help screen as well, which shows you the possiblities:

~~~~
 %\% Print total lines
 &\& Print all line content
 & [LN] Print [LN] line content
 &\&\&    Print all line content with line numbers
 ^^ Write new lines from start of file
 ^ [LN] Write new lines from [LN]
 $\$ Finish writing new lines
 -- Remove all lines from file
 - [LN] Remove single line from file
 + [LN] Add a single new line after [LN]
 // [K] Search for [K] in file and return lines
 / [K]  Search for [K] in file and return count
 .. Save changes to file and quit
 .  Save changes to file
 ,, Discard unsaved changes and quit
 ,  Discard unsaved changes and reload last save
 << Discard changes, delete file and exit
 !! Command line passthrough
 ## Print version number
 ?? Show this help screen
~~~~