Skip to content

Commit

Permalink
Allow to print paths as OSC8 hyperlinks
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
vimpostor committed Aug 3, 2023
1 parent 9c32d8e commit 3ba601c
Show file tree
Hide file tree
Showing 11 changed files with 33 additions and 3 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ For more options see `blobdrop -h` or the man page `blobdrop(1)`.
- Respect system dark mode
- Shell completions
- Optional notification drag frontend
- Optional OSC8 hyperlink frontend
- Efficient implementation, can scroll through a list of several thousand files without dropping any frames

# Alternatives
Expand Down
1 change: 1 addition & 0 deletions assets/completions/bash-completion/completions/blobdrop
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ _blobdrop() {
-v --version
-f --frameless
-k --keep
-l --link
-n --notification
-p --persistent
-t --ontop
Expand Down
2 changes: 1 addition & 1 deletion assets/completions/zsh/site-functions/_blobdrop
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#compdef blobdrop

_blobdrop() {
_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'
_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'
return 0
}

Expand Down
4 changes: 4 additions & 0 deletions doc/man/man1/blobdrop.1
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ blobdrop \- Quickly drag and drop files from the terminal to applications
[\-v]
[\-f]
[\-k]
[\-l]
[\-n]
[\-p]
[\-t]
Expand Down Expand Up @@ -36,6 +37,9 @@ Show a frameless window.
.B \-k, \-\-keep
When using sink mode, keep dropped files around by default.
.TP
.B \-l, \-\-link
Print paths to stdout via OSC8 hyperlinks.
.TP
.B \-n, \-\-notification
Send a notification for dragging.
.TP
Expand Down
6 changes: 6 additions & 0 deletions src/Models/path_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ void PathModel::open(int i) const {
};
}

void PathModel::print_hyperlinks() {
for (auto &i : paths) {
std::cout << Util::print_osc8_link(i.get_uri(), i.pretty_print()) << std::endl;
}
}

void PathModel::send_notification() {
refresh_folded_paths();
const auto uri_list = folded_uri_list.split(QChar::LineFeed, Qt::SkipEmptyParts);
Expand Down
1 change: 1 addition & 0 deletions src/Models/path_model.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class PathModel : public QAbstractListModel {
Q_INVOKABLE void taint_all_used();
Q_INVOKABLE void refresh_folded_paths();
Q_INVOKABLE void open(int i) const;
Q_INVOKABLE void print_hyperlinks();
Q_INVOKABLE void send_notification();
void add_path(Path p);
signals:
Expand Down
5 changes: 5 additions & 0 deletions src/Util/util.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "util.hpp"

#include <cstdlib>
#include <iostream>
#include <pwd.h>
#include <unistd.h>

Expand All @@ -25,4 +26,8 @@ std::string pwd() {
}
return result;
}

std::string print_osc8_link(const std::string &url, const std::string &text) {
return "\e]8;;" + url + "\e\\" + text + "\e]8;;\e\\";
}
}
1 change: 1 addition & 0 deletions src/Util/util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ namespace Util {

const char *home_dir();
std::string pwd();
std::string print_osc8_link(const std::string &url, const std::string &text);
}
8 changes: 7 additions & 1 deletion src/getopts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ bool parse(QCoreApplication &app) {
QCommandLineOption keep_opt(QStringList() << "k"
<< "keep",
"Keep dropped files around in sink mode.");
QCommandLineOption link_opt(QStringList() << "l"
<< "link",
"Print paths to stdout via OSC8 hyperlinks.");
QCommandLineOption notify_opt(QStringList() << "n"
<< "notification",
"Send a notification for dragging.");
Expand All @@ -31,7 +34,7 @@ bool parse(QCoreApplication &app) {
"Whether to autoquit after a drag is finished. 0 = disable, 1 = after first drag, 2 (default) = after all paths have been used",
"number");

p.addOptions({frameless_opt, keep_opt, notify_opt, persistent_opt, ontop_opt, auto_quit_opt});
p.addOptions({frameless_opt, keep_opt, link_opt, notify_opt, persistent_opt, ontop_opt, auto_quit_opt});
p.process(app);

if (p.isSet(auto_quit_opt)) {
Expand All @@ -53,6 +56,9 @@ bool parse(QCoreApplication &app) {
if (p.isSet(keep_opt)) {
Settings::get()->keep_dropped_files = true;
}
if (p.isSet(link_opt)) {
Settings::get()->print_hyperlinks = true;
}
if (p.isSet(notify_opt)) {
Settings::get()->send_notification = true;
}
Expand Down
5 changes: 4 additions & 1 deletion src/qml/PathView.qml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ ListView {
target: dragallDummy
dragUri: PathModel.foldedUriList
Component.onCompleted: {
if (Settings.sendNotification) {
if (Settings.printHyperlinks) {
PathModel.print_hyperlinks();
Qt.quit();
} else if (Settings.sendNotification) {
PathModel.send_notification();
Qt.quit();
}
Expand Down
2 changes: 2 additions & 0 deletions src/settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class Settings : public QObject {
Q_PROPERTY(bool alwaysOnTop MEMBER always_on_top CONSTANT)
Q_PROPERTY(bool alwaysOnBottom MEMBER always_on_bottom WRITE setAlwaysOnBottom NOTIFY alwaysOnBottomChanged)
Q_PROPERTY(bool keepDroppedFiles MEMBER keep_dropped_files NOTIFY keepDroppedFilesChanged)
Q_PROPERTY(bool printHyperlinks MEMBER print_hyperlinks CONSTANT)
Q_PROPERTY(bool frameless MEMBER frameless CONSTANT)
Q_PROPERTY(bool sendNotification MEMBER send_notification CONSTANT)
public:
Expand All @@ -31,6 +32,7 @@ class Settings : public QObject {
bool always_on_top = false;
bool always_on_bottom = false;
bool keep_dropped_files = false;
bool print_hyperlinks = false;
bool frameless = false;
bool send_notification = false;
signals:
Expand Down

0 comments on commit 3ba601c

Please sign in to comment.