complition
This commit is contained in:
+35
-13
@@ -1,20 +1,24 @@
|
||||
//! Выполнение Lua-сценариев приложения.
|
||||
//!
|
||||
//! При запуске приложение выполняет [`STARTUP_SCRIPT`] из каталога [`SCRIPT_DIR`]
|
||||
//! При запуске приложение выполняет [`STARTUP_SCRIPT`] из каталога [`script_dir`]
|
||||
//! (см. [`ScriptEngine::run_startup`]). Скриптам доступны:
|
||||
//!
|
||||
//! * объект `app` — управление окном и редактором (методы [`AppApi`], вызываются
|
||||
//! через двоеточие: `app:next_tab()`);
|
||||
//! * функция `include(path)` — выполняет другой Lua-файл относительно [`SCRIPT_DIR`]
|
||||
//! * функция `include(path)` — выполняет другой Lua-файл относительно [`script_dir`]
|
||||
//! (или по абсолютному пути) в общем глобальном окружении;
|
||||
//! * стандартный `require`, который также ищет модули в [`SCRIPT_DIR`].
|
||||
//! * стандартный `require`, который также ищет модули в [`script_dir`].
|
||||
//!
|
||||
//! Каталог по умолчанию — текущий рабочий каталог. Его можно переопределить
|
||||
//! аргументом `--config <каталог>` при запуске приложения (см.
|
||||
//! [`parse_command_line`](crate::constants::parse_command_line)).
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use mlua::{Lua, Table};
|
||||
|
||||
use crate::api::{AppApi, TabInfo};
|
||||
use crate::constants::{SCRIPT_DIR, STARTUP_SCRIPT};
|
||||
use crate::constants::{STARTUP_SCRIPT, script_dir};
|
||||
|
||||
/// Вкладка превращается в Lua-таблицу `{ index = 0, title = "main.rs" }`.
|
||||
impl mlua::IntoLua for TabInfo {
|
||||
@@ -29,24 +33,40 @@ impl mlua::IntoLua for TabInfo {
|
||||
/// Движок Lua и состояние его глобального окружения.
|
||||
pub struct ScriptEngine {
|
||||
lua: Lua,
|
||||
/// Каталог, относительно которого ищутся `init.lua`, `include` и `require`.
|
||||
script_dir: PathBuf,
|
||||
}
|
||||
|
||||
impl ScriptEngine {
|
||||
/// Создаёт движок и публикует в нём API приложения.
|
||||
///
|
||||
/// Каталог сценариев берётся из [`script_dir`] (то есть из `--config`
|
||||
/// или текущего рабочего каталога).
|
||||
pub fn new(api: AppApi) -> mlua::Result<Self> {
|
||||
let engine = Self { lua: Lua::new() };
|
||||
Self::new_in(api, script_dir())
|
||||
}
|
||||
|
||||
/// Создаёт движок с явно заданным каталогом сценариев.
|
||||
///
|
||||
/// Полезно тестам и будущим режимам, где каталог конфигурации приходит
|
||||
/// не из глобального `--config`.
|
||||
pub fn new_in(api: AppApi, directory: impl AsRef<Path>) -> mlua::Result<Self> {
|
||||
let engine = Self {
|
||||
lua: Lua::new(),
|
||||
script_dir: directory.as_ref().to_path_buf(),
|
||||
};
|
||||
engine.expose_app_api(api)?;
|
||||
engine.configure_require()?;
|
||||
Ok(engine)
|
||||
}
|
||||
|
||||
/// Выполняет стартовый сценарий из [`SCRIPT_DIR`].
|
||||
/// Выполняет стартовый сценарий из каталога движка.
|
||||
///
|
||||
/// # Errors
|
||||
/// Возвращает ошибку, если файла нет, его не удалось прочитать или в нём
|
||||
/// есть синтаксическая/исполняемая ошибка.
|
||||
pub fn run_startup(&self) -> mlua::Result<()> {
|
||||
self.run_file(&script_path(STARTUP_SCRIPT))
|
||||
self.run_file(&script_path(&self.script_dir, STARTUP_SCRIPT))
|
||||
}
|
||||
|
||||
/// Выполняет Lua-файл в глобальном окружении движка.
|
||||
@@ -73,7 +93,7 @@ impl ScriptEngine {
|
||||
|
||||
if let Ok(package) = globals.get::<Table>("package") {
|
||||
let current: String = package.get("path").unwrap_or_default();
|
||||
let dir = SCRIPT_DIR;
|
||||
let dir = self.script_dir.display().to_string().replace('\\', "/");
|
||||
let extra = format!("{dir}/?.lua;{dir}/?/init.lua");
|
||||
let path = if current.is_empty() {
|
||||
extra
|
||||
@@ -85,10 +105,12 @@ impl ScriptEngine {
|
||||
|
||||
// include выполняет файл сразу, как dofile, но путь по умолчанию
|
||||
// отсчитывается от каталога сценариев, а не от cwd.
|
||||
let directory = self.script_dir.clone();
|
||||
globals.set(
|
||||
"include",
|
||||
self.lua
|
||||
.create_function(|lua, path: String| run_file(lua, &script_path(&path)))?,
|
||||
self.lua.create_function(move |lua, path: String| {
|
||||
run_file(lua, &script_path(&directory, &path))
|
||||
})?,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
@@ -96,13 +118,13 @@ impl ScriptEngine {
|
||||
}
|
||||
|
||||
/// Путь к файлу сценария: абсолютные пути используются как есть, остальные
|
||||
/// отсчитываются от [`SCRIPT_DIR`].
|
||||
fn script_path(path: &str) -> PathBuf {
|
||||
/// отсчитываются от каталога сценариев.
|
||||
fn script_path(directory: &Path, path: &str) -> PathBuf {
|
||||
let path = Path::new(path);
|
||||
if path.is_absolute() {
|
||||
path.to_path_buf()
|
||||
} else {
|
||||
Path::new(SCRIPT_DIR).join(path)
|
||||
directory.join(path)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user