mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 09:09: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.
|
||||
|
||||
* 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()`.
|
||||
* `ncdirect_render_image()` has been added, allowing images to be
|
||||
rendered in direct mode.
|
||||
|
||||
* 1.5.1 (2020-07-15)
|
||||
* 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_right(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
|
||||
|
@ -41,6 +41,31 @@ struct ncmultiselector; // widget supporting selecting 0..n from n options
|
||||
struct ncreader; // widget supporting free string input ala readline
|
||||
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'.
|
||||
// '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
|
||||
@ -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_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.
|
||||
API int ncdirect_clear(struct ncdirect* nc);
|
||||
|
||||
@ -898,16 +929,6 @@ typedef struct notcurses_options {
|
||||
// there can be four numbers separated by commas.
|
||||
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").
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
ncplane_rounded_box_sized(struct ncplane* n, uint32_t attr, uint64_t channels,
|
||||
int ylen, int xlen, unsigned ctlword){
|
||||
@ -2199,6 +2244,30 @@ ncplane_double_box(struct ncplane* n, uint32_t attr, uint64_t channels,
|
||||
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
|
||||
ncplane_double_box_sized(struct ncplane* n, uint32_t attr, uint64_t channels,
|
||||
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,
|
||||
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,
|
||||
// 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
|
||||
|
@ -67,34 +67,13 @@ done:
|
||||
return dinfo;
|
||||
}
|
||||
|
||||
static int
|
||||
linux_ncneofetch(struct notcurses* nc){
|
||||
static const distro_info*
|
||||
linux_ncneofetch(void){
|
||||
const distro_info* dinfo = getdistro();
|
||||
if(dinfo == NULL){
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
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 -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;
|
||||
return dinfo;
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
@ -119,19 +98,77 @@ get_kernel(void){
|
||||
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
|
||||
ncneofetch(struct notcurses* nc){
|
||||
const distro_info* dinfo = NULL;
|
||||
ncneo_kernel_e kern = get_kernel();
|
||||
switch(kern){
|
||||
case NCNEO_LINUX:
|
||||
return linux_ncneofetch(nc);
|
||||
dinfo = linux_ncneofetch();
|
||||
break;
|
||||
case NCNEO_FREEBSD:
|
||||
// FIXME
|
||||
dinfo = freebsd_ncneofetch();
|
||||
break;
|
||||
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){
|
||||
|
@ -12,7 +12,7 @@ auto pulser(struct notcurses* nc, struct ncplane* ncp __attribute__ ((unused)),
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
auto delta = timespec_to_ns(&now) - timespec_to_ns(pulsestart);
|
||||
if(delta > 500000000){
|
||||
if(delta > 250000000){
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@ -62,14 +62,14 @@ TEST_CASE("Fade") {
|
||||
CHECK(0 == notcurses_render(nc_));
|
||||
struct timespec ts;
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 500000000;
|
||||
ts.tv_nsec = 250000000;
|
||||
CHECK(0 == ncplane_fadeout(n_, &ts, nullptr, nullptr));
|
||||
}
|
||||
|
||||
SUBCASE("FadeIn") {
|
||||
struct timespec ts;
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 500000000;
|
||||
ts.tv_nsec = 250000000;
|
||||
CHECK(0 == ncplane_fadein(n_, &ts, nullptr, nullptr));
|
||||
}
|
||||
|
||||
@ -77,21 +77,21 @@ TEST_CASE("Fade") {
|
||||
CHECK(0 == notcurses_render(nc_));
|
||||
struct timespec ts;
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 500000000;
|
||||
ts.tv_nsec = 250000000;
|
||||
CHECK(0 < ncplane_fadeout(n_, &ts, fadeaborter, nullptr));
|
||||
}
|
||||
|
||||
SUBCASE("FadeInAbort") {
|
||||
struct timespec ts;
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 500000000;
|
||||
ts.tv_nsec = 250000000;
|
||||
CHECK(0 < ncplane_fadein(n_, &ts, fadeaborter, nullptr));
|
||||
}
|
||||
|
||||
SUBCASE("Pulse") {
|
||||
struct timespec ts;
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 150000000;
|
||||
ts.tv_nsec = 75000000;
|
||||
ncplane_erase(n_);
|
||||
ncplane_set_fg(n_, 0xffd700);
|
||||
CHECK(0 < ncplane_printf_aligned(n_, dimy - 1, NCALIGN_CENTER, "pulllllllse"));
|
||||
|
Loading…
x
Reference in New Issue
Block a user