mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 17:19:03 -04:00
view: support -m argument for margins #551
This commit is contained in:
parent
6e8a0bebae
commit
84107c547d
5
USAGE.md
5
USAGE.md
@ -98,6 +98,11 @@ typedef struct notcurses_options {
|
|||||||
int margin_t, margin_r, margin_b, margin_l;
|
int margin_t, margin_r, margin_b, margin_l;
|
||||||
} notcurses_options;
|
} notcurses_options;
|
||||||
|
|
||||||
|
// Lex a margin argument according to the standard notcurses definition. There
|
||||||
|
// can be either a single number, which will define all margins equally, or
|
||||||
|
// there can be four numbers separated by commas.
|
||||||
|
int notcurses_lex_margins(const char* op, notcurses_options* opts);
|
||||||
|
|
||||||
// Initialize a notcurses context on the connected terminal at 'fp'. 'fp' must
|
// Initialize a notcurses context on the connected terminal at 'fp'. 'fp' must
|
||||||
// be a tty. You'll usually want stdout. Returns NULL on error, including any
|
// be a tty. You'll usually want stdout. Returns NULL on error, including any
|
||||||
// failure initializing terminfo.
|
// failure initializing terminfo.
|
||||||
|
@ -23,10 +23,17 @@ and videos to the terminal. Media will be scaled to the terminal's size.
|
|||||||
|
|
||||||
**-s scalemode**: Scaling mode, one of **none**, **scale**, or **stretch**.
|
**-s scalemode**: Scaling mode, one of **none**, **scale**, or **stretch**.
|
||||||
|
|
||||||
|
**-m margins**: Define rendering margins (see below).
|
||||||
|
|
||||||
**-k**: Inhibit use of the alternate screen. Necessary if you want the output left on your terminal after the program exits.
|
**-k**: Inhibit use of the alternate screen. Necessary if you want the output left on your terminal after the program exits.
|
||||||
|
|
||||||
files: Select which files to render, and what order to render them in.
|
files: Select which files to render, and what order to render them in.
|
||||||
|
|
||||||
|
Default margins are all 0, and thus the full screen will be rendered. Using
|
||||||
|
**-m**, margins can be supplied. Provide a single number to set all four margins
|
||||||
|
to the same value, or four comma-delimited values for the top, right, bottom,
|
||||||
|
and left margins respectively. Negative margins are illegal.
|
||||||
|
|
||||||
# NOTES
|
# NOTES
|
||||||
|
|
||||||
Optimal display requires a terminal advertising the **rgb** terminfo(5)
|
Optimal display requires a terminal advertising the **rgb** terminfo(5)
|
||||||
|
@ -97,6 +97,7 @@ particular EGC is heavily reused within a plane.
|
|||||||
|
|
||||||
A few high-level widgets are included, all built atop ncplanes:
|
A few high-level widgets are included, all built atop ncplanes:
|
||||||
|
|
||||||
|
* **notcurses_fds(3)** for dumping file descriptors/subprocesses to a plane
|
||||||
* **notcurses_menu(3)** for menu bars at the top or bottom of the screen
|
* **notcurses_menu(3)** for menu bars at the top or bottom of the screen
|
||||||
* **notcurses_multiselector(3)** for selecting one or more items from a set
|
* **notcurses_multiselector(3)** for selecting one or more items from a set
|
||||||
* **notcurses_plot(3)** for drawing histograms and lineplots
|
* **notcurses_plot(3)** for drawing histograms and lineplots
|
||||||
|
@ -23,7 +23,9 @@ typedef struct notcurses_options {
|
|||||||
} notcurses_options;
|
} notcurses_options;
|
||||||
```
|
```
|
||||||
|
|
||||||
**struct notcurses* notcurses_init(const struct notcurses_options* opts, FILE* fp);**
|
**int notcurses_lex_margins(const char* op, notcurses_options* opts);**
|
||||||
|
|
||||||
|
**struct notcurses* notcurses_init(const notcurses_options* opts, FILE* fp);**
|
||||||
|
|
||||||
# DESCRIPTION
|
# DESCRIPTION
|
||||||
|
|
||||||
@ -67,7 +69,11 @@ the full screen cleared, followed by rendering to a subregion. Inhibiting the
|
|||||||
alternate screen plus margins will see rendering to a subregion, with the screen
|
alternate screen plus margins will see rendering to a subregion, with the screen
|
||||||
outside this region not cleared. This is the only means by which existing
|
outside this region not cleared. This is the only means by which existing
|
||||||
output can be undisturbed by notcurses. Margins are best-effort. Supplying any
|
output can be undisturbed by notcurses. Margins are best-effort. Supplying any
|
||||||
negative margin is an error.
|
negative margin is an error. **notcurses_lex_margins** provides lexing a
|
||||||
|
margin argument expression in one of two forms:
|
||||||
|
|
||||||
|
* a single number, which will be applied to all sides, or
|
||||||
|
* four comma-delimited numbers, applied to top, right, bottom, and left.
|
||||||
|
|
||||||
## Fatal signals
|
## Fatal signals
|
||||||
|
|
||||||
|
@ -785,6 +785,11 @@ typedef struct notcurses_options {
|
|||||||
int margin_t, margin_r, margin_b, margin_l;
|
int margin_t, margin_r, margin_b, margin_l;
|
||||||
} notcurses_options;
|
} notcurses_options;
|
||||||
|
|
||||||
|
// Lex a margin argument according to the standard notcurses definition. There
|
||||||
|
// can be either a single number, which will define all margins equally, or
|
||||||
|
// there can be four numbers separated by commas.
|
||||||
|
API int notcurses_lex_margins(const char* op, notcurses_options* opts);
|
||||||
|
|
||||||
// Initialize a notcurses context on the connected terminal at 'fp'. 'fp' must
|
// Initialize a notcurses context on the connected terminal at 'fp'. 'fp' must
|
||||||
// be a tty. You'll usually want stdout. Returns NULL on error, including any
|
// be a tty. You'll usually want stdout. Returns NULL on error, including any
|
||||||
// failure initializing terminfo.
|
// failure initializing terminfo.
|
||||||
|
@ -79,6 +79,7 @@ typedef struct notcurses_options {
|
|||||||
int margin_t, margin_r, margin_b, margin_l;
|
int margin_t, margin_r, margin_b, margin_l;
|
||||||
} notcurses_options;
|
} notcurses_options;
|
||||||
struct notcurses* notcurses_init(const notcurses_options*, FILE*);
|
struct notcurses* notcurses_init(const notcurses_options*, FILE*);
|
||||||
|
int notcurses_lex_margins(const char* op, notcurses_options* opts);
|
||||||
int notcurses_stop(struct notcurses*);
|
int notcurses_stop(struct notcurses*);
|
||||||
int notcurses_render(struct notcurses*);
|
int notcurses_render(struct notcurses*);
|
||||||
struct ncplane* notcurses_stdplane(struct notcurses*);
|
struct ncplane* notcurses_stdplane(struct notcurses*);
|
||||||
|
@ -127,53 +127,6 @@ usage(const char* exe, int status){
|
|||||||
exit(status);
|
exit(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract an integer, which must be non-negative, and followed by either a
|
|
||||||
// comma or a NUL terminator.
|
|
||||||
static int
|
|
||||||
lex_long(const char* op, int* i, char** endptr){
|
|
||||||
errno = 0;
|
|
||||||
long l = strtol(op, endptr, 10);
|
|
||||||
if(l < 0 || (l == LONG_MAX && errno == ERANGE) || (l > INT_MAX)){
|
|
||||||
fprintf(stderr, "Invalid margin: %s\n", op);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if((**endptr != ',' && **endptr) || *endptr == op){
|
|
||||||
fprintf(stderr, "Invalid margin: %s\n", op);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*i = l;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
lex_margins(const char* op, notcurses_options* opts){
|
|
||||||
if(opts->margin_t || opts->margin_r || opts->margin_b || opts->margin_l){
|
|
||||||
fprintf(stderr, "Provided margins twice!\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
char* eptr;
|
|
||||||
if(lex_long(op, &opts->margin_t, &eptr)){
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(!*eptr){ // allow a single value to be specified for all four margins
|
|
||||||
opts->margin_r = opts->margin_l = opts->margin_b = opts->margin_t;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
op = ++eptr; // once here, we require four values
|
|
||||||
if(lex_long(op, &opts->margin_r, &eptr) || !*eptr){
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
op = ++eptr;
|
|
||||||
if(lex_long(op, &opts->margin_b, &eptr) || !*eptr){
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
op = ++eptr;
|
|
||||||
if(lex_long(op, &opts->margin_l, &eptr) || *eptr){ // must end in NUL
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static demoresult*
|
static demoresult*
|
||||||
ext_demos(struct notcurses* nc, const char* spec, bool ignore_failures){
|
ext_demos(struct notcurses* nc, const char* spec, bool ignore_failures){
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -255,7 +208,11 @@ handle_opts(int argc, char** argv, notcurses_options* opts, bool* ignore_failure
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}case 'm':{
|
}case 'm':{
|
||||||
if(lex_margins(optarg, opts)){
|
if(opts->margin_t || opts->margin_r || opts->margin_b || opts->margin_l){
|
||||||
|
fprintf(stderr, "Provided margins twice!\n");
|
||||||
|
usage(*argv, EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if(notcurses_lex_margins(optarg, opts)){
|
||||||
usage(*argv, EXIT_FAILURE);
|
usage(*argv, EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1897,3 +1897,45 @@ bool ncplane_set_scrolling(ncplane* n, bool scrollp){
|
|||||||
n->scrolling = scrollp;
|
n->scrolling = scrollp;
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extract an integer, which must be non-negative, and followed by either a
|
||||||
|
// comma or a NUL terminator.
|
||||||
|
static int
|
||||||
|
lex_long(const char* op, int* i, char** endptr){
|
||||||
|
errno = 0;
|
||||||
|
long l = strtol(op, endptr, 10);
|
||||||
|
if(l < 0 || (l == LONG_MAX && errno == ERANGE) || (l > INT_MAX)){
|
||||||
|
fprintf(stderr, "Invalid margin: %s\n", op);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if((**endptr != ',' && **endptr) || *endptr == op){
|
||||||
|
fprintf(stderr, "Invalid margin: %s\n", op);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*i = l;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int notcurses_lex_margins(const char* op, notcurses_options* opts){
|
||||||
|
char* eptr;
|
||||||
|
if(lex_long(op, &opts->margin_t, &eptr)){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(!*eptr){ // allow a single value to be specified for all four margins
|
||||||
|
opts->margin_r = opts->margin_l = opts->margin_b = opts->margin_t;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
op = ++eptr; // once here, we require four values
|
||||||
|
if(lex_long(op, &opts->margin_r, &eptr) || !*eptr){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
op = ++eptr;
|
||||||
|
if(lex_long(op, &opts->margin_b, &eptr) || !*eptr){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
op = ++eptr;
|
||||||
|
if(lex_long(op, &opts->margin_l, &eptr) || *eptr){ // must end in NUL
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -17,10 +17,11 @@ static void usage(std::ostream& os, const char* name, int exitcode)
|
|||||||
__attribute__ ((noreturn));
|
__attribute__ ((noreturn));
|
||||||
|
|
||||||
void usage(std::ostream& o, const char* name, int exitcode){
|
void usage(std::ostream& o, const char* name, int exitcode){
|
||||||
o << "usage: " << name << " [ -h ] [ -l loglevel ] [ -d mult ] [ -s scaletype ] [ -k ] files" << '\n';
|
o << "usage: " << name << " [ -h ] [ -m margins ] [ -l loglevel ] [ -d mult ] [ -s scaletype ] [ -k ] files" << '\n';
|
||||||
o << " -k: don't use the alternate screen\n";
|
o << " -k: don't use the alternate screen\n";
|
||||||
o << " -l loglevel: integer between 0 and 9, goes to stderr'\n";
|
o << " -l loglevel: integer between 0 and 9, goes to stderr'\n";
|
||||||
o << " -s scaletype: one of 'none', 'scale', or 'stretch'\n";
|
o << " -s scaletype: one of 'none', 'scale', or 'stretch'\n";
|
||||||
|
o << " -m margins: margin, or 4 comma-separated margins\n";
|
||||||
o << " -d mult: non-negative floating point scale for frame time" << std::endl;
|
o << " -d mult: non-negative floating point scale for frame time" << std::endl;
|
||||||
exit(exitcode);
|
exit(exitcode);
|
||||||
}
|
}
|
||||||
@ -104,7 +105,7 @@ int handle_opts(int argc, char** argv, notcurses_options& opts, float* timescale
|
|||||||
*timescale = 1.0;
|
*timescale = 1.0;
|
||||||
*scalemode = NCScale::Scale;
|
*scalemode = NCScale::Scale;
|
||||||
int c;
|
int c;
|
||||||
while((c = getopt(argc, argv, "hl:d:s:k")) != -1){
|
while((c = getopt(argc, argv, "hl:d:s:m:k")) != -1){
|
||||||
switch(c){
|
switch(c){
|
||||||
case 'h':
|
case 'h':
|
||||||
usage(std::cout, argv[0], EXIT_SUCCESS);
|
usage(std::cout, argv[0], EXIT_SUCCESS);
|
||||||
@ -121,6 +122,15 @@ int handle_opts(int argc, char** argv, notcurses_options& opts, float* timescale
|
|||||||
case 'k':{
|
case 'k':{
|
||||||
opts.inhibit_alternate_screen = true;
|
opts.inhibit_alternate_screen = true;
|
||||||
break;
|
break;
|
||||||
|
}case 'm':{
|
||||||
|
if(opts.margin_t || opts.margin_r || opts.margin_b || opts.margin_l){
|
||||||
|
std::cerr << "Provided margins twice!" << std::endl;
|
||||||
|
usage(std::cerr, argv[0], EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if(notcurses_lex_margins(optarg, &opts)){
|
||||||
|
usage(std::cerr, argv[0], EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}case 'd':{
|
}case 'd':{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << optarg;
|
ss << optarg;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user