From 21db0f3a6224e7fe7175fb1796b0e02d8d3db87b Mon Sep 17 00:00:00 2001 From: tastytea Date: Thu, 28 Nov 2019 02:23:11 +0100 Subject: [PATCH 1/9] Turn examples into codeblocks. --- man/remwharead.1.adoc | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/man/remwharead.1.adoc b/man/remwharead.1.adoc index f65263e..2d42c93 100644 --- a/man/remwharead.1.adoc +++ b/man/remwharead.1.adoc @@ -77,32 +77,50 @@ Print version, copyright and license. .Save a thing into the database, with tags. ==== -`remwharead -t=tag1,tag2 https://example.com/article.html` +[source,shell] +---- +remwharead -t=tag1,tag2 https://example.com/article.html +---- ==== .Export all things between and including 2019-04-01 and 2019-05-31 to a file. ==== -`remwharead -e=asciidoc -f=out.adoc -T=2019-04-01,2019-05-31` +[source,shell] +---- +remwharead -e=asciidoc -f=out.adoc -T=2019-04-01,2019-05-31 +---- ==== .Export all things to an HTML file. ==== -`remwharead -e=asciidoc | asciidoctor --backend=html5 --out-file=out.html -` +[source,shell] +---- +remwharead -e=asciidoc | asciidoctor --backend=html5 --out-file=out.html - +---- ==== .Export all things about GRUB the boot-loader, but nothing about caterpillars. ==== -`remwharead -e=csv -s="grub AND boot"` +[source,shell] +---- +remwharead -e=csv -s="grub AND boot" +---- ==== .Output all articles by Jan Müller, consider different spellings. ==== -`remwharead -e=simple -S='Jan[\s]+M(ü|ue?)ller' -r` +[source,shell] +---- +remwharead -e=simple -S='Jan[\s]+M(ü|ue?)ller' -r +---- ==== .Export all things from the last week to an RSS feed. ==== -`remwharead -e=rss -T=$(date -d "-1 week" -I),$(date -Iminutes) | sed 's||https://example.com/|' > /var/www/feed.rss` +[source,shell] +---- +remwharead -e=rss -T=$(date -d "-1 week" -I),$(date -Iminutes) | sed 's||https://example.com/|' > /var/www/feed.rss +---- ==== === Display database From 6c5328595fe26ac95ab860787428c0fc42a006bb Mon Sep 17 00:00:00 2001 From: tastytea Date: Thu, 28 Nov 2019 02:23:39 +0100 Subject: [PATCH 2/9] Add example for mass-deletion. --- man/remwharead.1.adoc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/man/remwharead.1.adoc b/man/remwharead.1.adoc index 2d42c93..96c43d3 100644 --- a/man/remwharead.1.adoc +++ b/man/remwharead.1.adoc @@ -123,6 +123,21 @@ remwharead -e=rss -T=$(date -d "-1 week" -I),$(date -Iminutes) | sed 's|| ---- ==== +.Remove all entries that are tagged with mountain +==== +[source,shell] +---- +OLDIFS=${IFS} +IFS=$'\n' + +for uri in $(remwharead -e link -s mountain); do + remwharead -d "${uri}" +done + +IFS=${OLDIFS} +---- +==== + === Display database *remwharead* does not provide an interface to display the database. However, you From 138170975af90c7a728f5f196bcbfb970f5f310b Mon Sep 17 00:00:00 2001 From: tastytea Date: Thu, 28 Nov 2019 05:08:39 +0100 Subject: [PATCH 3/9] Add list.hpp to remwharead.hpp. --- include/remwharead.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/remwharead.hpp b/include/remwharead.hpp index c3d7f35..dfd005e 100644 --- a/include/remwharead.hpp +++ b/include/remwharead.hpp @@ -46,6 +46,7 @@ #include "export/json.hpp" #include "export/rss.hpp" #include "export/simple.hpp" +#include "export/list.hpp" #include "search.hpp" #include "sqlite.hpp" #include "time.hpp" From f8fd9b8c6d626397f5e6de4c3c0da927612e5770 Mon Sep 17 00:00:00 2001 From: tastytea Date: Thu, 28 Nov 2019 05:09:14 +0100 Subject: [PATCH 4/9] Add text_to_string(). --- include/sqlite.hpp | 8 ++++++++ src/lib/export/csv.cpp | 11 +---------- src/lib/sqlite.cpp | 27 +++++++++++++++++---------- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/include/sqlite.hpp b/include/sqlite.hpp index 71f07ca..5636f73 100644 --- a/include/sqlite.hpp +++ b/include/sqlite.hpp @@ -118,6 +118,14 @@ public: */ size_t remove(const string &uri); + /*! + * @brief Returns tags as comma separated string. + * + * @since 0.9.0 + */ + [[nodiscard]] + static string tags_to_string(const vector &tags); + private: fs::path _dbpath; std::unique_ptr _session; diff --git a/src/lib/export/csv.cpp b/src/lib/export/csv.cpp index 4aae58b..ac3a8d1 100644 --- a/src/lib/export/csv.cpp +++ b/src/lib/export/csv.cpp @@ -30,19 +30,10 @@ void Export::CSV::print() const << R"("Title","Description","Full text")" << "\r\n"; for (const Database::entry &entry : _entries) { - string strtags; - for (const string &tag : entry.tags) - { - strtags += tag; - if (tag != *(entry.tags.rbegin())) - { - strtags += ","; - } - } _out << '"' << quote(entry.uri) << "\",\"" << quote(entry.archive_uri) << "\",\"" << timepoint_to_string(entry.datetime) << "\",\"" - << quote(strtags) << "\",\"" + << quote(Database::tags_to_string(entry.tags)) << "\",\"" << quote(entry.title) << "\",\"" << quote(entry.description) << "\",\"" << quote(entry.fulltext_oneline()) << '"'<< "\r\n"; diff --git a/src/lib/sqlite.cpp b/src/lib/sqlite.cpp index 4da32af..e842869 100644 --- a/src/lib/sqlite.cpp +++ b/src/lib/sqlite.cpp @@ -84,18 +84,9 @@ void Database::store(const Database::entry &data) const try { const string strdatetime = timepoint_to_string(data.datetime, true); - string strtags; + string strtags = tags_to_string(data.tags); Statement insert(*_session); - for (const string &tag : data.tags) - { - strtags += tag; - if (tag != *(data.tags.rbegin())) - { - strtags += ","; - } - } - // useRef() uses the const reference. insert << "INSERT INTO remwharead " "VALUES(?, ?, ?, ?, ?, ?, ?);", @@ -175,6 +166,22 @@ size_t Database::remove(const string &uri) return del.execute(); } +string Database::tags_to_string(const vector &tags) +{ + string strtags; + + for (const string &tag : tags) + { + strtags += tag; + if (tag != *(tags.rbegin())) + { + strtags += ','; + } + } + + return strtags; +} + fs::path Database::get_data_home() const { fs::path path; From ad676bbc13db24f158e4d36864da8016ec249a64 Mon Sep 17 00:00:00 2001 From: tastytea Date: Thu, 28 Nov 2019 09:03:52 +0100 Subject: [PATCH 5/9] Add rofi export. --- include/export/rofi.hpp | 39 +++++++++++++++++++++++++++++++++++++++ include/remwharead.hpp | 1 + include/types.hpp | 3 ++- src/cli/main.cpp | 14 ++++++++++++++ src/cli/parse_options.cpp | 4 ++++ src/lib/export/rofi.cpp | 39 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 include/export/rofi.hpp create mode 100644 src/lib/export/rofi.cpp diff --git a/include/export/rofi.hpp b/include/export/rofi.hpp new file mode 100644 index 0000000..33ba8ec --- /dev/null +++ b/include/export/rofi.hpp @@ -0,0 +1,39 @@ +/* This file is part of remwharead. + * Copyright © 2019 tastytea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef REMWHAREAD_EXPORT_ROFI_HPP +#define REMWHAREAD_EXPORT_ROFI_HPP + +#include "export.hpp" + +namespace remwharead::Export +{ +/*! + * @brief Export title, tags and URL for consumption by rofi. + * + * @since 0.9.0 + * + * @headerfile rofi.hpp remwharead/export/rofi.hpp + */ +class Rofi : protected ExportBase +{ +public: + using ExportBase::ExportBase; + void print() const override; +}; +} // namespace remwharead::Export + +#endif // REMWHAREAD_EXPORT_ROFI_HPP diff --git a/include/remwharead.hpp b/include/remwharead.hpp index dfd005e..f078bde 100644 --- a/include/remwharead.hpp +++ b/include/remwharead.hpp @@ -47,6 +47,7 @@ #include "export/rss.hpp" #include "export/simple.hpp" #include "export/list.hpp" +#include "export/rofi.hpp" #include "search.hpp" #include "sqlite.hpp" #include "time.hpp" diff --git a/include/types.hpp b/include/types.hpp index 6f01510..e7ef292 100644 --- a/include/types.hpp +++ b/include/types.hpp @@ -37,7 +37,8 @@ enum class export_format simple, json, rss, - link + link, + rofi }; } // namespace remwharead diff --git a/src/cli/main.cpp b/src/cli/main.cpp index 1206732..edd971d 100644 --- a/src/cli/main.cpp +++ b/src/cli/main.cpp @@ -20,6 +20,7 @@ #include "export/csv.hpp" #include "export/json.hpp" #include "export/link.hpp" +#include "export/rofi.hpp" #include "export/rss.hpp" #include "export/simple.hpp" #include "search.hpp" @@ -228,6 +229,19 @@ int App::main(const std::vector &args) } break; } + case export_format::rofi: + { + if (file.is_open()) + { + Export::Rofi(entries, file).print(); + file.close(); + } + else + { + Export::Rofi(entries).print(); + } + break; + } default: { break; diff --git a/src/cli/parse_options.cpp b/src/cli/parse_options.cpp index acc0bf5..dae2c5c 100644 --- a/src/cli/parse_options.cpp +++ b/src/cli/parse_options.cpp @@ -156,6 +156,10 @@ void App::handle_options(const std::string &name, const std::string &value) { _format = export_format::link; } + else if (value == "rofi") + { + _format = export_format::rofi; + } else { cerr << "Error: Unknown format.\n"; diff --git a/src/lib/export/rofi.cpp b/src/lib/export/rofi.cpp new file mode 100644 index 0000000..69edcc1 --- /dev/null +++ b/src/lib/export/rofi.cpp @@ -0,0 +1,39 @@ +/* This file is part of remwharead. + * Copyright © 2019 tastytea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "export/rofi.hpp" +#include "sqlite.hpp" +#include + +namespace remwharead +{ +using std::string; + +void Export::Rofi::print() const +{ + _out << static_cast(0x00) << "markup-rows" + << static_cast(0x1f) << "true\n"; + + for (const Database::entry & entry : _entries) + { + _out << entry.title + << R"( ()" + << Database::tags_to_string(entry.tags) << ") " + << R"()" + << entry.uri << "\n"; + } +} +} // namespace remwharead From bce12ae53b9efb8833a03d8585d02a567214b01f Mon Sep 17 00:00:00 2001 From: tastytea Date: Thu, 28 Nov 2019 09:04:07 +0100 Subject: [PATCH 6/9] Add remwharead-rofi. --- scripts/remwharead-rofi | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100755 scripts/remwharead-rofi diff --git a/scripts/remwharead-rofi b/scripts/remwharead-rofi new file mode 100755 index 0000000..47d1ac4 --- /dev/null +++ b/scripts/remwharead-rofi @@ -0,0 +1,15 @@ +#!/bin/sh +# Open the whole database in rofi. Searches in title, tags and URI. +# The selected entry will be opened with the default browser. + +if [ -n "${2}" ]; then + uri=$(echo "${*}" | sed -E 's|^.+>([^><]+)$|\1|') + xdg-open "${uri}" + exit 0 +fi + +if [ "${1}" = "runremwharead" ]; then + /home/tastytea/Projekte/remwharead/build/src/cli/remwharead -e rofi +else + rofi -show remwharead -modi remwharead:"${0} runremwharead" +fi From 4ac61852edd98348128aa37e991d9f0cc0939d87 Mon Sep 17 00:00:00 2001 From: tastytea Date: Thu, 28 Nov 2019 09:22:03 +0100 Subject: [PATCH 7/9] Add test for rofi export. --- tests/test_rofi.cpp | 68 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 tests/test_rofi.cpp diff --git a/tests/test_rofi.cpp b/tests/test_rofi.cpp new file mode 100644 index 0000000..fdd3d25 --- /dev/null +++ b/tests/test_rofi.cpp @@ -0,0 +1,68 @@ +/* This file is part of remwharead. + * Copyright © 2019 tastytea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include "sqlite.hpp" +#include "export/rofi.hpp" + +using namespace remwharead; +using std::string; + +SCENARIO ("The Rofi export works correctly") +{ + bool exception = false; + bool rofi_ok = true; + + GIVEN ("One database entry") + { + Database::entry entry; + entry.uri = "https://example.com/page.html"; + entry.title = "Thoughtful title"; + entry.tags = { "tag1", "tag2" }; + + const string expected = static_cast(0x00) + string("markup-rows") + + static_cast(0x1f) + "true\n" + "Thoughtful title " + R"((tag1,tag2))" + R"( )" + "https://example.com/page.html\n"; + + try + { + std::ostringstream output; + Export::Rofi({ entry }, output).print(); + const string rofi = output.str(); + + if (rofi != expected) + { + rofi_ok = false; + } + } + catch (const std::exception &e) + { + exception = true; + } + + THEN ("No exception is thrown") + AND_THEN ("Output looks okay") + { + REQUIRE_FALSE(exception); + REQUIRE(rofi_ok); + } + } +} From cce04a60d9bcff72da3da005fa2d96528848ccf0 Mon Sep 17 00:00:00 2001 From: tastytea Date: Thu, 28 Nov 2019 09:33:27 +0100 Subject: [PATCH 8/9] Fix path in rofi script. --- scripts/remwharead-rofi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/remwharead-rofi b/scripts/remwharead-rofi index 47d1ac4..2ef49ee 100755 --- a/scripts/remwharead-rofi +++ b/scripts/remwharead-rofi @@ -9,7 +9,7 @@ if [ -n "${2}" ]; then fi if [ "${1}" = "runremwharead" ]; then - /home/tastytea/Projekte/remwharead/build/src/cli/remwharead -e rofi + remwharead -e rofi else rofi -show remwharead -modi remwharead:"${0} runremwharead" fi From 970fb1486af0dc95a63ce7f52005a81d9b902ebc Mon Sep 17 00:00:00 2001 From: tastytea Date: Thu, 28 Nov 2019 09:45:23 +0100 Subject: [PATCH 9/9] Add rofi export to documentation. --- README.adoc | 7 +++++++ man/remwharead.1.adoc | 10 ++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/README.adoc b/README.adoc index 90a6dfe..3c98ec6 100644 --- a/README.adoc +++ b/README.adoc @@ -20,6 +20,7 @@ :uri-ff-addon: https://addons.mozilla.org/firefox/addon/remwharead :uri-papirus: https://github.com/PapirusDevelopmentTeam/papirus-icon-theme :uri-hunter: https://github.com/cpp-pm/hunter +:uri-rofi: https://github.com/davatorium/rofi *remwharead* saves URIs of things you want to remember in a database along with an URI to the archived version, the current date and time, title, description, @@ -45,6 +46,12 @@ image::{uri-images-base}/example_tags.png[] See {uri-branch-main}/man/remwharead.1.adoc[manpage] and/or read {uri-blogpost}[the blogpost]. +=== With rofi + +The link:{uri-rofi}[rofi] export makes integration with rofi simple. See +link:{uri-branch-main}/scripts/remwharead-rofi[scripts/remwharead-rofi] for an +example. + === In your programs The complete functionality is implemented in a C++ library, libremwharead. Take diff --git a/man/remwharead.1.adoc b/man/remwharead.1.adoc index 96c43d3..b6ebac4 100644 --- a/man/remwharead.1.adoc +++ b/man/remwharead.1.adoc @@ -26,7 +26,8 @@ remwharead - Saves URIs of things you want to remember in a database the full text of the page and optional tags. The database can be filtered by time, tags and full text and exported to CSV, -AsciiDoc, a bookmarks file, JSON, RSS or a list of hyperlinks. +AsciiDoc, a bookmarks file, JSON, RSS, a list of hyperlinks or a rofi-compatible +list. Archiving is done using the Wayback machine from the https://archive.org/[Internet Archive]. @@ -38,7 +39,7 @@ Add tags to _URI_, delimited by commas. *-e*=_format_, *--export*=_format_:: Export to _format_. Possible values are _csv_, _asciidoc_, _bookmarks_, -_simple_, _json_, _rss_ or _link_. See _FORMATS_. +_simple_, _json_, _rss_, _link_ or _rofi_. See _FORMATS_. *-f*=_file_, *--file*=_file_:: Save output to _file_. Default is stdout. @@ -191,6 +192,11 @@ specification (the element _link_ in _channel_ is empty). Export as a plain list of links, separated by newlines. +=== rofi + +Export title, tags and URL for consumption by rofi. See the `scripts/` directory +on https://schlomp.space/tastytea/remwharead for an example. + == SEARCH EXPRESSIONS A search expression is either a single term, or several terms separated by _AND_