From: drh <> Date: Sat, 11 Apr 2026 22:58:25 +0000 (+0000) Subject: CLI prompt design change: The escape character is changed from \ to X-Git-Url: http://git.ipfire.org/index.cgi?a=commitdiff_plain;h=c0026ff7a607b3ca0715696ee898f7a25a77ddeb;p=thirdparty%2Fsqlite.git CLI prompt design change: The escape character is changed from \ to %#37;. This avoids lots of quoting problems when trying to specify prompt strings in various programming languages and shells. FossilOrigin-Name: e7e6ecc45dfe1a163d259be26877bd7e528ce154e73b3ca8ab7edc5aa94d2d02 --- diff --git a/manifest b/manifest index 222e2e319c..166e84b328 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Two\sC-preprocessor\smacros\sSQLITE_PS1\sand\sSQLITE_PS2\scan\sbe\sset\sto\soverride\nthe\sdefault\sprompt\sstrings\sin\sthe\sCLI. -D 2026-04-11T22:18:05.507 +C CLI\sprompt\sdesign\schange:\s\sThe\sescape\scharacter\sis\schanged\sfrom\s\\sto\n%#37;.\s\sThis\savoids\slots\sof\squoting\sproblems\swhen\strying\sto\sspecify\sprompt\nstrings\sin\svarious\sprogramming\slanguages\sand\sshells. +D 2026-04-11T22:58:25.521 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -735,7 +735,7 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c F src/resolve.c 928ff887f2a7c64275182060d94d06fdddbe32226c569781cf7e7edc6f58d7fd F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97 F src/select.c ffe199f025a0dd74670d2a77232bdea364a4d7b36f32c64a6572d39ba6a11576 -F src/shell.c.in ec0603f2c689611761c0158b03945b45be1f82458faf24c98a22efb0392e2e1c +F src/shell.c.in 1984ce045f526350d9d5c896b1cf8016acd46a8f973e493e00d0837db07cbac4 F src/sqlite.h.in a5605faa9479bbaac16c4ab43eb09ff50632004a8e05084d3fde56063ef73766 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479 F src/sqlite3ext.h 9788c301f95370fa30e808861f1d2e6f022a816ddbe2a4f67486784c1b31db2e @@ -1619,7 +1619,7 @@ F test/sharedA.test 64bdd21216dda2c6a3bd3475348ccdc108160f34682c97f2f51c19fc0e21 F test/sharedB.test 1a84863d7a2204e0d42f2e1606577c5e92e4473fa37ea0f5bdf829e4bf8ee707 F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939 F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 -F test/shell-prompt.sql c1437f778af91ae3dcb705225c09564a84197626f93de4725233c4ab6ac6daf0 +F test/shell-prompt.sql e8fb30de8ad201eeee0ba1f49505974010f1429f46f9e2c01f0dc6a4135f68cb F test/shell1.test eda2e527435f139224dda67db6bbd2466597408d4fe5883d647d67fa32d88f7c F test/shell2.test dc541d2681503e55466a24d35a4cbf8ca5b90b8fcdef37fc4db07373a67d31d3 F test/shell3.test 91efdd545097a61a1f72cf79c9ad5b49da080f3f10282eaf4c3c272cd1012db2 @@ -2198,8 +2198,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P 50d81300ba0f021f388aab1e86e97d688ed762cee408c610cf70977f7b488803 -R ce155f157db3345b96c76c7aebb15cce +P 6fa0216a19c2f165110121227d3f9b9119369f8cd61f9c6d13eaa1ae42a60d60 +R 5cf6d69f7c518c6e5fa5be100b777a6a U drh -Z c75826f50d2605e4feec81bbbbe95eef +Z 9c57625d95f1bb2a7bd8171d3c1fac72 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 75061e0b85..5972c2cae5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6fa0216a19c2f165110121227d3f9b9119369f8cd61f9c6d13eaa1ae42a60d60 +e7e6ecc45dfe1a163d259be26877bd7e528ce154e73b3ca8ab7edc5aa94d2d02 diff --git a/src/shell.c.in b/src/shell.c.in index e5fb186b48..551b328fb1 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -911,10 +911,10 @@ static char *local_getline(char *zLine, FILE *in){ ** The default prompts. */ #ifndef SQLITE_PS1 -# define SQLITE_PS1 "SQLite \\f> " +# define SQLITE_PS1 "SQLite %f> " #endif #ifndef SQLITE_PS2 -# define SQLITE_PS2 "\\B...\\H> " +# define SQLITE_PS2 "%B...%H> " #endif /* @@ -967,6 +967,11 @@ static const char *prompt_filename(ShellState *p){ ** Expand escapes in the given input prompt string. Return the ** expanded prompt in memory obtained from sqlite3_malloc(). The ** caller is responsible for freeing the memory. +** +** Early prototypes use U+005c '\\' as the escape character. But +** that is an escape character for shells and C and many other languages, +** which can lead to nested quoting problems and confusion. For that +** reason, the escape character is changed to U+0025 '%'. */ static char *expand_prompt( ShellState *p, /* The current shell state */ @@ -979,27 +984,27 @@ static char *expand_prompt( int onoff = 1; int idxSpace = -1; for(i=0; zPrompt[i]; i++){ - if( zPrompt[i]!='\\' ) continue; + if( zPrompt[i]!='%' ) continue; if( i>0 ){ if( onoff ) sqlite3_str_append(pOut, zPrompt, i); zPrompt += i; i = 0; } - /* At this point zPrompt[0] is a \ character and all prior + /* At this point zPrompt[0] is a % character and all prior ** characters have already been loaded into pOut. Process the ** escape sequence that zPrompt points to. */ c = zPrompt[1]; if( c==0 ){ - /* \ at the end of a line is silently ignored */ + /* ~ at the end of a line is silently ignored */ break; } - if( c=='\\' ){ - /* \\ maps into a single \ */ + if( c=='%' ){ + /* %% maps into a single % */ zPrompt++; continue; } if( c>='0' && c<='7' ){ - /* \nnn becomes a single byte given by octal nnn */ + /* %nnn becomes a single byte given by octal nnn */ int v = c - '0'; while( i<=2 && zPrompt[i+1]>='0' && zPrompt[i+1]<='7' ){ v = v*8 + zPrompt[++i] - '0'; @@ -1010,7 +1015,7 @@ static char *expand_prompt( continue; } if( c=='e' ){ - /* \e is \033 "Escape" */ + /* %e is shorthand for %033 which is U+001B "Escape" */ if( onoff ) sqlite3_str_append(pOut, "\033", 1); zPrompt += 2; i = -1; @@ -1022,12 +1027,12 @@ static char *expand_prompt( ** currently in a transaction. Example 1: Show a "*" before the ">" ** like psql: ** - ** .prompt 'sqlite\x*\;> ' + ** .prompt 'sqlite%x*%;> ' ** ** Example 2: Show database filename is blue if not in a transaction, ** or red if within a transaction: ** - ** .prompt '\e[1;\x31\:34\;m\f>\e[0m ' + ** .prompt '%e[1;%x31%:34%;m~f>%e[0m ' */ if( c==':' ){ /* toggle display on/off */ @@ -1044,7 +1049,7 @@ static char *expand_prompt( continue; } if( c=='x' ){ - /* \x turns display off not in a transaction, on if in txn */ + /* %x turns display off not in a transaction, on if in txn */ onoff = p->db && !sqlite3_get_autocommit(p->db); zPrompt += 2; i = -1; @@ -1052,9 +1057,9 @@ static char *expand_prompt( } if( c=='f' || c=='F' || c=='~' ){ - /* \f becomes the tail of the database filename */ - /* \F becomes the full pathname */ - /* \~ becomes the full pathname relative to $HOME */ + /* %f becomes the tail of the database filename */ + /* %F becomes the full pathname */ + /* %~ becomes the full pathname relative to $HOME */ if( onoff ){ const char *zFN = prompt_filename(p); if( c=='f' ){ @@ -1083,7 +1088,7 @@ static char *expand_prompt( } if( c=='H' ){ - /* \H becomes text needed to terminate current input */ + /* %H becomes text needed to terminate current input */ if( onoff ){ sqlite3_int64 R = zPrior ? sqlite3_incomplete(zPrior) : 0; int cc = (R>>16)&0xff; @@ -1115,8 +1120,8 @@ static char *expand_prompt( } if( c=='B' ){ - /* \B is a no-op for the main prompt. For the continuation prompt, - ** \B expands to zero or more spaces to make the continuation prompt + /* %B is a no-op for the main prompt. For the continuation prompt, + ** %B expands to zero or more spaces to make the continuation prompt ** at least as wide as the main prompt. */ if( onoff ) idxSpace = sqlite3_str_length(pOut); zPrompt += 2; @@ -1125,7 +1130,7 @@ static char *expand_prompt( } /* No match to a known escape. Generate an error. */ - if( onoff ) sqlite3_str_appendf(pOut,"UNKNOWN(\"\\%c\")",c); + if( onoff ) sqlite3_str_appendf(pOut,"UNKNOWN(\"%%%c\")",c); zPrompt += 2; i = -1; } @@ -1133,7 +1138,7 @@ static char *expand_prompt( sqlite3_str_append(pOut, zPrompt, i); } - /* Expand the \B, if there is one and if this is a continuation prompt */ + /* Expand the %B, if there is one and if this is a continuation prompt */ if( idxSpace>=0 && zPrior!=0 && zPrior[0]!=0 ){ char *zOther = expand_prompt(p, 0, prompt_string(p,0)); size_t wOther = sqlite3_qrf_wcswidth(zOther); diff --git a/test/shell-prompt.sql b/test/shell-prompt.sql index 215b54485f..4f880899ce 100644 --- a/test/shell-prompt.sql +++ b/test/shell-prompt.sql @@ -28,8 +28,8 @@ .testcase 110 .prompt --show .check < ' -Continuation: '\B...\H> ' +Main prompt: 'SQLite %f> ' +Continuation: '%B...%H> ' END .testcase 1000 @@ -61,7 +61,7 @@ SELECT shell_prompt_test(NULL,'CREATE TRIGGER t1 BEGIN SELECT 1;'); .check " ...END;> "; .testcase 2000 -.prompt 'SQLite\x-txn$\:>\; ' +.prompt 'SQLite%x-txn$%:>%; ' SELECT shell_prompt_test(NULL); .check 'SQLite> '; .testcase 2001