Add support for nested |exec| expressions

Nested exec expressions like ${execp echo '${execp echo hi}'} are not
evaluated correctly because parsing expressions like these generates and
registers new callbacks but we never wait for these callbacks to
complete before returning the result of the evaluation.

Fix this by re-evaluating expressions after running all pending
callbacks.
This commit is contained in:
Kushagra Sinha 2019-03-03 17:45:02 +01:00 committed by Brenden Matthews
parent 4cb79fb3e1
commit c352069b31
3 changed files with 75 additions and 1 deletions

View File

@ -727,6 +727,17 @@ void generate_text_internal(char *p, int p_max_size, struct text_object root) {
void evaluate(const char *text, char *p, int p_max_size) {
struct text_object subroot {};
/**
* Consider expressions like: ${execp echo '${execp echo hi}'}
* These would require multiple passes of evaluation:
* The first pass would parse the first level of |execp| and would generate
* a callback registration using |register_exec|, but to correctly evaluate
* the expression, we would need to wait for the just registered callback to
* execute and return its result.
*/
parse_conky_vars(&subroot, text, p, p_max_size);
conky::run_all_callbacks();
// Run another evaluation pass.
parse_conky_vars(&subroot, text, p, p_max_size);
DBGP2("evaluated '%s' to '%s'", text, p);

View File

@ -4,7 +4,7 @@ include_directories(${CMAKE_SOURCE_DIR}/src)
include_directories(${CMAKE_BINARY_DIR})
include_directories(${conky_includes})
set(test_srcs "")
set(test_srcs "test-conky.cc")
if(OS_LINUX)
set(test_srcs ${test_srcs} test-linux.cc)

63
tests/test-conky.cc Normal file
View File

@ -0,0 +1,63 @@
/*
*
* Conky, a system monitor, based on torsmo
*
* Any original torsmo code is licensed under the BSD license
*
* All code written since the fork of torsmo is licensed under the GPL
*
* Please see COPYING for details
*
* Copyright (c) 2005-2019 Brenden Matthews, Philip Kovacs, et. al.
* (see AUTHORS)
* All rights reserved.
*
* 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, either version 3 of the License, or
* (at your option) any later version.
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#include "catch2/catch.hpp"
#include "conky.h"
#include "lua-config.hh"
TEST_CASE("Expressions can be evaluated", "[evaluate]") {
state = std::make_unique<lua::state>();
conky::export_symbols(*state);
SECTION("Simple expressions without substitutions can be evaluated") {
constexpr int kMaxSize = 10;
const char input[kMaxSize] = "text";
char result[kMaxSize]{'\0'};
evaluate(input, result, kMaxSize);
REQUIRE(strncmp(input, result, kMaxSize) == 0);
}
SECTION("execs can be evaluated") {
constexpr int kMaxSize = 50;
const char input[kMaxSize] = "${exec echo text}";
char result[kMaxSize]{'\0'};
evaluate(input, result, kMaxSize);
REQUIRE(strncmp("text", result, kMaxSize) == 0);
}
SECTION("execp echo without other substitutions can be evaluated") {
constexpr int kMaxSize = 50;
const char input[kMaxSize] = "${execp echo text}";
char result[kMaxSize]{'\0'};
evaluate(input, result, kMaxSize);
REQUIRE(strncmp("text", result, kMaxSize) == 0);
}
}