Files
klammertext/mac/file.h
T
ack 830b19394d Klammertext runs natively on Windows; a Windows source-install guide; the bundled sh for @eval :shell
Assembled from klammertext-dev f344a37d772c. The commands, the library,
the Standard Klammer Set, the reflection klammerset and the Python
binding build and run natively on Windows (MSYS2 UCRT64 gcc, python.org
Python), and both test tiers pass there. doc/install/windows_source_install.md
is the fifth install guide: a source install parallel to the Linux and
macOS ones, verified by following it on a pristine Windows 11.

Behaviour on every system: paths Klammertext prints use forward slashes;
output is LF; the command line is UTF-8 on Windows; @eval :shell is a
POSIX shell command everywhere -- on Windows it runs the sh Klammertext
ships, BusyBox for Windows (win/busybox/, GPLv2, with its licence and the
source pointer). KLAMMERTEXT_FONTS and KLAMMERTEXT_KLAMMERSETS are lists in
the system's PATH convention (';' on Windows). On Linux and macOS nothing
observable changes.
2026-09-25 00:33:26 +02:00

113 lines
5.8 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);
// The separator of a directory list in an environment variable
// (KLAMMERTEXT_FONTS, KLAMMERTEXT_KLAMMERSETS): ';' on Windows, where a drive
// letter puts a colon inside every absolute path, ':' everywhere else -- the
// convention of PATH on each system.
#ifdef _WIN32
constexpr char path_list_separator = ';';
#else
constexpr char path_list_separator = ':';
#endif
// The user's home directory as the system names it: HOME, and on Windows
// USERPROFILE when HOME is unset (a plain PowerShell or cmd sets no HOME;
// an MSYS2 shell does). Empty when neither is set.
std::string home_directory();
// The first PROGRAM on PATH (split on path_list_separator; on Windows the
// name also tried with ".exe"), or "" when none: what "which" answers, without
// spawning a shell -- on Windows popen()'s cmd.exe has no "which".
std::string find_in_path(const std::string& program);
// The directories listed in an environment variable, split on
// path_list_separator, empty entries dropped; DEFAULT_SUBDIR under the home
// directory when the variable is unset or empty.
std::vector<std::string> directory_list(const char* variable, const std::string& default_subdir);
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 symbolic_klammertext_filename(std::string filename);
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());