Skip to content

Commit bc0d4ec

Browse files
committed
finish the batch interface
1 parent 16a722f commit bc0d4ec

File tree

9 files changed

+261
-61
lines changed

9 files changed

+261
-61
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
- fix an infobar race
1717
- program: add find unresolved syms
1818
- lots more vips7 compat macros
19-
- fix nip4-batch as a shebang interpreter
19+
- fix up nip4-batch
20+
- add some man pages
2021

2122
## 9.0.12 2025/08/21
2223

TODO

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1-
- test other nip4-batch options
1+
- main_shutdown() takes a LONG time
22

3-
benchmark on banana
3+
can we just del temp files maybe? just call vips_shutdown()?
4+
5+
- stop menu loading when we're not in workspace mode?
6+
7+
or maybe we do this already?
48

59
- add tab completion ... somewhat like VS intellisense
610

man/meson.build

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
install_man(
2+
'nip4.1',
3+
'nip4-batch.1',
4+
)

man/nip4-batch.1

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
.TH NIP4-BATCH 1 "Oct 4 2025"
2+
3+
.SH NAME
4+
.PP
5+
nip4-batch - command-line interface to the nip4 image processing spreadsheet
6+
7+
.SH SYNOPSIS
8+
.B nip4-batch
9+
.I filename
10+
.RI [ arg1.. ]
11+
.br
12+
.B nip4-batch -e
13+
.I expression
14+
.RI [ arg1.. ]
15+
.br
16+
.B nip4-batch -w
17+
.RI [ filename1.. ]
18+
19+
.SH DESCRIPTION
20+
.B nip4-batch
21+
is a command-line interface to the
22+
.B nip4(1)
23+
image processing spreadsheet.
24+
25+
There are three principal modes:
26+
27+
.TP
28+
.B nip4-batch filename [ arg1.. ]
29+
Load filename as a set of definitions and pass in any other arguments as
30+
argc and argv. This is the default mode and is suitable for writing scripts
31+
in nip4's programming language.
32+
33+
.TP
34+
.B nip4-batch -e expression [ arg1.. ]
35+
Set main = expression, set argc and argc to any remaining arguments, and
36+
print the value of symbol "main" to stdout.
37+
38+
.TP
39+
.B nip4-batch -w [ filename1.. ]
40+
Load the named files as workspaces or images. You can use the options below
41+
to pass the workspace parameters and control what workspace results are
42+
saved or printed.
43+
44+
.SS "Command Line Options"
45+
.PP
46+
These options give more precise control over nip4-batch's behaviour.
47+
48+
.TP
49+
.B --workspace
50+
Load arguments as workspaces.
51+
52+
.TP
53+
.BI --expression= expression
54+
Evaluate
55+
.I expression
56+
and print the result to stdout. Any other arguments are loaded as argc and
57+
argv.
58+
59+
.TP
60+
.BI --output= filename
61+
The value of main is written to
62+
.I filename.
63+
If main is a
64+
list, the filename is incremented between objects. You can use
65+
the suffix to specify the format and options to write in.
66+
67+
.TP
68+
.B --print-main
69+
Print the value of main on exit. nip4-batch will check for a top-level
70+
symbol called main, and also check each workspace for a main.
71+
72+
.SS "Debugging Options"
73+
.PP
74+
Some other options are useful for debugging, benchmarking, and for generating
75+
strings for internationalisation.
76+
77+
.TP
78+
.B --verbose
79+
Produce verbose error messages: handy for debugging in batch mode.
80+
81+
.TP
82+
.B --i18n
83+
Output strings from .def files for internationalisation.
84+
85+
.TP
86+
.B --version
87+
Print version information.
88+
89+
.TP
90+
.B --test
91+
Start up (including any arg processing), test for any errors,
92+
and exit with an error code if any occurred. Useful for running
93+
automated tests.
94+
95+
.TP
96+
.BI --prefix= PREFIX
97+
Set install prefix. Start up as if nip4-batch had been installed to PREFIX.
98+
Useful for running automated tests without installing the thing.
99+
100+
.SH EXAMPLES
101+
102+
.TP
103+
.B nip4-batch -e "2 + 2"
104+
Prints 4 to stdout.
105+
106+
.TP
107+
.B nip4-batch -e "99 + Image_file argv?1" -o result.png fred.jpg
108+
Load argv1 (fred.jpg), add 99, output to result.png.
109+
110+
.TP
111+
.B nip4-batch -e "Matrix [[1,2],[4,5]] ** -1" -o poop.mat
112+
Invert the 2x2 matrix and write the result to poop.mat.
113+
114+
.SH COPYRIGHT
115+
2025 (c) libvips.org

man/nip4.1

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
.TH NIP4 1 "Oct 4 2025"
2+
.SH NAME
3+
nip4 \- image processing spreadsheet
4+
5+
.SH SYNOPSIS
6+
.B nip4
7+
.RI [ filename1.. ]
8+
9+
.SH DESCRIPTION
10+
.B nip4
11+
is a spreadsheet-like tool for scientific image processing. You can develop
12+
large image processing pipelines interactively, then execute them batch-style
13+
with the separate
14+
.B nip4-batch(1)
15+
program. It is fast and uses relatively little memory.
16+
17+
A full manual is available online.
18+
19+
.SH EXAMPLES
20+
21+
.TP
22+
.B nip4 fred.jpg
23+
Start nip4, loading the image fred.jpg.
24+
25+
.TP
26+
.B nip4 sample.ws
27+
Start nip4, loading a previous saved workspace.
28+
29+
.SH SEE ALSO
30+
nip4-batch(1)
31+
32+
.SH COPYRIGHT
33+
2025 (c) libvips.org

meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,4 @@ meson.add_install_script('meson_post_install.py')
116116
subdir('src')
117117
subdir('share')
118118
subdir('test')
119+
subdir('man')

src/heap.c

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2531,11 +2531,12 @@ graph_pointer(PElement *root)
25312531

25322532
/* Fwd ref.
25332533
*/
2534-
static void shell_pelement(PElement *base);
2534+
static gboolean shell_pelement(PElement *base);
25352535

2536-
/* Print a graph shell-style.
2536+
/* Print a graph shell-style. TRUE for node is a concrete, printable or
2537+
* saveable thing.
25372538
*/
2538-
static void
2539+
static gboolean
25392540
shell_node(HeapNode *hn)
25402541
{
25412542
PElement p1, p2;
@@ -2544,10 +2545,14 @@ shell_node(HeapNode *hn)
25442545
*/
25452546
if (hn->flgs & FLAG_PRINT) {
25462547
printf("<*circular*>");
2547-
return;
2548+
return TRUE;
25482549
}
25492550
hn->flgs |= FLAG_PRINT;
25502551

2552+
gboolean concrete;
2553+
2554+
concrete = FALSE;
2555+
25512556
switch (hn->type) {
25522557
case TAG_CLASS:
25532558
case TAG_APPL:
@@ -2563,15 +2568,17 @@ shell_node(HeapNode *hn)
25632568
string_mode = PEISCHAR(&p1);
25642569

25652570
for (;;) {
2566-
if (string_mode)
2571+
if (string_mode) {
25672572
printf("%c", PEGETCHAR(&p1));
2573+
concrete = TRUE;
2574+
}
25682575
else
2569-
shell_pelement(&p1);
2576+
concrete = shell_pelement(&p1);
25702577

25712578
PEPOINTRIGHT(hn, &p2);
25722579
if (PEISMANAGEDSTRING(&p2)) {
2573-
printf("%s\n",
2574-
PEGETMANAGEDSTRING(&p2)->string);
2580+
printf("%s\n", PEGETMANAGEDSTRING(&p2)->string);
2581+
concrete = TRUE;
25752582
break;
25762583
}
25772584
else if (PEISELIST(&p2))
@@ -2584,28 +2591,37 @@ shell_node(HeapNode *hn)
25842591
if (string_mode && !PEISCHAR(&p1))
25852592
string_mode = FALSE;
25862593
}
2587-
} break;
2594+
}
2595+
break;
25882596

25892597
case TAG_DOUBLE:
25902598
printf("%g", hn->body.num);
2599+
concrete = TRUE;
25912600
break;
25922601

25932602
case TAG_COMPLEX:
25942603
printf("%g %g",
25952604
GETLEFT(hn)->body.num, GETRIGHT(hn)->body.num);
2605+
concrete = TRUE;
25962606
break;
25972607

25982608
case TAG_FREE:
25992609
default:
26002610
g_assert(FALSE);
26012611
}
2612+
2613+
return concrete;
26022614
}
26032615

26042616
/* Print a pelement shell-style.
26052617
*/
2606-
static void
2618+
static gboolean
26072619
shell_pelement(PElement *base)
26082620
{
2621+
gboolean concrete;
2622+
2623+
concrete = FALSE;
2624+
26092625
switch (PEGETTYPE(base)) {
26102626
/* Only allow concrete base types.
26112627
*/
@@ -2618,35 +2634,40 @@ shell_pelement(PElement *base)
26182634
case ELEMENT_TAG:
26192635
case ELEMENT_SYMBOL:
26202636
case ELEMENT_NOVAL:
2621-
printf("no-value");
26222637
break;
26232638

26242639
case ELEMENT_NODE:
2625-
shell_node(PEGETVAL(base));
2640+
concrete = shell_node(PEGETVAL(base));
26262641
break;
26272642

26282643
case ELEMENT_CHAR:
26292644
printf("%c", (int) PEGETCHAR(base));
2645+
concrete = TRUE;
26302646
break;
26312647

26322648
case ELEMENT_BOOL:
26332649
printf("%s", bool_to_char(PEGETBOOL(base)));
2650+
concrete = TRUE;
26342651
break;
26352652

26362653
case ELEMENT_ELIST:
26372654
printf("[ ]");
2655+
concrete = TRUE;
26382656
break;
26392657

26402658
case ELEMENT_MANAGED:
26412659
if (PEISIMAGE(base))
26422660
printf("%s", PEGETIMAGE(base)->filename);
26432661
else if (PEISMANAGEDSTRING(base))
26442662
printf("%s", PEGETMANAGEDSTRING(base)->string);
2663+
concrete = TRUE;
26452664
break;
26462665

26472666
default:
26482667
g_assert(FALSE);
26492668
}
2669+
2670+
return concrete;
26502671
}
26512672

26522673
/* Print a pelement shell-style.
@@ -2660,6 +2681,6 @@ graph_value(PElement *root)
26602681
error_alert(NULL);
26612682

26622683
heap_clear(reduce_context->heap, FLAG_PRINT);
2663-
shell_pelement(root);
2664-
printf("\n");
2684+
if (shell_pelement(root))
2685+
printf("\n");
26652686
}

0 commit comments

Comments
 (0)