Пример #1
0
/*
 * Returns the already visited list for the given filename. If none is found it
 * allocates a new one.
 */
static ff_visited_list_hdr_T *ff_get_visited_list(char_u *filename, ff_visited_list_hdr_T **list_headp)
{
  ff_visited_list_hdr_T  *retptr = NULL;

  /* check if a visited list for the given filename exists */
  if (*list_headp != NULL) {
    retptr = *list_headp;
    while (retptr != NULL) {
      if (fnamecmp(filename, retptr->ffvl_filename) == 0) {
#ifdef FF_VERBOSE
        if (p_verbose >= 5) {
          verbose_enter_scroll();
          smsg((char_u *)"ff_get_visited_list: FOUND list for %s",
              filename);
          /* don't overwrite this either */
          msg_puts((char_u *)"\n");
          verbose_leave_scroll();
        }
#endif
        return retptr;
      }
      retptr = retptr->ffvl_next;
    }
  }

#ifdef FF_VERBOSE
  if (p_verbose >= 5) {
    verbose_enter_scroll();
    smsg((char_u *)"ff_get_visited_list: new list for %s", filename);
    /* don't overwrite this either */
    msg_puts((char_u *)"\n");
    verbose_leave_scroll();
  }
#endif

  /*
   * if we reach this we didn't find a list and we have to allocate new list
   */
  retptr = (ff_visited_list_hdr_T*)alloc((unsigned)sizeof(*retptr));
  if (retptr == NULL)
    return NULL;

  retptr->ffvl_visited_list = NULL;
  retptr->ffvl_filename = vim_strsave(filename);
  if (retptr->ffvl_filename == NULL) {
    vim_free(retptr);
    return NULL;
  }
  retptr->ffvl_next = *list_headp;
  *list_headp = retptr;

  return retptr;
}
Пример #2
0
/// List all features aligned in columns, dictionary style.
static void list_features(void)
{
  int nfeat = 0;
  int width = 0;

  // Find the length of the longest feature name, use that + 1 as the column
  // width
  int i;
  for (i = 0; features[i] != NULL; ++i) {
    int l = (int)STRLEN(features[i]);

    if (l > width) {
      width = l;
    }
    nfeat++;
  }
  width += 1;

  if (Columns < width) {
    // Not enough screen columns - show one per line
    for (i = 0; features[i] != NULL; ++i) {
      version_msg(features[i]);
      if (msg_col > 0) {
        msg_putchar('\n');
      }
    }
    return;
  }

  // The rightmost column doesn't need a separator.
  // Sacrifice it to fit in one more column if possible.
  int ncol = (int)(Columns + 1) / width;
  int nrow = nfeat / ncol + (nfeat % ncol ? 1 : 0);

  // i counts columns then rows.  idx counts rows then columns.
  for (i = 0; !got_int && i < nrow * ncol; ++i) {
    int idx = (i / ncol) + (i % ncol) * nrow;
    if (idx < nfeat) {
      int last_col = (i + 1) % ncol == 0;
      msg_puts((char_u *)features[idx]);
      if (last_col) {
        if (msg_col > 0) {
          msg_putchar('\n');
        }
      } else {
        while (msg_col % width) {
          msg_putchar(' ');
        }
      }
    } else {
      if (msg_col > 0) {
        msg_putchar('\n');
      }
    }
  }
  MSG_PUTS("For differences from Vim, see :help vim-differences\n\n");
}
Пример #3
0
/*
 * List placed signs for "rbuf".  If "rbuf" is NULL do it for all buffers.
 */
    static void
sign_list_placed(buf_T *rbuf, char_u *sign_group)
{
    buf_T	*buf;
    signlist_T	*sign;
    char	lbuf[MSG_BUF_LEN];
    char	group[MSG_BUF_LEN];

    msg_puts_title(_("\n--- Signs ---"));
    msg_putchar('\n');
    if (rbuf == NULL)
	buf = firstbuf;
    else
	buf = rbuf;
    while (buf != NULL && !got_int)
    {
	if (buf->b_signlist != NULL)
	{
	    vim_snprintf(lbuf, MSG_BUF_LEN, _("Signs for %s:"), buf->b_fname);
	    msg_puts_attr(lbuf, HL_ATTR(HLF_D));
	    msg_putchar('\n');
	}
	FOR_ALL_SIGNS_IN_BUF(buf, sign)
	{
	    if (got_int)
		break;
	    if (!sign_in_group(sign, sign_group))
		continue;
	    if (sign->group != NULL)
		vim_snprintf(group, MSG_BUF_LEN, _("  group=%s"),
							sign->group->sg_name);
	    else
		group[0] = '\0';
	    vim_snprintf(lbuf, MSG_BUF_LEN,
			   _("    line=%ld  id=%d%s  name=%s  priority=%d"),
			   (long)sign->lnum, sign->id, group,
			   sign_typenr2name(sign->typenr), sign->priority);
	    msg_puts(lbuf);
	    msg_putchar('\n');
	}
	if (rbuf != NULL)
	    break;
	buf = buf->b_next;
    }
}
Пример #4
0
/*
 * Find a file in a search context.
 * The search context was created with vim_findfile_init() above.
 * Return a pointer to an allocated file name or NULL if nothing found.
 * To get all matching files call this function until you get NULL.
 *
 * If the passed search_context is NULL, NULL is returned.
 *
 * The search algorithm is depth first. To change this replace the
 * stack with a list (don't forget to leave partly searched directories on the
 * top of the list).
 */
char_u *vim_findfile(void *search_ctx_arg)
{
  char_u      *file_path;
  char_u      *rest_of_wildcards;
  char_u      *path_end = NULL;
  ff_stack_T  *stackp;
  int len;
  int i;
  char_u      *p;
  char_u      *suf;
  ff_search_ctx_T *search_ctx;

  if (search_ctx_arg == NULL)
    return NULL;

  search_ctx = (ff_search_ctx_T *)search_ctx_arg;

  /*
   * filepath is used as buffer for various actions and as the storage to
   * return a found filename.
   */
  file_path = xmalloc(MAXPATHL);

  /* store the end of the start dir -- needed for upward search */
  if (search_ctx->ffsc_start_dir != NULL)
    path_end = &search_ctx->ffsc_start_dir[
      STRLEN(search_ctx->ffsc_start_dir)];

  /* upward search loop */
  for (;; ) {
    /* downward search loop */
    for (;; ) {
      /* check if user user wants to stop the search*/
      ui_breakcheck();
      if (got_int)
        break;

      /* get directory to work on from stack */
      stackp = ff_pop(search_ctx);
      if (stackp == NULL)
        break;

      /*
       * TODO: decide if we leave this test in
       *
       * GOOD: don't search a directory(-tree) twice.
       * BAD:  - check linked list for every new directory entered.
       *       - check for double files also done below
       *
       * Here we check if we already searched this directory.
       * We already searched a directory if:
       * 1) The directory is the same.
       * 2) We would use the same wildcard string.
       *
       * Good if you have links on same directory via several ways
       *  or you have selfreferences in directories (e.g. SuSE Linux 6.3:
       *  /etc/rc.d/init.d is linked to /etc/rc.d -> endless loop)
       *
       * This check is only needed for directories we work on for the
       * first time (hence stackp->ff_filearray == NULL)
       */
      if (stackp->ffs_filearray == NULL
          && ff_check_visited(&search_ctx->ffsc_dir_visited_list
              ->ffvl_visited_list,
              stackp->ffs_fix_path
              , stackp->ffs_wc_path
              ) == FAIL) {
#ifdef FF_VERBOSE
        if (p_verbose >= 5) {
          verbose_enter_scroll();
          smsg((char_u *)"Already Searched: %s (%s)",
              stackp->ffs_fix_path, stackp->ffs_wc_path);
          /* don't overwrite this either */
          msg_puts((char_u *)"\n");
          verbose_leave_scroll();
        }
#endif
        ff_free_stack_element(stackp);
        continue;
      }
#ifdef FF_VERBOSE
      else if (p_verbose >= 5) {
        verbose_enter_scroll();
        smsg((char_u *)"Searching: %s (%s)",
            stackp->ffs_fix_path, stackp->ffs_wc_path);
        /* don't overwrite this either */
        msg_puts((char_u *)"\n");
        verbose_leave_scroll();
      }
#endif

      /* check depth */
      if (stackp->ffs_level <= 0) {
        ff_free_stack_element(stackp);
        continue;
      }

      file_path[0] = NUL;

      /*
       * If no filearray till now expand wildcards
       * The function expand_wildcards() can handle an array of paths
       * and all possible expands are returned in one array. We use this
       * to handle the expansion of '**' into an empty string.
       */
      if (stackp->ffs_filearray == NULL) {
        char_u *dirptrs[2];

        /* we use filepath to build the path expand_wildcards() should
         * expand.
         */
        dirptrs[0] = file_path;
        dirptrs[1] = NULL;

        /* if we have a start dir copy it in */
        if (!vim_isAbsName(stackp->ffs_fix_path)
            && search_ctx->ffsc_start_dir) {
          STRCPY(file_path, search_ctx->ffsc_start_dir);
          add_pathsep(file_path);
        }

        /* append the fix part of the search path */
        STRCAT(file_path, stackp->ffs_fix_path);
        add_pathsep(file_path);

        rest_of_wildcards = stackp->ffs_wc_path;
        if (*rest_of_wildcards != NUL) {
          len = (int)STRLEN(file_path);
          if (STRNCMP(rest_of_wildcards, "**", 2) == 0) {
            /* pointer to the restrict byte
             * The restrict byte is not a character!
             */
            p = rest_of_wildcards + 2;

            if (*p > 0) {
              (*p)--;
              file_path[len++] = '*';
            }

            if (*p == 0) {
              /* remove '**<numb> from wildcards */
              STRMOVE(rest_of_wildcards, rest_of_wildcards + 3);
            } else
              rest_of_wildcards += 3;

            if (stackp->ffs_star_star_empty == 0) {
              /* if not done before, expand '**' to empty */
              stackp->ffs_star_star_empty = 1;
              dirptrs[1] = stackp->ffs_fix_path;
            }
          }

          /*
           * Here we copy until the next path separator or the end of
           * the path. If we stop at a path separator, there is
           * still something else left. This is handled below by
           * pushing every directory returned from expand_wildcards()
           * on the stack again for further search.
           */
          while (*rest_of_wildcards
                 && !vim_ispathsep(*rest_of_wildcards))
            file_path[len++] = *rest_of_wildcards++;

          file_path[len] = NUL;
          if (vim_ispathsep(*rest_of_wildcards))
            rest_of_wildcards++;
        }

        /*
         * Expand wildcards like "*" and "$VAR".
         * If the path is a URL don't try this.
         */
        if (path_with_url(dirptrs[0])) {
          stackp->ffs_filearray = (char_u **)xmalloc(sizeof(char *));
          stackp->ffs_filearray[0] = vim_strsave(dirptrs[0]);
          stackp->ffs_filearray_size = 1;
        } else
          /* Add EW_NOTWILD because the expanded path may contain
           * wildcard characters that are to be taken literally.
           * This is a bit of a hack. */
          expand_wildcards((dirptrs[1] == NULL) ? 1 : 2, dirptrs,
              &stackp->ffs_filearray_size,
              &stackp->ffs_filearray,
              EW_DIR|EW_ADDSLASH|EW_SILENT|EW_NOTWILD);

        stackp->ffs_filearray_cur = 0;
        stackp->ffs_stage = 0;
      } else
        rest_of_wildcards = &stackp->ffs_wc_path[
          STRLEN(stackp->ffs_wc_path)];

      if (stackp->ffs_stage == 0) {
        /* this is the first time we work on this directory */
        if (*rest_of_wildcards == NUL) {
          /*
           * We don't have further wildcards to expand, so we have to
           * check for the final file now.
           */
          for (i = stackp->ffs_filearray_cur;
               i < stackp->ffs_filearray_size; ++i) {
            if (!path_with_url(stackp->ffs_filearray[i])
                && !os_isdir(stackp->ffs_filearray[i]))
              continue;                 /* not a directory */

            /* prepare the filename to be checked for existence
             * below */
            STRCPY(file_path, stackp->ffs_filearray[i]);
            add_pathsep(file_path);
            STRCAT(file_path, search_ctx->ffsc_file_to_search);

            /*
             * Try without extra suffix and then with suffixes
             * from 'suffixesadd'.
             */
            len = (int)STRLEN(file_path);
            if (search_ctx->ffsc_tagfile)
              suf = (char_u *)"";
            else
              suf = curbuf->b_p_sua;
            for (;; ) {
              /* if file exists and we didn't already find it */
              if ((path_with_url(file_path)
                   || (os_file_exists(file_path)
                       && (search_ctx->ffsc_find_what
                           == FINDFILE_BOTH
                           || ((search_ctx->ffsc_find_what
                                == FINDFILE_DIR)
                               == os_isdir(file_path)))))
#ifndef FF_VERBOSE
                  && (ff_check_visited(
                          &search_ctx->ffsc_visited_list->ffvl_visited_list,
                          file_path
                          , (char_u *)""
                          ) == OK)
#endif
                  ) {
#ifdef FF_VERBOSE
                if (ff_check_visited(
                        &search_ctx->ffsc_visited_list->ffvl_visited_list,
                        file_path
                        , (char_u *)""
                        ) == FAIL) {
                  if (p_verbose >= 5) {
                    verbose_enter_scroll();
                    smsg((char_u *)"Already: %s",
                        file_path);
                    /* don't overwrite this either */
                    msg_puts((char_u *)"\n");
                    verbose_leave_scroll();
                  }
                  continue;
                }
#endif

                /* push dir to examine rest of subdirs later */
                stackp->ffs_filearray_cur = i + 1;
                ff_push(search_ctx, stackp);

                if (!path_with_url(file_path))
                  simplify_filename(file_path);
                if (os_dirname(ff_expand_buffer, MAXPATHL)
                    == OK) {
                  p = path_shorten_fname(file_path,
                      ff_expand_buffer);
                  if (p != NULL)
                    STRMOVE(file_path, p);
                }
#ifdef FF_VERBOSE
                if (p_verbose >= 5) {
                  verbose_enter_scroll();
                  smsg((char_u *)"HIT: %s", file_path);
                  /* don't overwrite this either */
                  msg_puts((char_u *)"\n");
                  verbose_leave_scroll();
                }
#endif
                return file_path;
              }

              /* Not found or found already, try next suffix. */
              if (*suf == NUL)
                break;
              copy_option_part(&suf, file_path + len,
                  MAXPATHL - len, ",");
            }
          }
        } else {
          /*
           * still wildcards left, push the directories for further
           * search
           */
          for (i = stackp->ffs_filearray_cur;
               i < stackp->ffs_filearray_size; ++i) {
            if (!os_isdir(stackp->ffs_filearray[i]))
              continue;                 /* not a directory */

            ff_push(search_ctx,
                ff_create_stack_element(
                    stackp->ffs_filearray[i],
                    rest_of_wildcards,
                    stackp->ffs_level - 1, 0));
          }
        }
        stackp->ffs_filearray_cur = 0;
        stackp->ffs_stage = 1;
      }

      /*
       * if wildcards contains '**' we have to descent till we reach the
       * leaves of the directory tree.
       */
      if (STRNCMP(stackp->ffs_wc_path, "**", 2) == 0) {
        for (i = stackp->ffs_filearray_cur;
             i < stackp->ffs_filearray_size; ++i) {
          if (fnamecmp(stackp->ffs_filearray[i],
                  stackp->ffs_fix_path) == 0)
            continue;             /* don't repush same directory */
          if (!os_isdir(stackp->ffs_filearray[i]))
            continue;               /* not a directory */
          ff_push(search_ctx,
              ff_create_stack_element(stackp->ffs_filearray[i],
                  stackp->ffs_wc_path, stackp->ffs_level - 1, 1));
        }
      }

      /* we are done with the current directory */
      ff_free_stack_element(stackp);

    }

    /* If we reached this, we didn't find anything downwards.
     * Let's check if we should do an upward search.
     */
    if (search_ctx->ffsc_start_dir
        && search_ctx->ffsc_stopdirs_v != NULL && !got_int) {
      ff_stack_T  *sptr;

      /* is the last starting directory in the stop list? */
      if (ff_path_in_stoplist(search_ctx->ffsc_start_dir,
              (int)(path_end - search_ctx->ffsc_start_dir),
              search_ctx->ffsc_stopdirs_v) == TRUE)
        break;

      /* cut of last dir */
      while (path_end > search_ctx->ffsc_start_dir
             && vim_ispathsep(*path_end))
        path_end--;
      while (path_end > search_ctx->ffsc_start_dir
             && !vim_ispathsep(path_end[-1]))
        path_end--;
      *path_end = 0;
      path_end--;

      if (*search_ctx->ffsc_start_dir == 0)
        break;

      STRCPY(file_path, search_ctx->ffsc_start_dir);
      add_pathsep(file_path);
      STRCAT(file_path, search_ctx->ffsc_fix_path);

      /* create a new stack entry */
      sptr = ff_create_stack_element(file_path,
          search_ctx->ffsc_wc_path, search_ctx->ffsc_level, 0);
      ff_push(search_ctx, sptr);
    } else
      break;
  }

  free(file_path);
  return NULL;
}
Пример #5
0
/*
 * List all features aligned in columns, dictionary style.
 */
    static void
list_features(void)
{
    int		i;
    int		ncol;
    int		nrow;
    int		nfeat = 0;
    int		width = 0;

    /* Find the length of the longest feature name, use that + 1 as the column
     * width */
    for (i = 0; features[i] != NULL; ++i)
    {
	int l = (int)STRLEN(features[i]);

	if (l > width)
	    width = l;
	++nfeat;
    }
    width += 1;

    if (Columns < width)
    {
	/* Not enough screen columns - show one per line */
	for (i = 0; features[i] != NULL; ++i)
	{
	    version_msg(features[i]);
	    if (msg_col > 0)
		msg_putchar('\n');
	}
	return;
    }

    /* The rightmost column doesn't need a separator.
     * Sacrifice it to fit in one more column if possible. */
    ncol = (int) (Columns + 1) / width;
    nrow = nfeat / ncol + (nfeat % ncol ? 1 : 0);

    /* i counts columns then rows.  idx counts rows then columns. */
    for (i = 0; !got_int && i < nrow * ncol; ++i)
    {
	int idx = (i / ncol) + (i % ncol) * nrow;

	if (idx < nfeat)
	{
	    int last_col = (i + 1) % ncol == 0;

	    msg_puts((char_u *)features[idx]);
	    if (last_col)
	    {
		if (msg_col > 0)
		    msg_putchar('\n');
	    }
	    else
	    {
		while (msg_col % width)
		    msg_putchar(' ');
	    }
	}
	else
	{
	    if (msg_col > 0)
		msg_putchar('\n');
	}
    }
}
Пример #6
0
/// Dumps termcap info to the messages area.
/// Serves a similar purpose as Vim `:set termcap` (removed in Nvim).
///
/// @note adapted from unibilium unibi-dump.c
void terminfo_info_msg(const unibi_term *const ut)
{
  if (exiting) {
    return;
  }
  msg_puts_title("\n\n--- Terminal info --- {{{\n");

  char *term;
  get_tty_option("term", &term);
  msg_printf_attr(0, "&term: %s\n", term);
  msg_printf_attr(0, "Description: %s\n", unibi_get_name(ut));
  const char **a = unibi_get_aliases(ut);
  if (*a) {
    msg_puts("Aliases: ");
    do {
      msg_printf_attr(0, "%s%s\n", *a, a[1] ? " | " : "");
      a++;
    } while (*a);
  }

  msg_puts("Boolean capabilities:\n");
  for (enum unibi_boolean i = unibi_boolean_begin_ + 1;
       i < unibi_boolean_end_; i++) {
    msg_printf_attr(0, "  %-25s %-10s = %s\n", unibi_name_bool(i),
                    unibi_short_name_bool(i),
                    unibi_get_bool(ut, i) ? "true" : "false");
  }

  msg_puts("Numeric capabilities:\n");
  for (enum unibi_numeric i = unibi_numeric_begin_ + 1;
       i < unibi_numeric_end_; i++) {
    int n = unibi_get_num(ut, i);  // -1 means "empty"
    msg_printf_attr(0, "  %-25s %-10s = %d\n", unibi_name_num(i),
                    unibi_short_name_num(i), n);
  }

  msg_puts("String capabilities:\n");
  for (enum unibi_string i = unibi_string_begin_ + 1;
       i < unibi_string_end_; i++) {
    const char *s = unibi_get_str(ut, i);
    if (s) {
      msg_printf_attr(0, "  %-25s %-10s = ", unibi_name_str(i),
                      unibi_short_name_str(i));
      // Most of these strings will contain escape sequences.
      msg_outtrans_special((char_u *)s, false);
      msg_putchar('\n');
    }
  }

  if (unibi_count_ext_bool(ut)) {
    msg_puts("Extended boolean capabilities:\n");
    for (size_t i = 0; i < unibi_count_ext_bool(ut); i++) {
      msg_printf_attr(0, "  %-25s = %s\n",
                      unibi_get_ext_bool_name(ut, i),
                      unibi_get_ext_bool(ut, i) ? "true" : "false");
    }
  }

  if (unibi_count_ext_num(ut)) {
    msg_puts("Extended numeric capabilities:\n");
    for (size_t i = 0; i < unibi_count_ext_num(ut); i++) {
      msg_printf_attr(0, "  %-25s = %d\n",
                      unibi_get_ext_num_name(ut, i),
                      unibi_get_ext_num(ut, i));
    }
  }

  if (unibi_count_ext_str(ut)) {
    msg_puts("Extended string capabilities:\n");
    for (size_t i = 0; i < unibi_count_ext_str(ut); i++) {
      msg_printf_attr(0, "  %-25s = ", unibi_get_ext_str_name(ut, i));
      msg_outtrans_special((char_u *)unibi_get_ext_str(ut, i), false);
      msg_putchar('\n');
    }
  }

  msg_puts("}}}\n");
  xfree(term);
}
Пример #7
0
/*
 * List string items nicely aligned in columns.
 * When "size" is < 0 then the last entry is marked with NULL.
 * The entry with index "current" is inclosed in [].
 */
    void
list_in_columns(char_u **items, int size, int current)
{
    int		i;
    int		ncol;
    int		nrow;
    int		item_count = 0;
    int		width = 0;

    /* Find the length of the longest item, use that + 1 as the column
     * width. */
    for (i = 0; size < 0 ? items[i] != NULL : i < size; ++i)
    {
	int l = (int)vim_strsize(items[i]) + (i == current ? 2 : 0);

	if (l > width)
	    width = l;
	++item_count;
    }
    width += 1;

    if (Columns < width)
    {
	/* Not enough screen columns - show one per line */
	for (i = 0; i < item_count; ++i)
	{
	    version_msg_wrap(items[i], i == current);
	    if (msg_col > 0)
		msg_putchar('\n');
	}
	return;
    }

    /* The rightmost column doesn't need a separator.
     * Sacrifice it to fit in one more column if possible. */
    ncol = (int) (Columns + 1) / width;
    nrow = item_count / ncol + (item_count % ncol ? 1 : 0);

    /* i counts columns then rows.  idx counts rows then columns. */
    for (i = 0; !got_int && i < nrow * ncol; ++i)
    {
	int idx = (i / ncol) + (i % ncol) * nrow;

	if (idx < item_count)
	{
	    int last_col = (i + 1) % ncol == 0;

	    if (idx == current)
		msg_putchar('[');
	    msg_puts(items[idx]);
	    if (idx == current)
		msg_putchar(']');
	    if (last_col)
	    {
		if (msg_col > 0)
		    msg_putchar('\n');
	    }
	    else
	    {
		while (msg_col % width)
		    msg_putchar(' ');
	    }
	}
	else
	{
	    if (msg_col > 0)
		msg_putchar('\n');
	}
    }
}