コード例 #1
0
/*
 * Convert a key code sequence into a key code sequence string.
 */
astr keyvectostr(size_t *keys, size_t numkeys)
{
    size_t i;
    astr as = astr_new();

    for (i = 0; i < numkeys; i++) {
        astr key = chordtostr(keys[i]);
        astr_cat(as, key);
        astr_delete(key);
        if (i < numkeys - 1)
            astr_cat_char(as, ' ');
    }

    return as;
}
コード例 #2
0
/*
 * Convert a key like "\\C-xrs" to "C-x r s"
 */
astr simplify_key(char *key)
{
    int i, j;
    size_t *keys;
    astr dest = astr_new();

    if (key == NULL)
        return dest;
    i = keystrtovec(key, &keys);
    for (j = 0; j < i; j++) {
        astr as;
        if (j > 0)
            astr_cat_char(dest, ' ');
        as = chordtostr(keys[j]);
        astr_cat(dest, as);
        astr_delete(as);
    }
    if (i > 0)
        free(keys);

    return dest;
}
コード例 #3
0
ファイル: file.c プロジェクト: M1lan/zile
/*
 * This functions does some corrections and expansions to
 * the passed path:
 *
 * - expands `~/' and `~name/' expressions;
 * - replaces `//' with `/' (restarting from the root directory);
 * - removes `..' and `.' entries.
 *
 * The return value indicates success or failure.
 */
bool
expand_path (astr path)
{
  int ok = true;
  const char *sp = astr_cstr (path);
  astr epath = astr_new ();

  if (*sp != '/' && *sp != '~')
    {
      astr_cat (epath, agetcwd ());
      if (astr_len (epath) == 0 ||
          astr_get (epath, astr_len (epath) - 1) != '/')
        astr_cat_char (epath, '/');
    }

  for (const char *p = sp; *p != '\0';)
    {
      if (*p == '/')
        {
          if (*++p == '/')
            { /* Got `//'.  Restart from this point. */
              while (*p == '/')
                p++;
              astr_truncate (epath, 0);
            }
          if (astr_len (epath) == 0 ||
              astr_get (epath, astr_len (epath) - 1) != '/')
            astr_cat_char (epath, '/');
        }
      else if (*p == '~' && (p == sp || p[-1] == '/'))
        { /* Got `/~' or leading `~'.  Restart from this point. */
          struct passwd *pw;

          astr_truncate (epath, 0);
          ++p;

          if (*p == '/')
            { /* Got `~/'.  Insert the user's home directory. */
              pw = getpwuid (getuid ());
              if (pw == NULL)
                {
                  ok = false;
                  break;
                }
              if (!STREQ (pw->pw_dir, "/"))
                astr_cat_cstr (epath, pw->pw_dir);
            }
          else
            { /* Got `~something'.  Insert that user's home directory. */
              astr as = astr_new ();
              while (*p != '\0' && *p != '/')
                astr_cat_char (as, *p++);
              pw = getpwnam (astr_cstr (as));
              if (pw == NULL)
                {
                  ok = false;
                  break;
                }
              astr_cat_cstr (epath, pw->pw_dir);
            }
        }
      else if (*p == '.' && (p[1] == '/' || p[1] == '\0'))
        { /* Got `.'. */
          ++p;
        }
      else if (*p == '.' && p[1] == '.' && (p[2] == '/' || p[2] == '\0'))
        { /* Got `..'. */
          if (astr_len (epath) >= 1 && astr_get (epath, astr_len (epath) - 1) == '/')
            astr_truncate (epath, astr_len (epath) - 1);
          while (astr_get (epath, astr_len (epath) - 1) != '/' && astr_len (epath) >= 1)
            astr_truncate (epath, astr_len (epath) - 1);
          p += 2;
        }

      if (*p != '~')
        while (*p != '\0' && *p != '/')
          astr_cat_char (epath, *p++);
    }

  astr_cpy (path, epath);

  return ok;
}
コード例 #4
0
ファイル: term_minibuf.c プロジェクト: gvvaughan/luajit-zile
static astr
do_minibuf_read (const char *prompt, const char *value, size_t pos,
               Completion * cp, History * hp)
{
  static int overwrite_mode = 0;
  int c, thistab, lasttab = -1;
  size_t prompt_len;
  char *s;
  astr as = astr_new_cstr (value), saved = NULL;

  prompt_len = strlen (prompt);
  if (pos == SIZE_MAX)
    pos = astr_len (as);

  for (;;)
    {
      switch (lasttab)
        {
        case COMPLETION_MATCHEDNONUNIQUE:
          s = " [Complete, but not unique]";
          break;
        case COMPLETION_NOTMATCHED:
          s = " [No match]";
          break;
        case COMPLETION_MATCHED:
          s = " [Sole completion]";
          break;
        default:
          s = "";
        }
      draw_minibuf_read (prompt, astr_cstr (as), prompt_len, s, pos);

      thistab = -1;

      switch (c = getkey ())
        {
        case KBD_NOKEY:
          break;
        case KBD_CTRL | 'z':
          FUNCALL (suspend_emacs);
          break;
        case KBD_RET:
          term_move (term_height () - 1, 0);
          term_clrtoeol ();
          if (saved)
            astr_delete (saved);
          return as;
        case KBD_CANCEL:
          term_move (term_height () - 1, 0);
          term_clrtoeol ();
          if (saved)
            astr_delete (saved);
          astr_delete (as);
          return NULL;
        case KBD_CTRL | 'a':
        case KBD_HOME:
          pos = 0;
          break;
        case KBD_CTRL | 'e':
        case KBD_END:
          pos = astr_len (as);
          break;
        case KBD_CTRL | 'b':
        case KBD_LEFT:
          if (pos > 0)
            --pos;
          else
            ding ();
          break;
        case KBD_CTRL | 'f':
        case KBD_RIGHT:
          if (pos < astr_len (as))
            ++pos;
          else
            ding ();
          break;
        case KBD_CTRL | 'k':
          /* FIXME: do kill-register save. */
          if (pos < astr_len (as))
            astr_truncate (as, pos);
          else
            ding ();
          break;
        case KBD_BS:
          if (pos > 0)
            astr_remove (as, --pos, 1);
          else
            ding ();
          break;
        case KBD_CTRL | 'd':
        case KBD_DEL:
          if (pos < astr_len (as))
            astr_remove (as, pos, 1);
          else
            ding ();
          break;
        case KBD_INS:
          overwrite_mode = overwrite_mode ? 0 : 1;
          break;
        case KBD_META | 'v':
        case KBD_PGUP:
          if (cp == NULL)
            {
              ding ();
              break;
            }

          if (get_completion_flags (cp) & CFLAG_POPPEDUP)
            {
              completion_scroll_down ();
              thistab = lasttab;
            }
          break;
        case KBD_CTRL | 'v':
        case KBD_PGDN:
          if (cp == NULL)
            {
              ding ();
              break;
            }

          if (get_completion_flags (cp) & CFLAG_POPPEDUP)
            {
              completion_scroll_up ();
              thistab = lasttab;
            }
          break;
        case KBD_UP:
        case KBD_META | 'p':
          if (hp)
            {
              const char *elem = previous_history_element (hp);
              if (elem)
                {
                  if (!saved)
                    saved = astr_cpy (astr_new (), as);

                  astr_cpy_cstr (as, elem);
                }
            }
          break;
        case KBD_DOWN:
        case KBD_META | 'n':
          if (hp)
            {
              const char *elem = next_history_element (hp);
              if (elem)
                astr_cpy_cstr (as, elem);
              else if (saved)
                {
                  astr_cpy (as, saved);
                  astr_delete (saved);
                  saved = NULL;
                }
            }
          break;
        case KBD_TAB:
        got_tab:
          if (cp == NULL)
            {
              ding ();
              break;
            }

          if (lasttab != -1 && lasttab != COMPLETION_NOTMATCHED
              && get_completion_flags (cp) & CFLAG_POPPEDUP)
            {
              completion_scroll_up ();
              thistab = lasttab;
            }
          else
            {
              astr bs = astr_new ();
              astr_cpy (bs, as);
              thistab = completion_try (cp, bs, true);
              astr_delete (bs);
              switch (thistab)
                {
                case COMPLETION_MATCHED:
                case COMPLETION_MATCHEDNONUNIQUE:
                case COMPLETION_NONUNIQUE:
                  {
                    bs = astr_new ();
                    if (get_completion_flags (cp) & CFLAG_FILENAME)
                      astr_cat (bs, get_completion_path (cp));
                    astr_ncat_cstr (bs, get_completion_match (cp), get_completion_matchsize (cp));
                    if (strncmp (astr_cstr (as), astr_cstr (bs),
                                 astr_len (bs)) != 0)
                      thistab = -1;
                    astr_delete (as);
                    as = bs;
                    pos = astr_len (as);
                    break;
                  }
                case COMPLETION_NOTMATCHED:
                  ding ();
                }
            }
          break;
        case ' ':
          if (cp != NULL)
            goto got_tab;
          /* FALLTHROUGH */
        default:
          if (c > 255 || !isprint (c))
            {
              ding ();
              break;
            }
          astr_insert_char (as, pos++, c);
          if (overwrite_mode && pos != astr_len (as))
            astr_remove (as, pos, 1);
        }

      lasttab = thistab;
    }
}