diff --git a/README.md b/README.md
index 57d95a1..acf5c78 100644
--- a/README.md
+++ b/README.md
@@ -52,7 +52,6 @@ also just insert a link to the note or yank a link instead of opening the note.
![](img/tags-linkcounts.png)
-
## Contents
@@ -76,6 +75,7 @@ also just insert a link to the note or yank a link instead of opening the note.
- [Hard-coded stuff](#hard-coded-stuff)
## Requirements
+
Telekasten requires Neovim v0.6.0 or higher. Besides that, its only mandatory
dependency of is
[telescope.nvim](https://github.com/nvim-telescope/telescope.nvim), which acts
@@ -115,7 +115,6 @@ telekasten.requirements`).
-
Vim-plug
@@ -136,8 +135,8 @@ telekasten.requirements`).
-
### Base setup
+
In order to use Telekasten, you need to first require its setup function
somewhere in your `init.lua`. Take this opportunity to indicate the path for
your notes directory. If you do not specify anything, the plugin will ask you to
@@ -148,6 +147,7 @@ require('telekasten').setup({
home = vim.fn.expand("~/zettelkasten"), -- Put the name of your notes directory here
})
```
+
**NOTE:** For Windows users, please indicate the path as
`C:/Users/username/zettelkasten/`. See `:h telekasten.windows` for more details
about the specificities for Windows.
@@ -155,26 +155,29 @@ about the specificities for Windows.
### Suggested dependencies
#### Calendar
+
Telekasten interacts very nicely with
[calendar-vim](https://github.com/renerocksai/calendar-vim). Installing this
plugin will allow you to create journal entries for the selected dates and
highlight dates with attached entries.
#### Image preview
+
Various plugins or external tools can be used as image previewers to help you
pick the correct illustrations for your note.
+
- [telescope-media-files.nvim](https://github.com/nvim-telescope/telescope-media-files.nvim)
- [catimg](https://github.com/posva/catimg)
- [viu](https://github.com/atanunq/viu)
#### Image pasting
+
- [xclip](https://github.com/astrand/xclip)
- [wl-clipboard](https://github.com/bugaevc/wl-clipboard)
_Image pasting is supported by default on MacOS, it is not necessary to install
any other tool._
-
#### Other useful resources/plugins
While they do not interact directly with Telekasten, the following plugins
@@ -191,15 +194,18 @@ greatly improve the note-taking experience.
generate a table of contents for your markdown documents
- [synctodo](https://github.com/cnshsliu/synctodo): bash script to sync todos
among Telekasten, Mac and iPhone reminders.
-
+- [telescope-all-recent](https://github.com/prochri/telescope-all-recent.nvim):
+ shows files you have recently opened.
## Usage
The simplest way to use the plugin is to call directly the related Telekasten
command:
+
```vim
:Telekasten
```
+
Advanced use
Each sub-command is implemented by a specific lua function. While high-level
@@ -211,14 +217,13 @@ custom mappings.
:lua require('telekasten').search_notes()
```
-See the [wiki](https://github.com/renerocksai/telekasten.nvim/wiki/Mappings#advanced-key-mappings) for more details regarding advanced usage.
### Commands
The following sub-commands are defined:
-- `panel` : brings up the [command palette](command-palette)
+- `panel` : brings up the [command palette](#command-palette)
- `find_notes` : Find notes by title (filename)
- `show_tags` : brings up the tag list. From there you can select a tag to search for tagged notes - or yank or insert the tag
- `find_daily_notes` : Find daily notes by title (date)
@@ -243,8 +248,7 @@ The following sub-commands are defined:
- `switch_vault` : switch the vault. Brings up a picker. See the `vaults` config
option for more.
-
-### Command palette
+### Command palette
Telekasten comes with a small helper command palette that let the user browse
the different commands available. This feature is quite similar to the excellent
@@ -252,14 +256,15 @@ the different commands available. This feature is quite similar to the excellent
limited to Telekasten.
You can call this panel using
+
```vim
:Telekasten panel
```
+
This can be especially useful if all your Telekasten mappings start with the
same prefix. In that case, bind the command panel to the prefix only and it will
pop-up when you hesitate to complete the mapping.
-
## Customization
### Highlights
@@ -268,6 +273,7 @@ Telekasten.nvim allows you to color your `[[links]]` and `#tags` by providing
the following syntax groups:
- `tkLink` : the link title inside the brackets
+- `tkAliasedLink` : the concealed portion of `[[concealed link|link alias]]`
- `tkBrackets` : the brackets surrounding the link title
- `tkHighlight` : ==highlighted== text (non-standard markdown)
- `tkTag` : well, tags
@@ -275,7 +281,6 @@ the following syntax groups:
An additional `CalNavi` group is defined to tweak the appearance of the calendar
navigation button.
-
```vim
" Example
hi tkLink ctermfg=Blue cterm=bold,underline guifg=blue gui=bold,underline
@@ -289,7 +294,6 @@ workflow even smoother. A good idea is to take advantage of the [command
palette][#command-palette] and start all your mappings with the same prefix
(`z`, for `Z`ettelkasten for instance).
-
```lua
-- Launch panel if nothing is typed after z
vim.keymap.set("n", "z", "Telekasten panel")
@@ -309,18 +313,16 @@ vim.keymap.set("i", "[[", "Telekasten insert_link")
```
-
#### Advanced mappings
+
Each Telekasten command is bound to a specific lua function. As lua functions
can accept arguments, it is possible to craft special mappings to tailor the
execution of a function to your specific need.
-See the [wiki](https://github.com/renerocksai/telekasten.nvim/wiki/Mappings#advanced-key-mappings) for more details regarding advanced key mappings.
-
-
## Features
### Vaults
+
Telekasten allows the user to have completely separated note collections and
switch between them easily. Simply add data to the `vaults` table in the
configuration and configure each vault as you wish.
@@ -356,15 +358,14 @@ these can be previewed.
See the documentation for more details regarding the different types of links
(`:h telekasten.link_notation`).
-
### Tag notation
Telekasten supports the following tag notations:
1. `#tag`
-2. `:tag:`
-3. `yaml-bare`: bare tags in a tag collection in the yaml metadata:
-
+2. `@tag`
+3. `:tag:`
+4. `yaml-bare`: bare tags in a tag collection in the yaml metadata:
See the documentation for more details regarding the tag syntax (`:h
telekasten.tag_notation`).
diff --git a/doc/telekasten.txt b/doc/telekasten.txt
index 1b136a6..019a798 100644
--- a/doc/telekasten.txt
+++ b/doc/telekasten.txt
@@ -69,8 +69,8 @@ telekasten.setup({opts})
-- Main paths
home = '/path/to/directory', -- path to main notes folder
- daily = '/path/to/directory', -- path to daily notes
- weekly = '/path/to/directory', -- path to weekly notes
+ dailies = '/path/to/directory', -- path to daily notes
+ weeklies = '/path/to/directory', -- path to weekly notes
templates = '/path/to/directory', -- path to templates
-- Specific note templates
@@ -103,6 +103,9 @@ telekasten.setup({opts})
dailies_create_nonexisting = true, -- create non-existing dailies
weeklies_create_nonexisting = true, -- create non-existing weeklies
+ -- skip telescope prompt for goto_today and goto_thisweek
+ journal_auto_open = false,
+
-- Image link style",
-- wiki: ![[image name]]
-- markdown: ![](image_subdir/xxxxx.png)
@@ -114,7 +117,7 @@ telekasten.setup({opts})
-- Make syntax available to markdown buffers and telescope previewers
install_syntax = true,
- -- Tag notation: '#tag', ':tag:', 'yaml-bare'
+ -- Tag notation: '#tag', '@tag', ':tag:', 'yaml-bare'
tag_notation = "#tag",
-- When linking to a note in subdir/, create a [[subdir/title]] link
@@ -125,7 +128,9 @@ telekasten.setup({opts})
command_palette_theme = "ivy",
-- Tag list theme:
- -- get_cursor: small tag list at cursor; ivy and dropdown like above
+ -- get_cursor (small tag list at cursor)
+ -- dropdown (window)
+ -- ivy (bottom panel)
show_tags_theme = "ivy",
-- Previewer for media files (images mostly)
@@ -134,6 +139,20 @@ telekasten.setup({opts})
-- "viu-previewer" if you have viu installed
media_previewer = "telescope-media-files",
+ -- Customize insert image and preview image files list. This is useful
+ -- to add optional filetypes into filtered list (for example
+ -- telescope-media-files optionally supporting svg preview)
+ media_extensions = {
+ ".png",
+ ".jpg",
+ ".bmp",
+ ".gif",
+ ".pdf",
+ ".mp4",
+ ".webm",
+ ".webp",
+ },
+
-- Calendar integration
plug_into_calendar = true, -- use calendar integration
calendar_opts = {
@@ -162,6 +181,8 @@ telekasten.setup({opts})
}
},
+ -- Specify a clipboard program to use
+ clipboard_program = "", -- xsel, xclip, wl-paste, osascript
}
<
@@ -331,6 +352,14 @@ telekasten.setup({opts})
Default: true
+ *telekasten.settings.journal_auto_open*
+ journal_auto_open: ~
+ Flag that determines whether the telescope picker should be used when
+ opening the daily and weekly notes, or if they should be directly
+ created/opened.
+
+ Default: false
+
*telekasten.settings.template_new_note*
template_new_note: ~
Markdown template for new notes. Set to `nil` if you don't want a
@@ -369,6 +398,7 @@ telekasten.setup({opts})
Valid options are:
- `'#tag'`
+ - `'@tag'`
- `':tag:'`
- `'yaml-bare'`
@@ -428,7 +458,7 @@ telekasten.setup({opts})
*telekasten.settings.media_previewer*
media_previewer:~
- Previewer used for viewing media / image files. There are two
+ Previewer used for viewing media / image files. There are three
options:
- `'telescope-media-files'` : use the telescope-media-files.nvim
plugin
@@ -446,6 +476,14 @@ telekasten.setup({opts})
Default: `nil`
Example: `"call jobstart('firefox --new-window {{url}}')"`
+
+ *telekasten.settings.enable_create_new*
+ enable_create_new: ~
+ Flag that determines if creating new notes with in enabled when
+ using the `find_notes` picker.
+
+ Default: true
+
*telekasten.calendar_opts*
-----------------------------------
Valid keys for {opts.calendar_opts}
@@ -496,10 +534,7 @@ groups:
- `tkBrackets` : the brackets surrounding the link title
- `tkHighlight` : ==highlighted== text (non-standard markdown)
- `tkTag` : well, tags
-- `tkAliasedLink` : link with alias
-- `tkHighlightedAliasedLink` : link with alias in `tkAliasedLink`
-- `tkLinkAlias` : body of the link (left part of `[[aaa|bbb]]`)
-- `tkLinkBody` : alias of the link (right part of `[[aaa|bbb]]`)
+- `tkAliasedLink` : the concealed part of the link (left part of `[[aaa|bbb]]`)
`tkHighlight`, has nothing to do with links but I added it anyway, since I like
highlighting text when taking notes.
@@ -530,6 +565,12 @@ You can assign colors to the new syntax groups in your `init.vim`:
hi tkTag ctermfg=175 guifg=#d3869B
<
+NOTE: Users configuring the following highlight groups prior to 09/2023, be aware they are deprecated:
+- `tkHighlightedAliasLink`: this syntax group is now covered by `tkHighlight`
+- `tkLinkBody`: this syntax group is renamed to `tkAliasedLink`
+- `tkAliasedLink`: this group used to cover the whole link, it is now equivalent to the former `tkLinkBody`
+- `tkLinkAlias`: this rule is deprecated
+
================================================================================
Section 3: Usage *telekasten.usage*
@@ -666,7 +707,7 @@ telekasten.insert_link({opts})~
Default: `nil`
*telekasten.follow_link()*
-telekasten.insert_link()~
+telekasten.follow_link()~
Take the text between the brackets of a link pointing to a linked note, or
of a tag and open a Telescope file finder with it.
@@ -817,8 +858,9 @@ Section 3.2: Tag Notation *telekasten.tag_notation*
Telekasten supports the following tag notations:
1. `#tag`
-2. `:tag:`
-3. bare tags in a tag collection in the yaml metadata:
+2. `@tag`
+3. `:tag:`
+4. bare tags in a tag collection in the yaml metadata:
>
---
title: My awesome note
diff --git a/lua/telekasten.lua b/lua/telekasten.lua
index b763c8d..ce6fa93 100644
--- a/lua/telekasten.lua
+++ b/lua/telekasten.lua
@@ -59,40 +59,47 @@ local function make_config_path_absolute(path)
if not (Path:new(path):is_absolute()) and path ~= nil then
ret = config.options.home .. "/" .. path
end
- return ret:gsub("/$", "")
+
+ if ret ~= nil then
+ ret = ret:gsub("/$", "")
+ end
+
+ return ret
end
local function recursive_substitution(dir, old, new)
- if not fileutils.global_dir_check() then
- return
- end
+ fileutils.global_dir_check(function(dir_check)
+ if not dir_check then
+ return
+ end
- if vim.fn.executable("sed") == 0 then
- vim.api.nvim_err_write("Sed not installed!\n")
- return
- end
+ if vim.fn.executable("sed") == 0 then
+ vim.api.nvim_err_write("Sed not installed!\n")
+ return
+ end
- old = tkutils.grep_escape(old)
- new = tkutils.grep_escape(new)
+ old = tkutils.grep_escape(old)
+ new = tkutils.grep_escape(new)
- local sedcommand = "sed -i"
- if vim.fn.has("mac") == 1 then
- sedcommand = "sed -i ''"
- end
-
- -- 's|\(\[\[foo\)\([]#|\]\)|\[\[MYTEST\2|g'
- local replace_cmd = "rg -0 -l -t markdown '"
- .. old
- .. "' "
- .. dir
- .. " | xargs -0 "
- .. sedcommand
- .. " 's|\\("
- .. old
- .. "\\)\\([]#|]\\)|"
- .. new
- .. "\\2|g' >/dev/null 2>&1"
- os.execute(replace_cmd)
+ local sedcommand = "sed -i"
+ if vim.fn.has("mac") == 1 then
+ sedcommand = "sed -i ''"
+ end
+
+ -- 's|\(\[\[foo\)\([]#|\]\)|\[\[MYTEST\2|g'
+ local replace_cmd = "rg -0 -l -t markdown '"
+ .. old
+ .. "' "
+ .. dir
+ .. " | xargs -0 "
+ .. sedcommand
+ .. " 's|\\("
+ .. old
+ .. "\\)\\([]#|]\\)|"
+ .. new
+ .. "\\2|g' >/dev/null 2>&1"
+ os.execute(replace_cmd)
+ end)
end
local function save_all_mod_buffers()
@@ -160,24 +167,33 @@ local function make_relative_path(bufferpath, imagepath, sep)
end
local function imgFromClipboard()
- if not fileutils.global_dir_check() then
- return
- end
+ fileutils.global_dir_check(function(dir_check)
+ if not dir_check then
+ return
+ end
- local get_paste_command
- if vim.fn.executable("xclip") == 1 then
- get_paste_command = function(dir, filename)
+ local paste_command = {}
+ paste_command["xsel"] = function(dir, filename)
+ local _image_path = vim.fn.system("xsel --clipboard --output")
+ local image_path = _image_path:gsub("file://", "")
+ if
+ vim.fn
+ .system("file --mime-type -b " .. image_path)
+ :gsub("%s+", "")
+ == "image/png"
+ then
+ return "cp " .. image_path .. " " .. dir .. "/" .. filename
+ else
+ return ""
+ end
+ end
+ paste_command["xclip"] = function(dir, filename)
return "xclip -selection clipboard -t image/png -o > "
.. dir
.. "/"
.. filename
end
- elseif vim.fn.executable("wl-paste") == 1 then
- get_paste_command = function(dir, filename)
- return "wl-paste -n -t image/png > " .. dir .. "/" .. filename
- end
- elseif vim.fn.executable("osascript") == 1 then
- get_paste_command = function(dir, filename)
+ paste_command["osascript"] = function(dir, filename)
return string.format(
'osascript -e "tell application \\"System Events\\" to write (the clipboard as «class PNGf») to '
.. '(make new file at folder \\"%s\\" with properties {name:\\"%s\\"})"',
@@ -185,68 +201,95 @@ local function imgFromClipboard()
filename
)
end
- else
- vim.api.nvim_err_write("No xclip installed!\n")
- return
- end
- -- TODO: check `xclip -selection clipboard -t TARGETS -o` for the occurence of `image/png`
+ paste_command["wl-paste"] = function(dir, filename)
+ return "wl-paste -n -t image/png > " .. dir .. "/" .. filename
+ end
- -- 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 pngdir = config.options.image_subdir or config.options.home
- local png = Path:new(pngdir, pngname).filename
- local relpath = make_relative_path(vim.fn.expand("%:p"), png, "/")
-
- local output = vim.fn.system(get_paste_command(pngdir, pngname))
- if output ~= "" then
- -- Remove empty file created by previous command if failed
- vim.fn.system("rm " .. png)
- vim.api.nvim_err_writeln(
- string.format(
- "Unable to write image %s.\nIs there an image on the clipboard?\nSee also issue 131",
- png
+ local get_paste_command
+ if paste_command[config.options.clipboard_program] ~= nil then
+ if vim.fn.executable(config.options.clipboard_program) ~= 1 then
+ vim.api.nvim_err_write(
+ "The clipboard program specified [`"
+ .. config.options.clipboard_program
+ .. "`] is not executable or not in your $PATH\n"
+ )
+ end
+ get_paste_command = paste_command[config.options.clipboard_program]
+ elseif vim.fn.executable("xsel") == 1 then
+ get_paste_command = paste_command["xsel"]
+ elseif vim.fn.executable("xclip") == 1 then
+ get_paste_command = paste_command["xclip"]
+ elseif vim.fn.executable("wl-paste") == 1 then
+ get_paste_command = paste_command["wl-paste"]
+ elseif vim.fn.executable("osascript") == 1 then
+ get_paste_command = paste_command["osascript"]
+ else
+ vim.api.nvim_err_write(
+ "No clipboard programs found!\nChecked executables: xsel, xclip, wl-paste, osascript\n"
)
- )
- end
+ 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 pngdir = config.options.image_subdir
+ and config.options.image_subdir
+ or config.options.home
+ local png = Path:new(pngdir, pngname).filename
+ local relpath = make_relative_path(vim.fn.expand("%:p"), png, "/")
+
+ local output = vim.fn.system(get_paste_command(pngdir, pngname))
+ if output ~= "" then
+ -- Remove empty file created by previous command if failed
+ vim.fn.system("rm " .. png)
+ vim.api.nvim_err_writeln(
+ string.format(
+ "Unable to write image %s.\nIs there an image on the clipboard?\nSee also issue 131",
+ png
+ )
+ )
+ end
- if fileutils.file_exists(png) then
- if config.options.image_link_style == "markdown" then
- vim.api.nvim_put({ "![](" .. relpath .. ")" }, "", true, true)
+ if fileutils.file_exists(png) then
+ if config.options.image_link_style == "markdown" then
+ vim.api.nvim_put({ "![](" .. relpath .. ")" }, "", true, true)
+ else
+ vim.api.nvim_put({ "![[" .. pngname .. "]]" }, "", true, true)
+ end
else
- vim.api.nvim_put({ "![[" .. pngname .. "]]" }, "", true, true)
+ vim.api.nvim_err_writeln("Unable to write image " .. png)
end
- else
- vim.api.nvim_err_writeln("Unable to write image " .. png)
- end
+ end)
end
-- end of image stuff
@@ -256,7 +299,8 @@ local function create_note_from_template(
uuid,
filepath,
templatefn,
- calendar_info
+ calendar_info,
+ callback
)
-- first, read the template file
local lines = {}
@@ -267,21 +311,34 @@ local function create_note_from_template(
end
-- now write the output file, substituting vars line by line
- local ofile = io.open(filepath, "a")
- for _, line in pairs(lines) do
- ofile:write(
- templates.subst_templated_values(
- line,
- title,
- calendar_info,
- uuid,
- config.options.calendar_opts.calendar_monday
- ) .. "\n"
- )
- end
+ local file_dir = filepath:match("(.*/)") or ""
+ fileutils.check_dir_and_ask(
+ file_dir,
+ "Create weekly dir",
+ function(dir_succeed)
+ if dir_succeed == false then
+ return
+ end
- ofile:flush()
- ofile:close()
+ local ofile = io.open(filepath, "a")
+
+ for _, line in pairs(lines) do
+ ofile:write(
+ templates.subst_templated_values(
+ line,
+ title,
+ calendar_info,
+ uuid,
+ config.options.calendar_opts.calendar_monday
+ ) .. "\n"
+ )
+ end
+
+ ofile:flush()
+ ofile:close()
+ callback()
+ end
+ )
end
--- Pinfo
@@ -534,10 +591,6 @@ function Pinfo:resolve_link(title, opts)
-- final round, there still can be a subdir mess-up
if not Path:new(self.filepath):parent():exists() then
print("Path " .. self.filepath .. " is invalid!")
- -- local fname_only = Path:new(self.filename):_split()
- -- fname_only = fname_only[#fname_only]
- -- self.filepath = opts.home .. "/" .. fname_only
- self.filepath = ""
end
end
@@ -649,8 +702,11 @@ local picker_actions = {}
-- - this requires the telescope-media-files.nvim extension
local function find_files_sorted(opts)
opts = opts or {}
+ local search_pattern = opts.search_pattern or nil
+ local search_depth = opts.search_depth or nil
+ local scan_opts = { search_pattern = search_pattern, depth = search_depth }
- local file_list = scan.scan_dir(opts.cwd, {})
+ local file_list = scan.scan_dir(opts.cwd, scan_opts)
local filter_extensions = opts.filter_extensions
or config.options.filter_extensions
file_list = filter_filetypes(file_list, filter_extensions)
@@ -940,49 +996,62 @@ local function FindDailyNotes(opts)
opts.close_after_yanking = opts.close_after_yanking
or config.options.close_after_yanking
- if not fileutils.global_dir_check() then
- return
- end
-
- local today = os.date(dateutils.dateformats.date)
- local fname = config.options.dailies
- .. "/"
- .. today
- .. config.options.extension
- local fexists = fileutils.file_exists(fname)
- if
- (fexists ~= true)
- and (
- (opts.dailies_create_nonexisting == true)
- or config.options.dailies_create_nonexisting == true
- )
- then
- create_note_from_template(
- today,
- nil,
- fname,
- M.note_type_templates.daily
- )
- opts.erase = true
- opts.erase_file = fname
- end
+ fileutils.global_dir_check(function(dir_check)
+ if not dir_check then
+ return
+ end
- find_files_sorted({
- prompt_title = "Find daily note",
- cwd = config.options.dailies,
- find_command = config.options.find_command,
- attach_mappings = function(_, map)
- actions.select_default:replace(picker_actions.select_default)
- map("i", "", picker_actions.yank_link(opts))
- map("i", "", picker_actions.paste_link(opts))
- map("n", "", picker_actions.yank_link(opts))
- map("n", "", picker_actions.paste_link(opts))
- map("n", "", picker_actions.close(opts))
- map("n", "", picker_actions.close(opts))
- return true
- end,
- sort = config.options.sort,
- })
+ local today = os.date(dateutils.dateformats.date)
+ local fname = config.options.dailies
+ .. "/"
+ .. today
+ .. config.options.extension
+ local fexists = fileutils.file_exists(fname)
+ local function picker()
+ find_files_sorted({
+ prompt_title = "Find daily note",
+ cwd = config.options.dailies,
+ find_command = config.options.find_command,
+ search_pattern = "%d%d%d%d%-%d%d%-%d%d",
+ search_depth = 1,
+ attach_mappings = function(_, map)
+ actions.select_default:replace(
+ picker_actions.select_default
+ )
+ map("i", "", picker_actions.yank_link(opts))
+ map("i", "", picker_actions.paste_link(opts))
+ map("n", "", picker_actions.yank_link(opts))
+ map("n", "", picker_actions.paste_link(opts))
+ map("n", "", picker_actions.close(opts))
+ map("n", "", picker_actions.close(opts))
+ return true
+ end,
+ sort = config.options.sort,
+ })
+ end
+ if
+ (fexists ~= true)
+ and (
+ (opts.dailies_create_nonexisting == true)
+ or config.options.dailies_create_nonexisting == true
+ )
+ then
+ create_note_from_template(
+ today,
+ nil,
+ fname,
+ M.note_type_templates.daily,
+ nil,
+ function()
+ opts.erase = true
+ opts.erase_file = fname
+ picker()
+ end
+ )
+ return
+ end
+ picker()
+ end)
end
--
@@ -998,49 +1067,64 @@ local function FindWeeklyNotes(opts)
opts.close_after_yanking = opts.close_after_yanking
or config.options.close_after_yanking
- if not fileutils.global_dir_check() then
- return
- end
+ fileutils.global_dir_check(function(dir_check)
+ if not dir_check then
+ return
+ end
- local title = os.date(dateutils.dateformats.isoweek)
- local fname = config.options.weeklies
- .. "/"
- .. title
- .. config.options.extension
- local fexists = fileutils.file_exists(fname)
- if
- (fexists ~= true)
- and (
- (opts.weeklies_create_nonexisting == true)
- or config.options.weeklies_create_nonexisting == true
- )
- then
- create_note_from_template(
- title,
- nil,
- fname,
- M.note_type_templates.weekly
- )
- opts.erase = true
- opts.erase_file = fname
- end
+ local title = os.date(dateutils.dateformats.isoweek)
+ local fname = config.options.weeklies
+ .. "/"
+ .. title
+ .. config.options.extension
+ local fexists = fileutils.file_exists(fname)
+
+ local function picker()
+ find_files_sorted({
+ prompt_title = "Find weekly note",
+ cwd = config.options.weeklies,
+ find_command = config.options.find_command,
+ search_pattern = "%d%d%d%d%-W%d+",
+ search_depth = 1,
+ attach_mappings = function(_, map)
+ actions.select_default:replace(
+ picker_actions.select_default
+ )
+ map("i", "", picker_actions.yank_link(opts))
+ map("i", "", picker_actions.paste_link(opts))
+ map("n", "", picker_actions.yank_link(opts))
+ map("n", "", picker_actions.paste_link(opts))
+ map("n", "", picker_actions.close(opts))
+ map("n", "", picker_actions.close(opts))
+ return true
+ end,
+ sort = config.options.sort,
+ })
+ end
- find_files_sorted({
- prompt_title = "Find weekly note",
- cwd = config.options.weeklies,
- find_command = config.options.find_command,
- attach_mappings = function(_, map)
- actions.select_default:replace(picker_actions.select_default)
- map("i", "", picker_actions.yank_link(opts))
- map("i", "", picker_actions.paste_link(opts))
- map("n", "", picker_actions.yank_link(opts))
- map("n", "", picker_actions.paste_link(opts))
- map("n", "", picker_actions.close(opts))
- map("n", "", picker_actions.close(opts))
- return true
- end,
- sort = config.options.sort,
- })
+ if
+ (fexists ~= true)
+ and (
+ (opts.weeklies_create_nonexisting == true)
+ or config.options.weeklies_create_nonexisting == true
+ )
+ then
+ create_note_from_template(
+ title,
+ nil,
+ fname,
+ M.note_type_templates.weekly,
+ nil,
+ function()
+ opts.erase = true
+ opts.erase_file = fname
+ picker()
+ end
+ )
+ return
+ end
+ picker()
+ end)
end
--
@@ -1058,52 +1142,62 @@ local function InsertLink(opts)
opts.subdirs_in_links = opts.subdirs_in_links
or config.options.subdirs_in_links
- if not fileutils.global_dir_check() then
- return
- end
+ fileutils.global_dir_check(function(dir_check)
+ if not dir_check then
+ return
+ end
- local cwd = config.options.home
- local find_command = config.options.find_command
- local sort = config.options.sort
- local attach_mappings = function(prompt_bufnr, map)
- actions.select_default:replace(function()
- actions.close(prompt_bufnr)
- local selection = action_state.get_selected_entry()
- local pinfo = Pinfo:new({
- filepath = selection.filename or selection.value,
- opts,
- })
- vim.api.nvim_put({ "[[" .. pinfo.title .. "]]" }, "", false, true)
- if opts.i then
- vim.api.nvim_feedkeys("a", "m", false)
- end
- end)
- map("i", "", picker_actions.yank_link(opts))
- map("i", "", picker_actions.paste_link(opts))
- map("n", "", picker_actions.yank_link(opts))
- map("n", "", picker_actions.paste_link(opts))
- map("i", "", picker_actions.paste_link(opts))
- map("n", "", picker_actions.paste_link(opts))
- return true
- end
+ local cwd = config.options.home
+ local find_command = config.options.find_command
+ local sort = config.options.sort
+ local attach_mappings = function(prompt_bufnr, map)
+ actions.select_default:replace(function()
+ actions.close(prompt_bufnr)
+ local selection = action_state.get_selected_entry()
+ if selection == nil then
+ selection = { filename = action_state.get_current_line() }
+ end
+ local pinfo = Pinfo:new({
+ filepath = selection.filename or selection.value,
+ opts,
+ })
+ vim.api.nvim_put(
+ { "[[" .. pinfo.title .. "]]" },
+ "",
+ false,
+ true
+ )
+ if opts.i then
+ vim.api.nvim_feedkeys("a", "m", false)
+ end
+ end)
+ map("i", "", picker_actions.yank_link(opts))
+ map("i", "", picker_actions.paste_link(opts))
+ map("n", "", picker_actions.yank_link(opts))
+ map("n", "", picker_actions.paste_link(opts))
+ map("i", "", picker_actions.paste_link(opts))
+ map("n", "", picker_actions.paste_link(opts))
+ return true
+ end
- if opts.with_live_grep then
- builtin.live_grep({
- prompt_title = "Insert link to note with live grep",
- cwd = cwd,
- attach_mappings = attach_mappings,
- find_command = find_command,
- sort = sort,
- })
- else
- find_files_sorted({
- prompt_title = "Insert link to note",
- cwd = cwd,
- attach_mappings = attach_mappings,
- find_command = find_command,
- sort = sort,
- })
- end
+ if opts.with_live_grep then
+ builtin.live_grep({
+ prompt_title = "Insert link to note with live grep",
+ cwd = cwd,
+ attach_mappings = attach_mappings,
+ find_command = find_command,
+ sort = sort,
+ })
+ else
+ find_files_sorted({
+ prompt_title = "Insert link to note",
+ cwd = cwd,
+ attach_mappings = attach_mappings,
+ find_command = find_command,
+ sort = sort,
+ })
+ end
+ end)
end
-- local function check_for_link_or_tag()
@@ -1154,32 +1248,71 @@ local function PreviewImg(opts)
opts.close_after_yanking = opts.close_after_yanking
or config.options.close_after_yanking
- if not fileutils.global_dir_check() then
- return
- end
+ fileutils.global_dir_check(function(dir_check)
+ if not dir_check then
+ return
+ end
+
+ local saved_reg = vim.fn.getreg('"0')
+ vim.cmd("normal yi)")
+ local fname = vim.fn.getreg('"0'):gsub("^img/", "")
+ vim.fn.setreg('"0', saved_reg)
+
+ -- check if fname exists anywhere
+ local imageDir = config.options.image_subdir or config.options.home
+ local fexists = fileutils.file_exists(imageDir .. "/" .. fname)
+
+ if fexists == true then
+ find_files_sorted({
+ prompt_title = "Preview image/media",
+ cwd = imageDir,
+ default_text = fname,
+ find_command = config.options.find_command,
+ filter_extensions = config.options.media_extensions,
+ preview_type = "media",
+ attach_mappings = function(prompt_bufnr, map)
+ actions.select_default:replace(function()
+ actions.close(prompt_bufnr)
+ end)
+ map("i", "", picker_actions.yank_img_link(opts))
+ map("i", "", picker_actions.paste_img_link(opts))
+ map("n", "", picker_actions.yank_img_link(opts))
+ map("n", "", picker_actions.paste_img_link(opts))
+ map("i", "", picker_actions.paste_img_link(opts))
+ map("n", "", picker_actions.paste_img_link(opts))
+ return true
+ end,
+ sort = config.options.sort,
+ })
+ else
+ print("File not found: " .. config.options.home .. "/" .. fname)
+ end
+ end)
+end
- vim.cmd("normal yi)")
- local fname = vim.fn.getreg('"0'):gsub("^img/", "")
+--
+-- BrowseImg:
+-- -----------
+--
+-- preview media
+--
+local function BrowseImg(opts)
+ opts = opts or {}
+ opts.insert_after_inserting = opts.insert_after_inserting
+ or config.options.insert_after_inserting
+ opts.close_after_yanking = opts.close_after_yanking
+ or config.options.close_after_yanking
- -- check if fname exists anywhere
- local imageDir = config.options.image_subdir or config.options.home
- local fexists = fileutils.file_exists(imageDir .. "/" .. fname)
+ fileutils.global_dir_check(function(dir_check)
+ if not dir_check then
+ return
+ end
- if fexists == true then
find_files_sorted({
prompt_title = "Preview image/media",
- cwd = imageDir,
- default_text = fname,
+ cwd = config.options.home,
find_command = config.options.find_command,
- filter_extensions = {
- ".png",
- ".jpg",
- ".bmp",
- ".gif",
- ".pdf",
- ".mp4",
- ".webm",
- },
+ filter_extensions = config.options.media_extensions,
preview_type = "media",
attach_mappings = function(prompt_bufnr, map)
actions.select_default:replace(function()
@@ -1195,103 +1328,59 @@ local function PreviewImg(opts)
end,
sort = config.options.sort,
})
- else
- print("File not found: " .. config.options.home .. "/" .. fname)
- end
+ end)
end
--
--- BrowseImg:
+-- FindFriends:
-- -----------
--
--- preview media
+-- Find notes also linking to the link under cursor
--
-local function BrowseImg(opts)
+local function FindFriends(opts)
opts = opts or {}
opts.insert_after_inserting = opts.insert_after_inserting
or config.options.insert_after_inserting
opts.close_after_yanking = opts.close_after_yanking
or config.options.close_after_yanking
- if not fileutils.global_dir_check() then
- return
- end
+ fileutils.global_dir_check(function(dir_check)
+ if not dir_check then
+ return
+ end
- find_files_sorted({
- prompt_title = "Preview image/media",
- cwd = config.options.home,
- find_command = config.options.find_command,
- filter_extensions = {
- ".png",
- ".jpg",
- ".bmp",
- ".gif",
- ".pdf",
- ".mp4",
- ".webm",
- },
- preview_type = "media",
- attach_mappings = function(prompt_bufnr, map)
- actions.select_default:replace(function()
- actions.close(prompt_bufnr)
- end)
- map("i", "", picker_actions.yank_img_link(opts))
- map("i", "", picker_actions.paste_img_link(opts))
- map("n", "", picker_actions.yank_img_link(opts))
- map("n", "", picker_actions.paste_img_link(opts))
- map("i", "", picker_actions.paste_img_link(opts))
- map("n", "", picker_actions.paste_img_link(opts))
- return true
- end,
- sort = config.options.sort,
- })
+ local saved_reg = vim.fn.getreg('"0')
+ vim.cmd("normal yi]")
+ local title = vim.fn.getreg('"0')
+ vim.fn.setreg('"0', saved_reg)
+
+ title = linkutils.remove_alias(title)
+ title = title:gsub("^(%[)(.+)(%])$", "%2")
+
+ builtin.live_grep({
+ prompt_title = "Notes referencing `" .. title .. "`",
+ cwd = config.options.home,
+ default_text = "\\[\\[" .. title .. "([#|].+)?\\]\\]",
+ find_command = config.options.find_command,
+ attach_mappings = function(_, map)
+ actions.select_default:replace(picker_actions.select_default)
+ map("i", "", picker_actions.yank_link(opts))
+ map("i", "", picker_actions.paste_link(opts))
+ map("n", "", picker_actions.yank_link(opts))
+ map("n", "", picker_actions.paste_link(opts))
+ map("i", "", picker_actions.paste_link(opts))
+ map("n", "", picker_actions.paste_link(opts))
+ return true
+ end,
+ })
+ end)
end
--
--- FindFriends:
+-- YankLink:
-- -----------
--
--- Find notes also linking to the link under cursor
---
-local function FindFriends(opts)
- opts = opts or {}
- opts.insert_after_inserting = opts.insert_after_inserting
- or config.options.insert_after_inserting
- opts.close_after_yanking = opts.close_after_yanking
- or config.options.close_after_yanking
-
- if not fileutils.global_dir_check() then
- return
- end
-
- vim.cmd("normal yi]")
- local title = vim.fn.getreg('"0')
- title = linkutils.remove_alias(title)
- title = title:gsub("^(%[)(.+)(%])$", "%2")
-
- builtin.live_grep({
- prompt_title = "Notes referencing `" .. title .. "`",
- cwd = config.options.home,
- default_text = "\\[\\[" .. title .. "([#|].+)?\\]\\]",
- find_command = config.options.find_command,
- attach_mappings = function(_, map)
- actions.select_default:replace(picker_actions.select_default)
- map("i", "", picker_actions.yank_link(opts))
- map("i", "", picker_actions.paste_link(opts))
- map("n", "", picker_actions.yank_link(opts))
- map("n", "", picker_actions.paste_link(opts))
- map("i", "", picker_actions.paste_link(opts))
- map("n", "", picker_actions.paste_link(opts))
- return true
- end,
- })
-end
-
---
--- YankLink:
--- -----------
---
--- Create and yank a [[link]] from the current note.
+-- Create and yank a [[link]] from the current note.
--
local function YankLink()
local title = "[["
@@ -1301,6 +1390,31 @@ local function YankLink()
print("yanked " .. title)
end
+local function rename_update_links(oldfile, newname)
+ if config.options.rename_update_links == true then
+ -- Only look for the first part of the link, so we do not touch to #heading or #^paragraph
+ -- Should use regex instead to ensure it is a proper link
+ local oldlink = "[[" .. oldfile.title
+ local newlink = "[[" .. newname
+
+ -- Save open buffers before looking for links to replace
+ if #(vim.fn.getbufinfo({ bufmodified = 1 })) > 1 then
+ vim.ui.select({ "Yes (default)", "No" }, {
+ prompt = "Telekasten.nvim: "
+ .. "Save all modified buffers before updating links?",
+ }, function(answer)
+ if answer ~= "No" then
+ save_all_mod_buffers()
+ end
+ end)
+ end
+
+ recursive_substitution(config.options.home, oldlink, newlink)
+ recursive_substitution(config.options.dailies, oldlink, newlink)
+ recursive_substitution(config.options.weeklies, oldlink, newlink)
+ end
+end
+
--
-- RenameNote:
-- -----------
@@ -1339,55 +1453,37 @@ local function RenameNote()
-- Savas newfile, delete buffer of old one and remove old file
if newname ~= "" and newname ~= oldfile.title then
- if
- not (fileutils.check_dir_and_ask(newpath, "Renamed file"))
- then
- return
- end
-
- local oldTitle = oldfile.title:gsub(" ", "\\ ")
- vim.cmd(
- "saveas "
- .. config.options.home
- .. "/"
- .. newname
- .. config.options.extension
- )
- vim.cmd("bdelete " .. oldTitle .. config.options.extension)
- os.execute(
- "rm "
- .. config.options.home
- .. "/"
- .. oldTitle
- .. config.options.extension
- )
- end
-
- if config.options.rename_update_links == true then
- -- Only look for the first part of the link, so we do not touch to #heading or #^paragraph
- -- Should use regex instead to ensure it is a proper link
- local oldlink = "[[" .. oldfile.title
- local newlink = "[[" .. newname
-
- -- Save open buffers before looking for links to replace
- if #(vim.fn.getbufinfo({ bufmodified = 1 })) > 1 then
- vim.ui.select({ "Yes (default)", "No" }, {
- prompt = "Telekasten.nvim: "
- .. "Save all modified buffers before updating links?",
- }, function(answer)
- if answer ~= "No" then
- save_all_mod_buffers()
+ fileutils.check_dir_and_ask(
+ newpath,
+ "Renamed file",
+ function(success)
+ if not success then
+ return
end
- end)
- end
- recursive_substitution(config.options.home, oldlink, newlink)
- recursive_substitution(config.options.dailies, oldlink, newlink)
- recursive_substitution(
- config.options.weeklies,
- oldlink,
- newlink
+ local oldTitle = oldfile.title:gsub(" ", "\\ ")
+ vim.cmd(
+ "saveas "
+ .. config.options.home
+ .. "/"
+ .. newname
+ .. config.options.extension
+ )
+ vim.cmd(
+ "bdelete " .. oldTitle .. config.options.extension
+ )
+ os.execute(
+ "rm "
+ .. config.options.home
+ .. "/"
+ .. oldTitle
+ .. config.options.extension
+ )
+ rename_update_links(oldfile, newname)
+ end
)
+ else
+ rename_update_links(oldfile, newname)
end
end
)
@@ -1418,6 +1514,42 @@ local function GotoDate(opts)
.. word
.. config.options.extension
local fexists = fileutils.file_exists(fname)
+ local function picker()
+ if opts.journal_auto_open then
+ if opts.calendar == true then
+ -- ensure that the calendar window is not improperly overwritten
+ vim.cmd("wincmd w")
+ end
+ vim.cmd("e " .. fname)
+ else
+ find_files_sorted({
+ prompt_title = "Goto day",
+ cwd = config.options.dailies,
+ default_text = word,
+ find_command = config.options.find_command,
+ attach_mappings = function(prompt_bufnr, map)
+ actions.select_default:replace(function()
+ actions.close(prompt_bufnr)
+
+ -- open the new note
+ if opts.calendar == true then
+ vim.cmd("wincmd w")
+ end
+ vim.cmd("e " .. fname)
+ picker_actions.post_open()
+ end)
+ map("i", "", picker_actions.yank_link(opts))
+ map("i", "", picker_actions.paste_link(opts))
+ map("n", "", picker_actions.yank_link(opts))
+ map("n", "", picker_actions.paste_link(opts))
+ map("n", "", picker_actions.close(opts))
+ map("n", "", picker_actions.close(opts))
+ return true
+ end,
+ })
+ end
+ end
+
if
(fexists ~= true)
and (
@@ -1430,41 +1562,17 @@ local function GotoDate(opts)
nil,
fname,
M.note_type_templates.daily,
- opts.dates
+ opts.dates,
+ function()
+ opts.erase = true
+ opts.erase_file = fname
+ picker()
+ end
)
- opts.erase = true
- opts.erase_file = fname
+ return
end
- if opts.journal_auto_open then
- vim.cmd("e " .. fname)
- else
- find_files_sorted({
- prompt_title = "Goto day",
- cwd = config.options.dailies,
- default_text = word,
- find_command = config.options.find_command,
- attach_mappings = function(prompt_bufnr, map)
- actions.select_default:replace(function()
- actions.close(prompt_bufnr)
-
- -- open the new note
- if opts.calendar == true then
- vim.cmd("wincmd w")
- end
- vim.cmd("e " .. fname)
- picker_actions.post_open()
- end)
- map("i", "", picker_actions.yank_link(opts))
- map("i", "", picker_actions.paste_link(opts))
- map("n", "", picker_actions.yank_link(opts))
- map("n", "", picker_actions.paste_link(opts))
- map("n", "", picker_actions.close(opts))
- map("n", "", picker_actions.close(opts))
- return true
- end,
- })
- end
+ picker()
end
--
@@ -1476,15 +1584,17 @@ end
local function GotoToday(opts)
opts = opts or {}
- if not fileutils.global_dir_check() then
- return
- end
+ fileutils.global_dir_check(function(dir_check)
+ if not dir_check then
+ return
+ end
- local today = os.date(dateutils.dateformats.date)
- opts.date_table = os.date("*t")
- opts.date = today
- opts.dailies_create_nonexisting = true -- Always use template for GotoToday
- GotoDate(opts)
+ local today = os.date(dateutils.dateformats.date)
+ opts.date_table = os.date("*t")
+ opts.date = today
+ opts.dailies_create_nonexisting = true -- Always use template for GotoToday
+ GotoDate(opts)
+ end)
end
--
@@ -1500,43 +1610,47 @@ local function FindNotes(opts)
opts.close_after_yanking = opts.close_after_yanking
or config.options.close_after_yanking
- if not fileutils.global_dir_check() then
- return
- end
+ fileutils.global_dir_check(function(dir_check)
+ if not dir_check then
+ return
+ end
- local cwd = config.options.home
- local find_command = config.options.find_command
- local sort = config.options.sort
- local attach_mappings = function(_, map)
- actions.select_default:replace(picker_actions.select_default)
- map("i", "", picker_actions.yank_link(opts))
- map("i", "", picker_actions.paste_link(opts))
- map("n", "", picker_actions.yank_link(opts))
- map("n", "", picker_actions.paste_link(opts))
- map("i", "", picker_actions.paste_link(opts))
- map("n", "", picker_actions.paste_link(opts))
- map("i", "", picker_actions.create_new(opts))
- map("n", "", picker_actions.create_new(opts))
- return true
- end
+ local cwd = config.options.home
+ local find_command = config.options.find_command
+ local sort = config.options.sort
+ local attach_mappings = function(_, map)
+ actions.select_default:replace(picker_actions.select_default)
+ map("i", "", picker_actions.yank_link(opts))
+ map("i", "", picker_actions.paste_link(opts))
+ map("n", "", picker_actions.yank_link(opts))
+ map("n", "", picker_actions.paste_link(opts))
+ map("i", "", picker_actions.paste_link(opts))
+ map("n", "", picker_actions.paste_link(opts))
+ if config.options.enable_create_new then
+ map("i", "", picker_actions.create_new(opts))
+ map("n", "", picker_actions.create_new(opts))
+ end
+ return true
+ end
- if opts.with_live_grep then
- builtin.live_grep({
- prompt_title = "Find notes by live grep",
- cwd = cwd,
- find_command = find_command,
- attach_mappings = attach_mappings,
- sort = sort,
- })
- else
- find_files_sorted({
- prompt_title = "Find notes by name",
- cwd = cwd,
- find_command = find_command,
- attach_mappings = attach_mappings,
- sort = sort,
- })
- end
+ if opts.with_live_grep then
+ builtin.live_grep({
+ prompt_title = "Find notes by live grep",
+ cwd = cwd,
+ find_command = find_command,
+ attach_mappings = attach_mappings,
+ sort = sort,
+ })
+ else
+ find_files_sorted({
+ prompt_title = "Find notes by name",
+ cwd = cwd,
+ find_command = find_command,
+ attach_mappings = attach_mappings,
+ sort = sort,
+ })
+ end
+ end)
end
--
@@ -1548,45 +1662,39 @@ end
local function InsertImgLink(opts)
opts = opts or {}
- if not fileutils.global_dir_check() then
- return
- end
+ fileutils.global_dir_check(function(dir_check)
+ if not dir_check then
+ return
+ end
- find_files_sorted({
- prompt_title = "Find image/media",
- cwd = config.options.home,
- find_command = config.options.find_command,
- filter_extensions = {
- ".png",
- ".jpg",
- ".bmp",
- ".gif",
- ".pdf",
- ".mp4",
- ".webm",
- },
- preview_type = "media",
- attach_mappings = function(prompt_bufnr, map)
- actions.select_default:replace(function()
- actions.close(prompt_bufnr)
- local selection = action_state.get_selected_entry()
- local fn = selection.value
- fn = make_relative_path(vim.fn.expand("%:p"), fn, "/")
- vim.api.nvim_put({ "![](" .. fn .. ")" }, "", true, true)
- if opts.i then
- vim.api.nvim_feedkeys("A", "m", false)
- end
- end)
- map("i", "", picker_actions.yank_img_link(opts))
- map("i", "", picker_actions.paste_img_link(opts))
- map("n", "", picker_actions.yank_img_link(opts))
- map("n", "", picker_actions.paste_img_link(opts))
- map("i", "", picker_actions.paste_img_link(opts))
- map("n", "", picker_actions.paste_img_link(opts))
- return true
- end,
- sort = config.options.sort,
- })
+ find_files_sorted({
+ prompt_title = "Find image/media",
+ cwd = config.options.home,
+ find_command = config.options.find_command,
+ filter_extensions = config.options.media_extensions,
+ preview_type = "media",
+ attach_mappings = function(prompt_bufnr, map)
+ actions.select_default:replace(function()
+ actions.close(prompt_bufnr)
+ local selection = action_state.get_selected_entry()
+ local fn = selection.value
+ fn = make_relative_path(vim.fn.expand("%:p"), fn, "/")
+ vim.api.nvim_put({ "![](" .. fn .. ")" }, "", true, true)
+ if opts.i then
+ vim.api.nvim_feedkeys("A", "m", false)
+ end
+ end)
+ map("i", "", picker_actions.yank_img_link(opts))
+ map("i", "", picker_actions.paste_img_link(opts))
+ map("n", "", picker_actions.yank_img_link(opts))
+ map("n", "", picker_actions.paste_img_link(opts))
+ map("i", "", picker_actions.paste_img_link(opts))
+ map("n", "", picker_actions.paste_img_link(opts))
+ return true
+ end,
+ sort = config.options.sort,
+ })
+ end)
end
--
@@ -1602,27 +1710,29 @@ local function SearchNotes(opts)
opts.close_after_yanking = opts.close_after_yanking
or config.options.close_after_yanking
- if not fileutils.global_dir_check() then
- return
- end
+ fileutils.global_dir_check(function(dir_check)
+ if not dir_check then
+ return
+ end
- builtin.live_grep({
- prompt_title = "Search in notes",
- cwd = config.options.home,
- search_dirs = { config.options.home },
- default_text = opts.default_text or vim.fn.expand(""),
- find_command = config.options.find_command,
- attach_mappings = function(_, map)
- actions.select_default:replace(picker_actions.select_default)
- map("i", "", picker_actions.yank_link(opts))
- map("i", "", picker_actions.paste_link(opts))
- map("n", "", picker_actions.yank_link(opts))
- map("n", "", picker_actions.paste_link(opts))
- map("i", "", picker_actions.paste_link(opts))
- map("n", "", picker_actions.paste_link(opts))
- return true
- end,
- })
+ builtin.live_grep({
+ prompt_title = "Search in notes",
+ cwd = config.options.home,
+ search_dirs = { config.options.home },
+ default_text = opts.default_text or vim.fn.expand(""),
+ find_command = config.options.find_command,
+ attach_mappings = function(_, map)
+ actions.select_default:replace(picker_actions.select_default)
+ map("i", "", picker_actions.yank_link(opts))
+ map("i", "", picker_actions.paste_link(opts))
+ map("n", "", picker_actions.yank_link(opts))
+ map("n", "", picker_actions.paste_link(opts))
+ map("i", "", picker_actions.paste_link(opts))
+ map("n", "", picker_actions.paste_link(opts))
+ return true
+ end,
+ })
+ end)
end
--
@@ -1638,31 +1748,37 @@ local function ShowBacklinks(opts)
opts.close_after_yanking = opts.close_after_yanking
or config.options.close_after_yanking
- if not fileutils.global_dir_check() then
- return
- end
+ fileutils.global_dir_check(function(dir_check)
+ if not dir_check then
+ return
+ end
- local title =
- Pinfo:new({ filepath = vim.fn.expand("%:p"), config.options }).title
- -- or vim.api.nvim_buf_get_name(0)
- builtin.live_grep({
- results_title = "Backlinks to " .. title,
- prompt_title = "Search",
- cwd = config.options.home,
- search_dirs = { config.options.home },
- default_text = "\\[\\[" .. title .. "([#|].+)?\\]\\]",
- find_command = config.options.find_command,
- attach_mappings = function(_, map)
- actions.select_default:replace(picker_actions.select_default)
- map("i", "", picker_actions.yank_link(opts))
- map("i", "", picker_actions.paste_link(opts))
- map("n", "", picker_actions.yank_link(opts))
- map("n", "", picker_actions.paste_link(opts))
- map("i", "", picker_actions.paste_link(opts))
- map("n", "", picker_actions.paste_link(opts))
- return true
- end,
- })
+ local title =
+ Pinfo:new({ filepath = vim.fn.expand("%:p"), config.options }).title
+ -- or vim.api.nvim_buf_get_name(0)
+
+ local escaped_title = string.gsub(title, "%(", "\\(")
+ escaped_title = string.gsub(escaped_title, "%)", "\\)")
+
+ builtin.live_grep({
+ results_title = "Backlinks to " .. title,
+ prompt_title = "Search",
+ cwd = config.options.home,
+ search_dirs = { config.options.home },
+ default_text = "\\[\\[" .. escaped_title .. "([#|].+)?\\]\\]",
+ find_command = config.options.find_command,
+ attach_mappings = function(_, map)
+ actions.select_default:replace(picker_actions.select_default)
+ map("i", "", picker_actions.yank_link(opts))
+ map("i", "", picker_actions.paste_link(opts))
+ map("n", "", picker_actions.yank_link(opts))
+ map("n", "", picker_actions.paste_link(opts))
+ map("i", "", picker_actions.paste_link(opts))
+ map("n", "", picker_actions.paste_link(opts))
+ return true
+ end,
+ })
+ end)
end
--
@@ -1716,11 +1832,13 @@ local function on_create_with_template(opts, title)
uuid,
fname,
template,
- pinfo.calendar_info
+ pinfo.calendar_info,
+ function()
+ -- open the new note
+ vim.cmd("e " .. fname)
+ picker_actions.post_open()
+ end
)
- -- open the new note
- vim.cmd("e " .. fname)
- picker_actions.post_open()
end)
map("i", "", picker_actions.yank_link(opts))
map("i", "", picker_actions.paste_link(opts))
@@ -1734,12 +1852,21 @@ end
local function CreateNoteSelectTemplate(opts)
opts = opts or {}
- if not fileutils.global_dir_check() then
- return
- end
+ fileutils.global_dir_check(function(dir_check)
+ if not dir_check then
+ return
+ end
- fileutils.prompt_title(config.options.extension, nil, function(title)
- on_create_with_template(opts, title)
+ -- get the current working directory
+ local current_dir = vim.fn.getcwd()
+ -- change the cwd to the configured home directory, so tab completion
+ -- works for the folders in that directory
+ vim.fn.chdir(config.options.home)
+ fileutils.prompt_title(config.options.extension, nil, function(title)
+ on_create_with_template(opts, title)
+ end)
+ -- change back to the original directory
+ vim.fn.chdir(current_dir)
end)
end
@@ -1772,6 +1899,24 @@ local function on_create(opts, title)
})
local fname = pinfo.filepath
+ local function picker()
+ find_files_sorted({
+ prompt_title = "Created note...",
+ cwd = pinfo.root_dir,
+ default_text = generate_note_filename(uuid, title),
+ find_command = config.options.find_command,
+ attach_mappings = function(_, map)
+ actions.select_default:replace(picker_actions.select_default)
+ map("i", "", picker_actions.yank_link(opts))
+ map("i", "", picker_actions.paste_link(opts))
+ map("n", "", picker_actions.yank_link(opts))
+ map("n", "", picker_actions.paste_link(opts))
+ map("n", "", picker_actions.close(opts))
+ map("n", "", picker_actions.close(opts))
+ return true
+ end,
+ })
+ end
if pinfo.fexists ~= true then
-- TODO: pass in the calendar_info returned in pinfo
create_note_from_template(
@@ -1779,43 +1924,41 @@ local function on_create(opts, title)
uuid,
fname,
pinfo.template,
- pinfo.calendar_info
+ pinfo.calendar_info,
+ function()
+ opts.erase = true
+ opts.erase_file = fname
+ picker()
+ end
)
- opts.erase = true
- opts.erase_file = fname
+ return
end
- find_files_sorted({
- prompt_title = "Created note...",
- cwd = pinfo.root_dir,
- default_text = generate_note_filename(uuid, title),
- find_command = config.options.find_command,
- attach_mappings = function(_, map)
- actions.select_default:replace(picker_actions.select_default)
- map("i", "", picker_actions.yank_link(opts))
- map("i", "", picker_actions.paste_link(opts))
- map("n", "", picker_actions.yank_link(opts))
- map("n", "", picker_actions.paste_link(opts))
- map("n", "", picker_actions.close(opts))
- map("n", "", picker_actions.close(opts))
- return true
- end,
- })
+ picker()
end
local function CreateNote(opts)
opts = opts or {}
- if not fileutils.global_dir_check() then
- return
- end
+ fileutils.global_dir_check(function(dir_check)
+ if not dir_check then
+ return
+ end
- if config.options.template_handling == "always_ask" then
- return CreateNoteSelectTemplate(opts)
- end
+ if config.options.template_handling == "always_ask" then
+ return CreateNoteSelectTemplate(opts)
+ end
- fileutils.prompt_title(config.options.extension, nil, function(title)
- on_create(opts, title)
+ -- get the current working directory
+ local current_dir = vim.fn.getcwd()
+ -- change the cwd to the configured home directory, so tab completion
+ -- works for the folders in that directory
+ vim.fn.chdir(config.options.home)
+ fileutils.prompt_title(config.options.extension, nil, function(title)
+ on_create(opts, title)
+ end)
+ -- change back to the original directory
+ vim.fn.chdir(current_dir)
end)
end
@@ -1838,426 +1981,444 @@ local function FollowLink(opts)
or config.options.new_note_location
local uuid_type = opts.uuid_type or config.options.uuid_type
- if not fileutils.global_dir_check() then
- return
- end
+ fileutils.global_dir_check(function(dir_check)
+ if not dir_check then
+ return
+ end
- local search_mode = "files"
- local title
- local filename_part = ""
+ local search_mode = "files"
+ local title
+ local filename_part = ""
- -- first: check if we're in a tag or a link
- local kind, atcol, tag
- local globArg = ""
+ -- first: check if we're in a tag or a link
+ local kind
+ local globArg = ""
- if opts.follow_tag ~= nil then
- kind = "tag"
- tag = opts.follow_tag
- if opts.templateDir ~= nil then
- globArg = "--glob=!" .. "**/" .. opts.templateDir .. "/*.md"
+ if opts.follow_tag ~= nil then
+ kind = "tag"
+ title = opts.follow_tag
+ if opts.templateDir ~= nil then
+ globArg = "--glob=!" .. "**/" .. opts.templateDir .. "/*.md"
+ end
+ else
+ kind, _ = check_for_link_or_tag()
end
- else
- kind, atcol = check_for_link_or_tag()
- end
- if kind == "tag" then
- if atcol ~= nil then
- tag = taglinks.get_tag_at(
- vim.api.nvim_get_current_line(),
- atcol,
- config.options
- )
- end
- search_mode = "tag"
- title = tag
- else
- if kind == "link" then
- -- we are in a link
- vim.cmd("normal yi]")
- title = vim.fn.getreg('"0')
- title = title:gsub("^(%[)(.+)(%])$", "%2")
- title = linkutils.remove_alias(title)
+ if kind == "tag" then
+ search_mode = "tag"
+ if title == nil then
+ local saved_reg = vim.fn.getreg('"0')
+ vim.cmd("normal yiw")
+ title = vim.fn.getreg('"0')
+ vim.fn.setreg('"0', saved_reg)
+ end
else
- -- we are in an external [link]
- vim.cmd("normal yi)")
- local url = vim.fn.getreg('"0')
- return follow_url(url)
- end
+ local saved_reg = vim.fn.getreg('"0')
+ if kind == "link" then
+ -- we are in a link
+ vim.cmd("normal yi]")
+ title = vim.fn.getreg('"0')
+ title = title:gsub("^(%[)(.+)(%])$", "%2")
+ title = title:gsub("%s*\n", " ")
+ title = linkutils.remove_alias(title)
+ else
+ -- we are in an external [link]
+ vim.cmd("normal yi)")
+ local url = vim.fn.getreg('"0')
+ vim.fn.setreg('"0', saved_reg)
+ return follow_url(url)
+ end
+ vim.fn.setreg('"0', saved_reg)
- local parts = vim.split(title, "#")
+ local parts = vim.split(title, "#")
- -- if there is a #
- if #parts ~= 1 then
- search_mode = "heading"
- title = parts[2]
- filename_part = parts[1]
- parts = vim.split(title, "%^")
+ -- if there is a #
if #parts ~= 1 then
- search_mode = "para"
+ search_mode = "heading"
title = parts[2]
+ filename_part = parts[1]
+ parts = vim.split(title, "%^")
+ if #parts ~= 1 then
+ search_mode = "para"
+ title = parts[2]
+ end
end
- end
- -- this applies to heading and para search_mode
- -- if we cannot find the file, revert to global heading search by
- -- setting filename to empty string
- if #filename_part > 0 then
- local pinfo = Pinfo:new({ title = filename_part })
- filename_part = pinfo.filepath
- if pinfo.fexists == false then
- -- print("error")
- filename_part = ""
+ -- this applies to heading and para search_mode
+ -- if we cannot find the file, revert to global heading search by
+ -- setting filename to empty string
+ if #filename_part > 0 then
+ local pinfo = Pinfo:new({ title = filename_part })
+ filename_part = pinfo.filepath
+ if pinfo.fexists == false then
+ -- print("error")
+ filename_part = ""
+ end
end
end
- end
- if search_mode == "files" then
- -- check if subdir exists
- local filepath = title:match("(.*/)") or ""
- filepath = config.options.home .. "/" .. filepath
- fileutils.check_dir_and_ask(filepath, "")
+ if search_mode == "files" then
+ -- check if subdir exists
+ local filepath = title:match("(.*/)") or ""
+ filepath = config.options.home .. "/" .. filepath
+ fileutils.check_dir_and_ask(filepath, "", function()
+ -- check if fname exists anywhere
+ local pinfo = Pinfo:new({ title = title })
+ local function picker()
+ find_files_sorted({
+ prompt_title = "Follow link to note...",
+ cwd = pinfo.root_dir,
+ default_text = title,
+ find_command = config.options.find_command,
+ attach_mappings = function(_, map)
+ actions.select_default:replace(
+ picker_actions.select_default
+ )
+ map("i", "", picker_actions.yank_link(opts))
+ map("i", "", picker_actions.paste_link(opts))
+ map("n", "", picker_actions.yank_link(opts))
+ map("n", "", picker_actions.paste_link(opts))
+ map("n", "", picker_actions.close(opts))
+ map("n", "", picker_actions.close(opts))
+ return true
+ end,
+ sort = config.options.sort,
+ })
+ end
- -- check if fname exists anywhere
- local pinfo = Pinfo:new({ title = title })
- if
- (pinfo.fexists ~= true)
- and (
- (opts.follow_creates_nonexisting == true)
- or config.options.follow_creates_nonexisting == true
- )
- then
- if opts.template_handling == "always_ask" then
- return on_create_with_template(opts, title)
- end
+ if
+ (pinfo.fexists ~= true)
+ and (
+ (opts.follow_creates_nonexisting == true)
+ or config.options.follow_creates_nonexisting == true
+ )
+ then
+ if opts.template_handling == "always_ask" then
+ return on_create_with_template(opts, title)
+ end
- if #pinfo.filepath > 0 then
- local uuid = fileutils.new_uuid(uuid_type)
- create_note_from_template(
- title,
- uuid,
- pinfo.filepath,
- pinfo.template,
- pinfo.calendar_info
- )
- opts.erase = true
- opts.erase_file = pinfo.filepath
- end
- end
+ if #pinfo.filepath > 0 then
+ local uuid = fileutils.new_uuid(uuid_type)
+ create_note_from_template(
+ title,
+ uuid,
+ pinfo.filepath,
+ pinfo.template,
+ pinfo.calendar_info,
+ function()
+ opts.erase = true
+ opts.erase_file = pinfo.filepath
+ picker()
+ end
+ )
+ return
+ end
+ end
- find_files_sorted({
- prompt_title = "Follow link to note...",
- cwd = pinfo.root_dir,
- default_text = title,
- find_command = config.options.find_command,
- attach_mappings = function(_, map)
- actions.select_default:replace(picker_actions.select_default)
- map("i", "", picker_actions.yank_link(opts))
- map("i", "", picker_actions.paste_link(opts))
- map("n", "", picker_actions.yank_link(opts))
- map("n", "", picker_actions.paste_link(opts))
- map("n", "", picker_actions.close(opts))
- map("n", "", picker_actions.close(opts))
- return true
- end,
- sort = config.options.sort,
- })
- end
+ picker()
+ end)
+ end
- if search_mode ~= "files" then
- local search_pattern = title
- local cwd = config.options.home
+ if search_mode ~= "files" then
+ local search_pattern = title
+ local cwd = config.options.home
- opts.cwd = cwd
- local counts = nil
- if opts.show_link_counts then
- counts = linkutils.generate_backlink_map(config.options)
- end
+ opts.cwd = cwd
+ local counts = nil
+ if opts.show_link_counts then
+ counts = linkutils.generate_backlink_map(config.options)
+ end
- -- display with devicons
- local function iconic_display(display_entry)
- local display_opts = {
- path_display = function(_, e)
- return e:gsub(tkutils.escape(opts.cwd .. "/"), "")
- end,
- }
+ -- display with devicons
+ local function iconic_display(display_entry)
+ local display_opts = {
+ path_display = function(_, e)
+ return e:gsub(tkutils.escape(opts.cwd .. "/"), "")
+ end,
+ }
- local hl_group
- local display =
- utils.transform_path(display_opts, display_entry.value)
+ local hl_group
+ local display =
+ utils.transform_path(display_opts, display_entry.value)
- display_entry.filn = display_entry.filn or display:gsub(":.*", "")
- display, hl_group =
- utils.transform_devicons(display_entry.filn, display, false)
+ display_entry.filn = display_entry.filn
+ or display:gsub(":.*", "")
+ display, hl_group =
+ utils.transform_devicons(display_entry.filn, display, false)
- if hl_group then
- return display, { { { 1, 3 }, hl_group } }
- else
- return display
+ if hl_group then
+ return display, { { { 1, 3 }, hl_group } }
+ else
+ return display
+ end
end
- end
- -- for media_files
- local popup_opts = {}
- opts.get_preview_window = function()
- return popup_opts.preview
- end
-
- -- local width = config.width
- -- or config.layout_config.width
- -- or config.layout_config[config.layout_strategy].width
- -- or vim.o.columns
- -- local telescope_win_width
- -- if width > 1 then
- -- telescope_win_width = width
- -- else
- -- telescope_win_width = math.floor(vim.o.columns * width)
- -- end
- local displayer = entry_display.create({
- separator = "",
- items = {
- { width = 4 },
- { width = 4 },
- { remaining = true },
- },
- })
+ -- for media_files
+ local popup_opts = {}
+ opts.get_preview_window = function()
+ return popup_opts.preview
+ end
- local function make_display(entry)
- local fn = entry.filename
- local nlinks = counts.link_counts[fn] or 0
- local nbacks = counts.backlink_counts[fn] or 0
+ -- local width = config.width
+ -- or config.layout_config.width
+ -- or config.layout_config[config.layout_strategy].width
+ -- or vim.o.columns
+ -- local telescope_win_width
+ -- if width > 1 then
+ -- telescope_win_width = width
+ -- else
+ -- telescope_win_width = math.floor(vim.o.columns * width)
+ -- end
+ local displayer = entry_display.create({
+ separator = "",
+ items = {
+ { width = 4 },
+ { width = 4 },
+ { remaining = true },
+ },
+ })
- if opts.show_link_counts then
- local display, hl = iconic_display(entry)
-
- return displayer({
- {
- "L" .. tostring(nlinks),
- function()
- return {
- { { 0, 1 }, "tkTagSep" },
- { { 1, 3 }, "tkTag" },
- }
- end,
- },
- {
- "B" .. tostring(nbacks),
- function()
- return {
- { { 0, 1 }, "tkTagSep" },
- { { 1, 3 }, "DevIconMd" },
- }
- end,
- },
- {
- display,
- function()
- return hl
- end,
- },
- })
- else
- return iconic_display(entry)
+ local function make_display(entry)
+ local fn = entry.filename
+ local nlinks = counts.link_counts[fn] or 0
+ local nbacks = counts.backlink_counts[fn] or 0
+
+ if opts.show_link_counts then
+ local display, hl = iconic_display(entry)
+
+ return displayer({
+ {
+ "L" .. tostring(nlinks),
+ function()
+ return {
+ { { 0, 1 }, "tkTagSep" },
+ { { 1, 3 }, "tkTag" },
+ }
+ end,
+ },
+ {
+ "B" .. tostring(nbacks),
+ function()
+ return {
+ { { 0, 1 }, "tkTagSep" },
+ { { 1, 3 }, "DevIconMd" },
+ }
+ end,
+ },
+ {
+ display,
+ function()
+ return hl
+ end,
+ },
+ })
+ else
+ return iconic_display(entry)
+ end
end
- end
- local lookup_keys = {
- value = 1,
- ordinal = 1,
- }
+ local lookup_keys = {
+ value = 1,
+ ordinal = 1,
+ }
- local find = (function()
- if Path.path.sep == "\\" then
- return function(t)
- local start, _, filn, lnum, col, text =
- string.find(t, [[([^:]+):(%d+):(%d+):(.*)]])
+ local find = (function()
+ if Path.path.sep == "\\" then
+ return function(t)
+ local start, _, filn, lnum, col, text =
+ string.find(t, [[([^:]+):(%d+):(%d+):(.*)]])
- -- Handle Windows drive letter (e.g. "C:") at the beginning (if present)
- if start == 3 then
- filn = string.sub(t.value, 1, 3) .. filn
- end
+ -- Handle Windows drive letter (e.g. "C:") at the beginning (if present)
+ if start == 3 then
+ filn = string.sub(t.value, 1, 3) .. filn
+ end
- return filn, lnum, col, text
+ return filn, lnum, col, text
+ end
+ else
+ return function(t)
+ local _, _, filn, lnum, col, text =
+ string.find(t, [[([^:]+):(%d+):(%d+):(.*)]])
+ return filn, lnum, col, text
+ end
end
- else
- return function(t)
- local _, _, filn, lnum, col, text =
- string.find(t, [[([^:]+):(%d+):(%d+):(.*)]])
- return filn, lnum, col, text
+ end)()
+
+ local parse = function(t)
+ -- print("t: ", vim.inspect(t))
+ local filn, lnum, col, text = find(t.value)
+
+ local ok
+ ok, lnum = pcall(tonumber, lnum)
+ if not ok then
+ lnum = nil
end
- end
- end)()
- local parse = function(t)
- -- print("t: ", vim.inspect(t))
- local filn, lnum, col, text = find(t.value)
+ ok, col = pcall(tonumber, col)
+ if not ok then
+ col = nil
+ end
- local ok
- ok, lnum = pcall(tonumber, lnum)
- if not ok then
- lnum = nil
- end
+ t.filn = filn
+ t.lnum = lnum
+ t.col = col
+ t.text = text
- ok, col = pcall(tonumber, col)
- if not ok then
- col = nil
+ return { filn, lnum, col, text }
end
- t.filn = filn
- t.lnum = lnum
- t.col = col
- t.text = text
-
- return { filn, lnum, col, text }
- end
+ local function entry_maker(_)
+ local mt_vimgrep_entry
- local function entry_maker(_)
- local mt_vimgrep_entry
+ opts = opts or {}
- opts = opts or {}
+ -- local disable_devicons = opts.disable_devicons
+ -- local disable_coordinates = opts.disable_coordinates or true
+ local only_sort_text = opts.only_sort_text
- -- local disable_devicons = opts.disable_devicons
- -- local disable_coordinates = opts.disable_coordinates or true
- local only_sort_text = opts.only_sort_text
+ local execute_keys = {
+ path = function(t)
+ if Path:new(t.filename):is_absolute() then
+ return t.filename, false
+ else
+ return Path:new({ t.cwd, t.filename }):absolute(),
+ false
+ end
+ end,
+ filename = function(t)
+ return parse(t)[1], true
+ end,
+ lnum = function(t)
+ return parse(t)[2], true
+ end,
+ col = function(t)
+ return parse(t)[3], true
+ end,
+ text = function(t)
+ return parse(t)[4], true
+ end,
+ }
- local execute_keys = {
- path = function(t)
- if Path:new(t.filename):is_absolute() then
- return t.filename, false
- else
- return Path:new({ t.cwd, t.filename }):absolute(), false
+ -- For text search only, the ordinal value is actually the text.
+ if only_sort_text then
+ execute_keys.ordinal = function(t)
+ return t.text
end
- end,
- filename = function(t)
- return parse(t)[1], true
- end,
- lnum = function(t)
- return parse(t)[2], true
- end,
- col = function(t)
- return parse(t)[3], true
- end,
- text = function(t)
- return parse(t)[4], true
- end,
- }
-
- -- For text search only, the ordinal value is actually the text.
- if only_sort_text then
- execute_keys.ordinal = function(t)
- return t.text
end
- end
- mt_vimgrep_entry = {
- cwd = vim.fn.expand(opts.cwd or vim.loop.cwd()),
- __index = function(t, k)
- local raw = rawget(mt_vimgrep_entry, k)
- if raw then
- return raw
- end
+ mt_vimgrep_entry = {
+ cwd = vim.fn.expand(opts.cwd or vim.loop.cwd()),
+ __index = function(t, k)
+ local raw = rawget(mt_vimgrep_entry, k)
+ if raw then
+ return raw
+ end
- local executor = rawget(execute_keys, k)
- if executor then
- local val, save = executor(t)
- if save then
- rawset(t, k, val)
+ local executor = rawget(execute_keys, k)
+ if executor then
+ local val, save = executor(t)
+ if save then
+ rawset(t, k, val)
+ end
+ return val
end
- return val
- end
- return rawget(t, rawget(lookup_keys, k))
- end,
- }
+ return rawget(t, rawget(lookup_keys, k))
+ end,
+ }
- --
- if opts.show_link_counts then
- mt_vimgrep_entry.display = make_display
- else
- mt_vimgrep_entry.display = iconic_display
- end
+ --
+ if opts.show_link_counts then
+ mt_vimgrep_entry.display = make_display
+ else
+ mt_vimgrep_entry.display = iconic_display
+ end
- return function(line)
- return setmetatable({ line }, mt_vimgrep_entry)
+ return function(line)
+ return setmetatable({ line }, mt_vimgrep_entry)
+ end
end
- end
- opts.entry_maker = entry_maker(opts)
+ opts.entry_maker = entry_maker(opts)
- local live_grepper = finders.new_job(
- function(prompt)
- if not prompt or prompt == "" then
- return nil
- end
+ local live_grepper = finders.new_job(
+ function(prompt)
+ if not prompt or prompt == "" then
+ return nil
+ end
- local search_command = {
- "rg",
- "--vimgrep",
- "-e",
- "^#+\\s" .. prompt,
- "--",
- }
- if search_mode == "para" then
- search_command = {
+ local search_command = {
"rg",
"--vimgrep",
"-e",
- "\\^" .. prompt,
+ "^#+\\s" .. prompt,
"--",
}
- end
+ if search_mode == "para" then
+ search_command = {
+ "rg",
+ "--vimgrep",
+ "-e",
+ "\\^" .. prompt,
+ "--",
+ }
+ end
- if search_mode == "tag" then
- search_command = {
- "rg",
- "--vimgrep",
- globArg,
- "-e",
- prompt,
- "--",
- }
- end
+ if search_mode == "tag" then
+ search_command = {
+ "rg",
+ "--vimgrep",
+ globArg,
+ "-e",
+ prompt,
+ "--",
+ }
+ end
- if #filename_part > 0 then
- table.insert(search_command, filename_part)
- else
- table.insert(search_command, cwd)
- end
+ if #filename_part > 0 then
+ table.insert(search_command, filename_part)
+ else
+ table.insert(search_command, cwd)
+ end
- local ret = vim.tbl_flatten({ search_command })
- return ret
- end,
- opts.entry_maker or make_entry.gen_from_vimgrep(opts),
- opts.max_results,
- opts.cwd
- )
+ local ret = vim.tbl_flatten({ search_command })
+ return ret
+ end,
+ opts.entry_maker or make_entry.gen_from_vimgrep(opts),
+ opts.max_results,
+ opts.cwd
+ )
- -- builtin.live_grep({
- local picker = pickers.new(opts, {
- cwd = cwd,
- prompt_title = "Notes referencing `" .. title .. "`",
- default_text = search_pattern,
- initial_mode = "insert",
- -- link to specific file (a daily file): [[2021-02-22]]
- -- link to heading in specific file (a daily file): [[2021-02-22#Touchpoint]]
- -- link to heading globally [[#Touchpoint]]
- -- link to heading in specific file (a daily file): [[The cool note#^xAcSh-xxr]]
- -- link to paragraph globally [[#^xAcSh-xxr]]
- finder = live_grepper,
- previewer = conf.grep_previewer(opts),
- sorter = sorters.highlighter_only(opts),
- attach_mappings = function(_, map)
- actions.select_default:replace(picker_actions.select_default)
- map("i", "", picker_actions.yank_link(opts))
- map("i", "", picker_actions.paste_link(opts))
- map("n", "", picker_actions.yank_link(opts))
- map("n", "", picker_actions.paste_link(opts))
- map("i", "", picker_actions.paste_link(opts))
- map("n", "", picker_actions.paste_link(opts))
- return true
- end,
- })
- picker:find()
- end
+ -- builtin.live_grep({
+ local picker = pickers.new(opts, {
+ cwd = cwd,
+ prompt_title = "Notes referencing `" .. title .. "`",
+ default_text = search_pattern,
+ initial_mode = "insert",
+ -- link to specific file (a daily file): [[2021-02-22]]
+ -- link to heading in specific file (a daily file): [[2021-02-22#Touchpoint]]
+ -- link to heading globally [[#Touchpoint]]
+ -- link to heading in specific file (a daily file): [[The cool note#^xAcSh-xxr]]
+ -- link to paragraph globally [[#^xAcSh-xxr]]
+ finder = live_grepper,
+ previewer = conf.grep_previewer(opts),
+ sorter = sorters.highlighter_only(opts),
+ attach_mappings = function(_, map)
+ actions.select_default:replace(
+ picker_actions.select_default
+ )
+ map("i", "", picker_actions.yank_link(opts))
+ map("i", "", picker_actions.paste_link(opts))
+ map("n", "", picker_actions.yank_link(opts))
+ map("n", "", picker_actions.paste_link(opts))
+ map("i", "", picker_actions.paste_link(opts))
+ map("n", "", picker_actions.paste_link(opts))
+ return true
+ end,
+ })
+ picker:find()
+ end
+ end)
end
--
@@ -2275,57 +2436,74 @@ local function GotoThisWeek(opts)
opts.journal_auto_open = opts.journal_auto_open
or config.options.journal_auto_open
- if not fileutils.global_dir_check() then
- return
- end
+ fileutils.global_dir_check(function(dir_check)
+ if not dir_check then
+ return
+ end
- local dinfo = dateutils.calculate_dates(
- nil,
- config.options.calendar_opts.calendar_monday
- )
- local title = dinfo.isoweek
- local fname = config.options.weeklies
- .. "/"
- .. title
- .. config.options.extension
- local fexists = fileutils.file_exists(fname)
- if
- (fexists ~= true)
- and (
- (opts.weeklies_create_nonexisting == true)
- or config.options.weeklies_create_nonexisting == true
- )
- then
- create_note_from_template(
- title,
+ local dinfo = dateutils.calculate_dates(
nil,
- fname,
- M.note_type_templates.weekly
+ config.options.calendar_opts.calendar_monday
)
- opts.erase = true
- opts.erase_file = fname
- end
+ local title = dinfo.isoweek
+ local fname = config.options.weeklies
+ .. "/"
+ .. title
+ .. config.options.extension
+ local fexists = fileutils.file_exists(fname)
+ local function picker()
+ if opts.journal_auto_open then
+ if opts.calendar == true then
+ -- ensure that the calendar window is not improperly overwritten
+ vim.cmd("wincmd w")
+ end
+ vim.cmd("e " .. fname)
+ else
+ find_files_sorted({
+ prompt_title = "Goto this week:",
+ cwd = config.options.weeklies,
+ default_text = title,
+ find_command = config.options.find_command,
+ attach_mappings = function(_, map)
+ actions.select_default:replace(
+ picker_actions.select_default
+ )
+ map("i", "", picker_actions.yank_link(opts))
+ map("i", "", picker_actions.paste_link(opts))
+ map("n", "", picker_actions.yank_link(opts))
+ map("n", "", picker_actions.paste_link(opts))
+ map("n", "", picker_actions.close(opts))
+ map("n", "", picker_actions.close(opts))
+ return true
+ end,
+ })
+ end
+ end
- if opts.journal_auto_open then
- vim.cmd("e " .. fname)
- else
- find_files_sorted({
- prompt_title = "Goto this week:",
- cwd = config.options.weeklies,
- default_text = title,
- find_command = config.options.find_command,
- attach_mappings = function(_, map)
- actions.select_default:replace(picker_actions.select_default)
- map("i", "", picker_actions.yank_link(opts))
- map("i", "", picker_actions.paste_link(opts))
- map("n", "", picker_actions.yank_link(opts))
- map("n", "", picker_actions.paste_link(opts))
- map("n", "", picker_actions.close(opts))
- map("n", "", picker_actions.close(opts))
- return true
- end,
- })
- end
+ if
+ (fexists ~= true)
+ and (
+ (opts.weeklies_create_nonexisting == true)
+ or config.options.weeklies_create_nonexisting == true
+ )
+ then
+ create_note_from_template(
+ title,
+ nil,
+ fname,
+ M.note_type_templates.weekly,
+ nil,
+ function()
+ opts.erase = true
+ opts.erase_file = fname
+ picker()
+ end
+ )
+ return
+ end
+
+ picker()
+ end)
end
--
@@ -2481,90 +2659,92 @@ local function FindAllTags(opts)
opts.templateDir = templateDir
opts.rg_pcre = config.options.rg_pcre
- if not fileutils.global_dir_check() then
- return
- end
+ fileutils.global_dir_check(function(dir_check)
+ if not dir_check then
+ return
+ end
- local tag_map = tagutils.do_find_all_tags(opts)
- local taglist = {}
+ local tag_map = tagutils.do_find_all_tags(opts)
+ local taglist = {}
- local max_tag_len = 0
- for k, v in pairs(tag_map) do
- taglist[#taglist + 1] = { tag = k, details = v }
- if #k > max_tag_len then
- max_tag_len = #k
+ local max_tag_len = 0
+ for k, v in pairs(tag_map) do
+ taglist[#taglist + 1] = { tag = k, details = v }
+ if #k > max_tag_len then
+ max_tag_len = #k
+ end
end
- end
- if config.options.show_tags_theme == "get_cursor" then
- opts = themes.get_cursor({
- layout_config = {
- height = math.min(math.floor(vim.o.lines * 0.8), #taglist),
- },
- })
- elseif config.options.show_tags_theme == "ivy" then
- opts = themes.get_ivy({
- layout_config = {
- prompt_position = "top",
- height = math.min(math.floor(vim.o.lines * 0.8), #taglist),
- },
- })
- else
- opts = themes.get_dropdown({
- layout_config = {
- prompt_position = "top",
- height = math.min(math.floor(vim.o.lines * 0.8), #taglist),
- },
- })
- end
- -- re-apply
- opts.cwd = config.options.home
- opts.tag_notation = config.options.tag_notation
- opts.i = i
- pickers
- .new(opts, {
- prompt_title = "Tags",
- finder = finders.new_table({
- results = taglist,
- entry_maker = function(entry)
- return {
- value = entry,
- -- display = entry.tag .. ' \t (' .. #entry.details .. ' matches)',
- display = string.format(
- "%" .. max_tag_len .. "s ... (%3d matches)",
- entry.tag,
- #entry.details
- ),
- ordinal = entry.tag,
- }
- end,
- }),
- sorter = conf.generic_sorter(opts),
- attach_mappings = function(prompt_bufnr, map)
- actions.select_default:replace(function()
- -- actions for insert tag, default action: search for tag
- local selection =
- action_state.get_selected_entry().value.tag
- local follow_opts = {
- follow_tag = selection,
- show_link_counts = true,
- templateDir = templateDir,
- }
- actions._close(prompt_bufnr, false)
- vim.schedule(function()
- FollowLink(follow_opts)
+ if config.options.show_tags_theme == "get_cursor" then
+ opts = themes.get_cursor({
+ layout_config = {
+ height = math.min(math.floor(vim.o.lines * 0.8), #taglist),
+ },
+ })
+ elseif config.options.show_tags_theme == "ivy" then
+ opts = themes.get_ivy({
+ layout_config = {
+ prompt_position = "top",
+ height = math.min(math.floor(vim.o.lines * 0.8), #taglist),
+ },
+ })
+ else
+ opts = themes.get_dropdown({
+ layout_config = {
+ prompt_position = "top",
+ height = math.min(math.floor(vim.o.lines * 0.8), #taglist),
+ },
+ })
+ end
+ -- re-apply
+ opts.cwd = config.options.home
+ opts.tag_notation = config.options.tag_notation
+ opts.i = i
+ pickers
+ .new(opts, {
+ prompt_title = "Tags",
+ finder = finders.new_table({
+ results = taglist,
+ entry_maker = function(entry)
+ return {
+ value = entry,
+ -- display = entry.tag .. ' \t (' .. #entry.details .. ' matches)',
+ display = string.format(
+ "%" .. max_tag_len .. "s ... (%3d matches)",
+ entry.tag,
+ #entry.details
+ ),
+ ordinal = entry.tag,
+ }
+ end,
+ }),
+ sorter = conf.generic_sorter(opts),
+ attach_mappings = function(prompt_bufnr, map)
+ actions.select_default:replace(function()
+ -- actions for insert tag, default action: search for tag
+ local selection =
+ action_state.get_selected_entry().value.tag
+ local follow_opts = {
+ follow_tag = selection,
+ show_link_counts = false,
+ templateDir = templateDir,
+ }
+ actions._close(prompt_bufnr, false)
+ vim.schedule(function()
+ FollowLink(follow_opts)
+ end)
end)
- end)
- map("i", "", picker_actions.yank_tag(opts))
- map("i", "", picker_actions.paste_tag(opts))
- map("n", "", picker_actions.yank_tag(opts))
- map("n", "", picker_actions.paste_tag(opts))
- map("n", "", picker_actions.close(opts))
- map("n", "", picker_actions.close(opts))
- return true
- end,
- })
- :find()
+ map("i", "", picker_actions.yank_tag(opts))
+ map("i", "", picker_actions.paste_tag(opts))
+ map("n", "", picker_actions.yank_tag(opts))
+ map("n", "", picker_actions.paste_tag(opts))
+ map("n", "", picker_actions.close(opts))
+ map("n", "", picker_actions.close(opts))
+ return true
+ end,
+ })
+ :find()
+ end)
end
-- Setup(cfg)
@@ -2666,17 +2846,18 @@ local function Setup(cfg)
config.options.rg_pcre = true
end
config.options.media_previewer = config.options.media_previewer
+ config.options.media_extensions = config.options.media_extensions
end
local function _setup(cfg)
if cfg.vaults ~= nil and cfg.default_vault ~= nil then
M.vaults = cfg.vaults
cfg.vaults = nil
- Setup(cfg.vaults[cfg.default_vault])
+ Setup(M.vaults[cfg.default_vault])
elseif cfg.vaults ~= nil and cfg.vaults["default"] ~= nil then
M.vaults = cfg.vaults
cfg.vaults = nil
- Setup(cfg.vaults["default"])
+ Setup(M.vaults["default"])
elseif cfg.home ~= nil then
M.vaults = cfg.vaults or {}
cfg.vaults = nil
diff --git a/lua/telekasten/config.lua b/lua/telekasten/config.lua
index 76c2bd2..a855230 100644
--- a/lua/telekasten/config.lua
+++ b/lua/telekasten/config.lua
@@ -75,7 +75,22 @@ local function get_defaults(home)
new_note_location = "smart",
rename_update_links = true,
media_previewer = "telescope-media-files",
+ media_extensions = {
+ ".png",
+ ".jpg",
+ ".bmp",
+ ".gif",
+ ".pdf",
+ ".mp4",
+ ".webm",
+ ".webp",
+ },
+ -- A customizable fallback handler for urls.
follow_url_fallback = nil,
+ -- Enable creation new notes with Ctrl-n when finding notes
+ enable_create_new = true,
+ -- Specify a clipboard program to use
+ clipboard_program = "", -- xsel, xclip, wl-paste, osascript
}
return { options = opts }
end
diff --git a/lua/telekasten/utils/files.lua b/lua/telekasten/utils/files.lua
index 191cbb8..cd437dc 100644
--- a/lua/telekasten/utils/files.lua
+++ b/lua/telekasten/utils/files.lua
@@ -75,7 +75,7 @@ function M.new_uuid(uuid_style)
return uuid
end
-function M.check_dir_and_ask(dir, purpose)
+function M.check_dir_and_ask(dir, purpose, callback)
local ret = false
if dir ~= nil and Path:new(dir):exists() == false then
vim.ui.select({ "No (default)", "Yes" }, {
@@ -97,30 +97,39 @@ function M.check_dir_and_ask(dir, purpose)
-- unreachable: plenary.Path:mkdir() will error out
tkutils.print_error("Could not create directory " .. dir)
ret = false
+ callback(ret)
end
end
end)
else
ret = true
+ if callback ~= nil then
+ callback(ret)
+ end
end
return ret
end
-function M.global_dir_check()
+function M.global_dir_check(callback)
local ret
if config.options.home == nil then
tkutils.print_error("Telekasten.nvim: home is not configured!")
ret = false
- else
- ret = M.check_dir_and_ask(config.options.home, "home")
+ callback(ret)
end
-
- ret = ret and M.check_dir_and_ask(config.options.dailies, "dailies")
- ret = ret and M.check_dir_and_ask(config.options.weeklies, "weeklies")
- ret = ret and M.check_dir_and_ask(config.options.templates, "templates")
- ret = ret and M.check_dir_and_ask(config.options.image_subdir, "images")
-
- return ret
+ local check = M.check_dir_and_ask
+ -- nested callbacks to handle asynchronous vim.ui.select
+ -- looks a little confusing but execution is sequential from top to bottom
+ check(config.options.home, "home", function()
+ check(config.options.dailies, "dailies", function()
+ check(config.options.weeklies, "weeklies", function()
+ check(config.options.templates, "templates", function()
+ -- Note the `callback` in this last function call
+ check(config.options.image_subdir, "images", callback)
+ end)
+ end)
+ end)
+ end)
end
return M
diff --git a/lua/telekasten/utils/taglinks.lua b/lua/telekasten/utils/taglinks.lua
index 28ea5e6..54aed5c 100644
--- a/lua/telekasten/utils/taglinks.lua
+++ b/lua/telekasten/utils/taglinks.lua
@@ -52,6 +52,9 @@ M.is_tag_or_link_at = function(line, col, opts)
if char == "#" then
seen_hashtag = true
end
+ if char == "@" then
+ seen_hashtag = true
+ end
-- Tags should have a space before #, if not we are likely in a link
if char == " " and seen_hashtag and opts.tag_notation == "#tag" then
if not cannot_be_tag then
diff --git a/lua/telekasten/utils/tags.lua b/lua/telekasten/utils/tags.lua
index 6abcf44..e1c2708 100644
--- a/lua/telekasten/utils/tags.lua
+++ b/lua/telekasten/utils/tags.lua
@@ -1,14 +1,20 @@
local Job = require("plenary.job")
local M = {}
-local hashtag_re = "(^|\\s|'|\")#[a-zA-ZÀ-ÿ]+[a-zA-ZÀ-ÿ0-9/\\-_]*"
+
+local hashtag_re =
+ "(^|\\s|'|\")#[a-zA-ZÀ-ÿ\\p{Script=Han}]+[a-zA-ZÀ-ÿ0-9/\\-_\\p{Script=Han}]*"
-- PCRE hashtag allows to remove the hex color codes from hastags
-local hashtag_re_pcre =
- "(^|\\s|'|\")((?!(#[a-fA-F0-9]{3})(\\W|$)|(#[a-fA-F0-9]{6})(\\W|$))#[a-zA-ZÀ-ÿ]+[a-zA-ZÀ-ÿ0-9/\\-_]*)"
-local colon_re = "(^|\\s):[a-zA-ZÀ-ÿ]+[a-zA-ZÀ-ÿ0-9/\\-_]*:"
+local hashtag_re_pcre = "(^|\\s|'|\")((?!(#[a-fA-F0-9]{3})(\\W|$)|(#[a-fA-F0-9]{6})(\\W|$))"
+ .. "#[a-zA-ZÀ-ÿ\\p{Script=Han}]+[a-zA-ZÀ-ÿ0-9/\\-_\\p{Script=Han}]*)"
+local atsign_re =
+ "(^|\\s|'|\")@[a-zA-ZÀ-ÿ\\p{Script=Han}]+[a-zA-ZÀ-ÿ0-9/\\-_\\p{Script=Han}]*"
+local atsign_re_pcre = "(^|\\s|'|\")((?!(@[a-fA-F0-9]{3})(\\W|$)|(@[a-fA-F0-9]{6})(\\W|$))"
+ .. "@[a-zA-ZÀ-ÿ\\p{Script=Han}]+[a-zA-ZÀ-ÿ0-9/\\-_\\p{Script=Han}]*)"
+local colon_re =
+ "(^|\\s):[a-zA-ZÀ-ÿ\\p{Script=Han}]+[a-zA-ZÀ-ÿ0-9/\\-_\\p{Script=Han}]*:"
local yaml_re =
- "(^|\\s)tags:\\s*\\[\\s*([a-zA-ZÀ-ÿ]+[a-zA-ZÀ-ÿ0-9/\\-_]*(,\\s*)*)*\\s*]"
-
+ "(^|\\s)tags:\\s*\\[\\s*([a-zA-ZÀ-ÿ\\p{Script=Han}]+[a-zA-ZÀ-ÿ0-9/\\-_\\p{Script=Han}]*(,\\s*)*)*\\s*]"
local function command_find_all_tags(opts)
opts = opts or {}
opts.cwd = opts.cwd or "."
@@ -23,11 +29,11 @@ local function command_find_all_tags(opts)
local re = hashtag_re
- if opts.tag_notation == ":tag:" then
+ if opts.tag_notation == "@tag" then
+ re = atsign_re
+ elseif opts.tag_notation == ":tag:" then
re = colon_re
- end
-
- if opts.tag_notation == "yaml-bare" then
+ elseif opts.tag_notation == "yaml-bare" then
re = yaml_re
end
@@ -41,18 +47,32 @@ local function command_find_all_tags(opts)
}
-- PCRE engine allows to remove hex color codes from #hastags
- if opts.rg_pcre and (re == hashtag_re) then
- re = hashtag_re_pcre
-
- rg_args = {
- "--vimgrep",
- "--pcre2",
- globArg,
- "-o",
- re,
- "--",
- opts.cwd,
- }
+ if opts.rg_pcre then
+ if re == hashtag_re then
+ re = hashtag_re_pcre
+
+ rg_args = {
+ "--vimgrep",
+ "--pcre2",
+ globArg,
+ "-o",
+ re,
+ "--",
+ opts.cwd,
+ }
+ elseif re == atsign_re then
+ re = atsign_re_pcre
+
+ rg_args = {
+ "--vimgrep",
+ "--pcre2",
+ globArg,
+ "-o",
+ re,
+ "--",
+ opts.cwd,
+ }
+ end
end
return "rg", rg_args
diff --git a/syntax/telekasten.vim b/syntax/telekasten.vim
index 600e486..52f7838 100644
--- a/syntax/telekasten.vim
+++ b/syntax/telekasten.vim
@@ -8,8 +8,10 @@ unlet b:current_syntax
syn region Comment matchgroup=Comment start="" contains=tkTag keepend
-syntax region tkLink matchgroup=tkBrackets start=/\[\[/ end=/\]\]/ display oneline
-syntax region tkHighlight matchgroup=tkBrackets start=/==/ end=/==/ display oneline contains=tkHighlightedAliasedLink
+syntax region tkLink matchgroup=tkBrackets start=/\[\[/ end=/\]\]/ keepend display contains=tkAliasedLink
+syntax match tkAliasedLink "[^\[\]]\+|" contained conceal
+
+syntax region tkHighlight matchgroup=tkBrackets start=/==/ end=/==/ display contains=tkAliasedLink
syntax match tkTag "\v#[a-zA-ZÀ-ÿ]+[a-zA-ZÀ-ÿ0-9/\-_]*"
syntax match tkTag "\v:[a-zA-ZÀ-ÿ]+[a-zA-ZÀ-ÿ0-9/\-_]*:"
@@ -17,10 +19,6 @@ syntax match tkTag "\v:[a-zA-ZÀ-ÿ]+[a-zA-ZÀ-ÿ0-9/\-_]*:"
syntax match tkTagSep "\v\s*,\s*" contained
syntax region tkTag matchgroup=tkBrackets start=/^tags\s*:\s*\[\s*/ end=/\s*\]\s*$/ contains=tkTagSep display oneline
-syntax region tkAliasedLink start="\[\[[^\]]\+|" end="\]\]" keepend oneline contains=tkLinkAlias,tkLinkBody
-syntax region tkHighlightedAliasedLink start="\[\[[^\]]\+|" end="\]\]" keepend oneline contained contains=tkLinkAlias,tkLinkBody
-syntax region tkLinkAlias start="|"ms=s+1 end=".+\]\]"me=e-2 keepend contained
-syntax region tkLinkBody start="\[\["ms=s+2 end="|" keepend contained conceal
let b:current_syntax = 'telekasten'
@@ -38,4 +36,4 @@ let b:current_syntax = 'telekasten'
"
" " Tags
" hi tkTagSep ctermfg=gray
-" hi tkTag ctermfg=magenta
+" hi tkTag ctermfg=magenta
\ No newline at end of file