Filenames with spaces; output beside the input file; warning fixes (from dev c08eb1bbfa4c)

- Filenames may contain spaces: quote on the command line; filename
  lists use a standalone "/" separator; unseparated names that do not
  exist are rejoined into names that do (announced); leading ~ expands.
- Without -o, output is written to the input file's directory; -o fully
  specifies the output directory and basename.
- "Word not parsed" warnings now appear without -v, only for text that
  survives removal, with correct line numbers.
- New tst/filename_test.sh regression suite.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-26 23:22:59 +02:00
parent d9c98ac86d
commit fd9a370af7
21 changed files with 430 additions and 34 deletions

View File

@@ -47,10 +47,14 @@ Document_class::Document_class(Machine& machine) : Klammer_base(machine)
m_logo = get("logo");
m_text = get("text");
m_files = word_split(get("files"));
// Filename lists: standalone-"/" separation, existence rescue for
// spaces, ~ expansion (resolve_filename_list in mac/file.cpp); the
// existence checks resolve relative names against the input directory,
// as parse_input_filename() will.
m_files = resolve_filename_list(get("files"), get("K_input_dir"));
m_css_text = get("css_text");
m_css_filenames = word_split(get("css_files"));
m_css_filenames = resolve_filename_list(get("css_files"), get("K_input_dir"));
m_include_sks_css = strbool(get("include_sks_css"), loc);
frame_background_color = get("frame_background_color");
frame_text_color = get("frame_text_color");
@@ -58,7 +62,7 @@ Document_class::Document_class(Machine& machine) : Klammer_base(machine)
nav_text_color = get("nav_text_color");
js_text = get("js_text");
m_js_filenames = word_split(get("js_files"));
m_js_filenames = resolve_filename_list(get("js_files"), get("K_input_dir"));
m_include_sks_js = strbool(get("include_sks_js"), loc);
// font_dirs = word_split(get("font_dirs"));
@@ -99,7 +103,7 @@ Document_class::Document_class(Machine& machine) : Klammer_base(machine)
//use_pages_dir = strbool(get("use_pages_dir"), loc);
// m_toc_only = strbool(get("K_toc_only"), loc);
m_kt_root_filename = get("K_input_filenames");
m_kt_root_filename = get("K_input_filename");
m_no_cache = !strbool(get("cache"), loc);
@@ -138,8 +142,20 @@ fs::path parse_input_filename(std::string s, std::string input_dir)
if (p.extension() != ".kt") {
p += ".kt";
}
if (!file_exists(p)) {
p = input_dir + "/kt/" + p.string();
if (p.is_absolute()) {
return p;
}
// A relative :files name resolves against the input file's directory
// (K_input_dir), so a document renders identically wherever ktext is
// run from; then the legacy kt/ subdirectory; a name found in neither
// is returned as given (cwd-relative) and errors downstream.
fs::path in_input_dir = fs::path(input_dir) / p;
if (file_exists(in_input_dir.string())) {
return in_input_dir;
}
fs::path in_kt_dir = fs::path(input_dir) / "kt" / p;
if (file_exists(in_kt_dir.string())) {
return in_kt_dir;
}
return p;
}