Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[local_bookmark:1.0] feat: Implement MVP #199

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions local_bookmark/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Albert Local Bookmark Plugin

Open the URLs defined in the local plain text file.

## The format of the bookmark file

```
# Keyword 1
http://example1.com

# Keyword 2, Keyword 3
http://example2.com

# keyword 4
http://a.example3.com
http://b.example3.com

# Keyword 5
http://a.example4.com

# Keyword 5
http://b.example4.com
```

That is:
- The keywords are preceded by a `#` and are comma-separated, and the URLs are listed below the keywords.
- Empty lines are ignored.
- The keyword and URL mappings can be 1 to 1, 1 to many, or many to 1.
- URLs with the same keyword are allowed, as the "Keyword 5" shown in the example above.
- Keywords are case-insensitive.
121 changes: 121 additions & 0 deletions local_bookmark/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2024 Chi-Sheng Liu

"""
Open the URLs defined in the local plain text file.

See https://github.com/albertlauncher/python/local_bookmark for details
"""

from albert import *
from pathlib import Path
import webbrowser

from thefuzz import fuzz

md_iid = '2.0'
md_version = '1.0'
md_name = 'Local Bookmark'
md_description = 'Open locally defined URLs in browser'
md_license = "MIT"
md_url = 'https://github.com/albertlauncher/python/local_bookmark'
md_authors = "@MortalHappiness"
md_lib_dependencies = ["thefuzz"]


class LocalBookmarkPluginError(Exception):
pass


class Plugin(PluginInstance, TriggerQueryHandler):
def __init__(self):
TriggerQueryHandler.__init__(self,
id=md_id,
name=md_name,
description=md_description,
defaultTrigger='lb ')
PluginInstance.__init__(self, extensions=[self])

self._file_path = self.readConfig('file_path', str)
if self._file_path is None:
self._file_path = ""

@property
def file_path(self):
return self._file_path

@file_path.setter
def file_path(self, value):
self._file_path = value
self.writeConfig('file_path', value)

def configWidget(self):
return [
{
"type": "lineedit",
"label": "Bookmark file path",
"property": "file_path",
},
]

def handleTriggerQuery(self, query):
file_path = self.file_path

try:
if not file_path:
raise LocalBookmarkPluginError("Please set the bookmark file path in the configuration.")
if not Path(file_path).is_file():
raise LocalBookmarkPluginError("The file does not exist. Please create one.")
except LocalBookmarkPluginError as e:
query.add(
StandardItem(
id=md_name,
text="Error",
subtext=str(e),
iconUrls=["xdg:error"],
)
)
return

# Parse the file
keyword_to_urls = {}
current_keywords = ()
for line in Path(file_path).read_text().split("\n"):
if not line:
continue
if line.startswith("#"):
current_keywords = tuple(keyword.strip() for keyword in line[1:].split(","))
continue
for keyword in current_keywords:
keyword_to_urls.setdefault(keyword, []).append(line)

search = query.string.strip().lower()
if not search:
query.add(
StandardItem(
id=md_name,
text="Open the local bookmark file in editor",
iconUrls=["xdg:text"],
actions=[Action("config", "Open the local bookmark file in editor",
lambda: runDetachedProcess(["xdg-open", file_path]))]
)
)
return

items = []
for keyword, urls in sorted(keyword_to_urls.items()):
score = fuzz.token_set_ratio(search, keyword.lower())
if score:
items.extend([(score, keyword, url) for url in urls])
items.sort(reverse=True, key=lambda x: x[0])

query.add([
StandardItem(
id=md_name,
text=keyword,
subtext=url,
iconUrls=["xdg:browser"],
actions=[Action("open", "Open in browser", lambda u=url: webbrowser.open(u))]
) for (_, keyword, url) in items
])
return items