aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/buffer_defs.h3
-rw-r--r--src/nvim/eval.c4
-rw-r--r--src/nvim/event/libuv_process.h5
-rw-r--r--src/nvim/ex_docmd.c29
-rw-r--r--src/nvim/file_search.c30
-rw-r--r--src/nvim/fold.c24
-rw-r--r--src/nvim/getchar.c71
-rw-r--r--src/nvim/memline.c2
-rw-r--r--src/nvim/memory.c7
-rw-r--r--src/nvim/ops.c49
-rw-r--r--src/nvim/option.c2
-rw-r--r--src/nvim/terminal.c1
-rw-r--r--src/nvim/testdir/test_fold.vim16
-rw-r--r--src/nvim/window.c41
14 files changed, 151 insertions, 133 deletions
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index a1b5633c32..3e9767adde 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -825,8 +825,7 @@ struct tabpage_S {
frame_T *(tp_snapshot[SNAP_COUNT]); ///< window layout snapshots
dictitem_T tp_winvar; ///< variable for "t:" Dictionary
dict_T *tp_vars; ///< internal variables, local to tab page
- char_u *localdir; ///< Absolute path of local directory or
- ///< NULL
+ char_u *tp_localdir; ///< Absolute path of local CWD or NULL
};
/*
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 6dc7e5606e..78f470b10a 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -10901,7 +10901,7 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
case kCdScopeTab: // FALLTHROUGH
assert(tp);
- from = tp->localdir;
+ from = tp->tp_localdir;
if (from) {
break;
}
@@ -12015,7 +12015,7 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
break;
case kCdScopeTab:
assert(tp);
- rettv->vval.v_number = tp->localdir ? 1 : 0;
+ rettv->vval.v_number = tp->tp_localdir ? 1 : 0;
break;
case kCdScopeGlobal:
// The global scope never has a local directory
diff --git a/src/nvim/event/libuv_process.h b/src/nvim/event/libuv_process.h
index aaaa896e10..1132ce79ca 100644
--- a/src/nvim/event/libuv_process.h
+++ b/src/nvim/event/libuv_process.h
@@ -14,8 +14,9 @@ typedef struct libuv_process {
static inline LibuvProcess libuv_process_init(Loop *loop, void *data)
{
- LibuvProcess rv;
- rv.process = process_init(loop, kProcessTypeUv, data);
+ LibuvProcess rv = {
+ .process = process_init(loop, kProcessTypeUv, data)
+ };
return rv;
}
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 87b6959101..774380b2f0 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -6943,24 +6943,27 @@ void free_cd_dir(void)
/// @param scope Scope of the function call (global, tab or window).
void post_chdir(CdScope scope)
{
- // The local directory of the current window is always overwritten.
+ // Always overwrite the window-local CWD.
xfree(curwin->w_localdir);
curwin->w_localdir = NULL;
- // Overwrite the local directory of the current tab page for `cd` and `tcd`
+ // Overwrite the tab-local CWD for :cd, :tcd.
if (scope >= kCdScopeTab) {
- xfree(curtab->localdir);
- curtab->localdir = NULL;
+ xfree(curtab->tp_localdir);
+ curtab->tp_localdir = NULL;
}
if (scope < kCdScopeGlobal) {
- // If still in global directory, need to remember current directory as
- // global directory.
+ // If still in global directory, set CWD as the global directory.
if (globaldir == NULL && prev_dir != NULL) {
globaldir = vim_strsave(prev_dir);
}
}
+ char cwd[MAXPATHL];
+ if (os_dirname((char_u *)cwd, MAXPATHL) != OK) {
+ return;
+ }
switch (scope) {
case kCdScopeGlobal:
// We are now in the global directory, no need to remember its name.
@@ -6968,23 +6971,17 @@ void post_chdir(CdScope scope)
globaldir = NULL;
break;
case kCdScopeTab:
- // Remember this local directory for the tab page.
- if (os_dirname(NameBuff, MAXPATHL) == OK) {
- curtab->localdir = vim_strsave(NameBuff);
- }
+ curtab->tp_localdir = (char_u *)xstrdup(cwd);
break;
case kCdScopeWindow:
- // Remember this local directory for the window.
- if (os_dirname(NameBuff, MAXPATHL) == OK) {
- curwin->w_localdir = vim_strsave(NameBuff);
- }
+ curwin->w_localdir = (char_u *)xstrdup(cwd);
break;
case kCdScopeInvalid:
- // We should never get here
assert(false);
}
- shorten_fnames(TRUE);
+ shorten_fnames(true);
+ do_autocmd_dirchanged(cwd, scope);
}
/// `:cd`, `:tcd`, `:lcd`, `:chdir`, `:tchdir` and `:lchdir`.
diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c
index 79a39c6503..b73d9944ce 100644
--- a/src/nvim/file_search.c
+++ b/src/nvim/file_search.c
@@ -1519,7 +1519,7 @@ theend:
return file_name;
}
-static void do_autocmd_dirchanged(char_u *new_dir, CdScope scope)
+void do_autocmd_dirchanged(char *new_dir, CdScope scope)
{
static bool recursive = false;
@@ -1550,10 +1550,11 @@ static void do_autocmd_dirchanged(char_u *new_dir, CdScope scope)
}
dict_add_nr_str(dict, "scope", 0L, (char_u *)buf);
- dict_add_nr_str(dict, "cwd", 0L, new_dir);
+ dict_add_nr_str(dict, "cwd", 0L, (char_u *)new_dir);
dict_set_keys_readonly(dict);
- apply_autocmds(EVENT_DIRCHANGED, (char_u *)buf, new_dir, false, NULL);
+ apply_autocmds(EVENT_DIRCHANGED, (char_u *)buf, (char_u *)new_dir, false,
+ NULL);
dict_clear(dict);
@@ -1565,14 +1566,25 @@ static void do_autocmd_dirchanged(char_u *new_dir, CdScope scope)
/// @return OK or FAIL
int vim_chdirfile(char_u *fname)
{
- char_u dir[MAXPATHL];
+ char dir[MAXPATHL];
STRLCPY(dir, fname, MAXPATHL);
- *path_tail_with_sep(dir) = NUL;
- if (os_chdir((char *)dir) != 0) {
+ *path_tail_with_sep((char_u *)dir) = NUL;
+
+ if (os_dirname(NameBuff, sizeof(NameBuff)) != OK) {
+ NameBuff[0] = NUL;
+ }
+
+ if (os_chdir(dir) != 0) {
return FAIL;
}
- do_autocmd_dirchanged(dir, kCdScopeWindow);
+
+#ifdef BACKSLASH_IN_FILENAME
+ slash_adjust(dir);
+#endif
+ if (!strequal(dir, (char *)NameBuff)) {
+ do_autocmd_dirchanged(dir, kCdScopeWindow);
+ }
return OK;
}
@@ -1587,10 +1599,6 @@ int vim_chdir(char_u *new_dir, CdScope scope)
}
int r = os_chdir((char *)dir_name);
- if (r == 0) {
- do_autocmd_dirchanged(dir_name, scope);
- }
-
xfree(dir_name);
return r;
}
diff --git a/src/nvim/fold.c b/src/nvim/fold.c
index 1423463800..7c0283971e 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -29,6 +29,7 @@
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/undo.h"
+#include "nvim/ops.h"
/* local declarations. {{{1 */
/* typedef fold_T {{{2 */
@@ -1593,29 +1594,32 @@ static void foldCreateMarkers(linenr_T start, linenr_T end)
/*
* Add "marker[markerlen]" in 'commentstring' to line "lnum".
*/
-static void foldAddMarker(linenr_T lnum, char_u *marker, size_t markerlen)
+static void foldAddMarker(linenr_T lnum, const char_u *marker, size_t markerlen)
{
char_u *cms = curbuf->b_p_cms;
char_u *line;
char_u *newline;
char_u *p = (char_u *)strstr((char *)curbuf->b_p_cms, "%s");
+ bool line_is_comment = false;
- /* Allocate a new line: old-line + 'cms'-start + marker + 'cms'-end */
+ // Allocate a new line: old-line + 'cms'-start + marker + 'cms'-end
line = ml_get(lnum);
size_t line_len = STRLEN(line);
if (u_save(lnum - 1, lnum + 1) == OK) {
+ // Check if the line ends with an unclosed comment
+ skip_comment(line, false, false, &line_is_comment);
newline = xmalloc(line_len + markerlen + STRLEN(cms) + 1);
STRCPY(newline, line);
- if (p == NULL)
+ // Append the marker to the end of the line
+ if (p == NULL || line_is_comment) {
STRLCPY(newline + line_len, marker, markerlen + 1);
- else {
+ } else {
STRCPY(newline + line_len, cms);
memcpy(newline + line_len + (p - cms), marker, markerlen);
STRCPY(newline + line_len + (p - cms) + markerlen, p + 2);
}
-
- ml_replace(lnum, newline, FALSE);
+ ml_replace(lnum, newline, false);
}
}
@@ -2535,10 +2539,10 @@ static void foldSplit(garray_T *gap, int i, linenr_T top, linenr_T bot)
* 1 2 3
* 1 2 3
* top 2 3 4 5
- * 2 3 4 5
- * bot 2 3 4 5
- * 3 5 6
- * 3 5 6
+ * 2 3 4 5
+ * bot 2 3 4 5
+ * 3 5 6
+ * 3 5 6
*
* 1: not changed
* 2: truncate to stop above "top"
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index b7c6fd41f2..0ba0559bc1 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -1913,59 +1913,30 @@ static int vgetorpeek(int advance)
if ((mp == NULL || max_mlen >= mp_match_len)
&& keylen != KEYLEN_PART_MAP) {
- // When no matching mapping found or found a non-matching mapping
- // that matches at least what the matching mapping matched:
- // Check if we have a terminal code, when:
- // mapping is allowed,
- // keys have not been mapped,
- // and not an ESC sequence, not in insert mode,
- // and when not timed out.
- if ((no_mapping == 0 || allow_keys != 0)
- && (typebuf.tb_maplen == 0
- || (p_remap && typebuf.tb_noremap[
- typebuf.tb_off] == RM_YES))
- && !timedout) {
- keylen = 0;
- } else
- keylen = 0;
- if (keylen == 0) { /* no matching terminal code */
- /* When there was a matching mapping and no
- * termcode could be replaced after another one,
- * use that mapping (loop around). If there was
- * no mapping use the character from the
- * typeahead buffer right here. */
- if (mp == NULL) {
- /*
- * get a character: 2. from the typeahead buffer
- */
- c = typebuf.tb_buf[typebuf.tb_off] & 255;
- if (advance) { /* remove chars from tb_buf */
- cmd_silent = (typebuf.tb_silent > 0);
- if (typebuf.tb_maplen > 0)
- KeyTyped = FALSE;
- else {
- KeyTyped = TRUE;
- /* write char to script file(s) */
- gotchars(typebuf.tb_buf
- + typebuf.tb_off, 1);
- }
- KeyNoremap = typebuf.tb_noremap[
- typebuf.tb_off];
- del_typebuf(1, 0);
+ // No matching mapping found or found a non-matching mapping that
+ // matches at least what the matching mapping matched
+ keylen = 0;
+ // If there was no mapping, use the character from the typeahead
+ // buffer right here. Otherwise, use the mapping (loop around).
+ if (mp == NULL) {
+ // get a character: 2. from the typeahead buffer
+ c = typebuf.tb_buf[typebuf.tb_off] & 255;
+ if (advance) { // remove chars from tb_buf
+ cmd_silent = (typebuf.tb_silent > 0);
+ if (typebuf.tb_maplen > 0) {
+ KeyTyped = false;
+ } else {
+ KeyTyped = true;
+ // write char to script file(s)
+ gotchars(typebuf.tb_buf + typebuf.tb_off, 1);
}
- break; /* got character, break for loop */
+ KeyNoremap = typebuf.tb_noremap[typebuf.tb_off];
+ del_typebuf(1, 0);
}
- }
- if (keylen > 0) { /* full matching terminal code */
- continue; /* try mapping again */
- }
-
- /* Partial match: get some more characters. When a
- * matching mapping was found use that one. */
- if (mp == NULL || keylen < 0)
- keylen = KEYLEN_PART_KEY;
- else
+ break; // got character, break for loop
+ } else {
keylen = mp_match_len;
+ }
}
/* complete match */
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index b67f550358..1a315fce8b 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -2318,7 +2318,7 @@ ml_append_int (
*
* return FAIL for failure, OK otherwise
*/
-int ml_replace(linenr_T lnum, char_u *line, int copy)
+int ml_replace(linenr_T lnum, char_u *line, bool copy)
{
if (line == NULL) /* just checking... */
return FAIL;
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index b593936d7b..58c01fbe7a 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -475,6 +475,13 @@ void *xmemdup(const void *data, size_t len)
return memcpy(xmalloc(len), data, len);
}
+/// Returns true if strings `a` and `b` are equal. Arguments may be NULL.
+bool strequal(const char *a, const char *b)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ return (a == NULL && b == NULL) || (a && b && strcmp(a, b) == 0);
+}
+
/*
* Avoid repeating the error message many times (they take 1 second each).
* Did_outofmem_msg is reset when a character is read.
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 530193bd41..1e4d392754 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -3438,43 +3438,47 @@ dis_msg (
os_breakcheck();
}
-/*
- * If "process" is TRUE and the line begins with a comment leader (possibly
- * after some white space), return a pointer to the text after it. Put a boolean
- * value indicating whether the line ends with an unclosed comment in
- * "is_comment".
- * line - line to be processed,
- * process - if FALSE, will only check whether the line ends with an unclosed
- * comment,
- * include_space - whether to also skip space following the comment leader,
- * is_comment - will indicate whether the current line ends with an unclosed
- * comment.
- */
-static char_u *skip_comment(char_u *line, int process, int include_space, int *is_comment)
+/// If \p "process" is true and the line begins with a comment leader (possibly
+/// after some white space), return a pointer to the text after it.
+/// Put a boolean value indicating whether the line ends with an unclosed
+/// comment in "is_comment".
+///
+/// @param line - line to be processed
+/// @param process - if false, will only check whether the line ends
+/// with an unclosed comment,
+/// @param include_space - whether to skip space following the comment leader
+/// @param[out] is_comment - whether the current line ends with an unclosed
+/// comment.
+char_u *skip_comment(
+ char_u *line, bool process, bool include_space, bool *is_comment
+)
{
char_u *comment_flags = NULL;
int lead_len;
int leader_offset = get_last_leader_offset(line, &comment_flags);
- *is_comment = FALSE;
+ *is_comment = false;
if (leader_offset != -1) {
/* Let's check whether the line ends with an unclosed comment.
* If the last comment leader has COM_END in flags, there's no comment.
*/
while (*comment_flags) {
if (*comment_flags == COM_END
- || *comment_flags == ':')
+ || *comment_flags == ':') {
break;
- ++comment_flags;
+ }
+ comment_flags++;
+ }
+ if (*comment_flags != COM_END) {
+ *is_comment = true;
}
- if (*comment_flags != COM_END)
- *is_comment = TRUE;
}
- if (process == FALSE)
+ if (process == false) {
return line;
+ }
- lead_len = get_leader_len(line, &comment_flags, FALSE, include_space);
+ lead_len = get_leader_len(line, &comment_flags, false, include_space);
if (lead_len == 0)
return line;
@@ -3496,8 +3500,9 @@ static char_u *skip_comment(char_u *line, int process, int include_space, int *i
* starting with a closing part of a three-part comment. That's good,
* because we don't want to remove those as this would be annoying.
*/
- if (*comment_flags == ':' || *comment_flags == NUL)
+ if (*comment_flags == ':' || *comment_flags == NUL) {
line += lead_len;
+ }
return line;
}
@@ -3531,7 +3536,7 @@ int do_join(size_t count,
int *comments = NULL;
int remove_comments = (use_formatoptions == TRUE)
&& has_format_option(FO_REMOVE_COMS);
- int prev_was_comment;
+ bool prev_was_comment;
if (save_undo && u_save(curwin->w_cursor.lnum - 1,
curwin->w_cursor.lnum + (linenr_T)count) == FAIL) {
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 8990b59f57..4a8ca741db 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -1490,7 +1490,7 @@ do_set (
new_value_alloced = true;
if (newval == NULL) {
newval = empty_option;
- } else if (!(options[opt_idx].flags | P_NO_DEF_EXP)) {
+ } else if (!(options[opt_idx].flags & P_NO_DEF_EXP)) {
s = option_expand(opt_idx, newval);
if (s == NULL) {
s = newval;
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index cec7fc84a5..bd925a8106 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -238,6 +238,7 @@ Terminal *terminal_open(TerminalOptions opts)
set_option_value((uint8_t *)"wrap", false, NULL, OPT_LOCAL);
set_option_value((uint8_t *)"number", false, NULL, OPT_LOCAL);
set_option_value((uint8_t *)"relativenumber", false, NULL, OPT_LOCAL);
+ set_option_value((uint8_t *)"list", false, NULL, OPT_LOCAL);
buf_set_term_title(curbuf, (char *)curbuf->b_ffname);
RESET_BINDING(curwin);
// Reset cursor in current window.
diff --git a/src/nvim/testdir/test_fold.vim b/src/nvim/testdir/test_fold.vim
index 1f835b876f..7cb9faa75f 100644
--- a/src/nvim/testdir/test_fold.vim
+++ b/src/nvim/testdir/test_fold.vim
@@ -96,6 +96,22 @@ func! Test_indent_fold2()
bw!
endfunc
+func Test_folds_marker_in_comment()
+ new
+ call setline(1, ['" foo', 'bar', 'baz'])
+ setl fen fdm=marker
+ setl com=sO:\"\ -,mO:\"\ \ ,eO:\"\",:\" cms=\"%s
+ norm! zf2j
+ setl nofen
+ :1y
+ call assert_equal(['" foo{{{'], getreg(0,1,1))
+ :+2y
+ call assert_equal(['baz"}}}'], getreg(0,1,1))
+
+ set foldmethod&
+ bwipe!
+endfunc
+
func Test_manual_fold_with_filter()
if !executable('cat')
return
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 73a60b2e04..7c7d73fdfb 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -2998,8 +2998,7 @@ void free_tabpage(tabpage_T *tp)
hash_init(&tp->tp_vars->dv_hashtab);
unref_var_dict(tp->tp_vars);
-
- xfree(tp->localdir); // Free tab-local working directory
+ xfree(tp->tp_localdir);
xfree(tp);
}
@@ -3025,7 +3024,7 @@ int win_new_tabpage(int after, char_u *filename)
return FAIL;
}
- newtp->localdir = tp->localdir ? vim_strsave(tp->localdir) : NULL;
+ newtp->tp_localdir = tp->tp_localdir ? vim_strsave(tp->tp_localdir) : NULL;
curtab = newtp;
@@ -3617,28 +3616,38 @@ static void win_enter_ext(win_T *wp, bool undo_sync, int curwin_invalid,
curwin->w_cursor.coladd = 0;
changed_line_abv_curs(); /* assume cursor position needs updating */
- // The new directory is either the local directory of the window, of the tab
- // or NULL.
- char_u *new_dir = curwin->w_localdir ? curwin->w_localdir : curtab->localdir;
+ // New directory is either the local directory of the window, tab or NULL.
+ char *new_dir = (char *)(curwin->w_localdir
+ ? curwin->w_localdir : curtab->tp_localdir);
+
+ char cwd[MAXPATHL];
+ if (os_dirname((char_u *)cwd, MAXPATHL) != OK) {
+ cwd[0] = NUL;
+ }
if (new_dir) {
// Window/tab has a local directory: Save current directory as global
- // directory (unless that was done already) and change to the local
- // directory.
+ // (unless that was done already) and change to the local directory.
if (globaldir == NULL) {
- char_u cwd[MAXPATHL];
-
- if (os_dirname(cwd, MAXPATHL) == OK) {
- globaldir = vim_strsave(cwd);
+ if (cwd[0] != NUL) {
+ globaldir = (char_u *)xstrdup(cwd);
}
}
- if (os_chdir((char *)new_dir) == 0) {
+ if (os_chdir(new_dir) == 0) {
+ if (!p_acd && !strequal(new_dir, cwd)) {
+ do_autocmd_dirchanged(new_dir, curwin->w_localdir
+ ? kCdScopeWindow : kCdScopeTab);
+ }
shorten_fnames(true);
}
} else if (globaldir != NULL) {
- /* Window doesn't have a local directory and we are not in the global
- * directory: Change to the global directory. */
- ignored = os_chdir((char *)globaldir);
+ // Window doesn't have a local directory and we are not in the global
+ // directory: Change to the global directory.
+ if (os_chdir((char *)globaldir) == 0) {
+ if (!p_acd && !strequal((char *)globaldir, cwd)) {
+ do_autocmd_dirchanged((char *)globaldir, kCdScopeGlobal);
+ }
+ }
xfree(globaldir);
globaldir = NULL;
shorten_fnames(TRUE);