X-Git-Url: https://pd.if.org/git/?p=pd_readline;a=blobdiff_plain;f=pdrl.c;fp=pdrl.c;h=cdceba10a0f8e5834cf626ec3f4a2a94a27e4f17;hp=0000000000000000000000000000000000000000;hb=050f646dd55e7fef8b2d0dcf5d1740ea8484f9c1;hpb=d56fdb0ce92c92e27ef45a8315ff26c272a1f23d diff --git a/pdrl.c b/pdrl.c new file mode 100644 index 0000000..cdceba1 --- /dev/null +++ b/pdrl.c @@ -0,0 +1,255 @@ + + +/* pdrl.c */ + +/* Some code to allow the editing of a command-line. */ +/* You can also move around with the left and right */ +/* arrow keys, and recall previous commands with the */ +/* up-arrow key. */ +/* This code is released to the public domain. */ +/* "Share and enjoy...." ;) */ +/* See the UNLICENSE file for details. */ + +/* TO DO - */ +/* a) Add support for Home and End (of line) keys. */ +/* b) Add support for function keys. */ +/* c) Add support for Insert key so that text can be */ +/* inserted. */ +/* d) Put much of the code into a header file. */ +/* e) Change so that pressing Enter adds the current */ +/* line of commands to the command-history. */ +/* ( May look at using Ctrl-D to exit, as Python */ +/* does with its command-line. ) */ +/* f) Add support for copying and pasting text via */ +/* Ctrl-C and Ctrl-V. */ + + +#include +#include +#include + +/* This implementation of getch() is from here - */ +/* http://wesley.vidiqatch.org/ */ +/* Thanks, Wesley! */ +static struct termios old, new; + +/* Initialize new terminal i/o settings */ +void initTermios(int echo) { + tcgetattr(0, &old); /* grab old terminal i/o settings */ + new = old; /* make new settings same as old settings */ + new.c_lflag &= ~ICANON; /* disable buffered i/o */ + new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */ + tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */ +} + + +/* Restore old terminal i/o settings */ +void resetTermios(void) { + tcsetattr(0, TCSANOW, &old); +} + + +/* Read 1 character - echo defines echo mode */ +char getch_(int echo) { + char ch; + initTermios(echo); + ch = getchar(); + resetTermios(); + return ch; +} + + +/* Read 1 character without echo */ +char getch(void) { + return getch_(0); +} + + +/* Read 1 character with echo */ +char getche(void) { + return getch_(1); +} + + + +/* Helper function, to let us see if a file */ +/* exists in the current directory. */ +int fexists(char *fname) +{ + FILE *fptr; + fptr = fopen(fname, "r") ; + if ( !fptr ) return -1 ; /* File does not exist in dir. */ + fclose(fptr); + return 0; /* File DOES exist in dir. */ +} + + +/* Helper function to chop newlines off the lines read in. */ +/* Without this being done, an extra newline is inserted */ +/* (which is usually not what is wanted). */ +char *chop(char *s) +{ + s[strcspn(s,"\n")] = '\0'; + return s; +} + + +/* An array to store the command-history file in. */ +/* Only 20 lines are read. */ +char hist[20][80]; + + + +/* Read the file into the array of strings. */ +void readfile(char *fname) +{ + int retval = fexists(fname); + + int i; + if (retval == 0) { + /* File exists, so open it. */ + /* We open it in read-write mode so we can */ + /* append new commands to it. */ + FILE *fptr; + fptr = fopen(fname, "rw"); + + for(i=0; i<20; i++) + { + chop(fgets(hist[i], 80, fptr) ); + } + + } /* retval == 0 */ + + else puts("Error! File does not exist. \n"); + +} + + +/* Helper function to print the command-history file. */ +void printfile(void) +{ + int j; + + for(j=0; j<20; j++) + { + puts(hist[j]); + } +} + + + + +/* Helper function. Print a previous command-line WITHOUT */ +/* a newline. */ +void putline(char *str) +{ + char *line = chop(str); + printf("%s", line); +} + + + + +int main(void) +{ + +/* Our "command-history" file. */ +readfile("test.txt"); + + +/* "Pointer" for the history file. */ +int histpnt = 20; + + + while(1) + { + + int key = getch(); + + /* Printable chars. */ + if ( (key >= 32) && (key <= 126) ) + { + /* We have a printable key so print it. */ + putchar(key); + } + + /* Up arrow is 27, 91, 65. ( ESC [ A ) */ + /* Down arrow is 27, 91, 66. ( ESC [ B ) */ + /* Right arrow is 27, 91, 67. ( ESC [ C ) */ + /* Left arrow is 27, 91, 68. ( ESC [ D ) */ + /* Function keys. */ + /* F2 is 27, 79, 81. */ + /* F3 is 27, 79, 82. */ + /* F4 is 27, 79, 83. */ + + /* Backspace */ + else if(key == 127) + { + /* Move left 1 char and delete that char */ + printf("\033[1D"); + printf("\040"); + printf("\033[1D"); + } + + /* We have an escape key-sequence */ + else if(key == 27) + { + key = getch(); + if(key == 91) + key = getch(); + + if (key == 65) /* Up Arrow */ + { + /* Move one command "back" in history. */ + histpnt -= 1; + /* Clear to end of line. */ + printf("\033[80D"); + printf("\033[K"); + /* Print the pointed-at command-sequence. */ + putline(hist[histpnt]); + } + + if(key == 66) /* Down Arrow */ + { + /* Move one command "forward" in history. */ + histpnt += 1; + /* Clear to end of line. */ + printf("\033[80D"); + printf("\033[K"); + /* Print the pointed-at command-sequence. */ + putline(hist[histpnt]); + } + + if(key == 67) /* Left arrow */ + { + /* Move one character to the left. */ + printf("\033[1C"); + } + + if(key == 68) /* Right arrow */ + { + /* Move one character to the right. */ + printf("\033[1D"); + } + + } /* End of key=27 key sequence. */ + + + /* The Enter key exits. Enter is 10 decimal */ + else if(key == 10) + { + puts("\n"); + puts("Exiting... \n"); + break; + } /* Key = Enter */ + } + + return 0; + +} + + + + + +