LukeSmithxyz / voidrice

My dotfiles (deployed by LARBS)
GNU General Public License v3.0
4.29k stars 1.21k forks source link

Extremely Improved Bookmarks (Search + Strip URL + More) #1312

Open emrakyz opened 1 year ago

emrakyz commented 1 year ago

The inspiration: (Luke Smith's Video): "Bookmarking for Unix Chads" Instructions & Justifications & Very Detailed Explanation for Everything can be found below.

Short Summary

Video Presentation Under a Minute (Notification Support Added Later):

https://user-images.githubusercontent.com/89175311/233964479-b82ac239-1c8f-4cc7-8d04-2e5dcaa23585.mp4

Execution Time: Instant Required Programs: dash | sed | echo | grep | dmenu | notification daemon | browser | xclip (or "wl-paste --primary" on Wayland)

Instructions

These directories should exist: ~/.local/share/

  1. Open a browser and highlight (xclip -o users) a website's URL (starting with "http") such as "https://github.com"
  2. Run the script with a shortcut you created for the window manager that is used.
  3. Write "@@" inside the dmenu prompt then enter (@@ can be changed of course). This opens the "Action Menu".
  4. Select "Add" option then enter.
  5. The bookmark will be added inside the bookmarks menu. It can be edited or deleted later from the action menu that can be opened with "@@".
  6. If a website that has the word "search" in it is added inside bookmarks such as a SearxNG instance "paulgo.io/search?q=" , its search function can be used. When selected, it will offer for a new prompt for the desired keywords.

Justification

  1. The script uses jq for parsing and modifying JSON data, which is a lightweight and powerful command-line JSON processor. This choice allows for easy manipulation of the JSON file that stores bookmarks.

The script now uses tools like sed, grep, cut. The logic is also simplified.

  1. The script checks for an existing URLQUERY_FILE and initializes it if it doesn't exist or is empty. This ensures that the file is always in a valid state for the script to operate.

  2. The script supports searching within specific websites by checking if the word "search" is in the URL (More words can be added). This feature provides a convenient way to search within bookmarked websites directly from the script.

  3. The use of the dash shell (#!/bin/sh) as the interpreter provides a lightweight and fast shell environment for the script, improving performance. Since the script is efficient enough, this performance difference is not huge, so it can also be used with bash with some modifications.

Detailed Explanation

FUNCTIONS:

URLQUERY_FILE: The file where bookmarks are saved. CLIPBOARD: Command to fetch content from the clipboard. ACTION_MENU: A unique string that triggers the action menu when selected. DMENU(): This is a function wrapper around the dmenu command to simplify its usage in the script. error_notify(): Displays an error notification and exits the script if an error occurs. ensure_file_exists(): Checks if the bookmark file exists. If it doesn’t, it creates it. get_selection(): Retrieves a selection from the bookmark file using dmenu. update_file(): A utility function to modify the bookmark file. is_valid_url(): Validates if string in clipboard is a valid URL. add_bookmark(): Adds a new bookmark to the file. delete_bookmark(): Deletes a selected bookmark from the file. edit_name() and edit_url(): Functions for editing the name or URL of an existing bookmark. edit_bookmark(): Allows the user to choose to edit either the name or the URL of a bookmark. open_bookmark(): Opens a selected bookmark in the default web browser. If the bookmarked URL has search, it prompts you for an extra query.

FLOW:

TheYellowArchitect commented 11 months ago

The idea got me hyped enough to try it. I would recommend renaming the script to sth like urlbookmark so as to make it explicit to the user (without even opening it) that it's seperated from the zsh bookmarks (write ;bd on the terminal to access some of them)

It requires dash to run (so if included, I assume LARBS must include dash), so a minimum of having a comment under the first line: #sudo pacman -Syuu dash to not get 'bad file' error or otherwise ifinstalled dash || { echo >&2 "'dash' is required but it's not installed."; exit 1; }

As for usability, I suggest somehow not requiring the Enter keypress after typing @@, the 2nd @ should trigger the 'Add/Delete/Edit'.

The main problem is that the script is currently broken. Upon adding a bookmark, it doesn't prompt for 'Name' dmenu at all. This is true when running it from .local/bin and also from dwm shortcut { MODKEY|ShiftMask, XK_x, spawn, {.v = (const char*[]){ "urlbookmark", NULL } } },

So when I copy a url at clipboard, then press @@ then Enter, dmenu just vanishes. No error message, no notification, its like it just exits normally.

My mind got to the urlquery file, which indeed is not written with anything when you add something to it. I gave it chmod 777. On adding a URL, it still silently exits without asking for the 'Name' prompt, and nothing being written to urlquery.

I don't know what the format of urlquery must be, but I tried appending this: "Arch https://archlinux.org/packages/" and then executed the command. It did show the url but on pressing 'Enter' it didn't pop the browser or anything. It opened a new tab on my browser which points to "file:/// /home/$USERNAME"

Even if it all worked, if on the above packages url, you cannot search directly (as displayed in the video above with paulgo searx engine), I suggest against it imo. Because even if it worked, there is also the problem with local URL bookmarks which I assume will always be desynced to the browser's bookmarks (nothing this script can do against that, browsers are the bane of modern computers)

emrakyz commented 11 months ago

@TheYellowArchitect

Thanks for trying. Yes it requires a POSIX shell. Dash is very lightweight and the fastest shell so I chose Dash for most of my scripts. It's also portable.

The file format (urlquery) is very simple. Your format is wrong. We use "=" as a separator: SearXNG=https://searx.tiekoetter.com/search?q= Wiki=https://www.wikiwand.com/en/ Economist=https://www.economist.com Reuters=https://www.reuters.com

I have been using this for a very long time I don't think it's broken. You don't have to change the file yourself.

FYI: xclip -o works with selected (highlighted) text; not copied. I am on Wayland and use a different command but it should work the same.

Here below is a newer showcase. I can help you fix it if you can't fix it. By the way your last sentence is technically not correct. I have been using this script for a very long time and search function on all sites work. If a website changes its URL, you can change the URL too. It's not something that frequently happens.

showcase.webm

emrakyz commented 11 months ago

Here is your example site. Arch Linux website use this format. So you will highlight the link below. You don't need to copy. You need to highlight it (I don't do it on the video because I use another command that works with copying that is wl-copy. x-clip also has an equivalent but in that video Luke uses xclip -o so I kept the same):

https://archlinux.org/packages/?sort=&q=

So we will use this format in our file (the script does this automatically): Arch Packages=https://archlinux.org/packages/?sort=&q=

Let me walk you through it with a video. I will back-up all of my current files and delete everything then start from 0. I just add another keyword for this site because it doesn't have search in it. Then I add it into my bookmarks and try to search in it.

showcase_arch.webm

emrakyz commented 11 months ago

I added some QOL and non-important improvements.

These directories should exist:~/.local/share/

Remove the file beforehand just in case rm -fv ~/.local/share/urlquery

1- Highlight this link by choosing every character of it with your mouse: https://github.com

2- Run the script with a shortcut you created for the window manager that is used. On Luke's DWM setup you will have a line like this. I use grave key you can use anything you want: { MODKEY, XK_grave, spawn, {.v = (const char*[]){ "bookmark_manager.sh", NULL } } },

When you run this script. The script automatically creates the urlquery file.

3- Then you need to prompt "@@" then enter; action menu opens. Select "Add" and it will prompt you asking a name. Enter "GitHub" for example and enter. When you do that, the "urlquery" file will have this line exactly: GitHub=https://github.com

Now you can open your bookmark menu and select GitHub. You can see the similar showcases on newer videos I posted after your message.

So the next time you open the bookmark script, the script will use the program "cut" with the "=" as a delimeter and will give you -f1 on Dmenu which is GitHub and -f2 to the browser which is https://github.com

Basically: cut -d= -f1 means GitHub cut -d= -f2 means https://github.com

URL=$(grep "^$SELECTION=" "$URLQUERY_FILE" | cut -d= -f2-)

This line fills the URL variable. We search for our selection inside the file, then we find it. Then we will cut the second field using "=" as the delimeter which is the actual URL.

Then we have a line like this: $BROWSER "$URL"

So in this repo, it means entering this command on the terminal: librewolf https://github.com

TheYellowArchitect commented 11 months ago

Thank you very much for the detailed reply. Not even in stack overflow would I find such an explanation, reminds me of forums :)

I am especially surprised to see it working with custom searches (arch packages demonstration). That's extremely useful as I can query into whatever database from my command line, and for this reason alone, if fixed, I would suggest it gets merged. Though I would still suggest a name like urlbookmark or urlbookmarkmanager because LARBS already has bookmarks via zsh (press ;bf or ;bd in the terminal to see bookmarks. Basically you can map ;XX to whatever path, and its usable by st, lf, vim and I assume more) and its unintuitive to have 2 bookmark managers. Obviously, having both bookmark managers is better than either, so just a rename to specify its for URLs ftw

==================

Because even if it worked, there is also the problem with local URL bookmarks which I assume will always be desynced to the browser's bookmarks (nothing this script can do against that, browsers are the bane of modern computers)

By the way your last sentence is technically not correct. I have been using this script for a very long time and search function on all sites work. If a website changes its URL, you can change the URL too. It's not something that frequently happens.

There is a misunderstanding. Assuming this script works as showcased, these URL bookmarks are local, and do not sync with the browser's bookmarks. If you highlight a text in the browser, then click the star icon to the right, you add a bookmark to the browser. But this newly bookmarked URL is not bookmarked on the local bookmark manager. So if you bookmark a URL with your bookmark manager, it does not display on the browser as a bookmarked URL (as in, being clickable, icon and all). And vice versa if you bookmark a URL in the browser, it doesn't bookmark in the local bookmark manager.

Now in a better world where browsers at least had local config files (in a txt or json or xml or whatever), it would be quite easy to sync them, where the browser writing on its config bookmark file would also write it in urlquery (or even better, having a single urlquery file for both browser and this script)

Since that is not possible because of the anti-user nature of browsers, the best alternative is to open the browser, export bookmarks as html, then manually paste them into urlquery (or write a script which does this) then use this pretty much.

Regardless of the above problem, this local bookmark manager is still superior to the browser's bookmarks, for 2 main reasons:

  1. The browser can hold up to 8 bookmarks in a line, and every user has very many bookmarks, so a user needs to click and search with the mouse. With this, you just type, it's faster.
  2. Search engine while searching for bookmark is an amazing feature - you basically query into any database without having to open the browser and typing a url or clicking your search engine.

For the above reasons, I would definitely use this over the browser's bookmarks, even though they don't sync.

========

I used the script of the latest commit but I am still having issues making it work. I attach both use-cases. First being trying to add a script, and second being having added a url to urlquery, pressing enter to open the search functionality. On the "line 87 error" it was me putting a bonus | character on that packages addition you added, I fixed it right before recording

I assume it has something to do with dmenu? On the terminal, I input alias | grep 'dmenu' and nothing comes up, so it's not an alias conflict (I have same aliasrc as this repo's https://github.com/LukeSmithxyz/voidrice/blob/master/.config/shell/aliasrc )

https://github.com/LukeSmithxyz/voidrice/assets/25630803/65480a46-ec44-4ffc-85c8-33e86498745c

https://github.com/LukeSmithxyz/voidrice/assets/25630803/f985ccc7-ae09-4402-ba2e-b0b54e451984

emrakyz commented 11 months ago

@TheYellowArchitect

Oh of course. The browser bookmarks would be desynced. I misunderstood that. I haven't used in-browser bookmarks for years since I started using shell scripts.

I guess I realized the problem. Since I use Rofi, it can be a little bit different than Dmenu. I guess dmenu can't show 0 lined entries. Can you change -l 0 with another number such as 2. That's why you probably don't see the newer dmenu prompt.

For example you can do this to change all 0 line entries with 2 just for trying; and try running the script again later: sed -i 's/DMENU 0/DMENU 2/g' bookmark_manager.sh

Additionally FYI: Brave browser has a problem. I mean not a problem but a difference. It adds / at the end of URLs if you copy directly from the address bar on Brave (or any chromium browsers). Firefox and Librewolf don't do this.

For example: https://www.github.com becomes https://www.github.com/ so it can break some URLs especially the ones with a search function. I could remove that in the script but then some websites would be broken because some sites use a search with a forward slash such as: https://www.wikiwand.com/en/{yourkeyword} -- so I can't remove that myself.

This is an easy fix :) You can work this out.

TheYellowArchitect commented 11 months ago

I guess I realized the problem. Since I use Rofi, it can be a little bit different than Dmenu. I guess dmenu can't show 0 lined entries. Can you change -l 0 with another number such as 2. That's why you probably don't see the newer dmenu prompt.

For example you can do this to change all 0 line entries with 2 just for trying; and try running the script again later: sed -i 's/DMENU 0/DMENU 2/g' bookmark_manager.sh

I run the above sed -i 's/DMENU 0/DMENU 2/g' .local/bin/urlbookmark and then ran it. Also went manually on that file and replaced dmenu -l $1 with dmenu -l 5 and still the same result. Specifically, with latest commit (no sed changes^) if I press enter on Arch linux url, it opens browser on that url (instead of then having dmenu query)

Also pressing edit, then Arch, I have 2 prompts (Edit/Delete), but pressing enter on either doesn't show anything afterwards. I will try to debug it, will post anything new

Additionally FYI: Brave browser has a problem. I mean not a problem but a difference. It adds / at the end of URLs if you copy directly from the address bar on Brave (or any chromium browsers). Firefox and Librewolf don't do this.

For example: https://www.github.com/ becomes https://www.github.com/ so it can broke some URLs especially the ones with a search function. I could remove that in the script but then some websites would be broken because some sites use a search with a forward slash such as: https://www.wikiwand.com/en/{yourkeyword} -- so I can't remove that myself.

This is an easy fix :) You can work this out.

I use librefox atm, but you are right, even if I changed browser, its just a character swap. Regardless, thanks for notifying me for this, because if I didn't use librefox it would bug and I wouldn't understand why

TheYellowArchitect commented 11 months ago

In this function, when I am prompted to Add, and press Enter, it prints "test3" on terminal, but it doesn't continue from there (e.g. continuing on dmenu) and also doesn't show "test4"


add_bookmark() {
    URL=$($CLIPBOARD) ;
    is_valid_url "$URL" || error_notify "The clipboard content is not a valid URL." ;
    grep -q "=$URL$" "$URLQUERY_FILE" && notify-send "The URL is already in the list." && return ;
    echo "test3";
    dmenu -i -l 2 -p "Name"
    #NAME=$(DMENU 0 "Name")
    echo "test4";
    [ -n "$NAME" ] && echo "${NAME}=${URL}" >> "$URLQUERY_FILE" && notify-send "'$NAME' is bookmarked."
    echo "test5";
}

Specifically, I found the problem. If I run this code dmenu -i -l 2 -p "Name" on the terminal, it shows nothing and has the same behaviour as your script's. That is because dmenu doesn't run properly without any pipe/input into it. So for example, echo "" | dmenu -i -l 2 -p "Name" works.

I am currently looking into how to implement this cleanly everywhere

emrakyz commented 11 months ago

Thanks for detailed analysis. I can fix this in batch form and inform you again. The problem is indeed how dmenu works compared to Rofi.

TheYellowArchitect commented 11 months ago

I fixed it here (remove the debug messages :sweat_smile: ) https://github.com/LukeSmithxyz/voidrice/pull/1376/commits/eea4bc19f4a5bb1deca3117d66e192a81111c01f

I tried to branch on your fork, but since me and you both have /voidrice git couldn't differentiate (e.g. have 2 repositories with different names) I guess it's possible but anyway, the above is the fix which works locally. It's not perfect though because dmenu with 0 inputs starts with "0" character to the left, and also on the right has an empty highlighted box option until you type your first character. I assume there must be options to fix these minor aesthetic issues.

Regardless, thank you for creating this useful script and for the assistance. The script works as expected now. I suggest replacing the above parts of the code and it should work for everyone. As for author status, don't include me, it was a simple fix

emrakyz commented 11 months ago

@TheYellowArchitect

Can you test the latest version again? I will also change the name.

By the way there is a patch for dmenu to make it centered if you want. Center Patch for Dmenu

TheYellowArchitect commented 11 months ago

That works too. I confirmed it just now. It has the same minor aesthetics problem as mentioned however. That said, please add the packages part next to search and wiki like you did in your showcase, its quite useful for software development in general (I remember back when colleagues would browse java packages xaxaxa)

Ah also, I heavily suggest changing the name to urlbookmark or urlbookmarkmanager or anything containing url, so a random LARBS user won't get confused on bookmarks since these are unrelated to ;bd and ;bf

emrakyz commented 11 months ago

I renamed it. For aesthetics, you can search dmenu patches, just like the one I shared for Centered menu.

Offtopic: @TheYellowArchitect You must be greek with "xaxaxa" laugh? In Turkey, random characters are used for that purpose: "dfglksdfk" known as keysmashing :)

The case conditions for searching should be optional though? What do you think? I think a user should add any keyword there according to their usecase just like you adding "packages". Wiki and search would be intuitive for users that's why I used them.

TheYellowArchitect commented 11 months ago

I renamed it.

Nice, the name is great as it distincts from local bookmarks

For aesthetics, you can search dmenu patches, just like the one I shared for Centered menu.

Thank you for sharing me that list of patches. The aesthetics problem is minor anyway, it only lasts while you don't type any character, and when there are no choices, so it's not worth a patch, this script is worth a visual inconvenience which I won't even notice in practice

Offtopic: @TheYellowArchitect You must be greek with "xaxaxa" laugh? In Turkey, random characters are used for that purpose: "dfglksdfk" known as keysmashing :)

Unexpected observation but accurate xaxaxa Also thank you for explaining that keysmashing part, it's fascinating how a universal action (laughter) expresses so differently into keyboard characters. For example I was playing with russians years ago and they used "))))))))))" and it took me days to understand it's their equivalent of laughter, pretty cool

The case conditions for searching should be optional though? What do you think? I think a user should add any keyword there according to their usecase just like you adding "packages". Wiki and search would be intuitive for users that's why I used them.

I understand that some keywords should be optional, but I cannot think of a url containing packages and not having searchable packages, hence my suggestion to include it, because i remember having seen it before with java, and I assume one can see it with NuGet packages (C#) and javascript

Anyway, as long you place a comment above that line on what triggers the search, it's great imo. My use-case is covered personally, so idk about what URLs others save with the keyword packages inside, a comment above is good enough

emrakyz commented 11 months ago

@TheYellowArchitect

Open to more suggestions :)

FYI you can also use Arch Wiki or Gentoo Wiki with their search URLs: Arch Wiki=https://wiki.archlinux.org/?search= Gentoo Wiki=https://wiki.gentoo.org/?search=

TheYellowArchitect commented 11 months ago

Aside of the above, literally nothing can be suggested at this moment, you have added so much in a single day, that I would feel greedy if I requested anything else (since it would be optional, this script works great as it is atm)