Cole o link da imagem na área de transferência ao editar o Markdown

9

Tenho uma imagem na área de transferência e quero colá-la no meu documento como texto [](img/image1.png).

Em vez de primeiro copiá-lo para esse diretório, quero fazê-lo ppressionando uma única tecla no Vim. Assim, ele conecta p, verifica se estou editando um arquivo Markdown, salva a imagem da área de transferência no local img/image1.pnge insere [](img/image1.png)no arquivo.

Isso é possível com o Vim?

Eu uso o macOS e o terminal Vim.

Maxim Kochurov
fonte
Para maior clareza, é "Copiei uma imagem diretamente como se estivesse digitando, digamos, palavra" ou "Copiei um arquivo de imagem no localizador"? (Na verdade, eu não sei se eles são diferentes ...) #
315 Joe Joe

Respostas:

2

O comando terminal habitual para acessar a área de transferência no Mac é pbpaste. No entanto, como isso não funciona para dados de imagem, precisamos recorrer ao AppleScript:

nnoremap <silent> <buffer> p :call MarkdownClipboardImage()<cr>

function! MarkdownClipboardImage() abort
  " Create `img` directory if it doesn't exist
  let img_dir = getcwd() . '/img'
  if !isdirectory(img_dir)
    silent call mkdir(img_dir)
  endif

  " First find out what filename to use
  let index = 1
  let file_path = img_dir . "/image" . index . ".png"
  while filereadable(file_path)
    let index = index + 1
    let file_path = img_dir . "/image" . index . ".png"
  endwhile

  let clip_command = 'osascript'
  let clip_command .= ' -e "set png_data to the clipboard as «class PNGf»"'
  let clip_command .= ' -e "set referenceNumber to open for access POSIX path of'
  let clip_command .= ' (POSIX file \"' . file_path . '\") with write permission"'
  let clip_command .= ' -e "write png_data to referenceNumber"'

  silent call system(clip_command)
  if v:shell_error == 1
    normal! p
  else
    execute "normal! i[](" . file_path . ")"
  endif
endfunction

Adicione o código acima a ~/.vim/after/ftplugin/markdown.vim.

Isso salva os dados da área de transferência no arquivo "img / image1.png" se ele contiver dados PNG. Em seguida, apenas usa o :normal!botão para inserir o link de remarcação desejado.

Se a área de transferência não contiver dados PNG (ou se não estivermos em um arquivo Markdown), ela executará um pcomando regular .

Se eu estivesse usando isso, eu o arrumaria para oferecer suporte a outros tipos de imagem e deixar o cursor em uma posição mais útil, mas isso funciona bem como uma prova de conceito.

(Eu também usaria um <leader>pmapeamento como sugerido por Karl Yngve Lervåg  - isso parece ser a funcionalidade que eu preferiria chamar especificamente - mas não foi isso que você pediu).

Leitura adicional

Rico
fonte
Bom, atualizei minha resposta com um link para o seu, já que sua solução realmente atende aos requisitos do MacOS.
Karl Yngve Lervåg
11
@ KarlYngveLervåg Obrigado, isso é muito gentil da sua parte. Eu nem teria escrito minha resposta se não fosse a sua: você me inspirou a encontrar uma solução nativa para Mac!
Rich
3

A solução a seguir deve funcionar na maioria dos sistemas Linux. Requer uma xclipferramenta relativamente atualizada . Para uma solução que funcione no MacOS / OSX, consulte a resposta de @ Rich .


Propus uma solução que mapeia em <leader>pvez de remapear p, pois acho que essa é uma abordagem muito mais saudável. A função SaveFileinspecionará a área de transferência com xclip. Se houver um arquivo de imagem, ele será salvo img/imageN.<ext>, a menos que o arquivo já exista. Ele também preencherá o *registro com o [](img/...)texto e o colará.

nnoremap <silent> <leader>p :call SaveFile()<cr>

function! SaveFile() abort
  let targets = filter(
        \ systemlist('xclip -selection clipboard -t TARGETS -o'),
        \ 'v:val =~# ''image''')
  if empty(targets) | return | endif

  let outdir = expand('%:p:h') . '/img'
  if !isdirectory(outdir)
    call mkdir(outdir)
  endif

  let mimetype = targets[0]
  let extension = split(mimetype, '/')[-1]
  let tmpfile = outdir . '/savefile_tmp.' . extension
  call system(printf('xclip -selection clipboard -t %s -o > %s',
        \ mimetype, tmpfile))

  let cnt = 0
  let filename = outdir . '/image' . cnt . '.' . extension
  while filereadable(filename)
    call system('diff ' . tmpfile . ' ' . filename)
    if !v:shell_error
      call delete(tmpfile)
      break
    endif

    let cnt += 1
    let filename = outdir . '/image' . cnt . '.' . extension
  endwhile

  if filereadable(tmpfile)
    call rename(tmpfile, filename)
  endif

  let @* = '[](' . fnamemodify(filename, ':.') . ')'
  normal! "*p
endfunction
Karl Yngve Lervåg
fonte
Esta solução falha silenciosamente para mim :(
Maxim Kochurov 11/11
Meu palpite é que você tem uma versão antiga do xclip. Você deve tentar executar os xclipcomandos no seu terminal.
Karl Yngve Lervåg
1

Com base nas respostas acima, criei um plug - in para o vim resolvendo meu problema no macos e possivelmente no linux. Espero que você ache este plugin útil. Também aprecio quaisquer contribuições e solicitações de recursos.

Maxim Kochurov
fonte
Acho que nunca vi isso antes. Obrigado pelo crédito no seu README! Também comecei a escrever um plugin, mas nunca consegui implementar todos os recursos que havia planejado.
Rich