Compare commits
No commits in common. 'main' and 'v0.8.0' have entirely different histories.
@ -0,0 +1,2 @@
|
||||
*.db filter=lfs diff=lfs merge=lfs -text
|
||||
*.png filter=lfs diff=lfs merge=lfs -text
|
@ -1,19 +0,0 @@
|
||||
title: "[Help] "
|
||||
body:
|
||||
- type: checkboxes
|
||||
id: checks
|
||||
attributes:
|
||||
label: Verify
|
||||
options:
|
||||
- label: I searched the existing discussions for help
|
||||
required: true
|
||||
- type: textarea
|
||||
id: help
|
||||
attributes:
|
||||
label: How can we help you?
|
||||
validations:
|
||||
required: true
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
:warning: Unfortunately, my time is limited and I can't offer reliable user support. I might answer if you catch me on a slow day, or hopefully someone else will.
|
@ -1,14 +0,0 @@
|
||||
body:
|
||||
- type: checkboxes
|
||||
id: checks
|
||||
attributes:
|
||||
label: Verify
|
||||
options:
|
||||
- label: I searched the existing discussions for similar ideas
|
||||
required: true
|
||||
- type: textarea
|
||||
id: help
|
||||
attributes:
|
||||
label: Share your idea or feature request
|
||||
validations:
|
||||
required: true
|
@ -1,65 +0,0 @@
|
||||
name: Bug report
|
||||
description: File a bug report to help improve zk.
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for filing a bug report!
|
||||
- type: checkboxes
|
||||
id: checks
|
||||
attributes:
|
||||
label: Check if applicable
|
||||
description: |
|
||||
:warning: My time is limited and if I don't plan on fixing the reported bug myself, I might close this issue. No hard feelings.
|
||||
:heart: But if you would like to contribute a fix yourself, **I'll be happy to guide you through the codebase and review a pull request**.
|
||||
options:
|
||||
- label: I have searched the existing issues (**required**)
|
||||
required: true
|
||||
- label: I'm willing to help fix the problem and contribute a pull request
|
||||
- type: textarea
|
||||
id: bug-description
|
||||
attributes:
|
||||
label: Describe the bug
|
||||
description: Also tell me, what did you expect to happen?
|
||||
placeholder: A clear and concise description of what the bug is.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: bug-steps
|
||||
attributes:
|
||||
label: How to reproduce?
|
||||
description: |
|
||||
Step by step explanation to reproduce the issue.
|
||||
|
||||
If you can, drag and drop:
|
||||
- a zipped sample notebook
|
||||
- screenshots or a screencast showing the issue
|
||||
placeholder: |
|
||||
1. Add a note with the content "..."
|
||||
2. Run `zk edit --interactive`
|
||||
3. See error
|
||||
...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: vim-config
|
||||
attributes:
|
||||
label: zk configuration
|
||||
description: |
|
||||
Paste the minimal `zk` configuration file (`.zk/config.toml`) reproducing the issue.
|
||||
render: toml
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: bug-environment
|
||||
attributes:
|
||||
label: Environment
|
||||
description: |
|
||||
Run the following shell commands and paste the result here:
|
||||
```
|
||||
zk --version && echo "system: `uname -srmo`"
|
||||
```
|
||||
placeholder: |
|
||||
zk 0.13.0
|
||||
system: Darwin 22.5.0 arm64
|
||||
render: bash
|
@ -1,10 +0,0 @@
|
||||
name: Feature request
|
||||
description: Suggest an idea for this project.
|
||||
body:
|
||||
- type: checkboxes
|
||||
id: checks
|
||||
attributes:
|
||||
label: If you have an idea, open a discussion
|
||||
options:
|
||||
- label: I will [create a new discussion](https://github.com/zk-org/zk/discussions/new?category=ideas) instead of an issue.
|
||||
|
@ -1,13 +0,0 @@
|
||||
name: User support
|
||||
description: You need help?
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
:warning: Unfortunately, my time is limited and I can't offer reliable user support. I might answer if you catch me on a slow day, or hopefully someone else will.
|
||||
- type: checkboxes
|
||||
id: checks
|
||||
attributes:
|
||||
label: If you need help, open a discussion
|
||||
options:
|
||||
- label: I will [create a new discussion](https://github.com/zk-org/zk/discussions/new?category=help) instead of an issue.
|
@ -1,16 +0,0 @@
|
||||
version: 2
|
||||
updates:
|
||||
|
||||
# Maintain dependencies for GitHub Actions
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
# Maintain dependencies for gomod
|
||||
- package-ecosystem: "gomod"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
# Disable version updates for gomod dependencies
|
||||
open-pull-requests-limit: 0
|
@ -1,40 +0,0 @@
|
||||
name: "CodeQL code scanning"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ main ]
|
||||
schedule:
|
||||
# Wed 23:33 UTC
|
||||
- cron: '33 23 * * 3'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'go' ]
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
@ -1,43 +0,0 @@
|
||||
name: Deploy to GitHub Pages
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- "published"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
concurrency:
|
||||
group: "pages"
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup Pages
|
||||
uses: actions/configure-pages@v5
|
||||
- name: Fix anchor tag in README
|
||||
run: ex -s -c '%s/docs\/getting-started\.md/docs\/getting-started/|x' README.md
|
||||
- name: Build with Jekyll
|
||||
uses: actions/jekyll-build-pages@v1
|
||||
with:
|
||||
source: ./
|
||||
destination: ./_site
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
deploy:
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
steps:
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
@ -1,19 +0,0 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
homebrew:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
- name: Update Homebrew formula
|
||||
uses: dawidd6/action-homebrew-bump-formula@v3
|
||||
with:
|
||||
token: ${{secrets.HOMEBREW_GITHUB_TOKEN}}
|
||||
formula: zk
|
@ -1,31 +0,0 @@
|
||||
name: Triage
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- .github/workflows/triage.yml
|
||||
schedule:
|
||||
# Once every day at midnight UTC
|
||||
- cron: "0 0 * * *"
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
days-before-stale: 30
|
||||
|
||||
days-before-issue-close: 5
|
||||
stale-issue-label: 'stale'
|
||||
stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs in the next 5 days.'
|
||||
close-issue-message: 'This issue was closed because it has been stalled for 5 days with no activity.'
|
||||
exempt-issue-labels: 'help wanted,feature request,enhancement,bug'
|
||||
|
||||
days-before-pr-close: -1
|
||||
stale-pr-label: 'stale'
|
||||
stale-pr-message: 'This pull request has been automatically marked as stale because it has not had recent activity.'
|
@ -1,62 +0,0 @@
|
||||
# Contributing to `zk`
|
||||
|
||||
## Understanding the codebase
|
||||
|
||||
### Building the project
|
||||
|
||||
It is recommended to use the `Makefile` for compiling the project, as the `go` command requires a few parameters.
|
||||
|
||||
```shell
|
||||
make build
|
||||
```
|
||||
|
||||
This will be expanded to the following command:
|
||||
|
||||
```shell
|
||||
CGO_ENABLED=1 GOARCH=arm64 go build -tags "fts5" -ldflags "-X=main.Version=`git describe --tags --match v[0-9]* 2> /dev/null` -X=main.Build=`git rev-parse --short HEAD`"
|
||||
```
|
||||
|
||||
- `CGO_ENABLED=1` enables CGO, which is required by the `mattn/go-sqlite3` dependency.
|
||||
- `GOARCH=arm64` is only required for Apple Silicon chips.
|
||||
- `-tags "fts5"` enables the FTS option with `mattn/go-sqlite3`, which handles much of the magic behind `zk`'s `--match` filtering option.
|
||||
- ``-ldflags "-X=main.Version=`git describe --tags --match v[0-9]* 2> /dev/null` -X=main.Build=`git rev-parse --short HEAD`"`` will automatically set `zk`'s build and version numbers using the latest Git tag and commit SHA.
|
||||
|
||||
### Automated tests
|
||||
|
||||
The project is vetted with two different kind of automated tests: unit tests and end-to-end tests.
|
||||
|
||||
#### Unit tests
|
||||
|
||||
Unit tests are using the standard [Go testing library](https://pkg.go.dev/testing). To execute them, use the command `make test`.
|
||||
|
||||
They are ideal for testing parsing output or individual API edge cases and minutiae.
|
||||
|
||||
#### End-to-end tests
|
||||
|
||||
Most of `zk`'s functionality is tested with functional tests ran with [`tesh`](https://github.com/mickael-menu/tesh), which you can execute with `make tesh` (or `make teshb`, to debug whitespaces changes).
|
||||
|
||||
When addressing a GitHub issue, it's a good idea to begin by creating a `tesh` file in `tests/issue-XXX.tesh`. If a starting notebook state is required, it can be added under `tests/fixtures`.
|
||||
|
||||
If you modify the output of `zk`, you may disrupt some `tesh` files. You can use `make tesh-update` to automatically update them with the correct output.
|
||||
|
||||
### CI workflows
|
||||
|
||||
Several GitHub action workflows are executed when pull requests are merged or releases are created.
|
||||
|
||||
- `.github/workflows/build.yml` checks that the project can be built and the tests still pass.
|
||||
- `.github/workflows/codeql.yml` runs static analysis to vet code quality.
|
||||
- `.github/workflows/gh-pages.yml` deploy the documentation files to GitHub Pages.
|
||||
- `.github/workflows/release.yml` submits a new version to Homebrew when a Git version tag is created.
|
||||
- `.github/workflows/triage.yml` automatically tags old issues and PRs as staled.
|
||||
|
||||
## Releasing a new version
|
||||
|
||||
When `zk` is ready to be released, you can update the `CHANGELOG.md` ([for example](https://github.com/zk-org/zk/commit/ea4457ad671aa85a6b15747460c6f2c9ad61bf73)) and create a new Git version tag (for example `v0.13.0`). Make sure you follow the [Semantic Versioning](https://semver.org) scheme.
|
||||
|
||||
Then, create [a new GitHub release](https://github.com/zk-org/zk/releases) with a copy of the latest `CHANGELOG.md` entries and the binaries for all supported platforms.
|
||||
|
||||
Binaries can be created automatically using `make dist-linux` and `make dist-macos`.
|
||||
|
||||
Unfortunately, `make dist-macos` must be run manually on both an Apple Silicon and Intel chips. The Linux builds are created using Docker and [these custom images](https://github.com/zk-org/zk-xcompile), which are hosted via [ghcr.io within zk-org](https://github.com/orgs/zk-org/packages/container/package/zk-xcompile).
|
||||
|
||||
This process is convoluted because `zk` requires CGO with `mattn/go-sqlite3`, which prevents using Go's native cross-compilation. Transitioning to a CGO-free SQLite driver such as [cznic/sqlite](https://gitlab.com/cznic/sqlite) could simplify the distribution process significantly.
|
@ -1,24 +0,0 @@
|
||||
title: "zk"
|
||||
permalink: /:title
|
||||
defaults:
|
||||
- scope:
|
||||
path: "README.md"
|
||||
values:
|
||||
title: "zk"
|
||||
- scope:
|
||||
path: "" # all
|
||||
values:
|
||||
render_with_liquid: false
|
||||
exclude:
|
||||
- ".github/"
|
||||
- ".gitignore"
|
||||
- "CHANGELOG.md"
|
||||
- "CONTRIBUTING.md"
|
||||
- "LICENSE"
|
||||
- "Makefile"
|
||||
- "go.mod"
|
||||
- "go.sum"
|
||||
- "internal/"
|
||||
- "main.go"
|
||||
- "tests/"
|
||||
|
@ -0,0 +1,2 @@
|
||||
permalink: /:title
|
||||
theme: jekyll-theme-modernist
|
@ -0,0 +1,57 @@
|
||||
<!doctype html>
|
||||
<html lang="{{ site.lang | default: "en-US" }}">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
|
||||
{% seo %}
|
||||
|
||||
<link rel="stylesheet" href="{{ '/assets/css/style.css?v=' | append: site.github.build_revision | relative_url }}">
|
||||
<script src="{{ '/assets/js/scale.fix.js' | relative_url }}"></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
||||
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
<header {% unless site.description or site.github.project_tagline %} class="without-description" {% endunless %}>
|
||||
<h1><a href="https://mickael-menu.github.io/zk/">{{ site.title | default: site.github.repository_name }}</a></h1>
|
||||
{% if site.description or site.github.project_tagline %}
|
||||
<p>{{ site.description | default: site.github.project_tagline }}</p>
|
||||
{% endif %}
|
||||
<p class="view"><a href="{{ site.github.repository_url }}">View the Project on GitHub <small>{{ github_name }}</small></a></p>
|
||||
<ul>
|
||||
{% if site.show_downloads %}
|
||||
<li><a href="{{ site.github.zip_url }}">Download <strong>ZIP File</strong></a></li>
|
||||
<li><a href="{{ site.github.tar_url }}">Download <strong>TAR Ball</strong></a></li>
|
||||
{% endif %}
|
||||
<li><a href="{{ site.github.repository_url }}">View On <strong>GitHub</strong></a></li>
|
||||
</ul>
|
||||
</header>
|
||||
<section>
|
||||
|
||||
{{ content }}
|
||||
|
||||
</section>
|
||||
</div>
|
||||
<footer>
|
||||
{% if site.github.is_project_page %}
|
||||
<p>Project maintained by <a href="{{ site.github.owner_url }}">{{ site.github.owner_name }}</a></p>
|
||||
{% endif %}
|
||||
</footer>
|
||||
<!--[if !IE]><script>fixScale(document);</script><![endif]-->
|
||||
|
||||
{% if site.google_analytics %}
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
ga('create', '{{ site.google_analytics }}', 'auto');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
{% endif %}
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,9 @@
|
||||
---
|
||||
---
|
||||
|
||||
@import "{{ site.theme }}";
|
||||
|
||||
code, pre {
|
||||
font-size: inherit;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 91 KiB |
Before Width: | Height: | Size: 167 KiB After Width: | Height: | Size: 166 KiB |
Before Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 373 KiB After Width: | Height: | Size: 131 B |
@ -1,15 +0,0 @@
|
||||
# Notebook configuration
|
||||
|
||||
The `[notebook]` section from the [configuration file](config.md) is used to set the default notebook directory.
|
||||
If the path starts with `~` it will be replaced with the user home directory (`$HOME`). This property also supports environment variables.
|
||||
|
||||
```toml
|
||||
[notebook]
|
||||
dir = "~/notebook" # same as "$HOME/notebook"
|
||||
```
|
||||
|
||||
The following properties are customizable:
|
||||
|
||||
* `dir` (string)
|
||||
* Path of the default notebook.
|
||||
* Only available in the global config file (`~/.config/zk/config.toml`).
|
@ -1,14 +0,0 @@
|
||||
# Setting your default shell
|
||||
|
||||
This is *currently* not supported on Windows (that defaults always to `cmd`).
|
||||
|
||||
You can customize which shell to use to run aliases and commands either from the [configuration file](config.md) or environment variables. In order of precedence, `zk` will use:
|
||||
|
||||
1. `ZK_SHELL` environment variable
|
||||
2. `shell` configuration property
|
||||
```toml
|
||||
[tool]
|
||||
shell = "/bin/bash"
|
||||
```
|
||||
3. `SHELL` environment variable
|
||||
4. `sh` as fallback
|
@ -1,27 +0,0 @@
|
||||
package lsp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/zk-org/zk/internal/core"
|
||||
)
|
||||
|
||||
const cmdIndex = "zk.index"
|
||||
|
||||
func executeCommandIndex(notebook *core.Notebook, args []interface{}) (interface{}, error) {
|
||||
opts := core.NoteIndexOpts{}
|
||||
if len(args) == 2 {
|
||||
options, ok := args[1].(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("zk.index expects a dictionary of options as second argument, got: %v", args[1])
|
||||
}
|
||||
if forceOption, ok := options["force"]; ok {
|
||||
opts.Force = toBool(forceOption)
|
||||
}
|
||||
if verboseOption, ok := options["verbose"]; ok {
|
||||
opts.Verbose = toBool(verboseOption)
|
||||
}
|
||||
}
|
||||
|
||||
return notebook.Index(opts)
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
package lsp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/zk-org/zk/internal/core"
|
||||
"github.com/zk-org/zk/internal/util/errors"
|
||||
"github.com/tliron/glsp"
|
||||
protocol "github.com/tliron/glsp/protocol_3_16"
|
||||
)
|
||||
|
||||
const cmdLink = "zk.link"
|
||||
|
||||
type cmdLinkOpts struct {
|
||||
Path *string `json:"path"`
|
||||
Location *protocol.Location `json:"location"`
|
||||
Title *string `json:"title"`
|
||||
}
|
||||
|
||||
func executeCommandLink(notebook *core.Notebook, documents *documentStore, context *glsp.Context, args []interface{}) (interface{}, error) {
|
||||
var opts cmdLinkOpts
|
||||
|
||||
if len(args) > 1 {
|
||||
arg, ok := args[1].(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%s expects a dictionary of options as second argument, got: %v", cmdLink, args[1])
|
||||
}
|
||||
err := unmarshalJSON(arg, &opts)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse %s args, got: %v", cmdLink, arg)
|
||||
}
|
||||
}
|
||||
|
||||
if opts.Path == nil {
|
||||
return nil, errors.New("'path' not provided")
|
||||
}
|
||||
|
||||
note, err := notebook.FindByHref(*opts.Path, false)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if note == nil {
|
||||
return nil, errors.New("Requested note to link to not found!")
|
||||
}
|
||||
|
||||
info := &linkInfo{
|
||||
note: note,
|
||||
location: opts.Location,
|
||||
title: opts.Title,
|
||||
}
|
||||
|
||||
err = linkNote(notebook, documents, context, info)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
"path": filepath.Join(notebook.Path, note.Path),
|
||||
}, nil
|
||||
}
|
@ -1,162 +0,0 @@
|
||||
package lsp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/zk-org/zk/internal/cli"
|
||||
"github.com/zk-org/zk/internal/core"
|
||||
"github.com/zk-org/zk/internal/util"
|
||||
"github.com/zk-org/zk/internal/util/errors"
|
||||
strutil "github.com/zk-org/zk/internal/util/strings"
|
||||
)
|
||||
|
||||
const cmdList = "zk.list"
|
||||
|
||||
type cmdListOpts struct {
|
||||
Select []string `json:"select"`
|
||||
cli.Filtering
|
||||
}
|
||||
|
||||
func executeCommandList(logger util.Logger, notebook *core.Notebook, args []interface{}) (interface{}, error) {
|
||||
var opts cmdListOpts
|
||||
if len(args) > 1 {
|
||||
arg, ok := args[1].(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%s expects a dictionary of options as second argument, got: %v", cmdTagList, args[1])
|
||||
}
|
||||
err := unmarshalJSON(arg, &opts)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse %s args, got: %v", cmdTagList, arg)
|
||||
}
|
||||
}
|
||||
|
||||
if len(opts.Select) == 0 {
|
||||
return nil, fmt.Errorf("%s expects a `select` option with the list of fields to return", cmdTagList)
|
||||
}
|
||||
var selection = newListSelection(opts.Select)
|
||||
|
||||
findOpts, err := opts.NewNoteFindOpts(notebook)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
notes, err := notebook.FindNotes(findOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
listNotes := []listNote{}
|
||||
for _, note := range notes {
|
||||
listNotes = append(listNotes, newListNote(note, selection, notebook.Path))
|
||||
}
|
||||
|
||||
return listNotes, nil
|
||||
}
|
||||
|
||||
type listSelection struct {
|
||||
Filename bool
|
||||
FilenameStem bool
|
||||
Path bool
|
||||
AbsPath bool
|
||||
Title bool
|
||||
Lead bool
|
||||
Body bool
|
||||
Snippets bool
|
||||
RawContent bool
|
||||
WordCount bool
|
||||
Tags bool
|
||||
Metadata bool
|
||||
Created bool
|
||||
Modified bool
|
||||
Checksum bool
|
||||
}
|
||||
|
||||
func newListSelection(fields []string) listSelection {
|
||||
return listSelection{
|
||||
Filename: strutil.Contains(fields, "filename"),
|
||||
FilenameStem: strutil.Contains(fields, "filenameStem"),
|
||||
Path: strutil.Contains(fields, "path"),
|
||||
AbsPath: strutil.Contains(fields, "absPath"),
|
||||
Title: strutil.Contains(fields, "title"),
|
||||
Lead: strutil.Contains(fields, "lead"),
|
||||
Body: strutil.Contains(fields, "body"),
|
||||
Snippets: strutil.Contains(fields, "snippets"),
|
||||
RawContent: strutil.Contains(fields, "rawContent"),
|
||||
WordCount: strutil.Contains(fields, "wordCount"),
|
||||
Tags: strutil.Contains(fields, "tags"),
|
||||
Metadata: strutil.Contains(fields, "metadata"),
|
||||
Created: strutil.Contains(fields, "created"),
|
||||
Modified: strutil.Contains(fields, "modified"),
|
||||
Checksum: strutil.Contains(fields, "checksum"),
|
||||
}
|
||||
}
|
||||
|
||||
func newListNote(note core.ContextualNote, selection listSelection, basePath string) listNote {
|
||||
var res listNote
|
||||
if selection.Filename {
|
||||
res.Filename = note.Filename()
|
||||
}
|
||||
if selection.FilenameStem {
|
||||
res.FilenameStem = note.FilenameStem()
|
||||
}
|
||||
if selection.Path {
|
||||
res.Path = note.Path
|
||||
}
|
||||
if selection.AbsPath {
|
||||
res.AbsPath = filepath.Join(basePath, note.Path)
|
||||
}
|
||||
if selection.Title {
|
||||
res.Title = note.Title
|
||||
}
|
||||
if selection.Lead {
|
||||
res.Lead = note.Lead
|
||||
}
|
||||
if selection.Body {
|
||||
res.Body = note.Body
|
||||
}
|
||||
if selection.Snippets {
|
||||
res.Snippets = note.Snippets
|
||||
}
|
||||
if selection.RawContent {
|
||||
res.RawContent = note.RawContent
|
||||
}
|
||||
if selection.WordCount {
|
||||
res.WordCount = note.WordCount
|
||||
}
|
||||
if selection.Tags {
|
||||
res.Tags = note.Tags
|
||||
}
|
||||
if selection.Metadata {
|
||||
res.Metadata = note.Metadata
|
||||
}
|
||||
if selection.Created {
|
||||
res.Created = ¬e.Created
|
||||
}
|
||||
if selection.Modified {
|
||||
res.Modified = ¬e.Modified
|
||||
}
|
||||
if selection.Checksum {
|
||||
res.Checksum = note.Checksum
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
type listNote struct {
|
||||
Filename string `json:"filename,omitempty"`
|
||||
FilenameStem string `json:"filenameStem,omitempty"`
|
||||
Path string `json:"path,omitempty"`
|
||||
AbsPath string `json:"absPath,omitempty"`
|
||||
Title string `json:"title,omitempty"`
|
||||
Lead string `json:"lead,omitempty"`
|
||||
Body string `json:"body,omitempty"`
|
||||
Snippets []string `json:"snippets,omitempty"`
|
||||
RawContent string `json:"rawContent,omitempty"`
|
||||
WordCount int `json:"wordCount,omitempty"`
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
Metadata map[string]interface{} `json:"metadata,omitempty"`
|
||||
Created *time.Time `json:"created,omitempty"`
|
||||
Modified *time.Time `json:"modified,omitempty"`
|
||||
Checksum string `json:"checksum,omitempty"`
|
||||
}
|
@ -1,112 +0,0 @@
|
||||
package lsp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/zk-org/zk/internal/core"
|
||||
dateutil "github.com/zk-org/zk/internal/util/date"
|
||||
"github.com/zk-org/zk/internal/util/errors"
|
||||
"github.com/zk-org/zk/internal/util/opt"
|
||||
"github.com/tliron/glsp"
|
||||
protocol "github.com/tliron/glsp/protocol_3_16"
|
||||
)
|
||||
|
||||
const cmdNew = "zk.new"
|
||||
|
||||
type cmdNewOpts struct {
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
Dir string `json:"dir"`
|
||||
Group string `json:"group"`
|
||||
Template string `json:"template"`
|
||||
Extra map[string]string `json:"extra"`
|
||||
Date string `json:"date"`
|
||||
Edit jsonBoolean `json:"edit"`
|
||||
DryRun jsonBoolean `json:"dryRun"`
|
||||
InsertLinkAtLocation *protocol.Location `json:"insertLinkAtLocation"`
|
||||
InsertContentAtLocation *protocol.Location `json:"insertContentAtLocation"`
|
||||
}
|
||||
|
||||
func executeCommandNew(notebook *core.Notebook, documents *documentStore, context *glsp.Context, args []interface{}) (interface{}, error) {
|
||||
var opts cmdNewOpts
|
||||
if len(args) > 1 {
|
||||
arg, ok := args[1].(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%s expects a dictionary of options as second argument, got: %v", cmdNew, args[1])
|
||||
}
|
||||
err := unmarshalJSON(arg, &opts)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse %s args, got: %v", cmdNew, arg)
|
||||
}
|
||||
}
|
||||
|
||||
date, err := dateutil.TimeFromNatural(opts.Date)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "%s, failed to parse the `date` option", opts.Date)
|
||||
}
|
||||
|
||||
note, err := notebook.NewNote(core.NewNoteOpts{
|
||||
Title: opt.NewNotEmptyString(opts.Title),
|
||||
Content: opts.Content,
|
||||
Directory: opt.NewNotEmptyString(opts.Dir),
|
||||
Group: opt.NewNotEmptyString(opts.Group),
|
||||
Template: opt.NewNotEmptyString(opts.Template),
|
||||
Extra: opts.Extra,
|
||||
DryRun: bool(opts.DryRun),
|
||||
Date: date,
|
||||
})
|
||||
if err != nil {
|
||||
var noteExists core.ErrNoteExists
|
||||
if !errors.As(err, ¬eExists) {
|
||||
return nil, err
|
||||
}
|
||||
note, err = notebook.FindNote(core.NoteFindOpts{
|
||||
IncludeHrefs: []string{noteExists.Name},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if note == nil {
|
||||
return nil, errors.New("zk.new could not generate a new note")
|
||||
}
|
||||
|
||||
if opts.InsertContentAtLocation != nil {
|
||||
go context.Call(protocol.ServerWorkspaceApplyEdit, protocol.ApplyWorkspaceEditParams{
|
||||
Edit: protocol.WorkspaceEdit{
|
||||
Changes: map[string][]protocol.TextEdit{
|
||||
opts.InsertContentAtLocation.URI: {{Range: opts.InsertContentAtLocation.Range, NewText: note.RawContent}},
|
||||
},
|
||||
},
|
||||
}, nil)
|
||||
}
|
||||
|
||||
if !opts.DryRun && opts.InsertLinkAtLocation != nil {
|
||||
minNote := note.AsMinimalNote()
|
||||
|
||||
info := &linkInfo{
|
||||
note: &minNote,
|
||||
location: opts.InsertLinkAtLocation,
|
||||
title: &opts.Title,
|
||||
}
|
||||
err := linkNote(notebook, documents, context, info)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
absPath := filepath.Join(notebook.Path, note.Path)
|
||||
if !opts.DryRun && opts.Edit {
|
||||
go context.Call(protocol.ServerWindowShowDocument, protocol.ShowDocumentParams{
|
||||
URI: pathToURI(absPath),
|
||||
TakeFocus: boolPtr(true),
|
||||
}, nil)
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
"path": absPath,
|
||||
"content": note.RawContent,
|
||||
}, nil
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
package lsp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/zk-org/zk/internal/core"
|
||||
"github.com/zk-org/zk/internal/util"
|
||||
"github.com/zk-org/zk/internal/util/errors"
|
||||
)
|
||||
|
||||
const cmdTagList = "zk.tag.list"
|
||||
|
||||
type cmdTagListOpts struct {
|
||||
Sort []string `json:"sort"`
|
||||
}
|
||||
|
||||
func executeCommandTagList(logger util.Logger, notebook *core.Notebook, args []interface{}) (interface{}, error) {
|
||||
var opts cmdTagListOpts
|
||||
if len(args) > 1 {
|
||||
arg, ok := args[1].(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%s expects a dictionary of options as second argument, got: %v", cmdTagList, args[1])
|
||||
}
|
||||
err := unmarshalJSON(arg, &opts)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse %s args, got: %v", cmdTagList, arg)
|
||||
}
|
||||
}
|
||||
|
||||
var sorters []core.CollectionSorter
|
||||
var err error
|
||||
if opts.Sort != nil {
|
||||
sorters, err = core.CollectionSortersFromStrings(opts.Sort)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return notebook.FindCollections(core.CollectionKindTag, sorters)
|
||||
}
|