blog.lazkani.io/content/posts/bookmark-with-org-capture.md

134 lines
7.2 KiB
Markdown

+++
title = "Bookmark with Org-capture"
author = ["Elia el Lazkani"]
date = 2020-09-17
lastmod = 2021-05-27
tags = ["org-mode", "emacs", "org-capture", "org-web-tools", "org-cliplink"]
categories = ["text-editors"]
draft = false
+++
I was reading, and watching, [Mike Zamansky](https://cestlaz.github.io/about/)'s blog post [series](https://cestlaz.github.io/stories/emacs/) about _org-capture_ and how he manages his bookmarks. His blog and video series are a big recommendation from me, he is teaching me tons every time I watch his videos. His inspirational videos were what made me dig down on how I could do what he's doing but... my way...
I stumbled across [this](https://dewaka.com/blog/2020/04/08/bookmarking-with-org-mode/) blog post that describes the process of using `org-cliplink` to insert the _title_ of the post into an _org-mode_ link. Basically, what I wanted to do is provide a link and get an _org-mode_ link. Sounds simple enough. Let's dig in.
<!--more-->
## Org Capture Templates {#org-capture-templates}
I will assume that you went through Mike's [part 1](https://cestlaz.github.io/posts/using-emacs-23-capture-1/) and [part 2](https://cestlaz.github.io/posts/using-emacs-24-capture-2/) posts to understand what `org-capture-templates` are and how they work. I essentially learned it from him and I do not think I can do a better job than a teacher.
Now that we understand where we need to start from, let's explain the situation. We need to find a way to call `org-capture` and provide it with a _template_. This _template_ will need to take a _url_ and add an _org-mode_ _url_ in our bookmarks. It will look something like the following.
```emacs-lisp
(setq org-capture-templates
'(("b" "Bookmark (Clipboard)" entry (file+headline "~/path/to/bookmarks.org" "Bookmarks")
"** %(some-function-here-to-call)\n:PROPERTIES:\n:TIMESTAMP: %t\n:END:%?\n" :empty-lines 1 :prepend t)))
```
I formatted it a bit so it would have some properties. I simply used the `%t` to put the _timestamp_ of when I took the bookmark. I used the `%?` to drop me at the end for editing. Then `some-function-here-to-call` a function to call to generate our _bookmark section_ with a title.
The blog post I eluded to earlier solved it by using [org-cliplink](https://github.com/rexim/org-cliplink). While `org-cliplink` is great for getting _titles_ and manipulating them, I don't really need that functionality. I can do it manually. Sometimes, though, I would like to copy a page... Maybe if there is a project that _could_ attempt to do someth... Got it... [org-web-tools](https://github.com/alphapapa/org-web-tools).
### Configuring _org-capture_ with _org-web-tools_ {#configuring-org-capture-with-org-web-tools}
You would assume that you would be able to just pop `(org-web-tools-insert-link-for-url)` in the previous block and you're all done. But uhhh....
```text
Wrong number of arguments: (1 . 1), 0
```
No dice. What would seem to be the problem ?
We look at the definition and we find this.
```emacs-lisp
(defun org-web-tools-insert-link-for-url (url)
"Insert Org link to URL using title of HTML page at URL.
If URL is not given, look for first URL in `kill-ring'."
(interactive (list (org-web-tools--get-first-url)))
(insert (org-web-tools--org-link-for-url url)))
```
I don't know why, exactly, it doesn't work by calling it straight away because I do not know _emacs-lisp_ at all. If you do, let me know. I suspect it has something to do with `(interactive)` and the list provided to it as arguments.
Anyway, I can see it is using `org-web-tools--org-link-for-url`, which the documentation suggests does the same thing as `org-web-tools-insert-link-for-url`, but is not exposed with `(interactive)`. Okay, we have bits and pieces of the puzzle. Let's put it together.
First, we create the function.
```emacs-lisp
(defun org-web-tools-insert-link-for-clipboard-url ()
"Extend =org-web-tools-inster-link-for-url= to take URL from clipboard or kill-ring"
(interactive)
(org-web-tools--org-link-for-url (org-web-tools--get-first-url)))
```
Then, we set our `org-capture-templates` variable to the list of our _only_ item.
```emacs-lisp
(setq org-capture-templates
'(("b" "Bookmark (Clipboard)" entry (file+headline "~/path/to/bookmarks.org" "Bookmarks")
"** %(org-web-tools-insert-link-for-clipboard-url)\n:PROPERTIES:\n:TIMESTAMP: %t\n:END:%?\n" :empty-lines 1 :prepend t)))
```
Now if we copy a link into the _clipboard_ and then call `org-capture` with the option `b`, we get prompted to edit the following before adding it to our _bookmarks_.
```org
** [[https://cestlaz.github.io/stories/emacs/][Using Emacs Series - C'est la Z]]
:PROPERTIES:
:TIMESTAMP: <2020-09-17 do>
:END:
```
Works like a charm.
### Custom URL {#custom-url}
What if we need to modify the url in some way before providing it. I have that use case. All I needed to do is create a function that takes _input_ from the user and provide it to `org-web-tools--org-link-for-url`. How hard can that be ?! uhoh! I said the curse phrase didn't I ?
```emacs-lisp
(defun org-web-tools-insert-link-for-given-url ()
"Extend =org-web-tools-inster-link-for-url= to take a user given URL"
(interactive)
(let ((url (read-string "Link: ")))
(org-web-tools--org-link-for-url url)))
```
We can, then, hook the whole thing up to our `org-capture-templates` and we get.
```emacs-lisp
(setq org-capture-templates
'(("b" "Bookmark (Clipboard)" entry (file+headline "~/path/to/bookmarks.org" "Bookmarks")
"** %(org-web-tools-insert-link-for-clipboard-url)\n:PROPERTIES:\n:TIMESTAMP: %t\n:END:%?\n" :empty-lines 1 :prepend t)
("B" "Bookmark (Paste)" entry (file+headline "~/path/to/bookmarks.org" "Bookmarks")
"** %(org-web-tools-insert-link-for-given-url)\n:PROPERTIES:\n:TIMESTAMP: %t\n:END:%?\n" :empty-lines 1 :prepend t)))
```
if we use the `B`, this time, it will prompt us for input.
### Configure _org-capture_ with _org-cliplink_ {#configure-org-capture-with-org-cliplink}
Recently, this setup has started to fail and I got contacted by a friend pointing me to my own blog post. So I decided to fix it.
My old setup used to use _org-cliplink_ but I moved away from it for some reason. I cannot remember why. It is time to move back to it.
In this setup, I got rid of the _custom function_ to get the link manually. I believe that is why I moved but I cannot be certain.
Anyway, nothing worked so why keep something not working right ?
All this means is that we only need to setup our `org-capture-templates`. We can do so as follows.
```emacs-lisp
(setq org-capture-templates
'(("b" "Bookmark (Clipboard)" entry (file+headline "~/path/to/bookmarks.org" "Bookmarks")
"** %(org-cliplink)\n:PROPERTIES:\n:TIMESTAMP: %t\n:END:%?\n" :empty-lines 1 :prepend t)
```
Now, you should have a working setup... `org-cliplink` willing !
## Conclusion {#conclusion}
I thought this was going to be harder to pull off but, alas, it was simple, even for someone who doesn't know _emacs-lisp_, to figure out. I hope I'd get more familiar with _emacs-lisp_ with time and be able to do more. Until next time, I recommend you hook `org-capture` into your workflow. Make sure it fits your work style, otherwise you will not use it, and make your path a more productive one.