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

View File

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