示例#1
0
/* A simplified loop for vi. Don't dispatch key at end.
   Don't recognize minus sign? */
static int
rl_digit_loop1 (void)
{
  int key, c;

  while (1)
    {
      rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg, 0);
      key = c = rl_read_key ();

      if (_rl_keymap[c].type == ISFUNC &&
	  _rl_keymap[c].function == (Function *)rl_universal_argument)
	{
	  rl_numeric_arg *= 4;
	  continue;
	}

      c = UNMETA (c);
      if (digit_p (c))
	{
	  if (rl_explicit_arg)
	    rl_numeric_arg = (rl_numeric_arg * 10) + digit_value (c);
	  else
	    rl_numeric_arg = digit_value (c);
	  rl_explicit_arg = 1;
	}
      else
	{
	  rl_clear_message ();
	  rl_stuff_char (key);
	  break;
	}
    }
  return (0);
}
示例#2
0
int
rl_vi_domove (int key, int *nextkey)
{
  int c, save;
  int old_end;

  rl_mark = rl_point;
  c = rl_read_key ();
  *nextkey = c;

  if (!member (c, vi_motion))
    {
      if (digit_p (c))
	{
	  save = rl_numeric_arg;
	  rl_numeric_arg = digit_value (c);
	  rl_digit_loop1 ();
	  rl_numeric_arg *= save;
	  c = rl_read_key ();	/* real command */
	  *nextkey = c;
	}
      else if (key == c && (key == 'd' || key == 'y' || key == 'c'))
	{
	  rl_mark = rl_end;
	  rl_beg_of_line (1, c);
	  _rl_vi_last_motion = c;
	  return (0);
	}
      else
	return (-1);
    }

  _rl_vi_last_motion = c;

  /* Append a blank character temporarily so that the motion routines
     work right at the end of the line. */
  old_end = rl_end;
  rl_line_buffer[rl_end++] = ' ';
  rl_line_buffer[rl_end] = '\0';

  _rl_dispatch (c, _rl_keymap);

  /* Remove the blank that we added. */
  rl_end = old_end;
  rl_line_buffer[rl_end] = '\0';
  if (rl_point > rl_end)
    rl_point = rl_end;

  /* No change in position means the command failed. */
  if (rl_mark == rl_point)
    return (-1);

  /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
     word.  If we are not at the end of the line, and we are on a
     non-whitespace character, move back one (presumably to whitespace). */
  if ((to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark &&
      !whitespace (rl_line_buffer[rl_point]))
    rl_point--;

  /* If cw or cW, back up to the end of a word, so the behaviour of ce
     or cE is the actual result.  Brute-force, no subtlety. */
  if (key == 'c' && rl_point >= rl_mark && (to_upper (c) == 'W'))
    {
      /* Don't move farther back than where we started. */
      while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point]))
	rl_point--;

      /* Posix.2 says that if cw or cW moves the cursor towards the end of
	 the line, the character under the cursor should be deleted. */
      if (rl_point == rl_mark)
        rl_point++;
      else
	{
	  /* Move past the end of the word so that the kill doesn't
	     remove the last letter of the previous word.  Only do this
	     if we are not at the end of the line. */
	  if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point]))
	    rl_point++;
	}
    }

  if (rl_mark < rl_point)
    exchange (rl_point, rl_mark);

  return (0);
}
示例#3
0
文件: lexer.c 项目: nathan/logo
static void logo_Lexer_advance(logo_Lexer *self) {
#define opv(_name, _value) do { self->token = (logo_Token) { .type = logo_Token_ ## _name, .value = _value, .start = start, .end = logo_Stream_position(self->stream) }; return; } while (0)
#define op(_name) opv(_name, NULL)

    long start = logo_Stream_position(self->stream);
    int c = logo_Stream_next(self->stream);

    bool whitespace = false;
trim:
    if (whitespace_p(c) || ((self->list_level || self->in_proc) && newline_p(c))) {
        start = logo_Stream_position(self->stream);
        c = logo_Stream_next(self->stream);
        whitespace = true;
        goto trim;
    }
    if (c == '#') {
        if (logo_Stream_next(self->stream) == '!') {
            do {
                c = logo_Stream_next(self->stream);
            } while (!newline_p(c) && c != logo_Stream_END);
            start = logo_Stream_position(self->stream) - 1;
            goto trim;
        }
        logo_Stream_skip(self->stream, -1);
    }
    if (c == ';' && self->list_level == 0) {
        do {
            c = logo_Stream_next(self->stream);
        } while (!newline_p(c) && c != logo_Stream_END);
        start = logo_Stream_position(self->stream) - 1;
        goto trim;
    }

    switch (c) {
        case logo_Stream_END:
            op(END);
        case '[':
            ++self->list_level;
            op(LBRACKET);
        case ']':
            if (self->list_level > 0) --self->list_level;
            op(RBRACKET);
    }
    if (newline_p(c)) {
        do {
            c = logo_Stream_next(self->stream);
        } while (newline_p(c));
        logo_Stream_skip(self->stream, -1);
        op(NEWLINE);
    }

    if (self->list_level || self->in_proc) {
        size_t size = 0;
        do {
            ++size;
            c = logo_Stream_next(self->stream);
        } while (lword_p(c));

        logo_Stream_skip(self->stream, -size - 1);

        char *s = malloc(size + 1), *p;
        for (p = s; p < s + size; ++p) {
            *p = logo_Stream_next(self->stream);
        }
        *p = 0;

        if (self->in_proc && strcmp(s, "end") == 0) {
            free(s);
            op(PROCEND);
        }

        opv(WORD, s);
    }

    switch (c) {
        case '(': op(LPAREN);
        case ')': op(RPAREN);
        case ':': op(COLON);
        case '?': op(QUESTION);
        case '+': op(ADD);
        case '-':
            if (whitespace && !whitespace_p(logo_Stream_peek(self->stream))) {
                op(INVERSE);
            }
            op(SUB);
        case '*': op(MUL);
        case '/': op(DIV);
        case '=': op(EQUAL);
        case '>':
            if (logo_Stream_peek(self->stream) == '=') {
                logo_Stream_next(self->stream);
                op(GTE);
            }
            op(GT);
        case '<':
            if (logo_Stream_peek(self->stream) == '=') {
                logo_Stream_next(self->stream);
                op(LTE);
            }
            if (logo_Stream_peek(self->stream) == '>') {
                logo_Stream_next(self->stream);
                op(NOTEQUAL);
            }
            op(LT);
    }

    if (c == '"') {
        size_t size = 0;
        c = logo_Stream_next(self->stream);
        while (word_p(c)) {
            ++size;
            c = logo_Stream_next(self->stream);
        }

        logo_Stream_skip(self->stream, -size - 1);

        char *s = malloc(size + 1), *p;
        for (p = s; p < s + size; ++p) {
            *p = logo_Stream_next(self->stream);
        }
        *p = 0;

        opv(WORD, s);
    }
    if (digit_p(c)) {
        size_t size = 0;
#define next do { ++size; c = logo_Stream_next(self->stream); } while (0)

        do {
            do next; while (digit_p(c));

            if (c == '.') {
                next;
                if (!digit_p(c)) break;
                do next; while (digit_p(c));
            }
            if (c == 'e' || c == 'E') {
                next;
                if (c == '+' || c == '-') next;
                if (!digit_p(c)) break;
                do next; while (digit_p(c));
            }

            if (name_p(c)) break;

            logo_Stream_skip(self->stream, -size - 1);

            char *s = malloc(size + 1), *p;
            for (p = s; p < s + size; ++p) {
                *p = logo_Stream_next(self->stream);
            }
            *p = 0;

            opv(NUMBER, s);
        } while (false);
#undef next

        logo_Stream_skip(self->stream, -size - 1);
        c = logo_Stream_next(self->stream);
    }
    if (name_p(c)) {
        size_t size = 0;
        do {
            ++size;
            c = logo_Stream_next(self->stream);
        } while (name_p(c));

        logo_Stream_skip(self->stream, -size - 1);

        char *s = malloc(size), *p;
        for (p = s; p < s + size; ++p) {
            *p = logo_Stream_next(self->stream);
        }
        *p = 0;

        opv(NAME, s);
    }
#undef op
}