mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 17:19:03 -04:00
ncneofetch: create info plane #550
This commit is contained in:
parent
31bd01b56d
commit
7ca5a7e82c
3
NEWS.md
3
NEWS.md
@ -2,7 +2,10 @@ This document attempts to list user-visible changes and any major internal
|
|||||||
rearrangements of Notcurses.
|
rearrangements of Notcurses.
|
||||||
|
|
||||||
* 1.5.2 (not yet released)
|
* 1.5.2 (not yet released)
|
||||||
|
* The `ncneofetch` program has been added, of no great consequence.
|
||||||
* A `NULL` value can now be passed as `sbytes` to `ncplane_puttext()`.
|
* A `NULL` value can now be passed as `sbytes` to `ncplane_puttext()`.
|
||||||
|
* `ncdirect_render_image()` has been added, allowing images to be
|
||||||
|
rendered in direct mode.
|
||||||
|
|
||||||
* 1.5.1 (2020-07-15)
|
* 1.5.1 (2020-07-15)
|
||||||
* The semantics of rendering have changed slightly. In 1.5.0 and prior
|
* The semantics of rendering have changed slightly. In 1.5.0 and prior
|
||||||
|
5
USAGE.md
5
USAGE.md
@ -320,6 +320,11 @@ int ncdirect_cursor_up(struct ncdirect* nc, int num);
|
|||||||
int ncdirect_cursor_left(struct ncdirect* nc, int num);
|
int ncdirect_cursor_left(struct ncdirect* nc, int num);
|
||||||
int ncdirect_cursor_right(struct ncdirect* nc, int num);
|
int ncdirect_cursor_right(struct ncdirect* nc, int num);
|
||||||
int ncdirect_cursor_down(struct ncdirect* nc, int num);
|
int ncdirect_cursor_down(struct ncdirect* nc, int num);
|
||||||
|
|
||||||
|
// Display an image using the specified blitter and scaling. The image may
|
||||||
|
// be arbitrarily many rows -- the output will scroll -- but will only occupy
|
||||||
|
// the column of the cursor, and those to the right.
|
||||||
|
nc_err_e ncdirect_render_image(const char* filename, ncblitter_e blitter, ncscale_e scale);
|
||||||
```
|
```
|
||||||
|
|
||||||
## Alignment
|
## Alignment
|
||||||
|
@ -41,6 +41,31 @@ struct ncmultiselector; // widget supporting selecting 0..n from n options
|
|||||||
struct ncreader; // widget supporting free string input ala readline
|
struct ncreader; // widget supporting free string input ala readline
|
||||||
struct ncfadectx; // context for a palette fade operation
|
struct ncfadectx; // context for a palette fade operation
|
||||||
|
|
||||||
|
// each has the empty cell in addition to the product of its dimensions. i.e.
|
||||||
|
// NCBLIT_1x1 has two states: empty and full block. NCBLIT_1x1x4 has five
|
||||||
|
// states: empty, the three shaded blocks, and the full block.
|
||||||
|
typedef enum {
|
||||||
|
NCBLIT_DEFAULT, // let the ncvisual pick
|
||||||
|
NCBLIT_1x1, // full block █
|
||||||
|
NCBLIT_2x1, // full/(upper|left) blocks ▄█
|
||||||
|
NCBLIT_1x1x4, // shaded full blocks ▓▒░█
|
||||||
|
NCBLIT_2x2, // quadrants ▗▐ ▖▄▟▌▙█
|
||||||
|
NCBLIT_4x1, // four vert/horz levels █▆▄▂ / ▎▌▊█
|
||||||
|
NCBLIT_BRAILLE, // 4 rows, 2 cols (braille) ⡀⡄⡆⡇⢀⣀⣄⣆⣇⢠⣠⣤⣦⣧⢰⣰⣴⣶⣷⢸⣸⣼⣾⣿
|
||||||
|
NCBLIT_8x1, // eight vert/horz levels █▇▆▅▄▃▂▁ / ▏▎▍▌▋▊▉█
|
||||||
|
NCBLIT_SIXEL, // 6 rows, 1 col (RGB), spotty support among terminals
|
||||||
|
} ncblitter_e;
|
||||||
|
|
||||||
|
// How to scale an ncvisual during rendering. NCSCALE_NONE will apply no
|
||||||
|
// scaling. NCSCALE_SCALE scales a visual to the plane's size, maintaining
|
||||||
|
// aspect ratio. NCSCALE_STRETCH stretches and scales the image in an
|
||||||
|
// attempt to fill the entirety of the plane.
|
||||||
|
typedef enum {
|
||||||
|
NCSCALE_NONE,
|
||||||
|
NCSCALE_SCALE,
|
||||||
|
NCSCALE_STRETCH,
|
||||||
|
} ncscale_e;
|
||||||
|
|
||||||
// Initialize a direct-mode notcurses context on the connected terminal at 'fp'.
|
// Initialize a direct-mode notcurses context on the connected terminal at 'fp'.
|
||||||
// 'fp' must be a tty. You'll usually want stdout. Direct mode supportes a
|
// 'fp' must be a tty. You'll usually want stdout. Direct mode supportes a
|
||||||
// limited subset of notcurses routines which directly affect 'fp', and neither
|
// limited subset of notcurses routines which directly affect 'fp', and neither
|
||||||
@ -102,6 +127,12 @@ API int ncdirect_cursor_yx(struct ncdirect* n, int* y, int* x);
|
|||||||
API int ncdirect_cursor_push(struct ncdirect* n);
|
API int ncdirect_cursor_push(struct ncdirect* n);
|
||||||
API int ncdirect_cursor_pop(struct ncdirect* n);
|
API int ncdirect_cursor_pop(struct ncdirect* n);
|
||||||
|
|
||||||
|
// Display an image using the specified blitter and scaling. The image may
|
||||||
|
// // be arbitrarily many rows -- the output will scroll -- but will only occupy
|
||||||
|
// // the column of the cursor, and those to the right.
|
||||||
|
API nc_err_e ncdirect_render_image(const char* filename, ncblitter_e blitter,
|
||||||
|
ncscale_e scale);
|
||||||
|
|
||||||
// Clear the screen.
|
// Clear the screen.
|
||||||
API int ncdirect_clear(struct ncdirect* nc);
|
API int ncdirect_clear(struct ncdirect* nc);
|
||||||
|
|
||||||
@ -898,16 +929,6 @@ typedef struct notcurses_options {
|
|||||||
// there can be four numbers separated by commas.
|
// there can be four numbers separated by commas.
|
||||||
API int notcurses_lex_margins(const char* op, notcurses_options* opts);
|
API int notcurses_lex_margins(const char* op, notcurses_options* opts);
|
||||||
|
|
||||||
// How to scale a visual in ncvisual_decode(). NCSCALE_NONE will apply no
|
|
||||||
// scaling. NCSCALE_SCALE scales a visual to the plane's size, maintaining
|
|
||||||
// aspect ratio. NCSCALE_STRETCH stretches and scales the image in an attempt
|
|
||||||
// to fill the entirety of the plane.
|
|
||||||
typedef enum {
|
|
||||||
NCSCALE_NONE,
|
|
||||||
NCSCALE_SCALE,
|
|
||||||
NCSCALE_STRETCH,
|
|
||||||
} ncscale_e;
|
|
||||||
|
|
||||||
// Lex a visual scaling mode (one of "none", "stretch", or "scale").
|
// Lex a visual scaling mode (one of "none", "stretch", or "scale").
|
||||||
API int notcurses_lex_scalemode(const char* op, ncscale_e* scalemode);
|
API int notcurses_lex_scalemode(const char* op, ncscale_e* scalemode);
|
||||||
|
|
||||||
@ -2170,6 +2191,30 @@ ncplane_rounded_box(struct ncplane* n, uint32_t attr, uint64_t channels,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
ncplane_perimeter_rounded(struct ncplane* n, uint32_t attrword,
|
||||||
|
uint64_t channels, unsigned ctlword){
|
||||||
|
if(ncplane_cursor_move_yx(n, 0, 0)){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int dimy, dimx;
|
||||||
|
ncplane_dim_yx(n, &dimy, &dimx);
|
||||||
|
cell ul = CELL_TRIVIAL_INITIALIZER;
|
||||||
|
cell ur = CELL_TRIVIAL_INITIALIZER;
|
||||||
|
cell ll = CELL_TRIVIAL_INITIALIZER;
|
||||||
|
cell lr = CELL_TRIVIAL_INITIALIZER;
|
||||||
|
cell vl = CELL_TRIVIAL_INITIALIZER;
|
||||||
|
cell hl = CELL_TRIVIAL_INITIALIZER;
|
||||||
|
if(cells_rounded_box(n, attrword, channels, &ul, &ur, &ll, &lr, &hl, &vl)){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int r = ncplane_box_sized(n, &ul, &ur, &ll, &lr, &hl, &vl, dimy, dimx, ctlword);
|
||||||
|
cell_release(n, &ul); cell_release(n, &ur);
|
||||||
|
cell_release(n, &ll); cell_release(n, &lr);
|
||||||
|
cell_release(n, &hl); cell_release(n, &vl);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
ncplane_rounded_box_sized(struct ncplane* n, uint32_t attr, uint64_t channels,
|
ncplane_rounded_box_sized(struct ncplane* n, uint32_t attr, uint64_t channels,
|
||||||
int ylen, int xlen, unsigned ctlword){
|
int ylen, int xlen, unsigned ctlword){
|
||||||
@ -2199,6 +2244,30 @@ ncplane_double_box(struct ncplane* n, uint32_t attr, uint64_t channels,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
ncplane_perimeter_double(struct ncplane* n, uint32_t attrword,
|
||||||
|
uint64_t channels, unsigned ctlword){
|
||||||
|
if(ncplane_cursor_move_yx(n, 0, 0)){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int dimy, dimx;
|
||||||
|
ncplane_dim_yx(n, &dimy, &dimx);
|
||||||
|
cell ul = CELL_TRIVIAL_INITIALIZER;
|
||||||
|
cell ur = CELL_TRIVIAL_INITIALIZER;
|
||||||
|
cell ll = CELL_TRIVIAL_INITIALIZER;
|
||||||
|
cell lr = CELL_TRIVIAL_INITIALIZER;
|
||||||
|
cell vl = CELL_TRIVIAL_INITIALIZER;
|
||||||
|
cell hl = CELL_TRIVIAL_INITIALIZER;
|
||||||
|
if(cells_double_box(n, attrword, channels, &ul, &ur, &ll, &lr, &hl, &vl)){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int r = ncplane_box_sized(n, &ul, &ur, &ll, &lr, &hl, &vl, dimy, dimx, ctlword);
|
||||||
|
cell_release(n, &ul); cell_release(n, &ur);
|
||||||
|
cell_release(n, &ll); cell_release(n, &lr);
|
||||||
|
cell_release(n, &hl); cell_release(n, &vl);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
ncplane_double_box_sized(struct ncplane* n, uint32_t attr, uint64_t channels,
|
ncplane_double_box_sized(struct ncplane* n, uint32_t attr, uint64_t channels,
|
||||||
int ylen, int xlen, unsigned ctlword){
|
int ylen, int xlen, unsigned ctlword){
|
||||||
@ -2225,21 +2294,6 @@ API struct ncvisual* ncvisual_from_rgba(const void* rgba, int rows,
|
|||||||
API struct ncvisual* ncvisual_from_bgra(const void* rgba, int rows,
|
API struct ncvisual* ncvisual_from_bgra(const void* rgba, int rows,
|
||||||
int rowstride, int cols);
|
int rowstride, int cols);
|
||||||
|
|
||||||
// each has the empty cell in addition to the product of its dimensions. i.e.
|
|
||||||
// NCBLIT_1x1 has two states: empty and full block. NCBLIT_1x1x4 has five
|
|
||||||
// states: empty, the three shaded blocks, and the full block.
|
|
||||||
typedef enum {
|
|
||||||
NCBLIT_DEFAULT, // let the ncvisual pick
|
|
||||||
NCBLIT_1x1, // full block █
|
|
||||||
NCBLIT_2x1, // full/(upper|left) blocks ▄█
|
|
||||||
NCBLIT_1x1x4, // shaded full blocks ▓▒░█
|
|
||||||
NCBLIT_2x2, // quadrants ▗▐ ▖▄▟▌▙█
|
|
||||||
NCBLIT_4x1, // four vert/horz levels █▆▄▂ / ▎▌▊█
|
|
||||||
NCBLIT_BRAILLE, // 4 rows, 2 cols (braille) ⡀⡄⡆⡇⢀⣀⣄⣆⣇⢠⣠⣤⣦⣧⢰⣰⣴⣶⣷⢸⣸⣼⣾⣿
|
|
||||||
NCBLIT_8x1, // eight vert/horz levels █▇▆▅▄▃▂▁ / ▏▎▍▌▋▊▉█
|
|
||||||
NCBLIT_SIXEL, // 6 rows, 1 col (RGB), spotty support among terminals
|
|
||||||
} ncblitter_e;
|
|
||||||
|
|
||||||
// Promote an ncplane 'n' to an ncvisual. The plane may contain only spaces,
|
// Promote an ncplane 'n' to an ncvisual. The plane may contain only spaces,
|
||||||
// half blocks, and full blocks. The latter will be checked, and any other
|
// half blocks, and full blocks. The latter will be checked, and any other
|
||||||
// glyph will result in a NULL being returned. This function exists so that
|
// glyph will result in a NULL being returned. This function exists so that
|
||||||
|
@ -67,34 +67,13 @@ done:
|
|||||||
return dinfo;
|
return dinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static const distro_info*
|
||||||
linux_ncneofetch(struct notcurses* nc){
|
linux_ncneofetch(void){
|
||||||
const distro_info* dinfo = getdistro();
|
const distro_info* dinfo = getdistro();
|
||||||
if(dinfo == NULL){
|
if(dinfo == NULL){
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
nc_err_e err;
|
return dinfo;
|
||||||
struct ncvisual* ncv = ncvisual_from_file(dinfo->logofile, &err);
|
|
||||||
if(ncv == NULL){
|
|
||||||
fprintf(stderr, "Error opening logo file at %s\n", dinfo->logofile);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
struct ncvisual_options vopts = {
|
|
||||||
.scaling = NCSCALE_SCALE,
|
|
||||||
.blitter = NCBLIT_2x2,
|
|
||||||
};
|
|
||||||
struct ncplane* n = ncvisual_render(nc, ncv, &vopts);
|
|
||||||
if(n == NULL){
|
|
||||||
ncvisual_destroy(ncv);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(notcurses_render(nc)){
|
|
||||||
ncvisual_destroy(ncv);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ncplane_destroy(n);
|
|
||||||
ncvisual_destroy(ncv);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -119,19 +98,77 @@ get_kernel(void){
|
|||||||
return NCNEO_UNKNOWN;
|
return NCNEO_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct ncplane*
|
||||||
|
display(struct notcurses* nc, const distro_info* dinfo){
|
||||||
|
if(dinfo->logofile){
|
||||||
|
nc_err_e err;
|
||||||
|
struct ncvisual* ncv = ncvisual_from_file(dinfo->logofile, &err);
|
||||||
|
if(ncv == NULL){
|
||||||
|
fprintf(stderr, "Error opening logo file at %s\n", dinfo->logofile);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
struct ncvisual_options vopts = {
|
||||||
|
.scaling = NCSCALE_SCALE,
|
||||||
|
.blitter = NCBLIT_2x2,
|
||||||
|
.n = notcurses_stdplane(nc),
|
||||||
|
};
|
||||||
|
if(ncvisual_render(nc, ncv, &vopts) == NULL){
|
||||||
|
ncvisual_destroy(ncv);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ncvisual_destroy(ncv);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const distro_info*
|
||||||
|
freebsd_ncneofetch(void){
|
||||||
|
static const distro_info fbsd = {
|
||||||
|
.name = "FreeBSD",
|
||||||
|
.logofile = NULL, // FIXME
|
||||||
|
};
|
||||||
|
return &fbsd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
infoplane(struct notcurses* nc){
|
||||||
|
struct ncplane* infop = ncplane_new(nc, 8, 60, 0, 0, NULL);
|
||||||
|
if(infop == NULL){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(ncplane_perimeter_rounded(infop, 0, 0, 0)){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ncneofetch(struct notcurses* nc){
|
ncneofetch(struct notcurses* nc){
|
||||||
|
const distro_info* dinfo = NULL;
|
||||||
ncneo_kernel_e kern = get_kernel();
|
ncneo_kernel_e kern = get_kernel();
|
||||||
switch(kern){
|
switch(kern){
|
||||||
case NCNEO_LINUX:
|
case NCNEO_LINUX:
|
||||||
return linux_ncneofetch(nc);
|
dinfo = linux_ncneofetch();
|
||||||
|
break;
|
||||||
case NCNEO_FREEBSD:
|
case NCNEO_FREEBSD:
|
||||||
// FIXME
|
dinfo = freebsd_ncneofetch();
|
||||||
break;
|
break;
|
||||||
case NCNEO_UNKNOWN:
|
case NCNEO_UNKNOWN:
|
||||||
return -1;
|
break;
|
||||||
}
|
}
|
||||||
return -1;
|
if(dinfo == NULL){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(display(nc, dinfo)){
|
||||||
|
return -1; // FIXME soldier on, perhaps?
|
||||||
|
}
|
||||||
|
if(infoplane(nc)){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(notcurses_render(nc)){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void){
|
int main(void){
|
||||||
|
@ -12,7 +12,7 @@ auto pulser(struct notcurses* nc, struct ncplane* ncp __attribute__ ((unused)),
|
|||||||
struct timespec now;
|
struct timespec now;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
auto delta = timespec_to_ns(&now) - timespec_to_ns(pulsestart);
|
auto delta = timespec_to_ns(&now) - timespec_to_ns(pulsestart);
|
||||||
if(delta > 500000000){
|
if(delta > 250000000){
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -62,14 +62,14 @@ TEST_CASE("Fade") {
|
|||||||
CHECK(0 == notcurses_render(nc_));
|
CHECK(0 == notcurses_render(nc_));
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
ts.tv_sec = 0;
|
ts.tv_sec = 0;
|
||||||
ts.tv_nsec = 500000000;
|
ts.tv_nsec = 250000000;
|
||||||
CHECK(0 == ncplane_fadeout(n_, &ts, nullptr, nullptr));
|
CHECK(0 == ncplane_fadeout(n_, &ts, nullptr, nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBCASE("FadeIn") {
|
SUBCASE("FadeIn") {
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
ts.tv_sec = 0;
|
ts.tv_sec = 0;
|
||||||
ts.tv_nsec = 500000000;
|
ts.tv_nsec = 250000000;
|
||||||
CHECK(0 == ncplane_fadein(n_, &ts, nullptr, nullptr));
|
CHECK(0 == ncplane_fadein(n_, &ts, nullptr, nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,21 +77,21 @@ TEST_CASE("Fade") {
|
|||||||
CHECK(0 == notcurses_render(nc_));
|
CHECK(0 == notcurses_render(nc_));
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
ts.tv_sec = 0;
|
ts.tv_sec = 0;
|
||||||
ts.tv_nsec = 500000000;
|
ts.tv_nsec = 250000000;
|
||||||
CHECK(0 < ncplane_fadeout(n_, &ts, fadeaborter, nullptr));
|
CHECK(0 < ncplane_fadeout(n_, &ts, fadeaborter, nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBCASE("FadeInAbort") {
|
SUBCASE("FadeInAbort") {
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
ts.tv_sec = 0;
|
ts.tv_sec = 0;
|
||||||
ts.tv_nsec = 500000000;
|
ts.tv_nsec = 250000000;
|
||||||
CHECK(0 < ncplane_fadein(n_, &ts, fadeaborter, nullptr));
|
CHECK(0 < ncplane_fadein(n_, &ts, fadeaborter, nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBCASE("Pulse") {
|
SUBCASE("Pulse") {
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
ts.tv_sec = 0;
|
ts.tv_sec = 0;
|
||||||
ts.tv_nsec = 150000000;
|
ts.tv_nsec = 75000000;
|
||||||
ncplane_erase(n_);
|
ncplane_erase(n_);
|
||||||
ncplane_set_fg(n_, 0xffd700);
|
ncplane_set_fg(n_, 0xffd700);
|
||||||
CHECK(0 < ncplane_printf_aligned(n_, dimy - 1, NCALIGN_CENTER, "pulllllllse"));
|
CHECK(0 < ncplane_printf_aligned(n_, dimy - 1, NCALIGN_CENTER, "pulllllllse"));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user