From 9b553ad28df74f0a0c5f20a96ab1248c8724b1c1 Mon Sep 17 00:00:00 2001 From: Patrice Peterson Date: Fri, 10 Sep 2021 17:41:51 -0700 Subject: [PATCH 1/3] docs: extmark indexing #12742 Extmarks mostly use api-indexing, except for nvim_buf_get_extmarks(), which uses api-indexing with inclusive ranges. ref #11456 --- runtime/doc/api.txt | 61 ++++++++++++++++++++++++++++++++++++------- src/nvim/api/buffer.c | 17 ++++++------ src/nvim/api/vim.c | 6 ++--- 3 files changed, 63 insertions(+), 21 deletions(-) diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index dae7986fdb..18f56ba477 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -127,6 +127,10 @@ Special types (msgpack EXT) ~ Most of the API uses 0-based indices, and ranges are end-exclusive. For the end of a range, -1 denotes the last line/column. +Exception: the following API functions use 0-based, end-inclusive indexing: + + |nvim_buf_get_extmarks()| + Exception: the following API functions use "mark-like" indexing (1-based lines, 0-based columns): @@ -443,6 +447,41 @@ in the buffer. They could be used to represent cursors, folds, misspelled words, and anything else that needs to track a logical location in the buffer over time. +Extmarks use |api-indexing|, and you can think of them as cursor positions. +For example, an extmark at position 1 exists between the first and second +character on a line, similar to a bar cursor. For that reason, the maximum +extmark index on a line is 1 larger than the character index: > + + f o o b a r <-- line contents (with spaces for illustration purposes) + 0 1 2 3 4 5 <-- character positions (0-based) + 0 1 2 3 4 5 6 <-- extmark positions (0-based) + +Note that extmarks have "forward gravity": If you place the cursor directly on +an extmark position and enter some text, the extmark gets pushed forward. > + + f o o|b a r <-- line (| = cursor) + 3 <-- extmark + + (Now add "z" at cursor position): + + f o o z|b a r <-- line (| = cursor) + 4 <-- extmark + +If your extmark is on the last possible index of a line (7 in the above +"foozbar" example) and you enter a newline at that point, the extmark will +accordingly be pushed to the next line: > + + f o o z b a r| <-- line (| = cursor) + 7 <-- extmark + + (Now add at cursor position): + + f o o z b a r <-- first line + <-- extmarks (none present) + | <-- second line (| = cursor) + 0 <-- new extmark position + + Example: We will set an extmark at the first row and third column. |api-indexing| is @@ -779,10 +818,9 @@ nvim_feedkeys({keys}, {mode}, {escape_csi}) *nvim_feedkeys()* On execution error: does not fail, but updates v:errmsg. - If you need to input sequences like use - |nvim_replace_termcodes| to replace the termcodes and then - pass the resulting string to nvim_feedkeys. You'll also want - to enable escape_csi. + To input sequences like use |nvim_replace_termcodes()| + (typically with escape_csi=true) to replace the keycodes. Then + pass the result to nvim_feedkeys(). Example: > :let key = nvim_replace_termcodes("", v:true, v:false, v:true) @@ -2072,7 +2110,7 @@ nvim_buf_get_commands({buffer}, {opts}) *nvim_buf_get_commands()* *nvim_buf_get_extmark_by_id()* nvim_buf_get_extmark_by_id({buffer}, {ns_id}, {id}, {opts}) - Returns position for a given extmark id + Gets the position (0-indexed) of an extmark {id}. Parameters: ~ {buffer} Buffer handle, or 0 for current buffer @@ -2082,7 +2120,8 @@ nvim_buf_get_extmark_by_id({buffer}, {ns_id}, {id}, {opts}) • details: Whether to include the details dict Return: ~ - (row, col) tuple or empty list () if extmark id was absent + 0-indexed (row, col) tuple or empty list () if extmark id + was absent *nvim_buf_get_extmarks()* nvim_buf_get_extmarks({buffer}, {ns_id}, {start}, {end}, {opts}) @@ -2122,10 +2161,12 @@ nvim_buf_get_extmarks({buffer}, {ns_id}, {start}, {end}, {opts}) Parameters: ~ {buffer} Buffer handle, or 0 for current buffer {ns_id} Namespace id from |nvim_create_namespace()| - {start} Start of range, given as (row, col) or valid - extmark id (whose position defines the bound) - {end} End of range, given as (row, col) or valid - extmark id (whose position defines the bound) + {start} Start of range, given as 0-indexed (row, col) or + valid extmark id (whose position defines the + bound) + {end} End of range (inclusive), given as 0-indexed + (row, col) or valid extmark id (whose position + defines the bound) {opts} Optional parameters. Keys: • limit: Maximum number of marks to return • details Whether to include the details dict diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 878ffdf06f..3260c083b8 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -1232,7 +1232,7 @@ static Array extmark_to_array(ExtmarkInfo extmark, bool id, bool add_dict) return rv; } -/// Returns position for a given extmark id +/// Gets the position (0-indexed) of an extmark {id}. /// /// @param buffer Buffer handle, or 0 for current buffer /// @param ns_id Namespace id from |nvim_create_namespace()| @@ -1240,7 +1240,8 @@ static Array extmark_to_array(ExtmarkInfo extmark, bool id, bool add_dict) /// @param opts Optional parameters. Keys: /// - details: Whether to include the details dict /// @param[out] err Error details, if any -/// @return (row, col) tuple or empty list () if extmark id was absent +/// @return 0-indexed (row, col) tuple or empty list () if extmark id was +/// absent ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id, Integer id, Dictionary opts, Error *err) @@ -1320,10 +1321,10 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id, /// /// @param buffer Buffer handle, or 0 for current buffer /// @param ns_id Namespace id from |nvim_create_namespace()| -/// @param start Start of range, given as (row, col) or valid extmark id -/// (whose position defines the bound) -/// @param end End of range, given as (row, col) or valid extmark id -/// (whose position defines the bound) +/// @param start Start of range, given as 0-indexed (row, col) or valid +/// extmark id (whose position defines the bound) +/// @param end End of range (inclusive), given as 0-indexed (row, col) or +/// valid extmark id (whose position defines the bound) /// @param opts Optional parameters. Keys: /// - limit: Maximum number of marks to return /// - details Whether to include the details dict @@ -1424,8 +1425,8 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, /// /// @param buffer Buffer handle, or 0 for current buffer /// @param ns_id Namespace id from |nvim_create_namespace()| -/// @param line Line where to place the mark, 0-based -/// @param col Column where to place the mark, 0-based +/// @param line Line where to place the mark, 0-based. |api-indexing| +/// @param col Column where to place the mark, 0-based. |api-indexing| /// @param opts Optional parameters. /// - id : id of the extmark to edit. /// - end_line : ending line of the mark, 0-based inclusive. diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 5f48a26a29..8f848aba32 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -275,9 +275,9 @@ static void on_redraw_event(void **argv) /// /// On execution error: does not fail, but updates v:errmsg. /// -/// If you need to input sequences like use |nvim_replace_termcodes| to -/// replace the termcodes and then pass the resulting string to nvim_feedkeys. -/// You'll also want to enable escape_csi. +/// To input sequences like use |nvim_replace_termcodes()| (typically +/// with escape_csi=true) to replace |keycodes|, then pass the result to +/// nvim_feedkeys(). /// /// Example: ///

From f8e406ed304dc4e71ab3db71a27cd10d12817ee5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Javier=20L=C3=B3pez?= 
Date: Sun, 8 Aug 2021 16:17:23 -0500
Subject: [PATCH 2/3] docs: extmarks indexing #15311

fix #11456
---
 runtime/doc/api.txt   | 40 ++++++++++++++++++++++++++++++----------
 src/nvim/api/buffer.c | 10 +++++-----
 2 files changed, 35 insertions(+), 15 deletions(-)

diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index 18f56ba477..6247aab550 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -127,10 +127,6 @@ Special types (msgpack EXT) ~
 Most of the API uses 0-based indices, and ranges are end-exclusive. For the
 end of a range, -1 denotes the last line/column.
 
-Exception: the following API functions use 0-based, end-inclusive indexing:
-
-    |nvim_buf_get_extmarks()|
-
 Exception: the following API functions use "mark-like" indexing (1-based
 lines, 0-based columns):
 
@@ -138,6 +134,14 @@ lines, 0-based columns):
     |nvim_win_get_cursor()|
     |nvim_win_set_cursor()|
 
+Exception: the following API functions use |extmarks| indexing (0-based lines,
+0-based columns end-inclusive):
+
+    |nvim_buf_del_extmark()|
+    |nvim_buf_get_extmark_by_id()|
+    |nvim_buf_get_extmarks()|
+    |nvim_buf_set_extmark()|
+
 							*api-fast*
 Most API functions are "deferred": they are queued on the main loop and
 processed sequentially with normal input.  So if the editor is waiting for
@@ -440,12 +444,13 @@ Example: create a float with scratch buffer: >
 >
 
 ==============================================================================
-Extended marks						   *api-extended-marks*
+Extended marks					*api-extended-marks* *extmarks*
 
 Extended marks (extmarks) represent buffer annotations that track text changes
 in the buffer. They could be used to represent cursors, folds, misspelled
 words, and anything else that needs to track a logical location in the buffer
-over time.
+over time. It is useful to think of an extmark position to be in the space
+between characters.
 
 Extmarks use |api-indexing|, and you can think of them as cursor positions.
 For example, an extmark at position 1 exists between the first and second
@@ -488,12 +493,16 @@ We will set an extmark at the first row and third column. |api-indexing| is
 zero-indexed, so we use row=0 and column=2. Passing id=0 creates a new mark
 and returns the id: >
 
+      01 2345678
+    0 ex|ample..
+<        ^ This is the extmark position
+>
     let g:mark_ns = nvim_create_namespace('myplugin')
-    let g:mark_id = nvim_buf_set_extmark(0, g:mark_ns, 0, 0, 2, {})
-
+    let g:mark_id = nvim_buf_set_extmark(0, g:mark_ns, 0, 2, {})
+<
 We can get a mark by its id: >
 
-    echo nvim_buf_get_extmark_by_id(0, g:mark_ns, g:mark_id)
+    echo nvim_buf_get_extmark_by_id(0, g:mark_ns, g:mark_id, {})
     => [0, 2]
 
 We can get all marks in a buffer for our namespace (or by a range): >
@@ -502,7 +511,18 @@ We can get all marks in a buffer for our namespace (or by a range): >
     => [[1, 0, 2]]
 
 Deleting all text surrounding an extmark does not remove the extmark. To
-remove an extmark use |nvim_buf_del_extmark()|.
+remove an extmark use |nvim_buf_del_extmark()|. Deleting "x" in our example
+would result in the following: >
+
+      0 12345678
+    0 e|ample..
+<       ^ This is the extmark position
+>
+    echo nvim_buf_get_extmark_by_id(0, g:mark_ns, g:mark_id, {})
+    => [0, 1]
+<
+    Note: An extmark "gravity" is the direction it will be shifted after a
+    text edit. See |nvim_buf_set_extmark()| for more information.
 
 Namespaces allow your plugin to manage only its own extmarks, ignoring those
 created by another plugin.
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index 3260c083b8..3808f601d9 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -1232,7 +1232,7 @@ static Array extmark_to_array(ExtmarkInfo extmark, bool id, bool add_dict)
   return rv;
 }
 
-/// Gets the position (0-indexed) of an extmark {id}.
+/// Gets the position (0-indexed) of an extmark.
 ///
 /// @param buffer  Buffer handle, or 0 for current buffer
 /// @param ns_id  Namespace id from |nvim_create_namespace()|
@@ -1321,10 +1321,10 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id,
 ///
 /// @param buffer  Buffer handle, or 0 for current buffer
 /// @param ns_id  Namespace id from |nvim_create_namespace()|
-/// @param start  Start of range, given as 0-indexed (row, col) or valid
-///               extmark id (whose position defines the bound)
-/// @param end  End of range (inclusive), given as 0-indexed (row, col) or
-///             valid extmark id (whose position defines the bound)
+/// @param start  Start of range: a 0-indexed (row, col) or valid extmark id
+/// (whose position defines the bound). |api-indexing|
+/// @param end  End of range (inclusive): a 0-indexed (row, col) or valid
+/// extmark id (whose position defines the bound). |api-indexing|
 /// @param opts  Optional parameters. Keys:
 ///          - limit:  Maximum number of marks to return
 ///          - details Whether to include the details dict

From 915703f2d87fb591adb247b8a1664380c5e9c951 Mon Sep 17 00:00:00 2001
From: "Justin M. Keyes" 
Date: Fri, 10 Sep 2021 19:10:09 -0700
Subject: [PATCH 3/3] docs: extmarks indexing #15311

ref #11456
---
 runtime/doc/api.txt | 79 +++++++++++++++++++--------------------------
 src/nvim/api/vim.c  |  2 +-
 2 files changed, 35 insertions(+), 46 deletions(-)

diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index 6247aab550..df345e4981 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -134,8 +134,8 @@ lines, 0-based columns):
     |nvim_win_get_cursor()|
     |nvim_win_set_cursor()|
 
-Exception: the following API functions use |extmarks| indexing (0-based lines,
-0-based columns end-inclusive):
+Exception: the following API functions use |extmarks| indexing (0-based
+indices, end-inclusive):
 
     |nvim_buf_del_extmark()|
     |nvim_buf_get_extmark_by_id()|
@@ -447,84 +447,73 @@ Example: create a float with scratch buffer: >
 Extended marks					*api-extended-marks* *extmarks*
 
 Extended marks (extmarks) represent buffer annotations that track text changes
-in the buffer. They could be used to represent cursors, folds, misspelled
-words, and anything else that needs to track a logical location in the buffer
-over time. It is useful to think of an extmark position to be in the space
-between characters.
+in the buffer. They can represent cursors, folds, misspelled words, anything
+that needs to track a logical location in the buffer over time. |api-indexing|
 
-Extmarks use |api-indexing|, and you can think of them as cursor positions.
-For example, an extmark at position 1 exists between the first and second
-character on a line, similar to a bar cursor. For that reason, the maximum
-extmark index on a line is 1 larger than the character index: >
+Extmark position works like "bar" cursor: it exists between characters. Thus
+the maximum extmark index on a line is 1 more than the character index: >
 
-     f o o b a r  <-- line contents (with spaces for illustration purposes)
-     0 1 2 3 4 5  <-- character positions (0-based)
-    0 1 2 3 4 5 6 <-- extmark positions (0-based)
+     f o o b a r      line contents
+     0 1 2 3 4 5      character positions (0-based)
+    0 1 2 3 4 5 6     extmark positions (0-based)
 
-Note that extmarks have "forward gravity": If you place the cursor directly on
-an extmark position and enter some text, the extmark gets pushed forward. >
+Extmarks have "forward gravity": if you place the cursor directly on an
+extmark position and enter some text, the extmark migrates forward. >
 
-     f o o|b a r  <-- line (| = cursor)
-          3       <-- extmark
+     f o o|b a r      line (| = cursor)
+          3           extmark
 
-     (Now add "z" at cursor position):
+     f o o z|b a r    line (| = cursor)
+            4         extmark (after typing "z")
 
-     f o o z|b a r  <-- line (| = cursor)
-            4       <-- extmark
+If an extmark is on the last index of a line and you inputsa newline at that
+point, the extmark will accordingly migrate to the next line: >
 
-If your extmark is on the last possible index of a line (7 in the above
-"foozbar" example) and you enter a newline at that point, the extmark will
-accordingly be pushed to the next line: >
+     f o o z b a r|   line (| = cursor)
+                  7   extmark
 
-     f o o z b a r|  <-- line (| = cursor)
-                  7  <-- extmark
-
-     (Now add  at cursor position):
-
-     f o o z b a r  <-- first line
-                    <-- extmarks (none present)
-     |              <-- second line (| = cursor)
-     0              <-- new extmark position
+     f o o z b a r    first line
+                      extmarks (none present)
+     |                second line (| = cursor)
+     0                extmark (after typing )
 
 
 Example:
 
-We will set an extmark at the first row and third column. |api-indexing| is
-zero-indexed, so we use row=0 and column=2. Passing id=0 creates a new mark
-and returns the id: >
+Let's set an extmark at the first row (row=0) and third column (column=2).
+|api-indexing| Passing id=0 creates a new mark and returns the id: >
 
       01 2345678
     0 ex|ample..
-<        ^ This is the extmark position
+<        ^ extmark position
 >
     let g:mark_ns = nvim_create_namespace('myplugin')
     let g:mark_id = nvim_buf_set_extmark(0, g:mark_ns, 0, 2, {})
 <
-We can get a mark by its id: >
+We can get the mark by its id: >
 
     echo nvim_buf_get_extmark_by_id(0, g:mark_ns, g:mark_id, {})
     => [0, 2]
 
-We can get all marks in a buffer for our namespace (or by a range): >
+We can get all marks in a buffer by |namespace| (or by a range): >
 
     echo nvim_buf_get_extmarks(0, g:mark_ns, 0, -1, {})
     => [[1, 0, 2]]
 
-Deleting all text surrounding an extmark does not remove the extmark. To
-remove an extmark use |nvim_buf_del_extmark()|. Deleting "x" in our example
-would result in the following: >
+Deleting all surrounding text does NOT remove an extmark! To remove extmarks
+use |nvim_buf_del_extmark()|. Deleting "x" in our example: >
 
       0 12345678
     0 e|ample..
-<       ^ This is the extmark position
+<       ^ extmark position
 >
     echo nvim_buf_get_extmark_by_id(0, g:mark_ns, g:mark_id, {})
     => [0, 1]
 <
-    Note: An extmark "gravity" is the direction it will be shifted after a
-    text edit. See |nvim_buf_set_extmark()| for more information.
+    Note: Extmark "gravity" decides how it will shift after a text edit.
+          See |nvim_buf_set_extmark()|
 
-Namespaces allow your plugin to manage only its own extmarks, ignoring those
+Namespaces allow any plugin to manage only its own extmarks, ignoring those
 created by another plugin.
 
 Extmark positions changed by an edit will be restored on undo/redo. Creating
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 8f848aba32..f65d5cc185 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -1551,7 +1551,7 @@ void nvim_set_current_tabpage(Tabpage tabpage, Error *err)
   }
 }
 
-/// Creates a new namespace, or gets an existing one.
+/// Creates a new *namespace*, or gets an existing one.
 ///
 /// Namespaces are used for buffer highlights and virtual text, see
 /// |nvim_buf_add_highlight()| and |nvim_buf_set_extmark()|.