diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt index 2b4bd189ad7567..c064a043f015f2 100644 --- a/runtime/doc/change.txt +++ b/runtime/doc/change.txt @@ -1,4 +1,4 @@ -*change.txt* For Vim version 9.1. Last change: 2024 Jun 23 +*change.txt* For Vim version 9.1. Last change: 2024 Jul 14 VIM REFERENCE MANUAL by Bram Moolenaar @@ -95,13 +95,13 @@ For inserting text see |insert.txt|. These commands delete text. You can repeat them with the `.` command (except `:d`) and undo them. Use Visual mode to delete blocks of text. See |registers| for an explanation of registers. - + *d-special* An exception for the d{motion} command: If the motion is not linewise, the start and end of the motion are not in the same line, and there are only blanks before the start and there are no non-blanks after the end of the motion, the delete becomes linewise. This means that the delete also removes the line of blanks that you might expect to remain. Use the |o_v| operator to -force the motion to be characterwise. +force the motion to be characterwise or set |cpo-z|. Trying to delete an empty region of text (e.g., "d0" in the first column) is an error when 'cpoptions' includes the 'E' flag. @@ -251,7 +251,7 @@ blank; this is probably a bug, because "dw" deletes all the blanks; use the If you prefer "cw" to include the space after a word, use this mapping: > :map cw dwi -Or use "caw" (see |aw|). +Alternatively use "caw" (see also |aw| and |cpo-z|). *:c* *:ch* *:change* :{range}c[hange][!] Replace lines of text with some different text. diff --git a/runtime/doc/motion.txt b/runtime/doc/motion.txt index 8b536055a7c852..3e45884be9bf2c 100644 --- a/runtime/doc/motion.txt +++ b/runtime/doc/motion.txt @@ -1,4 +1,4 @@ -*motion.txt* For Vim version 9.1. Last change: 2023 Dec 27 +*motion.txt* For Vim version 9.1. Last change: 2024 Jul 14 VIM REFERENCE MANUAL by Bram Moolenaar @@ -434,7 +434,7 @@ WORD before the fold. Special case: "cw" and "cW" are treated like "ce" and "cE" if the cursor is on a non-blank. This is because "cw" is interpreted as change-word, and a -word does not include the following white space. +word does not include the following white space (see also |cw|). Another special case: When using the "w" motion in combination with an operator and the last word moved over is at the end of a line, the end of diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 5f1a2a074f74a2..725a805194b39e 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1,4 +1,4 @@ -*options.txt* For Vim version 9.1. Last change: 2024 Jul 11 +*options.txt* For Vim version 9.1. Last change: 2024 Jul 13 VIM REFERENCE MANUAL by Bram Moolenaar @@ -2486,6 +2486,9 @@ A jump table for the options with a short description can be found at |Q_op|. *cpo-Z* Z When using "w!" while the 'readonly' option is set, don't reset 'readonly'. + *cpo-z* + z Special casing the motion for "cw" and "dw" + (see |cw| and |d-special|). *cpo-!* ! When redoing a filter command, use the last used external command, whatever it was. Otherwise the last diff --git a/runtime/doc/tags b/runtime/doc/tags index 00c216c84740af..8d0af6620eaa38 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -6671,6 +6671,7 @@ cpo-v options.txt /*cpo-v* cpo-w options.txt /*cpo-w* cpo-x options.txt /*cpo-x* cpo-y options.txt /*cpo-y* +cpo-z options.txt /*cpo-z* cpo-{ options.txt /*cpo-{* cpp.vim syntax.txt /*cpp.vim* crash-recovery recover.txt /*crash-recovery* @@ -6733,6 +6734,7 @@ cw change.txt /*cw* cweb.vim syntax.txt /*cweb.vim* cynlib.vim syntax.txt /*cynlib.vim* d change.txt /*d* +d-special change.txt /*d-special* daB motion.txt /*daB* daW motion.txt /*daW* dab motion.txt /*dab* diff --git a/src/normal.c b/src/normal.c index 541c8ed1c466d1..a929dd8082d954 100644 --- a/src/normal.c +++ b/src/normal.c @@ -6598,8 +6598,12 @@ nv_wordcmd(cmdarg_T *cap) // "ce" will change until the end of the next word, but "cw" // will change only one character! This is done by setting // flag. - cap->oap->inclusive = TRUE; - word_end = TRUE; + // This can be configured using :set cpo-z + if (vim_strchr(p_cpo, CPO_WORD) != NULL) + { + cap->oap->inclusive = TRUE; + word_end = TRUE; + } flag = TRUE; } } diff --git a/src/ops.c b/src/ops.c index dcb48d32334261..2de2557fbd1aab 100644 --- a/src/ops.c +++ b/src/ops.c @@ -676,6 +676,7 @@ op_delete(oparg_T *oap) && !oap->block_mode && oap->line_count > 1 && oap->motion_force == NUL + && (vim_strchr(p_cpo, CPO_WORD) != NULL) && oap->op_type == OP_DELETE) { ptr = ml_get(oap->end.lnum) + oap->end.col; diff --git a/src/option.h b/src/option.h index e84f7f9adda193..fba2672877a716 100644 --- a/src/option.h +++ b/src/option.h @@ -212,6 +212,7 @@ typedef enum { #define CPO_REPLCNT 'X' // "R" with a count only deletes chars once #define CPO_YANK 'y' #define CPO_KEEPRO 'Z' // don't reset 'readonly' on ":w!" +#define CPO_WORD 'z' // do not special-case word motions cw and dw #define CPO_DOLLAR '$' #define CPO_FILTER '!' #define CPO_MATCH '%' @@ -231,9 +232,9 @@ typedef enum { #define CPO_SCOLON ';' // using "," and ";" will skip over char if // cursor would not move // default values for Vim, Vi and POSIX -#define CPO_VIM "aABceFs" -#define CPO_VI "aAbBcCdDeEfFgHiIjJkKlLmMnoOpPqrRsStuvwWxXyZ$!%*-+<>;" -#define CPO_ALL "aAbBcCdDeEfFgHiIjJkKlLmMnoOpPqrRsStuvwWxXyZ$!%*-+<>#{|&/\\.;" +#define CPO_VIM "aABceFsz" +#define CPO_VI "aAbBcCdDeEfFgHiIjJkKlLmMnoOpPqrRsStuvwWxXyZz$!%*-+<>;" +#define CPO_ALL "aAbBcCdDeEfFgHiIjJkKlLmMnoOpPqrRsStuvwWxXyZz$!%*-+<>#{|&/\\.;" // characters for p_ww option: #define WW_ALL "bshl<>[]~" diff --git a/src/testdir/test_codestyle.vim b/src/testdir/test_codestyle.vim index a455264de7e8fc..58ccb6abba66f9 100644 --- a/src/testdir/test_codestyle.vim +++ b/src/testdir/test_codestyle.vim @@ -68,7 +68,8 @@ def Test_test_files() && fname !~ 'test_listchars.vim' && fname !~ 'test_visual.vim' cursor(1, 1) - var lnum = search(fname =~ "test_regexp_latin" ? '[^á] \t' : ' \t') + var skip = 'getline(".") =~ "codestyle: ignore"' + var lnum = search(fname =~ "test_regexp_latin" ? '[^á] \t' : ' \t', 'W', 0, 0, skip) ReportError('testdir/' .. fname, lnum, 'space before Tab') endif @@ -155,4 +156,4 @@ def Test_help_files() enddef -" vim: shiftwidth=2 sts=2 expandtab +" vim: shiftwidth=2 sts=2 expandtab nofoldenable diff --git a/src/testdir/test_cpoptions.vim b/src/testdir/test_cpoptions.vim index 6ff8301d6352af..80819cf2d41cfd 100644 --- a/src/testdir/test_cpoptions.vim +++ b/src/testdir/test_cpoptions.vim @@ -912,4 +912,50 @@ func Test_cpo_dot() let &cpo = save_cpo endfunc +" Test for the 'z' flag in 'cpo' (make cw and dw work similar and avoid +" inconsistencies, see :h cpo-z) +" modified) +func Test_cpo_z() + let save_cpo = &cpo + new + " Test 1: dw behaves differently from cw + call setline(1, ['foo bar baz', 'one two three']) + call cursor(1, 1) + " dw does not delete the whitespace after the word + norm! wcwanother + set cpo-=z + " dw deletes the whitespace after the word + call cursor(2, 1) + norm! wcwfour + call assert_equal(['foo another baz', 'one fourthree'], getline(1, '$')) + " Test 2: d{motion} becomes linewise :h d-special + %d + call setline(1, ['one ', ' bar', ' e ', 'zwei']) + call cursor(2, 1) + set cpo+=z + " delete operation becomes linewise + call feedkeys("fbd/e\\zs\", 'tnx') + call assert_equal(['one ', 'zwei'], getline(1, '$')) + %d + call setline(1, ['one ', ' bar', ' e ', 'zwei']) + call cursor(2, 1) + call feedkeys("fbd2w", 'tnx') + call assert_equal(['one ', 'zwei'], getline(1, '$')) + + " delete operation does not become line wise + set cpo-=z + call setline(1, ['one ', ' bar', ' e ', 'zwei']) + call cursor(2, 1) + call feedkeys("fbd/e\\zs\", 'tnx') + call assert_equal(['one ', ' ', 'zwei'], getline(1, '$')) " codestyle: ignore + %d + call setline(1, ['one ', ' bar', ' e ', 'zwei']) + call cursor(2, 1) + call feedkeys("fbd2w", 'tnx') + call assert_equal(['one ', ' ', 'zwei'], getline(1, '$')) + + " clean up + bw! + let &cpo = save_cpo +endfunc " vim: shiftwidth=2 sts=2 expandtab