Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Properly format errors, avoid erroring after already triggering an error #2188

Merged
merged 7 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .luacheckrc
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ globals = {
"luautf8",
"pl",
"fluent",
"executablePath",
"extendSilePath",
}
max_line_length = false
ignore = {
Expand Down
22 changes: 22 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ version = "0.15.7"
[dependencies.anyhow]
version = "1.0"

[dependencies.snafu]
version = "0.8"

[dependencies.clap]
version = "4.4"
optional = true
Expand Down
4 changes: 2 additions & 2 deletions core/sile.lua
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,10 @@ local function runEvals (evals, arg)
for _, snippet in ipairs(evals) do
local pId = SILE.traceStack:pushText(snippet)
local status, func = pcall(load, snippet)
if status then
if status and type(func) == "function" then
func()
else
SU.error(("Error parsing code provided in --%s snippet: %s"):format(arg, func))
SU.error(("Error parsing code provided in --%s snippet: %s"):format(arg, snippet))
end
SILE.traceStack:pop(pId)
end
Expand Down
2 changes: 1 addition & 1 deletion core/utilities/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ function utilities.error (message, isbug)
utilities.warn(message, isbug)
_skip_traceback_levels = 2
io.stderr:flush()
SILE.outputter:finish() -- Only really useful from the REPL but no harm in trying
SILE.outputter:finish()
SILE.scratch.caughterror = true
error("", 2)
end
Expand Down
13 changes: 7 additions & 6 deletions outputters/libtexpdf.lua
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,13 @@ end
function outputter._endHook (_) end

function outputter:finish ()
self:_ensureInit()
pdf.endpage()
self:runHooks("prefinish")
pdf.finish()
started = false
lastkey = nil
if started then
pdf.endpage()
self:runHooks("prefinish")
pdf.finish()
started = false
lastkey = nil
end
end

function outputter.getCursor (_)
Expand Down
1 change: 0 additions & 1 deletion rusile.rockspec.in
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,3 @@ build = {
"ru@PACKAGE_NAME@",
},
}

35 changes: 30 additions & 5 deletions src/bin/sile.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,42 @@
use sile::cli::Cli;

use snafu::prelude::*;

use clap::{CommandFactory, FromArgMatches};

use sile::cli::Cli;
use sile::Result;
#[derive(Snafu)]
enum Error {
#[snafu(display("{}", source))]
Args { source: clap::error::Error },

#[snafu(display("{}", source))]
Runtime { source: anyhow::Error },

#[snafu(display("{}", source))]
Version { source: anyhow::Error },
}

// Deeper error types are reported using the Debug trait, but we handle them via Snafu and the Display trait.
// So we delegate. c.f. https://github.com/shepmaster/snafu/issues/110
impl std::fmt::Debug for Error {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Display::fmt(self, fmt)
}
}

type Result<T, E = Error> = std::result::Result<T, E>;

fn main() -> Result<()> {
let version = option_env!("VERGEN_GIT_DESCRIBE").unwrap_or_else(|| env!("CARGO_PKG_VERSION"));
let version = version.replacen('-', ".r", 1);
let long_version = sile::version()?
let long_version = sile::version()
.context(VersionSnafu)?
.strip_prefix("SILE ")
.unwrap_or("")
.to_string();
let app = Cli::command().version(version).long_version(long_version);
let matches = app.get_matches();
let args = Cli::from_arg_matches(&matches).expect("Unable to parse arguments");
let args = Cli::from_arg_matches(&matches).context(ArgsSnafu)?;
sile::run(
args.input,
args.backend,
Expand All @@ -29,6 +53,7 @@ fn main() -> Result<()> {
args.r#use,
args.quiet,
args.traceback,
)?;
)
.context(RuntimeSnafu)?;
Ok(())
}
3 changes: 2 additions & 1 deletion src/embed.rs.in
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ extern "C-unwind" {
/// Register a Lua function in the loaders/searchers table to return C modules linked into the CLI
/// binary and another to return embedded Lua resources as Lua modules. See discussion in mlua:
/// https://github.com/khvzak/mlua/discussions/322
pub fn inject_embedded_loaders(lua: &Lua) {
pub fn inject_embedded_loaders(lua: Lua) -> crate::Result<Lua> {
let package: LuaTable = lua.globals().get("package").unwrap();
let loaders: LuaTable = match package.get("loaders").unwrap() {
LuaValue::Table(loaders) => loaders,
Expand Down Expand Up @@ -164,4 +164,5 @@ pub fn inject_embedded_loaders(lua: &Lua) {
})
.unwrap();
loaders.push(embedded_ftl_loader).unwrap();
Ok(lua)
}
55 changes: 30 additions & 25 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
// rust-embed include attributes have issues with lots of matches...
#![recursion_limit = "2048"]

use mlua::prelude::*;

#[cfg(not(feature = "static"))]
use mlua::chunk;
use mlua::prelude::*;
use std::{env, path::PathBuf};
use std::env;
use std::path::PathBuf;

#[cfg(feature = "cli")]
pub mod cli;

Expand All @@ -16,29 +19,30 @@ pub mod types;
pub type Result<T> = anyhow::Result<T>;

pub fn start_luavm() -> crate::Result<Lua> {
let lua = unsafe { Lua::unsafe_new() };
let mut lua = unsafe { Lua::unsafe_new() };
#[cfg(feature = "static")]
crate::embed::inject_embedded_loaders(&lua);
inject_paths(&lua);
load_sile(&lua);
inject_version(&lua);
{
lua = embed::inject_embedded_loaders(lua)?;
}
lua = inject_paths(lua)?;
lua = load_sile(lua)?;
lua = inject_version(lua)?;
Ok(lua)
}

pub fn inject_paths(lua: &Lua) {
pub fn inject_paths(lua: Lua) -> crate::Result<Lua> {
#[cfg(feature = "static")]
lua.load(r#"require("core.pathsetup")"#)
.set_name("relative pathsetup loader")
.exec()
.unwrap();
.exec()?;
#[cfg(not(feature = "static"))]
{
let datadir = env!("CONFIGURE_DATADIR").to_string();
let sile_path = match env::var("SILE_PATH") {
Ok(val) => format!("{datadir};{val}"),
Err(_) => datadir,
};
let sile_path: LuaString = lua.create_string(&sile_path).unwrap();
let sile_path: LuaString = lua.create_string(&sile_path)?;
lua.load(chunk! {
local status
for path in string.gmatch($sile_path, "[^;]+") do
Expand All @@ -50,9 +54,9 @@ pub fn inject_paths(lua: &Lua) {
end
})
.set_name("hard coded pathsetup loader")
.exec()
.unwrap();
.exec()?;
}
Ok(lua)
}

pub fn get_rusile_exports(lua: &Lua) -> LuaResult<LuaTable> {
Expand All @@ -62,28 +66,29 @@ pub fn get_rusile_exports(lua: &Lua) -> LuaResult<LuaTable> {
Ok(exports)
}

fn setenv(key: String, value: String) -> LuaResult<()> {
fn setenv(key: String, value: String) {
env::set_var(key, value);
Ok(())
}

pub fn inject_version(lua: &Lua) {
let sile: LuaTable = lua.globals().get("SILE").unwrap();
let mut full_version: String = sile.get("full_version").unwrap();
pub fn inject_version(lua: Lua) -> crate::Result<Lua> {
let sile: LuaTable = lua.globals().get("SILE")?;
let mut full_version: String = sile.get("full_version")?;
full_version.push_str(" [Rust]");
sile.set("full_version", full_version).unwrap();
sile.set("full_version", full_version)?;
Ok(lua)
}

pub fn load_sile(lua: &Lua) {
let entry: LuaString = lua.create_string("core.sile").unwrap();
let require: LuaFunction = lua.globals().get("require").unwrap();
require.call::<LuaTable>(entry).unwrap();
pub fn load_sile(lua: Lua) -> crate::Result<Lua> {
let entry: LuaString = lua.create_string("core.sile")?;
let require: LuaFunction = lua.globals().get("require")?;
require.call::<LuaTable>(entry)?;
Ok(lua)
}

pub fn version() -> crate::Result<String> {
let lua = start_luavm()?;
let sile: LuaTable = lua.globals().get("SILE").unwrap();
let full_version: String = sile.get("full_version").unwrap();
let sile: LuaTable = lua.globals().get("SILE")?;
let full_version: String = sile.get("full_version")?;
Ok(full_version)
}

Expand Down
Loading