home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.lang.c      Meh, in C you gotta define EVERYTHING      243,242 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 241,880 of 243,242   
   Michael Sanders to All   
   mini_repl.c   
   10 Nov 25 12:59:38   
   
   From: porkchop@invalid.foo   
      
   /*   
    * mini_repl.c – Mini REPL with persistent history   
    * Michael Sanders - 2025 use as you see fit   
    *   
    * repl commands:   
    *   .q   quit   
    *   .h   show short help   
    *   .c   clear the screen   
    *   
    * Full persistent history (~/.mini_repl_history)   
    * via up/down keys, no history duplicates.   
    *   
    * Build: cc mini_repl.c -o mini_repl   
    *   
    */   
      
   #include    
   #include    
   #include    
   #include    
   #include    
   #include    
   #include    
      
   #define MAXLINE 1024   
   #define HISTORY_MAX 128   
   #define HISTFILE ".mini_repl_history"   
      
   static char *history[HISTORY_MAX];   
   static int hist_count = 0;   
   static int hist_index = -1;   
   static char hist_path[PATH_MAX];   
      
   /* -------- Helpers -------- */   
   static void clear_screen(void) {   
       fputs("\033[2J\033[H", stdout);   
       fflush(stdout);   
   }   
      
   static void load_history(void) {   
       const char *home = getenv("HOME");   
       if (home) snprintf(hist_path, sizeof(hist_path), "%s/%s", home, HISTFILE);   
       else strncpy(hist_path, HISTFILE, sizeof(hist_path) - 1);   
      
       FILE *fp = fopen(hist_path, "r");   
       if (!fp) return;   
      
       char line[MAXLINE];   
       while (fgets(line, sizeof(line), fp) && hist_count < HISTORY_MAX) {   
           line[strcspn(line, "\r\n")] = '\0';   
           if (*line) history[hist_count++] = strdup(line);   
       }   
       fclose(fp);   
   }   
      
   static void save_history(void) {   
       FILE *fp = fopen(hist_path, "w");   
       if (!fp) return;   
       for (int i = 0; i < hist_count; i++) fprintf(fp, "%s\n", history[i]);   
       fclose(fp);   
   }   
      
   static void add_history(const char *line) {   
       if (!line || !*line) return;   
       for (int i = 0; i < hist_count; i++) {   
           if (strcmp(history[i], line) == 0) {   
               free(history[i]);   
               for (int j = i; j < hist_count - 1; j++) history[j] = history[j +   
   1];   
               hist_count--;   
               break;   
           }   
       }   
       if (hist_count == HISTORY_MAX) {   
           free(history[0]);   
           memmove(&history[0], &history[1], sizeof(char*) * (HISTORY_MAX - 1));   
           hist_count--;   
       }   
       history[hist_count++] = strdup(line);   
   }   
      
   /* -------- REPL -------- */   
   int main(void) {   
       load_history();   
      
       struct termios orig, raw;   
       tcgetattr(STDIN_FILENO, &orig);   
       raw = orig;   
       raw.c_lflag &= ~(ICANON | ECHO);   
       tcsetattr(STDIN_FILENO, TCSANOW, &raw);   
      
       printf("Mini REPL (.h help, .c clear, .q quit)\n> ");   
       fflush(stdout);   
      
       char line[MAXLINE];   
       int pos = 0;   
      
       for (;;) {   
           unsigned char c;   
           if (read(STDIN_FILENO, &c, 1) != 1) break;   
      
           if (c == '\n' || c == '\r') {   
               line[pos] = '\0';   
      
               /* BLANK: erase current line and re-prompt */   
               if (pos == 0) {   
                   printf("\033[2K\r> ");   
                   fflush(stdout);   
                   continue;   
               }   
      
               /* ERASE input line before any output */   
               printf("\033[2K\r");   
               fflush(stdout);   
      
               if (strcmp(line, ".q") == 0) {   
                   add_history(line);   
                   break;   
               } else if (strcmp(line, ".c") == 0) {   
                   add_history(line);   
                   clear_screen();   
                   printf("> ");   
               } else if (strcmp(line, ".h") == 0) {   
                   add_history(line);   
                   printf("Commands:\n  .q   Quit\n  .c   Clear screen\n  .h     
   Show help\n\n> ");   
               } else {   
                   add_history(line);   
                   printf("You typed: %s\n> ", line);   
               }   
      
               fflush(stdout);   
               pos = 0;   
               hist_index = hist_count;   
               continue;   
           }   
      
           if (c == 4) break; /* Ctrl+D */   
      
           if (c == 127 || c == '\b') { /* backspace */   
               if (pos > 0) {   
                   pos--;   
                   printf("\b \b");   
                   fflush(stdout);   
               }   
               continue;   
           }   
      
           if (c == 27) { /* arrows */   
               unsigned char seq[2];   
               if (read(STDIN_FILENO, seq, 2) == 2 && seq[0] == '[') {   
                   if (seq[1] == 'A') { /* up */   
                       if (hist_index > 0) hist_index--;   
                       if (hist_index >= 0 && hist_index < hist_count) {   
                           printf("\033[2K\r> %s", history[hist_index]);   
                           fflush(stdout);   
                           strcpy(line, history[hist_index]);   
                           pos = (int)strlen(line);   
                       }   
                   } else if (seq[1] == 'B') { /* down */   
                       if (hist_index < hist_count - 1) hist_index++;   
                       else hist_index = hist_count;   
                       if (hist_index < hist_count) {   
                           printf("\033[2K\r> %s", history[hist_index]);   
                           strcpy(line, history[hist_index]);   
                           pos = (int)strlen(line);   
                       } else {   
                           printf("\033[2K\r> ");   
                           pos = 0;   
                           line[0] = '\0';   
                       }   
                       fflush(stdout);   
                   }   
               }   
               continue;   
           }   
      
           if (isprint(c) && pos < MAXLINE - 1) {   
               line[pos++] = c;   
               putchar(c);   
               fflush(stdout);   
           }   
       }   
      
       tcsetattr(STDIN_FILENO, TCSANOW, &orig);   
       save_history();   
       for (int i = 0; i < hist_count; i++) free(history[i]);   
       return 0;   
   }   
      
   --   
   :wq   
   Mike Sanders   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca