6 static Buffer
*register_buffer(Register
*reg
, size_t slot
) {
7 Buffer
*buf
= array_get(®
->values
, slot
);
10 if (array_resize(®
->values
, slot
) && (buf
= array_get(®
->values
, slot
)))
14 if (!array_add(®
->values
, &new))
16 size_t capacity
= array_capacity(®
->values
);
17 for (size_t i
= array_length(®
->values
); i
< capacity
; i
++) {
18 if (!array_add(®
->values
, &new))
21 return array_get(®
->values
, slot
);
24 static ssize_t
read_buffer(void *context
, char *data
, size_t len
) {
25 buffer_append(context
, data
, len
);
29 bool register_init(Register
*reg
) {
32 array_init_sized(®
->values
, sizeof(Buffer
));
33 return array_add(®
->values
, &buf
);
36 void register_release(Register
*reg
) {
39 size_t n
= array_capacity(®
->values
);
40 for (size_t i
= 0; i
< n
; i
++)
41 buffer_release(array_get(®
->values
, i
));
42 array_release(®
->values
);
45 const char *register_slot_get(Vis
*vis
, Register
*reg
, size_t slot
, size_t *len
) {
51 Buffer
*buf
= array_get(®
->values
, slot
);
54 buffer_terminate(buf
);
56 *len
= buffer_length0(buf
);
57 return buffer_content0(buf
);
61 Buffer
*buf
= array_get(®
->values
, 0);
64 buffer_printf(buf
, "%zu", slot
+1);
66 *len
= buffer_length0(buf
);
67 return buffer_content0(buf
);
69 case REGISTER_CLIPBOARD
:
73 Buffer
*buf
= array_get(®
->values
, slot
);
78 int status
= vis_pipe(vis
, vis
->win
->file
,
79 &(Filerange
){ .start
= 0, .end
= 0 },
80 (const char*[]){ VIS_CLIPBOARD
, "--paste", NULL
},
81 buf
, read_buffer
, &buferr
, read_buffer
);
84 vis_info_show(vis
, "Command failed %s", buffer_content0(&buferr
));
85 buffer_release(&buferr
);
87 *len
= buffer_length0(buf
);
88 return buffer_content0(buf
);
90 case REGISTER_BLACKHOLE
:
96 const char *register_get(Vis
*vis
, Register
*reg
, size_t *len
) {
97 return register_slot_get(vis
, reg
, 0, len
);
100 bool register_slot_put(Vis
*vis
, Register
*reg
, size_t slot
, const char *data
, size_t len
) {
101 if (reg
->type
!= REGISTER_NORMAL
)
103 Buffer
*buf
= register_buffer(reg
, slot
);
104 return buf
&& buffer_put(buf
, data
, len
);
107 bool register_put(Vis
*vis
, Register
*reg
, const char *data
, size_t len
) {
108 return register_slot_put(vis
, reg
, 0, data
, len
) &&
109 register_resize(reg
, 1);
112 bool register_put0(Vis
*vis
, Register
*reg
, const char *data
) {
113 return register_put(vis
, reg
, data
, strlen(data
)+1);
116 static bool register_slot_append_range(Register
*reg
, size_t slot
, Text
*txt
, Filerange
*range
) {
118 case REGISTER_NORMAL
:
120 Buffer
*buf
= register_buffer(reg
, slot
);
123 size_t len
= text_range_size(range
);
124 if (len
== SIZE_MAX
|| !buffer_grow(buf
, len
+1))
126 if (buf
->len
> 0 && buf
->data
[buf
->len
-1] == '\0')
128 buf
->len
+= text_bytes_get(txt
, range
->start
, len
, buf
->data
+ buf
->len
);
129 return buffer_append(buf
, "\0", 1);
136 bool register_slot_put_range(Vis
*vis
, Register
*reg
, size_t slot
, Text
*txt
, Filerange
*range
) {
138 return register_slot_append_range(reg
, slot
, txt
, range
);
141 case REGISTER_NORMAL
:
143 Buffer
*buf
= register_buffer(reg
, slot
);
146 size_t len
= text_range_size(range
);
147 if (len
== SIZE_MAX
|| !buffer_reserve(buf
, len
+1))
149 buf
->len
= text_bytes_get(txt
, range
->start
, len
, buf
->data
);
150 return buffer_append(buf
, "\0", 1);
152 case REGISTER_CLIPBOARD
:
155 buffer_init(&buferr
);
157 int status
= vis_pipe(vis
, vis
->win
->file
, range
,
158 (const char*[]){ VIS_CLIPBOARD
, "--copy", NULL
},
159 NULL
, NULL
, &buferr
, read_buffer
);
162 vis_info_show(vis
, "Command failed %s", buffer_content0(&buferr
));
163 buffer_release(&buferr
);
166 case REGISTER_BLACKHOLE
:
173 bool register_put_range(Vis
*vis
, Register
*reg
, Text
*txt
, Filerange
*range
) {
174 return register_slot_put_range(vis
, reg
, 0, txt
, range
) &&
175 register_resize(reg
, 1);
178 size_t vis_register_count(Vis
*vis
, Register
*reg
) {
179 if (reg
->type
== REGISTER_NUMBER
)
180 return vis
->win
? view_cursors_count(vis
->win
->view
) : 0;
181 return array_length(®
->values
);
184 bool register_resize(Register
*reg
, size_t count
) {
185 return array_truncate(®
->values
, count
);
188 enum VisRegister
vis_register_from(Vis
*vis
, char reg
) {
190 case '+': return VIS_REG_CLIPBOARD
;
191 case '@': return VIS_MACRO_LAST_RECORDED
;
194 if ('a' <= reg
&& reg
<= 'z')
195 return VIS_REG_a
+ reg
- 'a';
196 if ('A' <= reg
&& reg
<= 'Z')
197 return VIS_REG_A
+ reg
- 'A';
198 for (size_t i
= 0; i
< LENGTH(vis_registers
); i
++) {
199 if (vis_registers
[i
].name
== reg
)
202 return VIS_REG_INVALID
;
205 void vis_register(Vis
*vis
, enum VisRegister reg
) {
206 if (VIS_REG_A
<= reg
&& reg
<= VIS_REG_Z
) {
207 vis
->action
.reg
= &vis
->registers
[VIS_REG_a
+ reg
- VIS_REG_A
];
208 vis
->action
.reg
->append
= true;
209 } else if (reg
< LENGTH(vis
->registers
)) {
210 vis
->action
.reg
= &vis
->registers
[reg
];
211 vis
->action
.reg
->append
= false;
215 static Register
*register_from(Vis
*vis
, enum VisRegister id
) {
216 if (VIS_REG_A
<= id
&& id
<= VIS_REG_Z
)
217 id
= VIS_REG_a
+ id
- VIS_REG_A
;
218 if (id
< LENGTH(vis
->registers
))
219 return &vis
->registers
[id
];
223 bool vis_register_put(Vis
*vis
, enum VisRegister id
, const char *data
, size_t len
) {
224 Register
*reg
= register_from(vis
, id
);
227 return register_put(vis
, reg
, data
, len
);
230 const char *vis_register_get(Vis
*vis
, enum VisRegister id
, size_t *len
) {
231 return vis_register_slot_get(vis
, id
, 0, len
);
234 const char *vis_register_slot_get(Vis
*vis
, enum VisRegister id
, size_t slot
, size_t *len
) {
235 Register
*reg
= register_from(vis
, id
);
237 return register_slot_get(vis
, reg
, slot
, len
);
242 const RegisterDef vis_registers
[] = {
243 [VIS_REG_DEFAULT
] = { '"', VIS_HELP("Unnamed register") },
244 [VIS_REG_ZERO
] = { '0', VIS_HELP("Yank register") },
245 [VIS_REG_1
] = { '1', VIS_HELP("1st sub-expression match") },
246 [VIS_REG_2
] = { '2', VIS_HELP("2nd sub-expression match") },
247 [VIS_REG_3
] = { '3', VIS_HELP("3rd sub-expression match") },
248 [VIS_REG_4
] = { '4', VIS_HELP("4th sub-expression match") },
249 [VIS_REG_5
] = { '5', VIS_HELP("5th sub-expression match") },
250 [VIS_REG_6
] = { '6', VIS_HELP("6th sub-expression match") },
251 [VIS_REG_7
] = { '7', VIS_HELP("7th sub-expression match") },
252 [VIS_REG_8
] = { '8', VIS_HELP("8th sub-expression match") },
253 [VIS_REG_9
] = { '9', VIS_HELP("9th sub-expression match") },
254 [VIS_REG_AMPERSAND
] = { '&', VIS_HELP("Last regex match") },
255 [VIS_REG_BLACKHOLE
] = { '_', VIS_HELP("/dev/null register") },
256 [VIS_REG_CLIPBOARD
] = { '*', VIS_HELP("System clipboard register, see vis-clipboard(1)") },
257 [VIS_REG_DOT
] = { '.', VIS_HELP("Last inserted text") },
258 [VIS_REG_SEARCH
] = { '/', VIS_HELP("Last search pattern") },
259 [VIS_REG_COMMAND
] = { ':', VIS_HELP("Last :-command") },
260 [VIS_REG_SHELL
] = { '!', VIS_HELP("Last shell command given to either <, >, |, or !") },
261 [VIS_REG_NUMBER
] = { '#', VIS_HELP("Cursor number") },