Open mickael-menu opened 2 years ago
Here's a spec, feel free to review and comment.
We're talking about two separate features using the same renaming process under the hood:
In both cases, the path of the note, its title and all the inbound or outbound links might need to be updated in a single atomic operation.
The actual FS changes will be handled by POSIX diff
and patch
.
We'll need one new zk
command per feature. Both commands will fail if the new generated filenames already exist.
zk rename
Usage: zk rename <path> <new-title>
Rename the title of a note, updating all the backlinks and the note filename, if needed.
Arguments:
<path> Path to the note to rename.
<new-title> New title of the note.
Flags:
-i, --interactive Edit the changes before they are applied.
-n, --dry-run Don't actually rename the note. Instead, prints the changes on stdout
and the updated note path on stderr.
zk move
Usage: zk move <source> ... <target>
Move a note (or several) to a different path, updating all the backlinks.
Arguments:
<source> Paths to the notes or directories to move.
<target> Target directory or path if a single source note is given.
Flags:
-i, --interactive Edit the changes before they are applied.
-n, --dry-run Don't actually move the notes. Instead, prints the changes on stdout
and the updated note paths on stderr.
-i
)The interactive flag offers an opportunity to edit the changes before they are applied. The confirmation is done in two steps, by editing temporary files (similar to git commit
).
This edits a file containing all the filename/paths changes, with the following format:
source > target
source.md > target.md
Foo.md > Bar Qux.md
The user can edit the target paths, or remove a line to cancel a file move. Emptying the file cancels the whole process.
After validating the new paths, zk
will generate all the file changes required (renaming titles, updating links) and generate a POSIX diff.
The user can edit any part of the diff, as long as the output is still a valid POSIX diff file. It will be applied as-is. Emptying the diff file cancels the whole process.
-n
)The dry run flag prints the content of the changes (as edited in the interactive flag) without applying them.
If the client sends a workspace.didRenameFiles
event, the server will trigger the renaming process to update the links.
The user can update the title of a note manually using a RenameRequest
when the caret is over the note title. This will trigger the renaming process to update the links and note filepath.
The LCP integration is not compatible with the interactive mode. The user is expected to backup their notes before such operation.
The user can configure the diff
and patch
commands used by zk
from the config file.
[tool]
# Diff command used to edit the changes applied when renaming notes.
diff = "colordiff -u"
# Editor used to modify a diff when using the interactive mode.
# When missing, falls back on tool.editor.
diff-editor = "nvim"
# Patch command applying the changes when renaming notes.
# Use `patch --backup` to make backup copies of the files before they are modified.
patch = "patch"
Given the note N that we want to retitle "T".
note.filename
option for the note group of N contains the keyword title
:
note.filename
template contains a generated id
, it will be randomized again. This should be fine as the inbound links will be updated anyway, but the user can decide to revert the id
in interactive (-i
) mode. tool.diff-editor
.
.zk/DIFF
.DIFF
the result of replacing in the note content:
format.link-format
with the new title T and generated filepath.DIFF
the result of replacing the old link by the new generated one.DIFF
file using tool.diff-editor
.
tool.patch
.It's not a priority, but the link replacement algorithm could be smarter to try to preserve case changes or custom titles in a link.
Given the note N that we want to move to the new path P.
.zk/DIFF
.DIFF
the result of replacing in the content of N:
format.link-format
with the new path P.DIFF
the result of replacing the old link by the new generated one.DIFF
file using tool.diff-editor
.tool.patch
.Given the sources Sn that we want to move to the new folder P.
tool.diff-editor
.
It's not a priority, but the link replacement algorithm could be smarter to try to preserve case changes or custom titles in a link.
@mickael-menu Look like some logic missing in moving process logic. The links inside the moved file should be updated too. For example, file foo.md
move to bar/
. Then the link ./path/to/file.md
inside foo.md
may need to be updated as ../path/to/file.md
.
I believe this should be in scope for zk
, because the README highlights do mention notebook housekeeping (and renaming is definitely a big part of it, not to mention the "housekeeping" only consists of two features as of now).
The renaming features suggested by @mickael-menu are quite comprehensive; personally I would be very happy with a simple renaming command that lets me do batch renaming using templates, something like the following:
# Change name format from "{{timestamp}}-{{CamelCaseTitle}}" to "{{timestamp}}-{{slug title}}"
zk rename Wiki/ "{{metadata.ctimestamp}}-{{slug title}}"
Since the notes already exist, the rename command can allow metadata and all other relevant fields in the template. This could provide very powerful renaming capabilities.
I am not a heavy user of the linking capabilities so I'm not sure how those would be handled.
Discussed in https://github.com/mickael-menu/zk/discussions/199