有馬総一郎のブログ

(彼氏の事情)

2018年11月18日 00:18:55 JST - 3 minute read - Vim

手遅れながらvimplenote-vimを使いやすくする(検索したノートを更新できるようにする)

今度は、折角の mattn/vimplenote-vimのアドバンテージとしてノートの検索ができるのだから、検索したノートを参照だけでなく、更新できるようにしたい。

何故、検索したノートを更新できないか、調べてみたところ、リストから開いてノート更新のする場合は、authorizationのファンクションが呼ばれているけど、検索してノートを開いて更新しようとした場合は、authorizationのファンクションが呼ばれていない

ノート一覧:Vimplenote -l

  1. list_note_index_in_scratch_buffer
  2. authorization
  3. open_scratch_buffer

ノートを開く

  1. GetNoteToCurrentBuffer
  2. display_note_in_scratch_buffer
  3. authorization
  4. open_scratch_buffer

更新:w

  1. update_note_from_current_buffer
  2. get_current_note
  3. authorization

ノート検索:Vimplenote -s

  1. search_notes_with_tags
  2. authorization
  3. open_scratch_buffer

ノートを開く

  1. GetNoteToCurrentBuffer
  2. display_note_in_scratch_buffer
  3. authorization
  4. open_scratch_buffer

更新:w

  1. update_note_from_current_buffer
  2. get_current_note

つまりget_current_note()でemptyとなって更新できない。

vimplenote-vim/autoload/vimplenote.vim

function! s:interface.update_note_from_current_buffer() dict
  let note = self.get_current_note()
  if empty(note)
    return
  endif

if len(self.authorization())

検索した場合は notes リストが空なので、更新できないということだった。

vimplenote-vim/autoload/vimplenote.vim

function! s:interface.get_current_note()
  let mx = '^VimpleNote:\zs\w\+'
  let key = matchstr(bufname('%'), mx)
  if len(key) == 0
    return {}
  endif
  let found = filter(copy(self.notes), 'v:val.key == key')
  if len(found) == 0
   return
endif

なら、検索したときに notes リストに結果を詰めようと思ったが、検索結果としては更新日付やタグといった情報が足りていない。0でとりあえず埋めとこうとしたが、そうすると更新するときにタグが空になってしまったりするので宜しくない。

また、リスト取得時に検索したノートが混じってしまい、更新日付が1970年のノートとして表示される。

じゃあ、更新するときに、検索したノートの場合は一覧取得の時とは別の実装で次の処理に行くようにしようと思ったが、更新に限らず、ノートに対する処理は notes に詰めこまれている前提なので全ての処理に改修を加えるのは一苦労。

パフォーマンスが劣化するけど、検索結果取得の時も、一覧取得と同様に各ノートを一つずつ取得して必要な情報を取ることにした。それでも、一覧表示時に検索したノートが混じるのは宜しくないので、検索したノートは削除するかたちで実装してみた。

vimplenote.vim 検索したノートも更新可能に

--- a/autoload/vimplenote.vim
+++ b/autoload/vimplenote.vim
@@ -122,6 +122,10 @@ function! s:interface.list_note_index_in_scratch_buffer() dict
     echohl ErrorMsg | echomsg "VimpleNote: " res.message | echohl None
     return
   endif
+  let found = filter(copy(self.notes), 'v:val.search == 1')
+  if len(found) > 0
+    let self.notes = []
+  endif
   let datas = webapi#json#decode(res.content)
   for note in datas.data
     if !note.deleted
@@ -143,6 +147,7 @@ function! s:interface.list_note_index_in_scratch_buffer() dict
       \  "key": note.key,
       \  "modifydate": note.modifydate,
       \  "deleted": note.deleted,
+      \  "search": 0,
       \})
     endif
   endfor
@@ -170,9 +175,27 @@ function! s:interface.search_notes_with_tags(...) dict
     return
   endif
   let datas = webapi#json#decode(res.content)
+  for result in datas.Response.Results
+    let url = printf('https://simple-note.appspot.com/api2/data/%s?auth=%s&email=%s', result.key, self.token, webapi#http#encodeURI(self.email))
+    let res = webapi#http#get(url)
+    if res.status !~ '^2'
+      echohl ErrorMsg | echomsg "VimpleNote: " res.message | echohl None
+      return
+    endif
+    let data = webapi#json#decode(res.content)
+    let lines = split(data.content, "\n")
+    call add(self.notes, {
+    \  "title": len(lines) > 0 ? lines[0] : '',
+    \  "tags": data.tags,
+    \  "key": result.key,
+    \  "modifydate": data.modifydate,
+    \  "deleted": data.deleted,
+    \  "search": 1,
+    \})
+  endfor
   call self.open_scratch_buffer("==VimpleNote==")
   silent %d _
-  call setline(1, map(datas.Response.Results, 'printf("%s | [%s]", v:val.key, matchstr(substitute(v:val.content, "\n", " ", "g"), "^.*\\%<60c"))'))
+  call setline(1, map(copy(self.notes), 'printf("%s [%s]", strftime("%Y/%m/%d %H:%M:%S", v:val.modifydate), matchstr(v:val.title, "^.*\\%<60c"))'))
   nnoremap <buffer> <cr> :call <SID>GetNoteToCurrentBuffer(0)<cr>
   setlocal nomodified
 endfunction
@@ -188,11 +211,7 @@ function! s:interface.display_note_in_scratch_buffer(flag) dict
   if line('.') == 0 || getline('.') == ''
     return
   endif
-  if a:flag
-    let note = self.notes[line('.')-1]
-  else
-    let note = { "key" : matchstr(getline('.'), '^[^ ]\+\ze') }
-  endif
+  let note = self.notes[line('.')-1]
   let url = printf('https://simple-note.appspot.com/api2/data/%s?auth=%s&email=%s', note.key, self.token, webapi#http#encodeURI(self.email))
   let res = webapi#http#get(url)
   if res.status !~ '^2'

vimplenote.vim 検索結果が残り続けるのを修正

@@ -174,6 +174,7 @@ function! s:interface.search_notes_with_tags(...) dict
     echohl ErrorMsg | echomsg "VimpleNote: " res.message | echohl None
     return
   endif
+  let self.notes = []
   let datas = webapi#json#decode(res.content)
   for result in datas.Response.Results
     let url = printf('https://simple-note.appspot.com/api2/data/%s?auth=%s&email=%s', result.key, self.token, webapi#http#encodeURI(self.email))

とりあえず、これで様子見だ。

それにしても、call setline(1, map([1,2,3], 'printf("%s | [%s]", "ddddd cccccc", "xxxxx")'))で、

ddddd cccccc | [xxxxx]
ddddd cccccc | [xxxxx]
ddddd cccccc | [xxxxx]

こうなるんだね…他filterとかなかなか、個人的に直感的に理解しにくいメソッドだ。