2012-10-21 14:52:34 +02:00
|
|
|
/*
|
2023-07-05 22:10:13 +02:00
|
|
|
** Copyright (C) 2022-2023 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
2012-10-21 14:52:34 +02:00
|
|
|
**
|
|
|
|
** 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, 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, write to the Free Software Foundation,
|
|
|
|
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
**
|
|
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
|
2022-11-16 22:26:29 +01:00
|
|
|
#include "mu-script.hh"
|
2023-07-05 22:10:13 +02:00
|
|
|
#include "mu/mu-options.hh"
|
|
|
|
#include "utils/mu-utils.hh"
|
|
|
|
#include "utils/mu-option.hh"
|
|
|
|
|
|
|
|
#include <fstream>
|
|
|
|
#include <iostream>
|
2020-02-17 20:45:21 +01:00
|
|
|
|
2022-11-16 22:26:29 +01:00
|
|
|
#ifdef BUILD_GUILE
|
2020-02-17 20:45:21 +01:00
|
|
|
#pragma GCC diagnostic push
|
|
|
|
#pragma GCC diagnostic ignored "-Wredundant-decls"
|
2012-10-21 14:52:34 +02:00
|
|
|
#include <libguile.h>
|
2020-02-17 20:45:21 +01:00
|
|
|
#pragma GCC diagnostic pop
|
2012-10-21 14:52:34 +02:00
|
|
|
#endif /*BUILD_GUILE*/
|
|
|
|
|
2022-11-16 22:26:29 +01:00
|
|
|
using namespace Mu;
|
2012-10-21 14:52:34 +02:00
|
|
|
|
2022-11-16 22:26:29 +01:00
|
|
|
static std::string
|
|
|
|
get_name(const std::string& path)
|
2012-10-21 14:52:34 +02:00
|
|
|
{
|
2022-11-16 22:26:29 +01:00
|
|
|
auto pos = path.find_last_of("/");
|
|
|
|
if (pos == std::string::npos)
|
|
|
|
return path;
|
2012-10-21 14:52:34 +02:00
|
|
|
|
2022-11-16 22:26:29 +01:00
|
|
|
auto name = path.substr(pos + 1);
|
2012-10-21 14:52:34 +02:00
|
|
|
|
2022-11-16 22:26:29 +01:00
|
|
|
pos = name.find_last_of(".");
|
|
|
|
if (pos == std::string::npos)
|
|
|
|
return name;
|
2012-10-21 14:52:34 +02:00
|
|
|
|
2022-11-16 22:26:29 +01:00
|
|
|
return name.substr(0, pos);
|
2012-10-22 22:16:01 +02:00
|
|
|
}
|
|
|
|
|
2012-10-21 14:52:34 +02:00
|
|
|
|
2022-11-16 22:26:29 +01:00
|
|
|
static Mu::Option<Mu::ScriptInfo>
|
|
|
|
get_info(std::string&& path, const std::string& prefix)
|
2012-10-22 22:16:01 +02:00
|
|
|
{
|
2022-11-16 22:26:29 +01:00
|
|
|
std::ifstream file{path};
|
|
|
|
if (!file.is_open()) {
|
2023-07-05 22:10:13 +02:00
|
|
|
mu_warning ("failed to open {}", path);
|
2022-11-16 22:26:29 +01:00
|
|
|
return Nothing;
|
2012-12-23 14:24:52 +01:00
|
|
|
}
|
|
|
|
|
2022-11-16 22:26:29 +01:00
|
|
|
Mu::ScriptInfo info{};
|
|
|
|
info.path = path;
|
|
|
|
info.name = get_name(path);
|
2012-12-23 14:24:52 +01:00
|
|
|
|
2022-11-16 22:26:29 +01:00
|
|
|
std::string line;
|
|
|
|
while (std::getline(file, line)) {
|
2012-12-23 14:24:52 +01:00
|
|
|
|
2022-11-16 22:26:29 +01:00
|
|
|
if (line.find(prefix) != 0)
|
2012-10-22 22:16:01 +02:00
|
|
|
continue;
|
|
|
|
|
2022-11-16 22:26:29 +01:00
|
|
|
line = line.substr(prefix.length());
|
2012-10-21 16:20:20 +02:00
|
|
|
|
2022-11-16 22:26:29 +01:00
|
|
|
if (info.oneline.empty())
|
|
|
|
info.oneline = line;
|
|
|
|
else
|
|
|
|
info.description += line;
|
2012-10-21 14:52:34 +02:00
|
|
|
}
|
|
|
|
|
2022-11-16 22:26:29 +01:00
|
|
|
// std::cerr << "ONELINE: " << info.oneline << '\n';
|
|
|
|
// std::cerr << "DESCR : " << info.description << '\n';
|
2012-10-21 14:52:34 +02:00
|
|
|
|
2022-11-16 22:26:29 +01:00
|
|
|
return info;
|
2012-10-21 14:52:34 +02:00
|
|
|
}
|
|
|
|
|
2022-05-28 22:58:16 +02:00
|
|
|
|
|
|
|
|
2022-11-16 22:26:29 +01:00
|
|
|
static void
|
|
|
|
script_infos_in_dir(const std::string& scriptdir, Mu::ScriptInfos& infos)
|
2022-05-19 20:06:43 +02:00
|
|
|
{
|
2022-11-16 22:26:29 +01:00
|
|
|
DIR *dir = opendir(scriptdir.c_str());
|
|
|
|
if (!dir) {
|
2023-07-05 22:10:13 +02:00
|
|
|
mu_debug("failed to open '{}': {}", scriptdir,
|
2022-11-16 22:26:29 +01:00
|
|
|
g_strerror(errno));
|
|
|
|
return;
|
|
|
|
}
|
2022-05-19 20:06:43 +02:00
|
|
|
|
2022-11-16 22:26:29 +01:00
|
|
|
const std::string ext{".scm"};
|
2022-05-19 20:06:43 +02:00
|
|
|
|
2022-11-16 22:26:29 +01:00
|
|
|
struct dirent *dentry;
|
|
|
|
while ((dentry = readdir(dir))) {
|
2022-05-19 20:06:43 +02:00
|
|
|
|
2022-11-16 22:26:29 +01:00
|
|
|
if (!g_str_has_suffix(dentry->d_name, ext.c_str()))
|
|
|
|
continue;
|
2022-05-19 20:06:43 +02:00
|
|
|
|
2022-11-16 22:26:29 +01:00
|
|
|
auto&& info = get_info(scriptdir + "/" + dentry->d_name, ";; INFO: ");
|
|
|
|
if (!info)
|
|
|
|
continue;
|
2022-05-19 20:06:43 +02:00
|
|
|
|
2022-11-16 22:26:29 +01:00
|
|
|
infos.emplace_back(std::move(*info));
|
2022-05-19 20:06:43 +02:00
|
|
|
}
|
|
|
|
|
2022-11-16 22:26:29 +01:00
|
|
|
closedir(dir); /* ignore error checking... */
|
2022-05-19 20:06:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-11-16 22:26:29 +01:00
|
|
|
Mu::ScriptInfos
|
|
|
|
Mu::script_infos(const Mu::ScriptPaths& paths)
|
2012-10-21 14:52:34 +02:00
|
|
|
{
|
2022-11-16 22:26:29 +01:00
|
|
|
/* create a list of names, paths */
|
|
|
|
ScriptInfos infos;
|
|
|
|
for (auto&& dir: paths) {
|
|
|
|
script_infos_in_dir(dir, infos);
|
2017-11-05 12:12:41 +01:00
|
|
|
}
|
|
|
|
|
2022-11-16 22:26:29 +01:00
|
|
|
std::sort(infos.begin(), infos.end(), [](auto&& i1, auto&& i2) {
|
|
|
|
return i1.name < i2.name;
|
|
|
|
});
|
|
|
|
|
|
|
|
return infos;
|
|
|
|
}
|
|
|
|
|
|
|
|
Result<void>
|
|
|
|
Mu::run_script(const std::string& path,
|
|
|
|
const std::vector<std::string>& args)
|
|
|
|
{
|
|
|
|
#ifndef BUILD_GUILE
|
|
|
|
return Err(Error::Code::Script,
|
|
|
|
"guile script support is not available");
|
|
|
|
#else
|
|
|
|
std::string mainargs;
|
|
|
|
for (auto&& arg: args)
|
2023-07-07 09:47:03 +02:00
|
|
|
mainargs += mu_format("{}\"{}\"", mainargs.empty() ? "" : " ", arg);
|
|
|
|
auto expr = mu_format("(main '(\"{}\" {}))", get_name(path), mainargs);
|
2022-11-16 22:26:29 +01:00
|
|
|
|
|
|
|
std::vector<const char*> argv = {
|
|
|
|
GUILE_BINARY,
|
|
|
|
"-l", path.c_str(),
|
|
|
|
"-c", expr.c_str(),
|
|
|
|
};
|
|
|
|
|
|
|
|
/* does not return */
|
|
|
|
scm_boot_guile(argv.size(), const_cast<char**>(argv.data()),
|
|
|
|
[](void *closure, int argc, char **argv) {
|
|
|
|
scm_shell(argc, argv);
|
|
|
|
}, NULL);
|
|
|
|
|
|
|
|
return Ok();
|
|
|
|
#endif /*BUILD_GUILE*/
|
2012-10-21 14:52:34 +02:00
|
|
|
}
|