mirror of
https://github.com/neovim/neovim.git
synced 2024-12-24 13:15:09 -07:00
vim-patch:partial:8.1.0914: code related to findfile() is spread out (#30000)
Problem: Code related to findfile() is spread out.
Solution: Put findfile() related code into a new source file. (Yegappan
Lakshmanan, closes vim/vim#3934)
5fd0f5052f
Keep functions related to wildcard expansion in path.c, as in Vim they
are now spread out among multiple files, which isn't really ideal.
This commit is contained in:
parent
0c99ce0e89
commit
11a6f3c930
@ -52,7 +52,9 @@
|
|||||||
#include "nvim/ascii_defs.h"
|
#include "nvim/ascii_defs.h"
|
||||||
#include "nvim/autocmd.h"
|
#include "nvim/autocmd.h"
|
||||||
#include "nvim/autocmd_defs.h"
|
#include "nvim/autocmd_defs.h"
|
||||||
#include "nvim/buffer_defs.h"
|
#include "nvim/charset.h"
|
||||||
|
#include "nvim/cursor.h"
|
||||||
|
#include "nvim/errors.h"
|
||||||
#include "nvim/eval.h"
|
#include "nvim/eval.h"
|
||||||
#include "nvim/eval/typval.h"
|
#include "nvim/eval/typval.h"
|
||||||
#include "nvim/eval/typval_defs.h"
|
#include "nvim/eval/typval_defs.h"
|
||||||
@ -63,6 +65,7 @@
|
|||||||
#include "nvim/mbyte.h"
|
#include "nvim/mbyte.h"
|
||||||
#include "nvim/memory.h"
|
#include "nvim/memory.h"
|
||||||
#include "nvim/message.h"
|
#include "nvim/message.h"
|
||||||
|
#include "nvim/normal.h"
|
||||||
#include "nvim/option.h"
|
#include "nvim/option.h"
|
||||||
#include "nvim/option_vars.h"
|
#include "nvim/option_vars.h"
|
||||||
#include "nvim/os/fs.h"
|
#include "nvim/os/fs.h"
|
||||||
@ -1503,6 +1506,225 @@ theend:
|
|||||||
return file_name;
|
return file_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the file name at the cursor.
|
||||||
|
/// If Visual mode is active, use the selected text if it's in one line.
|
||||||
|
/// Returns the name in allocated memory, NULL for failure.
|
||||||
|
char *grab_file_name(int count, linenr_T *file_lnum)
|
||||||
|
{
|
||||||
|
int options = FNAME_MESS | FNAME_EXP | FNAME_REL | FNAME_UNESC;
|
||||||
|
if (VIsual_active) {
|
||||||
|
size_t len;
|
||||||
|
char *ptr;
|
||||||
|
if (get_visual_text(NULL, &ptr, &len) == FAIL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// Only recognize ":123" here
|
||||||
|
if (file_lnum != NULL && ptr[len] == ':' && isdigit((uint8_t)ptr[len + 1])) {
|
||||||
|
char *p = ptr + len + 1;
|
||||||
|
|
||||||
|
*file_lnum = getdigits_int32(&p, false, 0);
|
||||||
|
}
|
||||||
|
return find_file_name_in_path(ptr, len, options, count, curbuf->b_ffname);
|
||||||
|
}
|
||||||
|
return file_name_at_cursor(options | FNAME_HYP, count, file_lnum);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the file name under or after the cursor.
|
||||||
|
///
|
||||||
|
/// The 'path' option is searched if the file name is not absolute.
|
||||||
|
/// The string returned has been alloc'ed and should be freed by the caller.
|
||||||
|
/// NULL is returned if the file name or file is not found.
|
||||||
|
///
|
||||||
|
/// options:
|
||||||
|
/// FNAME_MESS give error messages
|
||||||
|
/// FNAME_EXP expand to path
|
||||||
|
/// FNAME_HYP check for hypertext link
|
||||||
|
/// FNAME_INCL apply "includeexpr"
|
||||||
|
char *file_name_at_cursor(int options, int count, linenr_T *file_lnum)
|
||||||
|
{
|
||||||
|
return file_name_in_line(get_cursor_line_ptr(),
|
||||||
|
curwin->w_cursor.col, options, count, curbuf->b_ffname,
|
||||||
|
file_lnum);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @param rel_fname file we are searching relative to
|
||||||
|
/// @param file_lnum line number after the file name
|
||||||
|
///
|
||||||
|
/// @return the name of the file under or after ptr[col].
|
||||||
|
///
|
||||||
|
/// Otherwise like file_name_at_cursor().
|
||||||
|
char *file_name_in_line(char *line, int col, int options, int count, char *rel_fname,
|
||||||
|
linenr_T *file_lnum)
|
||||||
|
{
|
||||||
|
// search forward for what could be the start of a file name
|
||||||
|
char *ptr = line + col;
|
||||||
|
while (*ptr != NUL && !vim_isfilec((uint8_t)(*ptr))) {
|
||||||
|
MB_PTR_ADV(ptr);
|
||||||
|
}
|
||||||
|
if (*ptr == NUL) { // nothing found
|
||||||
|
if (options & FNAME_MESS) {
|
||||||
|
emsg(_("E446: No file name under cursor"));
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t len;
|
||||||
|
bool in_type = true;
|
||||||
|
bool is_url = false;
|
||||||
|
|
||||||
|
// Search backward for first char of the file name.
|
||||||
|
// Go one char back to ":" before "//", or to the drive letter before ":\" (even if ":"
|
||||||
|
// is not in 'isfname').
|
||||||
|
while (ptr > line) {
|
||||||
|
if ((len = (size_t)(utf_head_off(line, ptr - 1))) > 0) {
|
||||||
|
ptr -= len + 1;
|
||||||
|
} else if (vim_isfilec((uint8_t)ptr[-1]) || ((options & FNAME_HYP) && path_is_url(ptr - 1))) {
|
||||||
|
ptr--;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search forward for the last char of the file name.
|
||||||
|
// Also allow ":/" when ':' is not in 'isfname'.
|
||||||
|
len = path_has_drive_letter(ptr) ? 2 : 0;
|
||||||
|
while (vim_isfilec((uint8_t)ptr[len]) || (ptr[len] == '\\' && ptr[len + 1] == ' ')
|
||||||
|
|| ((options & FNAME_HYP) && path_is_url(ptr + len))
|
||||||
|
|| (is_url && vim_strchr(":?&=", (uint8_t)ptr[len]) != NULL)) {
|
||||||
|
// After type:// we also include :, ?, & and = as valid characters, so that
|
||||||
|
// http://google.com:8080?q=this&that=ok works.
|
||||||
|
if ((ptr[len] >= 'A' && ptr[len] <= 'Z') || (ptr[len] >= 'a' && ptr[len] <= 'z')) {
|
||||||
|
if (in_type && path_is_url(ptr + len + 1)) {
|
||||||
|
is_url = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
in_type = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr[len] == '\\' && ptr[len + 1] == ' ') {
|
||||||
|
// Skip over the "\" in "\ ".
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
len += (size_t)(utfc_ptr2len(ptr + len));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is trailing punctuation, remove it.
|
||||||
|
// But don't remove "..", could be a directory name.
|
||||||
|
if (len > 2 && vim_strchr(".,:;!", (uint8_t)ptr[len - 1]) != NULL
|
||||||
|
&& ptr[len - 2] != '.') {
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_lnum != NULL) {
|
||||||
|
const char *line_english = " line ";
|
||||||
|
const char *line_transl = _(line_msg);
|
||||||
|
|
||||||
|
// Get the number after the file name and a separator character.
|
||||||
|
// Also accept " line 999" with and without the same translation as
|
||||||
|
// used in last_set_msg().
|
||||||
|
char *p = ptr + len;
|
||||||
|
if (strncmp(p, line_english, strlen(line_english)) == 0) {
|
||||||
|
p += strlen(line_english);
|
||||||
|
} else if (strncmp(p, line_transl, strlen(line_transl)) == 0) {
|
||||||
|
p += strlen(line_transl);
|
||||||
|
} else {
|
||||||
|
p = skipwhite(p);
|
||||||
|
}
|
||||||
|
if (*p != NUL) {
|
||||||
|
if (!isdigit((uint8_t)(*p))) {
|
||||||
|
p++; // skip the separator
|
||||||
|
}
|
||||||
|
p = skipwhite(p);
|
||||||
|
if (isdigit((uint8_t)(*p))) {
|
||||||
|
*file_lnum = (linenr_T)getdigits_long(&p, false, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return find_file_name_in_path(ptr, len, options, count, rel_fname);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *eval_includeexpr(const char *const ptr, const size_t len)
|
||||||
|
{
|
||||||
|
const sctx_T save_sctx = current_sctx;
|
||||||
|
set_vim_var_string(VV_FNAME, ptr, (ptrdiff_t)len);
|
||||||
|
current_sctx = curbuf->b_p_script_ctx[BV_INEX].script_ctx;
|
||||||
|
|
||||||
|
char *res = eval_to_string_safe(curbuf->b_p_inex,
|
||||||
|
was_set_insecurely(curwin, kOptIncludeexpr, OPT_LOCAL),
|
||||||
|
true);
|
||||||
|
|
||||||
|
set_vim_var_string(VV_FNAME, NULL, 0);
|
||||||
|
current_sctx = save_sctx;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the name of the file ptr[len] in 'path'.
|
||||||
|
/// Otherwise like file_name_at_cursor().
|
||||||
|
///
|
||||||
|
/// @param rel_fname file we are searching relative to
|
||||||
|
char *find_file_name_in_path(char *ptr, size_t len, int options, long count, char *rel_fname)
|
||||||
|
{
|
||||||
|
char *file_name;
|
||||||
|
char *tofree = NULL;
|
||||||
|
|
||||||
|
if (len == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((options & FNAME_INCL) && *curbuf->b_p_inex != NUL) {
|
||||||
|
tofree = eval_includeexpr(ptr, len);
|
||||||
|
if (tofree != NULL) {
|
||||||
|
ptr = tofree;
|
||||||
|
len = strlen(ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options & FNAME_EXP) {
|
||||||
|
char *file_to_find = NULL;
|
||||||
|
char *search_ctx = NULL;
|
||||||
|
|
||||||
|
file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS,
|
||||||
|
true, rel_fname, &file_to_find, &search_ctx);
|
||||||
|
|
||||||
|
// If the file could not be found in a normal way, try applying
|
||||||
|
// 'includeexpr' (unless done already).
|
||||||
|
if (file_name == NULL
|
||||||
|
&& !(options & FNAME_INCL) && *curbuf->b_p_inex != NUL) {
|
||||||
|
tofree = eval_includeexpr(ptr, len);
|
||||||
|
if (tofree != NULL) {
|
||||||
|
ptr = tofree;
|
||||||
|
len = strlen(ptr);
|
||||||
|
file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS,
|
||||||
|
true, rel_fname, &file_to_find, &search_ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (file_name == NULL && (options & FNAME_MESS)) {
|
||||||
|
char c = ptr[len];
|
||||||
|
ptr[len] = NUL;
|
||||||
|
semsg(_("E447: Can't find file \"%s\" in path"), ptr);
|
||||||
|
ptr[len] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Repeat finding the file "count" times. This matters when it
|
||||||
|
// appears several times in the path.
|
||||||
|
while (file_name != NULL && --count > 0) {
|
||||||
|
xfree(file_name);
|
||||||
|
file_name = find_file_in_path(ptr, len, options, false, rel_fname,
|
||||||
|
&file_to_find, &search_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
xfree(file_to_find);
|
||||||
|
vim_findfile_cleanup(search_ctx);
|
||||||
|
} else {
|
||||||
|
file_name = xstrnsave(ptr, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
xfree(tofree);
|
||||||
|
|
||||||
|
return file_name;
|
||||||
|
}
|
||||||
|
|
||||||
void do_autocmd_dirchanged(char *new_dir, CdScope scope, CdCause cause, bool pre)
|
void do_autocmd_dirchanged(char *new_dir, CdScope scope, CdCause cause, bool pre)
|
||||||
{
|
{
|
||||||
static bool recursive = false;
|
static bool recursive = false;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <stddef.h> // IWYU pragma: keep
|
#include <stddef.h> // IWYU pragma: keep
|
||||||
|
|
||||||
|
#include "nvim/pos_defs.h" // IWYU pragma: keep
|
||||||
#include "nvim/types_defs.h" // IWYU pragma: keep
|
#include "nvim/types_defs.h" // IWYU pragma: keep
|
||||||
#include "nvim/vim_defs.h" // IWYU pragma: keep
|
#include "nvim/vim_defs.h" // IWYU pragma: keep
|
||||||
|
|
||||||
@ -12,6 +13,17 @@ enum {
|
|||||||
FINDFILE_BOTH = 2, ///< files and directories
|
FINDFILE_BOTH = 2, ///< files and directories
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Values for file_name_in_line()
|
||||||
|
enum {
|
||||||
|
FNAME_MESS = 1, ///< give error message
|
||||||
|
FNAME_EXP = 2, ///< expand to path
|
||||||
|
FNAME_HYP = 4, ///< check for hypertext link
|
||||||
|
FNAME_INCL = 8, ///< apply 'includeexpr'
|
||||||
|
FNAME_REL = 16, ///< ".." and "./" are relative to the (current)
|
||||||
|
///< file instead of the current directory
|
||||||
|
FNAME_UNESC = 32, ///< remove backslashes used for escaping
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "file_search.h.generated.h"
|
# include "file_search.h.generated.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include "nvim/ex_docmd.h"
|
#include "nvim/ex_docmd.h"
|
||||||
#include "nvim/ex_eval.h"
|
#include "nvim/ex_eval.h"
|
||||||
#include "nvim/ex_getln.h"
|
#include "nvim/ex_getln.h"
|
||||||
|
#include "nvim/file_search.h"
|
||||||
#include "nvim/fileio.h"
|
#include "nvim/fileio.h"
|
||||||
#include "nvim/fold.h"
|
#include "nvim/fold.h"
|
||||||
#include "nvim/getchar.h"
|
#include "nvim/getchar.h"
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "nvim/ex_cmds_defs.h"
|
#include "nvim/ex_cmds_defs.h"
|
||||||
#include "nvim/ex_getln.h"
|
#include "nvim/ex_getln.h"
|
||||||
#include "nvim/extmark.h"
|
#include "nvim/extmark.h"
|
||||||
|
#include "nvim/file_search.h"
|
||||||
#include "nvim/fold.h"
|
#include "nvim/fold.h"
|
||||||
#include "nvim/garray.h"
|
#include "nvim/garray.h"
|
||||||
#include "nvim/garray_defs.h"
|
#include "nvim/garray_defs.h"
|
||||||
|
@ -8,23 +8,17 @@
|
|||||||
|
|
||||||
#include "auto/config.h"
|
#include "auto/config.h"
|
||||||
#include "nvim/ascii_defs.h"
|
#include "nvim/ascii_defs.h"
|
||||||
#include "nvim/buffer_defs.h"
|
|
||||||
#include "nvim/charset.h"
|
#include "nvim/charset.h"
|
||||||
#include "nvim/cmdexpand.h"
|
#include "nvim/cmdexpand.h"
|
||||||
#include "nvim/eval.h"
|
#include "nvim/eval.h"
|
||||||
#include "nvim/eval/typval_defs.h"
|
|
||||||
#include "nvim/ex_docmd.h"
|
#include "nvim/ex_docmd.h"
|
||||||
#include "nvim/file_search.h"
|
|
||||||
#include "nvim/fileio.h"
|
#include "nvim/fileio.h"
|
||||||
#include "nvim/garray.h"
|
#include "nvim/garray.h"
|
||||||
#include "nvim/gettext_defs.h"
|
|
||||||
#include "nvim/globals.h"
|
#include "nvim/globals.h"
|
||||||
#include "nvim/macros_defs.h"
|
#include "nvim/macros_defs.h"
|
||||||
#include "nvim/mbyte.h"
|
#include "nvim/mbyte.h"
|
||||||
#include "nvim/memory.h"
|
#include "nvim/memory.h"
|
||||||
#include "nvim/message.h"
|
|
||||||
#include "nvim/option.h"
|
#include "nvim/option.h"
|
||||||
#include "nvim/option_defs.h"
|
|
||||||
#include "nvim/option_vars.h"
|
#include "nvim/option_vars.h"
|
||||||
#include "nvim/os/fs.h"
|
#include "nvim/os/fs.h"
|
||||||
#include "nvim/os/fs_defs.h"
|
#include "nvim/os/fs_defs.h"
|
||||||
@ -37,7 +31,6 @@
|
|||||||
#include "nvim/regexp_defs.h"
|
#include "nvim/regexp_defs.h"
|
||||||
#include "nvim/strings.h"
|
#include "nvim/strings.h"
|
||||||
#include "nvim/vim_defs.h"
|
#include "nvim/vim_defs.h"
|
||||||
#include "nvim/window.h"
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
URL_SLASH = 1, // path_is_url() has found ":/"
|
URL_SLASH = 1, // path_is_url() has found ":/"
|
||||||
@ -1687,87 +1680,6 @@ void simplify_filename(char *filename)
|
|||||||
} while (*p != NUL);
|
} while (*p != NUL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *eval_includeexpr(const char *const ptr, const size_t len)
|
|
||||||
{
|
|
||||||
const sctx_T save_sctx = current_sctx;
|
|
||||||
set_vim_var_string(VV_FNAME, ptr, (ptrdiff_t)len);
|
|
||||||
current_sctx = curbuf->b_p_script_ctx[BV_INEX].script_ctx;
|
|
||||||
|
|
||||||
char *res = eval_to_string_safe(curbuf->b_p_inex,
|
|
||||||
was_set_insecurely(curwin, kOptIncludeexpr, OPT_LOCAL),
|
|
||||||
true);
|
|
||||||
|
|
||||||
set_vim_var_string(VV_FNAME, NULL, 0);
|
|
||||||
current_sctx = save_sctx;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the name of the file ptr[len] in 'path'.
|
|
||||||
/// Otherwise like file_name_at_cursor().
|
|
||||||
///
|
|
||||||
/// @param rel_fname file we are searching relative to
|
|
||||||
char *find_file_name_in_path(char *ptr, size_t len, int options, long count, char *rel_fname)
|
|
||||||
{
|
|
||||||
char *file_name;
|
|
||||||
char *tofree = NULL;
|
|
||||||
|
|
||||||
if (len == 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((options & FNAME_INCL) && *curbuf->b_p_inex != NUL) {
|
|
||||||
tofree = eval_includeexpr(ptr, len);
|
|
||||||
if (tofree != NULL) {
|
|
||||||
ptr = tofree;
|
|
||||||
len = strlen(ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options & FNAME_EXP) {
|
|
||||||
char *file_to_find = NULL;
|
|
||||||
char *search_ctx = NULL;
|
|
||||||
|
|
||||||
file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS,
|
|
||||||
true, rel_fname, &file_to_find, &search_ctx);
|
|
||||||
|
|
||||||
// If the file could not be found in a normal way, try applying
|
|
||||||
// 'includeexpr' (unless done already).
|
|
||||||
if (file_name == NULL
|
|
||||||
&& !(options & FNAME_INCL) && *curbuf->b_p_inex != NUL) {
|
|
||||||
tofree = eval_includeexpr(ptr, len);
|
|
||||||
if (tofree != NULL) {
|
|
||||||
ptr = tofree;
|
|
||||||
len = strlen(ptr);
|
|
||||||
file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS,
|
|
||||||
true, rel_fname, &file_to_find, &search_ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (file_name == NULL && (options & FNAME_MESS)) {
|
|
||||||
char c = ptr[len];
|
|
||||||
ptr[len] = NUL;
|
|
||||||
semsg(_("E447: Can't find file \"%s\" in path"), ptr);
|
|
||||||
ptr[len] = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Repeat finding the file "count" times. This matters when it
|
|
||||||
// appears several times in the path.
|
|
||||||
while (file_name != NULL && --count > 0) {
|
|
||||||
xfree(file_name);
|
|
||||||
file_name = find_file_in_path(ptr, len, options, false, rel_fname,
|
|
||||||
&file_to_find, &search_ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
xfree(file_to_find);
|
|
||||||
vim_findfile_cleanup(search_ctx);
|
|
||||||
} else {
|
|
||||||
file_name = xstrnsave(ptr, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
xfree(tofree);
|
|
||||||
|
|
||||||
return file_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks for a Windows drive letter ("C:/") at the start of the path.
|
/// Checks for a Windows drive letter ("C:/") at the start of the path.
|
||||||
///
|
///
|
||||||
/// @see https://url.spec.whatwg.org/#start-with-a-windows-drive-letter
|
/// @see https://url.spec.whatwg.org/#start-with-a-windows-drive-letter
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "nvim/ex_cmds_defs.h"
|
#include "nvim/ex_cmds_defs.h"
|
||||||
#include "nvim/ex_docmd.h"
|
#include "nvim/ex_docmd.h"
|
||||||
#include "nvim/ex_getln.h"
|
#include "nvim/ex_getln.h"
|
||||||
|
#include "nvim/file_search.h"
|
||||||
#include "nvim/fileio.h"
|
#include "nvim/fileio.h"
|
||||||
#include "nvim/fold.h"
|
#include "nvim/fold.h"
|
||||||
#include "nvim/garray.h"
|
#include "nvim/garray.h"
|
||||||
|
@ -6837,142 +6837,6 @@ static void frame_add_height(frame_T *frp, int n)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the file name at the cursor.
|
|
||||||
// If Visual mode is active, use the selected text if it's in one line.
|
|
||||||
// Returns the name in allocated memory, NULL for failure.
|
|
||||||
char *grab_file_name(int count, linenr_T *file_lnum)
|
|
||||||
{
|
|
||||||
int options = FNAME_MESS | FNAME_EXP | FNAME_REL | FNAME_UNESC;
|
|
||||||
if (VIsual_active) {
|
|
||||||
size_t len;
|
|
||||||
char *ptr;
|
|
||||||
if (get_visual_text(NULL, &ptr, &len) == FAIL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
// Only recognize ":123" here
|
|
||||||
if (file_lnum != NULL && ptr[len] == ':' && isdigit((uint8_t)ptr[len + 1])) {
|
|
||||||
char *p = ptr + len + 1;
|
|
||||||
|
|
||||||
*file_lnum = getdigits_int32(&p, false, 0);
|
|
||||||
}
|
|
||||||
return find_file_name_in_path(ptr, len, options, count, curbuf->b_ffname);
|
|
||||||
}
|
|
||||||
return file_name_at_cursor(options | FNAME_HYP, count, file_lnum);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the file name under or after the cursor.
|
|
||||||
//
|
|
||||||
// The 'path' option is searched if the file name is not absolute.
|
|
||||||
// The string returned has been alloc'ed and should be freed by the caller.
|
|
||||||
// NULL is returned if the file name or file is not found.
|
|
||||||
//
|
|
||||||
// options:
|
|
||||||
// FNAME_MESS give error messages
|
|
||||||
// FNAME_EXP expand to path
|
|
||||||
// FNAME_HYP check for hypertext link
|
|
||||||
// FNAME_INCL apply "includeexpr"
|
|
||||||
char *file_name_at_cursor(int options, int count, linenr_T *file_lnum)
|
|
||||||
{
|
|
||||||
return file_name_in_line(get_cursor_line_ptr(),
|
|
||||||
curwin->w_cursor.col, options, count, curbuf->b_ffname,
|
|
||||||
file_lnum);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @param rel_fname file we are searching relative to
|
|
||||||
/// @param file_lnum line number after the file name
|
|
||||||
///
|
|
||||||
/// @return the name of the file under or after ptr[col]. Otherwise like file_name_at_cursor().
|
|
||||||
char *file_name_in_line(char *line, int col, int options, int count, char *rel_fname,
|
|
||||||
linenr_T *file_lnum)
|
|
||||||
{
|
|
||||||
// search forward for what could be the start of a file name
|
|
||||||
char *ptr = line + col;
|
|
||||||
while (*ptr != NUL && !vim_isfilec((uint8_t)(*ptr))) {
|
|
||||||
MB_PTR_ADV(ptr);
|
|
||||||
}
|
|
||||||
if (*ptr == NUL) { // nothing found
|
|
||||||
if (options & FNAME_MESS) {
|
|
||||||
emsg(_("E446: No file name under cursor"));
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t len;
|
|
||||||
bool in_type = true;
|
|
||||||
bool is_url = false;
|
|
||||||
|
|
||||||
// Search backward for first char of the file name.
|
|
||||||
// Go one char back to ":" before "//", or to the drive letter before ":\" (even if ":"
|
|
||||||
// is not in 'isfname').
|
|
||||||
while (ptr > line) {
|
|
||||||
if ((len = (size_t)(utf_head_off(line, ptr - 1))) > 0) {
|
|
||||||
ptr -= len + 1;
|
|
||||||
} else if (vim_isfilec((uint8_t)ptr[-1]) || ((options & FNAME_HYP) && path_is_url(ptr - 1))) {
|
|
||||||
ptr--;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search forward for the last char of the file name.
|
|
||||||
// Also allow ":/" when ':' is not in 'isfname'.
|
|
||||||
len = path_has_drive_letter(ptr) ? 2 : 0;
|
|
||||||
while (vim_isfilec((uint8_t)ptr[len]) || (ptr[len] == '\\' && ptr[len + 1] == ' ')
|
|
||||||
|| ((options & FNAME_HYP) && path_is_url(ptr + len))
|
|
||||||
|| (is_url && vim_strchr(":?&=", (uint8_t)ptr[len]) != NULL)) {
|
|
||||||
// After type:// we also include :, ?, & and = as valid characters, so that
|
|
||||||
// http://google.com:8080?q=this&that=ok works.
|
|
||||||
if ((ptr[len] >= 'A' && ptr[len] <= 'Z') || (ptr[len] >= 'a' && ptr[len] <= 'z')) {
|
|
||||||
if (in_type && path_is_url(ptr + len + 1)) {
|
|
||||||
is_url = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
in_type = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ptr[len] == '\\' && ptr[len + 1] == ' ') {
|
|
||||||
// Skip over the "\" in "\ ".
|
|
||||||
len++;
|
|
||||||
}
|
|
||||||
len += (size_t)(utfc_ptr2len(ptr + len));
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there is trailing punctuation, remove it.
|
|
||||||
// But don't remove "..", could be a directory name.
|
|
||||||
if (len > 2 && vim_strchr(".,:;!", (uint8_t)ptr[len - 1]) != NULL
|
|
||||||
&& ptr[len - 2] != '.') {
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file_lnum != NULL) {
|
|
||||||
const char *line_english = " line ";
|
|
||||||
const char *line_transl = _(line_msg);
|
|
||||||
|
|
||||||
// Get the number after the file name and a separator character.
|
|
||||||
// Also accept " line 999" with and without the same translation as
|
|
||||||
// used in last_set_msg().
|
|
||||||
char *p = ptr + len;
|
|
||||||
if (strncmp(p, line_english, strlen(line_english)) == 0) {
|
|
||||||
p += strlen(line_english);
|
|
||||||
} else if (strncmp(p, line_transl, strlen(line_transl)) == 0) {
|
|
||||||
p += strlen(line_transl);
|
|
||||||
} else {
|
|
||||||
p = skipwhite(p);
|
|
||||||
}
|
|
||||||
if (*p != NUL) {
|
|
||||||
if (!isdigit((uint8_t)(*p))) {
|
|
||||||
p++; // skip the separator
|
|
||||||
}
|
|
||||||
p = skipwhite(p);
|
|
||||||
if (isdigit((uint8_t)(*p))) {
|
|
||||||
*file_lnum = (linenr_T)getdigits_long(&p, false, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return find_file_name_in_path(ptr, len, options, count, rel_fname);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add or remove a status line from window(s), according to the
|
/// Add or remove a status line from window(s), according to the
|
||||||
/// value of 'laststatus'.
|
/// value of 'laststatus'.
|
||||||
///
|
///
|
||||||
|
@ -8,17 +8,6 @@
|
|||||||
#include "nvim/option_defs.h" // IWYU pragma: keep
|
#include "nvim/option_defs.h" // IWYU pragma: keep
|
||||||
#include "nvim/types_defs.h" // IWYU pragma: keep
|
#include "nvim/types_defs.h" // IWYU pragma: keep
|
||||||
|
|
||||||
/// Values for file_name_in_line()
|
|
||||||
enum {
|
|
||||||
FNAME_MESS = 1, ///< give error message
|
|
||||||
FNAME_EXP = 2, ///< expand to path
|
|
||||||
FNAME_HYP = 4, ///< check for hypertext link
|
|
||||||
FNAME_INCL = 8, ///< apply 'includeexpr'
|
|
||||||
FNAME_REL = 16, ///< ".." and "./" are relative to the (current)
|
|
||||||
///< file instead of the current directory
|
|
||||||
FNAME_UNESC = 32, ///< remove backslashes used for escaping
|
|
||||||
};
|
|
||||||
|
|
||||||
/// arguments for win_split()
|
/// arguments for win_split()
|
||||||
enum {
|
enum {
|
||||||
WSP_ROOM = 0x01, ///< require enough room
|
WSP_ROOM = 0x01, ///< require enough room
|
||||||
|
Loading…
Reference in New Issue
Block a user