Realized that recent changes deserve a new version number.
[selector.git] / selector.c
index 94cd99e..945844f 100644 (file)
@@ -3,7 +3,7 @@
  *  selector is a simple command line utility for selection of strings
  *  with a dynamic pattern-matching.
  *
- *  Copyright (c) 2009-2013 Francois Fleuret
+ *  Copyright (c) 2009-2015 Francois Fleuret
  *  Written by Francois Fleuret <francois@fleuret.org>
  *
  *  This file is part of selector.
@@ -46,7 +46,7 @@
 #include <getopt.h>
 #include <limits.h>
 
-#define VERSION "1.1.7"
+#define VERSION "1.1.8"
 
 #define BUFFER_SIZE 16384
 
@@ -65,6 +65,7 @@ int global_remove_duplicates = 0;
 int global_use_regexp = 0;
 int global_case_sensitive = 0;
 char *global_title = 0;
+regex_t *global_prefix_regexp = 0;
 int global_error_flash = 0;
 int global_upper_caps_makes_case_sensitive = 0;
 int global_show_long_lines = 0;
@@ -111,21 +112,21 @@ void inject_into_tty_buffer(char *string, int add_control_qs) {
 /*********************************************************************/
 
 void str_to_positive_integers(char *string, int *values, int nb) {
-  int current_value, gotone;
+  int current_value, got_one;
   char *s;
   int n;
 
   n = 0;
   current_value = 0;
-  gotone = 0;
+  got_one = 0;
   s = string;
 
   while(1) {
     if(*s >= '0' && *s <= '9') {
       current_value = current_value * 10 + (int) (*s - '0');
-      gotone = 1;
+      got_one = 1;
     } else if(*s == ',' || *s == '\0') {
-      if(gotone) {
+      if(got_one) {
         if(n < nb) {
           values[n++] = current_value;
           if(*s == '\0') {
@@ -138,7 +139,7 @@ void str_to_positive_integers(char *string, int *values, int nb) {
             }
           }
           current_value = 0;
-          gotone = 0;
+          got_one = 0;
         } else {
           fprintf(stderr,
                   "selector: Too many values in `%s'.\n", string);
@@ -204,6 +205,8 @@ void usage(FILE *out) {
   fprintf(out, "         make a flash instead of a beep on an edition error\n");
   fprintf(out, " --bash\n");
   fprintf(out, "         setting for bash history search, same as -b -i -d -v -w -l ${HISTSIZE}\n");
+  fprintf(out, " --delete-regexp <regexp>\n");
+  fprintf(out, "         deletes in every line the portion matching the regexp\n");
   fprintf(out, " --\n");
   fprintf(out, "         all following arguments are filenames\n");
   fprintf(out, " -t <title>, --title <title>\n");
@@ -877,9 +880,20 @@ void update_screen(int *current_focus_line, int *displayed_focus_line,
 /*********************************************************************/
 
 void store_line(struct hash_table_t *hash_table,
-                const char *new_line,
+                char *new_line,
                 int *nb_lines, char **lines) {
   int dup;
+  char *c, *d;
+  regmatch_t matches;
+
+  /* Remove some parts matching a regexp */
+
+  if(global_prefix_regexp && regexec(global_prefix_regexp, new_line, 1, &matches, 0) == 0) {
+    c = new_line + matches.rm_so;
+    d = new_line + matches.rm_eo;
+    while(*d) { *c++ = *d++; }
+    *c = 0;
+  }
 
   /* Remove the zsh history prefix */
 
@@ -960,9 +974,9 @@ void read_file(struct hash_table_t *hash_table,
 
 /* For long options that have no equivalent short option, use a
    non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
-enum
-{
-  OPT_BASH_MODE = CHAR_MAX + 1
+enum {
+  OPT_BASH_MODE = CHAR_MAX + 1,
+  OPT_DELETE_REGEXP = CHAR_MAX + 2
 };
 
 static struct option long_options[] = {
@@ -980,13 +994,14 @@ static struct option long_options[] = {
   { "regexp", no_argument, 0, 'e' },
   { "case-sensitive", no_argument, 0, 'a' },
   { "show-long-lines", no_argument, 0, 'j'},
-  { "show-hits", no_argument, 0, 'j'},
+  { "show-hits", no_argument, 0, 'y'},
   { "upper-case-makes-case-sensitive", no_argument, 0, 'u' },
   { "title", 1, 0, 't' },
   { "pattern", 1, 0, 'r' },
   { "number-of-lines", 1, 0, 'l' },
   { "colors", 1, 0, 'c' },
   { "bash", no_argument, 0, OPT_BASH_MODE },
+  { "delete-regexp", 1, 0, OPT_DELETE_REGEXP },
   { "help", no_argument, 0, 'h' },
   { 0, 0, 0, 0 }
 };
@@ -1010,14 +1025,14 @@ int main(int argc, char **argv) {
   struct hash_table_t *hash_table;
   char *bash_histsize;
 
-  /* Group and others have no access to created files */
-  umask(S_IRWXG | S_IRWXO);
-
   if(!isatty(STDIN_FILENO)) {
     fprintf(stderr, "selector: The standard input is not a tty.\n");
     exit(EXIT_FAILURE);
   }
 
+  /* Group and others have no access to created files */
+  umask(S_IRWXG | S_IRWXO);
+
   pattern[0] = '\0';
 
   color_fg_modeline  = COLOR_WHITE;
@@ -1108,6 +1123,16 @@ int main(int argc, char **argv) {
       strcpy(global_title, optarg);
       break;
 
+    case OPT_DELETE_REGEXP:
+      free(global_prefix_regexp);
+      global_prefix_regexp = safe_malloc(sizeof(*global_prefix_regexp));
+
+      if(regcomp(global_prefix_regexp, optarg, 0)) {
+        fprintf(stderr, "selector: Regexp syntax error `%s'.\n", optarg);
+        exit(EXIT_FAILURE);
+      }
+      break;
+
     case 'r':
       strcpy(pattern, optarg);
       break;
@@ -1443,5 +1468,10 @@ int main(int argc, char **argv) {
   free(lines);
   free(global_title);
 
+  if(global_prefix_regexp) {
+    regfree(global_prefix_regexp);
+    free(global_prefix_regexp);
+  }
+
   exit(EXIT_SUCCESS);
 }