Dear SWI-Prolog user,
SWI-Prolog 10.1.14 is ready for download. There are a large number of
changes. Some bug fixes and notably a lot of work improving the
development tools. Highlights:
- Bug in atom-GC for dying threads that unregister atoms after tearing
down the Prolog engine. This notably concerns thread-local predicates
and local tables. - Fix handling very large integers on Windows. Here we have, besides the
memory limit, a 512Mb limit inside libGMP. Also fixes several integer
operations for values > 2^{31}, silently truncating. Note that these
issues only appear on Windows because he C typelongis 32 bits there.
It also only affects libGMP integers. The libBF API usesint64_tand
is thus not affected. - Avoid child processes inheriting socket file descriptors.
- Fixes to halting Prolog from various locations (menus, threads, etc.)
Development tools
-
Introduced more theme support and TTY links in Prolog messages. Pretty
much any reference to a predicate is now a link. When tracing, the goal
is a link to the call-site. This means (typically) Ctrl-click on a goal
in the debugger edits the call-site. This works in Epilog as well as
any terminal that supports OSC 8 escape sequences. -
Introduce OSC 133 semantic marks. These allow the terminal to distinguish
prompts, user input and command output. These are handled by Epilog,
providing folding of the output of commands as well as copying the command,
its output or both. Using the resourceprolog_terminal.fold_previous: @on,
old commands are automatically folded, leaving only commands and the output
of the last command visible. Please try! Various modern terminals also
support OSC 133 (e.g., iTerm2 on MacOS). -
Many fixes and enhancements to Epilog.
Enjoy — Jan
SWI-Prolog Changelog since version 10.1.13
-
MAINTENANCE: Added scripts/submodule-update Updates the submodules
likegit submodule update, but pulls a submodule that is on a branch
tracking a remote branch instead of detaching its HEAD. -
FIXED: only write OSC 8 hyperlinks to a terminal ansi_hyperlink/3
wrote the escape sequence whenever the hyperlink_term flag was set,
also when the stream was a memory stream. A message captured with
with_output_to/2 then came back with the escapes in it, which broke
test_messages.pl for anyone running with hyperlinks enabled. -
TEST: split tests/core into tests/core_text and tests/core_lang
tests/core was the longest running swipl test at 13.8 seconds,
holding back “ctest -j”. Split it in two along the obvious line:
core_text holds the tests for characters, strings, encodings, syntax,
read/write and stream I/O, core_lang the tests for terms, arithmetic,
control, compilation and the runtime. -
TEST: test_agc_margin: build the filler atom once per size atom_of/3
rebuilt a 100,000 element code list for each of the 200 atoms in
every trigger test, which made this file 10.7 of the 16.4 seconds of
the core test suite. The list only depends on the requested size,
so build one per size and share it. Runs in 0.1 second now; the
atoms it creates are still distinct and still 100kB each. -
ENHANCED: locale independent character classification and case
conversion code_type/2, char_type/2, upcase_atom/2, downcase_atom/2 and
the other text primitives no longer call <wctype.h>. Character classes
and case conversion are derived from the Unicode Character Database
at build time, so they answer the same in every locale and on every
C library, cover the full Unicode range also on Windows where wint_t
is 16 bits, and agree with the classification read/1 uses. -
FIXED: #1517 crash in atom-GC while destroying a thread or engine
Destroying a thread or engine that holds many atoms, notably in
its private tables, could crash in PL_unregister_atom() if the atom
garbage collector reclaimed one of these atoms concurrently. -
FIXED: normalize_space/2 to normalize Unicode separator characters
normalize_space/2 used unicode_separator(), which implements the
UAX #31 Pattern_White_Space set used by the Prolog reader. As a
result it did not normalize the Unicode separator characters such
as U+00A0 (no-break space) or U+3000 (ideographic space), while it
did replace the invisible bidi format characters U+200E and U+200F
by a space. It now uses fiswspace(), i.e., the same classification
as code_type(Code, space). -
DOC: document the maximum size of unbounded integers Unbounded integers
are limited by the global stack limit and, if the system is built
using GMP on a platform wherelongis 32 bits (i.e., Windows),
to 512Mb. Document this in \secref{morelimits} and refer to it from
the description of **/2. -
FIXED: Windows crash creating very large integers If
longis 32 bits,
as on Windows, GMP integers are limited to 512Mb and GMP calls abort()
if we ask for more. Our checks only verified the result fits in the
global stack limit (1Gb by default), so for exampleX is 2^4294967294
took the entire process down. In addition, the exponent was truncated
tounsigned long, which madeX is 2^4294967296silently evaluate
to 1. -
CMAKE: test_libs() and test_lib() take OPTIONS Commandline options
for swipl itself, handed to it before the test is loaded: a -D flag
the test needs set before its libraries are, a -p that only it wants,
and the like. There was nowhere to put such a thing: the command is
built inside test_lib(), so a package that needed one had to register
its tests by hand. -
ADDED: PL_prompt_is_continuation() Says whether the prompt that
comes next continues an input that was started earlier, which is what
prompt1/1 and PrologPrompt() already decide between: the prompt of a
first line is handed out once, and everything after it is the prompt
of prompt/2. -
FIXED: crash when a second Epilog window is deleted Updates xpce.
The terminals share the interned Colour objects of their palette but
held them with a flag rather than a count, so deleting one Epilog
window freed colours the others were still painting with. -
ADDED: el_set/2 prompt_marks(Boolean) Updates libedit and xpce.
Turns the OSC 133 prompt marks off for a terminal that would print
them rather than read them. They are on by default. -
ADDED: OSC 133 semantic prompt marks Updates libedit and xpce.
The commandline editor marks its prompts and the line it reads with the
FinalTerm OSC 133 sequences, and the Epilog terminal reads them: it now
knows when there is a line being edited and where it starts, rather than
deducing it from bracketed paste. That gives click-to-move-the-caret
back to vi mode, and terminals with shell integration (iTerm2, kitty,
WezTerm, VS Code) get prompt navigation over a swipl session for free. -
FIXED: a click in the Epilog terminal disturbed a single character
read Updates libedit and xpce. A click in the line being edited asks
the client to move its caret with cursor keys; a client reading a
single character answered with the ESC of the first of them, which
made the command line tracer print “Unknown option (h for help)”
when a link in its port message was clicked. -
FIXED: Missing empty line after a bullet list in help/1 output A list
nested in the body of a definition list (dd) was formatted as a nested
list, losing the empty lines that separate it from the surrounding text. -
DOC: ansi_format/3: use code markup for the ‘#RGB’ colour names These
are Prolog atoms, so they belong in code markup. This also avoids
the LaTeX translation of the quotes into typographic quotes. -
FIXED: Spacing of infix operators in term description items
A comma binds to the left operand and is followed by a space.
Adds \infixopsep{Op}, used by \infixterm and \infixtermitem, which
also keeps a module qualifier free of surrounding spaces. -
ADDED: Epilog terminal: highlight the other occurrences of the
selection Updated xpce. The dark theme had no isearch styles for
terminal_image, so the pale turquoise of the other matches was drawn
with the terminal’s white foreground; both are now given colour :=
black, as the editor entry already does. -
FIXED: user streams lose FD_CLOEXEC when restore_ctty() reconnects
them dup2() does not carry the flag over, so after a child revoked
our controlling terminal and restore_ctty() opened it again, the
standard streams were inherited by the next process we start. -
MODIFIED: ansi_get_color/2 now reports floats in 0.0..1.0 The
components of the rgb/3 term were integers in the range 0..65535.
That range is ambiguous with the rgb/3 term of win_window_color/2,
whose components are in 0..255, and it suggested a precision the
terminal does not offer: it reports one to four hexadecimal digits
per component, which we scaled up to 16 bits. A component is now
the fraction of its maximum, which needs no scale to be agreed upon.
This is an incompatible change to a predicate that is rarely used
outside library(theme/auto). -
ENHANCED: Hyperlink and stripe the goals printed by the debugger Goals
printed by the debugger are now a hyperlink to their call site, i.e.,
the position in the clause of the parent frame from which the goal
is called. They also carry the new colour class goal(Port, Parity),
where Parity alternates over the steps of a trace. This allows themes
to separate successive steps using a soft background colour and/or
to colour the goal by port. The dark and light themes stripe the goals. -
ENHANCED: Centralise predicate references in messages and make them
links boot/messages.pl formatted a predicate reference in some forty
places, using four different module-hiding policies, three copies of
the source location lookup and a mix of ~q and ~p. Only one of them
produced a link. All of them now go through predicate_reference//1,2,
which prints the predicate indicator using thecodeclass and turns
it into a hyperlink to its definition when the location is known.
Messages that list candidates, such as the alternatives for an unknown
procedure, tag each predicate with its kind using predicate_kind/2
and the new themeable class predicate(Kind). -
ENHANCED: Central source location for predicates, including C predicates
Added ‘$predicate_source_location’/2, which resolves a predicate
to File:Line. It follows imported_from/1 to the module that defines
the predicate and falls back to the location of the implementing C
function for foreign predicates. The (expensive) foreign lookup runs
addr2lineoratosin a child process and is therefore memoised. -
ENHANCED: Hook prolog:line_editor_attributes/2 Tell the line editor how
to switch the decoration of the input line off and on again. It must
switch these off before erasing the rows the line no longer uses,
as erasing paints with the current background colour. Called each
time we build a prompt, so a theme loaded at run time is picked up. -
FIXED: ansi_get_color/2: accept the colour replies terminals really
send The reply was matched against a fixed pattern of exactly four
hex digits per component terminated by BEL, which is what xterm sends.
An X11 colour specification allows one to four digits per component and
the string may be terminated by BEL or ST, which made ansi_get_color/2
fail on terminals that answer the query perfectly well. The Epilog
terminal is one of these: it replies with two digits and ST. -
ENHANCED: Colour the toplevel prompt, the typed query and the answers
The interactive toplevel now decorates the prompt, the text typed by
the user and the answers using the theme classesprompt,input,
answer(Parity)andbinding(name).Parityisoddorevenand
alternates over the answers of a single query, which allows a theme to
stripe the answers of a non-deterministic query. The default theme
only makes the prompt and the variable names bold; the background
colours are defined by library(theme/dark) and library(theme/light)
as these require knowing the background colour of the terminal. -
SUBMODULE: xpce: background colour erase and terminal identification
Provides two fixes needed by the coloured toplevel: -
CMAKE: Create .dSYM bundles on macOS On macOS the DWARF stays
in the object files and the linked binary only carries a debug
map that points at them. atos(1) follows that map, which is how
‘$foreign_predicate_source’/2 finds the source of a predicate defined
in C, used by edit/1 and for the links in messages. The map breaks
when the objects are removed and some toolchains produce one atos
cannot follow: a MacPorts gcc build resolves no source line at all.
Running dsymutil(1) after the link collects the DWARF into a .dSYM
bundle, which atos locates by UUID, and fixes both. -
FIXED: addr2line: do not report “at” without a source location
Without source line information atos(1) emits “func (in lib.dylib) +
0” and addr2line(1) emits “??:0”. We turned both into "func() at ",
which is worse than the bare “func()”. The " at " is now only added
once we know a location follows. -
FIXED: halt/0 from an event callback did not take effect until input
arrived With the SDL backend XPCE has no separatepcethread, so
events for the main thread are dispatched from PL_dispatch() while
the toplevel waits for terminal input. A callback such as Epilog’s
“Halt Prolog” therefore raises unwind(halt(Status)) in the waiting
thread itself, but the wait loop only asked PL_handle_signals(), which
returns 0 when no signal is pending. Dispatching continued until
the user typed a character, and $raw_read/2 then returned end_of_file
with the exception still pending, printing “did not clear exception:
unwind(halt(0))”. -
FIXED: Windows: Control-C only interrupted the first computation
#1515 The console control handler runs on a thread of its own, which
has no Prolog engine, so PL_raise() had nothing to raise SIGINT on.
It should call PL_w32thread_raise(), but the#ifdef O_PLMTguarding
that never held: pl-main.c does not see config.h. What made ^C work
at all was the C runtime’s own handler, installed when PL_initialise()
calls signal(SIGINT, …) and therefore called first. As it resets
the handler to SIG_DFL before calling it, it only answered the first ^C. -
FIXED: Print and link the column of a source location counting from 1.
The column of a syntax error and of the hyperlinks we emit for a
location was taken from theline_positionof the stream, which
counts from 0, while the C compiler, ripgrep, editors and edit/1 all
count the first column as 1. -
ADDED: shell_command/1: find the preferred interactive shell executable.
-
PORT: #1514 Windows: make sure PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE
is defined. -
FIXED: library(prolog_xref): track prolog_listen/2 properly.
Created called heads with arity 0, as inp()rather thanp. -
ADDED:
ls/1: tag links with@ -
DOC: Include library(shell) into the documentation.
-
MODIFIED: library(www_browser): use desktop_open/2 from library(desktop)
If library(desktop) is available, www_open_url/1 now lets the desktop
open the URL rather than searching for a browser itself. On Windows
we use win_shell/2 if library(desktop) is not available.
Package clib
-
FIXED: sockets are inherited by processes we start A socket that lacks
FD_CLOEXEC goes to every process we exec. A child that inherits a
listening socket keeps its port in use for as long as it lives, so
an HTTP server does not come back after a restart, and the child may
accept connections meant for us. Prolog streams get the flag from
Snew(), but a socket is a plain OS handle until it is turned into a
stream, and a server socket never is. -
ADDED: library(desktop): desktop_open/1,2 to open a file, directory
or URL desktop_open/1,2 hands a document over to the application the
desktop associates with it, e.g., a PDF viewer for a.pdffile or a
file browser for a directory. It uses the Windows ShellExecute() API,
openon MacOS and one ofxdg-open,gio,kde-open,
etc. on other systems. The Prolog flagdesktop_openerand the
option opener(Command) allow selecting the command explicitly. -
ENHANCED: process_create/3: detached(true) no longer waits for the
process If detached(true) is used without process(PID) and without
pipes, process_create/3 now returns as soon as the process is started
instead of waiting for its completion. On POSIX systems this uses
a second fork(), such that the process is inherited byinitand
we do not have to reclaim it. On Windows we close the process and
job handles.
Package http
- FIXED: HTML rendering of url/2 message elements The HTML message
renderer passed the URL of an url/2 element straight into href, which
raises a type error if it is a File:Line source location rather than a
web link, and it wrote the label as-is, which is wrong now that a label
may be a Format-Args pair or an ansi/3 term. Labels are now rendered to
text and a source location prints as text rather than as a broken link.
Package libedit
-
FIXED: a prompt the program wrote itself was lost on a redraw A read
that starts where the output left the caret has no prompt of its own:
format("name: "), read_line_to_string(user_input, S)' puts those six columns on the screen as ordinary output and then reads. libedit is handed an empty prompt and takes the line to start in column 0, six columns to the left of where it does. While it moves the caret relatively that goes unseen, but a full refresh -- a SIGWINCH, a resize it notices at a keypress, ^L -- redraws the input overname:
’ and leaves the caret six columns out. -
ADDED: OSC 133: mark the end of the output and a continuation prompt
The prompt, the input and the start of the output were marked; where
the output ended was left for the reader to guess from the prompt
after it, and a term typed over several lines was marked as several
commands because every line got the mark that starts one. -
ADDED: el_set/2 and el_get/2 prompt_marks(Boolean) Turns the OSC 133
prompt marks off for a terminal that would print them rather than
read them. They are on by default. The marks live in the prompt
string, so setting the option throws the cached prompt away for
update_prompt() to build again. -
ADDED: mark the prompt and the input with OSC 133 While reading a
line, surround the prompt and the input with the FinalTerm “semantic
prompt” marks:A' before the prompt,B’ before the input and `C’
when the line was entered. A terminal that reads them – Epilog,
iTerm2, kitty, WezTerm, VS Code – can tell prompt, input and output
apart, and so jump between prompts, act on the output of one command,
or move the caret to a click in the line being edited. -
FIXED: no bracketed paste while reading a single character Bracketed
paste (DEC private mode 2004) says that a line editor owns the input.
A read that asks for one character – get_single_char/1, the tracer
at its `? ’ prompt, with_tty_raw/1 – is not such a read, so turn
the mode off for its duration. -
FIXED: resize of a wrapped input line missed when SIGWINCH is lost
Resizing an Epilog window while editing a line that wraps could leave
libedit painting on rows that hold something else: the next key moved
the caret by rows and columns computed from the width the terminal
no longer had, and the repaint left a copy of the first row behind. -
ENHANCED: Do not leave the input decoration on the rows libedit
erases The toplevel decorates the line being edited by leaving the
attributes of the colour classinputin effect while the user
is typing. If that class has a background colour, the rows libedit
erases because the line got shorter were painted with it and stayed
that way: unwrap a long line or move from a multi-line history entry
to a shorter one and a coloured bar was left below the line. -
FIXED: Do not decorate completions and incremental search as input
The toplevel decorates the input line by leaving the attributes of the
colour classinputin effect while the user is typing. The completion
alternatives and the incremental search prompt are written while these
are active, so they were coloured as input. Worse,inputmay have
a background colour, which the\e[0K' used by the search prompt then paints to the right margin. Both now reset the attributes first; theredisplay’ that ends these commands re-installs the decoration. -
FIXED: honour a PL_dispatch() exception before reading the terminal
The PL_RAWTTY/PL_NOTTY branch of Sread_libedit() ignored the result
of PL_dispatch() and blocked in read(2), so an exception raised by a
signal or an event callback was only noticed after the user typed a
character. Hand it to the stream instead, as read_char() already does. -
FIXED: Windows: do not report a modifier key press as a NUL character
Windows queues a key-down event for the modifier of every combination
typed. Reporting it to libedit as a character handed it a NUL.
For ^C that NUL was answered to the interrupt handler’s “Action (h
for help) ?” prompt, which printed “Unknown option” before the user
had touched a key. See swipl-devel issue #1515.
Package ltx2htm
-
FIXED: Spacing of infix operators in term description items A comma
binds to the left operand and is followed by a space. Rendering it
with a symmetric separator turned e.g. the ansi_format/3 attributes into
fg(Color) , bg(Color),hfg(Color),hbg(Color). Replaces nospace_op/1
with op_spacing/4 and adds the LaTeX \infixopsep{Op} to do the same
for the printed manual. -
FIXED: Preserve spaces around single and back quotes The LaTeX tokenizer
classifies'and`as words. As spaces between two adjacent
words are dropped on input and regenerated on output this loses the
spaces around them: the translation turns the quotes into the HTML
entities‘and’and such command tokens do not take
part in the regeneration. Tokenize the quotes as TOK_NOSPACEWORD
such that the surrounding spaces are preserved in the token list.
Package pengines
- FIXED: HTML rendering of url/2 message elements The HTML message
renderer passed the URL of an url/2 element straight into href, which
is wrong if it is a File:Line source location rather than a web link,
and it wrote the label as-is, which is wrong now that a label may
be a Format-Args pair or an ansi/3 term. Labels are now rendered to
text and a source location prints as text rather than as a broken link.
Package pldoc
- FIXED: Spacing of infix operators in term description items
A comma binds to the left operand and is followed by a space.
Adds \infixopsep{Op}, used by \infixterm and \infixtermitem, which
also keeps a module qualifier free of surrounding spaces.
Package xpce
-
FIXED: print dialog proposed a printer queue named
postscript' When $PRINTER is not set, <-print_command_template now proposes plain ``lpr``, letting lpr(1) pick the default queue, rather than expanding %p to the bogus queue namepostscript’. That name was also a leftover
from printing PostScript. -
FIXED: resources referring to .png icons that were replaced by .svg
Several libraries still referred to 16x16 and 32x32 .png icons that
were removed when the development tools moved to .svg. Notably,
this made the PceEmacs buffer menu fail to open. -
MODIFIED: print graphics as PDF rather than PostScript
graphical<-postscriptand classwin_printerare gone, leaving
both library(print_graphics) and PceDraw unable to print. Both now
render to a temporary PDF file and hand that to the print spooler. -
REMOVED: PceDraw and grapher Windows metafile support Class
win_metafileanddisplay->selection_ownerno longer exist
and the clipboard handles text only, so none of this can work.
Removes the PceDraw clipboard menu with its ->export_win_metafile
and ->import_win_metafile, thedraw_metafileshape and
grapher->copy_graph. -
FIXED: PceEmacs C mode: GDB commands called a non-existing method The
method is->tell_gdb_warn; only ->break_at_line used the right name. -
FIXED: calls to the deleted
graphical->synchroniseBoth callers
only wanted the pending changes to become visible, which is what
window->flushdoes. -
FIXED: the Dialog Editor used the deleted
display<-visual_type
Colour is now always available, so the monochrome alternatives and
the ifcolour/2 helper selecting between them are dropped. -
FIXED: PceEmacs buffer menu and Dialog Editor used deleted frame
methodsframe<->iconandframe<->icon_labelwere deleted,
but two callers were missed. As a result, opening the PceEmacs buffer
menu reported an error and failed to create the window. -
FIXED: crash when ->initialise fails on a class with non-slot C fields
Instance prototypes initialise the declared slots only, leaving C fields
such asfile.fdfilled with uninitialised memory. As a failed
->initialise still sends ->unlink,new(_, file(SomeFileObject))
crashed in Sclose(). -
ENHANCED: Epilog: toggle fold_previous from the Settings menu Added
a marked “Fold previous command” item to the Settings submenu that
toggles the fold_previous setting of the current terminal. As with
the Debug menu items, a condition updates the mark from the terminal
state each time the menu is opened. -
FIXED: Epilog: a window row is not a buffer line under a closed fold
Writing below a closed fold scrolled the window although it had room
for the caret still, taking what was above the fold off the top,
and a client that placed its caret with CUP landed in the text the
fold hides, where what it wrote next never showed. Both counted
lines where the window counts rows. -
FIXED: Epilog: the alternate screen over a closed fold Entering the
alternate screen saved one line per row of the window, but a closed
fold hides lines the window does not show and the erase that follows
takes those away too: what came back after e.g. help/0 was the text
the fold hid, with everything below it gone. The window is now saved
in the lines its rows cover, and the blocks that name them stay while
the application owns the window, so the folds close again over the
text that comes back. -
TEST: terminal: wait for the echo of a repeated command The fixed
pause was never long enough on Windows, where the input reaches the
client over a pipe a character to the dispatch round. -
FIXED: terminal: let go of a block whose end was erased An erase takes
the lines below the caret and leaves the ones above, so a block can
keep its prompt and lose the mark that closed it. It can no longer
say how far it reaches, but rlc_sweep_blocks() kept it as long as one
anchor was live and ED 0 did not sweep at all. Windows hit this on
every ^L: libedit’s built-in termcap clears the screen with CUP home +
ED 0, and the stale blocks broke terminal_blocks. -
TEST: terminal: a C0 control around an OSC 133 mark is not printed
-
FIXED: terminal: ignore unhandled C0 control characters Characters
below 0x20 that have no VT100 meaning were rendered as glyphs.
A bash PS0 carrying readline’s […] markers, for example, makes
bash emit \001 and \002 verbatim before every command’s output.
Real terminals discard such controls. -
ENHANCED: Use ->opacity to grey out an inactive terminal.
-
ADDED: terminal_image ->input_focus: bool Handling the keyboard
focus is now a method of its own rather than inline code in ->event,
allowing subclasses to react on gaining or losing the focus. -
TEST: terminal: a prompt the program wrote survives a resize Resize
while a read that started where the output left the caret is pending,
and check that the row is unchanged, that the caret stayed put and
that ^A goes to the start of the input rather than to column 0. -
TEST: terminal: dump the screen when the no-prompt click misses
click_moves_the_caret_without_a_prompt asserted the caret column with
a bare comparison, which says4=:=10' and nothing about how the caret got there. It is the one caret assertion in the suite a redraw can move: the prompt is the program's own output, so libedit takes the line to start at column 0, and a full refresh paints the input overname: ’ and leaves the caret six columns to the left of the click.
assert_cursor/3 reports the row and the screen, on which that is plain. -
TEST: terminal: sample the terminal rather than the frame chrome
term_screenshot/2 read the top 41 pixel rows of `frame <-image’,
where the Epilog menu bar sits: the terminal starts 38 pixels down.
Every shot therefore sampled the same unchanging chrome, two
shots compared equal whatever the terminal was told to paint, and
terminal_attributes failed on each of its “must differ” assertions
from the day it was added. -
ADDED: Epilog: hide and show the output of every command from the
menu The menu of a fold marker gains Hide/Show all outputs, and Remove
moves up beside the folding it belongs with. -
ADDED: the xpce_defaults flag: decline the user’s Defaults file
XPCE read the class variable defaults on the first lookup of a class
variable, wherever in the program that happened to fall, and read the
file belonging to whoever was running it along with them. A test suite
or an application that must not depend on the preferences of its user
had no way to say so: by the time it could speak they had been read.
This is not hypothetical – a terminal test failed here because the
author had turned a mode on in his own Defaults. -
ADDED: Epilog: close the previous command as one is entered Reading an
OSC 133 mark was a static function with nowhere to put a policy, and the
policy this wanted is not the terminal’s. It becomes ->prompt_mark,
sent from the OSC decoder as ->window_label and ->working_directory
already are, with the letters decoded to what they mean here: where
a prompt starts, where the line the user edits starts, where that
line was entered and its output begins, and where the output ends.
The default implementation is what read them before. -
ADDED: terminal_block->remove: take a command out of the buffer
Folding hides the output of a command; this takes the whole of it away.
The lines it covers go and the text under them moves up into the gap,
which for an input typed over several lines is all of them at once –
they are one block, so they go as one. -
ADDED: Epilog: act on the command the mouse or the caret is on The
terminal knows what its window has been used for; this is what it
takes to reach that. Right-clicking a command offers to copy it,
to copy what it printed, or to hide that output; \C-\S-h folds the
command being edited, and \C-\S-<cursor_up> and \C-\S-<cursor_down>
walk the prompts, as terminals with shell integration do. -
ADDED: Epilog terminal: commands as terminal_block objects, and
folding The OSC 133 marks were read for the one thing the mouse needed
and thrown away. They say more:A' is where a prompt starts,B’
where the line the user edits starts,C' where it was entered and the output begins, andD’ where that output ends. Kept, they are
a model of what the window has been used for, and <-blocks hands it
over as a chain of terminal_block objects, oldest first. -
FIXED: xpce terminal: XPCE_TERM_TRACE printed the wrong parser state
The name table in rlc_putansi() still held the seven states of an older
ansi_state, in the wrong order, so every trace line past CMD_ESC named
a state the parser was not in. It now lists all twelve in enum order. -
FIXED: xpce terminal: ESC > (DECKPNM) left the keypad in application
mode Both ESC = and ESC > set app_keypad_mode to true, so leaving
application keypad mode never took effect. Nothing reads the flag yet,
which is why this went unnoticed. -
FIXED: xpce terminal: enabled the ptsname() NULL check
rlc_open_pty_pair() passed the result of ptsname() straight to strncpy()
because the guard against it returning NULL sat in an #if 0. The name
it reports, NAME_cannotPtsname, is already in the generated table,
so the check only had to be turned back on. -
CLEANUP: xpce terminal: removed the dead Windows-console API terminal.h
still declared the plterm.dll console interface the emulator grew out
of: the RlcHook typedefs and their setters, rlc_read/write/ close,
getch/kbhit, ScreenCols/ScreenRows, the line-edit and completion
structs, the history ring buffer and the lqueued/user_data types.
None of it was ever defined. With them go the five LINE-READ SUPPORT
functions in terminal.c that had no callers, rlc_caret_forward()
which only rlc_goto_mark() used, the rlc_data fields for colours and
scrollbar state that ti-> and the palette replaced, and the unused
GWL_DATA, IMODE_ and OPT_* macros – the last two also shadowed the
OPT_SIZE enum of SWI-Prolog.h. -
FIXED: xpce terminal: a second terminal took the palette Colours with
it A terminal resolves the colour cube and the 24 bit colours of its
client to Colour objects and holds them in its palette between paints.
It held them with ->lock_object, whose F_LOCKED is a flag rather than
a count, while ws_pixel_to_colour() hands every terminal that resolves
an RGBA value the same interned Colour. The first terminal to go
therefore took the protection of all the others with it: deleting a
second Epilog window freed a Colour the first still had in its palette,
and the next paint that used that colour handed r_clear() a Colour
that was gone. Which is a crash in r_set_fill_fgbg(), as reported. -
TEST: terminal: a click with nothing to say a line is being edited
Exercises el_set/2 prompt_marks(false): with the marks and bracketed
paste both off the client says nothing about the line it is editing,
and the caret stays where it is. -
ADDED: Epilog terminal: read the OSC 133 semantic prompt marks A client
that marks its prompts says outright what the terminal could until now
only guess: betweenB' andC’ there is a line being edited, and `B’
landed where it starts. That is what a click needs to know before
it asks the client to move its caret there, and a click in front of
the input now stops at the input rather than walking into the prompt. -
FIXED: Epilog terminal: click sent cursor keys at a single char read
A click in the line being edited asks the client to move its caret, by
sending as many cursor keys as there are grapheme clusters in between.
A client that reads a single character has no caret to move and
answers with the ESC of the first of them: clicking the source link
in a port message of the command line tracer made it print “Unknown
option (h for help)”. -
TEST: run the terminal resize tests with SIGWINCH held back
EPILOG_NO_SIGWINCH keeps rlc_resize_pty() from raising the signal
on the client thread, which leaves libedit where a Windows console
always is and where a lost signal puts us: with nothing but the size
on the pty to go on. That is the path the three resize tests that
press a key were failing on about one run in five, and the only way
to reach it deliberately. -
FIXED: xpce: crash when the window system has no display On a machine
where SDL_Init() fails – headless, or no DISPLAY – xpce loads without
a display object and `new(F, frame(hello))’ then stored a display
that is not there. Reading it crashed the process, in ->create, in
<-display, or in the first window that wanted its default colours.
Say it instead: with no display there is no frame, and no window either. -
TEST: move the alternate screen background erase test to the bce suite
It belongs with the other background colour erase tests, and it runs
there without a pty and without libedit: the whole file takes a second,
where the terminal suite is off unless asked for. Reading pixels is
still the only way to see the painted tail, so the window is sized
to its terminal and the test lets the paint happen before it samples. -
FIXED: xpce: a freed colour left a dangling entry in @rgba A Colour
registers itself in @colours, by name, and in @rgba, by its encoded
RGBA value. Both hold their members withrefer' none, so neither keeps the Colour alive, but ->unlink only took the @colours entry out. The @rgba entry then pointed at memory that had been handed out again, and the next lookup of that colour value returned it:Image <-pixel’
does one per pixel it reads, `Colour <-lookup’ one per new/2 on a colour
with an RGB value, and the terminal one per palette slot it resolves.
This crashed the xpce terminal test suite in about half of its runs. -
FIXED: Epilog terminal: background colour erase lost over the alternate
screen The full-line background of the input lines disappeared after
help/1, and only the text kept its background. The tail of such a
line is painted from the background colour erase (bce) that `\e[K’
records on the line rather than from cells, and rlc_copy_line()
did not carry that record along when smcup saved the screen. -
FIXED: Epilog: warning when inserting a non-ASCII character Typing a
character above 127 into a terminal_image, e.g. using the Unicode symbol
picker, reported “Cannot construct 1-th argument for ->insert_self”.
The key binding maps any character >= 128 to ->insert_self and fills
the argument from the event id, which requires the declared type to
includecharorevent_id. terminal_image declared it as the int
range “0..”. -
ADDED: Epilog terminal: a double-clicked word is matched as a word
Picking a word with a double click says to look for that word, not for
the letters it happens to be made of: a double click onBar' passes overBarn’ while dragging over the same three characters does not.
It also makes a one-character word worth looking for, which a single
character picked any other way is not. A search seeded from such
a selection with ^S or ^R keeps it; one started with \C-\S-f has no
selection to take it from. -
ADDED: Epilog terminal: ^S and ^R search on from the selection With
a selection whose other occurrences are highlighted, ^S and ^R start
an incremental search for what it holds, from where it is, and step
to the next resp. previous match at once – so the matches that are
already lit up are the ones they walk. From there it is the ordinary
search: repeats, Backspace to widen, M-c and M-w, Escape to leave the
hit selected. ^G gives back the view and the selection the search
started from, so a search one did not mean to start costs nothing. -
ADDED: Epilog terminal: highlight the other occurrences of the selection
Selecting text in an Epilog terminal now says what to look for as well
as what to copy: the other places the selected text occurs on the page
are painted in <-isearch_other_style, the way the other matches of an
incremental search are, and the bar reports which of them the selection
is and how many there are, as `Selection: Bar (1/5)'. Picking out
a variable or an atom finds the rest of them without typing it again. -
TEST: terminal: sync with the client before handing out a new terminal
The first test of a unit could find the prompt back on top of what
it painted: the window sends the client a SIGWINCH while it is still
settling on its size, and the client answers that with a redraw of
its input line. Neither wait_for_prompt/1 nor wait_settled/1 covers
that redraw – it paints the prompt where the prompt already is,
so it leaves the screen exactly as it found it. -
TEST: terminal: check that SGR attributes select a font New unit
terminal_attributes. It paints the same glyphs wrapped in each
SGR sequence, samples the window through the new term_screenshot/2
primitive and compares the samples: two shots of the same text differ
exactly when it was painted in a different font, so the test need
not know which font the painter chose. -
ENHANCED: terminal: render italic text (SGR 3) The terminal now draws
italic (SGR 3) text in a slanted font and turns it off again on SGR
23, and combines italic with bold. Epilog claims to be an xterm,
whose terminfo advertises sitm/ritm, so programs were already sending
the sequence and it was being dropped. -
ENHANCED: class style: added ->italic and <-italic A style can now
ask for slanted text through an attribute, the way it already asks
for bold, instead of having to name an italic font in its ->font slot. -
FIXED: class style: setting a second attribute had no effect A style
that already carried one of ->bold, ->highlight, ->grey or ->hidden
silently ignored requests to set or clear another one. -
FIXED: build on Linux: O_CLOEXEC undeclared in the xpce terminal The
pty code asks for_XOPEN_SOURCE 600to get the pty API, and glibc
hides everything newer than POSIX 2001 once that macro is set by hand,
O_CLOEXEC among it. The close-on-exec flags added by the previous
commit therefore did not compile on Linux. MacOS declares the symbol
at any level because this file also defines_DARWIN_C_SOURCE,
which is why it went unnoticed. -
FIXED: shell of an Epilog window survives halting Prolog The
pty descriptors were inherited by every process the client starts.
The client hands its own three to a shell of shell/0 or process_create/3
as stdin, stdout and stderr, and those it is welcome to, but a copy of
the master is another matter: as long as the child holds it, closing our
side is not the last reference and the pty never hangs up. The shell
is then never sent the SIGHUP that closing the master owes it, and it
stays behind, holding whatever else it inherited, after Prolog is gone. -
FIXED: epilog: describe this terminal to the programs that run in it
Epilog claims to be an xterm compatible terminal by settingTERM,
but leftTERM_PROGRAMat the value it inherited from the terminal
it was started from, and run_shell/0 let the shell inherit both.
Programs run from an Epilog window or its shell therefore applied the
quirks of that other terminal to ours. Notably ansi_get_color/2 does
not query a terminal that says it isApple_Terminal, so no program
started from an Epilog window could find out the colours of the window
it runs in, which is what library(theme/auto) uses to pick a theme. -
FIXED: terminal: paint the erased tail of a line with the background
(bce)ESC [ K(Erase in Line) dropped the cells to the right of
the caret rather than painting them with the background colour that
is in effect. As a result a coloured block, such as the striped
answers of the interactive toplevel, only covered its own text and
stopped short of the right margin. -
FIXED: destroying a frame leaked the backing store of its windows
unlinkFrame() uncreated the frame before it freed its members, but
ws_created_window() is false from the moment the frame is uncreated.
uncreateWindow(), reached from freeObject() on each member, therefore
skipped ws_uncreate_window() and leaked the Cairo backing surface
and the WsWindow of every window of every destroyed frame. -
FIXED: SDL: dangling pointer to the window holding the pointer
grab grabbing_window held a bare pointer, so a window that grabbed
the pointer and then destroyed itself – Epilog’s “Halt Prolog”
menu item does exactly that – was unallocated while the event loop
still referred to it. Hold a code reference as we do for the mouse
tracking window, which also makes the F_FREED test a valid read,
and report the recovery under DEBUG(event) rather than on the console. -
FIXED: Epilog: “Halt Prolog” when Epilog runs inside a Prolog toplevel
The menu item asserted quit_requested/0, which is only examined
by ep_wait__/0, i.e., when Epilog is the main goal. Started using
epilog/0 from a running Prolog there is no such loop and the item
did nothing. Track whether ep_wait/1 is active in ep_main_running/0
and call halt/0 directly if it is not. -
FIXED: gcc -Wstringop-truncation warning on MacOS and FreeBSD. The path
fields of the OS structs used to find the working directory of the
foreground process are fixed size arrays that need not be terminated.
Bound the copy by the field size and fail if the path does not fit
rather than returning a truncated one. -
ADDED: Epilog profile/2: a profile/1 option to refine another profile.
A profile that gives profile(Super) takes Super’s options for the ones
it does not give itself, so a profile can be a shell in a particular
directory or a toplevel with a particular background without repeating
what it inherits. This is the option epilog/1 already takes to pick
a profile, now meaningful in a profile of its own. -
ADDED: epilog/1: inject(Spec) option to type at a new terminal.
Spec is an item or a list of items. A string is typed as a line of
text, any other item as a Prolog goal, using ->inject. As we cannot
tell whether the terminal runs a shell or Prolog, the caller says so
by choosing the type. -
ADDED: xpce timer ->start: number of times to fire, and <-times.
A timer started as ->start(repeat, N) fires N times and goes idle.
<-times is what is left of that, counted off before the message runs,
so a message that sees 0 knows it was the last one and may start the
timer again, as it may for a `once’ timer. Without the argument a
timer repeats as before. -
FIXED: xpce terminal ->send: write to a pty we never opened or
already closed. rlc_send() tested the master fd for non-zero.
The struct is zeroed before the pty is opened, so “never opened”
was caught, but rlc_close_connection() leaves -1, which passed the
test and reached write(-1, …). -
PORT: Make compile on MacOS again.
-
FIXED: Epilog and PceEmacs: the column of a source location
counts from 1. Clicking a link with a column, e.g., produced by
rg --hyperlink-format=file://{path}#L{line}:{column}, placed
the caret one character to the right, as theline_posof an xpce
source_location counts from 0 while edit/1 and the tools that emit
such links count from 1. Epilog now also accepts the#L<line>
form used by GitHub and rg. -
FIXED: xpce terminal: a coloured hyperlink label kept the colours
of its client. Thelink_stylecolours now only apply to cells
for which the client did not select a colour itself. A client that
colours its links, e.g.,rg --hyperlink-format=..., had its colours
replaced by the link style. The underline of the link style still
marks the link, and thelink_armed_styleused while hovering keeps
replacing the colours: that is transient feedback which must show on
a coloured link as well. -
MODIFIED: PceEmacs File/Shell now starts a shell in an Epilog window.
-
FIXED: xpce terminal: translating a click to a cell was one cell off.
Clicking the last character of a hyperlink did not open it and clicking
the cell before it did, as the pixel of a click was mapped to the
cell boundary at or after it rather than to the cell containing it. -
FIXED: xpce terminal: process escape sequences inside an OSC
8 hyperlink. An OSC 8 hyperlink is a state rather than a self
contained sequence: the label betweenESC ] 8 ; <params> ; <URL> STand the same sequence with an empty URL is ordinary output that
may carry SGR sequences. We used to collect the label as text, so
a client that colours its links, e.g.,rg --hyperlink-format=...,
painted the escape sequences on the screen. Parameters such asid=
are now accepted as well. -
ADDED: library(epilog): profiles for new terminal windows. A profile
is a named set of options for epilog/1. The built-in profiles are
prolog, which runs the Prolog top level, andshell, which runs an
interactive OS shell in the terminal. New and split windows inherit
the profile and start in the working directory reported by the window
they were created from. Profiles are added using the multifile hook
epilog:profile/2. -
ADDED: xpce terminal_image <-working_directory, <-foreground_directory
and <-host A client that reports its directory using OSC 7 (ESC ] 7 ;
file://host/path ST), which shells emit from their prompt hook, or
using OSC 9;9, the Windows spelling, now updates <-working_directory
and <-host. <-foreground_directory instead asks the OS where
<-foreground_process is, which needs no cooperation from the client,
but only works on Linux, macOS, FreeBSD, NetBSD and Solaris. -
FIXED: terminal: pass Ctrl+Z to a process running in the terminal
Ctrl+Z was dropped unconditionally, so a shell started on a terminal
could not suspend its jobs. -
FIXED: Ctrl+, Ctrl+], Ctrl+^ and Ctrl+_ to produce a control character
These keys were passed on as the plain punctuation character, so a
program running in a terminal could not be sent SIGQUIT with Ctrl+. -
FIXED: terminal: clear(1) left the old screen behind ED 3 (erase saved
lines) rebased the ring on slot 0 when the window was already empty,
but left the text of those slots and the caret where they were, so
the screen came back with old content. `clear’ sends ED 2 before ED
3 and hit exactly that. -
ADDED: epilog:profile/2 Multifile hook. This hook can be used to
define new Epilog profiles. For exampleepilog:profile(shell, [title('Shell'), goal(shell)]). -
ADDED: epilog: a bar over the terminal for messages and search options
The incremental search says what it is looking for, how many there
are and whether it found anything; until now nothing in an epilog
window could show that. Its frame has no reporter, so the ->report
calls already there – the ones the font commands make – went nowhere. -
ADDED: terminal_image: Emacs style incremental search on Ctrl-Shift-F
Type and the terminal highlights what it finds and scrolls to it.
^S and ^R walk the matches, backspace widens the search again, ESC
leaves the hit where it is and ^G gives back the view the search
started from. As in class editor, a focus function sits in the way
of ->typed and sees every key until the search ends. -
ADDED: terminal_image: search the buffer with <-find <-find, <-length
and <-contents address the terminal’s buffer as a flat sequence
of characters, and ->selection and ->scroll_to take an index in
that same space, so a hit can be highlighted and brought into view.
<-find follows text_buffer<-find in its arguments, its defaults and
in failing rather than raising when there is no match. -
ADDED: epilog/1: option background(Colour).
-
ADDED: epilog/1: option goal_split(Goal) to determine the goal to
run in a new splitted terminal. -
MODIFIED: Class
terminal_image: first try to process Shift-Ctrl-Key
or Gui-Key as accelerator -
TEST: terminal: wait for the shell of shell/1 to be reading
start_interactive_shell/1 slept a second and hoped; it now waits for
the shell’s prompt. What is typed next then reaches a shell that
is reading, and ^D in particular is no longer lost: on an empty line
it is end of input to the line discipline, which hands it to whoever
reads next as a zero-length read. A shell that has not put its own
line editor on the terminal yet is not reading, and by the time it
does the terminal is in raw mode, where the ^D the line discipline
already consumed cannot come back.