Skip to content
This repository was archived by the owner on Feb 23, 2025. It is now read-only.

Commit d53c14b

Browse files
authored
Merge pull request #441 from liquidz/dev
Next release
2 parents f89c57b + 06ade39 commit d53c14b

36 files changed

+875
-193
lines changed

CHANGELOG.adoc

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,30 @@ All notable changes to this project will be documented in this file. This change
22

33
== Unreleased (dev)
44

5+
// {{{
6+
=== Added
7+
8+
* Added support for virtual text in Vim9.
9+
** Requires Vim 9.0.297 or later.
10+
* Added bencode component using Vim9 script.
11+
* Added `g:iced#eval#popup_align` option.
12+
* Added spinner while code is evaluating.
13+
** Added `g:iced#eval#popup_spinner_texts` option.
14+
** Added `g:iced#eval#popup_spinner_interval` option.
15+
* Added `IcedIsolatedEval` command.
16+
* Added `IcedEvalInContextAtMark` command.
17+
18+
=== Changed
19+
* Bumped iced-nrepl to 1.2.465.
20+
* Bumped joker to 1.0.1.
21+
22+
=== Fixed
23+
* Fixed neovim virtual text component to use `nvim_buf_set_extmark`.
24+
* Fixed neovim virtual text component to clear a virtual text on the same line.
25+
* Fixed neovim virtual text component to set virtual text on correct line.
26+
* Fixed to clear virtual texts when code evaluation is interrupted
27+
// }}}
28+
529
== 3.11.3086 (2022-08-29)
630
// {{{
731
=== Added

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,7 @@ outdated:
121121
.PHONY: repl
122122
repl:
123123
clojure -R:jackin:dev -m iced-repl
124+
125+
.PHONY: benchmark
126+
benchmark:
127+
vim -u NONE -i NONE -n -N --cmd 'source scripts/bencode_benchmark.vim'
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
if !has('vim9script') | finish | endif
2+
vim9script
3+
4+
def EncodeString(s: string): string
5+
return printf('%d:%s', strlen(s), s)
6+
enddef
7+
8+
def EncodeNumber(i: number): string
9+
return printf('i%de', i)
10+
enddef
11+
12+
def EncodeList(coll: list<any>): string
13+
var result: list<string> = []
14+
for x in coll
15+
add(result, Encode(x))
16+
endfor
17+
return printf('l%se', join(result, ''))
18+
enddef
19+
20+
def EncodeDictionary(dict: dict<any>): string
21+
var result: list<string> = []
22+
for k in keys(dict)
23+
add(result, Encode(k))
24+
add(result, Encode(dict[k]))
25+
endfor
26+
return printf('d%se', join(result, ''))
27+
enddef
28+
29+
export def Encode(x: any): string
30+
const t = type(x)
31+
if t == v:t_string
32+
return EncodeString(x)
33+
elseif t == v:t_number
34+
return EncodeNumber(x)
35+
elseif t == v:t_list
36+
return EncodeList(x)
37+
elseif t == v:t_dict
38+
return EncodeDictionary(x)
39+
elseif t == 7 # v:none or v:null
40+
return EncodeString('')
41+
endif
42+
return ''
43+
enddef
44+
45+
def DecodeString(s: string): dict<any>
46+
const i = stridx(s, ':')
47+
if i == -1
48+
throw 'Failed to parse string token'
49+
endif
50+
const len = str2nr(strpart(s, 0, i))
51+
return {'value': strpart(s, i + 1, len), 'rest': strpart(s, i + len + 1)}
52+
enddef
53+
54+
def DecodeNumber(s: string): dict<any>
55+
const i = stridx(s, 'e')
56+
if i == -1
57+
throw 'Failed to parse integer token'
58+
endif
59+
return {'value': str2nr(strpart(s, 1, i - 1)), 'rest': strpart(s, i + 1)}
60+
enddef
61+
62+
def DecodeList(s: string): dict<any>
63+
var result: list<any> = []
64+
var tmp = strpart(s, 1)
65+
66+
while tmp[0] != 'e'
67+
const decoded = DecodeRaw(tmp)
68+
add(result, decoded.value)
69+
tmp = trim(decoded.rest)
70+
endwhile
71+
72+
return {'value': result, 'rest': strpart(tmp, 1)}
73+
enddef
74+
75+
def DecodeDictionary(s: string): dict<any>
76+
var result: dict<any> = {}
77+
var tmp = strpart(s, 1)
78+
79+
while tmp[0] != 'e'
80+
const k = DecodeRaw(tmp)
81+
const v = DecodeRaw(trim(k.rest))
82+
result[k.value] = v.value
83+
tmp = trim(v.rest)
84+
endwhile
85+
86+
return {'value': result, 'rest': strpart(tmp, 1)}
87+
enddef
88+
89+
def DecodeRaw(s: string): dict<any>
90+
const c = s[0]
91+
var result: dict<any> = {}
92+
93+
if c == 'i'
94+
result = DecodeNumber(s)
95+
elseif c =~ '[0-9]'
96+
result = DecodeString(s)
97+
elseif c == 'l'
98+
result = DecodeList(s)
99+
elseif c == 'd'
100+
result = DecodeDictionary(s)
101+
else
102+
throw 'Failed to parse bencode.'
103+
endif
104+
105+
return result
106+
enddef
107+
108+
export def Decode(s: string): any
109+
var result: list<any> = []
110+
var decoding: bool = true
111+
var tmp = s
112+
113+
while decoding
114+
const decoded = DecodeRaw(tmp)
115+
if ! has_key(decoded, 'value')
116+
decoding = false
117+
else
118+
add(result, decoded.value)
119+
tmp = trim(decoded.rest)
120+
121+
if tmp == ''
122+
decoding = false
123+
endif
124+
endif
125+
endwhile
126+
127+
if len(result) == 1
128+
return result[0]
129+
endif
130+
return result
131+
enddef
132+
# vim:ft=vim
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
let s:save_cpo = &cpoptions
2+
set cpoptions&vim
3+
4+
let s:script_path = printf('%s/bencode.vim9script', expand('<sfile>:h'))
5+
import s:script_path as that
6+
let s:bencode = {}
7+
8+
function! s:bencode.encode(v) abort
9+
return s:that.Encode(a:v)
10+
endfunction
11+
12+
function! s:bencode.decode(s) abort
13+
return s:that.Decode(a:s)
14+
endfunction
15+
16+
function! iced#component#bencode#vim9#start(_) abort
17+
call iced#util#debug('start', 'vim9 bencode')
18+
return s:bencode
19+
endfunction
20+
21+
let &cpoptions = s:save_cpo
22+
unlet s:save_cpo

autoload/iced/component/repl/nrepl.vim

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ let s:nrepl = {
66
\ 'disconnect': function('iced#nrepl#disconnect'),
77
\ 'env': 'nrepl',
88
\ 'eval_code': function('iced#nrepl#eval#code'),
9+
\ 'eval_code_isolatedy': function('iced#nrepl#eval#code_isolatedly'),
910
\ 'eval_outer_top_list': function('iced#nrepl#eval#outer_top_list'),
1011
\ 'eval_at_mark': function('iced#repl#eval_at_mark'),
12+
\ 'eval_in_context_at_mark': function('iced#repl#eval_in_context_at_mark'),
1113
\ 'eval_last_outer_top_list': function('iced#repl#eval_last_outer_top_list'),
1214
\ 'eval_raw': function('iced#nrepl#eval'),
1315
\ 'is_connected': function('iced#nrepl#is_connected'),

autoload/iced/component/repl/socket_repl.vim

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
let s:save_cpo = &cpoptions
22
set cpoptions&vim
33

4+
function! s:not_supported(...) abort
5+
return iced#message#error('not_supported')
6+
endfunction
7+
48
let s:socket_repl = {
59
\ 'connect': function('iced#socket_repl#connect'),
610
\ 'disconnect': function('iced#socket_repl#disconnect'),
711
\ 'env': 'socket_repl',
812
\ 'eval_code': function('iced#socket_repl#eval'),
13+
\ 'eval_code_isolatedy': funcref('s:not_supported'),
914
\ 'eval_outer_top_list': function('iced#socket_repl#eval_outer_top_list'),
1015
\ 'eval_at_mark': function('iced#repl#eval_at_mark'),
16+
\ 'eval_in_context_at_mark': function('iced#repl#eval_in_context_at_mark'),
1117
\ 'eval_last_outer_top_list': function('iced#repl#eval_last_outer_top_list'),
1218
\ 'is_connected': function('iced#socket_repl#is_connected'),
1319
\ 'status': function('iced#socket_repl#status'),

autoload/iced/component/spinner.vim

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
let s:save_cpo = &cpoptions
2+
set cpoptions&vim
3+
4+
let s:spinner = {
5+
\ 'timer': '',
6+
\ 'virtual_text': '',
7+
\ 'working_spinners': {},
8+
\ }
9+
10+
function! s:start_spinner__spinner(uniq_key, opt) abort dict
11+
let buffer = get(a:opt, 'buffer', bufnr('%'))
12+
let line = get(a:opt, 'line', line('.'))
13+
let idx = get(a:opt, 'index', 0)
14+
let texts = get(a:opt, 'texts', [' |', ' /', '-', ' \'])
15+
let highlight = get(a:opt, 'highlight', 'Comment')
16+
let align = get(a:opt, 'align', 'after')
17+
let interval = get(a:opt, 'interval', 200)
18+
19+
let idx = idx >= len(texts) ? 0 : idx
20+
21+
if has_key(self.working_spinners, a:uniq_key)
22+
call self.virtual_text.set(texts[idx], {
23+
\ 'highlight': highlight,
24+
\ 'align': align,
25+
\ 'buffer': buffer,
26+
\ 'line': line,
27+
\ 'auto_clear': v:false,
28+
\ 'indent': 0,
29+
\ })
30+
31+
let new_opt = copy(a:opt)
32+
let new_opt['index'] = idx + 1
33+
let new_opt['buffer'] = buffer
34+
let new_opt['line'] = line
35+
return self.timer.start(
36+
\ interval,
37+
\ {-> call(funcref('s:start_spinner__spinner'), [a:uniq_key, new_opt], self)})
38+
endif
39+
endfunction
40+
41+
function! s:spinner.start(uniq_key, opt) abort
42+
" NOTE: Spinner is only supported by Vim9/Neovim
43+
if self.virtual_text.env ==# 'vim8'
44+
return
45+
endif
46+
47+
let self.working_spinners[a:uniq_key] = v:true
48+
return self.timer.start(200, {-> call(funcref('s:start_spinner__spinner'), [a:uniq_key, a:opt], self)})
49+
endfunction
50+
51+
function! s:spinner.stop(uniq_key) abort
52+
if has_key(self.working_spinners, a:uniq_key)
53+
unlet self.working_spinners[a:uniq_key]
54+
endif
55+
endfunction
56+
57+
function! iced#component#spinner#start(this) abort
58+
call iced#util#debug('start', 'spinner')
59+
let d = deepcopy(s:spinner)
60+
let d['timer'] = a:this.timer
61+
let d['virtual_text'] = a:this.virtual_text
62+
return d
63+
endfunction
64+
65+
let &cpoptions = s:save_cpo
66+
unlet s:save_cpo

autoload/iced/component/virtual_text/neovim.vim

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,28 @@ let s:save_cpo = &cpoptions
22
set cpoptions&vim
33

44
let s:vt = {
5+
\ 'env': 'neovim',
56
\ 'timer': '',
67
\ 'ns': nvim_create_namespace('iced_virtual_text_namespace'),
78
\ }
89

10+
function! s:text_align_to_virt_text_pos(align) abort
11+
return get({'after': 'eol', 'right': 'right_align'}, a:align, 'eol')
12+
endfunction
13+
914
function! s:vt.set(text, ...) abort
1015
let opt = get(a:, 1, {})
1116
let buf = get(opt, 'buffer', bufnr('%'))
12-
let line = get(opt, 'line', line('.') -1)
17+
let line = get(opt, 'line', '')
18+
let line = empty(line) ? line('.') - 1 : line - 1
1319
let hl = get(opt, 'highlight', 'Normal')
14-
call nvim_buf_set_virtual_text(buf, self.ns, line, [[a:text, hl]], {})
20+
let align = get(opt, 'align', 'after')
21+
22+
call nvim_buf_clear_namespace(buf, self.ns, line, line + 1)
23+
call nvim_buf_set_extmark(buf, self.ns, line, 0, {
24+
\ 'virt_text': [[a:text, hl]],
25+
\ 'virt_text_pos': s:text_align_to_virt_text_pos(align)
26+
\ })
1527

1628
if get(opt, 'auto_clear', v:false)
1729
let time = get(opt, 'clear_time', 3000)
@@ -26,8 +38,8 @@ function! s:vt.clear(...) abort
2638
if empty(opt)
2739
call nvim_buf_clear_namespace(buf, self.ns, 1, line('$'))
2840
else
29-
let line = get(opt, 'line', line('.') -1)
30-
call nvim_buf_clear_namespace(buf, self.ns, line, line + 1)
41+
let line = get(opt, 'line', line('.') - 1)
42+
call nvim_buf_clear_namespace(buf, self.ns, line - 1, line)
3143
endif
3244
endfunction
3345

0 commit comments

Comments
 (0)