Skip to content

[Suggestion]: Rethinking link target syntax #62

@boltlessengineer

Description

@boltlessengineer

Currently link location syntax (that one under {...}) is bit unorganized imo.

  • file location {:this:} (for norg files)
  • line number {123}
  • URL {https://example.com}
  • detached modifier {* heading} or {^ footnote} excluding nestable detached modifiers
  • file linkable {/ this.txt}
  • magic char {# this}
  • wiki link {? this}
  • timestamps {@ this}
  • extendable link {= this} (already deprecated as we will remove legacy attributes nestable detached modifiers)

Several thoughts on this:

  • Do we need a line number? How would we implement it? Line Number Link feature should be depreciated #22
  • 3 ways to link to file is bit too much.
  • What are timestamps and why do we need them as links? They won't work without the context of Neorg workspace and journaling system. Then why are we including it in Norg as a first-class citizen?
  • How can we support both URI, POSIX path, Windows-style path in same syntax? Previous discussion on discord server

So I tried to do a complete redesign just as I did with layer system on #57

Suggestion

  • Deprecate file linkable and merge it with URI links as raw links.
  • Deprecate line number. Merge it to URI links and let Neorg-like applications to handle them. So user can choose from both path/to/file.txt:123 or path/to/file.txt#L123. But Norg itself won't guarantee this will always work.
  • Deprecate timestamps and extendable link.
  • Don't support Windows-style path.
  • Omit $ for current workspace. Just start with {:/
  • Re-organize link targets based on how they work, rather than how they're implemented

Full explanation

full PEG expression (janet)
(defn- app-target
  [& args]
  [:app (match args
          [[:workspace workspace]
           path
           [:scopes scopes]] {:workspace workspace
                              :path path
                              :scopes scopes}
          [path
           [:scopes scopes]] {:path path
                              :scopes scopes})])

(def target-peg
  (peg/compile
    ~{:main (* :s* (+ :app :local))
      :app (/ (* (? (* :sep :workspace))
                 :sep
                 :scope-text
                 (+ (* :sep :scopes)
                    (constant [:scopes []])))
              ,app-target)
      :local (/ (+ :scopes :uri)
                ,|[:local $])
      :uri (/ (<- (some 1))
              ,|[:uri $])
      :scopes (/ (* :scope (any (* :sep (? :scope))))
                 ,|[:scopes [;$&]])
      :workspace (/ (* "$" :scope-text)
                    ,|[:workspace $])
      :scope-text (<- (some (if-not :sep 1)))
      :sep (* :s* ":" :s*)
      :scope (+ :scope-heading
                :scope-wiki)
      :scope-heading-prefix (/ (* (<- (some "*")) :s*)
                               ,length)
      :scope-heading (/ (* :scope-heading-prefix
                           :scope-text)
                        ,|[:heading $0 $1])
      :scope-wiki (* "?"
                     :s+
                     :scope-text)}))

In norg, there are two types of links:

  • app links
  • raw links

App links

App links will always point to a norg file, including current document.

It can be divided to three parts:

  • workspace
  • path
  • scopes

Example

{:path/to/norg_file} - find `path/to/norg_file.norg` relative to current document path
{:path/to/norg_file:} - same as above (empty scope)
{:/path/to/norg_file} - find `path/to/norg_file.norg` from current workspace root
{:$foo} - find `index.norg` from root of workspace `foo`
{* heading} - find `* heading` from current document
{:$foo/path/to/norg_file} - find `path/to/norg_file.norg` from root of workspace `foo`
{:/path/to/norg_file:* heading} - find `* heading` in file `path/to/norg_file.norg` from current workspace root.

Raw links

Raw links are any link location that doesn't match to app links.

Example

{https://example.com}
{file:///path/to/file.txt}
{path/to/file.txt}
{./path/to/file.txt}
{/path/to/file.txt}
{/path/to/file.txt:123}
{/path/to/file.txt#L123-L125}

{/c/Users/boltless/file.txt} - POSIX-mapped windows-style path (MSYS style)

It is usually in form of UTF-8 URI but parsers won't check that. Usually works without the context of Neorg-like application.

This can be useful when used on single file mode and when we know the only export target like README.norg which will export to HTML file rendered on repository homepage.
For example, user can link to a static file under same domain without creating entire link resolving system in Neorg-like application like {/assets/style.css} or {/rss.xml}.

On export, exporter won't usually touch raw links.
On navigating (e.g. LSP goto-definition), Neorg-like applications will try to resolve the location based on how they are implemented/configured.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions