Skip to content

Commit 6f07bc6

Browse files
committed
feat: add support for sketch.json file (#50)
1 parent 54326c6 commit 6f07bc6

File tree

6 files changed

+171
-7
lines changed

6 files changed

+171
-7
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ users make sure the `arduino` command is in your PATH.
9595

9696
| Command | arg | description |
9797
| ------------------------- | ------------ | --------------------------------------------------------------------------- |
98+
| `ArduinoAttach` | [port] | Automatically attach to your board (see `arduino-cli board attach -h`) |
9899
| `ArduinoChooseBoard` | [board] | Select the type of board. With no arg, will present a choice dialog. |
99100
| `ArduinoChooseProgrammer` | [programmer] | Select the programmer. With no arg, will present a choice dialog. |
100101
| `ArduinoChoosePort` | [port] | Select the serial port. With no arg, will present a choice dialog. |
@@ -109,6 +110,7 @@ can put them in `ftplugin/arduino.vim`:
109110

110111
```vim
111112
" Change these as desired
113+
nnoremap <buffer> <leader>aa <cmd>ArduinoAttach<CR>
112114
nnoremap <buffer> <leader>am <cmd>ArduinoVerify<CR>
113115
nnoremap <buffer> <leader>au <cmd>ArduinoUpload<CR>
114116
nnoremap <buffer> <leader>ad <cmd>ArduinoUploadAndSerial<CR>

autoload/arduino.vim

Lines changed: 96 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ else
2020
let s:TERM = '!'
2121
endif
2222
let s:hardware_dirs = {}
23+
let s:SKETCHFILE = v:null
2324
python3 import json
2425

2526
" Initialization {{{1
@@ -82,6 +83,7 @@ function! arduino#InitializeConfig() abort
8283
echoerr 'arduino-cli: command not found'
8384
endif
8485
call arduino#ReloadBoards()
86+
call s:ReadSketchJson()
8587
endfunction
8688

8789
function! arduino#RunCmd(cmd) abort
@@ -196,10 +198,13 @@ function! arduino#GetBuildPath() abort
196198
endfunction
197199

198200
function! arduino#GetCLICompileCommand(...) abort
199-
let cmd = 'arduino-cli compile -b ' . g:arduino_board
200-
let port = arduino#GetPort()
201-
if !empty(port)
202-
let cmd = cmd . ' -p ' . port
201+
let cmd = 'arduino-cli compile'
202+
if s:SKETCHFILE == v:null
203+
let cmd = cmd . ' -b ' . g:arduino_board
204+
let port = arduino#GetPort()
205+
if !empty(port)
206+
let cmd = cmd . ' -p ' . port
207+
endif
203208
endif
204209
if !empty(g:arduino_programmer)
205210
let cmd = cmd . ' -P ' . g:arduino_programmer
@@ -420,6 +425,31 @@ function! s:ChooserItemOrder(i1, i2) abort
420425
return l1 == l2 ? 0 : l1 > l2 ? 1 : -1
421426
endfunction
422427

428+
function! arduino#Attach(...) abort
429+
if !s:has_cli
430+
echoerr 'ArduinoAttach requires arduino-cli'
431+
return
432+
end
433+
let port = v:null
434+
if a:0
435+
let port = a:1
436+
function PostAttach() abort
437+
call s:ReadSketchJson()
438+
call s:notify('Arduino attached to board ' . g:arduino_board)
439+
endfunction
440+
call arduino#job#run(['arduino-cli', 'board', 'attach', '-p', port], funcref('PostAttach'))
441+
else
442+
let ports = arduino#GetPorts()
443+
if empty(ports)
444+
echoerr 'No likely serial ports detected!'
445+
elseif len(ports) == 1
446+
call arduino#Attach(ports[0])
447+
else
448+
call arduino#chooser#Choose('Select Port', ports, 'arduino#Attach')
449+
endif
450+
endif
451+
endfunction
452+
423453
" Port selection {{{2
424454

425455
function! arduino#ChoosePort(...) abort
@@ -437,6 +467,7 @@ endfunction
437467

438468
function! arduino#SelectPort(port) abort
439469
let g:arduino_serial_port = a:port
470+
call s:WriteSketchKey('port', 'serial://' . g:arduino_serial_port)
440471
endfunction
441472

442473
" Board selection {{{2
@@ -465,6 +496,9 @@ function! arduino#SelectBoard(board) abort
465496
\}
466497
" Have to delay this to give the previous chooser UI time to clear
467498
call timer_start(10, {tid -> arduino#ChooseBoardOption()})
499+
if empty(options)
500+
call s:WriteSketchKey('fqbn', g:arduino_board)
501+
endif
468502
endfunction
469503

470504
" Prompt user for the next unselected board option
@@ -474,17 +508,21 @@ function! arduino#ChooseBoardOption() abort
474508
if !has_key(s:callback_data.opts, opt.option)
475509
let s:callback_data.active_option = opt.option
476510
call arduino#chooser#Choose(opt.option_label, opt.values, 'arduino#SelectOption')
477-
return
511+
return v:true
478512
endif
479513
endfor
514+
return v:false
480515
endfunction
481516

482517
" Callback from option selection
483518
function! arduino#SelectOption(value) abort
484519
let opt = s:callback_data.active_option
485520
let s:callback_data.opts[opt] = a:value
486521
call arduino#SetBoard(s:callback_data.board, s:callback_data.opts)
487-
call arduino#ChooseBoardOption()
522+
let choosing = arduino#ChooseBoardOption()
523+
if !choosing
524+
call s:WriteSketchKey('fqbn', g:arduino_board)
525+
endif
488526
endfunction
489527

490528
" Programmer selection {{{2
@@ -626,6 +664,49 @@ endfunction
626664

627665
" Utility functions {{{1
628666

667+
function! s:ReadSketchJson() abort
668+
let dir = getcwd()
669+
while v:true
670+
let sketch = dir . '/sketch.json'
671+
if filereadable(sketch)
672+
let data = json_decode(join(readfile(sketch)))
673+
let cpu = get(data, 'cpu', {})
674+
if !empty(cpu)
675+
let s:SKETCHFILE = sketch
676+
let board = get(cpu, 'fqbn', '')
677+
if !empty(board)
678+
let g:arduino_board = board
679+
endif
680+
let port = get(cpu, 'port', '')
681+
if !empty(port)
682+
if port =~? '^serial://'
683+
let port = strcharpart(port, 9)
684+
endif
685+
let g:arduino_serial_port = port
686+
endif
687+
endif
688+
return
689+
endif
690+
let next_dir = fnamemodify(dir, ':h')
691+
if next_dir == dir
692+
break
693+
else
694+
let dir = next_dir
695+
endif
696+
endwhile
697+
let s:SKETCHFILE = v:null
698+
endfunction
699+
700+
function s:WriteSketchKey(key, value) abort
701+
if s:SKETCHFILE == v:null
702+
return
703+
endif
704+
let data = json_decode(join(readfile(s:SKETCHFILE)))
705+
let cpu = get(data, 'cpu', {})
706+
let cpu[a:key] = a:value
707+
call writefile([json_encode(data)], s:SKETCHFILE)
708+
endfunction
709+
629710
function! s:CacheLine(lines, varname) abort
630711
if exists(a:varname)
631712
let value = eval(a:varname)
@@ -675,7 +756,15 @@ function! arduino#GetInfo() abort
675756
if g:arduino_use_cli
676757
echo 'Verify command: ' . arduino#GetCLICompileCommand()
677758
else
678-
echo "Verify command: " . arduino#GetArduinoCommand("--verify")
759+
echo 'Verify command: ' . arduino#GetArduinoCommand('--verify')
760+
endif
761+
endfunction
762+
763+
function! s:notify(msg) abort
764+
if has('nvim')
765+
call luaeval('vim.notify(_A)', a:msg)
766+
else
767+
echo a:msg
679768
endif
680769
endfunction
681770

autoload/arduino/job.vim

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
let s:vim8_jobs = {}
2+
let s:vim8_next_id = 0
3+
4+
function! arduino#job#run(cmd, callback)
5+
if has('nvim')
6+
call s:nvim_run(a:cmd, a:callback)
7+
else
8+
call s:vim8_run(a:cmd, a:callback)
9+
endif
10+
endfunction
11+
12+
function! s:nvim_run(cmd, callback)
13+
let Callback = a:callback
14+
function On_exit(job_id, exit_code, event) closure
15+
if !a:exit_code
16+
call Callback()
17+
endif
18+
endfunction
19+
let job_id = jobstart(a:cmd, {
20+
\ 'on_exit': funcref('On_exit'),
21+
\ 'on_stderr': funcref('s:nvim_on_stderr'),
22+
\ 'stderr_buffered': v:true,
23+
\})
24+
if job_id == 0
25+
echoerr 'Error running job: invalid arguments'
26+
elseif job_id == -1
27+
echoerr 'Error running job: command is not executable'
28+
endif
29+
endfunction
30+
31+
function! s:nvim_on_stderr(job_id, data, name)
32+
for line in a:data
33+
if !empty(line)
34+
echoerr line
35+
endif
36+
endfor
37+
endfunction
38+
39+
function! s:nvim_on_exit(job_id, exit_code, event)
40+
if a:exit_code
41+
echoerr 'Error running job ' . a:exit_code
42+
end
43+
endfunction
44+
45+
function! s:vim8_run(cmd, callback)
46+
let job_id = s:vim8_next_id
47+
let s:vim8_next_id += 1
48+
let Callback = a:callback
49+
function! OnClose(channel) closure
50+
let job = s:vim8_jobs[job_id]
51+
while ch_status(a:channel, {'part': 'err'}) ==? 'buffered'
52+
echoerr ch_read(a:channel, {'part': 'err'})
53+
endwhile
54+
call remove(s:vim8_jobs, job_id)
55+
let exit_code = job_info(job)['exitval']
56+
if exit_code
57+
echoerr 'Error running job ' . exit_code
58+
else
59+
call Callback()
60+
endif
61+
endfunction
62+
let job = job_start(a:cmd, {'close_cb': 'OnClose'})
63+
let s:vim8_jobs[job_id] = job
64+
endfunction

doc/arduino.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,13 @@ Search these patterns to find a likely serial port to upload to. >
153153

154154
===============================================================================
155155
COMMANDS *arduino-commands*
156+
157+
*:ArduinoAttach*
158+
:ArduinoAttach [port]
159+
Automatically attach to your board (see `arduino-cli board attach -h`). If
160+
no port is provided and there is more than one option, you will be prompted
161+
to select one.
162+
156163
*:ArduinoChooseBoard*
157164
:ArduinoChooseBoard [board]
158165
Set [board] to be the currently selected board. It should match the format

doc/tags

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
'g:arduino_use_cli' arduino.txt /*'g:arduino_use_cli'*
1616
'g:arduino_use_slime' arduino.txt /*'g:arduino_use_slime'*
1717
'vim-arduino' arduino.txt /*'vim-arduino'*
18+
:ArduinoAttach arduino.txt /*:ArduinoAttach*
1819
:ArduinoChooseBoard arduino.txt /*:ArduinoChooseBoard*
1920
:ArduinoChoosePort arduino.txt /*:ArduinoChoosePort*
2021
:ArduinoChooseProgrammer arduino.txt /*:ArduinoChooseProgrammer*

ftplugin/arduino.vim

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ if g:arduino_auto_baud
1717
au BufReadPost,BufWritePost *.ino call arduino#SetAutoBaud()
1818
endif
1919

20+
command! -buffer -bar -nargs=? ArduinoAttach call arduino#Attach(<f-args>)
2021
command! -buffer -bar -nargs=? ArduinoChooseBoard call arduino#ChooseBoard(<f-args>)
2122
command! -buffer -bar -nargs=? ArduinoChooseProgrammer call arduino#ChooseProgrammer(<f-args>)
2223
command! -buffer -bar ArduinoVerify call arduino#Verify()

0 commit comments

Comments
 (0)