I want to make nice tables like you see on some manual page of Linux documentation
in C programming language. Is there any library or functions to create a table like them.
For example a table that you can find on man syslog like the following, produced by running man syslog:
┌──────────────────────┬───────────────┬────────────────────┐
│Interface │ Attribute │ Value │
├──────────────────────┼───────────────┼────────────────────┤
│openlog(), closelog() │ Thread safety │ MT-Safe │
├──────────────────────┼───────────────┼────────────────────┤
│syslog(), vsyslog() │ Thread safety │ MT-Safe env locale │
└──────────────────────┴───────────────┴────────────────────┘
This was probably done with "tbl". See man tbl. Also see the L. L. Cherry
and M. E. Lesk document "Tbl — A Program to Format Tables" which can be found via Google.
An example
This file:
$ cat f.tbl
.TS
allbox;
c s s
c c c
n n n.
AT&T Common Stock
Year Price Dividend
1984 15-20 $1.20
5 19-25 1.20
6 21-28 1.20
7 20-36 1.20
8 24-30 1.20
9 29-37 .30*
.TE
* (first quarter only)
Produced this (with tbl f.tbl > f.troff; nroff f.troff):
┌────────────────────────┐
│ AT&T Common Stock │
├─────┬───────┬──────────┤
│Year │ Price │ Dividend │
├─────┼───────┼──────────┤
│1984 │ 15‐20 │ $1.20 │
├─────┼───────┼──────────┤
│ 5 │ 19‐25 │ 1.20 │
├─────┼───────┼──────────┤
│ 6 │ 21‐28 │ 1.20 │
├─────┼───────┼──────────┤
│ 7 │ 20‐36 │ 1.20 │
├─────┼───────┼──────────┤
│ 8 │ 24‐30 │ 1.20 │
├─────┼───────┼──────────┤
│ 9 │ 29‐37 │ .30* │
└─────┴───────┴──────────┘
* (first quarter only)
You can take a look at the ncurses library here: http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/
Related
In the following directory structure:
.
├── a
│ ├── 1
│ ├── 2
│ ├── 3
│ └── 4
├── b
│ ├── 5
│ ├── 6
│ ├── 7
│ └── 8
├── c
├── d
└── test.hy
The following code prints the wrong path:
(eval-and-compile (import os) (import pathlib [Path]))
(defmacro with-cwd [dir #* body]
`(let [ cwd (.cwd Path) ]
(try (.chdir os ~dir)
~#body
(finally (.chdir os cwd)))))
(defmacro let-cwd [dir vars #* body] `(let ~vars (with-cwd ~dir ~#body)))
(setv a (/ (. (Path __file__) parent) "a"))
(let-cwd a [ b (/ a.parent "b") ] (print f"Hello from {(.cwd Path)}!\n") (print (.resolve b)))
It is supposed to print the following:
Hello from /home/shadowrylander/with-cwd-test/a!
/home/shadowrylander/with-cwd-test/b
While it is instead printing:
Hello from /home/shadowrylander/with-cwd-test/a!
/home/shadowrylander/with-cwd-test/a/b
Why is b not properly assigned when doing (quasiquote (let ~vars (with-cwd ~dir ~#body)))?
This looks like a bug (https://github.com/hylang/hy/issues/2318), although it has to do with __file__ and is unrelated to let or macros. Remember, when you run into trouble, simplify your problematic code as much as you can, so you can figure out what's going on.
It all started with the fact that at some point Pluto did not start, giving an error for incompatibility with some package. I removed several packages that seemed to me a possible source of problems, and started updating the packages, as a result of which I received a complaint about incompatibility with a specific package. I also deleted it - I received a complaint on the next one, and so on several times. The situation turned out to be too complicated and I completely deleted the directory with the packages and installed them again. But the mistake was repeated again. Now I have recorded everything in more detail. First, Pluto gave an error in connection with package "FuzzyCompletions" that I did not specifically install:
Warning: Reading WebSocket client stream failed for unknown reason:
│ parentbody = Dict{Any,Any} with 5 entries: …
│ exception =
│ TaskFailedException:
│ On worker 2:
│ LoadError: Unsatisfiable requirements detected for package FuzzyCompletions [fb4132e2]:
│ FuzzyCompletions [fb4132e2] log:
│ ├─FuzzyCompletions [fb4132e2] has no known versions!
│ └─restricted to versions 0.3-0.4 by an explicit requirement — no versions left
│ check_constraints at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Pkg\src\Resolve\graphtype.jl:935
│ Graph at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Pkg\src\Resolve\graphtype.jl:362
│ deps_graph at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Pkg\src\Operations.jl:502
│ resolve_versions! at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Pkg\src\Operations.jl:374
│ up at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Pkg\src\Operations.jl:1222
│ #up#106 at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Pkg\src\API.jl:245
│ #up#38 at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Pkg\src\API.jl:68 [inlined]
│ #instantiate#170 at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Pkg\src\API.jl:810
│ instantiate at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Pkg\src\API.jl:795
│ top-level scope at C:\Users\ten\.julia\packages\Pluto\luIaC\src\runner\Loader.jl:22
│ include at .\client.jl:457
│ top-level scope at none:1
│ eval at .\boot.jl:331
│ #103 at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Distributed\src\process_messages.jl:290
│ run_work_thunk at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Distributed\src\process_messages.jl:79
│ run_work_thunk at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Distributed\src\process_messages.jl:88
│ #96 at .\task.jl:356
│ in expression starting at C:\Users\ten\.julia\packages\Pluto\luIaC\src\runner\Loader.jl:1
│ Stacktrace:
│ [1] sync_end(::Channel{Any}) at .\task.jl:314
│ [2] macro expansion at .\task.jl:333 [inlined]
│ [3] remotecall_eval(::Module, ::Array{Int64,1}, ::Expr) at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Distributed\src\macros.jl:218
│ [4] create_workspaceprocess(; compiler_options::Pluto.Configuration.CompilerOptions) at C:\Users\ten\.julia\packages\Pluto\luIaC\src\evaluation\WorkspaceManager.jl:170
│ [5] make_workspace(::Tuple{Pluto.ServerSession,Pluto.Notebook}) at C:\Users\ten\.julia\packages\Pluto\luIaC\src\evaluation\WorkspaceManager.jl:43
│ [6] #7 at C:\Users\ten\.julia\packages\Pluto\luIaC\src\evaluation\WorkspaceManager.jl:188 [inlined]
│ [7] macro expansion at C:\Users\ten\.julia\packages\Pluto\luIaC\src\evaluation\Tokens.jl:76 [inlined]
│ [8] (::Pluto.var"#1#2"{Pluto.WorkspaceManager.var"#7#9"{Tuple{Pluto.ServerSession,Pluto.Notebook}},Pluto.Promise{Pluto.WorkspaceManager.Workspace}})() at .\task.jl:356
│ Stacktrace:
│ [1] wait at .\task.jl:267 [inlined]
│ [2] wait(::Pluto.Promise{Pluto.WorkspaceManager.Workspace}) at C:\Users\ten\.julia\packages\Pluto\luIaC\src\evaluation\Tokens.jl:83
│ [3] get_workspace at C:\Users\ten\.julia\packages\Pluto\luIaC\src\evaluation\WorkspaceManager.jl:190 [inlined]
│ [4] (::Pluto.var"#204#206")(::Pluto.ServerSession, ::Dict{Any,Any}, ::Pluto.Notebook; initiator::Pluto.Initiator) at C:\Users\ten\.julia\packages\Pluto\luIaC\src\webserver\REPLTools.jl:92
│ [5] process_ws_message(::Pluto.ServerSession, ::Dict{Any,Any}, ::HTTP.WebSockets.WebSocket{HTTP.ConnectionPool.Transaction{Sockets.TCPSocket}}) at C:\Users\ten\.julia\packages\Pluto\luIaC\src\webserver\WebServer.jl:357
│ [6] (::Pluto.var"#215#225"{Pluto.ServerSession,Base.RefValue{Function}})(::HTTP.WebSockets.WebSocket{HTTP.ConnectionPool.Transaction{Sockets.TCPSocket}}) at C:\Users\ten\.julia\packages\Pluto\luIaC\src\webserver\WebServer.jl:160
│ [7] upgrade(::Pluto.var"#215#225"{Pluto.ServerSession,Base.RefValue{Function}}, ::HTTP.Streams.Stream{HTTP.Messages.Request,HTTP.ConnectionPool.Transaction{Sockets.TCPSocket}}; binary::Bool) at C:\Users\ten\.julia\packages\HTTP\IAI92\src\WebSockets.jl:160│ [8] upgrade at C:\Users\ten\.julia\packages\HTTP\IAI92\src\WebSockets.jl:142 [inlined]
│ [9] (::Pluto.var"#214#224"{Pluto.ServerSession,HTTP.Handlers.Router{Symbol("##280")},Base.RefValue{Function}})(::HTTP.Streams.Stream{HTTP.Messages.Request,HTTP.ConnectionPool.Transaction{Sockets.TCPSocket}}) at C:\Users\ten\.julia\packages\Pluto\luIaC\src\webserver\WebServer.jl:147
│ [10] handle at C:\Users\ten\.julia\packages\HTTP\IAI92\src\Handlers.jl:269 [inlined]
│ [11] #4 at C:\Users\ten\.julia\packages\HTTP\IAI92\src\Handlers.jl:345 [inlined]
│ [12] macro expansion at C:\Users\ten\.julia\packages\HTTP\IAI92\src\Servers.jl:367 [inlined]
│ [13] (::HTTP.Servers.var"#13#14"{HTTP.Handlers.var"#4#5"{HTTP.Handlers.StreamHandlerFunction{Pluto.var"#214#224"{Pluto.ServerSession,HTTP.Handlers.Router{Symbol("##280")},Base.RefValue{Function}}}},HTTP.ConnectionPool.Transaction{Sockets.TCPSocket},HTTP.Streams.Stream{HTTP.Messages.Request,HTTP.ConnectionPool.Transaction{Sockets.TCPSocket}}})() at .\task.jl:356
└ # Pluto C:\Users\ten\.julia\packages\Pluto\luIaC\src\webserver\WebServer.jl:168
During the initial installation of the packages, there were no errors or warnings, this error was the first one
I decided to try to remove Pluto and run the update, but after that I got the following error:
julia> Pkg.rm("Pluto")
Updating `C:\Users\ten\.julia\environments\v1.5\Project.toml`
[c3e4b0f8] - Pluto v0.12.18
Updating `C:\Users\ten\.julia\environments\v1.5\Manifest.toml`
[fb4132e2] - FuzzyCompletions v0.4.0
[99f44e22] - MsgPack v1.1.0
[c3e4b0f8] - Pluto v0.12.18
julia> Pkg.update()
ERROR: Unsatisfiable requirements detected for package Distributions [31c24e10]:
Distributions [31c24e10] log:
├─Distributions [31c24e10] has no known versions!
└─restricted to versions * by an explicit requirement — no versions left
Deleted it, and got a claim to the next package:
julia> Pkg.rm("Distributions")
Updating `C:\Users\ten\.julia\environments\v1.5\Project.toml`
[31c24e10] - Distributions v0.24.10
No Changes to `C:\Users\ten\.julia\environments\v1.5\Manifest.toml`
julia> Pkg.update()
ERROR: Unsatisfiable requirements detected for package CSV [336ed68f]:
CSV [336ed68f] log:
├─CSV [336ed68f] has no known versions!
└─restricted to versions * by an explicit requirement — no versions left
Deleted it, and got a claim to the next package:
julia> Pkg.rm("CSV")
Updating `C:\Users\ten\.julia\environments\v1.5\Project.toml`
[336ed68f] - CSV v0.8.2
No Changes to `C:\Users\ten\.julia\environments\v1.5\Manifest.toml`
julia> Pkg.update()
ERROR: Unsatisfiable requirements detected for package DataFrames [a93c6f00]:
DataFrames [a93c6f00] log:
├─DataFrames [a93c6f00] has no known versions!
└─restricted to versions * by an explicit requirement — no versions left
Perhaps it would be possible to continue this way, but it is obvious that this would not solve the problem. So I stopped and decided to ask for advice
All the packages I use are pretty standard. Here is the current status of what is left after the deletion:
julia> Pkg.status()
Status `C:\Users\ten\.julia\environments\v1.5\Project.toml`
[dcc97b0b] GeoStats v0.21.0
[916415d5] Images v0.23.3
[682c06a0] JSON v0.21.1
[91a5bcdd] Plots v1.10.1
[7f904dfe] PlutoUI v0.6.11
[92933f4c] ProgressMeter v1.4.1
[6f49c342] RCall v0.13.10
[de0858da] Printf
[9a3f8284] Random
[10745b16] Statistics
I have not found any recipes for what to do in the case of such cascading accidents and what may be their cause. If I did something wrong, I'm ready to once again completely tear down the packages folder and install them again. But it seems that I do not understand the reasons for what is happening, so I would like to understand the nature of this phenomenon, so that this does not happen again in the future
As I already wrote in the comments the problem probably lies in the Julia registry.
To have a broader insight on what registries are and how they work you might give a look at the Documentation.
To check the status of the registry you can use (within the REPL) ] registry status and to update it ] registry update.
However, there might got something broken. Then you can delete and add the registry back.
This is done by:
pkg> registry rm General
pkg> registry add https://github.com/JuliaRegistries/General
where pkg> is the Pkg.jl REPL that you enter with a ].
I have two processes wrote in C that set up PUSH/PULL ZeroMQ sockets and two threads in a Python process that mirror the PUSH/PULL sockets. There are roughly 80 - 300 light weight (<30 bytes) messages per second being sent from the C process to the Python process, and 10-30 similar messages from the Python process to the C process.
I was running these services on 64 bit ARMv8 (Ubuntu based) and AMD64 (Ubuntu 18.04) with no noticeable latency. I tried running the exact same services on a 32 bit Linux based system and was shocked to see messages coming through over 30 seconds behind, even after killing the C services. When checking the CPU usage, it was pretty flat 30-40% and didn't appear to be the bottle neck.
My ZeroMQ socket settings didn't change between systems, I set LINGER to 0, I tried RCVTIMEO between 0 to 100 ms, and I tried varying BACKLOG between 0 and 50, with no difference either way. I tried using multiple IO threads and setting socket thread affinity, also to no avail. For the PUSH sockets I'm connecting the sockets on tcp://localhost:##### and binding the PULL sockets to tcp://*:#####. I also used ipc:///tmp/..., messages were being sent and received, but the latency still existed on the 32 bit system.
I investigated other Python steps in-between receiving the messages, and they don't appear to be taking more than a millisecond at most. When I time the socket.recv(0) it's as high as 0.02 seconds even when the RCVTIMEO is set to 0 for that socket.
Any suggestions why I would see this behaviour on the new 32 bit platform and not on other platforms? Am I possibly looking in all the wrong places?
Here's a bit of code to help explain:
The connection and the _recv() class-method are roughly depicted below:
def _connect(self):
self.context = zmq.Context(4)
self.sink = self.context.socket(zmq.PULL)
self.sink.setsockopt(zmq.LINGER, 0)
self.sink.setsockopt(zmq.RCVTIMEO, 100)
self.sink.setsockopt(zmq.BACKLOG, 0)
self.sink.bind("tcp://*:55755")
def _recv(self):
while True:
msg = None
try:
msg = self.sink.recv(0) # Use blocking or zmq.NOBLOCK, still appears to be slow
except zmq.Error
... meaningful exception handle here
# This last step, when timed usually takes less than a millisecond to process
if msg:
msg_dict = utils.bytestream_to_dict(msg) # unpacking step (negligible)
if msg_dict:
self.parser.parse(msg_dict) # parser is a dict of callbacks also negligible
On the C process side
zmq_init (4);
void *context = zmq_ctx_new ();
/* Connect the Sender */
void *vent = zmq_socket (context, ZMQ_PUSH);
int timeo = 0;
int timeo_ret = zmq_setsockopt(vent, ZMQ_SNDTIMEO, &timeo, sizeof(timeo));
if (timeo_ret != 0)
error("Failed to set ZMQ recv timeout because %s", zmq_strerror(errno));
int linger = 100;
int linger_ret = zmq_setsockopt(vent, ZMQ_LINGER, &linger, sizeof(linger));
if (linger_ret != 0)
error("Failed to set ZMQ linger because %s", zmq_strerror(errno));
if (zmq_connect (vent, vent_port) == 0)
info("Successfully initialized ZeroMQ ventilator on %s", vent_port);
else {
error("Failed to initialize %s ZeroMQ ventilator with error %s", sink_port,
zmq_strerror(errno));
ret = 1;
}
...
/* When a message needs to be sent it's instantly hitting this where msg is a char* */
ret = zmq_send(vent, msg, msg_len, ZMQ_NOBLOCK);
On docker running on target 32 bit system
lstopo - -v --no-io
Machine (P#0 local=1019216KB total=1019216KB HardwareName="Freescale i.MX6 Quad/DualLite (Device Tree)" HardwareRevision=0000 HardwareSerial=0000000000000000 Backend=Linux LinuxCgroup=/docker/d2b0a3b3a5eedb7e10fc89fdee6e8493716a359597ac61350801cc302d79b8c0 OSName=Linux OSRelease=3.10.54-dey+g441c8d4 OSVersion="#1 SMP PREEMPT RT Tue Jan 28 12:11:37 CST 2020" HostName=db1docker Architecture=armv7l hwlocVersion=1.11.12 ProcessName=lstopo)
Package L#0 (P#0 CPUModel="ARMv7 Processor rev 10 (v7l)" CPUImplementer=0x41 CPUArchitecture=7 CPUVariant=0x2 CPUPart=0xc09 CPURevision=10)
Core L#0 (P#0)
PU L#0 (P#0)
Core L#1 (P#1)
PU L#1 (P#1)
Core L#2 (P#2)
PU L#2 (P#2)
Core L#3 (P#3)
PU L#3 (P#3)
depth 0: 1 Machine (type #1)
depth 1: 1 Package (type #3)
depth 2: 4 Core (type #5)
depth 3: 4 PU (type #6)
EDIT:
We were able to make the latency disappear on our target machine by disabling nearly all other worker threads.
Q : roughly 80 - 300 light weight (<30 bytes) messages per second being sent from the C process to the Python process, and 10-30 similar messages from the Python process to the C process.
a ) there is Zero information about sending any messages from python to C ( not about this contained in the posted source code, only C PUSH-es to python )
b ) 300 [Hz] < 30 B payloads are nothing, in terms of ZeroMQ capabilities
c ) python is, since ever ( and almost for sure will remain so ), a pure-[SERIAL] in sense, whatever amount of Thread-instances, so any the execution will have to wait till it gets POSACK'ed the GIL-lock ownership, blocking any other work, thus re-instating a pure-[SERIAL] work one-step-after-another... yet at an additional costs of GIL-lock handshaking added.
d ) given all processes run on the same hardware-platform ( see the tcp://localhost... specified ), there is no reason to spawn as many as ( 4 + 4 )-IO-threads ( where python cannot "harness"-em on reading by a just one and a single-thread at a time (slo-mo), given no more but 4-CPU-cores were reported above by an lstopo excerpt:
Machine (995MB)
+Package L#0
Core L#0 +PU L#0 (P#0)
Core L#1 +PU L#1 (P#1)
Core L#2 +PU L#2 (P#2)
Core L#3 +PU L#3 (P#3)
e) ISO-OSI-L2/L3 parameters make sense to tweak but after all larger sources of latency got shaved off.
f) last, but not least, run python pystone test ( on both the original platform and the target-hardware platform ), to see the actual relative performance of the i.MX6-CPU-powered python, to become able to compare apples to apples
Running pystone on the target machine results in: This machine benchmarks at 10188.5 pystones/second and my host machine is 274264 pystones/second
so, the problem with the deployment onto an i.MX6-target is not just its 32-bit O/S per se, but also the 27x slower processing of over-subscribed IO-threads ( more threads 4+4 than 4-CPU-cores ) do not improve the flow of messages.
A better view, served by lstopo-no-graphics -.ascii
┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Machine (31876MB) │
│ │
│ ┌────────────────────────────────────────────────────────────┐ ┌───────────────────────────┐ │
│ │ Package P#0 │ ├┤╶─┬─────┼┤╶───────┤ PCI 10ae:1F44 │ │
│ │ │ │ │ │ │
│ │ ┌────────────────────────────────────────────────────────┐ │ │ │ ┌────────────┐ ┌───────┐ │ │
│ │ │ L3 (8192KB) │ │ │ │ │ renderD128 │ │ card0 │ │ │
│ │ └────────────────────────────────────────────────────────┘ │ │ │ └────────────┘ └───────┘ │ │
│ │ │ │ │ │ │
│ │ ┌──────────────────────────┐ ┌──────────────────────────┐ │ │ │ ┌────────────┐ │ │
│ │ │ L2 (2048KB) │ │ L2 (2048KB) │ │ │ │ │ controlD64 │ │ │
│ │ └──────────────────────────┘ └──────────────────────────┘ │ │ │ └────────────┘ │ │
│ │ │ │ └───────────────────────────┘ │
│ │ ┌──────────────────────────┐ ┌──────────────────────────┐ │ │ │
│ │ │ L1i (64KB) │ │ L1i (64KB) │ │ │ ┌───────────────┐ │
│ │ └──────────────────────────┘ └──────────────────────────┘ │ ├─────┼┤╶───────┤ PCI 10bc:8268 │ │
│ │ │ │ │ │ │
│ │ ┌────────────┐┌────────────┐ ┌────────────┐┌────────────┐ │ │ │ ┌────────┐ │ │
│ │ │ L1d (16KB) ││ L1d (16KB) │ │ L1d (16KB) ││ L1d (16KB) │ │ │ │ │ enp2s0 │ │ │
│ │ └────────────┘└────────────┘ └────────────┘└────────────┘ │ │ │ └────────┘ │ │
│ │ │ │ └───────────────┘ │
│ │ ┌────────────┐┌────────────┐ ┌────────────┐┌────────────┐ │ │ │
│ │ │ Core P#0 ││ Core P#1 │ │ Core P#2 ││ Core P#3 │ │ │ ┌──────────────────┐ │
│ │ │ ││ │ │ ││ │ │ ├─────┤ PCI 1002:4790 │ │
│ │ │ ┌────────┐ ││ ┌────────┐ │ │ ┌────────┐ ││ ┌────────┐ │ │ │ │ │ │
│ │ │ │ PU P#0 │ ││ │ PU P#1 │ │ │ │ PU P#2 │ ││ │ PU P#3 │ │ │ │ │ ┌─────┐ ┌─────┐ │ │
│ │ │ └────────┘ ││ └────────┘ │ │ └────────┘ ││ └────────┘ │ │ │ │ │ sr0 │ │ sda │ │ │
│ │ └────────────┘└────────────┘ └────────────┘└────────────┘ │ │ │ └─────┘ └─────┘ │ │
│ └────────────────────────────────────────────────────────────┘ │ └──────────────────┘ │
│ │ │
│ │ ┌───────────────┐ │
│ └─────┤ PCI 1002:479c │ │
│ └───────────────┘ │
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
I am trying out ncurses programming in C on Linux (Mint) and am having a strange problem. I keep getting windows with the wrong number of columns for the first and final lines. For example, with this code found on StackOverflow
#include <ncurses.h>
int main(){
initscr();
WINDOW * win = newwin(10,50,10,10);
box(win,0,0);
wrefresh(win);
wgetch(win);
endwin();
return 0;
}
I get this output:
┌─┐
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
└─┘
As if the first and final lines are only three columns wide. If I add text to the window, using waddch, I can only add three characters to the top line as well.
Any help would be appreciated, I can't find examples of other people running into this issue on the web, but it's not the easiest thing to come up with a good search string for.
Looks like you're using one of those xterm look-alikes, and running into their omission of repeat-character, noted a little over a year ago in the ncurses FAQ.
In Dyalog APL there is ⎕ML which changes how partition operates.
When ⎕ML←0
(5 ⍴ 1 0) ⊂ 5 5 ⍴ ⍳25
┌→─────────────────────┐
│ ┌→────┐ ┌→────┐ ┌→─┐ │
│ ↓ 1 2│ ↓ 3 4│ ↓ 5│ │
│ │ 6 7│ │ 8 9│ │10│ │
│ │11 12│ │13 14│ │15│ │
│ │16 17│ │18 19│ │20│ │
│ │21 22│ │23 24│ │25│ │
│ └~────┘ └~────┘ └~─┘ │
└∊─────────────────────┘
For the same statement (5 ⍴ 1 0) ⊂ 5 5 ⍴ ⍳25 in GNU APL
┏→━━━━━━━━━━━━━┓
↓┏→┓ ┏→┓ ┏→┓ ┃
┃┃1┃ ┃3┃ ┃5┃ ┃
┃┗━┛ ┗━┛ ┗━┛ ┃
┃┏→┓ ┏→┓ ┏→━┓┃
┃┃6┃ ┃8┃ ┃10┃┃
┃┗━┛ ┗━┛ ┗━━┛┃
┃┏→━┓ ┏→━┓ ┏→━┓┃
┃┃11┃ ┃13┃ ┃15┃┃
┃┗━━┛ ┗━━┛ ┗━━┛┃
┃┏→━┓ ┏→━┓ ┏→━┓┃
┃┃16┃ ┃18┃ ┃20┃┃
┃┗━━┛ ┗━━┛ ┗━━┛┃
┃┏→━┓ ┏→━┓ ┏→━┓┃
┃┃21┃ ┃23┃ ┃25┃┃
┃┗━━┛ ┗━━┛ ┗━━┛┃
┗∊━━━━━━━━━━━━━┛
Dyalog APL also does this when ⎕ML←3
Is there a way to alter how GNU APL behaves to obtain the same behaviour?
The short answer is no, because GNU APL follows IBM APL2 language conventions.
The core APL language was developed and perfected by the mid 1970s. However, Nested Arrays started coming a bit later, perhaps the first preliminary sneak peek implementations came out starting around 1980.
The major players at the time were IBM, I. P. Sharp Associates, STSC, and Dyalog, a relative newcomer. All nested array implementations differed in one detail or another, arguably the biggest such difference was the implementation of boxed arrays by Sharp which were the basis of the boxed array implementation found today in J.
Arguably, at the time, Mainframe IBM APL2 probably had the largest market share.
STSC would later change its name to Manugistics and the implementation would evolve into APL2000's APL+ product suite.
Both STSC and Dyalog provided some compatibility mode around the various nested array subspecies, STSC's was the )EVLEVEL system command, evolution level, and Dyalog's was []ML, migration level.
In a nutshell, Dyalog's []ML can be set to 0, 1, 2, or 3. From Dyalog's documentation,
[]ML 0 is the default native Dyalog nested array implementation
[]ML 1 changes the definition of monadic epsilon to be the "enlist" function, a kind of super-ravel
[]ML 2 swaps the definitions of the symbols used for the "first" and "mix" functions, plus presents an alternate definition of the "depth" function
[]ML 3 provides IBM APL2 compatibility.
Personally, I use []ML 3 almost exclusively, as I programmed heavily in APL2 when mainframes were still around.
Again, GNU APL follows IBM APL2 language compatibility. One way to achieve alternate enclose behaviours is to write cover functions to emulate the specialities of other implementations.