Clipboard snippets in your Inbox (for later review), even when Obsidian closed!
This is for Linux but may work elsewhere. It can be used system-wide, even when you don’t even use Obsidian.
Important bugfix: Please upgrade to v1.5+ to prevent errors when using spaces in your file paths!
Inspiration!
Talking with @koala on the Discord today, he gave me an inspiration. How about having something that …
- would allow copying from any program, web page, code editor, terminal window, etc.
- then add the text, HTML, or image into a “Clipboard” note in your vault’s Inbox,
- store copied images in an assets folder (subfolder in Inbox, or even the Inbox folder itself,
- and even use Pandoc (if installed) to convert HTML to Markdown on the fly, and store the Markdown in your “Clipboard” note?
-
More secret sauce (v1.1): If desired,
clipit
can now also create.pdf
,.odt
,.docx
clippings from HTML sources. These will be stored in the assets folder and linked in the Clipboard file. Read the comments in the source. - Pandoc experts can now really fine-tune the output in v1.3: Extensions and Options supported.
- V1.5 shows how to make a Daily Clipboard, much like Daily Notes.
- V1.6 handles some Pandoc edge cases, and also reports Pandoc errors to the CLIPFILE so they don’t go unnoticed.
- V1.7 now adds a YAML frontmatter header!
Solution!
Well, we have Linux, we can do anything! (Or maybe MacOS or the Windows WSL, where it might work—no guarantees.)
So I created a bash
script, clipit
, which can be stored in your ~/bin
, ~/.local/bin
or /usr/local/bin
folder, chmod +x
’ed and used.
You should modify the CLIPFILE
and CLIPASSETS
variables to suit your needs. Other options allow for a different date format, image file name, and Markdown dialect.
Almost all Linux systems (with a Desktop Environment) have a means to set keyboard shortcuts and associate applications with those. In my case, on Linux Mint 20.2, I used the Super+V key combo, since it’s kinda “Super Paste”, and Ctrl+V is usually the “paste” command.
(The “Super” key is labelled with either a “flying Windows” or “Tux penguin” on most keyboards.)
So now we’ve set that up, try copying something into the clipboard, and in a terminal try the command clipit
. This should work and create a new clipboard file within your vault.
If you get errors, especially Pandoc errors, read the explanations in the code! Most errors come from using an old Pandoc version or some settings that don’t play well together!
If that works, try out copying something and using the Super+V key combination, and it should make the next entry in your clipboard file. Easy, eh?
For the users of outliners and “heading link” people, each entry begins with a H2 header and the date, in ISO format.
Then follows the clipped text, converted HTML, or link to the downloaded image.
Each entry has a horizontal line ---
at the end, for easy visual separation.
Requirements
- Almost any Linux (maybe macOS) system having a Desktop Environment installed.
- X11 display server (sorry Wayland users!)
- A
bash
shell installed. -
xclip
must be installed (it often already is), otherwise use your package manager to install.- On Debian derivatives (i.e., Debian, Ubuntu, Linux Mint):
sudo apt install xclip
- On MacOS, using Homebrew:
brew install xclip
- On Debian derivatives (i.e., Debian, Ubuntu, Linux Mint):
- Pandoc should be installed and in the PATH, for HTML → Markdown conversion.
- If Pandoc complains about missing
rsvg-convert
, install that using your package manager, i.e., on Debian-type systems:sudo apt install librsvg2-bin
The CODE you’ve been waiting for!
#!/bin/bash
# clipit -- Quickly store clipboard from an X selection into the Obsidian Inbox, for later review.
# Brought to you by Matthias C. Hormann (aka Moonbase59), based on an idea by @koala/kometenstaub.
#
# Requirements:
# - X11 display server (sorry Wayland users!)
# - xclip must be installed (it often already is, otherwise use your package manager to install)
# - Pandoc should be installed and in the PATH, for HTML → Markdown conversion.
# - If Pandoc complains about missing "rsvg-convert", install that using your package manager,
# i.e. "sudo apt install librsvg2-bin" on Debian-type systems.
#
# IMPORTANT: Before building your perfect workflow, test this thoroughly using the "clipit" command
# on the command line, especially when using Pandoc! Pandoc has so many versions and different options,
# and you will only see the errors on the command line.
#
# Use with a keyboard shortcut (available in Linux under Settings → Keyboard → Keyboard Shortcuts)
# I’ve opted for SUPER+V, which is not normally used and this is a "super" paste ;-)
#
# Set up CLIPFILE to point to your desired Clipboard Markdown file.
# Each clipit invocation will generate a new, time-stamped entry.
#
# Set up CLIPASSETS (with a trailing /) to point to a folder where images should be stored.
# If the clipboard contains an image that can be saved as PNG, it will store a time-stamped
# "Pasted Image YYYYMMDDhhmmss.png" file in the CLIPASSETS folder, much like Obsidian does.
# An embed link to that image will be written into the CLIPFILE.
#
# v1.0 -- 2021-08-19
# - Initial release
# - Intentionally didn’t restrict xclip to _one_ clipboard, so it also works on console
# v1.1 -- 2021-08-19
# - Added option for other output formats (pdf, odt, docx), written to assets folder
# v1.2 -- 2021-08-20
# - Added XSELECTION option, to define the X11 selection to take
# v1.3 -- 2021-08-20
# - Added EXTENSIONS and OPTIONS for Pandoc, so the output can be fine-tuned.
# v1.4 -- 2021-08-20
# - Added good defaults and MUCH more comments. READ THEM.
# v1.5 -- 2021-08-21
# - Bugfix: CLIPFILE and CLIPASSETS paths with SPACES in them now work correctly.
# - Code optimizations to get rid of the many "echo" statements.
# - Added a comment on how to make a CLIPFILE PER DAY ("YYYY-MM-DD Clipboard.md").
# v1.6 -- 2021-08-20
# - Added Pandoc error reporting to CLIPFILE so setting problems don’t go unnoticed.
# - Bugfix: When copying from LibreOffice, a NUL byte gets added that confuses other programs.
# This now gets removed by clipit.
# - Code rework to handle edge cases for Pandoc output, i.e. "Font Name" with spaces.
# v1.7 -- 2021-08-26
# - Upon initial creation of a CLIPFILE, a YAML HEADER is now written.
# It has "date: YYYY-MM-DD" and user-settable "tags:"
# define me
me=`basename "$0"`
# --- USER CUSTOMIZATION: File and Assets Path ---
# This is the clipboard file (should point to a file within your vault’s Inbox)
# Use an absolute path here, and prefer $USER over $HOME, the latter isn’t always available.
# You CAN make a CLIPFILE PER DAY, using:
CLIPFILE="/home/$USER/Dokumente/Obsidian/Knowledgebase/-Inbox/$(date +"%F") Clipboard.md"
# If you just want ONE CLIPFILE, use this:
#CLIPFILE="/home/$USER/Dokumente/Obsidian/Knowledgebase/-Inbox/-Clipboard.md"
# The assets folder for images (must not necessarily be a subfolder of Inbox).
# Use a trailing "/"!
CLIPASSETS="/home/$USER/Dokumente/Obsidian/Knowledgebase/-Inbox/Anhänge/"
# tags for the YAML header: use "[tag1, tag2]" notation, NO # here!
#TAGS="" # no tags
TAGS="[clipboard]"
# --- USER CUSTOMIZATION: Extras, normally no need to change ---
# --- THINGS CAN BREAK HERE, but you might want to make it perfect. TEST ON COMMANDLINE! ---
# Date format YYYY-MM-DDThh:mm:ss+00:00
#TIMESTAMP=$(date +"%FT%T%:z")
TIMESTAMP=$(date +"%F %H:%M")
# Image name, make it unique! "Pasted Image YYYYMMDDhhmmss.png" here, like Obsidian.
IMAGENAME="Pasted Image $(date +"%Y%m%d%H%M%S").png"
# Base name for non-Markdown conversions (file output, extension comes from OUTPUTEXT)
OTHERNAME="Pasted Clip $(date +"%Y%m%d%H%M%S")"
# Pandoc’s list of Markdown dialects (my preference is "markdown_strict")
MARKDOWNDIALECTS=(commonmark, commonmark_x, gfm, markdown, markdown_github,
markdown_mmd, markdown_phpextra, markdown_strict)
# Markdown dialect to use for HTML conversion.
# Use one from above list! (markdown = Pandoc’s Markdown)
# If you really want to output docx, odt, pdf instead,
# you MUST set the correct OUTPUTEXTENSIONS, OPTIONS and OUTPUTEXT!
# Check Pandoc documentation for the version you have and TEST ON COMMANDLINE!
OUTPUTFORMAT="markdown_strict"
# Example for PDF output:
#OUTPUTFORMAT="pdf"
# Pandoc Extensions (+ to include, - to exclude, no spaces in between!)
# These must be allowed for the selected OUTPUTFORMAT, respectively, or you’ll get an error.
# Check Pandoc documentation for the version you have!
OUTPUTEXTENSIONS="+backtick_code_blocks+strikeout+footnotes" # for Markdown
# Example for PDF output:
#OUTPUTEXTENSIONS=""
# Pandoc options, set all headings ATX style (old: "--atx-headers", new: "--markdown-headings=atx")
# These can usually be left in: "--markdown-headings=atx -V papersize:a4". Check Pandoc docs!
# Need to put these into an array so the quoting works. (See BashFAQ/050.)
OPTIONS=(--atx-headers)
# Example for PDF output (for UTF-8, must use xelatex and font supporting all characters used):
#OPTIONS=(--markdown-headings=atx --pdf-engine=xelatex -V papersize:a4 -V mainfont:"DejaVu Sans")
# can use papersize:letter
# If using non-Markdown file output, you MUST specify the extension (with a leading dot).
# Get the list of possible output formats:
# pandoc --list-output-formats
OUTPUTEXT=".md"
# Example for PDF output:
#OUTPUTEXT=".pdf"
# --- DO NOT MODIFY BELOW THIS LINE! ---
# Which X11 selection to take?
# Use either of:
# primary -- default; primary selection (copy of last selection; mouse selection)
# secondary -- application-specific, seldom used
# clipboard -- Ctrl+C/X/V and context menu clipboard
XSELECTION="primary"
# check if xclip is installed
command -v xclip >/dev/null 2>&1 || \
{ echo >&2 "$me requires \"xclip\" but it's not installed. Aborting."; exit 2; }
# check if we have Pandoc available
PANDOC=true
command -v pandoc >/dev/null 2>&1 || \
{ PANDOC=false; echo >&2 "Pandoc is not installed."; \
echo >&2 "$me will work, but you're missing out big time!"; }
# Should you HAVE Pandoc but really don’t want to use it, set ...
# PANDOC=false
# tr should be available, no need to check here
# (it’s in GNU coreutils so should be in all distros)
# function: if the CLIPFILE doesn’t yet exist, create it & write a YAML header
init_clipfile () {
if [ ! -e "${CLIPFILE}" ] ; then
echo $'---\n'"date: $(date +"%F")"$'\n'"tags: ${TAGS}"$'\n---\n' >> "${CLIPFILE}"
fi
}
# check available targets and go process!
case $(xclip -o -t TARGETS) in
*image/png*)
# an image that can be converted to PNG
#echo "Found image, storing in ${CLIPASSETS}${IMAGENAME}"
init_clipfile
echo "## ${TIMESTAMP}"$'\n' >> "${CLIPFILE}"
xclip -selection ${XSELECTION} -o -t image/png > "${CLIPASSETS}${IMAGENAME}"
echo "![[${IMAGENAME}]]"$'\n\n---\n' >> "${CLIPFILE}"
;;
*text/html*)
# found HTML text, try to convert to Markdown
#echo "Found HTML text"
init_clipfile
echo "## ${TIMESTAMP}"$'\n' >> "${CLIPFILE}"
if [ "$PANDOC" = true ] ; then
if [[ "${MARKDOWNDIALECTS[@]}" =~ "${OUTPUTFORMAT}" ]] ; then
# ok, it’s Markdown, put into Clipboard file
# uses tr to remove unwanted NUL byte at end if copying from LibreOffice
xclip -selection ${XSELECTION} -o -t text/html | LC_ALL=C tr -d '\000' \
| pandoc -r html -w ${OUTPUTFORMAT}${OUTPUTEXTENSIONS} "${OPTIONS[@]}" \
>> "${CLIPFILE}"
ERROR=$?
if [ $ERROR -gt 0 ] ; then
echo "**Pandoc error ${ERROR}: Check \`${me}\` settings!**" >> "${CLIPFILE}"
echo "[List of Pandoc exit codes](https://pandoc.org/MANUAL.html#exit-codes)" >> "${CLIPFILE}"
fi
else
# some other format requested, write file to assets folder & create a link
# uses tr to remove unwanted NUL byte at end if copying from LibreOffice
xclip -selection ${XSELECTION} -o -t text/html | LC_ALL=C tr -d '\000' \
| pandoc -r html -w ${OUTPUTFORMAT}${OUTPUTEXTENSIONS} "${OPTIONS[@]}" \
-o "${CLIPASSETS}${OTHERNAME}${OUTPUTEXT}"
ERROR=$?
if [ $ERROR -gt 0 ] ; then
echo "**Pandoc error ${ERROR}: Check \`${me}\` settings!**" >> "${CLIPFILE}"
echo "[List of Pandoc exit codes](https://pandoc.org/MANUAL.html#exit-codes)" >> "${CLIPFILE}"
else
echo "[[${OTHERNAME}${OUTPUTEXT}]]" >> "${CLIPFILE}"
fi
fi
else
xclip -selection ${XSELECTION} -o >> "${CLIPFILE}"
fi
echo $'\n\n---\n' >> "${CLIPFILE}"
;;
*TEXT*|*STRING*)
# found TEXT, COMPOUND_TEXT, STRING or UTF8_STRING
#echo "Found text"
init_clipfile
echo "## ${TIMESTAMP}"$'\n' >> "${CLIPFILE}"
xclip -selection ${XSELECTION} -o >> "${CLIPFILE}"
echo $'\n\n---\n' >> "${CLIPFILE}"
;;
esac
Happy clipping!
Fun fact: You can even have your clipboard note open in Obsidian and watch it grow!
Notes
This is not meant to be a replacement for full-fledged webpage clippers like @death.au’s wonderful MarkDownload browser add-on. It’s just a convenient and fast tool to clip and collect text, HTML and images from everywhere, without the need of starting Obsidian everytime.
Thanks for the good idea, @koala!
Changelog
- v1.0 – 2021-08-19
- Initial release
- Intentionally didn’t restrict xclip to one clipboard, so it also works on console
- v1.1 – 2021-08-19
- Added option for other output formats (pdf, odt, docx), written to assets folder. This only works from HTML clippings!
- v1.2 – 2021-08-20
- Added XSELECTION option, to define the X11 selection to take. (For edge cases.)
- v1.3 – 2021-08-20
- Added EXTENSIONS and OPTIONS for Pandoc, so the output can be fine-tuned.
- v1.4 – 2021-08-20
- Added good defaults and MUCH more comments. READ THEM.
- v1.5 – 2021-08-21
- Bugfix: CLIPFILE and CLIPASSETS paths with SPACES in them now work correctly.
- Code optimizations to get rid of the many “echo” statements.
- Added a comment on how to make a CLIPFILE PER DAY (“YYYY-MM-DD Clipboard.md”).
- v1.6 – 2021-08-20
- Added Pandoc error reporting to CLIPFILE so setting problems don’t go unnoticed.
- Bugfix: When copying from LibreOffice, a NUL byte gets added that confuses other programs. This now gets removed by clipit.
- Code rework to handle edge cases for Pandoc output, i.e. “Font Name” with spaces.
- v1.7 – 2021-08-26
- Upon initial creation of a CLIPFILE, a YAML HEADER is now written.
It has “date: YYYY-MM-DD” and user-settable “tags:”. Tag default is “#clipboard”.
- Upon initial creation of a CLIPFILE, a YAML HEADER is now written.