Skip to content

Commit

Permalink
Highlighting of note links 😄
Browse files Browse the repository at this point in the history
  • Loading branch information
Rene Schallner committed Oct 31, 2017
1 parent e998ac1 commit 903bc2f
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 18 deletions.
45 changes: 28 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,19 @@ If you follow the (plain-text) Zettelkasten method (as proposed by [Zettelkasten

In short, it helps you manage an archive of interlinked notes that look like this:

```python
# The rise of the machines
tags = #AI #world-domination
![screenshot](sublime_zk.png)

Machines are becoming more and more intelligent and powerful.
See the **Usage** section below to see how this package might support your workflow.

This might reach a point where they might develop a consciensce of their own.

As a consequence, they might turn evil and try to kill us all ........... [[201710282118]]
```
## Features

See the **Feature** section below to see how this package might support your workflow.
* This plugin enables you to place wiki style links like `[[this]]` into your notes to link to other notes in your note archive.
* Clicking such a link and pressing `[ctrl]+[enter]` will open the corresponding note.
* Typing `[[` will open a list of existing notes so you can quickly link to existing notes.
* Typing `[shift]+[enter]` lets you enter a name for a new note. The new note is then created with a new note ID.
* Implicit note creation via links to non-existing notes' titles, see below.
* The ID format is YYYYMMDDHHMM - eg: 201710282111
* Highlighting of note links


## Installation
Expand All @@ -38,7 +39,7 @@ You should be all set.

### Zettelkasten note folder

No further configuration is necessary. This Zettelkasten package works with SublimeText Projects. It will use exactly the same directory where your SublimeText project file is located.
No further configuration is necessary. This Zettelkasten plugin works with SublimeText Projects. It will use exactly the same directory where your SublimeText project file is located.

#### How do I create a project in SublimeText?

Expand Down Expand Up @@ -76,16 +77,26 @@ The setting id_in_title is set to "false"

You can find this setting in the file `sublime_zk.sublime-settings`.

### Highlight references to other notes

By default, this plugin highlights links to other notes by underlying them.

**Note:** This only applies to links containing an ID, like this one: [[201710290256]].

It also shows a bookmark symbol in the gutter to the left of your text. These features can be controlled via the following settings in `sublime_zk.sublime-settings`:


```json
// highlight links to other notes?
"highlight_note_links": "true",

// when highlighting: also show bookmark symbols in the gutter?
"show_bookmarks_in_gutter": "true"
```

## Features

* This package enables you to place wiki style links like `[[this]]` into your notes to link to other notes in your note archive.
* Clicking such a link and pressing `[ctrl]+[enter]` will open the corresponding note.
* Typing `[[` will open a list of existing notes so you can quickly link to existing notes.
* Typing `[shift]+[enter]` lets you enter a name for a new note. The new note is then created with a new note ID.
* Implicit note creation via links to non-existing notes' titles, see below.
* The ID format is YYYYMMDDHHMM - eg: 201710282111

## Usage

### Creating a new note

Expand Down
Binary file added sublime_zk.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
110 changes: 110 additions & 0 deletions sublime_zk.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import sublime, sublime_plugin, os, re, subprocess, glob, datetime

# for highlighting
import threading

def timestamp():
return '{:%Y%m%d%H%M}'.format(datetime.datetime.now())
Expand Down Expand Up @@ -117,3 +119,111 @@ class InsertWikiLinkCommand(sublime_plugin.TextCommand):
def run(self, edit, args):
self.view.insert(edit, self.view.sel()[0].begin(), args['text'])









class NoteLinkHighlighter(sublime_plugin.EventListener):
LINK_REGEX = r"(\[\[)[0-9]{12}(\]\])"
DEFAULT_MAX_LINKS = 1000

note_links_for_view = {}
scopes_for_view = {}
ignored_views = []
highlight_semaphore = threading.Semaphore()

def on_activated(self, view):
self.update_note_link_highlights(view)

# Async listeners for ST3
def on_load_async(self, view):
self.update_note_link_highlights_async(view)

def on_modified_async(self, view):
self.update_note_link_highlights_async(view)

def on_close(self, view):
for map in [self.note_links_for_view, self.scopes_for_view, self.ignored_views]:
if view.id() in map:
del map[view.id()]

"""The logic entry point. Find all LINKs in view, store and highlight them"""
def update_note_link_highlights(self, view):
settings = sublime.load_settings('sublime_zk.sublime-settings')
should_highlight_note_links = settings.get('highlight_note_links', "True")
should_highlight_note_links = should_highlight_note_links.lower() != "false"

max_note_link_limit = NoteLinkHighlighter.DEFAULT_MAX_LINKS
if view.id() in NoteLinkHighlighter.ignored_views:
return

note_links = view.find_all(NoteLinkHighlighter.LINK_REGEX)

# update the regions to ignore the brackets
note_links = [sublime.Region(n.a+2, n.b-2) for n in note_links]

# Avoid slowdowns for views with too many LINKs
if len(note_links) > max_note_link_limit:
print("NoteLinkHighlighter: ignoring view with %u links" % len(note_links))
NoteLinkHighlighter.ignored_views.append(view.id())
return

NoteLinkHighlighter.note_links_for_view[view.id()] = note_links

if (should_highlight_note_links):
self.highlight_note_links(view, note_links)

def update_note_link_highlights_async(self, view):
NoteLinkHighlighter.highlight_semaphore.acquire()
try:
self.update_note_link_highlights(view)
finally:
NoteLinkHighlighter.highlight_semaphore.release()

"""Creates a set of regions from the intersection of note_links and scopes,
underlines all of them."""
def highlight_note_links(self, view, note_links):
settings = sublime.load_settings('sublime_zk.sublime-settings')
show_bookmarks_in_gutter = settings.get('show_bookmarks_in_gutter', "True")
show_bookmarks_in_gutter = show_bookmarks_in_gutter.lower() != "false"

# We need separate regions for each lexical scope for ST to use a proper color for the underline
scope_map = {}
for note_link in note_links:
scope_name = view.scope_name(note_link.a)
scope_map.setdefault(scope_name, []).append(note_link)

for scope_name in scope_map:
self.underline_regions(view, scope_name, scope_map[scope_name], show_bookmarks_in_gutter)

self.update_view_scopes(view, scope_map.keys())

"""Apply underlining to provided regions."""
def underline_regions(self, view, scope_name, regions, show_bookmarks=True):
if show_bookmarks:
symbol = 'bookmark'
else:
symbol = ''

view.add_regions(
u'clickable-note_links ' + scope_name,
regions,
#scope_name +
"markup.bold",
symbol,
flags=sublime.DRAW_NO_FILL|sublime.DRAW_NO_OUTLINE|sublime.DRAW_SOLID_UNDERLINE)

"""Store new set of underlined scopes for view. Erase underlining from
scopes that were used but are not anymore."""
def update_view_scopes(self, view, new_scopes):
old_scopes = NoteLinkHighlighter.scopes_for_view.get(view.id(), None)
if old_scopes:
unused_scopes = set(old_scopes) - set(new_scopes)
for unused_scope_name in unused_scopes:
view.erase_regions(u'clickable-note_links ' + unused_scope_name)

NoteLinkHighlighter.scopes_for_view[view.id()] = new_scopes
11 changes: 10 additions & 1 deletion sublime_zk.sublime-settings
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,14 @@
"wiki_extension": ".md",

// when creating a new note, put id into title?
"id_in_title": "false"
// "false" to disable
"id_in_title": "false",

// highlight links to other notes?
// "false" to disable
"highlight_note_links": "true",

// when highlighting: also show bookmark symbols in the gutter?
// "false" to disable
"show_bookmarks_in_gutter": "true"
}

0 comments on commit 903bc2f

Please sign in to comment.