feat: add bookmarks plugin (#132)
* dunarand/bookmarks plugin * fix: incorrect thumbnail.webp name * fix: corrected plugin.toml Removed invalid tag and noctalia version field * fix: Added missing `bar` widget entry to plugin section * docs: Added keybinds table * feat: added search IPC Directly initiates the search mode on noctalia msg panel-toggle dunarand/bookmarks:panel search * feat: drag bookmarks into/out of folders * fix+style: fixed regressing drag space highlight + renamed functions due to linter complaints * refactor:style: code cleanup & helper functions * chore: translation strings * feat: Turkish translation strings * chore: added nohup as dependency, bumped the version * style: formatting * docs: updated README to include nohup dependency
@@ -0,0 +1,121 @@
|
||||
# Bookmarks
|
||||
|
||||
A bookmarks/shortcuts plugin for Noctalia. You can add folders and commands to a list of bookmarks.
|
||||
Reorder bookmarks, categorize them with folders, set glyphs and labels, and simply left click to
|
||||
execute. All of it is user defined, stored in a JSON file you can backup.
|
||||
|
||||
## Plugin
|
||||
|
||||
| Field | Value |
|
||||
| ------- | ---------------------------------- |
|
||||
| ID | `dunarand/bookmarks` |
|
||||
| Entries | Bar widget: `bar`; panel: `panel`; |
|
||||
|
||||
Bar widget `bar` is not required. Instead, you can assign a keybind to directly open the `panel`,
|
||||
which is shown in the Usage section.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Noctalia v5.0.0 or higher
|
||||
- `nohup` (Optional): For "Run in background" wrapper toggle
|
||||
|
||||
## Usage
|
||||
|
||||
You can add the widget to your bar or assign the following command to your compositor keybinds. For
|
||||
example, in Hyprland v0.55+
|
||||
|
||||
```
|
||||
hl.bind(
|
||||
"SUPER + SHIFT + B",
|
||||
hl.dsp.exec_cmd("noctalia msg panel-toggle dunarand/bookmarks:panel")
|
||||
)
|
||||
```
|
||||
|
||||
You can interact with the bookmarks list via keybinds:
|
||||
|
||||
| Keybind | Purpose |
|
||||
| ------------------------ | ---------------------------------------------------------------- |
|
||||
| `CTRL + N` or Down Arrow | Select the next (below) item |
|
||||
| `CTRL + P` or Up Arrow | Select the previous (above) item |
|
||||
| `CTRL + S` | Search bookmarks |
|
||||
| `Enter` / `Return` | Execute the selected bookmark's command / Navigate into a folder |
|
||||
|
||||
- Bookmarks and folders are listed in the main panel.
|
||||
|
||||

|
||||
|
||||
- "?" button shows tooltips: bookmark command and its description.
|
||||
|
||||

|
||||
|
||||
- You can create or edit bookmarks by assigning them a glyph, a label, a command, and an
|
||||
optional description.
|
||||
|
||||

|
||||
|
||||
- "Run in background" toggle wraps the command you defined in the following way:
|
||||
|
||||
`nohup <bookmark-command> >/dev/null 2>&1 &`
|
||||
|
||||
For example, instead of typing the whole command
|
||||
|
||||
`nohup xdg-open "$HOME" >/dev/null 2>&1 &`
|
||||
|
||||
each time, you can instead define the command as `xdg-open "$HOME"` and toggle "Run in
|
||||
background" switch.
|
||||
|
||||
- "Run in terminal" switch executes the command with the default terminal. These switches are
|
||||
mutually exclusive so you can only choose one. Toggling on a switch will result the other to
|
||||
turn off.
|
||||
|
||||
- You can create folders and nest other bookmarks within folders.
|
||||
|
||||

|
||||
|
||||
Folders cannot nest other folders. This is by design and it'll not change unless I find a
|
||||
genuine usecase. You can edit folders by clicking on the "pen" icon next to its name.
|
||||
|
||||
- You can press the "eye" icon to enter edit mode where you can edit, delete, and reorder bookmarks.
|
||||
|
||||

|
||||
|
||||
- Each bookmark can be edited anytime.
|
||||
|
||||

|
||||
|
||||
The saved bookmarks are written to `$NOCTALIA_STATE_HOME/plugins/data/dunarand/bookmarks/data.json`.
|
||||
By default, `$NOCTALIA_STATE_HOME` should point to `~/.local/state/noctalia`. You can point to a
|
||||
different location for saving and backing up your bookmarks. This setting is configurable via
|
||||
**plugin settings** under Settings -> Plugins. Only JSON format is accepted.
|
||||
|
||||
## Settings
|
||||
|
||||
The bar widget has the following settings:
|
||||
|
||||
| Setting | Type | Default | Description |
|
||||
| --------- | -------- | ----------- | -------------------------------- |
|
||||
| `glyph` | `glyph` | `bookmark` | Glyph displayed on the bar |
|
||||
| `tooltip` | `string` | `Bookmarks` | Tooltip displayed on the bar |
|
||||
| `text` | `string` | `Bookmarks` | Widget text displayed on the bar |
|
||||
|
||||
The plugin itself has the following settings:
|
||||
|
||||
| Setting | Type | Default | Description |
|
||||
| ------------------ | ------ | ------- | ------------------------------------------------------------------------------------- |
|
||||
| `data_path` | `file` | | data.json file to store the saved bookmarks. Leave empty to use the default location. |
|
||||
| `show_info_button` | `bool` | `true` | Shows the "?" tooltip button on the bookmark entries. |
|
||||
|
||||
## IPC
|
||||
|
||||
1. Open the bookmarks panel:
|
||||
|
||||
```sh
|
||||
noctalia msg panel-toggle dunarand/bookmarks:panel
|
||||
```
|
||||
|
||||
2. Open the bookmarks panel in search mode (immediately puts you into search mode) so that you can
|
||||
use your bookmarks panel as a launcher:
|
||||
|
||||
```sh
|
||||
noctalia msg panel-toggle dunarand/bookmarks:panel search
|
||||
```
|
||||
|
After Width: | Height: | Size: 260 KiB |
|
After Width: | Height: | Size: 297 KiB |
|
After Width: | Height: | Size: 272 KiB |
|
After Width: | Height: | Size: 291 KiB |
|
After Width: | Height: | Size: 298 KiB |
|
After Width: | Height: | Size: 277 KiB |
@@ -0,0 +1,30 @@
|
||||
local PANEL_ID = "dunarand/bookmarks:panel"
|
||||
|
||||
local open = false
|
||||
|
||||
local function render()
|
||||
barWidget.setGlyph(noctalia.getConfig("glyph"))
|
||||
if open then
|
||||
barWidget.setGlyphColor("primary")
|
||||
barWidget.setColor("primary")
|
||||
else
|
||||
barWidget.setGlyphColor("on_surface")
|
||||
barWidget.setColor("on_surface")
|
||||
end
|
||||
|
||||
barWidget.setTooltip(noctalia.getConfig("tooltip"))
|
||||
barWidget.setText(noctalia.getConfig("text"))
|
||||
end
|
||||
|
||||
noctalia.state.watch("bookmarks_open", function(value)
|
||||
open = value == true
|
||||
render()
|
||||
end)
|
||||
|
||||
function update()
|
||||
render()
|
||||
end
|
||||
|
||||
function onClick()
|
||||
noctalia.togglePanel(PANEL_ID)
|
||||
end
|
||||
@@ -0,0 +1,60 @@
|
||||
id = "dunarand/bookmarks"
|
||||
name = "Bookmarks"
|
||||
version = "1.2.1"
|
||||
plugin_api = 13
|
||||
author = "dunarand"
|
||||
license = "MIT"
|
||||
icon = "bookmark"
|
||||
description = "A user-defined list of bookmarks. Each item has a label, a glyph, and a shell command."
|
||||
tags = ["launcher", "panel", "productivity", "utility"]
|
||||
dependencies = ["nohup"]
|
||||
|
||||
[[setting]]
|
||||
key = "data_path"
|
||||
type = "file"
|
||||
label_key = "settings.data_path.label"
|
||||
description_key = "settings.data_path.description"
|
||||
default = ""
|
||||
extensions = [".json"]
|
||||
|
||||
[[setting]]
|
||||
key = "show_info_button"
|
||||
type = "bool"
|
||||
label_key = "settings.show_info_button.label"
|
||||
description_key = "settings.show_info_button.description"
|
||||
default = true
|
||||
|
||||
[[widget]]
|
||||
id = "bar"
|
||||
entry = "bar.luau"
|
||||
|
||||
[[widget.setting]]
|
||||
key = "glyph"
|
||||
type = "glyph"
|
||||
label_key = "settings.glyph.label"
|
||||
description_key = "settings.glyph.description"
|
||||
default = "bookmark"
|
||||
|
||||
[[widget.setting]]
|
||||
key = "tooltip"
|
||||
type = "string"
|
||||
label_key = "settings.tooltip.label"
|
||||
description_key = "settings.tooltip.description"
|
||||
default = "Bookmarks"
|
||||
|
||||
[[widget.setting]]
|
||||
key = "text"
|
||||
type = "string"
|
||||
label_key = "settings.text.label"
|
||||
description_key = "settings.text.description"
|
||||
default = "Bookmarks"
|
||||
|
||||
[[panel]]
|
||||
id = "panel"
|
||||
entry = "panel.luau"
|
||||
width = 380
|
||||
height = 470
|
||||
placement = "attached"
|
||||
position = "auto"
|
||||
open_near_click = true
|
||||
capture_keys = ["ctrl+n", "ctrl+p", "up", "down", "Return", "ctrl+s"]
|
||||
|
After Width: | Height: | Size: 57 KiB |
@@ -0,0 +1,66 @@
|
||||
{
|
||||
"title": "Bookmarks",
|
||||
"new_bookmark": "New Bookmark",
|
||||
"edit_bookmark": "Edit Bookmark",
|
||||
"no_bookmarks": "No bookmarks yet",
|
||||
"search_placeholder": "Search bookmarks...",
|
||||
"no_search_results": "No matching bookmarks",
|
||||
"new_folder": "New Folder",
|
||||
"delete_folder_button": "Delete folder",
|
||||
"edit_folder": "Edit Folder",
|
||||
"folder_name_field": "Folder name",
|
||||
"open_tooltip": "Open",
|
||||
"back_button": "Back",
|
||||
"edit_tooltip": "Edit",
|
||||
"delete_tooltip": "Delete",
|
||||
"drag_tooltip": "Drag to reorder, or onto a folder to file it inside",
|
||||
"drop_out_of_folder": "Drop here to move back to the main panel",
|
||||
"show_controls_tooltip": "Show reorder/edit/delete controls",
|
||||
"hide_controls_tooltip": "Hide reorder/edit/delete controls",
|
||||
"cancel_button": "Cancel",
|
||||
"save_button": "Save",
|
||||
"glyph_field": "Glyph name (e.g. bookmark)",
|
||||
"label_field": "Label",
|
||||
"cmd_field": "Shell command",
|
||||
"description_field": "Description (optional)",
|
||||
"info_cmd_line": "Command: {cmd}",
|
||||
"info_description_line": "Description: {description}",
|
||||
"run_in_background_field": "Run in background",
|
||||
"run_in_terminal_field": "Run in terminal",
|
||||
"err_read_failed": "Failed to read bookmarks: {error}",
|
||||
"err_corrupt": "Bookmarks file is corrupt: {error}",
|
||||
"err_no_data_dir": "No data directory available",
|
||||
"err_reorder_failed": "Failed to reorder: {error}",
|
||||
"err_no_command": "This bookmark has no command",
|
||||
"err_exit_code": "\"{label}\" exited with code {code}",
|
||||
"err_launch_failed": "Failed to launch \"{label}\"",
|
||||
"err_delete_failed": "Failed to delete: {error}",
|
||||
"err_save_failed": "Failed to save: {error}",
|
||||
"err_label_required": "Label is required",
|
||||
"err_label_cmd_required": "Label and command are required",
|
||||
"folder_deleted": "Deleted folder \"{label}\" and its contents",
|
||||
"entry_updated": "Updated \"{label}\"",
|
||||
"entry_saved": "Saved \"{label}\"",
|
||||
"settings": {
|
||||
"glyph": {
|
||||
"label": "Glyph",
|
||||
"description": "Bar widget's glyph"
|
||||
},
|
||||
"tooltip": {
|
||||
"label": "Tooltip",
|
||||
"description": "Bar widget's tooltip"
|
||||
},
|
||||
"text": {
|
||||
"label": "Text",
|
||||
"description": "Bar widget's label. Leave empty to display only the glyph."
|
||||
},
|
||||
"data_path": {
|
||||
"label": "Data file",
|
||||
"description": "Where data.json is stored. Leave empty to use the default plugin data directory."
|
||||
},
|
||||
"show_info_button": {
|
||||
"label": "Show info button",
|
||||
"description": "Show a \"?\" button on bookmarks (not folders) to view their description and command on hover."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
{
|
||||
"title": "Yer İmleri",
|
||||
"new_bookmark": "Yeni Yer İmi",
|
||||
"edit_bookmark": "Yer İmini Düzenle",
|
||||
"no_bookmarks": "Henüz bir yer imi yok",
|
||||
"new_folder": "Yeni Klasör",
|
||||
"search_placeholder": "Yer imlerinde ara...",
|
||||
"no_search_results": "Eşleşen yer imi yok",
|
||||
"delete_folder_button": "Klasörü Sil",
|
||||
"edit_folder": "Klasörü Düzenle",
|
||||
"folder_name_field": "Klasör ismi",
|
||||
"open_tooltip": "Aç",
|
||||
"back_button": "Geri",
|
||||
"edit_tooltip": "Düzenle",
|
||||
"delete_tooltip": "Sil",
|
||||
"drag_tooltip": "Sıralamak için sürükle veya bir klasörün içine bırak",
|
||||
"drop_out_of_folder": "Ana panele göndermek için buraya bırak",
|
||||
"show_controls_tooltip": "Sıralama/düzenleme/silme kontrollerini göster",
|
||||
"hide_controls_tooltip": "Sıralama/düzenleme/silme kontrollerini gizle",
|
||||
"cancel_button": "İptal",
|
||||
"save_button": "Kaydet",
|
||||
"glyph_field": "Sembol (ör. bookmark)",
|
||||
"label_field": "İsim etiketi",
|
||||
"cmd_field": "Shell Komutu",
|
||||
"description_field": "Açıklama (İsteğe bağlı)",
|
||||
"info_cmd_line": "Komut: {cmd}",
|
||||
"info_description_line": "Açıklama: {description}",
|
||||
"run_in_background_field": "Arka planda çalıştır",
|
||||
"run_in_terminal_field": "Konsolda çalıştır",
|
||||
"err_read_failed": "Yer imleri okunamadı: {error}",
|
||||
"err_corrupt": "Bozuk yer imleri dosyası: {error}",
|
||||
"err_no_data_dir": "Eksik veri dizgini",
|
||||
"err_reorder_failed": "Sıralama Yapılamadı: {error}",
|
||||
"err_no_command": "Bu yer iminin bir komutu yok",
|
||||
"err_exit_code": "\"{label}\" {code} ile sonlandı",
|
||||
"err_launch_failed": "\"{label}\" açılamadı",
|
||||
"err_delete_failed": "Silinemedi: {error}",
|
||||
"err_save_failed": "Kaydedilemedi: {error}",
|
||||
"err_label_required": "Etiket gerekli",
|
||||
"err_label_cmd_required": "Etiket ve komut alanları gerekli",
|
||||
"folder_deleted": "\"{label}\" klasörü ve içeriği silindi",
|
||||
"entry_updated": "\"{label}\" güncellendi",
|
||||
"entry_saved": "\"{label}\" kaydedildi",
|
||||
"settings": {
|
||||
"glyph": {
|
||||
"label": "Sembol",
|
||||
"description": "Bar aracının sembolü (ör. bookmark)"
|
||||
},
|
||||
"tooltip": {
|
||||
"label": "İsim etiketi",
|
||||
"description": "Bar aracının isim etiketi"
|
||||
},
|
||||
"text": {
|
||||
"label": "Yazı",
|
||||
"description": "Bar aracının etiketi. Barda sadece sembolün görünmesi için boş bırakın."
|
||||
},
|
||||
"data_path": {
|
||||
"label": "Veri dosyası",
|
||||
"description": "data.json dosyasının saklandığı konum. Varsayılan eklenti veri konumunu kullanmak için boş bırakın."
|
||||
},
|
||||
"show_info_button": {
|
||||
"label": "Bilgi butonunu göster",
|
||||
"description": "Yer imlerinde (klasörlerde değil) üzerine gelindiğinde açıklamalarını ve komutlarını görüntülemek için bir \"?\" düğmesi göster."
|
||||
}
|
||||
}
|
||||
}
|
||||