mirror of
https://github.com/hyprwm/Hyprland.git
synced 2026-08-18 02:51:23 +00:00
hyprctl: random Lua-adjacent fixes (#15767)
* hyprctl(repl): go interactive if no Lua was given via args The previous check would mess up if `-i` was provided, since it'd see *an argument* and refuse to go interactive, even when it should've (i.e. `hyprctl -i 0 repl`). * ipc(socket1): new escape parsing for batch commands Semicolons are still the command separator, so those have to be escaped if they appear anywhere inside of commands (e.g. multi-statement Lua code). Also, literal backslashes need to be escaped as well. * tests(ipc): add test for hyprctl batch mode This test case includes slightly weird stuff (semicolons in Lua code; square brackets) that would break the old parsing logic. * format: dang braces
This commit is contained in:
@ -566,8 +566,8 @@ int main(int argc, char** argv) {
|
|||||||
std::println("{}", USAGE);
|
std::println("{}", USAGE);
|
||||||
else if (fullRequest.contains("/rollinglog") && needRoll)
|
else if (fullRequest.contains("/rollinglog") && needRoll)
|
||||||
exitStatus = request(fullRequest, 0, true);
|
exitStatus = request(fullRequest, 0, true);
|
||||||
else if (fullRequest.contains("/repl")) {
|
else if (auto pos = fullRequest.find("/repl"); pos != std::string::npos) {
|
||||||
if (ARGS.size() > 1) {
|
if (fullRequest.length() > pos + 5) {
|
||||||
// single command with output
|
// single command with output
|
||||||
exitStatus = request(fullRequest, 1);
|
exitStatus = request(fullRequest, 1);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -206,3 +206,16 @@ TEST_CASE(hyprctlREPL) {
|
|||||||
EXPECT(getCommandStdOut("hyprctl repl 'print(type(hl))'"), "table");
|
EXPECT(getCommandStdOut("hyprctl repl 'print(type(hl))'"), "table");
|
||||||
EXPECT(getCommandStdOut("hyprctl eval 'print(type(hl))'"), "ok");
|
EXPECT(getCommandStdOut("hyprctl eval 'print(type(hl))'"), "ok");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE(hyprctlBatch) {
|
||||||
|
const auto command = R"([[BATCH]] activewindow; repl local i = 42\; print(i, "hello\\nworld ]"); clients)";
|
||||||
|
const auto expected = R"(Invalid
|
||||||
|
|
||||||
|
|
||||||
|
42 hello
|
||||||
|
world ]
|
||||||
|
|
||||||
|
|
||||||
|
no open windows)";
|
||||||
|
EXPECT(getFromSocket(command), expected);
|
||||||
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
|
#include <sstream>
|
||||||
#include <hyprutils/string/String.hpp>
|
#include <hyprutils/string/String.hpp>
|
||||||
|
|
||||||
using namespace IPC::Socket1;
|
using namespace IPC::Socket1;
|
||||||
@ -129,25 +130,24 @@ SResponse CSocket1::dispatchBatch(std::string request, pid_t pid) {
|
|||||||
request = request.substr(BATCH_TOKEN.size());
|
request = request.substr(BATCH_TOKEN.size());
|
||||||
|
|
||||||
std::vector<std::string> commands;
|
std::vector<std::string> commands;
|
||||||
size_t commandStart = 0;
|
std::stringstream parsedCommand("");
|
||||||
int bracketDepth = 0;
|
|
||||||
|
|
||||||
for (size_t i = 0; i <= request.size(); ++i) {
|
for (size_t i = 0; i <= request.size(); ++i) {
|
||||||
const bool atEnd = i == request.size();
|
const bool atEnd = i == request.size();
|
||||||
|
if (atEnd || request[i] == ';') {
|
||||||
if (!atEnd) {
|
commands.emplace_back(Hyprutils::String::trim(parsedCommand.str()));
|
||||||
if (request[i] == '[')
|
parsedCommand.str("");
|
||||||
++bracketDepth;
|
parsedCommand.clear();
|
||||||
else if (request[i] == ']')
|
continue;
|
||||||
--bracketDepth;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!atEnd && (request[i] != ';' || bracketDepth != 0))
|
if (request[i] == '\\') {
|
||||||
continue;
|
if (i < request.size() && (request[i + 1] == '\\' || request[i + 1] == ';'))
|
||||||
|
++i;
|
||||||
if (commandStart < i)
|
else
|
||||||
commands.emplace_back(Hyprutils::String::trim(request.substr(commandStart, i - commandStart)));
|
Log::logger->log(Log::ERR, "Malformed socket1 request: invalid escape sequence {} at position {}, using it verbatim", request.subview(i, 2), i);
|
||||||
commandStart = i + 1;
|
}
|
||||||
|
parsedCommand << request[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<SResponse> responses;
|
std::vector<SResponse> responses;
|
||||||
|
|||||||
Reference in New Issue
Block a user