A character written in the ^...^ mnemonic form -- ^oe^, ^zz^, ^hello^ --
used to kill ktext outright: no message, no output, and an exit status
that looked like a crash because it was one. Only the forms that happen
to spell hexadecimal digits escaped, and they were right by luck rather
than by reading. Any caret form that names no character is now a located
error that quotes what was written.
A klammer may now sit inside square brackets and braces as it already
could inside parentheses, and may be followed by the punctuation that
ends a sentence: [@i word@], {@b word@}, @i word@'s. The rule is a fixed
list of characters, because none of them can occur inside a klammer name
and so none of them is ambiguous next to a delimiter. A letter still
cannot: "x@" is the named closing delimiter, so a letter before "@" has
two readings and no rule can separate them.
The abbreviations an author writes -- the hyphen form @i-word, a klammer
glued to its neighbouring punctuation -- are now recognised as author
conveniences only. They are not applied to @@ definitions or @@@ system
commands, which are written by someone who needs no such shorthand and
whose forms are already whole.
Also fixed, each of them silent: an exported shell function in the
environment broke every @eval in the document; a line break written with
@nl was destroyed when it passed through a klammer that generates a
table, printing as \textbackslash{}newline in the finished PDF; and
"kdesc --coverage" shortened its file column by comparing the spelling of
a path rather than the path, so a klammer set reached by a symbolic link
showed a full path where its neighbours showed a short one.
New in the distribution: ref/, a small klammerset that describes the
Klammermachine's own tables in Klammertext. It currently provides the
character tables -- the diacritics and the extended Latin letters -- as
klammers that render to any target, so the documentation of what can be
written cannot drift from what the machine accepts. It is early, and
will grow.
The Klammertext taxonomy now has a section on targets, describes the
@@@klammerset system command alongside the other three, and states the
precedence of "^" -- what a caret means before a letter, a digit, a
punctuation character, and a quote, in one ordered list.
(from dev 6594c7ff8c1f)
90 lines
4.6 KiB
C++
90 lines
4.6 KiB
C++
#pragma once
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <filesystem>
|
|
#include <functional>
|
|
|
|
namespace fs = std::filesystem;
|
|
|
|
std::string file_basename(const std::string& filename);
|
|
std::string extension(const std::string& filename);
|
|
std::string file_directory(const std::string& filename);
|
|
std::string absolute_pathname(const std::string& filename, const std::string& base="");
|
|
std::string relative_pathname(const std::string& filename);
|
|
std::string relative_pathname(const std::string& filename, const std::string& base);
|
|
|
|
fs::path relative_to_cwd(const fs::path& input);
|
|
|
|
bool file_exists(const std::string& pathname, bool error_if_not=false, bool is_directory=false);
|
|
|
|
// Text to its lines, and a file to (its whole text, its lines). These
|
|
// moved here from katom.{h,cpp} on 2026-09-02: neither produces a katom,
|
|
// and the second OPENS A FILE, so by the test in katomize.h -- does a
|
|
// character stream enter? -- they were in the wrong place. They are read
|
|
// almost exclusively as katomize_lines(line_split(text), source), which is
|
|
// what kept them next to katomization for so long; adjacency at the call
|
|
// site is not membership.
|
|
std::vector<std::string> line_split(const std::string& s);
|
|
std::pair<std::string, std::vector<std::string>> line_split(const fs::path& pathname);
|
|
|
|
// Filenames may contain spaces. A filename LIST in a flat string or an
|
|
// argument vector is separated by a standalone "/" token (whitespace on both
|
|
// sides; never a legal input filename -- "/" alone is the root directory).
|
|
// Without a separator, whitespace-split tokens that do not name existing
|
|
// files are greedily rejoined with their neighbors into names that do (the
|
|
// rescue is announced). A leading "~/" (or bare "~") expands to $HOME.
|
|
std::string expand_tilde(const std::string& path);
|
|
std::vector<std::string> group_filename_tokens(
|
|
const std::vector<std::string>& tokens, const std::string& base_dir="");
|
|
std::vector<std::string> resolve_filename_list(
|
|
const std::string& text, const std::string& base_dir="");
|
|
std::string string_from_file(const std::string& pathname, bool strip_surrounding_whitespace=false);
|
|
void string_to_file(const std::string& pathname, std::string contents);
|
|
std::vector<std::string> get_files_in_directory(const std::string& dir);
|
|
std::string find_file(const std::string& basename, std::vector<std::string> search_path,
|
|
bool error_if_not_found=true);
|
|
|
|
std::vector<fs::path>
|
|
find_file_recursive(const fs::path& root, const std::string& filename,
|
|
bool only_one=true); //, Locator loc=Locator());
|
|
std::vector<fs::path>
|
|
find_file_from_roots(const std::vector<std::string>& roots, const std::string& filename, bool only_one);
|
|
|
|
fs::path klammertext_filename(
|
|
const std::string& basename, bool error_if_missing=true, bool make_directory_if_missing=false);
|
|
std::vector<std::string> sks_dirs();
|
|
std::vector<std::string> get_sks_directories(const std::string& s, bool include_argument=true);
|
|
std::string cache_directory(const std::string& subdirectory, std::string parent_directory="");
|
|
std::time_t to_time_t(const fs::file_time_type& ftime);
|
|
bool in_modification_order(std::string filename1, std::string filename2);
|
|
void write_to_cache(const std::string& cache_dir, const std::string& basename, const std::string& text);
|
|
std::string read_from_cache(const std::string& cache_dir, const std::string& basename);
|
|
bool cache_requires_update(const std::string& cache_dir, const std::string& file_to_cache, const std::string& basename);
|
|
|
|
std::vector<fs::path> pathnames_with_extension(
|
|
const fs::path& dir, const std::string extension
|
|
);
|
|
//std::string find_file(const fs::path& root, const std::string& name);
|
|
std::vector<std::string> find_files_with_extension(
|
|
const fs::path& root, const std::string& ext, bool case_insensitive=false);
|
|
std::string combine_files(
|
|
const std::vector<std::string>& filenames,
|
|
const std::string& prolog="", const std::string& epilog="",
|
|
const std::function <std::string(std::string)>& processor = nullptr);
|
|
|
|
bool files_differ(const fs::path& p1,
|
|
const fs::path& p2,
|
|
std::size_t buffer_size = 1 << 16); // 64 KiB
|
|
|
|
// Copy a single file with an explicit binary stream (NOT std::filesystem
|
|
// copy_file/copy), forcing the destination world-readable. Required for output
|
|
// onto Apple `container` virtiofs mounts — see the definition in file.cpp.
|
|
void copy_file_stream(const fs::path& src, const fs::path& dst);
|
|
|
|
void copy_preserving_basename(
|
|
const std::vector<std::string>& filenames, const std::string& output_directory,
|
|
const std::string& link_directory);
|
|
|
|
fs::path resolve_relative_to(const fs::path& relative, const fs::path& base=std::filesystem::current_path());
|