diff options
author | drh <> | 2025-02-24 00:18:12 +0000 |
---|---|---|
committer | drh <> | 2025-02-24 00:18:12 +0000 |
commit | 96a65cc4747cd79cf7966d03a876230c7c9ddcde (patch) | |
tree | d74d6e89df0896941359eeffabc4c66a1a237a76 | |
parent | 9ba963f03530b2d0817d5b89c8e35e8b36430290 (diff) | |
download | sqlite-96a65cc4747cd79cf7966d03a876230c7c9ddcde.tar.gz sqlite-96a65cc4747cd79cf7966d03a876230c7c9ddcde.zip |
Three different --escape modes: symbol, ascii, off.
FossilOrigin-Name: b5adb52fc0dc1838cb9c66cff422f2b8ec147e546cf909dd3c48731fa1edfe50
-rw-r--r-- | manifest | 14 | ||||
-rw-r--r-- | manifest.uuid | 2 | ||||
-rw-r--r-- | src/shell.c.in | 94 | ||||
-rw-r--r-- | test/shell1.test | 2 |
4 files changed, 82 insertions, 30 deletions
@@ -1,5 +1,5 @@ -C Further\simprovements\sto\scontrol-character\sescapes\sin\sthe\sCLI. -D 2025-02-23T20:50:37.078 +C Three\sdifferent\s--escape\smodes:\s\ssymbol,\sascii,\soff. +D 2025-02-24T00:18:12.616 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md e108e1e69ae8e8a59e93c455654b8ac9356a11720d3345df2a4743e9590fb20d @@ -782,7 +782,7 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c F src/resolve.c 626c24b258b111f75c22107aa5614ad89810df3026f5ca071116d3fe75925c75 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97 F src/select.c a076f7db3a0fcbd9f710d7746cfc07e0b3baadee45eb3136bedc29c598ef8f1c -F src/shell.c.in 46794cfa6cdd9b0bbbe35fcf7726ac1f5f7f61bb8f6578ec12ceeab5e0242108 +F src/shell.c.in e846d86150299b4f49ee4ee6a2f3b59d9460c7dda9280b6046d80778b513deec F src/sqlite.h.in 8d4486fb28a90de818ac1e8c6206ea458e7de6bd8e0dfa3d554494f155be8c01 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54 @@ -1638,7 +1638,7 @@ F test/sharedA.test 64bdd21216dda2c6a3bd3475348ccdc108160f34682c97f2f51c19fc0e21 F test/sharedB.test 1a84863d7a2204e0d42f2e1606577c5e92e4473fa37ea0f5bdf829e4bf8ee707 F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939 F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 -F test/shell1.test 069ad46cc5e576207e684168777b9d093ad419f4573ea96c47cba9d97b344ba9 +F test/shell1.test b9e7b85af3aa614536786f593684ca5317e356821ad505dad32afc2ea0e99f12 F test/shell2.test 01a01f76ed98088ce598794fbf5b359e148271541a8ddbf79d21cc353cc67a24 F test/shell3.test db1953a8e59d08e9240b7cc5948878e184f7eb2623591587f8fd1f1a5bd536d8 F test/shell4.test 522fdc628c55eff697b061504fb0a9e4e6dfc5d9087a633ab0f3dd11bcc4f807 @@ -2210,8 +2210,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7 F tool/warnings.sh 49a486c5069de041aedcbde4de178293e0463ae9918ecad7539eedf0ec77a139 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 44c44620e8648a4265053f194e32b3a5c65d25b4f1fff61ef9b944e7cb0ed624 -R b68c8cdbf574035092ab2e3bfafec994 +P 9c2f974c17e3dfac78f3808fdfe916f7617cfdaa64430af38eae21bd6592e6f5 +R 76a86dfe0f25913e8833da92cffca725 U drh -Z 1875645df727b6997bdc49f0eb677111 +Z b3eaebce72752a9b1304ed1c64dcf320 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index a486e0cfc..890ec996a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9c2f974c17e3dfac78f3808fdfe916f7617cfdaa64430af38eae21bd6592e6f5 +b5adb52fc0dc1838cb9c66cff422f2b8ec147e546cf909dd3c48731fa1edfe50 diff --git a/src/shell.c.in b/src/shell.c.in index 515da6ada..3bc8d2717 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -1549,8 +1549,11 @@ static ShellState shellState; /* Allowed values for ShellState.eEscMode */ -#define SHELL_ESC_GRAPHIC 0 /* Substitute U+2400 graphics */ -#define SHELL_ESC_OFF 1 /* Send characters verbatim */ +#define SHELL_ESC_SYMBOL 0 /* Substitute U+2400 graphics */ +#define SHELL_ESC_ASCII 1 /* Substitute ^Y for X where Y=X+0x40 */ +#define SHELL_ESC_OFF 2 /* Send characters verbatim */ + +static const char *shell_EscModeNames[] = { "symbol", "ascii", "off" }; /* ** These are the allowed shellFlgs values @@ -2160,7 +2163,8 @@ static const char *escapeOutput( *ppFree = 0; return zInX; } - zOut = sqlite3_malloc64( i + 2*nCtrl + 1 ); + if( p->eEscMode==SHELL_ESC_SYMBOL ) nCtrl *= 2; + zOut = sqlite3_malloc64( i + nCtrl + 1 ); shell_check_oom(zOut); for(i=j=0; (c = zIn[i])!=0; i++){ if( c>0x1f @@ -2176,9 +2180,17 @@ static const char *escapeOutput( } zIn += i+1; i = -1; - zOut[j++] = 0xe2; - zOut[j++] = 0x90; - zOut[j++] = 0x80+c; + switch( p->eEscMode ){ + case SHELL_ESC_SYMBOL: + zOut[j++] = 0xe2; + zOut[j++] = 0x90; + zOut[j++] = 0x80+c; + break; + case SHELL_ESC_ASCII: + zOut[j++] = '^'; + zOut[j++] = 0x40+c; + break; + } } if( i>0 ){ memcpy(&zOut[j], zIn, i); @@ -9833,28 +9845,50 @@ static int do_meta_command(char *zLine, ShellState *p){ const char *zMode = 0; const char *zTabname = 0; int i, n2; + int chng = 0; ColModeOpts cmOpts = ColModeOpts_default; for(i=1; i<nArg; i++){ const char *z = azArg[i]; if( optionMatch(z,"wrap") && i+1<nArg ){ cmOpts.iWrap = integerValue(azArg[++i]); + chng = 1; }else if( optionMatch(z,"ww") ){ cmOpts.bWordWrap = 1; + chng = 1; }else if( optionMatch(z,"wordwrap") && i+1<nArg ){ cmOpts.bWordWrap = (u8)booleanValue(azArg[++i]); + chng = 1; }else if( optionMatch(z,"quote") ){ cmOpts.bQuote = 1; + chng = 1; }else if( optionMatch(z,"noquote") ){ cmOpts.bQuote = 0; - }else if( optionMatch(z,"escape") ){ - p->eEscMode = SHELL_ESC_GRAPHIC; - }else if( optionMatch(z,"noescape") ){ - p->eEscMode = SHELL_ESC_OFF; + chng = 1; + }else if( optionMatch(z,"escape") && i+1<nArg ){ + const char *zEsc = azArg[++i]; + int k; + for(k=0; k<ArraySize(shell_EscModeNames); k++){ + if( sqlite3_stricmp(zEsc,shell_EscModeNames[k])==0 ){ + p->eEscMode = k; + chng = 1; + break; + } + } + if( k>=ArraySize(shell_EscModeNames) ){ + sqlite3_fprintf(stderr, "unknown escape mod \"%s\" - choices:", zEsc); + for(k=0; k<ArraySize(shell_EscModeNames); k++){ + sqlite3_fprintf(stderr, " %s", shell_EscModeNames[k]); + } + sqlite3_fprintf(stderr, "\n"); + rc = 1; + goto meta_command_exit; + } }else if( zMode==0 ){ zMode = z; /* Apply defaults for qbox pseudo-mode. If that * overwrites already-set values, user was informed of this. */ + chng = 1; if( cli_strcmp(z, "qbox")==0 ){ ColModeOpts cmo = ColModeOpts_default_qbox; zMode = "box"; @@ -9865,6 +9899,7 @@ static int do_meta_command(char *zLine, ShellState *p){ }else if( z[0]=='-' ){ sqlite3_fprintf(stderr,"unknown option: %s\n", z); eputz("options:\n" + " --escape MODE\n" " --noquote\n" " --quote\n" " --wordwrap on/off\n" @@ -9878,25 +9913,27 @@ static int do_meta_command(char *zLine, ShellState *p){ goto meta_command_exit; } } - if( zMode==0 ){ + if( !chng ){ if( p->mode==MODE_Column || (p->mode>=MODE_Markdown && p->mode<=MODE_Box) ){ sqlite3_fprintf(p->out, "current output mode: %s --wrap %d --wordwrap %s " - "--%squote --%sescape\n", + "--%squote --escape %s\n", modeDescr[p->mode], p->cmOpts.iWrap, p->cmOpts.bWordWrap ? "on" : "off", p->cmOpts.bQuote ? "" : "no", - p->eEscMode ? "no" : "" + shell_EscModeNames[p->eEscMode] ); }else{ sqlite3_fprintf(p->out, - "current output mode: %s --%sescape\n", + "current output mode: %s --escape %s\n", modeDescr[p->mode], - p->eEscMode ? "no" : "" + shell_EscModeNames[p->eEscMode] ); } + } + if( zMode==0 ){ zMode = modeDescr[p->mode]; } n2 = strlen30(zMode); @@ -12650,7 +12687,7 @@ static const char zOptions[] = " -deserialize open the database using sqlite3_deserialize()\n" #endif " -echo print inputs before execution\n" - " -escape print control character XX as U+24XX\n" + " -escape MODE ctrl-char escape mode, one of: symbol, ascii, off\n" " -init FILENAME read/process named file\n" " -[no]header turn headers on or off\n" #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) @@ -12673,7 +12710,6 @@ static const char zOptions[] = " -multiplex enable the multiplexor VFS\n" #endif " -newline SEP set output row separator. Default: '\\n'\n" - " -noescape output control characters unmodified\n" " -nofollow refuse to open symbolic links to database files\n" " -nonce STRING set the safe-mode escape nonce\n" " -no-rowid-in-view Disable rowid-in-view using sqlite3_config()\n" @@ -13085,6 +13121,9 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ ShellSetFlag(&data,SHFLG_TestingMode); }else if( cli_strcmp(z,"-safe")==0 ){ /* no-op - catch this on the second pass */ + }else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){ + /* skip over the argument */ + i++; } } #ifndef SQLITE_SHELL_FIDDLE @@ -13184,10 +13223,23 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ }else if( cli_strcmp(z,"-csv")==0 ){ data.mode = MODE_Csv; memcpy(data.colSeparator,",",2); - }else if( cli_strcmp(z,"-noescape")==0 ){ - data.eEscMode = SHELL_ESC_OFF; - }else if( cli_strcmp(z,"-escape")==0 ){ - data.eEscMode = SHELL_ESC_GRAPHIC; + }else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){ + const char *zEsc = argv[++i]; + int k; + for(k=0; k<ArraySize(shell_EscModeNames); k++){ + if( sqlite3_stricmp(zEsc,shell_EscModeNames[k])==0 ){ + data.eEscMode = k; + break; + } + } + if( k>=ArraySize(shell_EscModeNames) ){ + sqlite3_fprintf(stderr, "unknown escape mode \"%s\" - choices:", zEsc); + for(k=0; k<ArraySize(shell_EscModeNames); k++){ + sqlite3_fprintf(stderr, " %s", shell_EscModeNames[k]); + } + sqlite3_fprintf(stderr, "\n"); + exit(1); + } #ifdef SQLITE_HAVE_ZLIB }else if( cli_strcmp(z,"-zip")==0 ){ data.openMode = SHELL_OPEN_ZIPFILE; diff --git a/test/shell1.test b/test/shell1.test index 6189ff83a..1aa974cde 100644 --- a/test/shell1.test +++ b/test/shell1.test @@ -450,7 +450,7 @@ do_test shell1-3.12.3 { # tcl TCL list elements do_test shell1-3.13.1 { catchcmd "test.db" ".mode" -} {0 {current output mode: list --escape}} +} {0 {current output mode: list --escape symbol}} do_test shell1-3.13.2 { catchcmd "test.db" ".mode FOO" } {1 {Error: mode should be one of: ascii box column csv html insert json line list markdown qbox quote table tabs tcl}} |