Skip to content

Commit de81f41

Browse files
authored
Merge pull request #5 from Garulf/feat-Check-list
Feature: Toggle Checklists via Context Menu
2 parents 12bed89 + 8b09207 commit de81f41

File tree

3 files changed

+94
-2
lines changed

3 files changed

+94
-2
lines changed

plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"Name": "Obsidian Notes",
55
"Description": "Search Obsidian notes",
66
"Author": "Garulf",
7-
"Version": "1.0.2",
7+
"Version": "1.1.0",
88
"Language": "python",
99
"Website": "https://github.com/Garulf/obsidian-notes",
1010
"IcoPath": "./icon.png",

plugin/main.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44

55
import obsidian
66

7+
CHECK_BOX_GLYPH = '\ue003'
8+
MARKED_CHECK_BOX_GLYPH = '\ue005'
9+
10+
711
def match(query, match):
812
return int(SM(lambda x: x == " ", query.lower().replace('\\', ' '), match.lower().replace('\\', ' '), autojunk=False).ratio() * 100)
913

@@ -31,10 +35,26 @@ def query(self, query):
3135
method=self.open_note,
3236
parameters=[vault.name, str(note.relative_path)],
3337
score=score,
38+
context=[vault.id, str(note.path), note.checklists()]
3439
)
3540

3641
def context_menu(self, data):
37-
pass
42+
vault_id = data[0]
43+
note_path = data[1]
44+
for checks in data[2]:
45+
self.add_item(
46+
title=checks['description'],
47+
subtitle=checks['title'],
48+
glyph=MARKED_CHECK_BOX_GLYPH if checks['checked'] else CHECK_BOX_GLYPH,
49+
method=self.toggle_checkbox,
50+
parameters=[vault_id, note_path, checks['raw']],
51+
dont_hide=True
52+
)
53+
54+
def toggle_checkbox(self, vault_id, note_path, raw):
55+
note = obsidian.get_note(vault_id, note_path)
56+
note.toggle_checkbox(raw)
57+
3858

3959
def open_note(self, vault_name, note_path):
4060
obsidian.open_note(vault_name, note_path)

plugin/obsidian.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
VAULTS_FILE = 'obsidian.json'
1010
VAULTS_PATH = Path(os.getenv('APPDATA'), 'obsidian', VAULTS_FILE)
11+
CHECK_BOX = '- [ ]'
12+
MARKED_CHECK_BOX = '- [x]'
1113

1214
def get_vaults():
1315
vaults = []
@@ -22,6 +24,25 @@ def get_vaults():
2224
vaults.append(Vault(vault, data['vaults'][vault]))
2325
return vaults
2426

27+
def get_vault(id):
28+
try:
29+
with open(VAULTS_PATH, 'r') as f:
30+
data = json.load(f)
31+
except FileNotFoundError:
32+
logger.error(f'{VAULTS_PATH} not found!\nIs obsidian installed?')
33+
raise
34+
else:
35+
try:
36+
return Vault(id, data['vaults'][id])
37+
except KeyError:
38+
logger.error(f'{id} not found!')
39+
raise
40+
41+
def get_note(vault_id, note_path):
42+
vault = get_vault(vault_id)
43+
return Note(vault, note_path)
44+
45+
2546
def open_note(vault_name, note_path):
2647
URI = f'open?vault={vault_name}&file={note_path}'.replace(' ', '%20').replace('/', '%2F').replace('\\', '%2F')
2748
URI = f'obsidian://{URI}'
@@ -42,6 +63,11 @@ def notes(self):
4263
notes.append(Note(self, note))
4364
return notes
4465

66+
def note(self, note_path):
67+
for note in self.notes():
68+
if str(note.relative_path) == note_path:
69+
return note
70+
4571

4672
class Note(object):
4773

@@ -55,6 +81,52 @@ def __init__(self, vault: Vault, full_path: str):
5581
def open_note(self):
5682
open_note(self.vault.name, self.relative_path)
5783

84+
def content(self):
85+
with open(self.path, 'r') as f:
86+
return f.read()
87+
88+
89+
def toggle_checkbox(self, raw):
90+
content = self.content()
91+
for line in content.splitlines():
92+
if raw == line:
93+
if MARKED_CHECK_BOX in line:
94+
toggled_line = line.replace(MARKED_CHECK_BOX, CHECK_BOX)
95+
else:
96+
toggled_line = line.replace(CHECK_BOX, MARKED_CHECK_BOX)
97+
break
98+
content = content.replace(line, toggled_line)
99+
with open(self.path, 'w') as f:
100+
f.write(content)
101+
102+
def checklists(self):
103+
checklists = []
104+
title = ''
105+
for line in self.content().splitlines():
106+
if CHECK_BOX in line or MARKED_CHECK_BOX in line:
107+
description = line.replace(CHECK_BOX, '').replace(MARKED_CHECK_BOX, '').strip()
108+
if MARKED_CHECK_BOX in line:
109+
checked = True
110+
else:
111+
checked = False
112+
if (CHECK_BOX not in prev_line and MARKED_CHECK_BOX not in prev_line) and prev_line.endswith(':'):
113+
title = prev_line.replace(':', '').strip()
114+
checklists.append(
115+
{
116+
'title': title,
117+
'description': description,
118+
'checked': checked,
119+
'raw': line
120+
}
121+
)
122+
else:
123+
title = ''
124+
prev_line = line
125+
return checklists
126+
127+
128+
129+
58130
if __name__ == "__main__":
59131
vaults = get_vaults()
60132
for vault in vaults:

0 commit comments

Comments
 (0)