コード例 #1
0
ファイル: readline.c プロジェクト: andreyvit/rlwrap
int cook_prompt_if_necessary () {
  char *pre_cooked, *filtered, *uncoloured;
  
  filtered = NULL;
  if (saved_rl_state.cooked_prompt)
    return FALSE;  /* cooked already */
  pre_cooked = mysavestring(saved_rl_state.raw_prompt);
  unbackspace(pre_cooked);
  if ( (prompt_regexp && ! match_regexp(pre_cooked, prompt_regexp, FALSE)) ||  /* raw prompt doesn't match '--only-cook' regexp */
       (strcmp((filtered =  pass_through_filter(TAG_PROMPT, pre_cooked)), "_THIS_CANNOT_BE_A_PROMPT_")== 0)) { /* filter has "refused" the prompt */
    saved_rl_state.cooked_prompt =  (impatient_prompt ? mysavestring(pre_cooked) : mysavestring("")); /* don't cook, eat raw (and eat nothing if patient) */
    free(pre_cooked);
    free(filtered); /* free(NULL) is not an error */
    return FALSE;
  }     
  free(pre_cooked);
  if(substitute_prompt) {
    uncoloured = mysavestring(substitute_prompt); 
    free(filtered);
  } else {
    uncoloured = filtered;
  }     
  if (colour_the_prompt) { 
    saved_rl_state.cooked_prompt =  colourise(uncoloured);
    free(uncoloured);
  } else {
    saved_rl_state.cooked_prompt = uncoloured;
  }
  return TRUE;
}       
コード例 #2
0
int cook_prompt_if_necessary () {
  char *pre_cooked, *rubbish_from_alternate_screen,  *filtered, *uncoloured, *cooked, *p, *non_rubbish = NULL;
  static char **term_ctrl_seqs[] 
    = {&term_rmcup, &term_rmkx, NULL}; /* (NULL-terminated) list of (pointers to) term control sequences that may be
                                       used by clients to return from an 'alternate screen'. If we spot one of those,
                                       assume that it, and anything before it, is rubbish and better left untouched */

  char ***tcptr;
  filtered = NULL;

  DPRINTF2(DEBUG_READLINE, "Prompt <%s>: %s", saved_rl_state.raw_prompt, prompt_is_still_uncooked ? "still raw" : "cooked already");

  if (saved_rl_state.cooked_prompt)    /* if (!prompt_is_still_uncooked) bombs with multi-line paste. Apparently
                                        prompt_is_still_uncooked can be FALSE while saved_rl_state.cooked_prompt = NULL. Ouch!@@@! */
    return FALSE;  /* cooked already */
  
  pre_cooked = mysavestring(saved_rl_state.raw_prompt);

  
  for (tcptr = term_ctrl_seqs; *tcptr; tcptr++) { 
    /* find last occurence of one of term_ctrl_seq */
    if (**tcptr && (p = mystrstr(pre_cooked, **tcptr))) {
      p += strlen(**tcptr);  /* p now points 1 char past term control sequence */ 
      if (p > non_rubbish) 
        non_rubbish = p; 
    }   
  }     
  /* non_rubbish now points 1 past the last 'alternate screen terminating' control char in prompt */
  if (non_rubbish) { 
    rubbish_from_alternate_screen = pre_cooked;
    pre_cooked = mysavestring(non_rubbish);
    *non_rubbish = '\0'; /* 0-terminate rubbish_from_alternate_screen */ 
  } else { 
    rubbish_from_alternate_screen = mysavestring("");
  }
  

  unbackspace(pre_cooked); /* programs that display a running counter would otherwise make rlwrap keep prompts
                              like " 1%\r 2%\r 3%\ ......" */

  if ( /* raw prompt doesn't match '--only-cook' regexp */
      (prompt_regexp && ! match_regexp(pre_cooked, prompt_regexp, FALSE)) ||
       /* now filter it, but filter may "refuse" the prompt */
      (strcmp((filtered =  pass_through_filter(TAG_PROMPT, pre_cooked)), "_THIS_CANNOT_BE_A_PROMPT_")== 0)) { 
    /* don't cook, eat raw (and eat nothing if patient) */       
    saved_rl_state.cooked_prompt =  (impatient_prompt ? mysavestring(pre_cooked) : mysavestring("")); 
    /* NB: if impatient, the rubbish_from_alternate_screen has been output already, no need to send it again */  
    free(pre_cooked);
    free(filtered); /* free(NULL) is never an error */
    return FALSE;
  }     
  free(pre_cooked);
  if(substitute_prompt) {
    uncoloured = mysavestring(substitute_prompt); 
    free(filtered);
  } else {
    uncoloured = filtered;
  }     
  if (colour_the_prompt) { 
    cooked =  colourise(uncoloured);
    free(uncoloured);
  } else {
    cooked = uncoloured;
  }
  if (! impatient_prompt)  /* in this case our rubbish hasn't been output yet. Output it now, but don't store
                              it in the prompt, as this may be re-printed e.g. after resuming a suspended rlwrap */
                              
    write_patiently(STDOUT_FILENO,rubbish_from_alternate_screen, strlen(rubbish_from_alternate_screen), "to stdout");
  saved_rl_state.cooked_prompt = cooked;
  return TRUE;
}       
コード例 #3
0
static void
line_handler(char *line)
{
  char *rewritten_line, *filtered_line;
  
  if (line == NULL) {           /* EOF on input, forward it  */
    DPRINTF1(DEBUG_READLINE, "EOF detected, writing character %d", term_eof);
    /* colour_the_prompt = FALSE; don't mess with the cruft that may come out of dying command @@@ but command may not die!*/
    write_EOF_to_master_pty();
  } else {
    if (*line &&                 /* forget empty lines  */
        redisplay &&             /* forget passwords    */
        !forget_line &&          /* forget lines entered by CTRL-O */
        !match_regexp(line, forget_regexp, TRUE)) {     /* forget lines (case-inseitively) matching -g option regexp */ 
      my_add_history(line);
    }
    forget_line = FALSE; /* until CTRL-O is used again */

    /* Time for a design decision: when we send the accepted line to the client command, it will most probably be echoed
       back. We have two choices: we leave the entered line on screen and suppress just enough of the clients output (I
       believe this is what rlfe does), or we remove the entered input (but not the prompt!) and let it be replaced by
       the echo.

       This is what we do; as a bonus, if the program doesn't echo, e.g. at a password prompt, the **** which has been
       put there by our homegrown_redisplay function will be removed (@@@is this what we want?)

       I think this method is more natural for multi-line input as well, (we will actually see our multi-line input as
       multiple lines) but not everyone will agree with that.
          
       O.K, we know for sure that cursor is at start of line. When clients output arrives, it will be printed at
       just the right place - but first we 'll erase the user input (as it may be about to be changed by the filter) */
    
    rl_delete_text(0, rl_end);  /* clear line  (after prompt) */
    rl_point = 0;
    my_redisplay();             /* and redisplay (this time without user input, cf the comments for the line_handler() function below) */

    rewritten_line =
      (multiline_separator ? 
       search_and_replace(multiline_separator, "\n", line, 0, NULL,
                          NULL) : mysavestring(line));


    
      
    if (redisplay)
      filtered_line = pass_through_filter(TAG_INPUT, rewritten_line);
    else { /* password, none of filters business */
      pass_through_filter(TAG_INPUT, "***"); /* filter some input anyway, to keep filter in sync (result is discarded).  */
      filtered_line = mysavestring(rewritten_line);
    }   
    free(rewritten_line);
        
    
    /* do we have to adapt clients winzsize now? */
    if (deferred_adapt_commands_window_size) {
      adapt_tty_winsize(STDIN_FILENO, master_pty_fd);
      kill(-command_pid, SIGWINCH);
      deferred_adapt_commands_window_size = FALSE;
    }


    
    /*OK, now feed line to underlying command and wait for the echo to come back */
    put_in_output_queue(filtered_line);
    DPRINTF2(DEBUG_READLINE, "putting %d bytes %s in output queue", (int) strlen(rewritten_line),
             mangle_string_for_debug_log(rewritten_line, 40));
    write_EOL_to_master_pty(return_key ? &return_key : "\n");

    accepted_lines++;
    free_foreign(line);         /* free_foreign because line was malloc'ed by readline, not by rlwrap */
    free(filtered_line);        /* we're done with them  */
        
    return_key = 0;
    within_line_edit = FALSE;
    if(!RL_ISSTATE(RL_STATE_MACROINPUT)) /* when called during playback of a multi-line macro, line_handler() will be called more 
                                            than once whithout re-entering main_loop(). If we'd remove it here, the second call
                                            would crash  */ 
       rl_callback_handler_remove();
    set_echo(FALSE);
    free(saved_rl_state.input_buffer);
    free(saved_rl_state.raw_prompt);
    free(saved_rl_state.cooked_prompt); 
    
    saved_rl_state.input_buffer = mysavestring("");
    saved_rl_state.raw_prompt = mysavestring("");
    saved_rl_state.cooked_prompt = NULL;
    saved_rl_state.point = 0;
    saved_rl_state.already_saved = TRUE;
    redisplay  = TRUE;

    if (one_shot_rlwrap)
      write_EOF_to_master_pty();
  }
}
コード例 #4
0
ファイル: main.c プロジェクト: albfan/rlwrap
char *
read_options_and_command_name(int argc, char **argv)
{
  int c;
  char *opt_C = NULL;
  int option_count = 0;
  int opt_b = FALSE;
  int opt_f = FALSE;
  int remaining = -1; /* remaining number of arguments on command line */
  int longindex = -1; /* index of current option in longopts[], set by getopt_long */
  
  
  full_program_name = mysavestring(argv[0]);
  program_name = mybasename(full_program_name);	/* normally "rlwrap"; needed by myerror() */
  rl_basic_word_break_characters = " \t\n\r(){}[],+-=&^%$#@\";|\\";

  opterr = 0;			/* we do our own error reporting */

  while (1) {
#ifdef HAVE_GETOPT_LONG
    c = getopt_long(argc, argv, optstring, longopts, &longindex);
#else
    c = getopt(argc, argv, optstring);
#endif

    if (c == EOF)
      break;
    option_count++;
    last_option_didnt_have_optional_argument = FALSE;
    remaining = argc - optind;
    last_opt = c;    

    switch (c) {
    case 'a':
      always_readline = TRUE;
      if (check_optarg('a', remaining))
        password_prompt_search_string = mysavestring(optarg);
      break;
    case 'A':	ansi_colour_aware = TRUE; break;
    case 'b':
      rl_basic_word_break_characters = add3strings("\r\n \t", optarg, "");
      opt_b = TRUE;
      break;
    case 'c':	complete_filenames = TRUE; break;
    case 'C':	opt_C = mysavestring(optarg); break;
    case 'd':
#ifdef DEBUG
      if (option_count > 1)
        myerror("-d or --debug option has to be the *first* rlwrap option");
      if (check_optarg('d', remaining))
        debug = atoi(optarg);
      else
        debug = DEBUG_DEFAULT;
#else
      myerror
        ("To use -d( for debugging), configure %s with --enable-debug and rebuild",
         program_name);
#endif
      break;

    case 'D': 
      history_duplicate_avoidance_policy=atoi(optarg);
      if (history_duplicate_avoidance_policy < 0 || history_duplicate_avoidance_policy > 2)
        myerror("%s option with illegal value %d, should be 0, 1 or 2",
                current_option('D', longindex), history_duplicate_avoidance_policy);
      break;
    case 'f':
      if (strncmp(optarg, ".", 10) == 0)
        feed_history_into_completion_list =  TRUE;
      else
        feed_file_into_completion_list(optarg);
      opt_f = TRUE;
      break;
    case 'F': myerror("The -F (--history-format) option is obsolete. Use -z \"history_format '%s'\" instead", optarg);
    case 'g': forget_regexp = mysavestring(optarg); match_regexp("just testing", forget_regexp, 1); break;
    case 'h':	usage(EXIT_SUCCESS);		/* will call exit() */
    case 'H':	history_filename = mysavestring(optarg); break;
    case 'i': 
      if (opt_f)
        myerror("-i option has to precede -f options");
      completion_is_case_sensitive = FALSE;
      break;
    case 'I':	pass_on_sigINT_as_sigTERM = TRUE; break;
    case 'l':	open_logfile(optarg); break;
    case 'n':	nowarn = TRUE; break;
    case 'm':
#ifndef HAVE_SYSTEM
      mywarn("the -m option doesn't work on this system");
#endif
      multiline_separator =
        (check_optarg('m', remaining) ? mysavestring(optarg) : " \\ ");
      break;
    case 'N': commands_children_not_wrapped = TRUE; break;
    case 'o': 
      one_shot_rlwrap = TRUE;
      impatient_prompt = FALSE;
      wait_before_prompt = 200;
      break;
    case 'O': prompt_regexp = mysavestring(optarg); match_regexp("just testing", prompt_regexp, 1); break;
    case 'p':
      colour_the_prompt = TRUE;
      initialise_colour_codes(check_optarg('p', remaining) ?
                              colour_name_to_ansi_code(optarg) :
                              colour_name_to_ansi_code("Red"));
      break;
    case 'P':
      pre_given = mysavestring(optarg);
      always_readline = TRUE; /* pre_given does not work well with transparent mode */
	
      break;
    case 'q': rl_basic_quote_characters = mysavestring(optarg); break;
    case 'r':	remember_for_completion = TRUE;	break;
    case 'R': renice = TRUE;	break;
    case 's':
      histsize = atoi(optarg);
      if (histsize < 0) {
        write_histfile = 0;
        histsize = -histsize;
      }
      break;
    case 'S': substitute_prompt =  mysavestring(optarg);break;
    case 't':	client_term_name=mysavestring(optarg);break;
#ifdef DEBUG
    case 'T':	test_terminal(); exit(EXIT_SUCCESS);
#endif
    case 'v':	printf("rlwrap %s\n",  VERSION); exit(EXIT_SUCCESS);
    case 'w':
      wait_before_prompt = atoi(optarg);
      if (wait_before_prompt < 0) {
        wait_before_prompt *= -1;
        impatient_prompt =  FALSE;
      }
      break;
    case 'z': filter_command = mysavestring(optarg);	break;
    case '?':
      assert(optind > 0);
      myerror("unrecognised option %s\ntry '%s --help' for more information",
              argv[optind-1], full_program_name);
    case ':':
      assert(optind > 0);
      myerror
        ("option %s requires an argument \ntry '%s --help' for more information",
         argv[optind-1], full_program_name);

    default:
      usage(EXIT_FAILURE);
    }
  }

  if (!complete_filenames && !opt_b) {	/* use / and . as default breaking characters whenever we don't complete filenames */
    rl_basic_word_break_characters =
      add2strings(rl_basic_word_break_characters, "/.");
  }

  
  if (optind >= argc) { /* rlwrap -a -b -c with no command specified */
    if (filter_command) { /* rlwrap -z filter with no command specified */
      mysignal(SIGALRM, &handle_sigALRM); /* needed for read_patiently2 */
      spawn_filter(filter_command);
      pass_through_filter(TAG_OUTPUT,""); /* ignore result but allow TAG_OUTPUT_OUT_OF_BAND */
      cleanup_rlwrap_and_exit(EXIT_SUCCESS);
    } else {
      usage(EXIT_FAILURE); 
    }
  }
  if (opt_C) {
    int countback = atoi(opt_C);	/* investigate whether -C option argument is numeric */

    if (countback > 0) {	/* e.g -C 1 or -C 12 */
      if (argc - countback < optind)	/* -C 666 */
	myerror("when using -C %d you need at least %d non-option arguments",
		countback, countback);
      else if (argv[argc - countback][0] == '-')	/* -C 2 perl -d blah.pl */
	myerror("the last argument minus %d appears to be an option!",
		countback);
      else {			/* -C 1 perl test.cgi */
	command_name = mysavestring(mybasename(argv[argc - countback]));

      }
    } else if (countback == 0) {	/* -C name1 name2 or -C 0 */
      if (opt_C[0] == '0' && opt_C[1] == '\0')	/* -C 0 */
	myerror("-C 0 makes no sense");
      else if (strlen(mybasename(opt_C)) != strlen(opt_C))	/* -C dir/name */
	myerror("-C option argument should not contain directory components");
      else if (opt_C[0] == '-')	/* -C -d  (?) */
	myerror("-C option needs argument");
      else			/* -C name */
	command_name = opt_C;
    } else {			/* -C -2 */
      myerror
	("-C option needs string or positive number as argument, perhaps you meant -C %d?",
	 -countback);
    }
  } else {			/* no -C option given, use command name */
    command_name = mysavestring(mybasename(argv[optind]));
  }
  assert(command_name != NULL);
  return command_name;
}