From 36a9c23bf12c183135bd5818977a6a7c6221074d Mon Sep 17 00:00:00 2001 From: nmaguiar Date: Thu, 3 Sep 2026 05:41:50 +0100 Subject: [PATCH 01/17] docs(cli): update documentation and console utilities - Update cli.md and index.md - Add console.md - Refactor genSB.js and openafconsole.js for better console integration --- docs/cli.md | 90 +++++++++++++++++++++++++++++++++++++---- docs/console.md | 99 +++++++++++++++++++++++++++++++++++++++++++++ docs/index.md | 3 +- js/genSB.js | 20 ++++----- js/openafconsole.js | 9 +++-- 5 files changed, 198 insertions(+), 23 deletions(-) create mode 100644 docs/console.md diff --git a/docs/cli.md b/docs/cli.md index b4c7a6658..d34f5a619 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -47,9 +47,9 @@ With no arguments, OpenAF launches the interactive GUI if a desktop is available | Flag | Argument | Description | |:-----|:---------|:-------------| -| `--install` | – | Generate wrapper scripts (`oaf`, `opack`, `ojob`, `oafp`, `pyoaf`, etc.) in the current directory. | +| `--install [args=] [--noopacks]` | see description | Generate wrapper scripts (`oaf`, `opack`, `ojob`, `oafp`, `pyoaf`, etc.) in the current directory. `args=` embeds extra JVM arguments (e.g. `-Xmx2g`) into every generated launcher and saves them to `.openaf-javaargs`. `--noopacks` skips auto-installing any `.opack` files found in the current directory during install. | | `--check` | – | Check if this is the latest released version. | -| `--update` | – | Update OpenAF to the latest version. | +| `--update [--force]` | – | Update OpenAF to the latest version (downloads a new `openaf.jar`, backs up the old one as `openaf.jar.old`, then re-`--repack`s). `--force` re-downloads even if already on the latest version. Disabled when the `noHomeComms` flag is set. See [Update process](#update-process) below. | | `--repack` | – | Repack `openaf.jar` for faster startup. | | `--console` | – | Launch the interactive OpenAF REPL console. | @@ -61,7 +61,7 @@ With no arguments, OpenAF launches the interactive GUI if a desktop is available | `--opack` | – | Execute the opack package-manager CLI. Use with `-e` to pass sub-commands. | | `--py ` | script path | Run a Python script with OpenAF bridge support (loads `pyoaf.js`). | | `--oafpy` | – | Emit the `oaf.py` bridge module for use from standalone Python scripts. See [python.md](./python.md). | -| `--sb ` | file path | Generate or prepend an OpenAF/oJob shebang to a JS or YAML file. | +| `--sb ` | file path | Generate or prepend an OpenAF/oJob/oafp shebang line, chosen by the file's extension. See [Shebang scripts](#shebang-scripts) below. | | `--bashcompletion ` | arg | Generate bash completion script. | | `--zshcompletion ` | arg | Generate zsh completion script. | @@ -76,10 +76,83 @@ After running `--install`, the following wrapper scripts are created in the inst | `opack` | `openaf --opack -e "$ARGS"` | oPack package manager CLI. | | `oafp` | `openaf -c "load(getOpenAFJar()+'::js/oafp.js')" -e "$ARGS"` | OpenAF data processor. See [oafp.md](./oafp.md). | | `pyoaf` | `openaf --py -e "$ARGS"` | Python runner. See [python.md](./python.md). | -| `oafc` / `openaf-console` | `openaf --console` | Interactive REPL. | -| `odoc` | `openaf -c "load(getOpenAFJar()+'::js/odoc.js')" -e "$ARGS"` | Documentation CLI. See [odoc.md](./odoc.md). | -| `update` | `openaf --update` | Update shortcut. | -| `oaf-sb` / `openaf-sb` / `ojob-sb` / `oafp-sb` | `openaf --sb` | Shebang generators. | +| `oafc` / `openaf-console` | `openaf --console` | Interactive REPL. See [console.md](./console.md). | +| `odoc` | `openaf -c "load(getOpenAFJar()+'::js/odoc.js')" -e "$ARGS"` | Documentation CLI. See [odoc.md](./odoc.md). Note: unlike the other rows in this table, `odoc` is not generated by `--install`/`genScripts.js` — it ships via the odoc tooling itself, so it may need to be aliased manually if not already on your `PATH`. | +| `update` / `update.sh` / `update.bat` | `openaf --update` (plus a JRE refresh step) | Update shortcut. See [Update process](#update-process) below. | +| `oaf-sb` / `openaf-sb` / `ojob-sb` / `oafp-sb` | `openaf -f "$SCRIPT" -e "$ARGS"` (resp. `--ojob`/oafp variants) | Shebang-line interpreters, invoked by the OS when a script starting with `#!/usr/bin/env oaf-sb` (etc.) is executed directly. See [Shebang scripts](#shebang-scripts) below. | + +## Shebang scripts + +`--sb ` turns a plain file into a self-executing script by prepending an interpreter line, +similar to `#!/usr/bin/env python3` for Python. It picks the right interpreter from the file +extension: + +| File type | Shebang line added | Runtime interpreter | +|:----------|:--------------------|:---------------------| +| `.js` | `#!/usr/bin/env /oaf-sb` | `openaf -f "$SCRIPT" -e "$ARGS"` | +| `.yaml` / `.yml` / `.json` | `#!/usr/bin/env /ojob-sb` | `openaf --ojob -e "$SCRIPT $ARGS"` | +| anything else (including no extension) | `#!/usr/bin/env -S /oafp-sb` | `openaf -c "load(...oafp.js)" -e "_shebang=true $OAFP_ARGS $ARGS"` | + +(As of this writing, the extension check only applied when prepending to an *existing* file — +generating a brand-new `.yaml`/`.json`/non-`.js` file via `--sb` incorrectly fell back to the +`.js`/`oaf-sb` template. This has been fixed in `js/genSB.js` so the extension is honored whether +or not the file already exists.) + +If the target file doesn't exist, `--sb` creates it with just the shebang line (plus, for `.js` +files, a starter `var params = processExpr(" ");`). If it exists and doesn't already start with +`#!`, the shebang line is prepended to its current contents. Running `--sb` again on a file that +already has a shebang is a no-op (it logs a warning and leaves the file untouched). + +```bash +# Generate an OpenAF (.js) shebang script and make it executable +openaf --sb hello.js +chmod +x hello.js +./hello.js abc=123 xyz=aaa +``` + +Inside `hello.js`, `oaf-sb` sets `__expr` from the trailing command-line tokens, so +`var params = processExpr(" ");` yields `{ abc: "123", xyz: "aaa" }` — the same mechanism `ojob` +and `oafp` use to parse `key=value` arguments. + +```bash +# Generate an oJob shebang file and run it directly +openaf --sb myjob.yaml +chmod +x myjob.yaml +./myjob.yaml env=prod +``` + +Once generated, these files no longer need the `openaf`/`ojob`/`oafp` command at all — the shebang +line resolves `oaf-sb`/`ojob-sb`/`oafp-sb` from the same directory as the other generated wrapper +scripts (via `/usr/bin/env`), so the install directory must be on `PATH` (or referenced with an +absolute path) for this to work. + +## Update process + +`--update` (and the generated `update`/`update.sh`/`update.bat` wrapper) checks the OpenAF home +servers for a newer release, and if one is found (or `--force` is given): + +1. Backs up the *current* `openaf.jar` to `openaf.jar.old` next to the install. +2. Downloads the new release in two forms: a plain build and a pre-`--repack`ed one. +3. Installs the pre-repacked build as the new `openaf.jar` (keeping the plain build as + `openaf.jar.orig`, which a later `--repack` needs if modules are ever added/excluded), then + restarts with `--repack` for fast startup. + +The `update.sh`/`update.bat` wrapper additionally refreshes the bundled JRE before touching the +jar: it runs `./ojob ojob.io/oaf/javaUpdate`, and if that produces a `jre.tgz` (Unix) or `jre.zip` +(Windows), the old `jre/` directory is moved to `jre.old` and the archive is extracted as the new +`jre/`. This step — and `--update`/`--check` in general — is skipped entirely when the `noHomeComms` +flag is set (e.g. restricted/offline installs), which is also why `--install` won't generate +`update.sh`/`update.bat` at all in that mode. + +```bash +# Update in place +update +# or +openaf --update + +# Force re-download even if already current +openaf --update --force +``` ## Common usage examples @@ -118,4 +191,5 @@ openaf -v - [oafp.md](./oafp.md) — OpenAF data processor. - [opacks.md](./opacks.md) — oPack package manager. - [python.md](./python.md) — Python integration. -- [odoc.md](./odoc.md) — documentation engine. \ No newline at end of file +- [odoc.md](./odoc.md) — documentation engine. +- [console.md](./console.md) — interactive REPL commands, aliases, and profile/history files. \ No newline at end of file diff --git a/docs/console.md b/docs/console.md new file mode 100644 index 000000000..e70f39899 --- /dev/null +++ b/docs/console.md @@ -0,0 +1,99 @@ +# OpenAF Interactive Console (oafc / openaf-console) + +[Index](./index.md) | [CLI Reference](./cli.md) | [OpenAF Reference](./openaf.md) | [Flags](./openaf-flags.md) + +The interactive console is OpenAF's REPL: a line editor (with history, completion and multi-line +input) on top of the same JavaScript engine used to run scripts. Anything that isn't a built-in +console command is evaluated as OpenAF/JavaScript and, unless output has been turned off, the +result is printed. + +## Starting the console + +```bash +openaf --console # raw flag +oafc # generated wrapper (recommended) +openaf-console # generated wrapper (same as oafc) +``` + +All three are equivalent; `oafc`/`openaf-console` are thin wrapper scripts created by +`--install` (see [cli.md](./cli.md#generated-wrapper-commands)) that just run +`openaf --console "$@"`. + +On startup the console: +- Loads `.openaf-console_profile` from the user's home/OpenAF directory, if present, and runs its + contents as console commands (one per line) — useful for predefining aliases or DB connections. +- Loads/saves command history to `.openaf-console_history` in the same directory. +- Prints a version banner and, unless `noHomeComms` is set, checks for a newer OpenAF release. + +## Basic usage + +``` +$ oafc +openaf:1> print("Hello World!"); +Hello World! +openaf:2> 1 + 1 +2 +openaf:3> var db = new DB("org.h2.Driver", "jdbc:h2:mem:", "sa", "") +openaf:4> sql db select 1 as a, 2 as b +``` + +- Expressions that evaluate to a value (not just statements) have their result printed automatically. +- Multi-line input is supported by default (`multi` command toggles it) — an unbalanced brace/paren + keeps the prompt open for the next line. +- `Ctrl-C` / `Ctrl-D` behave as usual for exiting or interrupting. + +## Built-in commands + +These are reserved words handled directly by the console (anything else is treated as a script +command). Run `help` with no arguments inside the console to see this list live; `help ` +searches the same offline help database used by ``-documented functions (see +[odoc.md](./odoc.md)). + +| Command | Description | Example | +|:--------|:-------------|:--------| +| `help` | Show the help screen, or look up a term in the offline help database. | `help`, `help AF`, `help scope` | +| `exit` | Exit the console. | `exit` | +| `time` | Toggle timing of every command executed (default off). | `time` | +| `output` | Toggle printing of command results (default on). | `output` | +| `beautify` | Toggle beautified/pretty-printed output (default on). | `beautify` | +| `color` | Toggle ANSI colorized output (default on when the terminal supports ANSI); `color on`/`color off` set it explicitly. | `color`, `color off` | +| `desc` | Describe the available methods/properties of a class. | `desc AF` | +| `scope` | List the current JS scope, optionally filtered by a regexp. | `scope sha` | +| `alias` | Create (or list) an alias for a console command line. With no argument, lists current aliases. | `alias ola=print("hi");` | +| `watch` | With no argument, reports whether watch is active. `watch on` / `watch off` toggle it without changing the expression. `watch ` re-evaluates `` before every prompt. `watch ` live-refreshes ``'s output every `N` seconds until `q` is pressed. | `watch new Date();`, `watch 5 ow.server.getThreadsInfo()` | +| `pause` | Toggle pausing long output at the terminal height (default on). | `pause` | +| `table ` | Evaluate `` and render an array-of-maps result as an ASCII table. | `table listFiles(".")` | +| `tree` | With no argument, reports whether persistent tree rendering is active (default on). `tree on` / `tree off` switch all subsequent map/array output between tree and flat table view. `tree ` renders ``'s result as a tree once, without changing the persistent mode. | `tree off`, `tree myObj` | +| `view ` | Evaluate `` and render a map/array result as a tree (default) or flat table, depending on the `tree` setting. With no argument (or `on`/`off`), reports/toggles a separate persistent "view" mode instead. | `view myObj` | +| `sql ` | Run a `SELECT` over a `DB` object variable and print a table. | `sql db select * from t` | +| `dsql ` | Describe the columns a query would produce, without fetching rows. | `dsql db select * from t` | +| `esql ` | Execute a non-SELECT statement (INSERT/UPDATE/DDL) over a `DB` object. | `esql db update t set a=1` | +| `diff with[New\|Changes\|Full] ` | Show differences between two objects/variables; `with` shows just the diff, `withChanges` just changed keys, `withNew` diff+changes, `withFull` the complete merged view. | `diff a with b`, `diff a withChanges b` | +| `pin ` | Prepend `` to every subsequent command until an empty line is entered (or `pin` is invoked again). | `pin sql db` | +| `multi` | Toggle multi-line expression entry (default on). | `multi` | +| `edit` | Compose a command in `$EDITOR` (or `vi`); `edit last` / `edit history` reopen a previous command. | `edit last` | +| `clear` | Clear the screen. | `clear` | +| `reset` | Reset the terminal (Unix consoles only), useful after a program leaves it in a bad state. | `reset` | +| `purge` | Purge the entire command history. | `purge` | + +## Built-in aliases + +A few convenience aliases ship enabled by default (see `alias` with no arguments to list all +currently defined aliases, including any you add): + +| Alias | Expands to | Example | +|:------|:-----------|:--------| +| `opack ` | `oPack()` — run the opack manager without leaving the console. | `opack list` | +| `ojob [k=v ...]` | Runs the given oJob file, passing remaining tokens as arguments (via `processExpr`). | `ojob myjob.yaml env=prod` | +| `ojobio` | Shortcut for `oJobRunFile("ojob.io")`. | `ojobio` | +| `sh [command]` | Drop into (or run one command in) the underlying system shell. | `sh ls -la` | +| `encryptText` | Prompts for text and prints its encrypted form (see `askEncrypt`). | `encryptText` | + +Custom aliases are defined with `alias name=` and cannot reuse a reserved +word. Aliases persist only for the session unless recreated from `.openaf-console_profile`. + +## See also + +- [cli.md](./cli.md) — full `openaf`/`oaf` flag reference and generated wrapper scripts. +- [odoc.md](./odoc.md) — the offline help database used by `help `. +- [openaf-flags.md](./openaf-flags.md) — `noHomeComms` and other runtime flags. diff --git a/docs/index.md b/docs/index.md index 7838b21a7..a66f42bce 100644 --- a/docs/index.md +++ b/docs/index.md @@ -4,7 +4,8 @@ Core references and extended guides to build and operate oJobs and OpenAF soluti ## Getting Started - getting-started.md – Install, hello world, first oJob, and where to go next -- cli.md – `openaf`/`oaf` command-line flags and generated wrapper scripts (`ojob`, `opack`, `oafp`, `pyoaf`, …) +- cli.md – `openaf`/`oaf` command-line flags and generated wrapper scripts (`ojob`, `opack`, `oafp`, `pyoaf`, …), shebang scripts (`--sb`), and the update process +- console.md – Interactive console (`oafc`/`openaf-console`): built-in commands, aliases, profile & history files ## Core - openaf.md – Core OpenAF runtime helpers & APIs (`$$`, `_$`, `$from`, `$path`, channels, etc.) diff --git a/js/genSB.js b/js/genSB.js index 7f95a1abb..76b26f63d 100644 --- a/js/genSB.js +++ b/js/genSB.js @@ -7,14 +7,14 @@ var tmplP = "#!/usr/bin/env -S {{openAFPath}}oafp-sb\n" var isoJob = false, isoafp = false var isWin = String(java.lang.System.getProperty("os.name")).match(/Windows/) +if (!expr.endsWith(".js")) { + if (expr.endsWith(".yaml") || expr.endsWith(".json") || expr.endsWith(".yml")) + isoJob = true + else + isoafp = true +} if (io.fileExists(expr)) { - if (!expr.endsWith(".js")) { - if (expr.endsWith(".yaml") || expr.endsWith(".json") || expr.endsWith(".yml")) - isoJob = true - else - isoafp = true - } - if (io.readFileString(expr).replace(/\n/g, "").trim().substring(0, 2) == "#!") + if (io.readFileString(expr).replace(/\n/g, "").trim().substring(0, 2) == "#!") logWarn("Shebang entry on file '" + expr + "' detected. Ignoring request."); else { io.writeFileString(expr, templify((isoJob ? tmplJ : (isoafp ? tmplP : tmpl)), { @@ -30,12 +30,12 @@ if (io.fileExists(expr)) { } } else { // No file exists - io.writeFileString(expr, templify((isoJob ? tmplJ : tmpl), { + io.writeFileString(expr, templify((isoJob ? tmplJ : (isoafp ? tmplP : tmpl)), { openAFPath: getOpenAFPath() })); if (!isWin) $sh("chmod u+x " + expr) .prefix("chmod") .get(0) - log("Generated " + (isoJob ? "oJob" : "OpenAF") + " shebang file: " + expr); - if (!isoJob) log("On OpenAF use the 'params' variable to access any parameter you pass executing the script like: " + io.fileInfo(expr).canonicalPath + " abc=123 xzy=aaa"); + log("Generated " + (isoJob ? "oJob" : (isoafp ? "oafp" : "OpenAF")) + " shebang file: " + expr); + if (!isoJob && !isoafp) log("On OpenAF use the 'params' variable to access any parameter you pass executing the script like: " + io.fileInfo(expr).canonicalPath + " abc=123 xzy=aaa"); } \ No newline at end of file diff --git a/js/openafconsole.js b/js/openafconsole.js index bba3a362e..28f99bbde 100755 --- a/js/openafconsole.js +++ b/js/openafconsole.js @@ -592,18 +592,19 @@ function __help(aTerm) { __o("__time__ Turns on or off the timing of any script command provided (default off)"); __o("__output__ Turns on or off the output of commands (default on)"); __o("__beautify__ Turns on or off the beautify of output (default on)"); - __o("__color__ Turns on or off the colorify of json output (default on)"); + __o("__color__ Turns on or off the colorify of json output (default on if the terminal supports ANSI)"); __o("__desc__ Provides a description of the available methods for a class (example 'desc AF')"); __o("__scope__ Lists the current OpenAF javascript scope loaded filtered by a regexp (example 'scope sha')"); - __o("__alias__ Create an alias for an openaf-console command line (example 'alias ola=print(\"hi\");')"); - __o("__watch__ Turns on or off an execution before every console prompt (example 'watch new Date();')"); - __o("__pause__ Pauses the output of a command if bigger than the terminal height (default off)"); + __o("__alias__ Create an alias for an openaf-console command line, or list current aliases with no argument (example 'alias ola=print(\"hi\");')"); + __o("__watch__ Turns on or off an execution before every console prompt; 'watch N cmd' live-refreshes cmd every N seconds until 'q' (example 'watch new Date();')"); + __o("__pause__ Pauses the output of a command if bigger than the terminal height (default on)"); __o("__sql__ Executes a SQL query, over a db connection, displaying the result in a table (example 'sql adm select...')"); __o("__dsql__ Returns the list of columns produced by a SQL query over a db connection."); __o("__esql__ Executes the SQL statement, over a db connection (example 'esql db update...')"); __o("__diff__ Show differences between object A and B (example 'diff A with B'; accepts with/withNew/withChanges/withFull)"); __o("__pin__ Pins the next command as a prefix for the next commands until an empty command (example 'pin sql db...')"); __o("__table__ Tries to show the command result array as an ascii table."); + __o("__tree__ Turns on or off a persistent tree view for map/array output, or shows a single result as a tree (default on)"); __o("__view__ Tries to show the command result object as an ascii table."); __o("__multi__ Turns on or off the entry of multiline expressions (default on)"); __o("__edit__ Compose a command in $EDITOR (or vi); use 'edit last' or 'edit history' to revise a previous command."); From 1355aed6253c89d9f920b0b2319ffa53a8419483 Mon Sep 17 00:00:00 2001 From: nmaguiar Date: Sat, 5 Sep 2026 11:43:08 +0100 Subject: [PATCH 02/17] feat(core): enhance core functionality and update formatting tests - Update js/openaf.js and AFBase.java with new logic - Minor adjustments to AFCmdBase.java - Expand test coverage in autoTestAll.Format.js --- js/openaf.js | 38 +++++++++++++++++++++++++++-- src/openaf/AFBase.java | 48 +++++++++++++++++++++++++++++++++---- src/openaf/AFCmdBase.java | 2 +- tests/autoTestAll.Format.js | 31 ++++++++++++++++++++++-- 4 files changed, 110 insertions(+), 9 deletions(-) diff --git a/js/openaf.js b/js/openaf.js index 6625aa869..72a8e3bfa 100644 --- a/js/openaf.js +++ b/js/openaf.js @@ -221,6 +221,7 @@ var __flags = ( typeof __flags != "undefined" && "[object Object]" == Object.pro NET_IGNORE_SSL_DOMAINS : __, TEMPLATE_SET : true, VISIBLELENGTH : true, + VISIBLELENGTH_WIDE_EMOJI : true, // If true (default), bare "Emoji_Presentation=Yes" symbols (e.g. ✅ ⏳ ⚽ without a trailing U+FE0F) count as double-width, matching how modern GUI terminals (macOS Terminal, iTerm2, VS Code) render them by default. Set to false to match plain wcwidth-style terminals that only widen with an explicit U+FE0F. MD_NOMAXWIDTH : true, MD_SHOWDOWN_OPTIONS : {}, MD_RENDER_SVG : false, // If true, ```svg fenced blocks are turned into inline SVG before markdown to HTML conversion @@ -4888,8 +4889,39 @@ const __visibleLengthIsEmojiLike = cp => ( cp == 0x23F0 || cp == 0x23F3 || (cp >= 0x25FD && cp <= 0x25FE) || (cp >= 0x2600 && cp <= 0x27BF) || + cp == 0x2934 || cp == 0x2935 || + (cp >= 0x2B1B && cp <= 0x2B1C) || cp == 0x2B50 || cp == 0x2B55 || + cp == 0x3030 || cp == 0x303D || cp == 0x3297 || cp == 0x3299 || (cp >= 0x1F000 && cp <= 0x1FAFF) ) +// Unicode Emoji_Presentation=Yes single code points within the ranges above: these render +// double-width in terminals by default, without needing a trailing U+FE0F variation selector +// (e.g. ✅ ⏳ ⌚ ⚡). Other code points in __visibleLengthIsEmojiLike (e.g. ✈ ✂ ☺) default to +// text (narrow) presentation and only become wide when explicitly marked with U+FE0F. +const __visibleLengthIsEmojiDefaultPresentation = cp => ( + (cp >= 0x231A && cp <= 0x231B) || + (cp >= 0x23E9 && cp <= 0x23EC) || + cp == 0x23F0 || cp == 0x23F3 || + (cp >= 0x25FD && cp <= 0x25FE) || + cp == 0x2614 || cp == 0x2615 || + (cp >= 0x2648 && cp <= 0x2653) || + cp == 0x267F || cp == 0x2693 || cp == 0x26A1 || + cp == 0x26AA || cp == 0x26AB || + cp == 0x26BD || cp == 0x26BE || + cp == 0x26C4 || cp == 0x26C5 || + cp == 0x26CE || cp == 0x26D4 || cp == 0x26EA || + cp == 0x26F2 || cp == 0x26F3 || cp == 0x26F5 || cp == 0x26FA || cp == 0x26FD || + cp == 0x2705 || + cp == 0x270A || cp == 0x270B || + cp == 0x2728 || + cp == 0x274C || cp == 0x274E || + (cp >= 0x2753 && cp <= 0x2755) || cp == 0x2757 || + (cp >= 0x2795 && cp <= 0x2797) || + cp == 0x27B0 || cp == 0x27BF || + cp == 0x2934 || cp == 0x2935 || + (cp >= 0x2B1B && cp <= 0x2B1C) || cp == 0x2B50 || cp == 0x2B55 || + cp == 0x3030 || cp == 0x303D || cp == 0x3297 || cp == 0x3299 +) const __visibleLengthIsWide = cp => ( cp >= 0x1100 && ( cp <= 0x115F || @@ -4909,8 +4941,9 @@ const __visibleLengthCodePointWidth = cp => { if (__visibleLengthIsControl(cp) || __visibleLengthIsCombining(cp) || __visibleLengthIsEmojiModifier(cp) || __visibleLengthIsVariationSelector(cp) || __visibleLengthIsKeycapMark(cp) || __visibleLengthIsTag(cp) || cp == 0x200D) return 0 return __visibleLengthIsWide(cp) ? 2 : 1 } -const visibleLength = str => { +const visibleLength = (str, wideEmojiPresentation) => { str = String(str).replace(__visibleLengthAnsiRE, "") + wideEmojiPresentation = isDef(wideEmojiPresentation) ? wideEmojiPresentation : __flags.VISIBLELENGTH_WIDE_EMOJI var l = 0 for(var i = 0; i < str.length; ) { var cp = str.codePointAt(i) @@ -4927,6 +4960,7 @@ const visibleLength = str => { } var width = __visibleLengthCodePointWidth(cp) + var isDefaultPresentationEmoji = wideEmojiPresentation && __visibleLengthIsEmojiDefaultPresentation(cp) var emojiCluster = __visibleLengthIsEmojiLike(cp) || width == 2 var emojiPresentation = false var textPresentation = false @@ -4973,7 +5007,7 @@ const visibleLength = str => { break } - if (!textPresentation && ((emojiCluster && (joinedEmoji || emojiPresentation || taggedEmoji)) || keycapEmoji)) width = Math.max(width, 2) + if (!textPresentation && (isDefaultPresentationEmoji || (emojiCluster && (joinedEmoji || emojiPresentation || taggedEmoji)) || keycapEmoji)) width = Math.max(width, 2) l += width } return l diff --git a/src/openaf/AFBase.java b/src/openaf/AFBase.java index 0822ab7ff..3a2b693fe 100644 --- a/src/openaf/AFBase.java +++ b/src/openaf/AFBase.java @@ -1729,15 +1729,22 @@ public static String getOpenAFJar() { /** * - * af.visibleLength(aString) : int + * af.visibleLength(aString, aWideEmojiPresentation) : int * Given aString returns its visible terminal width in columns, removing ANSI sequences and collapsing - * combined characters and emoji grapheme sequences. + * combined characters and emoji grapheme sequences. By default (aWideEmojiPresentation = true) bare + * "Emoji_Presentation=Yes" symbols (e.g. ✅ ⏳ ⚽ without a trailing U+FE0F) count as double-width, + * matching how modern GUI terminals (macOS Terminal, iTerm2, VS Code) render them. Pass false to match + * plain wcwidth-style terminals that only widen those symbols with an explicit U+FE0F. * */ @JSFunction - public static int visibleLength(String s) { + public static int visibleLength(String s, Object wideEmojiPresentation) { if (s == null) return 0; + boolean wideEmoji = wideEmojiPresentation == Undefined.instance || wideEmojiPresentation == null + ? true + : Context.toBoolean(wideEmojiPresentation); + s = VISIBLE_LENGTH_ANSI_RE.matcher(s).replaceAll(""); int length = 0; @@ -1757,6 +1764,7 @@ public static int visibleLength(String s) { } int width = visibleLengthCodePointWidth(cp); + boolean isDefaultPresentationEmoji = wideEmoji && visibleLengthIsEmojiDefaultPresentation(cp); boolean emojiCluster = visibleLengthIsEmojiLike(cp) || width == 2; boolean emojiPresentation = false; boolean textPresentation = false; @@ -1802,7 +1810,7 @@ public static int visibleLength(String s) { break; } - if (!textPresentation && ((emojiCluster && (joinedEmoji || emojiPresentation || taggedEmoji)) || keycapEmoji)) width = Math.max(width, 2); + if (!textPresentation && (isDefaultPresentationEmoji || (emojiCluster && (joinedEmoji || emojiPresentation || taggedEmoji)) || keycapEmoji)) width = Math.max(width, 2); length += width; } @@ -1848,9 +1856,41 @@ private static boolean visibleLengthIsEmojiLike(int cp) { || cp == 0x23F3 || (cp >= 0x25FD && cp <= 0x25FE) || (cp >= 0x2600 && cp <= 0x27BF) + || cp == 0x2934 || cp == 0x2935 + || (cp >= 0x2B1B && cp <= 0x2B1C) || cp == 0x2B50 || cp == 0x2B55 + || cp == 0x3030 || cp == 0x303D || cp == 0x3297 || cp == 0x3299 || (cp >= 0x1F000 && cp <= 0x1FAFF); } + // Unicode Emoji_Presentation=Yes single code points within the visibleLengthIsEmojiLike ranges: + // these render double-width in terminals by default, without needing a trailing U+FE0F variation + // selector (e.g. ✅ ⏳ ⌚ ⚡). Other code points in visibleLengthIsEmojiLike (e.g. ✈ ✂ ☺) default to + // text (narrow) presentation and only become wide when explicitly marked with U+FE0F. + private static boolean visibleLengthIsEmojiDefaultPresentation(int cp) { + return (cp >= 0x231A && cp <= 0x231B) + || (cp >= 0x23E9 && cp <= 0x23EC) + || cp == 0x23F0 || cp == 0x23F3 + || (cp >= 0x25FD && cp <= 0x25FE) + || cp == 0x2614 || cp == 0x2615 + || (cp >= 0x2648 && cp <= 0x2653) + || cp == 0x267F || cp == 0x2693 || cp == 0x26A1 + || cp == 0x26AA || cp == 0x26AB + || cp == 0x26BD || cp == 0x26BE + || cp == 0x26C4 || cp == 0x26C5 + || cp == 0x26CE || cp == 0x26D4 || cp == 0x26EA + || cp == 0x26F2 || cp == 0x26F3 || cp == 0x26F5 || cp == 0x26FA || cp == 0x26FD + || cp == 0x2705 + || cp == 0x270A || cp == 0x270B + || cp == 0x2728 + || cp == 0x274C || cp == 0x274E + || (cp >= 0x2753 && cp <= 0x2755) || cp == 0x2757 + || (cp >= 0x2795 && cp <= 0x2797) + || cp == 0x27B0 || cp == 0x27BF + || cp == 0x2934 || cp == 0x2935 + || (cp >= 0x2B1B && cp <= 0x2B1C) || cp == 0x2B50 || cp == 0x2B55 + || cp == 0x3030 || cp == 0x303D || cp == 0x3297 || cp == 0x3299; + } + private static boolean visibleLengthIsWide(int cp) { return cp >= 0x1100 && ( cp <= 0x115F diff --git a/src/openaf/AFCmdBase.java b/src/openaf/AFCmdBase.java index aee45d453..ddda384a3 100644 --- a/src/openaf/AFCmdBase.java +++ b/src/openaf/AFCmdBase.java @@ -15,7 +15,7 @@ * */ public class AFCmdBase { - public static String VERSION = "20260824"; + public static String VERSION = "20260905"; public static String DISTRIBUTION = "nightly"; public static String LICENSE = "See license info in openaf.jar/LICENSE and openaf.jar/LICENSES.txt"; diff --git a/tests/autoTestAll.Format.js b/tests/autoTestAll.Format.js index 59a3d8dd0..23da1c982 100644 --- a/tests/autoTestAll.Format.js +++ b/tests/autoTestAll.Format.js @@ -114,12 +114,39 @@ }; exports.testVisibleLengthEmojiPresentation = function() { - ow.test.assert(visibleLength("⚽"), 1, "Problem with bare emoji-presentation symbol visible width."); - ow.test.assert(af.visibleLength("⚽"), 1, "Problem with af.visibleLength bare emoji-presentation symbol visible width."); + // Default (VISIBLELENGTH_WIDE_EMOJI = true): bare Emoji_Presentation=Yes symbols count as + // double-width, matching modern GUI terminals (macOS Terminal, iTerm2, VS Code). + ow.test.assert(visibleLength("⚽"), 2, "Problem with bare emoji-presentation symbol visible width."); + ow.test.assert(af.visibleLength("⚽"), 2, "Problem with af.visibleLength bare emoji-presentation symbol visible width."); ow.test.assert(visibleLength("⚽️"), 2, "Problem with explicit emoji-presentation symbol visible width."); ow.test.assert(af.visibleLength("⚽️"), 2, "Problem with af.visibleLength explicit emoji-presentation symbol visible width."); ow.test.assert(visibleLength("⚽︎"), 1, "Problem with text-presentation symbol visible width."); ow.test.assert(af.visibleLength("⚽︎"), 1, "Problem with af.visibleLength text-presentation symbol visible width."); + + // Opt-out (per-call param or __flags.VISIBLELENGTH_WIDE_EMOJI = false): matches plain + // wcwidth-style terminals that only widen these symbols with an explicit U+FE0F. + ow.test.assert(visibleLength("⚽", false), 1, "Problem with bare emoji-presentation symbol visible width (narrow override)."); + ow.test.assert(af.visibleLength("⚽", false), 1, "Problem with af.visibleLength bare emoji-presentation symbol visible width (narrow override)."); + ow.test.assert(visibleLength("⚽️", false), 2, "Problem with explicit emoji-presentation symbol visible width (narrow override)."); + + var _oldWideEmoji = __flags.VISIBLELENGTH_WIDE_EMOJI; + try { + __flags.VISIBLELENGTH_WIDE_EMOJI = false; + ow.test.assert(visibleLength("⚽"), 1, "Problem with bare emoji-presentation symbol visible width (flag override)."); + } finally { + __flags.VISIBLELENGTH_WIDE_EMOJI = _oldWideEmoji; + } + + // Emoji_Presentation=Yes symbols outside the Dingbats/Misc Symbols block (Miscellaneous + // Symbols and Arrows: ⭐ ⭕ ⬛ ⬜) should also default to double-width. + ow.test.assert(visibleLength("⭐"), 2, "Problem with bare star symbol visible width."); + ow.test.assert(af.visibleLength("⭐"), 2, "Problem with af.visibleLength bare star symbol visible width."); + ow.test.assert(visibleLength("⭕"), 2, "Problem with bare heavy large circle visible width."); + ow.test.assert(af.visibleLength("⭕"), 2, "Problem with af.visibleLength bare heavy large circle visible width."); + ow.test.assert(visibleLength("⬛"), 2, "Problem with bare black large square visible width."); + ow.test.assert(af.visibleLength("⬛"), 2, "Problem with af.visibleLength bare black large square visible width."); + ow.test.assert(visibleLength("⬜"), 2, "Problem with bare white large square visible width."); + ow.test.assert(af.visibleLength("⬜"), 2, "Problem with af.visibleLength bare white large square visible width."); }; exports.testVisibleLengthSubdivisionFlag = function() { From 6b79cc87a918de8c7b3bd45dff5fb067cc5cd22c Mon Sep 17 00:00:00 2001 From: nmaguiar Date: Sat, 5 Sep 2026 11:46:48 +0100 Subject: [PATCH 03/17] refactor(js): update formatting logic in owrap.format.js --- js/owrap.format.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/js/owrap.format.js b/js/owrap.format.js index a518d53af..db657743f 100644 --- a/js/owrap.format.js +++ b/js/owrap.format.js @@ -3693,7 +3693,7 @@ OpenWrap.format.prototype.toSLON = function(aObj, cTheme) { sepArr : " | ", endArr : "]", strQuote : "'", - specialRE: "[\.\(\,\)\:\\[\\]\|\']" + specialRE: "[\.\(\,\)\:\\[\\]\|\'\\r\\n\\t]" } if (isMap(cTheme)) dTheme = merge(dTheme, cTheme); @@ -3719,7 +3719,7 @@ OpenWrap.format.prototype.toSLON = function(aObj, cTheme) { if (isNumber(aObj)) { return String(aObj) } - var _escape = s => s.replace(new RegExp(dTheme.strQuote, "g"), "\\" + dTheme.strQuote) + var _escape = s => s.replace(new RegExp(dTheme.strQuote, "g"), "\\" + dTheme.strQuote).replace(/\r/g, "\\r").replace(/\n/g, "\\n").replace(/\t/g, "\\t") if (!isMap(aObj) && !isArray(aObj)) return (isString(aObj) && aObj.match(new RegExp(dTheme.specialRE))) ? dTheme.strQuote + _escape(aObj) + dTheme.strQuote : String(aObj) } @@ -3739,7 +3739,7 @@ OpenWrap.format.prototype.toCSLON = function(aObj, cTheme) { sepArr : " | ", endArr : "]", strQuote: "'", - specialRE: "[\(\,\)\:\\[\\]\|\']" + specialRE: "[\(\,\)\:\\[\\]\|\'\\r\\n\\t]" } if (isMap(cTheme)) dTheme = merge(dTheme, cTheme); @@ -3762,7 +3762,7 @@ OpenWrap.format.prototype.toCSLON = function(aObj, cTheme) { if (isDate(aObj)) { return ansiColor("reset", ow.format.fromDate(aObj, 'yyyy-MM-dd/HH:mm:ss.SSS')) } - var _escape = s => s.replace(new RegExp(dTheme.strQuote, "g"), "\\" + dTheme.strQuote) + var _escape = s => s.replace(new RegExp(dTheme.strQuote, "g"), "\\" + dTheme.strQuote).replace(/\r/g, "\\r").replace(/\n/g, "\\n").replace(/\t/g, "\\t") if (!isMap(aObj) && !isArray(aObj)) return ansiColor("reset", (isString(aObj) && aObj.match(new RegExp(dTheme.specialRE))) ? dTheme.strQuote + _escape(aObj) + dTheme.strQuote : String(aObj)) } From 538472dd5cf3ab22ac7003c332f9ad8618844f12 Mon Sep 17 00:00:00 2001 From: nmaguiar Date: Sun, 6 Sep 2026 20:26:23 +0100 Subject: [PATCH 04/17] feat(format): update core JS logic and enhance format tests - Update oafp.js and openaf.js to refine core functionality - Expand autoTestAll.Format tests and configuration --- js/oafp.js | 16 +++++----- js/openaf.js | 55 ++++++++++++++++++++++++++++++++++- tests/autoTestAll.Format.js | 20 +++++++++++++ tests/autoTestAll.Format.yaml | 8 +++++ 4 files changed, 90 insertions(+), 9 deletions(-) diff --git a/js/oafp.js b/js/oafp.js index 6a69c8da6..240c9efdc 100755 --- a/js/oafp.js +++ b/js/oafp.js @@ -1,9 +1,9 @@ var params=processExpr(" "); -// (author: Nuno Aguiar, version: 20260822, license: Apache 2.0, url: https://github.com/openaf/oafp) +// (author: Nuno Aguiar, version: 20260906, license: Apache 2.0, url: https://github.com/openaf/oafp) // --- const _oafphelp={'docs/EXAMPLES.md':af.fromBytes2String(io.gunzip(af.fromBase64("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"))), 'docs/TEMPLATE.md':af.fromBytes2String(io.gunzip(af.fromBase64("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"))), -'docs/USAGE.md':af.fromBytes2String(io.gunzip(af.fromBase64("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"))), +'docs/USAGE.md':af.fromBytes2String(io.gunzip(af.fromBase64("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"))), 'docs/FILTERS.md':af.fromBytes2String(io.gunzip(af.fromBase64("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")))}; var _params=processExpr(" "); const oafp=a=>{if(!isUnDef(a)&&!isDef(a.____ojob)){isDef(a.secKey)&&(a=$sec().procMap(a));var T=b=>{for(var c=Object.keys(H),d=0;d{a.__origr=b;c.__ifrom&&(b=$from(isArray(b)?b:[b]).query(af.fromNLinq(c.__ifrom.trim())),delete c.__ifrom);if(c.__isql){var d=__;if(isString(a.sqlfilter))switch(a.sqlfilter.toLowerCase()){case "simple":d="nlinq";break;case "advanced":d="h2";break;default:d=__}if(isArray(b)&&b.length>0)if(isString(a.isqlfiltertables)){var f= @@ -68,7 +68,7 @@ f[0]:isBoolean(e)&&(k[g]=e?f[1]:f[2])})}return b},field2date:b=>{var c=a.field2d return b},field2byte:b=>{var c=a.field2byte.split(",").map(d=>d.trim());traverse(b,(d,f,g,e)=>{c.indexOf(g.length>0&&!g.startsWith("[")?g.substring(1)+"."+d:d)>=0&&isNumber(f)&&(e[d]=ow.format.toBytesAbbreviation(f))});return b},field4map:b=>{var c=a.field4map.split(",").map(d=>d.trim());traverse(b,(d,f,g,e)=>{c.indexOf(g.length>0&&!g.startsWith("[")?g.substring(1)+"."+d:d)>=0&&isString(f)&&(e[d]=y(f))});return b},field2str:b=>{var c=a.field2str.split(",").map(d=>d.trim());traverse(b,(d,f,g,e)=>{c.indexOf(g.length> 0&&!g.startsWith("[")?g.substring(1)+"."+d:d)>=0&&!isString(f)&&(e[d]=isMap(e[d])||isArray(e[d])?af.toSLON(e[d]):String(e[d]))});return b},allstrings:b=>{toBoolean(a.allstrings)&&traverse(b,(c,d,f,g)=>{isDef(d)&&!isString(d)&&(isNumber(d)?g[c]=String(d):isBoolean(d)?g[c]=String(d):isNull(d)&&(g[c]=""))});return b},oaf:b=>{if(isString(a.oaf)){let c;c=io.fileExists(a.oaf)?io.readFileString(a.oaf):a.oaf;if(isString(c))return(new Function("data",c+";return data"))(b)}return b}},M=new Map([["?",(b,c)=> {b=Array.from(M.keys()).filter(d=>d!="?").sort();z(b,c)}],["pm",(b,c)=>{z(b,c)}],["key",(b,c)=>{z(b,c)}],["html",(b,c)=>{var d;c=!1;a.htmlopen=_$(toBoolean(a.htmlopen),"htmlopen").isBoolean().default(!0);a.htmlwait=_$(a.htmlwait,"htmlwait").isNumber().default(2500);a.htmlopen&&(d=io.createTempFile("oafp_",".html"));ow.loadTemplate();a.htmldark=_$(toBoolean(a.htmldark),"htmldark").isBoolean().default(!1);isString(b)?(b=ow.template.html.genStaticVersion(ow.template.parseMD2HTML(b,!toBoolean(a.htmlpart), -!toBoolean(a.htmlcompact),__,a.htmldark)),b=b.replace("",'')):(b=ow.template.html.parseMap(b,!0,a.htmldark),b='"+b.out+"");a.htmlopen&&(io.writeFileString(d,b),c=openInBrowser("file:///"+d.replace(/\\/g,"/")));c?sleep(a.htmlwait,!0):w(b)}],["ctable",(b,c)=>{z(b,c)}],["stable",(b,c)=>{z(b,c)}],["table",(b,c)=>{z(b,c)}],["json",(b,c)=>{z(b,c)}],["yaml", +!toBoolean(a.htmlcompact),__,a.htmldark)),b=b.replace("",'')):(b=ow.template.html.parseMap(b,!0,a.htmldark),b='