From cf4fb1ac2092bb4700704e8e57b8dc44ca40847e Mon Sep 17 00:00:00 2001 From: larrybr Date: Sat, 5 Feb 2022 23:45:07 +0000 Subject: [PATCH] CLI cleanup, mode push/pop, parameter list beautification FossilOrigin-Name: 53d4582a0e9dab594264a5125324e1fab476e5fd806ebc61bd5fc6ffff10e34b --- manifest | 13 ++-- manifest.uuid | 2 +- src/shell.c.in | 158 ++++++++++++++++++++++++++++++++++++++--------- test/shell9.test | 69 +++++++++++++++++++++ 4 files changed, 206 insertions(+), 36 deletions(-) create mode 100644 test/shell9.test diff --git a/manifest b/manifest index 413eccbebe..0c7489652a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sCLI\sWindows\sbuild,\srefine\sits\shelp,\sre-org\sShellState -D 2022-02-05T15:26:39.028 +C CLI\scleanup,\smode\spush/pop,\sparameter\slist\sbeautification +D 2022-02-05T23:45:07.085 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -553,7 +553,7 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 0dd8e23fda88411d63b2e6650f2380fdb08e88112e9a095fc23d5a08de4b2641 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c a6d2d4bed279d7fe4fcedaf297eaf6441e8e17c6e3947a32d24d23be52ac02f2 -F src/shell.c.in 7c1978cfec3647870d7b2fe45178ec323a44e5549041be7db0ed190c4701579b x +F src/shell.c.in 537c1cfe3e7b90c94dbddf6226b951154cdb239f755a883008223296f5e07f28 x F src/sqlite.h.in d4daed3b2deb2e43df7f12be119b1b17a2954feadc33d521565bacbd072bfcb6 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h a95cb9ed106e3d39e2118e4dcc15a14faec3fa50d0093425083d340d9dfd96e6 @@ -1395,6 +1395,7 @@ F test/shell5.test b85069bfcf3159b225228629ab2c3e69aa923d098fea8ea074b5dcd743522 F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3 F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f F test/shell8.test 388471d16e4de767333107e30653983f186232c0e863f4490bb230419e830aae +F test/shell9.test 05f656a4c61b6e17b36a8cf7a70edffa6a77348bf4d633fb5cefb86b0127ce6b F test/shmlock.test 3dbf017d34ab0c60abe6a44e447d3552154bd0c87b41eaf5ceacd408dd13fda5 F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3 F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5 @@ -1943,8 +1944,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 6d415ac2c10da26e97164cb0846683a57e6a7f3717519c5fe889e077321a2cbd -R caf017840a4e87c78151d22dc2043bdc +P 991a06a4801270fddea7375d141863dc29fa87b737c728af60c81eea8445a0ea +R 0d98364e4220742b71a54a3a478fca95 U larrybr -Z 304046c8b2c6fad5a59c02f068067d82 +Z 19e18e7127c918582442483575f4c74f # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 6ec5f92c17..9a5620d41d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -991a06a4801270fddea7375d141863dc29fa87b737c728af60c81eea8445a0ea \ No newline at end of file +53d4582a0e9dab594264a5125324e1fab476e5fd806ebc61bd5fc6ffff10e34b \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 19f828370c..7ddd2dc7ce 100755 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -1141,6 +1141,11 @@ struct EQPGraph { char zPrefix[100]; /* Graph prefix */ }; +/* By default, omit the extension options that are not done yet. */ +#ifndef SHELL_OMIT_EXTENSIONS +# define SHELL_OMIT_EXTENSIONS 6 +#endif + /* Selectively omit features with one PP variable. Value is true iff ** either x is not defined or defined with 0 in bitnum bit position. */ @@ -1190,14 +1195,21 @@ typedef struct ColModeOpts { #define ColModeOpts_default { 60, 0, 0 } #define ColModeOpts_default_qbox { 60, 1, 0 } -typedef struct OutModeState { - u8 showHeader; /* True to show column names in List or Column mode */ - u8 mode; /* An output mode setting */ - u16 shellFlgs; /* Various flags */ - ColModeOpts cmOpts; /* Option values affecting columnar mode output */ - char colSeparator[20]; /* Column separator character for several modes */ - char rowSeparator[20]; /* Row separator character for MODE_Ascii */ -} OutModeState; +/* +** Stored output mode state, for partial save and later restore. +** Returned by: +** outputModeSave *outputModeSave(ShellState *p, SaveModeWhat ws). +** Accepted by: +** outputModeRestore(ShellState *p, OutputModeSave *pSaved). +** See enum SaveWhatMode regarding what to save and restore. +** Also see outputModePush(...), outputModePushSome(...) and +** outputModePop(...) for usages spanning more than one call. +*/ +typedef struct OutputModeSave{ + u16 what; /* Set upon creation. See SaveWhatMode for values. */ + char itsValues[1]; /* This size is inaccurate unless nothing is saved. */ +} OutputModeSave; +#define MODE_STACK_MAX 3 /* How many levels of saved output mode to allow. */ /* ** State information about the database connection is contained in an @@ -1206,13 +1218,13 @@ typedef struct OutModeState { typedef struct ShellState ShellState; struct ShellState { sqlite3 *db; /* The database */ + int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */ + u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */ u8 autoExplain; /* Automatically turn on .explain mode */ u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ u8 autoEQPtest; /* autoEQP is in test mode */ u8 autoEQPtrace; /* autoEQP is in trace mode */ u8 scanstatsOn; /* True to display scan stats before each finalize */ - u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */ - int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */ u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */ u8 nEqpLevel; /* Depth of the EQP output graph */ u8 eTraceType; /* SHELL_TRACE_* value for type of trace */ @@ -1220,19 +1232,19 @@ struct ShellState { u8 bSafeModePersist; /* The long-term value of bSafeMode */ u8 bAllowSysDump; /* Allow .dump use for sqlite_* tables. */ u8 bExtendedDotCmds; /* Bits set to enable various shell extensions */ - + /* Output mode state subject to systematic save/restore: (See OM_STATE.) */ u8 showHeader; /* True to show column names in List or Column mode */ u16 shellFlgs; /* Various flags */ - u16 priorShFlgs; /* Saved copy of flags */ u8 mode; /* An output mode setting */ - u8 modePrior; /* Saved mode */ - u8 cMode; /* temporary output mode for the current query */ - u8 normalMode; /* Output mode before ".explain on" */ ColModeOpts cmOpts; /* Option values affecting columnar mode output */ char colSeparator[20]; /* Column separator character for several modes */ - char colSepPrior[20]; /* Saved column separator */ char rowSeparator[20]; /* Row separator character for MODE_Ascii */ - char rowSepPrior[20]; /* Saved row separator */ + /* Output mode state-keep for systematic save/restore: (See OM_STATE.) */ + u8 nSavedModes; /* number of valid items in next array */ + OutputModeSave *pModeStack[MODE_STACK_MAX]; /* saved mode data buffers */ + /* Output mode state-keep for certain ad-hoc save/restore ops: */ + u8 cMode; /* temporary output mode for the current query */ + u8 normalMode; /* Output mode before ".explain on" */ int *colWidth; /* Requested width of each column in columnar modes */ int *actualWidth; /* Actual width of each column */ @@ -1587,19 +1599,97 @@ edit_func_end: #endif /* SQLITE_NOHAVE_SYSTEM */ /* -** Save or restore the current output mode +** Save or restore the current output mode, partially per spec. (OM_STATE) +*/ +typedef enum { + SWM_showHeader = 1, SWM_shellFlags = 2, SWM_mode = 4, SWM_cmOpts = 8, + SWM_colSeparator = 0x10, SWM_rowSeparator = 0x20, SWM_everything = 0x3F, + SWM_CountOf = 6 +} SaveWhatMode; + +/* This is available in most C89+ C compilers as offsetof(...), but since we + * cater to the most arcane C89-like compilers around, define it for sure: + */ +#define MEMBER_OFFSET(stype, member) ((size_t)&(((stype*)0)->member)) +#define MEMBER_SIZEOF(stype, member) (sizeof(((stype*)0)->member)) +static struct { + size_t offset; + size_t size; +} outputModeCopy[] = { +#define SS_MEMBER_COPY(mn) \ + { MEMBER_OFFSET(ShellState,mn), MEMBER_SIZEOF(ShellState,mn) } + SS_MEMBER_COPY(showHeader), SS_MEMBER_COPY(shellFlgs), + SS_MEMBER_COPY(mode), SS_MEMBER_COPY(cmOpts), + SS_MEMBER_COPY(colSeparator), SS_MEMBER_COPY(rowSeparator) +#undef SS_MEMBER_COPY +}; + +/* Allocate a buffer, copy requested output mode data to it, and return it. */ +static OutputModeSave *outputModeSave(ShellState *p, SaveWhatMode w){ + u16 what = (u16)w; + int i, nAlloc = sizeof(what)+1, mask = 1; + char *pSaved = 0, *pFill; + for( i=0; isizeof(what))? *((u16 *)pSaved) : 0; + int i, nAlloc = sizeof(what)+1, mask = 1; + char *pTake = (char *)pSaved + sizeof(what); + for( i=0; inSavedModesnSavedModes>=MODE_STACK_MAX ) return; + pOMS = outputModeSave(p, w); + shell_check_oom(pOMS); + p->pModeStack[p->nSavedModes++] = pOMS; +} static void outputModePush(ShellState *p){ - p->modePrior = p->mode; - p->priorShFlgs = p->shellFlgs; - memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator)); - memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator)); + outputModePushSome(p, SWM_everything); } static void outputModePop(ShellState *p){ - p->mode = p->modePrior; - p->shellFlgs = p->priorShFlgs; - memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator)); - memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator)); + OutputModeSave *pOMS; + assert(p->nSavedModes>0); /* Should not be here unless something pushed. */ + if( p->nSavedModes==0 ) return; + pOMS = p->pModeStack[--p->nSavedModes]; + assert(pOMS!=0); + p->pModeStack[p->nSavedModes] = 0; + outputModeRestore(p, pOMS); } /* @@ -8525,18 +8615,27 @@ static void list_params(ShellState *p, ParamTableUse ptu){ if( sqlite3_step(pStmt)==SQLITE_ROW ){ len = sqlite3_column_int(pStmt, 0); if( len>40 ) len = 40; + if( len<4 ) len = 4; } } sqlite3_finalize(pStmt); pStmt = 0; if( len ){ + utf8_printf(p->out, "%-*s %-8s %s\n", len, "name", "usage", "value"); rc = sqlite3_prepare_v2 - (p->db, "SELECT key, quote(value) FROM " + (p->db, "SELECT key, uses, quote(value) FROM " PARAM_TABLE_SNAME" WHERE ?1=3 OR uses=?1", -1, &pStmt, 0); sqlite3_bind_int(pStmt, 1, ptu); while( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){ - utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0), - sqlite3_column_text(pStmt,1)); + ParamTableUse ptux = sqlite3_column_int(pStmt,1); + const char *zUse; + switch( ptux ){ + case PTU_Binding: zUse = "binding"; break; + case PTU_Script: zUse = "script"; break; + default: zUse = "unknown"; + } + utf8_printf(p->out, "%-*s %-8s %s\n", len, sqlite3_column_text(pStmt,0), + zUse, sqlite3_column_text(pStmt,2)); } sqlite3_finalize(pStmt); } @@ -13316,6 +13415,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ #endif free(data.colWidth); free(data.zNonce); + for(i=0; i