Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,4 @@ target_include_directories(hyprlauncher PRIVATE "./protocols")

target_link_libraries(hyprlauncher PkgConfig::deps)

install(TARGETS hyprlauncher)
install(TARGETS hyprlauncher)
9 changes: 9 additions & 0 deletions protocols/hyprlauncher_core.xml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@
<arg name="options" type="array varchar" summary="option array"/>
</c2s>

<c2s name="set_provider_with_options">
<description summary="Open the launcher with a specific provider and options">
Opens the launcher with a given provider (e.g., 'clipboard').
If the launcher is already open, this is a no-op.
</description>
<arg name="provider" type="varchar" summary="provider name"/>
<arg name="options" type="array varchar" summary="option array for the provider"/>
</c2s>

<c2s name="get_info_object">
<description summary="Get launcher's info object">
Gets the launcher info object. That object will return some data about
Expand Down
85 changes: 85 additions & 0 deletions src/clipboard/ClipboardManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#include "ClipboardManager.hpp"
#include <hyprutils/os/Process.hpp>
#include <iterator>
#include "../helpers/Log.hpp"
#include <ranges>
#include <sstream>

using namespace Hyprutils::OS;

CClipboardManager::CClipboardManager(const SClipboardConfig& config) : m_Config(config) {}

static void executeCommand(const std::string& command, const std::string& arg) {
if (command.empty())
return;

bool hasPlaceholder = command.find('{') != std::string::npos;

if (hasPlaceholder) {
std::string finalCommand;
try {
finalCommand = std::vformat(command, std::make_format_args("\"$1\""));
} catch (const std::format_error& e) {
Debug::log(ERR, "Invalid format string in command: {}. Error: {}", command, e.what());
return;
}
CProcess proc("/bin/sh", {"-c", finalCommand, "-", arg});
proc.runAsync();
} else if (!arg.empty()) {
std::string shellCommand = "echo -n \"$1\" | " + command;
CProcess proc("/bin/sh", {"-c", shellCommand, "-", arg});
proc.runAsync();
} else {
CProcess proc("/bin/sh", {"-c", command});
proc.runAsync();
}
}

std::vector<SClipboardHistoryItem> CClipboardManager::getHistory() {
std::istringstream iss(m_Config.listCmd);
std::vector<std::string> parts{std::istream_iterator<std::string>{iss}, std::istream_iterator<std::string>{}};

if (parts.empty()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what the heck is going on here?

Debug::log(ERR, "Empty listCmd");
return {};
}

const std::string& binary = parts.front();
std::vector<std::string> args(parts.begin() + 1, parts.end());
CProcess proc(binary, args);
proc.runSync();
const std::string output = proc.stdOut();
const std::string errOut = proc.stdErr();

if (!errOut.empty())
Debug::log(WARN, "listCmd stderr: {}", errOut);

const int exitCode = proc.exitCode();
if (exitCode != 0) {
Debug::log(ERR, "listCmd exited with code {}: {}", exitCode, m_Config.listCmd);
return {};
}
std::vector<SClipboardHistoryItem> history;
for (auto&& line_view : std::ranges::views::split(output, '\n')) {
std::string line{line_view.begin(), line_view.end()};
if (line.empty())
continue;

const auto tabPos = line.find('\t');
std::string display = (tabPos != std::string::npos) ? line.substr(tabPos + 1) : line;
history.emplace_back(line, std::string(display));
}
return history;
}

void CClipboardManager::copyItem(const std::string& originalLine) {
executeCommand(m_Config.copyCmd, originalLine);
}

void CClipboardManager::deleteItem(const std::string& item) {
executeCommand(m_Config.deleteCmd, item);
}

SClipboardConfig CClipboardManager::getConfig() const {
return m_Config;
}
24 changes: 24 additions & 0 deletions src/clipboard/ClipboardManager.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#pragma once

#include <string>
#include <vector>
#include "../config/ConfigManager.hpp"

struct SClipboardHistoryItem {
std::string originalLine;
std::string displayLine;
};

class CClipboardManager {
public:
CClipboardManager(const SClipboardConfig& config);

SClipboardConfig getConfig() const;
std::vector<SClipboardHistoryItem> getHistory();

void copyItem(const std::string& item);
void deleteItem(const std::string& item);

private:
SClipboardConfig m_Config;
};
5 changes: 5 additions & 0 deletions src/config/ConfigManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ CConfigManager::CConfigManager() : m_inotifyFd(inotify_init()) {
m_config->addConfigValue("finders:desktop_prefix", Hyprlang::STRING{""});
m_config->addConfigValue("finders:unicode_prefix", Hyprlang::STRING{"."});
m_config->addConfigValue("finders:math_prefix", Hyprlang::STRING{"="});
m_config->addConfigValue("finders:clipboard_prefix", Hyprlang::STRING{">"});

m_config->addConfigValue("finders:clipboard:list_cmd", Hyprlang::STRING(&m_clipboardConfig.listCmd));
m_config->addConfigValue("finders:clipboard:copy_cmd", Hyprlang::STRING(&m_clipboardConfig.copyCmd));
m_config->addConfigValue("finders:clipboard:delete_cmd", Hyprlang::STRING(&m_clipboardConfig.deleteCmd));

m_config->addConfigValue("finders:desktop_launch_prefix", Hyprlang::STRING{""});
m_config->addConfigValue("finders:desktop_icons", Hyprlang::INT{1});
Expand Down
7 changes: 7 additions & 0 deletions src/config/ConfigManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@

#include <hyprutils/os/FileDescriptor.hpp>

struct SClipboardConfig {
std::string listCmd = "cliphist list";
std::string copyCmd = "cliphist decode \"{}\" | wl-copy";
std::string deleteCmd = "cliphist delete";
};

class CConfigManager {
public:
CConfigManager();
Expand All @@ -19,6 +25,7 @@ class CConfigManager {
Hyprutils::OS::CFileDescriptor m_inotifyFd;
std::vector<int> m_watches;
std::string m_configPath;
SClipboardConfig m_clipboardConfig;

void replantWatch();
};
Expand Down
11 changes: 6 additions & 5 deletions src/finders/FinderTypes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
#include <cstdint>

enum eFinderTypes : uint8_t {
FINDER_DESKTOP = 0,
FINDER_UNICODE = 1,
FINDER_MATH = 2,
FINDER_IPC = 3,
};
FINDER_DESKTOP = 0,
FINDER_UNICODE = 1,
FINDER_MATH = 2,
FINDER_IPC = 3,
FINDER_CLIPBOARD = 4,
};
26 changes: 26 additions & 0 deletions src/finders/clipboard/ClipboardEntry.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include "ClipboardEntry.hpp"
#include "../../helpers/Log.hpp"

CClipboardEntry::CClipboardEntry(const SClipboardHistoryItem& item, CClipboardManager* manager) :
m_Content(item.displayLine), m_OriginalLine(item.originalLine), m_Manager(manager) {
const auto tabPos = m_OriginalLine.find('\t');
m_ID = (tabPos != std::string::npos) ? m_OriginalLine.substr(0, tabPos) : m_OriginalLine;
}

const std::string& CClipboardEntry::fuzzable() {
return m_OriginalLine;
}

eFinderTypes CClipboardEntry::type() {
return FINDER_CLIPBOARD;
}

void CClipboardEntry::run() {
Debug::log(LOG, "Running clipboard entry: copying and pasting");
m_Manager->copyItem(m_ID);
}

void CClipboardEntry::remove() {
Debug::log(LOG, "Removing clipboard entry from history");
m_Manager->deleteItem(m_OriginalLine);
}
20 changes: 20 additions & 0 deletions src/finders/clipboard/ClipboardEntry.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once

#include "../IFinder.hpp"
#include "../../clipboard/ClipboardManager.hpp"

class CClipboardEntry : public IFinderResult {
public:
CClipboardEntry(const SClipboardHistoryItem& item, CClipboardManager* manager);
virtual ~CClipboardEntry() = default;

virtual const std::string& fuzzable();
virtual eFinderTypes type();
virtual void run();
virtual void remove();

std::string m_Content;
std::string m_OriginalLine;
std::string m_ID;
CClipboardManager* m_Manager;
};
58 changes: 58 additions & 0 deletions src/finders/clipboard/ClipboardFinder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include "ClipboardFinder.hpp"
#include "ClipboardEntry.hpp"
#include "../../helpers/Log.hpp"
#include "../../config/ConfigManager.hpp"
#include "../Fuzzy.hpp"

CClipboardFinder::CClipboardFinder() = default;

void CClipboardFinder::onConfigReload() {
Debug::log(LOG, "ClipboardFinder reloading config.");
m_ClipboardManager = makeUnique<CClipboardManager>(g_configManager->m_clipboardConfig);
}

std::vector<SFinderResult> CClipboardFinder::getResultsForQuery(const std::string& query) {
if (!m_ClipboardManager) {
Debug::log(ERR, "Clipboard manager not initialized. Cannot get history.");
return {};
}

const auto HISTORY = m_ClipboardManager->getHistory();
Debug::log(TRACE, "Fetched history has {} items.", HISTORY.size());
std::vector<SFinderResult> results;

if (query.empty()) {
const size_t limit = std::min((size_t)MAX_RESULTS_PER_FINDER, HISTORY.size());
results.reserve(limit);
for (size_t i = 0; i < limit; ++i) {
const auto& item = HISTORY[i];
results.emplace_back(SFinderResult{
.label = item.displayLine,
.result = makeShared<CClipboardEntry>(item, m_ClipboardManager.get()),
});
}
} else {
std::vector<CSharedPointer<IFinderResult>> allHistoryItems;
allHistoryItems.reserve(HISTORY.size());
for (const auto& item : HISTORY) {
allHistoryItems.emplace_back(makeShared<CClipboardEntry>(item, m_ClipboardManager.get()));
}

auto fuzzed = Fuzzy::getNResults(allHistoryItems, query, MAX_RESULTS_PER_FINDER);
results.reserve(fuzzed.size());

for (const auto& f : fuzzed) {
const auto entry = reinterpretPointerCast<CClipboardEntry>(f);
if (!entry)
continue;

results.emplace_back(SFinderResult{
.label = entry->m_Content,
.result = f,
});
}
}

Debug::log(TRACE, "Returning {} filtered results.", results.size());
return results;
}
18 changes: 18 additions & 0 deletions src/finders/clipboard/ClipboardFinder.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once

#include "../IFinder.hpp"
#include "../../clipboard/ClipboardManager.hpp"

class CClipboardFinder : public IFinder {
public:
virtual ~CClipboardFinder() = default;
CClipboardFinder();

virtual std::vector<SFinderResult> getResultsForQuery(const std::string& query);
void onConfigReload();

private:
UP<CClipboardManager> m_ClipboardManager;
};

inline UP<CClipboardFinder> g_clipboardFinder;
Loading