Introducing macro attributes and Macro#current

This commit is contained in:
Matthias Koefferlein 2025-07-13 21:14:53 +02:00
parent cc796317a0
commit 87bc1a60e1
4 changed files with 159 additions and 0 deletions

View File

@ -555,6 +555,47 @@ Class<lym::Macro> decl_Macro ("lay", "Macro",
"\n"
"This method has been introduced in version 0.27.5.\n"
) +
gsi::method ("current", &lym::Macro::current,
"@brief Gets the macro currently executed\n"
"\n"
"This method can be used inside scripts running in that macro "
"to identify the currently running macro. It returns nil outside the "
"'run' context. The Macro object can be used to pass information "
"in and out of the script using macro attributes (see \\set_attribute and "
"related methods).\n"
"\n"
"This method has been introduced in version 0.30.3.\n"
) +
gsi::method ("set_attribute", &lym::Macro::set_attribute, gsi::arg ("name"), gsi::arg ("value"),
"@brief Gets the attribute with the given name\n"
"\n"
"Attributes are generic key/value pairs that can be added to the Macro object.\n"
"This allows passing information in and out of the macro run (see \\current).\n"
"\n"
"This method has been introduced in version 0.30.3.\n"
) +
gsi::method ("has_attribute", &lym::Macro::has_attribute, gsi::arg ("name"),
"@brief Gets a value indicating whether the Macro has an attribute with the given name\n"
"\n"
"See \\set_attribute for a description of Macro attributes.\n"
"\n"
"This method has been introduced in version 0.30.3.\n"
) +
gsi::method ("get_attribute", &lym::Macro::get_attribute, gsi::arg ("name"),
"@brief Gets the value of the attribute with the given name\n"
"\n"
"See \\set_attribute for a description of Macro attributes.\n"
"If no attribute is present with the given name, nil is returned.\n"
"\n"
"This method has been introduced in version 0.30.3.\n"
) +
gsi::method ("delete_attribute", &lym::Macro::delete_attribute, gsi::arg ("name"),
"@brief Deletes the attribute with the given name\n"
"\n"
"See \\set_attribute for a description of Macro attributes.\n"
"\n"
"This method has been introduced in version 0.30.3.\n"
) +
gsi::method ("save_to", &lym::Macro::save_to, gsi::arg ("path"),
"@brief Saves the macro to the given file\n"
"\n"

View File

@ -1065,8 +1065,48 @@ bool Macro::can_run () const
}
}
static Macro *sp_current_macro = 0;
Macro *
Macro::current ()
{
return sp_current_macro;
}
const tl::Variant &
Macro::get_attribute (const std::string &name) const
{
auto a = m_attributes.find (name);
if (a == m_attributes.end ()) {
static tl::Variant nil;
return nil;
} else {
return a->second;
}
}
bool
Macro::has_attribute (const std::string &name) const
{
return m_attributes.find (name) != m_attributes.end ();
}
void
Macro::set_attribute (const std::string &name, const tl::Variant &value)
{
m_attributes[name] = value;
}
void
Macro::delete_attribute (const std::string &name)
{
m_attributes.erase (name);
}
int Macro::run () const
{
sp_current_macro = const_cast<Macro *> (this);
if (tl::verbosity () >= 20) {
tl::log << tl::to_string (tr ("Running macro ")) << path ();
}
@ -1097,7 +1137,10 @@ int Macro::run () const
throw tl::Exception (tl::to_string (tr ("Can't run macro (no interpreter): ")) + path ());
}
sp_current_macro = 0;
} catch (tl::ExitException &ex) {
sp_current_macro = 0;
return ex.status ();
}

View File

@ -26,6 +26,7 @@
#include "lymCommon.h"
#include "tlObject.h"
#include "tlVariant.h"
#include <string>
#include <map>
@ -382,6 +383,40 @@ public:
*/
void install_doc () const;
/**
* @brief Gets the attribute with the given name
*
* If no such attribute exists, nil is returned.
* Setting and getting attributes is a way to pass information in and
* out of a script (also see "current")
*/
const tl::Variant &get_attribute (const std::string &name) const;
/**
* @brief Gets a value indicating whether there is an attribute with the given name
*/
bool has_attribute (const std::string &name) const;
/**
* @brief Sets the attribute with the given name
*/
void set_attribute (const std::string &name, const tl::Variant &value);
/**
* @brief Deletes the attribute with the given name
*/
void delete_attribute (const std::string &name);
/**
* @brief Gets the macro currently executing
*
* This method returns the Macro currently executing during "run".
* This provides a way to pass information between the script
* running inside the macro and the outside execution context
* by setting or getting attributes.
*/
static Macro *current ();
/**
* @brief Executes the macro
*
@ -642,6 +677,7 @@ private:
Interpreter m_interpreter;
std::string m_dsl_interpreter;
Format m_format;
std::map<std::string, tl::Variant> m_attributes;
void on_menu_needs_update ();
void on_changed ();

View File

@ -190,6 +190,45 @@ END
end
# attributes
def test_4
macro = RBA::Macro::new
assert_equal(macro.has_attribute("x"), false)
macro.set_attribute("x", 17)
assert_equal(macro.has_attribute("x"), true)
assert_equal(macro.get_attribute("x"), 17)
macro.delete_attribute("x")
assert_equal(macro.has_attribute("x"), false)
assert_equal(macro.get_attribute("x"), nil)
end
# passing and returning values
def test_5
macro = RBA::Macro::new
macro.interpreter = RBA::Macro::Ruby
macro.text = <<"END"
macro = RBA::Macro::current
x = macro.get_attribute("x")
macro.set_attribute("y", x + 1)
END
macro.set_attribute("x", 17)
assert_equal(macro.has_attribute("x"), true)
assert_equal(macro.has_attribute("y"), false)
macro.run
assert_equal(macro.has_attribute("x"), true)
assert_equal(macro.get_attribute("x"), 17)
assert_equal(macro.has_attribute("y"), true)
assert_equal(macro.get_attribute("y"), 18)
end
end
load("test_epilogue.rb")