fix #43 via template_handling option, #38 via new_note_location opt, #33 improvements (detecting dailies/weeklies in links)

This commit is contained in:
Rene Schallner
2021-12-25 07:22:30 +01:00
parent c918734602
commit b1593bb4c1
4 changed files with 168 additions and 90 deletions

130
README.md
View File

@@ -1,12 +1,21 @@
<div align="center">
# ![](img/telekasten-logo-gray-270x87.png).nvim # ![](img/telekasten-logo-gray-270x87.png).nvim
<!-- [![Lua](https://img.shields.io/badge/Lua-blue.svg?style=for-the-badge&logo=lua)](http://www.lua.org) -->
<!-- [![Neovim](https://img.shields.io/badge/Neovim%200.6+-green.svg?style=for-the-badge&logo=neovim)](https://neovim.io) -->
[![Lua](https://img.shields.io/badge/Lua-blue.svg?style=plastic&logo=lua)](http://www.lua.org)
[![Neovim](https://img.shields.io/badge/Neovim%200.6+-green.svg?style=plastic&logo=neovim)](https://neovim.io)
</div>
A Neovim (lua) plugin for working with a text-based, markdown [zettelkasten](https://takesmartnotes.com/) / wiki and A Neovim (lua) plugin for working with a text-based, markdown [zettelkasten](https://takesmartnotes.com/) / wiki and
mixing it with a journal, based on [telescope.nvim](https://github.com/nvim-telescope/telescope.nvim). mixing it with a journal, based on [telescope.nvim](https://github.com/nvim-telescope/telescope.nvim).
#### Highlights: #### Highlights
- Find notes by name, #tag, and daily, weekly notes by date - Find notes by name, #tag, and daily, weekly notes by date
- search within all notes - search within all notes
- place and follow links to your notes or create new ones, with templates - place and follow links to your notes or create new ones, with templates
- current daily and weekly notes are (optionally) created if not present when searching for dailies or weeklies - current daily and weekly notes are (optionally) created if not present when searching for dailies or weeklies
- following a link to a non-existing note can also create the missing note (optional) - following a link to a non-existing note can also create the missing note (optional)
@@ -20,7 +29,11 @@ mixing it with a journal, based on [telescope.nvim](https://github.com/nvim-tele
- insert links to images - insert links to images
- **image previews**, via extension _(Linux only)_ - **image previews**, via extension _(Linux only)_
##### New features are being announced in the [discussions](https://github.com/renerocksai/telekasten.nvim/discussions)! <div align="center">
#### New features are being announced in the [discussions](https://github.com/renerocksai/telekasten.nvim/discussions)
</div>
--- ---
@@ -33,12 +46,12 @@ If you have `xclip` installed, Telekasten.nvim can even **paste images from the
sub-directory and insert a wiki or markdown link at the current cursor position! sub-directory and insert a wiki or markdown link at the current cursor position!
After having written the infamous [sublime_zk](https://github.com/renerocksai/sublime_zk) for SublimeText, having moved After having written the infamous [sublime_zk](https://github.com/renerocksai/sublime_zk) for SublimeText, having moved
on to my standalone [sublimeless_zk](https://github.com/renerocksai/sublimeless_zk), having tried on to my standalone [sublimeless_zk](https://github.com/renerocksai/sublimeless_zk), having tried
[Roam Research](https://roamresearch.com) and [Obsidian.md](https://obsidian.md) (which I still use sparingly), I have [Roam Research](https://roamresearch.com) and [Obsidian.md](https://obsidian.md) (which I still use sparingly), I have
eventually arrived back at the editor I feel at home the most: Neovim 😄! I can literally **live** inside of nvim now, eventually arrived back at the editor I feel at home the most: Neovim 😄! I can literally **live** inside of nvim now,
not only for writing code. not only for writing code.
This is the result of my first days of hacking neovim with lua (more features have been added since, see This is the result of my first days of hacking neovim with lua (more features have been added since, see
[Use it](#2-use-it) below the screenshots): [Use it](#2-use-it) below the screenshots):
![image](https://user-images.githubusercontent.com/30892199/145457184-758ae6cd-f1d2-48b4-b09b-4fa7e45c493f.png) ![image](https://user-images.githubusercontent.com/30892199/145457184-758ae6cd-f1d2-48b4-b09b-4fa7e45c493f.png)
@@ -54,7 +67,6 @@ This is the result of my first days of hacking neovim with lua (more features ha
![](img/tags-linkcounts.png) ![](img/tags-linkcounts.png)
## Search-based navigation ## Search-based navigation
Every navigation action, like following a link, is centered around a Telescope search: a Telescope search popup is Every navigation action, like following a link, is centered around a Telescope search: a Telescope search popup is
@@ -63,6 +75,7 @@ linked note, you get a preview in Telescope and can decide if you actually want
likely to show up more than one result, you can preview related notes immediately. likely to show up more than one result, you can preview related notes immediately.
### The preview is a powerful feature ### The preview is a powerful feature
Leaving the opening of the note to Telescope, you can decide with one keypress whether you want to open the note in a Leaving the opening of the note to Telescope, you can decide with one keypress whether you want to open the note in a
split or in the current window - or if you've seen enough. split or in the current window - or if you've seen enough.
@@ -70,44 +83,42 @@ I find that pressing the enter key to confirm the search does not interrupt my f
check the preview. I often get enough information from it alone so I don't actually have to "visit" every note in terms check the preview. I often get enough information from it alone so I don't actually have to "visit" every note in terms
of being able to edit it. of being able to edit it.
## Contents ## Contents
<!-- vim-markdown-toc GFM --> <!-- vim-markdown-toc GFM -->
* [0. Install and setup](#0-install-and-setup) - [0. Install and setup](#0-install-and-setup)
* [0.0 Prerequisites](#00-prerequisites) - [0.0 Prerequisites](#00-prerequisites)
* [0.0.1 Telescope](#001-telescope) - [0.0.1 Telescope](#001-telescope)
* [0.0.2 calendar-vim Plugin (optional)](#002-calendar-vim-plugin-optional) - [0.0.2 calendar-vim Plugin (optional)](#002-calendar-vim-plugin-optional)
* [0.0.3 For pasting images: xclip (optional)](#003-for-pasting-images-xclip-optional) - [0.0.3 For pasting images: xclip (optional)](#003-for-pasting-images-xclip-optional)
* [0.0.4 For image previews: telescope-media-files.nvim (optional)](#004-for-image-previews-telescope-media-filesnvim-optional) - [0.0.4 For image previews: telescope-media-files.nvim (optional)](#004-for-image-previews-telescope-media-filesnvim-optional)
* [0.1 Install the plugin](#01-install-the-plugin) - [0.1 Install the plugin](#01-install-the-plugin)
* [0.1.0 Other useful plugins](#010-other-useful-plugins) - [0.1.0 Other useful plugins](#010-other-useful-plugins)
* [0.2 Configure telekasten.nvim](#02-configure-telekastennvim) - [0.2 Configure telekasten.nvim](#02-configure-telekastennvim)
* [0.3 Configure your own colors](#03-configure-your-own-colors) - [0.3 Configure your own colors](#03-configure-your-own-colors)
* [1. Get Help](#1-get-help) - [1. Get Help](#1-get-help)
* [2. Use it](#2-use-it) - [2. Use it](#2-use-it)
* [2.0 Telekasten command](#20-telekasten-command) - [2.0 Telekasten command](#20-telekasten-command)
* [2.1 Telekasten command palette](#21-telekasten-command-palette) - [2.1 Telekasten command palette](#21-telekasten-command-palette)
* [2.2 Telekasten lua functions](#22-telekasten-lua-functions) - [2.2 Telekasten lua functions](#22-telekasten-lua-functions)
* [2.3 Link notation](#23-link-notation) - [2.3 Link notation](#23-link-notation)
* [2.4 Tag notation](#24-tag-notation) - [2.4 Tag notation](#24-tag-notation)
* [2.5 Note templates](#25-note-templates) - [2.5 Note templates](#25-note-templates)
* [2.5.1 Template files](#251-template-files) - [2.5.1 Template files](#251-template-files)
* [2.6 Using the calendar](#26-using-the-calendar) - [2.6 Using the calendar](#26-using-the-calendar)
* [2.7 Using the telescope pickers](#27-using-the-telescope-pickers) - [2.7 Using the telescope pickers](#27-using-the-telescope-pickers)
* [3. Bind it](#3-bind-it) - [3. Bind it](#3-bind-it)
* [4. The hardcoded stuff](#4-the-hardcoded-stuff) - [4. The hardcoded stuff](#4-the-hardcoded-stuff)
<!-- vim-markdown-toc --> <!-- vim-markdown-toc -->
## 0. Install and setup ## 0. Install and setup
### 0.0 Prerequisites ### 0.0 Prerequisites
#### 0.0.1 Telescope #### 0.0.1 Telescope
Since this plugin uses [telescope.nvim](https://github.com/nvim-telescope/telescope.nvim), you need to install it first. Since this plugin uses [telescope.nvim](https://github.com/nvim-telescope/telescope.nvim), you need to install it first.
[Neovim (v0.5.1)](https://github.com/neovim/neovim/releases/tag/v0.5.1) or the latest neovim nighly commit is required [Neovim (v0.5.1)](https://github.com/neovim/neovim/releases/tag/v0.5.1) or the latest neovim nighly commit is required
@@ -127,13 +138,14 @@ See below for installing and using it.
--- ---
#### 0.0.3 For pasting images: xclip (optional) #### 0.0.3 For pasting images: xclip (optional)
Telekasten.nvim supports pasting images from the clipboard. Currently, this is only implemented for systems that have Telekasten.nvim supports pasting images from the clipboard. Currently, this is only implemented for systems that have
the `xclip` utility installed. the `xclip` utility installed.
On Ubuntu/Debian like systems: On Ubuntu/Debian like systems:
```console ```console
$ sudo apt-get install xclip sudo apt-get install xclip
``` ```
--- ---
@@ -147,9 +159,9 @@ Telescope extension [telescope-media-files.nvim](https://github.com/nvim-telesco
This extension has its own list of prerequisites, of which I recommend (and use) the following: This extension has its own list of prerequisites, of which I recommend (and use) the following:
* [Überzug](https://github.com/seebye/ueberzug) (required for image support) - [Überzug](https://github.com/seebye/ueberzug) (required for image support)
* [ffmpegthumbnailer](https://github.com/dirkvdb/ffmpegthumbnailer) (optional, for video preview support) - [ffmpegthumbnailer](https://github.com/dirkvdb/ffmpegthumbnailer) (optional, for video preview support)
* [pdftoppm](https://linux.die.net/man/1/pdftoppm) (optional, for pdf preview support) - [pdftoppm](https://linux.die.net/man/1/pdftoppm) (optional, for pdf preview support)
Here is a demo from the original authors of Here is a demo from the original authors of
[telescope-media-files.nvim](https://github.com/nvim-telescope/telescope-media-files.nvim): [telescope-media-files.nvim](https://github.com/nvim-telescope/telescope-media-files.nvim):
@@ -159,13 +171,14 @@ Here is a demo from the original authors of
--- ---
### 0.1 Install the plugin ### 0.1 Install the plugin
Install with your plugin manager of choice. Mine is [Vundle](https://github.com/VundleVim/Vundle.vim). Install with your plugin manager of choice. Mine is [Vundle](https://github.com/VundleVim/Vundle.vim).
```vim ```vim
Plugin 'renerocksai/telekasten.nvim' Plugin 'renerocksai/telekasten.nvim'
``` ```
I higly recommend using the calendar integration. For that you'll need I higly recommend using the calendar integration. For that you'll need
[calendar-vim](https://github.com/renerocksai/calendar-vim): [calendar-vim](https://github.com/renerocksai/calendar-vim):
```vim ```vim
@@ -182,6 +195,7 @@ Other plugins I find useful in my day-to-day zettelkasten work:
- [telescope-media-files](https://github.com/nvim-telescope/telescope-media-files.nvim) - [telescope-media-files](https://github.com/nvim-telescope/telescope-media-files.nvim)
### 0.2 Configure telekasten.nvim ### 0.2 Configure telekasten.nvim
Somewhere in your vim config, put a snippet like this: Somewhere in your vim config, put a snippet like this:
```lua ```lua
@@ -200,7 +214,7 @@ require('telekasten').setup({
-- image subdir for pasting -- image subdir for pasting
-- subdir name -- subdir name
-- or nil if pasted images shouldn't go into a special subdir -- or nil if pasted images shouldn't go into a special subdir
image_subdir = "img", image_subdir = "img",
-- markdown file extension -- markdown file extension
extension = ".md", extension = ".md",
@@ -222,10 +236,10 @@ require('telekasten').setup({
-- set to `nil` or do not specify if you do not want a template -- set to `nil` or do not specify if you do not want a template
template_new_weekly= home .. '/' .. 'templates/weekly.md', template_new_weekly= home .. '/' .. 'templates/weekly.md',
-- image link style -- image link style
-- wiki: ![[image name]] -- wiki: ![[image name]]
-- markdown: ![](image_subdir/xxxxx.png) -- markdown: ![](image_subdir/xxxxx.png)
image_link_style = "markdown", image_link_style = "markdown",
-- integrate with calendar-vim -- integrate with calendar-vim
plug_into_calendar = true, plug_into_calendar = true,
@@ -262,6 +276,7 @@ require('telekasten').setup({
}) })
END END
``` ```
| setting | description | example | | setting | description | example |
| --- | --- | --- | | --- | --- | --- |
| `home` | path to your zettelkasten folder (folder with markdown files) | ~/zettelkasten | | `home` | path to your zettelkasten folder (folder with markdown files) | ~/zettelkasten |
@@ -303,7 +318,6 @@ END
| | - `get_cursor`: floating popup window at cursor position || | | - `get_cursor`: floating popup window at cursor position ||
| `subdirs_in_links` | include subdirs (if applicable) in generated (yanked, inserted) links| true | | `subdirs_in_links` | include subdirs (if applicable) in generated (yanked, inserted) links| true |
The calendar support has its own options, contained in `calendar_opts`: The calendar support has its own options, contained in `calendar_opts`:
| calendar setting | description | example | | calendar setting | description | example |
@@ -320,8 +334,8 @@ The calendar support has its own options, contained in `calendar_opts`:
| | 'left-fit' : mark to the left of the day| | | | 'left-fit' : mark to the left of the day| |
| | 'right' : mark to the right of the day| | | | 'right' : mark to the right of the day| |
### 0.3 Configure your own colors ### 0.3 Configure your own colors
Telekasten.nvim allows you to color your `[[links]]` and `#tags` by providing the following syntax groups: Telekasten.nvim allows you to color your `[[links]]` and `#tags` by providing the following syntax groups:
- `tkLink` : the link title inside the brackets - `tkLink` : the link title inside the brackets
@@ -356,14 +370,16 @@ hi tkTagSep ctermfg=gray guifg=gray
hi tkTag ctermfg=175 guifg=#d3869B hi tkTag ctermfg=175 guifg=#d3869B
``` ```
## 1. Get Help ## 1. Get Help
Telekasten.nvim now comes with its own help file. So you can always: Telekasten.nvim now comes with its own help file. So you can always:
```vim ```vim
:h telekasten.nvim :h telekasten.nvim
``` ```
or or
```vim ```vim
:h telekasten.<TAB> " or whatever your completion key is there :h telekasten.<TAB> " or whatever your completion key is there
``` ```
@@ -450,8 +466,8 @@ This is what the popup looks like:
![](img/panel-popup.png) ![](img/panel-popup.png)
### 2.2 Telekasten lua functions ### 2.2 Telekasten lua functions
The plugin defines the following functions: The plugin defines the following functions:
- `new_note()` : prompts for title and creates new note by template, then shows it in Telescope - `new_note()` : prompts for title and creates new note by template, then shows it in Telescope
@@ -468,7 +484,7 @@ The plugin defines the following functions:
optionally be created if not present, using the configured template optionally be created if not present, using the configured template
- `search_notes()`: live grep for word under cursor in all notes (search in notes), via Telescope - `search_notes()`: live grep for word under cursor in all notes (search in notes), via Telescope
- `insert_link()` : select a note by name, via Telescope, and place a `[[link]]` at the current cursor position - `insert_link()` : select a note by name, via Telescope, and place a `[[link]]` at the current cursor position
- **note**: - **note**:
- this function accepts a parameter `{i}`. If `true`, it will enter input mode by pressing the 'A' key. This is - this function accepts a parameter `{i}`. If `true`, it will enter input mode by pressing the 'A' key. This is
useful when being used in a simple `inoremap` key mapping like shown in [Bind it](#3-bind-it). useful when being used in a simple `inoremap` key mapping like shown in [Bind it](#3-bind-it).
- example: `insert_link({ i=true })` - example: `insert_link({ i=true })`
@@ -480,7 +496,7 @@ The plugin defines the following functions:
- `show_calendar()` : opens up the calendar in a properly-sized vertical split at the very right - `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 - `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 at the current cursor position
- `toggle_todo()` : turn a line into a `- [ ] ` line, or toggle between `- [ ]`, `- [x]`, and `- `. - `toggle_todo()` : turn a line into a `- [ ]` line, or toggle between `- [ ]`, `- [x]`, and `-`.
- **note**: - **note**:
- this function accepts a parameter `{i}`. If `true`, it will enter input mode by pressing the 'A' key. This is - this function accepts a parameter `{i}`. If `true`, it will enter input mode by pressing the 'A' key. This is
useful when being used in a simple `inoremap` key mapping like shown in [Bind it](#3-bind-it). useful when being used in a simple `inoremap` key mapping like shown in [Bind it](#3-bind-it).
@@ -489,7 +505,7 @@ The plugin defines the following functions:
- `find_friends()` : opens a telescope search for notes that also `[[link]]` to the link under the cursor. - `find_friends()` : opens a telescope search for notes that also `[[link]]` to the link under the cursor.
- `insert_img_link()` : opens a telescope search for all media (PDFs, images, videos (MP4, webm)) and places a markdown - `insert_img_link()` : opens a telescope search for all media (PDFs, images, videos (MP4, webm)) and places a markdown
image link to the picked one at the cursor position. image link to the picked one at the cursor position.
- **note**: - **note**:
- if the `telescope-media-files.nvim` plugin is installed, **a preview of images / media files will be given** - if the `telescope-media-files.nvim` plugin is installed, **a preview of images / media files will be given**
during the search. during the search.
- this function accepts a parameter `{i}`. If `true`, it will enter input mode by pressing the 'A' key. This is - this function accepts a parameter `{i}`. If `true`, it will enter input mode by pressing the 'A' key. This is
@@ -497,9 +513,9 @@ The plugin defines the following functions:
- example: `insert_link({ i=true })` - example: `insert_link({ i=true })`
- `preview_img()` : uses the `telescope-media-files.nvim` extension to preview the image / media file under the cursor - `preview_img()` : uses the `telescope-media-files.nvim` extension to preview the image / media file under the cursor
of a markdown image link: `![](path/to/img.png)`. The cursor must be between `(the two parenthesis)`. of a markdown image link: `![](path/to/img.png)`. The cursor must be between `(the two parenthesis)`.
- **note**: this requires the `telescope-media-files.nvim` plugin to be installed. - **note**: this requires the `telescope-media-files.nvim` plugin to be installed.
- `browse_media()` : uses the `telescope-media-files.nvim` extension to preview the image / media file linked to under the cursor. - `browse_media()` : uses the `telescope-media-files.nvim` extension to preview the image / media file linked to under the cursor.
- **note**: this requires the `telescope-media-files.nvim` plugin to be installed. - **note**: this requires the `telescope-media-files.nvim` plugin to be installed.
- `setup(opts)`: used for configuring paths, file extension, etc. - `setup(opts)`: used for configuring paths, file extension, etc.
- `panel()` : brings up the command palette - `panel()` : brings up the command palette
- `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 - `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
@@ -552,7 +568,7 @@ Regarding linking to paragraphs: The `^blockid` notation is supported by more an
- at the end of a line / paragraph you want to link to, you put some block id marker in the form of `^block-id`. - at the end of a line / paragraph you want to link to, you put some block id marker in the form of `^block-id`.
- typically, block ids are tool-generated - but no one can stop you defining your own. - typically, block ids are tool-generated - but no one can stop you defining your own.
- tool-generated block ids look like this: `^xAcSh-xxr`. - tool-generated block ids look like this: `^xAcSh-xxr`.
- instead of linking to a heading, you use the block id as heading: `[[Some note#^block-id]]`. - instead of linking to a heading, you use the block id as heading: `[[Some note#^block-id]]`.
- instead of putting the block id at the end of a line, you can also make a line break and put it in the next line, like - instead of putting the block id at the end of a line, you can also make a line break and put it in the next line, like
illustrated below. illustrated below.
@@ -591,7 +607,7 @@ following formats:
- snake_case: `#note_taking` - snake_case: `#note_taking`
- kebab-case: `#note-taking` - kebab-case: `#note-taking`
The only symbols allowed are: The only symbols allowed are:
- `_` : underscore - `_` : underscore
- `-` : dash - `-` : dash
@@ -603,7 +619,6 @@ is.
**Note**: For proper highlighting, the `install_syntax` option is set to `true` by default. This automatically sets the **Note**: For proper highlighting, the `install_syntax` option is set to `true` by default. This automatically sets the
syntax of filetype `markdown` to `telekasten`, and also registers this syntax with telescope previewers for `.md` files. syntax of filetype `markdown` to `telekasten`, and also registers this syntax with telescope previewers for `.md` files.
### 2.5 Note templates ### 2.5 Note templates
The functions `goto_today`, `goto_thisweek`, `find_daily_notes`, `find_weekly_notes`, and `follow_link` can create The functions `goto_today`, `goto_thisweek`, `find_daily_notes`, `find_weekly_notes`, and `follow_link` can create
@@ -714,7 +729,6 @@ command in vim:
:CalendarT :CalendarT
``` ```
### 2.7 Using the telescope pickers ### 2.7 Using the telescope pickers
When you are prompted with a telescope picker to select a note or media file, the following mappings apply: When you are prompted with a telescope picker to select a note or media file, the following mappings apply:
@@ -728,9 +742,8 @@ When you are prompted with a telescope picker to select a note or media file, th
- <kbd>RETURN / ENTER</kbd> : usually opens the selected note or performs the action defined by the called function - <kbd>RETURN / ENTER</kbd> : usually opens the selected note or performs the action defined by the called function
- e.g. `insert_img_link()`'s action is to insert a link to the selected image. - e.g. `insert_img_link()`'s action is to insert a link to the selected image.
## 3. Bind it ## 3. Bind it
Usually, you would set up some key bindings, though: Usually, you would set up some key bindings, though:
```vim ```vim
@@ -786,6 +799,7 @@ hi tkTag ctermfg=175 guifg=#d3869B
## 4. The hardcoded stuff ## 4. The hardcoded stuff
Currently, the following things are hardcoded: 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 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 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`) - the file naming format for pasted images: `pasted_img_YYYYMMDDhhmmss.png` (e.g. `pasted_img_20211126041108.png`)

View File

@@ -69,7 +69,7 @@ local rep = string.rep
local len = string.len -- luacheck: ignore local len = string.len -- luacheck: ignore
local sub = string.sub local sub = string.sub
local gsub = string.gsub local gsub = string.gsub
local gmatch = string.gmatch or string.gfind local gmatch = string.gmatch
local find = string.find local find = string.find
local ostime = os.time local ostime = os.time
local osdate = os.date local osdate = os.date
@@ -188,7 +188,7 @@ local function makedaynum(y, m, d)
end end
-- date from day number, month is zero base -- date from day number, month is zero base
local function breakdaynum(g) local function breakdaynum(g)
local g = g + 306 g = g + 306
local y = floor((10000 * g + 14780) / 3652425) local y = floor((10000 * g + 14780) / 3652425)
local d = g - dayfromyear(y) local d = g - dayfromyear(y)
if d < 0 then if d < 0 then
@@ -333,8 +333,8 @@ local function getequivyear(y)
and yt[-6] and yt[-6]
and yt[-7] and yt[-7]
then then
getequivyear = function(y) getequivyear = function(yy)
return yt[(weekday(makedaynum(y, 0, 1)) + 1) * (isleapyear(y) and -1 or 1)] return yt[(weekday(makedaynum(yy, 0, 1)) + 1) * (isleapyear(y) and -1 or 1)]
end end
return getequivyear(y) return getequivyear(y)
end end
@@ -565,7 +565,8 @@ local function date_parse(str)
elseif inlist(x, sl_timezone, 2, sw) then elseif inlist(x, sl_timezone, 2, sw) then
c = fix(sw[0]) -- ignore gmt and utc c = fix(sw[0]) -- ignore gmt and utc
if c ~= 0 then if c ~= 0 then
setz(c, x) -- setz(c, x) -- wtf
setz(c) -- better
end end
elseif not inlist(x, sl_weekdays, 2, sw) then elseif not inlist(x, sl_weekdays, 2, sw) then
sw:back() sw:back()
@@ -668,7 +669,8 @@ local tmap = {
} }
local function date_getdobj(v) local function date_getdobj(v)
local o, r = (tmap[type(v)] or fnil)(v) local o, r = (tmap[type(v)] or fnil)(v)
return (o and o:normalize() or error("invalid date time value")), r -- if r is true then o is a reference to a date obj return (o and o:normalize() or error("invalid date time value")), r
-- if r is true then o is a reference to a date obj
end end
--#end -- not DATE_OBJECT_AFX --#end -- not DATE_OBJECT_AFX
local function date_from(arg1, arg2, arg3, arg4, arg5, arg6, arg7) local function date_from(arg1, arg2, arg3, arg4, arg5, arg6, arg7)
@@ -1038,7 +1040,7 @@ local tvspec = {
return fmt("%s%.9f", x >= 10 and "" or "0", x) return fmt("%s%.9f", x >= 10 and "" or "0", x)
end, end,
-- percent character % -- percent character %
["%%"] = function(self) ["%%"] = function(_)
return "%" return "%"
end, end,
-- Group Spec -- -- Group Spec --

View File

@@ -68,6 +68,7 @@ M.date_from_doy = function(year, doy)
return ret -- unreachable if input values are sane return ret -- unreachable if input values are sane
end end
-- the algo on wikipedia seems wrong, so we opt for full-blown luadate
M.isoweek_to_date = function(year, isoweek) M.isoweek_to_date = function(year, isoweek)
local ret = date(year .. "-W" .. string.format("%02d", isoweek) .. "-1") local ret = date(year .. "-W" .. string.format("%02d", isoweek) .. "-1")
return { return {

View File

@@ -17,6 +17,7 @@ local filetype = require("plenary.filetype")
local taglinks = require("taglinks.taglinks") local taglinks = require("taglinks.taglinks")
local tagutils = require("taglinks.tagutils") local tagutils = require("taglinks.tagutils")
local linkutils = require("taglinks.linkutils") local linkutils = require("taglinks.linkutils")
local dateutils = require("taglinks.dateutils")
local Path = require("plenary.path") local Path = require("plenary.path")
-- declare locals for the nvim api stuff to avoid more lsp warnings -- declare locals for the nvim api stuff to avoid more lsp warnings
@@ -89,9 +90,9 @@ M.Cfg = {
show_tags_theme = "ivy", show_tags_theme = "ivy",
-- template_handling -- template_handling
-- - prefer_home: use new_note template for all new notes created via new_note(), -- What to do when creating a new note via `new_note()` or `follow_link()` to a non-existing note
-- new_templated_note(), and follow_link() to non-existing note -- - prefer_new_note: use `new_note` template
-- - smart: if day or week is detected in title, use daily / weekly -- - smart: if day or week is detected in title, use daily / weekly templates (default)
-- - always_ask: always ask before creating a note -- - always_ask: always ask before creating a note
template_handling = "smart", template_handling = "smart",
@@ -107,9 +108,15 @@ M.Cfg = {
-- --
-- Valid options: -- Valid options:
-- - smart: put daily-looking notes in daily, weekly-looking ones in weekly, -- - smart: put daily-looking notes in daily, weekly-looking ones in weekly,
-- - default: put all notes in home except for goto_today(), goto_thisweek() -- all other ones in home, except for notes/with/subdirs/in/title.
-- - same-as-current: put all new notes in the dir of the current note if -- (default)
-- present or else in home --
-- - prefer_home: put all notes in home except for goto_today(), goto_thisweek()
-- except for notes/with/subdirs/in/title.
--
-- - same_as_current: put all new notes in the dir of the current note if
-- present or else in home
-- except for notes/with/subdirs/in/title.
new_note_location = "smart", new_note_location = "smart",
} }
@@ -199,6 +206,7 @@ M.note_type_templates = {
} }
local function daysuffix(day) local function daysuffix(day)
day = tostring(day)
if (day == "1") or (day == "21") or (day == "31") then if (day == "1") or (day == "21") or (day == "31") then
return "st" return "st"
end end
@@ -393,6 +401,7 @@ local Pinfo = {
is_daily = false, is_daily = false,
is_weekly = false, is_weekly = false,
template = "", template = "",
calendar_info = nil,
} }
function Pinfo:new(opts) function Pinfo:new(opts)
@@ -434,10 +443,14 @@ function Pinfo:resolve_path(p, opts)
end end
if vim.startswith(p, M.Cfg.dailies) then if vim.startswith(p, M.Cfg.dailies) then
self.root_dir = M.Cfg.dailies self.root_dir = M.Cfg.dailies
-- TODO: parse "title" into calendarinfo like in resolve_link
-- not really necessary as the file exists anyway and therefore we don't need to instantiate a template
self.is_daily_or_weekly = true self.is_daily_or_weekly = true
self.is_daily = true self.is_daily = true
end end
if vim.startswith(p, M.Cfg.weeklies) then if vim.startswith(p, M.Cfg.weeklies) then
-- TODO: parse "title" into calendarinfo like in resolve_link
-- not really necessary as the file exists anyway and therefore we don't need to instantiate a template
self.root_dir = M.Cfg.weeklies self.root_dir = M.Cfg.weeklies
self.is_daily_or_weekly = true self.is_daily_or_weekly = true
self.is_weekly = true self.is_weekly = true
@@ -463,7 +476,7 @@ local function check_if_daily_or_weekly(title)
local is_daily = false local is_daily = false
local is_weekly = false local is_weekly = false
local dateinfo = {} local dateinfo = calculate_dates() -- sane default
local start, _, year, month, day = title:find(daily_match) local start, _, year, month, day = title:find(daily_match)
if start ~= nil then if start ~= nil then
@@ -473,7 +486,7 @@ local function check_if_daily_or_weekly(title)
dateinfo.year = tonumber(year) dateinfo.year = tonumber(year)
dateinfo.month = tonumber(month) dateinfo.month = tonumber(month)
dateinfo.day = tonumber(day) dateinfo.day = tonumber(day)
-- TODO: calculate_dates() here dateinfo = calculate_dates(dateinfo)
end end
end end
end end
@@ -483,8 +496,9 @@ local function check_if_daily_or_weekly(title)
if start ~= nil then if start ~= nil then
if tonumber(week) < 53 then if tonumber(week) < 53 then
is_weekly = true is_weekly = true
-- TODO: ISO8601 week -> date calculation -- ISO8601 week -> date calculation
dateinfo.year = tonumber(year) dateinfo = dateutils.isoweek_to_date(tonumber(year), tonumber(week))
dateinfo = calculate_dates(dateinfo)
end end
end end
return is_daily, is_weekly, dateinfo return is_daily, is_weekly, dateinfo
@@ -508,8 +522,12 @@ function Pinfo:resolve_link(title, opts)
self.is_daily = false self.is_daily = false
self.is_weekly = false self.is_weekly = false
self.template = nil self.template = nil
self.calendar_info = nil
if opts.weeklies and file_exists(opts.weeklies .. "/" .. self.filename) then if opts.weeklies and file_exists(opts.weeklies .. "/" .. self.filename) then
-- TODO: parse "title" into calendarinfo like below
-- not really necessary as the file exists anyway and therefore we don't need to instantiate a template
-- if we still want calendar_info, just move the code for it out of `if self.fexists == false`.
self.filepath = opts.weeklies .. "/" .. self.filename self.filepath = opts.weeklies .. "/" .. self.filename
self.fexists = true self.fexists = true
self.root_dir = opts.weeklies self.root_dir = opts.weeklies
@@ -517,6 +535,9 @@ function Pinfo:resolve_link(title, opts)
self.is_weekly = true self.is_weekly = true
end end
if opts.dailies and file_exists(opts.dailies .. "/" .. self.filename) then if opts.dailies and file_exists(opts.dailies .. "/" .. self.filename) then
-- TODO: parse "title" into calendarinfo like below
-- not really necessary as the file exists anyway and therefore we don't need to instantiate a template
-- if we still want calendar_info, just move the code for it out of `if self.fexists == false`.
self.filepath = opts.dailies .. "/" .. self.filename self.filepath = opts.dailies .. "/" .. self.filename
self.fexists = true self.fexists = true
self.root_dir = opts.dailies self.root_dir = opts.dailies
@@ -546,24 +567,41 @@ function Pinfo:resolve_link(title, opts)
-- if we just cannot find the note, check if it's a daily or weekly one -- if we just cannot find the note, check if it's a daily or weekly one
if self.fexists == false then if self.fexists == false then
-- TODO: if we're not smart, we also shouldn't need to try to set the calendar info..?
-- I bet someone will want the info in there, so let's put it in if possible
_, _, self.calendar_info = check_if_daily_or_weekly(self.title) -- will set today as default, so leave in!
if opts.new_note_location == "smart" then if opts.new_note_location == "smart" then
self.filepath = opts.home .. "/" .. self.filename -- default self.filepath = opts.home .. "/" .. self.filename -- default
-- TODO: store the date_info somewhere self.is_daily, self.is_weekly, self.calendar_info =
self.is_daily, self.is_weekly, _ = check_if_daily_or_weekly( check_if_daily_or_weekly(
self.title self.title
) )
if self.is_daily == true then if self.is_daily == true then
self.root_dir = opts.dailies self.root_dir = opts.dailies
self.filepath = opts.dailies .. "/" .. self.filename
self.is_daily_or_weekly = true self.is_daily_or_weekly = true
end end
if self.is_weekly == true then if self.is_weekly == true then
self.root_dir = opts.weeklies self.root_dir = opts.weeklies
self.filepath = opts.weeklies .. "/" .. self.filename
self.is_daily_or_weekly = true self.is_daily_or_weekly = true
end end
elseif opts.new_note_location == "same_as_current" then elseif opts.new_note_location == "same_as_current" then
local cwd = vim.fn.expand("%:p") local cwd = vim.fn.expand("%:p")
if #cwd > 0 then if #cwd > 0 then
self.root_dir = Path:new(cwd):parent():absolute() self.root_dir = Path:new(cwd):parent():absolute()
if Path:new(self.root_dir):exists() then
-- check if potential subfolders in filename would end up in a non-existing directory
self.filepath = self.root_dir .. "/" .. self.filename
if not Path:new(self.filepath):parent():exists() then
print("Path " .. self.filepath .. " is invalid!")
-- self.filepath = opts.home .. "/" .. self.filename
end
else
print("Path " .. self.root_dir .. " is invalid!")
-- self.filepath = opts.home .. "/" .. self.filename
end
else else
self.filepath = opts.home .. "/" .. self.filename self.filepath = opts.home .. "/" .. self.filename
end end
@@ -571,6 +609,15 @@ function Pinfo:resolve_link(title, opts)
-- default fn for creation -- default fn for creation
self.filepath = opts.home .. "/" .. self.filename self.filepath = opts.home .. "/" .. self.filename
end end
-- 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 end
-- now work out subdir relative to root -- now work out subdir relative to root
@@ -582,7 +629,7 @@ function Pinfo:resolve_link(title, opts)
-- now suggest a template based on opts -- now suggest a template based on opts
self.template = M.note_type_templates.normal self.template = M.note_type_templates.normal
if opts.template_handling == "prefer_home" then if opts.template_handling == "prefer_new_note" then
self.template = M.note_type_templates.normal self.template = M.note_type_templates.normal
elseif opts.template_handling == "always_ask" then elseif opts.template_handling == "always_ask" then
self.template = nil self.template = nil
@@ -1507,7 +1554,12 @@ local function on_create_with_template(opts, title)
-- local template = M.Cfg.templates .. "/" .. action_state.get_selected_entry().value -- local template = M.Cfg.templates .. "/" .. action_state.get_selected_entry().value
local template = action_state.get_selected_entry().value local template = action_state.get_selected_entry().value
-- TODO: pass in the calendar_info returned from the pinfo -- TODO: pass in the calendar_info returned from the pinfo
create_note_from_template(title, fname, template) create_note_from_template(
title,
fname,
template,
pinfo.calendar_info
)
-- open the new note -- open the new note
vim.cmd("e " .. fname) vim.cmd("e " .. fname)
picker_actions.post_open() picker_actions.post_open()
@@ -1554,11 +1606,14 @@ local function on_create(opts, title)
local pinfo = Pinfo:new({ title = title, opts }) local pinfo = Pinfo:new({ title = title, opts })
local fname = pinfo.filepath local fname = pinfo.filepath
print(vim.inspect(pinfo))
if pinfo.fexists ~= true then if pinfo.fexists ~= true then
-- TODO: pass in the calendar_info returned in pinfo -- TODO: pass in the calendar_info returned in pinfo
create_note_from_template(title, fname, pinfo.template) create_note_from_template(
title,
fname,
pinfo.template,
pinfo.calendar_info
)
opts.erase = true opts.erase = true
opts.erase_file = fname opts.erase_file = fname
end end
@@ -1689,11 +1744,17 @@ local function FollowLink(opts)
if opts.template_handling == "always_ask" then if opts.template_handling == "always_ask" then
return on_create_with_template(opts, title) return on_create_with_template(opts, title)
end end
-- TODO: if daily or weekly: derive date opts from filename!!!
-- pass in the info contained in pinfo if #pinfo.filepath > 0 then
create_note_from_template(title, pinfo.filepath, pinfo.template) create_note_from_template(
opts.erase = true title,
opts.erase_file = pinfo.filepath pinfo.filepath,
pinfo.template,
pinfo.calendar_info
)
opts.erase = true
opts.erase_file = pinfo.filepath
end
end end
find_files_sorted({ find_files_sorted({
@@ -2241,7 +2302,7 @@ local function FindAllTags(opts)
actions.select_default:replace(function() actions.select_default:replace(function()
actions._close(prompt_bufnr, true) actions._close(prompt_bufnr, true)
-- TODO actions for insert tag, default action: search for tag -- actions for insert tag, default action: search for tag
local selection = action_state.get_selected_entry().value.tag local selection = action_state.get_selected_entry().value.tag
local follow_opts = { local follow_opts = {
follow_tag = selection, follow_tag = selection,