Skip to content

Commit 3ba601c

Browse files
committed
Allow to print paths as OSC8 hyperlinks
This prints the path directly to stdout via OSC8 just like "ls --hyperlink=auto". Terminal emulators may implement drag and drop functionality universally for OSC8, so this can act as a third frontend. Right now I don't know of any terminal emulator that actually does this, but I might implement it for wezterm in the future.
1 parent 9c32d8e commit 3ba601c

File tree

11 files changed

+33
-3
lines changed

11 files changed

+33
-3
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ For more options see `blobdrop -h` or the man page `blobdrop(1)`.
4444
- Respect system dark mode
4545
- Shell completions
4646
- Optional notification drag frontend
47+
- Optional OSC8 hyperlink frontend
4748
- Efficient implementation, can scroll through a list of several thousand files without dropping any frames
4849

4950
# Alternatives

assets/completions/bash-completion/completions/blobdrop

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ _blobdrop() {
55
-v --version
66
-f --frameless
77
-k --keep
8+
-l --link
89
-n --notification
910
-p --persistent
1011
-t --ontop

assets/completions/zsh/site-functions/_blobdrop

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#compdef blobdrop
22

33
_blobdrop() {
4-
_arguments {-h,--help}'[show help]' {-v,--version}'[show version]' {-f,--frameless}'[show frameless window]' {-k,--keep}'[keep dropped files]' {-n,--notification}'[send notification]' {-p,--persistent}'[disable autohiding during drag]' {-t,--ontop}'[keep window on top]' {-x,--auto-quit}'[autoquit behaviour]:num:((0\:"do not autoquit" 1\:"after first drag" 2\:"after all items have been dragged"))' '*: arg:_files'
4+
_arguments {-h,--help}'[show help]' {-v,--version}'[show version]' {-f,--frameless}'[show frameless window]' {-k,--keep}'[keep dropped files]' {-l,--link}'[print OSC8 hyperlinks]' {-n,--notification}'[send notification]' {-p,--persistent}'[disable autohiding during drag]' {-t,--ontop}'[keep window on top]' {-x,--auto-quit}'[autoquit behaviour]:num:((0\:"do not autoquit" 1\:"after first drag" 2\:"after all items have been dragged"))' '*: arg:_files'
55
return 0
66
}
77

doc/man/man1/blobdrop.1

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ blobdrop \- Quickly drag and drop files from the terminal to applications
99
[\-v]
1010
[\-f]
1111
[\-k]
12+
[\-l]
1213
[\-n]
1314
[\-p]
1415
[\-t]
@@ -36,6 +37,9 @@ Show a frameless window.
3637
.B \-k, \-\-keep
3738
When using sink mode, keep dropped files around by default.
3839
.TP
40+
.B \-l, \-\-link
41+
Print paths to stdout via OSC8 hyperlinks.
42+
.TP
3943
.B \-n, \-\-notification
4044
Send a notification for dragging.
4145
.TP

src/Models/path_model.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ void PathModel::open(int i) const {
5959
};
6060
}
6161

62+
void PathModel::print_hyperlinks() {
63+
for (auto &i : paths) {
64+
std::cout << Util::print_osc8_link(i.get_uri(), i.pretty_print()) << std::endl;
65+
}
66+
}
67+
6268
void PathModel::send_notification() {
6369
refresh_folded_paths();
6470
const auto uri_list = folded_uri_list.split(QChar::LineFeed, Qt::SkipEmptyParts);

src/Models/path_model.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class PathModel : public QAbstractListModel {
2626
Q_INVOKABLE void taint_all_used();
2727
Q_INVOKABLE void refresh_folded_paths();
2828
Q_INVOKABLE void open(int i) const;
29+
Q_INVOKABLE void print_hyperlinks();
2930
Q_INVOKABLE void send_notification();
3031
void add_path(Path p);
3132
signals:

src/Util/util.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "util.hpp"
22

33
#include <cstdlib>
4+
#include <iostream>
45
#include <pwd.h>
56
#include <unistd.h>
67

@@ -25,4 +26,8 @@ std::string pwd() {
2526
}
2627
return result;
2728
}
29+
30+
std::string print_osc8_link(const std::string &url, const std::string &text) {
31+
return "\e]8;;" + url + "\e\\" + text + "\e]8;;\e\\";
32+
}
2833
}

src/Util/util.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,5 @@ namespace Util {
2121

2222
const char *home_dir();
2323
std::string pwd();
24+
std::string print_osc8_link(const std::string &url, const std::string &text);
2425
}

src/getopts.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ bool parse(QCoreApplication &app) {
1717
QCommandLineOption keep_opt(QStringList() << "k"
1818
<< "keep",
1919
"Keep dropped files around in sink mode.");
20+
QCommandLineOption link_opt(QStringList() << "l"
21+
<< "link",
22+
"Print paths to stdout via OSC8 hyperlinks.");
2023
QCommandLineOption notify_opt(QStringList() << "n"
2124
<< "notification",
2225
"Send a notification for dragging.");
@@ -31,7 +34,7 @@ bool parse(QCoreApplication &app) {
3134
"Whether to autoquit after a drag is finished. 0 = disable, 1 = after first drag, 2 (default) = after all paths have been used",
3235
"number");
3336

34-
p.addOptions({frameless_opt, keep_opt, notify_opt, persistent_opt, ontop_opt, auto_quit_opt});
37+
p.addOptions({frameless_opt, keep_opt, link_opt, notify_opt, persistent_opt, ontop_opt, auto_quit_opt});
3538
p.process(app);
3639

3740
if (p.isSet(auto_quit_opt)) {
@@ -53,6 +56,9 @@ bool parse(QCoreApplication &app) {
5356
if (p.isSet(keep_opt)) {
5457
Settings::get()->keep_dropped_files = true;
5558
}
59+
if (p.isSet(link_opt)) {
60+
Settings::get()->print_hyperlinks = true;
61+
}
5662
if (p.isSet(notify_opt)) {
5763
Settings::get()->send_notification = true;
5864
}

src/qml/PathView.qml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ ListView {
3131
target: dragallDummy
3232
dragUri: PathModel.foldedUriList
3333
Component.onCompleted: {
34-
if (Settings.sendNotification) {
34+
if (Settings.printHyperlinks) {
35+
PathModel.print_hyperlinks();
36+
Qt.quit();
37+
} else if (Settings.sendNotification) {
3538
PathModel.send_notification();
3639
Qt.quit();
3740
}

src/settings.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ class Settings : public QObject {
1212
Q_PROPERTY(bool alwaysOnTop MEMBER always_on_top CONSTANT)
1313
Q_PROPERTY(bool alwaysOnBottom MEMBER always_on_bottom WRITE setAlwaysOnBottom NOTIFY alwaysOnBottomChanged)
1414
Q_PROPERTY(bool keepDroppedFiles MEMBER keep_dropped_files NOTIFY keepDroppedFilesChanged)
15+
Q_PROPERTY(bool printHyperlinks MEMBER print_hyperlinks CONSTANT)
1516
Q_PROPERTY(bool frameless MEMBER frameless CONSTANT)
1617
Q_PROPERTY(bool sendNotification MEMBER send_notification CONSTANT)
1718
public:
@@ -31,6 +32,7 @@ class Settings : public QObject {
3132
bool always_on_top = false;
3233
bool always_on_bottom = false;
3334
bool keep_dropped_files = false;
35+
bool print_hyperlinks = false;
3436
bool frameless = false;
3537
bool send_notification = false;
3638
signals:

0 commit comments

Comments
 (0)