Update examples.

This commit is contained in:
CismonX 2020-12-18 18:37:47 +08:00
parent 2cdb088697
commit 5861677f5e
Signed by: cismonx
GPG Key ID: 3094873E29A482FB
2 changed files with 73 additions and 39 deletions

View File

@ -43,7 +43,7 @@
struct sixdraw_ctx {
struct termios termios;
union ctlseqs_value buffer[10];
union ctlseqs_value buffer[64];
char const *prog_name;
struct ctlseqs_matcher *matcher;
struct ctlseqs_reader *reader;
@ -111,7 +111,6 @@ sixdraw_get_winsize(struct sixdraw_ctx *ctx)
ctx->cols = ws.ws_col;
ctx->ch_width = ws.ws_xpixel / ws.ws_col;
ctx->ch_height = ws.ws_ypixel / ws.ws_row;
dprintf(ctx->out_fd, "%d %d \n%d %d %d %d\n", ws.ws_xpixel, ws.ws_ypixel, ctx->rows, ctx->cols, ctx->ch_width, ctx->ch_height);
return true;
}
@ -125,7 +124,7 @@ sixdraw_init(struct sixdraw_ctx *ctx, int argc, char **argv)
.timeout = SIXDRAW_DEFAULT_TIMEOUT_MILLIS,
};
// Process command line arguments
// Process command line arguments.
int opt;
while (-1 != (opt = getopt(argc, argv, "t:"))) {
switch (opt) {
@ -138,7 +137,7 @@ sixdraw_init(struct sixdraw_ctx *ctx, int argc, char **argv)
}
}
// Initialize control sequence matcher
// Initialize control sequence matcher.
ctx->matcher = ctlseqs_matcher_init();
if (ctx->matcher == NULL) {
sixdraw_print_error(ctx, "failed to initialize matcher");
@ -157,7 +156,7 @@ sixdraw_init(struct sixdraw_ctx *ctx, int argc, char **argv)
return false;
}
// Initialize control sequence reader
// Initialize control sequence reader.
ctx->reader = ctlseqs_reader_init();
if (ctx->reader == NULL) {
sixdraw_print_error(ctx, "failed to initialize reader");
@ -166,14 +165,14 @@ sixdraw_init(struct sixdraw_ctx *ctx, int argc, char **argv)
struct ctlseqs_reader_options reader_options = {
.buffer = ctx->buffer,
.fd = ctx->in_fd,
.maxlen = 32,
.maxlen = 4096,
};
if (ctlseqs_reader_config(ctx->reader, &reader_options) != CTLSEQS_OK) {
sixdraw_print_error(ctx, "failed to set reader options");
return false;
}
// Block SIGWINCH
// Block SIGWINCH.
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGWINCH);
@ -186,13 +185,13 @@ sixdraw_init(struct sixdraw_ctx *ctx, int argc, char **argv)
static bool
sixdraw_prepare(struct sixdraw_ctx *ctx)
{
// Check whether we're running on a terminal
// Check whether we're running on a terminal.
if (!isatty(ctx->in_fd) || !isatty(ctx->out_fd)) {
sixdraw_print_error(ctx, "this program can only run in a terminal");
return false;
}
// Set terminal to noncanonical mode
// Set terminal to noncanonical mode.
if (tcgetattr(ctx->in_fd, &ctx->termios) != 0) {
sixdraw_print_error(ctx, "failed to get terminal attributes");
return false;
@ -202,12 +201,12 @@ sixdraw_prepare(struct sixdraw_ctx *ctx)
termios.c_cc[VTIME] = 0;
termios.c_lflag &= ~(ICANON | ISIG | ECHO);
if (tcsetattr(ctx->in_fd, TCSANOW, &termios) != 0) {
sixdraw_print_error(ctx, "failed to get terminal attributes");
sixdraw_print_error(ctx, "failed to set terminal attributes");
return false;
}
ctx->has_termios = true;
// Set STDIN flags to non-blocking
// Set STDIN flags to nonblocking.
int flags = fcntl(ctx->in_fd, F_GETFL);
if (flags == -1) {
sixdraw_print_error(ctx, "failed to get file status flags");
@ -218,18 +217,20 @@ sixdraw_prepare(struct sixdraw_ctx *ctx)
return false;
}
// Get initial terminal window size
// Get initial terminal window size.
if (!sixdraw_get_winsize(ctx)) {
sixdraw_print_error(ctx, "failed to get terminal window size");
return false;
}
return true;
// Check terminal support for sixel graphics and DEC locator
// Check terminal support for sixel graphics and DEC locator.
dprintf(ctx->out_fd, CTLSEQS_PRIMARY_DA());
ssize_t result = ctlseqs_read(ctx->reader, ctx->matcher, 500);
ssize_t result;
do {
result = ctlseqs_read(ctx->reader, ctx->matcher, ctx->timeout);
} while (result == CTLSEQS_PARTIAL);
if (result != 0) {
sixdraw_print_error(ctx, "failed to get terminal attributes");
sixdraw_print_error(ctx, "failed to get terminal features");
return false;
}
bool has_sixel = false;
@ -251,9 +252,11 @@ sixdraw_prepare(struct sixdraw_ctx *ctx)
return false;
}
// Get current cursor status
// Get current cursor status.
dprintf(ctx->out_fd, CTLSEQS_DECRQM("25"));
result = ctlseqs_read(ctx->reader, ctx->matcher, ctx->timeout);
do {
result = ctlseqs_read(ctx->reader, ctx->matcher, ctx->timeout);
} while (result == CTLSEQS_PARTIAL);
if (result != 1) {
sixdraw_print_error(ctx, "failed to get cursor status");
return false;

View File

@ -17,7 +17,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "ctlseqs.h"
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif // HAVE_CONFIG_H
#include <ctype.h>
#include <errno.h>
@ -29,6 +31,8 @@
#include <termios.h>
#include <unistd.h>
#include <ctlseqs.h>
#define TCSGREP_NINTH_ARG_(a1, a2, a3, a4, a5, a6, a7, a8, a9, ...) a9
#define TCSGREP_COUNT_ARGS_(...) TCSGREP_NINTH_ARG_(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0)
@ -58,6 +62,8 @@ struct tcsgrep_ctx {
char const *prog_name;
int timeout;
int limit;
bool purge_long_seqs;
bool verbose;
};
static inline void
@ -79,7 +85,7 @@ parse_int(char const *str, int *dest)
}
static void
print_generic_seq(char const *header, union ctlseqs_value *buffer)
print_generic_seq(char const *header, union ctlseqs_value *buffer, bool newline)
{
size_t length = buffer[0].num;
char const *seq = buffer[1].str;
@ -96,13 +102,21 @@ print_generic_seq(char const *header, union ctlseqs_value *buffer)
printf(" \\x%02x", ch);
}
}
printf("\n");
if (newline) {
printf("\n");
}
}
static void
print_matching_seq(struct tcsgrep_sequence *seq, union ctlseqs_value *buffer)
print_matching_seq(struct tcsgrep_sequence *seq, union ctlseqs_value *buffer, bool verbose)
{
printf("OK %s", seq->name);
if (verbose) {
print_generic_seq("OK", buffer, false);
buffer += 2;
} else {
printf("OK");
}
printf(" %s", seq->name);
for (int idx = 0; idx < 8; ++idx) {
char placeholder = seq->args[idx];
switch (placeholder) {
@ -126,13 +140,15 @@ int
main(int argc, char **argv)
{
struct tcsgrep_ctx ctx = {
.prog_name = argv[0],
.timeout = -1,
.limit = 4096,
.prog_name = argv[0],
.timeout = -1,
.limit = 4096,
.purge_long_seqs = false,
.verbose = false,
};
int opt;
while (-1 != (opt = getopt(argc, argv, "t:l:"))) {
while (-1 != (opt = getopt(argc, argv, "t:l:pv"))) {
switch (opt) {
case 't':
if (!parse_int(optarg, &ctx.timeout)) {
@ -146,6 +162,12 @@ main(int argc, char **argv)
return 1;
}
break;
case 'p':
ctx.purge_long_seqs = true;
break;
case 'v':
ctx.verbose = true;
break;
case '?':
default:
print_error(&ctx, "invalid arguments");
@ -183,7 +205,7 @@ main(int argc, char **argv)
TCSGREP_DEFSEQ_NOARGS(DECKPAM),
TCSGREP_DEFSEQ_NOARGS(DECKPNM),
TCSGREP_DEFSEQ_NOARGS(RIS),
TCSGREP_DEFSEQ(DECUDK, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUMS),
TCSGREP_DEFSEQ(DECUDK, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_STR),
TCSGREP_DEFSEQ(DECRQSS, CTLSEQS_PH_STR),
TCSGREP_DEFSEQ(DECRSPS, CTLSEQS_PH_NUM, CTLSEQS_PH_STR),
TCSGREP_DEFSEQ(XTGETXRES, CTLSEQS_PH_STR),
@ -340,11 +362,12 @@ main(int argc, char **argv)
if (reader == NULL) {
print_error(&ctx, "failed to initialize reader");
}
union ctlseqs_value buffer[16];
static union ctlseqs_value buffer[4096];
struct ctlseqs_reader_options reader_options = {
.fd = STDIN_FILENO,
.maxlen = ctx.limit,
.buffer = buffer
.buffer = buffer,
.flags = ctx.verbose ? CTLSEQS_READER_SAVE_MATCHED_SEQS : 0,
};
if (ctlseqs_reader_config(reader, &reader_options) != CTLSEQS_OK) {
print_error(&ctx, "reader setopt failed");
@ -373,17 +396,14 @@ main(int argc, char **argv)
while (true) {
ssize_t result = ctlseqs_read(reader, matcher, ctx.timeout);
switch (result) {
case CTLSEQS_NOMEM:
print_error(&ctx, "failed to allocate memory");
status = 1;
goto terminate;
case CTLSEQS_ERROR:
print_error(&ctx, "unexpected error");
status = 1;
goto terminate;
case CTLSEQS_TIMEOUT:
printf("TIMEOUT\n");
break;
status = 1;
goto terminate;
case CTLSEQS_INTR:
printf("INTR\n");
break;
@ -391,19 +411,30 @@ main(int argc, char **argv)
printf("EOF\n");
break;
case CTLSEQS_PARTIAL:
print_generic_seq("PARTIAL", buffer);
if (ctx.verbose) {
print_generic_seq("PARTIAL", buffer, true);
}
break;
case CTLSEQS_NOMATCH:
print_generic_seq("NOMATCH", buffer);
print_generic_seq("NOMATCH", buffer, true);
break;
case CTLSEQS_NOMEM:
print_generic_seq("NOMEM", buffer, true);
if (ctx.purge_long_seqs) {
ctlseqs_purge(reader, buffer[0].num);
break;
} else {
status = 1;
goto terminate;
}
case CTLSEQS_NOSEQ:
print_generic_seq("NOSEQ", buffer);
print_generic_seq("NOSEQ", buffer, true);
if (buffer[1].str[0] == 0x03) {
goto terminate;
}
break;
default:
print_matching_seq(&seqs[result], buffer);
print_matching_seq(&seqs[result], buffer, ctx.verbose);
break;
}
}