From 97b5d322c90e121398c286e7cf976f80e8249ed6 Mon Sep 17 00:00:00 2001 From: Rene Schallner Date: Fri, 26 Nov 2021 04:49:51 +0100 Subject: [PATCH] support for IMAGE PASTING!!!!!!!!!!!!! --- README.md | 29 ++++++++++++++++ doc/telekasten.txt | 33 ++++++++++++++++++ lua/telekasten.lua | 86 +++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 140 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index bc2377d..88c7d0b 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,15 @@ Telekasten.nvim can optionally plug into [calendar-vim](https://github.com/mattn See below for installing and using it. +#### For pasting images: xclip (optional) +Telekasten.nvim supports pasting images from the clipboard. Currently, this is +only implemented for systems that have the `xclip` utility installed. + +On Ubuntu/Debian like systems: + +```console +$ sudo apt-get install xclip +``` ### 1. Install the plugin Install with your plugin manager of choice. Mine is [Vundle](https://github.com/VundleVim/Vundle.vim). @@ -68,6 +77,13 @@ require('telekasten').setup({ dailies = home .. '/' .. 'daily', weeklies = home .. '/' .. 'weekly', templates = home .. '/' .. 'templates', + + -- image subdir for pasting + -- subdir name + -- or nil if pasted images shouldn't go into a special subdir + image_subdir = "img", + + -- markdown file extension extension = ".md", -- following a link to a non-existing note will create it @@ -84,6 +100,11 @@ require('telekasten').setup({ -- template for newly created weekly notes (goto_thisweek) template_new_weekly= home .. '/' .. 'templates/weekly.md', + -- image link style + -- wiki: ![[image name]] + -- markdown: ![image name](image_subdir/xxxxx.png) + image_link_style = "wiki", + -- integrate with calendar-vim plug_into_calendar = true, calendar_opts = { @@ -103,6 +124,11 @@ END | `dailies` | path where your daily notes go | ~/zettelkasten/daily | | `weeklies` | path where your weekly notes go | ~/zettelkasten/weekly | | `templates` | path where your note templates go | ~/zettelkasten/templates | +| `image_subdir` | sub-directory where pasted images should go | img | +| | set to nil if pasted images shouldn't go into a special subdir | img | +| `image_link_style` | style of img links inserted when pasting images from clipboard | wiki | +| | `markdown` ... `![image name](image_subdir/xxxxx.png)` | | +| | `wiki` ... `![[image name]]` | | | `extension` | filename extension of your note files | .md | | `follow_creates_nonexisting` | following a link to a non-existing note will create it | true | | `dailies_create_nonexisting` | following a link to a non-existing daily note will create it | true | @@ -182,6 +208,7 @@ The plugin defines the following functions. - `follow_link()`: take text between brackets (linked note) and open a Telescope file finder with it: selects note to open (incl. preview) - with optional note creation for non-existing notes, honoring the configured template - `yank_notelink()` : yank a link to the current note, ready to paste - `show_calendar()` : opens up the calendar in a properly-sized vertical split at the very right +- `paste_img_and_link()` : pastes an image from the clipboard into a file under `image_subdir` and inserts a link to it at the current cursor position - `setup(opts)`: used for configuring paths, file extension, etc. To use one of the functions above, just run them with the `:lua ...` command. @@ -287,6 +314,7 @@ nnoremap zn :lua require('telekasten').new_note() nnoremap zN :lua require('telekasten').new_templated_note() nnoremap zy :lua require('telekasten').yank_notelink() nnoremap zc :lua require('telekasten').show_calendar() +nnoremap zi :lua require('telekasten').paste_img_and_link() " we could define [[ in **insert mode** to call insert link " inoremap [[ :lua require('telekasten').insert_link() @@ -310,3 +338,4 @@ hi tkHighlight ctermbg=yellow ctermfg=darkred cterm=bold Currently, the following things are hardcoded: - the file naming format for daily note files: `YYYY-MM-DD.ext` (e.g. `2021-11-21.md`) - the file naming format for weekly note files: `YYYY-Www.ext` (e.g. `2021-W46.md`) +- the file naming format for pasted images: `pasted_img_YYYYMMDDhhmmss.png` (e.g. `pasted_img_20211126041108.png`) diff --git a/doc/telekasten.txt b/doc/telekasten.txt index c945c3b..2dd1bce 100644 --- a/doc/telekasten.txt +++ b/doc/telekasten.txt @@ -55,6 +55,15 @@ telekasten.setup({opts}) home = '/path/to/directory', -- path to main markdown folder daily = '/path/to/directory', -- path to daily notes weekly = '/path/to/directory', -- path to weekly notes + + -- image subdir for pasting + -- subdir name + -- or nil if pasted images shouldn't go into a special subdir + image_subdir = "img", + + -- markdown file extension + extension = ".md", + templates = '/path/to/directory', -- path to templates extension = '.file extension', -- file extension of note files @@ -63,6 +72,12 @@ telekasten.setup({opts}) dailies_create_nonexisting = true, -- create non-existing dailies weeklies_create_nonexisting = true, -- create non-existing weeklies + -- image link style", + -- wiki: ![[image name]] + -- markdown: ![image name](image_subdir/xxxxx.png) + image_link_style = "wiki", + + -- specific note templates template_new_note = '/path/to/file', -- template for new notes template_new_daily = '/path/to/file', -- template for new daily notes @@ -124,6 +139,23 @@ telekasten.setup({opts}) Default: '.md' + *telekasten.settings.image_subdir* + image_subdir: ~ + Sub-directory where pasted images should go to. Set to `nil` if images + should not go into a sub-directory. + + Default: 'img' + + *telekasten.settings.image_link_style* + image_link_style: ~ + Style of links to insert when pasting an image. + + Valid options are: + - 'wiki' .. places links like this: `![[image_name]]` + - 'markdown' .. `![image_name](image_subdir/image_name)` + + Default: 'wiki' + *telekasten.settings.follow_create_nonexisting* follow_creates_nonexisting: ~ Flag that determines whether non-existing notes should be created when @@ -487,6 +519,7 @@ However, here are some suggestions: nnoremap zN :lua require('telekasten').new_templated_note() nnoremap zy :lua require('telekasten').yank_notelink() nnoremap zc :lua require('telekasten').show_calendar() + nnoremap zi :lua require('telekasten').paste_img_and_link() " we could define [[ in **insert mode** to call insert link " inoremap [[ :lua require('telekasten').insert_link() diff --git a/lua/telekasten.lua b/lua/telekasten.lua index a5882d3..d3419fd 100644 --- a/lua/telekasten.lua +++ b/lua/telekasten.lua @@ -19,6 +19,13 @@ local ZkCfg = { dailies = home .. "/" .. "daily", weeklies = home .. "/" .. "weekly", templates = home .. "/" .. "templates", + + -- image subdir for pasting + -- subdir name + -- or nil if pasted images shouldn't go into a special subdir + image_subdir = "img", + + -- markdown file extension extension = ".md", -- following a link to a non-existing note will create it @@ -31,6 +38,11 @@ local ZkCfg = { template_new_daily = home .. "/" .. "templates/daily_tk.md", template_new_weekly = home .. "/" .. "templates/weekly_tk.md", + -- image link style + -- wiki: ![[image name]] + -- markdown: ![image name](image_subdir/xxxxx.png) + image_link_style = "wiki", + -- integrate with calendar-vim plug_into_calendar = true, calendar_opts = { @@ -43,14 +55,6 @@ local ZkCfg = { }, } --- ---------------------------------------------------------------------------- - -local note_type_templates = { - normal = ZkCfg.template_new_note, - daily = ZkCfg.template_new_daily, - weekly = ZkCfg.template_new_weekly, -} - local function file_exists(fname) local f = io.open(fname, "r") -- print("checking for " .. fname) @@ -62,6 +66,71 @@ local function file_exists(fname) end end +-- ---------------------------------------------------------------------------- +-- image stuff +local imgFromClipboard = function() + if vim.fn.executable("xclip") == 0 then + print("No xclip installed!") + return + end + + -- TODO: check `xclip -selection clipboard -t TARGETS -o` for the occurence of `image/png` + + -- using plenary.job::new():sync() with on_stdout(_, data) unfortunately did some weird ASCII translation on the + -- data, so the PNGs were invalid. It seems like 0d 0a and single 0a bytes were stripped by the plenary job: + -- + -- plenary job version: + -- $ hexdump -C /tmp/x.png|head + -- 00000000 89 50 4e 47 1a 00 00 00 49 48 44 52 00 00 03 19 |.PNG....IHDR....| + -- 00000010 00 00 01 c1 08 02 00 00 00 8a 73 e1 c3 00 00 00 |..........s.....| + -- 00000020 09 70 48 59 73 00 00 0e c4 00 00 0e c4 01 95 2b |.pHYs..........+| + -- 00000030 0e 1b 00 00 20 00 49 44 41 54 78 9c ec dd 77 58 |.... .IDATx...wX| + -- 00000040 14 d7 fa 07 f0 33 bb b3 4b af 0b 2c 08 22 1d 04 |.....3..K..,."..| + -- 00000050 05 11 10 1b a2 54 c5 1e bb b1 c6 98 c4 68 72 4d |.....T.......hrM| + -- 00000060 e2 cd 35 37 26 b9 49 6e 6e 7e f7 a6 98 98 a8 29 |..57&.Inn~.....)| + -- 00000070 26 6a 8c 51 63 8b bd 00 8a 58 40 b0 81 08 2a 45 |&j.Qc....X@...*E| + -- 00000080 69 52 17 58 ca ee b2 f5 f7 c7 ea 4a 10 66 d7 01 |iR.X.......J.f..| + -- 00000090 b1 e4 fb 79 7c f2 2c e7 cc 39 e7 3d 67 66 b3 2f |...y|.,..9.=gf./| + -- + -- OK version + -- $ hexdump -C /tmp/x2.png|head + -- 00000000 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 |.PNG........IHDR| + -- 00000010 00 00 03 19 00 00 01 c1 08 02 00 00 00 8a 73 e1 |..............s.| + -- 00000020 c3 00 00 00 09 70 48 59 73 00 00 0e c4 00 00 0e |.....pHYs.......| + -- 00000030 c4 01 95 2b 0e 1b 00 00 20 00 49 44 41 54 78 9c |...+.... .IDATx.| + -- 00000040 ec dd 77 58 14 d7 fa 07 f0 33 bb b3 4b af 0b 2c |..wX.....3..K..,| + -- 00000050 08 22 1d 04 05 11 10 1b a2 54 c5 1e bb b1 c6 98 |.".......T......| + -- 00000060 c4 68 72 4d e2 cd 35 37 26 b9 49 6e 6e 7e f7 a6 |.hrM..57&.Inn~..| + -- 00000070 98 98 a8 29 26 6a 8c 51 63 8b bd 00 8a 58 40 b0 |...)&j.Qc....X@.| + -- 00000080 81 08 2a 45 69 52 17 58 ca ee b2 f5 f7 c7 ea 4a |..*EiR.X.......J| + -- 00000090 10 66 d7 01 b1 e4 fb 79 7c f2 2c e7 cc 39 e7 3d |.f.....y|.,..9.=| + + local pngname = "pasted_img_" .. os.date("%Y%m%d%H%M%S") .. ".png" + local pngpath = ZkCfg.home + local relpath = pngname + + if ZkCfg.image_subdir then + relpath = ZkCfg.image_subdir .. "/" .. pngname + end + pngpath = pngpath .. "/" .. pngname + + os.execute("xclip -selection clipboard -t image/png -o > " .. pngpath) + if file_exists(pngpath) then + if ZkCfg.image_link_style == "markdown" then + vim.api.nvim_put({ "![" .. pngname .. "](" .. relpath .. "]" }, "", false, true) + else + vim.api.nvim_put({ "![[" .. pngname .. "]]" }, "", false, true) + end + end +end +-- end of image stuff + +local note_type_templates = { + normal = ZkCfg.template_new_note, + daily = ZkCfg.template_new_daily, + weekly = ZkCfg.template_new_weekly, +} + local function daysuffix(day) if (day == "1") or (day == "21") or (day == "31") then return "st" @@ -592,5 +661,6 @@ local M = { show_calendar = ShowCalendar, CalendarSignDay = CalendarSignDay, CalendarAction = CalendarAction, + paste_img_and_link = imgFromClipboard, } return M