Skip to content
Browse files

patch 8.1.0757: not enough documentation for Blobs

Problem:    Not enough documentation for Blobs.
Solution:   Add a section about Blobs.
  • Loading branch information...
brammool committed Jan 15, 2019
1 parent 3d28b58 commit d89682477cd01ec60edd6d88093b95b12e180127
Showing with 140 additions and 15 deletions.
  1. +138 −15 runtime/doc/eval.txt
  2. +2 −0 src/version.c
@@ -1,4 +1,4 @@
*eval.txt* For Vim version 8.1. Last change: 2019 Jan 13
*eval.txt* For Vim version 8.1. Last change: 2019 Jan 15

@@ -17,7 +17,8 @@ done, the features in this document are not available. See |+eval| and
1.2 Function references |Funcref|
1.3 Lists |Lists|
1.4 Dictionaries |Dictionaries|
1.5 More about variables |more-variables|
1.5 Blobs |Blobs|
1.6 More about variables |more-variables|
2. Expression syntax |expression-syntax|
3. Internal variable |internal-variables|
4. Builtin Functions |functions|
@@ -53,7 +54,7 @@ Float A floating point number. |floating-point-format| *Float*
String A NUL terminated string of 8-bit unsigned characters (bytes).
|expr-string| Examples: "ab\txx\"--" 'x-z''a,c'

List An ordered sequence of items |List|.
List An ordered sequence of items, see |List| for details.
Example: [1, 2, ['a', 'b']]

Dictionary An associative, unordered array: Each entry has a key and a
@@ -72,7 +73,8 @@ Job Used for a job, see |job_start()|. *Job* *Jobs*

Channel Used for a channel, see |ch_open()|. *Channel* *Channels*

Blob Binary Large Object. Stores any sequence of bytes. *Blob*
Blob Binary Large Object. Stores any sequence of bytes. See |Blob|
for details
Example: 0zFF00ED015DAF
0z is an empty Blob.

@@ -459,7 +461,7 @@ example, to add up all the numbers in a list: >

1.4 Dictionaries ~
*dict* *Dictionaries* *Dictionary*
*dict* *Dict* *Dictionaries* *Dictionary*
A Dictionary is an associative array: Each entry has a key and a value. The
entry can be located with the key. The entries are stored without a specific
@@ -621,7 +623,122 @@ Functions that can be used with a Dictionary: >
:call map(dict, '">> " . v:val') " prepend ">> " to each item

1.5 More about variables ~
1.5 Blobs ~
*blob* *Blob* *Blobs* *E978*
A Blob mostly behaves like a |List| of numbers, where the numbers have an
8-bit value, from 0 to 255.

Blob creation ~

A Blob can be created with a |blob-literal|: >
:let b = 0zFF00ED015DAF

A blob can be read from a file with |readfile()| passing the {type} argument
set to "B", for example: >
:let b = readfile('image.png', 'B')

A blob can be read from a channel with the |ch_readblob()| function.

Blob index ~
*blob-index* *E979*
A byte in the Blob can be accessed by putting the index in square brackets
after the Blob. Indexes are zero-based, thus the first byte has index zero. >
:let myblob = 0z00112233

This comment has been minimized.

Copy link

bstaletic Jan 16, 2019

The z in 0z00112233 looks like a typo.

This comment has been minimized.

Copy link

mattn Jan 16, 2019

Not a typo. This is new literal for blob.

This comment has been minimized.

Copy link

brammool via email Jan 16, 2019

Author Contributor

This comment has been minimized.

Copy link

tonymec Jan 16, 2019

@bstaletic : It is just the new notation, with "something else", namely 0z, instead of 0x, to mark the difference between Numbers displayed in hex and Blobs displayed in hex. This new notation is defined under |blob-literal| (at line 1173(old)/1290(new) below), linked at line 634(new) with another 0z… example at line 635(new). There is also another example higher up, at line 76(old)/78(new). This notation is used too systematically to be an isolated typo; but the examples below in the patch show that blob[n] is a Number in the range 0-255 while blob[m:n] (where either n>=m or n<0<=m) is a Blob (of (n-m+1) bytes if m and n are of the same sign). IOW, myblob[0] gives the Number 0x00 i.e. 0, while myblob[0:0] gives the Blob 0z00. Similarly, for a List the results are also different (as shown under |list-index|):

let mylist = [1, 2, 3]
echo mylist[1]        " 2, in this case a Number
echo mylist[1:1]      " [2], a List

This comment has been minimized.

Copy link

bstaletic Jan 17, 2019

Apologies everyone. I was way too tired to read the docs properly.

:let byte = myblob[0] " get the first byte: 0x00
:let byte = myblob[2] " get the third byte: 0x22

A negative index is counted from the end. Index -1 refers to the last byte in
the Blob, -2 to the last but one byte, etc. >
:let last = myblob[-1] " get the last byte: 0x33

To avoid an error for an invalid index use the |get()| function. When an item
is not available it returns -1 or the default value you specify: >
:echo get(myblob, idx)
:echo get(myblob, idx, 999)

Blob concatenation ~

Two blobs can be concatenated with the "+" operator: >
:let longblob = myblob + 0z4455
:let myblob += 0z6677

To change a blob in-place see |blob-modification| below.

Part of a blob ~

A part of the Blob can be obtained by specifying the first and last index,
separated by a colon in square brackets: >
:let myblob = 0z00112233
:let shortblob = myblob[2:-1] " get 0z2233

Omitting the first index is similar to zero. Omitting the last index is
similar to -1. >
:let endblob = myblob[2:] " from item 2 to the end: 0z2233
:let shortblob = myblob[2:2] " Blob with one byte: 0z22
:let otherblob = myblob[:] " make a copy of the Blob

If the first index is beyond the last byte of the Blob or the second byte is
before the first byte, the result is an empty list. There is no error

If the second index is equal to or greater than the length of the list the
length minus one is used: >
:echo myblob[2:8] " result: 0z2233

Blob modification ~
To change a specific byte of a blob use |:let| this way: >
:let blob[4] = 0x44

When the index is just one beyond the end of the Blob, it is appended. Any
higher index is an error.

To change a sequence of bytes the [:] notation can be used: >
let blob[1:3] = 0z445566
The length of the replaced bytes much be exactly the same as the value
provided. *E972*

To change part of a blob you can specify the first and last byte to be
modified. The value must at least have the number of bytes in the range: >
:let blob[3:5] = [3, 4, 5]

You can also use the functions |add()|, |remove()| and |insert()|.

Blob identity ~

Blobs can be compared for equality: >
if blob == 0z001122
And for equal identity: >
if blob is otherblob
< *blob-identity* *E977*
When variable "aa" is a Blob and you assign it to another variable "bb", both
variables refer to the same Blob. Then the "is" operator returns true.

When making a copy using [:] or |copy()| the values are the same, but the
identity is different: >
:let blob = 0z112233
:let blob2 = blob
:echo blob == blob2
< 1 >
:echo blob is blob2
< 1 >
:let blob3 = blob[:]
:echo blob == blob3
< 1 >
:echo blob is blob3
< 0

Making a copy of a list is done with the |copy()| function. Using [:] also
works, as explained above.

1.6 More about variables ~
If you need to know the type of a variable or expression, use the |type()|
@@ -1167,7 +1284,7 @@ of 'encoding'.
Note that "\000" and "\x00" force the end of the string.

blob-literal *blob-literal* *E973* *E977* *E978*
blob-literal *blob-literal* *E973*

Hexadecimal starting with 0z or 0Z, with an arbitrary number of bytes.
@@ -2047,7 +2164,7 @@ USAGE RESULT DESCRIPTION ~

abs({expr}) Float or Number absolute value of {expr}
acos({expr}) Float arc cosine of {expr}
add({list}, {item}) List append {item} to |List| {list}
add({object}, {item}) List/Blob append {item} to {object}
and({expr}, {expr}) Number bitwise AND
append({lnum}, {text}) Number append {text} below line {lnum}
appendbufline({expr}, {lnum}, {text})
@@ -2611,13 +2728,14 @@ acos({expr}) *acos()*
{only available when compiled with the |+float| feature}

add({list}, {expr}) *add()*
Append the item {expr} to |List| {list}. Returns the
resulting |List|. Examples: >
add({object}, {expr}) *add()*
Append the item {expr} to |List| or |Blob| {object}. Returns
the resulting |List| or |Blob|. Examples: >
:let alist = add([1, 2, 3], item)
:call add(mylist, "woodstock")
< Note that when {expr} is a |List| it is appended as a single
item. Use |extend()| to concatenate |Lists|.
When {object} is a |Blob| then {expr} must be a number.
Use |insert()| to add an item at another position.

@@ -3665,11 +3783,12 @@ empty({expr}) *empty()*
Return the Number 1 if {expr} is empty, zero otherwise.
- A |List| or |Dictionary| is empty when it does not have any
- A String is empty when its length is zero.
- A Number and Float is empty when its value is zero.
- A |String| is empty when its length is zero.
- A |Number| and |Float| are empty when their value is zero.
- |v:false|, |v:none| and |v:null| are empty, |v:true| is not.
- A Job is empty when it failed to start.
- A Channel is empty when it is closed.
- A |Job| is empty when it failed to start.
- A |Channel| is empty when it is closed.
- A Blob is empty when its length is zero.

For a long |List| this is much faster than comparing the
length with zero.
@@ -4342,6 +4461,10 @@ get({list}, {idx} [, {default}]) *get()*
Get item {idx} from |List| {list}. When this item is not
available return {default}. Return zero when {default} is
get({blob}, {idx} [, {default}])
Get byte {idx} from |Blob| {blob}. When this byte is not
available return {default}. Return -1 when {default} is
get({dict}, {key} [, {default}])
Get item with key {key} from |Dictionary| {dict}. When this
item is not available return {default}. Return zero when
@@ -795,6 +795,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */

0 comments on commit d896824

Please sign in to comment.
You can’t perform that action at this time.