From 939930db1e6ae3d942571688867236d44b897980 Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 2 Apr 2026 11:43:04 +0000 Subject: [PATCH 01/19] Improvements to the syntax hints in the continuation prompt of the CLI FossilOrigin-Name: 5c544f169680804c9652b8f9fc843a4bac052706be6bac205baf13a8c83fc840 --- manifest | 15 ++++++----- manifest.tags | 4 +-- manifest.uuid | 2 +- src/shell.c.in | 68 ++++++++++++++++++++++++++------------------------ 4 files changed, 48 insertions(+), 41 deletions(-) diff --git a/manifest b/manifest index dee8022439..2344aa0734 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Always\suse\ssqlite3_malloc64()\sin\sextensions,\swhere\spossible. -D 2026-04-01T16:56:48.155 +C Improvements\sto\sthe\ssyntax\shints\sin\sthe\scontinuation\sprompt\sof\sthe\sCLI +D 2026-04-02T11:43:04.587 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 91ee40ec3f75192362cbaa0ad85316140b8dde00a184113d73a837fb6173dbcc +F src/shell.c.in fd7a7e7ddeaeec5ecda9ddcba5fa336bbc60f4024c54542dc1e85e00c1d67ef2 F src/sqlite.h.in 9cc1df08742989eb67ed2065f73a582195c48fee2eec5df9df122b33d4872885 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479 F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca @@ -2197,8 +2197,11 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P 91ead3c62dd7b1db3fdfd318e3c35a42fb33e8fa2e347b682eecbff2f4e8677b -R 6ba98470db6b05f2faea33c928a02358 +P 6194f3b5314ef98b5d73060450de8e3497272494b47e6f96992453418894ded1 +R ad9575498347584523c956e285476300 +T *branch * cli-prompt +T *sym-cli-prompt * +T -sym-trunk * U drh -Z 794fc55ed4b29b8614c8a579512409b7 +Z 39d54ce0e0b0fb1346202fa0ae4a8eab # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.tags b/manifest.tags index bec971799f..dd3d6d7cb3 100644 --- a/manifest.tags +++ b/manifest.tags @@ -1,2 +1,2 @@ -branch trunk -tag trunk +branch cli-prompt +tag cli-prompt diff --git a/manifest.uuid b/manifest.uuid index 7761c3627b..0046bf2858 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6194f3b5314ef98b5d73060450de8e3497272494b47e6f96992453418894ded1 +5c544f169680804c9652b8f9fc843a4bac052706be6bac205baf13a8c83fc840 diff --git a/src/shell.c.in b/src/shell.c.in index c931055ca2..3b170d7c66 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -811,14 +811,6 @@ static char *shell_strncpy(char *dest, const char *src, size_t n){ return dest; } -/* -** strcpy() workalike to squelch an unwarranted link-time warning -** from OpenBSD. -*/ -static void shell_strcpy(char *dest, const char *src){ - while( (*(dest++) = *(src++))!=0 ){} -} - /* ** Optionally disable dynamic continuation prompt. ** Unless disabled, the continuation prompt shows open SQL lexemes if any, @@ -876,31 +868,41 @@ static void setLexemeOpen(struct DynaPrompt *p, char *s, char c){ /* Upon demand, derive the continuation prompt to display. */ static char *dynamicContinuePrompt(void){ - if( continuePrompt[0]==0 - || (dynPrompt.zScannerAwaits==0 && dynPrompt.inParenLevel == 0) ){ + int k; /* Number of context hint characters */ + int nSpace; /* Spaces at the start of continuePrompt */ + int nDot; /* Dots following spaces */ + int nOrig; /* Total size of continuePrompt in bytes */ + int nCore; /* nOrig + 1 - nSpace */ + + nOrig = (int)strlen(continuePrompt); + if( nOrig<=1 + || (dynPrompt.zScannerAwaits==0 && dynPrompt.inParenLevel == 0) + ){ return continuePrompt; - }else{ - if( dynPrompt.zScannerAwaits ){ - size_t ncp = strlen(continuePrompt); - size_t ndp = strlen(dynPrompt.zScannerAwaits); - if( ndp > ncp-3 ) return continuePrompt; - shell_strcpy(dynPrompt.dynamicPrompt, dynPrompt.zScannerAwaits); - while( ndp<3 ) dynPrompt.dynamicPrompt[ndp++] = ' '; - shell_strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3, - PROMPT_LEN_MAX-4); - }else{ - if( dynPrompt.inParenLevel>9 ){ - shell_strncpy(dynPrompt.dynamicPrompt, "(..", 4); - }else if( dynPrompt.inParenLevel<0 ){ - shell_strncpy(dynPrompt.dynamicPrompt, ")x!", 4); - }else{ - shell_strncpy(dynPrompt.dynamicPrompt, "(x.", 4); - dynPrompt.dynamicPrompt[2] = (char)('0'+dynPrompt.inParenLevel); - } - shell_strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3, - PROMPT_LEN_MAX-4); + } + for(nSpace=0; continuePrompt[nSpace]==' '; nSpace++){} + for(nDot=0; continuePrompt[nSpace+nDot]=='.'; nDot++){} + nCore = nOrig + 1 - nSpace; + for(k=0; knSpace && nDot ){ + nSpace++; + nDot--; + } + memcpy(&dynPrompt.dynamicPrompt[k], + &continuePrompt[nSpace], + nCore); return dynPrompt.dynamicPrompt; } #endif /* !defined(SQLITE_OMIT_DYNAPROMPT) */ @@ -12125,8 +12127,10 @@ static QuickScanState quickscan(char *zLine, QuickScanState qss, } break; case '[': - cin = ']'; - deliberate_fall_through; /* FALLTHRU */ + cWait = ']'; + qss = QSS_HasDark | cWait; + CONTINUE_PROMPT_AWAITC(pst, cin); + goto TermScan; case '`': case '\'': case '"': cWait = cin; qss = QSS_HasDark | cWait; From 3944e7067771b4f62f5f6e8e60b675d47ce20feb Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 9 Apr 2026 18:51:09 +0000 Subject: [PATCH 02/19] Clean-ups in prompt generation in the CLI. FossilOrigin-Name: e2c9d4c6b731ea9afbb9cb22f86a3db3670ca67968f15891dc46ae1fc9ba34dc --- manifest | 12 +++++----- manifest.uuid | 2 +- src/shell.c.in | 60 +++++++++++++++++++++++++++----------------------- 3 files changed, 40 insertions(+), 34 deletions(-) diff --git a/manifest b/manifest index 14b4572856..96d0083569 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\s3.53.0\srelease\schanges\sinto\sthe\scli-prompt\sbranch -D 2026-04-09T13:21:09.840 +C Clean-ups\sin\sprompt\sgeneration\sin\sthe\sCLI. +D 2026-04-09T18:51:09.198 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 a81e410148dbe766675291436cd0e8d5eed3d201c84325c650214f7005957825 +F src/shell.c.in 1dcccee78238e27dfa90df67e15fb194c087f552608248fd900b7a5ee730782a F src/sqlite.h.in e2915e4a86d5e0783afb5cb72411df38d987c7f3c5aa2d5441b8e74d30b649d8 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479 F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca @@ -2197,8 +2197,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P 5c544f169680804c9652b8f9fc843a4bac052706be6bac205baf13a8c83fc840 4525003a53a7fc63ca75c59b22c79608659ca12f0131f52c18637f829977f20b -R 23f77bc70e281ba78bda728ec5fa2cf0 +P 8fd48b9fe47d47b3eca31d187f1d98174c257daea220ae7be18e4c82764d9d5c +R 7ffb65d89e42eb90bf23dccbc7a1df3f U drh -Z 6d085a4adab77824df1df33b9c2cf0d2 +Z ee302bdc160a37743cf8ada2bf8fc7e4 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 60a6fac2ae..8a875c645a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8fd48b9fe47d47b3eca31d187f1d98174c257daea220ae7be18e4c82764d9d5c +e2c9d4c6b731ea9afbb9cb22f86a3db3670ca67968f15891dc46ae1fc9ba34dc diff --git a/src/shell.c.in b/src/shell.c.in index c1f1e648de..1df77e475a 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -828,16 +828,16 @@ static char *shell_strncpy(char *dest, const char *src, size_t n){ typedef void *t_NoDynaPrompt; # define SCAN_TRACKER_REFTYPE t_NoDynaPrompt #else -# define CONTINUATION_PROMPT dynamicContinuePrompt() -# define CONTINUE_PROMPT_RESET \ +# define CONTINUATION_PROMPT(X) dynamicContinuePrompt() +# define CONTINUE_PROMPT_RESET(X) \ do {setLexemeOpen(&dynPrompt,0,0); trackParenLevel(&dynPrompt,0);} while(0) -# define CONTINUE_PROMPT_AWAITS(p,s) \ +# define CONTINUE_PROMPT_AWAITS(X,p,s) \ if(p && stdin_is_interactive) setLexemeOpen(p, s, 0) -# define CONTINUE_PROMPT_AWAITC(p,c) \ +# define CONTINUE_PROMPT_AWAITC(X,p,c) \ if(p && stdin_is_interactive) setLexemeOpen(p, 0, c) -# define CONTINUE_PAREN_INCR(p,n) \ +# define CONTINUE_PAREN_INCR(X,p,n) \ if(p && stdin_is_interactive) (trackParenLevel(p,n)) -# define CONTINUE_PROMPT_PSTATE (&dynPrompt) +# define CONTINUE_PROMPT_PSTATE(X) (&dynPrompt) typedef struct DynaPrompt *t_DynaPromptRef; # define SCAN_TRACKER_REFTYPE t_DynaPromptRef @@ -1048,7 +1048,7 @@ static char *one_input_line(ShellState *p, char *zPrior, int isContinuation){ if( in!=0 ){ zResult = local_getline(zPrior, in); }else{ - zPrompt = isContinuation ? CONTINUATION_PROMPT : mainPrompt; + zPrompt = isContinuation ? CONTINUATION_PROMPT(p) : mainPrompt; #if SHELL_USE_LOCAL_GETLINE sputz(stdout, zPrompt); fflush(stdout); @@ -12082,8 +12082,10 @@ meta_command_exit: # define CHAR_BIT 8 #endif typedef enum { - QSS_HasDark = 1<zInFile = zSrc; saved_lineno = p->lineno; p->lineno = 0; - CONTINUE_PROMPT_RESET; + CONTINUE_PROMPT_RESET(p); while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){ fflush(p->out); zLine = one_input_line(p, zLine, nSql>0); @@ -12455,11 +12461,11 @@ static int process_input(ShellState *p, const char *zSrc){ } p->lineno++; if( QSS_INPLAIN(qss) - && line_is_command_terminator(zLine) + && line_is_command_terminator(p, zLine) && line_is_complete(zSql, nSql) ){ memcpy(zLine,";",2); } - qss = quickscan(zLine, qss, CONTINUE_PROMPT_PSTATE); + qss = quickscan(p, zLine, qss, CONTINUE_PROMPT_PSTATE(p)); if( QSS_PLAINWHITE(qss) && nSql==0 ){ /* Just swallow single-line whitespace */ echo_group_input(p, zLine); @@ -12467,7 +12473,7 @@ static int process_input(ShellState *p, const char *zSrc){ continue; } if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){ - CONTINUE_PROMPT_RESET; + CONTINUE_PROMPT_RESET(p); echo_group_input(p, zLine); if( zLine[0]=='.' ){ rc = do_meta_command(zLine, p); @@ -12511,7 +12517,7 @@ static int process_input(ShellState *p, const char *zSrc){ }else if( nSql && QSS_SEMITERM(qss) && sqlite3_complete(zSql) ){ echo_group_input(p, zSql); errCnt += runOneSqlLine(p, zSql, p->zInFile, startline); - CONTINUE_PROMPT_RESET; + CONTINUE_PROMPT_RESET(p); nSql = 0; if( p->nPopOutput ){ output_reset(p); @@ -12535,7 +12541,7 @@ static int process_input(ShellState *p, const char *zSrc){ /* This may be incomplete. Let the SQL parser deal with that. */ echo_group_input(p, zSql); errCnt += runOneSqlLine(p, zSql, p->zInFile, startline); - CONTINUE_PROMPT_RESET; + CONTINUE_PROMPT_RESET(p); } free(zSql); free(zLine); From 30b824e432fa8539bcb4e32bfd511e1cdd8e4260 Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 9 Apr 2026 20:21:25 +0000 Subject: [PATCH 03/19] Strip out the legacy dynamic prompt generation. It will go back in as I add the user-defined prompt escapes. FossilOrigin-Name: ab08b7a8ef518f96a549a41fe8ff11776abe5e83153c5f8d5d58694ecc476389 --- manifest | 15 +-- manifest.tags | 4 +- manifest.uuid | 2 +- src/shell.c.in | 261 +++++++------------------------------------------ 4 files changed, 48 insertions(+), 234 deletions(-) diff --git a/manifest b/manifest index 96d0083569..f7524ecc9a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Clean-ups\sin\sprompt\sgeneration\sin\sthe\sCLI. -D 2026-04-09T18:51:09.198 +C Strip\sout\sthe\slegacy\sdynamic\sprompt\sgeneration.\s\sIt\swill\sgo\sback\sin\sas\sI\nadd\sthe\suser-defined\sprompt\sescapes. +D 2026-04-09T20:21:25.880 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 1dcccee78238e27dfa90df67e15fb194c087f552608248fd900b7a5ee730782a +F src/shell.c.in d2d6accf85d516d39ffb5101e3209e22b062c014be0b7c467c12bc3d2e9a4f96 F src/sqlite.h.in e2915e4a86d5e0783afb5cb72411df38d987c7f3c5aa2d5441b8e74d30b649d8 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479 F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca @@ -2197,8 +2197,11 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P 8fd48b9fe47d47b3eca31d187f1d98174c257daea220ae7be18e4c82764d9d5c -R 7ffb65d89e42eb90bf23dccbc7a1df3f +P e2c9d4c6b731ea9afbb9cb22f86a3db3670ca67968f15891dc46ae1fc9ba34dc +R 6a381ddbe79e14291b50a57316105ea7 +T *branch * cli-prompt-redo +T *sym-cli-prompt-redo * +T -sym-cli-prompt * U drh -Z ee302bdc160a37743cf8ada2bf8fc7e4 +Z 400a2e048f10888511ab99293cd1badd # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.tags b/manifest.tags index dd3d6d7cb3..f633b85a28 100644 --- a/manifest.tags +++ b/manifest.tags @@ -1,2 +1,2 @@ -branch cli-prompt -tag cli-prompt +branch cli-prompt-redo +tag cli-prompt-redo diff --git a/manifest.uuid b/manifest.uuid index 8a875c645a..ea4743febf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e2c9d4c6b731ea9afbb9cb22f86a3db3670ca67968f15891dc46ae1fc9ba34dc +ab08b7a8ef518f96a549a41fe8ff11776abe5e83153c5f8d5d58694ecc476389 diff --git a/src/shell.c.in b/src/shell.c.in index 1df77e475a..705400a05d 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -811,102 +811,6 @@ static char *shell_strncpy(char *dest, const char *src, size_t n){ return dest; } -/* -** Optionally disable dynamic continuation prompt. -** Unless disabled, the continuation prompt shows open SQL lexemes if any, -** or open parentheses level if non-zero, or continuation prompt as set. -** This facility interacts with the scanner and process_input() where the -** below 5 macros are used. -*/ -#ifdef SQLITE_OMIT_DYNAPROMPT -# define CONTINUATION_PROMPT continuePrompt -# define CONTINUE_PROMPT_RESET -# define CONTINUE_PROMPT_AWAITS(p,s) -# define CONTINUE_PROMPT_AWAITC(p,c) -# define CONTINUE_PAREN_INCR(p,n) -# define CONTINUE_PROMPT_PSTATE 0 -typedef void *t_NoDynaPrompt; -# define SCAN_TRACKER_REFTYPE t_NoDynaPrompt -#else -# define CONTINUATION_PROMPT(X) dynamicContinuePrompt() -# define CONTINUE_PROMPT_RESET(X) \ - do {setLexemeOpen(&dynPrompt,0,0); trackParenLevel(&dynPrompt,0);} while(0) -# define CONTINUE_PROMPT_AWAITS(X,p,s) \ - if(p && stdin_is_interactive) setLexemeOpen(p, s, 0) -# define CONTINUE_PROMPT_AWAITC(X,p,c) \ - if(p && stdin_is_interactive) setLexemeOpen(p, 0, c) -# define CONTINUE_PAREN_INCR(X,p,n) \ - if(p && stdin_is_interactive) (trackParenLevel(p,n)) -# define CONTINUE_PROMPT_PSTATE(X) (&dynPrompt) -typedef struct DynaPrompt *t_DynaPromptRef; -# define SCAN_TRACKER_REFTYPE t_DynaPromptRef - -static struct DynaPrompt { - char dynamicPrompt[PROMPT_LEN_MAX]; - char acAwait[2]; - int inParenLevel; - char *zScannerAwaits; -} dynPrompt = { {0}, {0}, 0, 0 }; - -/* Record parenthesis nesting level change, or force level to 0. */ -static void trackParenLevel(struct DynaPrompt *p, int ni){ - p->inParenLevel += ni; - if( ni==0 ) p->inParenLevel = 0; - p->zScannerAwaits = 0; -} - -/* Record that a lexeme is opened, or closed with args==0. */ -static void setLexemeOpen(struct DynaPrompt *p, char *s, char c){ - if( s!=0 || c==0 ){ - p->zScannerAwaits = s; - p->acAwait[0] = 0; - }else{ - p->acAwait[0] = c; - p->zScannerAwaits = p->acAwait; - } -} - -/* Upon demand, derive the continuation prompt to display. */ -static char *dynamicContinuePrompt(void){ - int k; /* Number of context hint characters */ - int nSpace; /* Spaces at the start of continuePrompt */ - int nDot; /* Dots following spaces */ - int nOrig; /* Total size of continuePrompt in bytes */ - int nCore; /* nOrig + 1 - nSpace */ - - nOrig = (int)strlen(continuePrompt); - if( nOrig<=1 - || (dynPrompt.zScannerAwaits==0 && dynPrompt.inParenLevel == 0) - ){ - return continuePrompt; - } - for(nSpace=0; continuePrompt[nSpace]==' '; nSpace++){} - for(nDot=0; continuePrompt[nSpace+nDot]=='.'; nDot++){} - nCore = nOrig + 1 - nSpace; - for(k=0; knSpace && nDot ){ - nSpace++; - nDot--; - } - memcpy(&dynPrompt.dynamicPrompt[k], - &continuePrompt[nSpace], - nCore); - return dynPrompt.dynamicPrompt; -} -#endif /* !defined(SQLITE_OMIT_DYNAPROMPT) */ - /* Indicate out-of-memory and exit. */ static void shell_out_of_memory(void){ eputz("Error: out of memory\n"); @@ -1048,7 +952,7 @@ static char *one_input_line(ShellState *p, char *zPrior, int isContinuation){ if( in!=0 ){ zResult = local_getline(zPrior, in); }else{ - zPrompt = isContinuation ? CONTINUATION_PROMPT(p) : mainPrompt; + zPrompt = isContinuation ? continuePrompt : mainPrompt; #if SHELL_USE_LOCAL_GETLINE sputz(stdout, zPrompt); fflush(stdout); @@ -12076,112 +11980,28 @@ meta_command_exit: return rc; } -/* Line scan result and intermediate states (supporting scan resumption) -*/ -#ifndef CHAR_BIT -# define CHAR_BIT 8 -#endif -typedef enum { - QSS_HasDark = 1<zInFile */ i64 saved_lineno; /* Prior value of p->lineno */ @@ -12446,7 +12267,6 @@ static int process_input(ShellState *p, const char *zSrc){ p->zInFile = zSrc; saved_lineno = p->lineno; p->lineno = 0; - CONTINUE_PROMPT_RESET(p); while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){ fflush(p->out); zLine = one_input_line(p, zLine, nSql>0); @@ -12460,20 +12280,12 @@ static int process_input(ShellState *p, const char *zSrc){ seenInterrupt = 0; } p->lineno++; - if( QSS_INPLAIN(qss) - && line_is_command_terminator(p, zLine) - && line_is_complete(zSql, nSql) ){ - memcpy(zLine,";",2); - } - qss = quickscan(p, zLine, qss, CONTINUE_PROMPT_PSTATE(p)); - if( QSS_PLAINWHITE(qss) && nSql==0 ){ + if( nSql==0 && line_is_all_whitespace(zLine) ){ /* Just swallow single-line whitespace */ echo_group_input(p, zLine); - qss = QSS_Start; continue; } if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){ - CONTINUE_PROMPT_RESET(p); echo_group_input(p, zLine); if( zLine[0]=='.' ){ rc = do_meta_command(zLine, p); @@ -12483,10 +12295,12 @@ static int process_input(ShellState *p, const char *zSrc){ errCnt++; } } - qss = QSS_Start; continue; } - /* No single-line dispositions remain; accumulate line(s). */ + if( line_is_command_terminator(zLine) && line_is_complete(zSql, nSql) ){ + memcpy(zLine,";",2); + } + hasSemi = strchr(zLine,';')!=0; nLine = strlen(zLine); if( nSql+nLine+2>=nAlloc ){ /* Grow buffer by half-again increments when big. */ @@ -12514,10 +12328,10 @@ static int process_input(ShellState *p, const char *zSrc){ nSql = 0; errCnt++; break; - }else if( nSql && QSS_SEMITERM(qss) && sqlite3_complete(zSql) ){ + } + if( nSql && hasSemi && sqlite3_complete(zSql) ){ echo_group_input(p, zSql); errCnt += runOneSqlLine(p, zSql, p->zInFile, startline); - CONTINUE_PROMPT_RESET(p); nSql = 0; if( p->nPopOutput ){ output_reset(p); @@ -12530,18 +12344,15 @@ static int process_input(ShellState *p, const char *zSrc){ p->nPopMode = 0; } p->bSafeMode = p->bSafeModePersist; - qss = QSS_Start; - }else if( nSql && QSS_PLAINWHITE(qss) ){ + }else if( nSql && line_is_all_whitespace(zSql) ){ echo_group_input(p, zSql); nSql = 0; - qss = QSS_Start; } } if( nSql ){ /* This may be incomplete. Let the SQL parser deal with that. */ echo_group_input(p, zSql); errCnt += runOneSqlLine(p, zSql, p->zInFile, startline); - CONTINUE_PROMPT_RESET(p); } free(zSql); free(zLine); From 6a6ebb0d06ce50945d651c6d57a145166770fb14 Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 9 Apr 2026 22:14:58 +0000 Subject: [PATCH 04/19] Store the prompts as part of the ShellState object, not as global variables. FossilOrigin-Name: 39f6c5a8a7d91e03f89b13496e333b9500977a2cbcc0c27ba14dfb87dc81e678 --- manifest | 15 ++++++--------- manifest.uuid | 2 +- src/shell.c.in | 30 +++++++++++++----------------- 3 files changed, 20 insertions(+), 27 deletions(-) diff --git a/manifest b/manifest index f7524ecc9a..8ad58a623b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Strip\sout\sthe\slegacy\sdynamic\sprompt\sgeneration.\s\sIt\swill\sgo\sback\sin\sas\sI\nadd\sthe\suser-defined\sprompt\sescapes. -D 2026-04-09T20:21:25.880 +C Store\sthe\sprompts\sas\spart\sof\sthe\sShellState\sobject,\snot\sas\sglobal\svariables. +D 2026-04-09T22:14:58.383 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 d2d6accf85d516d39ffb5101e3209e22b062c014be0b7c467c12bc3d2e9a4f96 +F src/shell.c.in 41b2b8ed58a2b34ca1b3027ab73fa5f21fa5a359025ec4d803fff43e5053c85e F src/sqlite.h.in e2915e4a86d5e0783afb5cb72411df38d987c7f3c5aa2d5441b8e74d30b649d8 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479 F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca @@ -2197,11 +2197,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P e2c9d4c6b731ea9afbb9cb22f86a3db3670ca67968f15891dc46ae1fc9ba34dc -R 6a381ddbe79e14291b50a57316105ea7 -T *branch * cli-prompt-redo -T *sym-cli-prompt-redo * -T -sym-cli-prompt * +P ab08b7a8ef518f96a549a41fe8ff11776abe5e83153c5f8d5d58694ecc476389 +R 94a7119792f4c428d79e21c5509da5f9 U drh -Z 400a2e048f10888511ab99293cd1badd +Z 849f1289eaea61587540a79ea11d0c87 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index ea4743febf..e245a501de 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ab08b7a8ef518f96a549a41fe8ff11776abe5e83153c5f8d5d58694ecc476389 +39f6c5a8a7d91e03f89b13496e333b9500977a2cbcc0c27ba14dfb87dc81e678 diff --git a/src/shell.c.in b/src/shell.c.in index 705400a05d..fa2c9d829b 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -355,6 +355,10 @@ typedef struct Mode { #define MFLG_CRLF 0x02 /* Use CR/LF output line endings */ #define MFLG_HDR 0x04 /* .header used to change headers on/off */ +/* +** Size of the prompt strings +*/ +#define PROMPT_MAX 128 /* ** State information about the database connection is contained in an @@ -397,8 +401,6 @@ struct ShellState { char *zDestTable; /* Name of destination table when MODE_Insert */ char *zTempFile; /* Temporary file that might need deleting */ char *zErrPrefix; /* Alternative error message prefix */ - char zTestcase[30]; /* Name of current test case */ - char outfile[FILENAME_MAX]; /* Filename for *out */ sqlite3_stmt *pStmt; /* Current statement if any. */ FILE *pLog; /* Write log output here */ Mode mode; /* Current display mode */ @@ -438,6 +440,10 @@ struct ShellState { const char * zDefaultDbName; /* Default name for db file */ } wasm; #endif + char zTestcase[30]; /* Name of current test case */ + char outfile[FILENAME_MAX]; /* Filename for *out */ + char mainPrompt[PROMPT_MAX]; /* Main prompt */ + char contPrompt[PROMPT_MAX]; /* Continuation prompt */ }; #ifdef SQLITE_SHELL_FIDDLE @@ -674,16 +680,6 @@ static volatile int seenInterrupt = 0; */ static char *Argv0; -/* -** Prompt strings. Initialized in main. Settable with -** .prompt main continue -*/ -#define PROMPT_LEN_MAX 128 -/* First line prompt. default: "sqlite> " */ -static char mainPrompt[PROMPT_LEN_MAX]; -/* Continuation prompt. default: " ...> " */ -static char continuePrompt[PROMPT_LEN_MAX]; - /* ** Write I/O traces to the following stream. */ @@ -952,7 +948,7 @@ static char *one_input_line(ShellState *p, char *zPrior, int isContinuation){ if( in!=0 ){ zResult = local_getline(zPrior, in); }else{ - zPrompt = isContinuation ? continuePrompt : mainPrompt; + zPrompt = isContinuation ? p->contPrompt : p->mainPrompt; #if SHELL_USE_LOCAL_GETLINE sputz(stdout, zPrompt); fflush(stdout); @@ -10343,10 +10339,10 @@ static int do_meta_command(const char *zLine, ShellState *p){ if( c=='p' && cli_strncmp(azArg[0], "prompt", n)==0 ){ if( nArg >= 2) { - shell_strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1); + shell_strncpy(p->mainPrompt,azArg[1],sizeof(p->mainPrompt)-1); } if( nArg >= 3) { - shell_strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1); + shell_strncpy(p->contPrompt,azArg[2],sizeof(p->contPrompt)-1); } }else @@ -12640,8 +12636,8 @@ static void main_init(ShellState *p) { #endif sqlite3_config(SQLITE_CONFIG_URI, 1); sqlite3_config(SQLITE_CONFIG_MULTITHREAD); - sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> "); - sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> "); + sqlite3_snprintf(sizeof(p->mainPrompt), p->mainPrompt,"sqlite> "); + sqlite3_snprintf(sizeof(p->contPrompt), p->contPrompt," ...> "); } /* From 850104bbad3627b868b2588de0d7a99a4ee6c487 Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 9 Apr 2026 23:37:48 +0000 Subject: [PATCH 05/19] A prototype of code that shows how to expand backslash escapes in the CLI prompt. FossilOrigin-Name: 9cf28959671920b4909521bb1db6f0cbbc85448fbf3594c43b4000505b4e055b --- manifest | 12 +++--- manifest.uuid | 2 +- src/shell.c.in | 105 +++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 105 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index 8ad58a623b..997b4f4cf1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Store\sthe\sprompts\sas\spart\sof\sthe\sShellState\sobject,\snot\sas\sglobal\svariables. -D 2026-04-09T22:14:58.383 +C A\sprototype\sof\scode\sthat\sshows\show\sto\sexpand\sbackslash\sescapes\sin\sthe\nCLI\sprompt. +D 2026-04-09T23:37:48.087 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 41b2b8ed58a2b34ca1b3027ab73fa5f21fa5a359025ec4d803fff43e5053c85e +F src/shell.c.in 35f99690f368ef171713cbccd89efef382944e4b85396bdb78e6995636e278b3 F src/sqlite.h.in e2915e4a86d5e0783afb5cb72411df38d987c7f3c5aa2d5441b8e74d30b649d8 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479 F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca @@ -2197,8 +2197,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P ab08b7a8ef518f96a549a41fe8ff11776abe5e83153c5f8d5d58694ecc476389 -R 94a7119792f4c428d79e21c5509da5f9 +P 39f6c5a8a7d91e03f89b13496e333b9500977a2cbcc0c27ba14dfb87dc81e678 +R d2a4bc02232fb4db2f52e0b9d98461ba U drh -Z 849f1289eaea61587540a79ea11d0c87 +Z f5b6fe9da177b5e89ebf6c4cb7c9f5ea # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index e245a501de..3544fb98a0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -39f6c5a8a7d91e03f89b13496e333b9500977a2cbcc0c27ba14dfb87dc81e678 +9cf28959671920b4909521bb1db6f0cbbc85448fbf3594c43b4000505b4e055b diff --git a/src/shell.c.in b/src/shell.c.in index fa2c9d829b..88956da841 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -926,12 +926,101 @@ static char *local_getline(char *zLine, FILE *in){ return zLine; } +/* +** 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. +*/ +static char *expand_prompt( + ShellState *p, /* The current shell state */ + const char *zPrior, /* Prior input lines not yet processed */ + const char *zPrompt /* Prompt string to be expanded */ +){ + sqlite3_str *pOut = sqlite3_str_new(0); + int i; + char c; + for(i=0; zPrompt[i]; i++){ + if( zPrompt[i]!='\\' ) continue; + if( i>0 ){ + sqlite3_str_append(pOut, zPrompt, i); + zPrompt += i; + i = 0; + } + /* 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 */ + break; + } + if( c=='\\' ){ + /* \\ maps into a single \ */ + zPrompt++; + continue; + } + if( c>='0' && c<='7' ){ + /* \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'; + } + sqlite3_str_appendchar(pOut, 1, v); + zPrompt += i+1; + i = -1; + continue; + } + if( c=='x' ){ + /* \x becomes "*" if in a transaction and nothing if not */ + if( p->db && !sqlite3_get_autocommit(p->db) ){ + sqlite3_str_append(pOut, "*", 1); + } + zPrompt += 2; + i = -1; + continue; + } + 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 */ + sqlite3_filename pFN = p->db ? sqlite3_db_filename(p->db,0) : 0; + const char *zFN; + if( pFN && (zFN = sqlite3_filename_database(pFN))!=0 ){ + if( c=='f' ){ + const char *zTail = strrchr(zFN,'/'); + if( zTail && zTail[1] ) zFN = &zTail[1]; + }else if( c=='~' ){ + const char *zHOME = getenv("HOME"); + size_t nHOME = zHOME ? strlen(zHOME) : 0; + if( nHOME0 ){ + sqlite3_str_append(pOut, zPrompt, i); + } + return sqlite3_str_finish(pOut); +} + /* ** Retrieve a single line of input text. ** ** If in==0 then read from standard input and prompt before each line. -** If isContinuation is true, then a continuation prompt is appropriate. -** If isContinuation is zero, then the main prompt should be used. +** If bContinue is true, then a continuation prompt is appropriate. +** If bContinue is zero, then the main prompt should be used. ** ** If zPrior is not NULL then it is a buffer from a prior call to this ** routine that can be reused. @@ -941,14 +1030,15 @@ static char *local_getline(char *zLine, FILE *in){ ** zPrior argument for reuse. */ #ifndef SQLITE_SHELL_FIDDLE -static char *one_input_line(ShellState *p, char *zPrior, int isContinuation){ - char *zPrompt; +static char *one_input_line(ShellState *p, char *zPrior, int bContinue){ char *zResult; FILE *in = p->in; if( in!=0 ){ zResult = local_getline(zPrior, in); }else{ - zPrompt = isContinuation ? p->contPrompt : p->mainPrompt; + const char *zBase = bContinue ? p->contPrompt : p->mainPrompt; + char *zPrompt = expand_prompt(p, zPrior, zBase); + shell_check_oom(zPrompt); #if SHELL_USE_LOCAL_GETLINE sputz(stdout, zPrompt); fflush(stdout); @@ -969,6 +1059,7 @@ static char *one_input_line(ShellState *p, char *zPrior, int isContinuation){ } if( zResult && *zResult ) shell_add_history(zResult); #endif + sqlite3_free(zPrompt); } return zResult; } @@ -12202,7 +12293,7 @@ static void echo_group_input(ShellState *p, const char *zDo){ ** impl because we need the global shellState and cannot access it from that ** function without moving lots of code around (creating a larger/messier diff). */ -static char *one_input_line(ShellState *p, char *zPrior, int isContinuation){ +static char *one_input_line(ShellState *p, char *zPrior, int bContinue){ /* Parse the next line from shellState.wasm.zInput. */ const char *zBegin = shellState.wasm.zPos; const char *z = zBegin; @@ -12211,7 +12302,7 @@ static char *one_input_line(ShellState *p, char *zPrior, int isContinuation){ FILE *in = p->in; UNUSED_PARAMETER(in); - UNUSED_PARAMETER(isContinuation); + UNUSED_PARAMETER(bContinue); if(!z || !*z){ return 0; } From b37bf0b8b471e6d0c203fbec078eac829c1f89a8 Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 10 Apr 2026 00:55:40 +0000 Subject: [PATCH 06/19] Improvements to the way \x works so that it can be used to change the prompt color. This really messes with linenoise, though. FossilOrigin-Name: bbee56f970ade40734c8a278f46d8a268b305fe349c3739c977fa9141d2c3b6a --- manifest | 12 ++++---- manifest.uuid | 2 +- src/shell.c.in | 80 ++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 65 insertions(+), 29 deletions(-) diff --git a/manifest b/manifest index 997b4f4cf1..a9c024d830 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C A\sprototype\sof\scode\sthat\sshows\show\sto\sexpand\sbackslash\sescapes\sin\sthe\nCLI\sprompt. -D 2026-04-09T23:37:48.087 +C Improvements\sto\sthe\sway\s\x\sworks\sso\sthat\sit\scan\sbe\sused\sto\schange\nthe\sprompt\scolor.\s\sThis\sreally\smesses\swith\slinenoise,\sthough. +D 2026-04-10T00:55:40.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 35f99690f368ef171713cbccd89efef382944e4b85396bdb78e6995636e278b3 +F src/shell.c.in 2bbbb04153354fe3d11677d69ce7b6d5bfe8113e2d3693791915590eaa4f1bce F src/sqlite.h.in e2915e4a86d5e0783afb5cb72411df38d987c7f3c5aa2d5441b8e74d30b649d8 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479 F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca @@ -2197,8 +2197,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P 39f6c5a8a7d91e03f89b13496e333b9500977a2cbcc0c27ba14dfb87dc81e678 -R d2a4bc02232fb4db2f52e0b9d98461ba +P 9cf28959671920b4909521bb1db6f0cbbc85448fbf3594c43b4000505b4e055b +R 1af695b623ae09a49f6867ddfb6fa639 U drh -Z f5b6fe9da177b5e89ebf6c4cb7c9f5ea +Z 856f286521a626031b862b8cbac557c5 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 3544fb98a0..e75a3aba4b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9cf28959671920b4909521bb1db6f0cbbc85448fbf3594c43b4000505b4e055b +bbee56f970ade40734c8a278f46d8a268b305fe349c3739c977fa9141d2c3b6a diff --git a/src/shell.c.in b/src/shell.c.in index 88956da841..86eb9bd620 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -939,10 +939,11 @@ static char *expand_prompt( sqlite3_str *pOut = sqlite3_str_new(0); int i; char c; + int onoff = 1; for(i=0; zPrompt[i]; i++){ if( zPrompt[i]!='\\' ) continue; if( i>0 ){ - sqlite3_str_append(pOut, zPrompt, i); + if( onoff ) sqlite3_str_append(pOut, zPrompt, i); zPrompt += i; i = 0; } @@ -965,39 +966,74 @@ static char *expand_prompt( while( i<=2 && zPrompt[i+1]>='0' && zPrompt[i+1]<='7' ){ v = v*8 + zPrompt[++i] - '0'; } - sqlite3_str_appendchar(pOut, 1, v); + if( onoff ) sqlite3_str_appendchar(pOut, 1, v); zPrompt += i+1; i = -1; continue; } - if( c=='x' ){ - /* \x becomes "*" if in a transaction and nothing if not */ - if( p->db && !sqlite3_get_autocommit(p->db) ){ - sqlite3_str_append(pOut, "*", 1); - } + if( c=='e' ){ + /* \e is \033 "Escape" */ + if( onoff ) sqlite3_str_append(pOut, "\033", 1); zPrompt += 2; i = -1; continue; } + + /* The intent of the following codes it to provide alternative + ** text displays depending on whether or not the connection is + ** currently in a transaction. Example 1: Show a "*" before the ">" + ** like psql: + ** + ** .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 ' + */ + if( c==':' ){ + /* toggle display on/off */ + onoff = !onoff; + zPrompt += 2; + i = -1; + continue; + } + if( c==';' ){ + /* Turn display on */ + onoff = 1; + zPrompt += 2; + i = -1; + continue; + } + if( c=='x' ){ + /* \x turns display off not in a transaction, on if in txn */ + onoff = p->db && !sqlite3_get_autocommit(p->db); + zPrompt += 2; + i = -1; + continue; + } + 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 */ - sqlite3_filename pFN = p->db ? sqlite3_db_filename(p->db,0) : 0; - const char *zFN; - if( pFN && (zFN = sqlite3_filename_database(pFN))!=0 ){ - if( c=='f' ){ - const char *zTail = strrchr(zFN,'/'); - if( zTail && zTail[1] ) zFN = &zTail[1]; - }else if( c=='~' ){ - const char *zHOME = getenv("HOME"); - size_t nHOME = zHOME ? strlen(zHOME) : 0; - if( nHOMEdb ? sqlite3_db_filename(p->db,0) : 0; + const char *zFN = pFN ? sqlite3_filename_database(pFN) : ":memory:"; + if( zFN ){ + if( c=='f' ){ + const char *zTail = strrchr(zFN,'/'); + if( zTail && zTail[1] ) zFN = &zTail[1]; + }else if( c=='~' ){ + const char *zHOME = getenv("HOME"); + size_t nHOME = zHOME ? strlen(zHOME) : 0; + if( nHOME0 ){ + if( i>0 && onoff ){ sqlite3_str_append(pOut, zPrompt, i); } return sqlite3_str_finish(pOut); From 693b15ac83ae826e146cded2fbd3ca6a38f1d841 Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 10 Apr 2026 13:43:48 +0000 Subject: [PATCH 07/19] Prototype sqlite3_incomplete() - a variant of sqlite3_complete() that returns additional information about what is needed to complete the statement. FossilOrigin-Name: a698fbfb8bb256ee0d9802c01562c11492ca2800a45360b268ac6cf397a7fad7 --- manifest | 14 +++---- manifest.uuid | 2 +- src/complete.c | 101 +++++++++++++++++++++++++++++++++++++++++++----- src/sqlite.h.in | 28 ++++++++++---- 4 files changed, 119 insertions(+), 26 deletions(-) diff --git a/manifest b/manifest index a9c024d830..1af3a09a0f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improvements\sto\sthe\sway\s\x\sworks\sso\sthat\sit\scan\sbe\sused\sto\schange\nthe\sprompt\scolor.\s\sThis\sreally\smesses\swith\slinenoise,\sthough. -D 2026-04-10T00:55:40.521 +C Prototype\ssqlite3_incomplete()\s-\sa\svariant\sof\ssqlite3_complete()\sthat\sreturns\nadditional\sinformation\sabout\swhat\sis\sneeded\sto\scomplete\sthe\sstatement. +D 2026-04-10T13:43:48.738 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -680,7 +680,7 @@ F src/btreeInt.h 9c0f9ea5c9b5f4dcaea18111d43efe95f2ac276cd86d770dce10fd99ccc9388 F src/build.c 8581de0af3b6c448f5d64e2d18a91ac1e7057b3bcb8b8827e1240f80d87486a4 F src/callback.c 3605bbf02bd7ed46c79cd48346db4a32fc51d67624400539c0532f4eead804ad F src/carray.c 3efe3982d5fb323334c29328a4e189ccaef6b95612a6084ad5fa124fd5db1179 -F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e +F src/complete.c 9304071c5f2ddd040cd786ec5d157c6a5592561674816e4a9e74164a0ba40647 F src/date.c 61e92f1f7e2e88e1cd91e91dc69eb2b2854e7877254470f9fabd776bfac922b8 F src/dbpage.c c9ea81c11727f27e02874611e92773e68e2a90a875ef2404b084564c235fd91f F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c @@ -736,7 +736,7 @@ F src/resolve.c 928ff887f2a7c64275182060d94d06fdddbe32226c569781cf7e7edc6f58d7fd F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97 F src/select.c ffe199f025a0dd74670d2a77232bdea364a4d7b36f32c64a6572d39ba6a11576 F src/shell.c.in 2bbbb04153354fe3d11677d69ce7b6d5bfe8113e2d3693791915590eaa4f1bce -F src/sqlite.h.in e2915e4a86d5e0783afb5cb72411df38d987c7f3c5aa2d5441b8e74d30b649d8 +F src/sqlite.h.in a5605faa9479bbaac16c4ab43eb09ff50632004a8e05084d3fde56063ef73766 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479 F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca F src/sqliteInt.h bc1cbc0c23dba35b324ae85a7dbb5fb182321bbd30857fb21f3d0cba049001a5 @@ -2197,8 +2197,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P 9cf28959671920b4909521bb1db6f0cbbc85448fbf3594c43b4000505b4e055b -R 1af695b623ae09a49f6867ddfb6fa639 +P bbee56f970ade40734c8a278f46d8a268b305fe349c3739c977fa9141d2c3b6a +R 12cd07af606e611ea7f41e67ab10d130 U drh -Z 856f286521a626031b862b8cbac557c5 +Z 547b407658ddec4e488d7004be7d0be4 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index e75a3aba4b..4c993035c5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bbee56f970ade40734c8a278f46d8a268b305fe349c3739c977fa9141d2c3b6a +a698fbfb8bb256ee0d9802c01562c11492ca2800a45360b268ac6cf397a7fad7 diff --git a/src/complete.c b/src/complete.c index bb2c03098e..08496366a8 100644 --- a/src/complete.c +++ b/src/complete.c @@ -49,12 +49,51 @@ extern const char sqlite3IsEbcdicIdChar[]; #endif /* -** Return TRUE if the given SQL string ends in a semicolon. +** Return zero if the given SQL string is complete - if all comments, +** string and blob literals, and quoted identifiers have been closed and +** if the entire string ends with ";" and possible with ";END;" if the +** string is a CREATE TRIGGER statement. A non-zero return indicates +** that the string is incomplete. Bits of the return value indicate +** what is missing and is needed to close out the statement. ** ** Special handling is require for CREATE TRIGGER statements. ** Whenever the CREATE TRIGGER keywords are seen, the statement ** must end with ";END;". ** +** Let the return code be a value R. R is split up into various +** subfields, at byte boundaries: +** +** R = 0xwwwwwwww00xxyyzz +** +** In other words, zz is the least significant byte, yy is the next +** most significant byte, xx is the third byte, wwwwwwww is a 32-bit +** value from the middle. +** +** zz == SQLITE_OK Input is complete +** zz == SQLITE_ERROR Input is incomplete +** zz == SQLITE_MISUSE Input is a NULL pointer +** zz != 0 New values for zz may be added in the future +** +** yy == 0x01 Need a semicolon at the end +** yy == 0x02 Need "END" and a semicolon +** yy == 0x03 Need semicolon, "END", and semicolon +** yy != 0 New values for yy may be added in the future +** +** xx == '\'' Incomplete string or blob literal +** xx == '"' Incomplete quoted identifier +** xx == '`' Incompelte MySQL-style quoted identifier +** xx == ']' Incomplete SQLServer-style quoted identifer +** xx == '-' Incomplete SQL-style comment +** xx == '/' Incomplete C-style comment +** xx != 0 New values of xx may be added in the future +** +** wwwwwwww Interpret as a signed integer, the number +** of unmatched "(". Negative means there are +** more ")" and "(". +** +** ((R>>24)&0xff)!=0 New uses for the 4th byte may be added +** in the future +** ** This implementation uses a state machine with 8 states: ** ** (0) INVALID We have not yet seen a non-whitespace character. @@ -101,9 +140,11 @@ extern const char sqlite3IsEbcdicIdChar[]; ** to recognize the end of a trigger can be omitted. All we have to do ** is look for a semicolon that is not part of an string or comment. */ -int sqlite3_complete(const char *zSql){ +sqlite3_int64 sqlite3_incomplete(const char *zSql){ u8 state = 0; /* Current state, using numbers defined in header comment */ u8 token; /* Value of the next token */ + u8 pending = 0; /* unmatched structure character */ + int nParen = 0; /* Nested parentheses */ #ifndef SQLITE_OMIT_TRIGGER /* A complex statement machine used to detect the end of a CREATE TRIGGER @@ -133,11 +174,21 @@ int sqlite3_complete(const char *zSql){ /* 2 NORMAL: */ { 1, 2, 2, }, }; #endif /* SQLITE_OMIT_TRIGGER */ + /* Mapping state number to yy value for the return */ + static const u8 statemap[8] = { + /* 0 INVALID */ 1, + /* 1 START */ 0, + /* 2 NORMAL */ 1, + /* 3 EXPLAIN */ 1, + /* 4 CREATE */ 1, + /* 5 TRIGGER */ 3, + /* 6 SEMI */ 2, + /* 7 END */ 1, + }; #ifdef SQLITE_ENABLE_API_ARMOR if( zSql==0 ){ - (void)SQLITE_MISUSE_BKPT; - return 0; + return SQLITE_MISUSE_BKPT; } #endif @@ -162,7 +213,10 @@ int sqlite3_complete(const char *zSql){ } zSql += 2; while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; } - if( zSql[0]==0 ) return 0; + if( zSql[0]==0 ){ + pending = '/'; + goto incomplete_finish; + } zSql++; token = tkWS; break; @@ -173,14 +227,20 @@ int sqlite3_complete(const char *zSql){ break; } while( *zSql && *zSql!='\n' ){ zSql++; } - if( *zSql==0 ) return state==1; + if( *zSql==0 ){ + if( state!=1 ) pending = '-'; + goto incomplete_finish; + } token = tkWS; break; } case '[': { /* Microsoft-style identifiers in [...] */ zSql++; while( *zSql && *zSql!=']' ){ zSql++; } - if( *zSql==0 ) return 0; + if( *zSql==0 ){ + pending = ']'; + goto incomplete_finish; + } token = tkOTHER; break; } @@ -190,7 +250,20 @@ int sqlite3_complete(const char *zSql){ int c = *zSql; zSql++; while( *zSql && *zSql!=c ){ zSql++; } - if( *zSql==0 ) return 0; + if( *zSql==0 ){ + pending = c; + goto incomplete_finish; + } + token = tkOTHER; + break; + } + case '(': { + nParen++; + token = tkOTHER; + break; + } + case ')': { + nParen--; token = tkOTHER; break; } @@ -257,7 +330,15 @@ int sqlite3_complete(const char *zSql){ state = trans[state][token]; zSql++; } - return state==1; +incomplete_finish: + if( state==1 ) nParen = 0; + return (((i64)nParen)<<32) | + ((i64)pending<<16) | + ((i64)statemap[state]<<8) | + (state!=1); +} +int sqlite3_complete(const char *zSql){ + return sqlite3_incomplete(zSql)==0; } #ifndef SQLITE_OMIT_UTF16 @@ -279,7 +360,7 @@ int sqlite3_complete16(const void *zSql){ sqlite3ValueSetStr(pVal, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC); zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8); if( zSql8 ){ - rc = sqlite3_complete(zSql8); + rc = sqlite3_incomplete(zSql8)==0; }else{ rc = SQLITE_NOMEM_BKPT; } diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 9323ce5eea..b4ed739a61 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -2960,8 +2960,9 @@ int sqlite3_is_interrupted(sqlite3*); ** These routines are useful during command-line input to determine if the ** currently entered text seems to form a complete SQL statement or ** if additional input is needed before sending the text into -** SQLite for parsing. ^These routines return 1 if the input string -** appears to be a complete SQL statement. ^A statement is judged to be +** SQLite for parsing. ^The sqlite3_complete(X) and sqlite3_complete16(X) +** routines return 1 if the input string X appears to be a complete SQL +** statement. ^A statement is judged to be ** complete if it ends with a semicolon token and is not a prefix of a ** well-formed CREATE TRIGGER statement. ^Semicolons that are embedded within ** string literals or quoted identifier names or comments are not @@ -2969,11 +2970,21 @@ int sqlite3_is_interrupted(sqlite3*); ** embedded) and thus do not count as a statement terminator. ^Whitespace ** and comments that follow the final semicolon are ignored. ** -** ^These routines return 0 if the statement is incomplete. ^If a -** memory allocation fails, then SQLITE_NOMEM is returned. +** ^The sqlite3_complete(X) and sqlite3_complete16(X) routines return 0 +** if the statement is incomplete. ^If a memory allocation fails, then +** SQLITE_NOMEM is returned. ** -** ^These routines do not parse the SQL statements and thus -** will not detect syntactically incorrect SQL. +** The [sqlite3_incomplete(X)] routine is similar to [sqlite3_complete(X)] +** except that sqlite3_incomplete(X) returns 0 if the input X is complete +** and non-zero if X is incomplete. The non-zero return from +** sqlite3_incomplete(X) contains additional information about what is +** needed to complete the input X. The sqlite3_incomplete(X) interface +** is only available for UTF-8 text. +** +** ^None of these routines do a full parse the SQL statements and thus +** will not detect syntactically incorrect SQL. They only determine if +** input text has properly terminated comments, string literals, and +** quoted identifiers, and if the statement ends with a semicolon. ** ** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior ** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked @@ -2981,14 +2992,15 @@ int sqlite3_is_interrupted(sqlite3*); ** then the return value from sqlite3_complete16() will be non-zero ** regardless of whether or not the input SQL is complete.)^ ** -** The input to [sqlite3_complete()] must be a zero-terminated -** UTF-8 string. +** The X input to [sqlite3_complete(X)] and [sqlite3_incomplete(X) +** must be a zero-terminated UTF-8 string. ** ** The input to [sqlite3_complete16()] must be a zero-terminated ** UTF-16 string in native byte order. */ int sqlite3_complete(const char *sql); int sqlite3_complete16(const void *sql); +sqlite3_int64 sqlite3_incomplete(const char *sql); /* ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors From 7632922625ed0edc3515193e2286e2fd10616954 Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 10 Apr 2026 19:33:15 +0000 Subject: [PATCH 08/19] The \H escape on a prompt string fills in with the characters needed to make the input "complete". Add the shell_expand_prompt() SQL function for testing purposes. FossilOrigin-Name: 6aafb76c74b73aafef74250dae9c8cbe73226c0efb606e8f80ea761b3293cf9d --- manifest | 12 +++++------ manifest.uuid | 2 +- src/shell.c.in | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index b46c2bb893..e1b85d02e7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\strunk\sfixes\sand\senhancements\sinto\sthe\scli-prompt-redo\sbranch -D 2026-04-10T18:53:13.643 +C The\s\H\sescape\son\sa\sprompt\sstring\sfills\sin\swith\sthe\scharacters\sneeded\nto\smake\sthe\sinput\s"complete".\s\sAdd\sthe\sshell_expand_prompt()\sSQL\sfunction\nfor\stesting\spurposes. +D 2026-04-10T19:33:15.316 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 e4093ccf2a9189ec34db7a34f011c6ecb9ec3721981526eb214bdf08ac2a590e +F src/shell.c.in d94e528d5a6ad833228197794d9d6473d51902cc91a37baef0984574650e3896 F src/sqlite.h.in a5605faa9479bbaac16c4ab43eb09ff50632004a8e05084d3fde56063ef73766 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479 F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca @@ -2197,8 +2197,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P a698fbfb8bb256ee0d9802c01562c11492ca2800a45360b268ac6cf397a7fad7 6ab6f622be3e1ad93166d139b5fccf9628c86d1c14c6dfb4464cb8cf52c94785 -R 4d2bbb27b149398ceae03cca09977cdc +P f3354ebf51e684ef680986bef9b606f63786c254f1c8774bcaf7a7f3d0d37056 +R eb9717568ba2a51cead72c45c6debdf8 U drh -Z 0e5a6f70160f3c705711d8f141e5cb21 +Z 98b23073eb30db46d4e741688a728681 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 8ccff5afc7..8b5506f102 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f3354ebf51e684ef680986bef9b606f63786c254f1c8774bcaf7a7f3d0d37056 +6aafb76c74b73aafef74250dae9c8cbe73226c0efb606e8f80ea761b3293cf9d diff --git a/src/shell.c.in b/src/shell.c.in index 1b5db0768d..7c3f75b1c3 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -1040,6 +1040,38 @@ static char *expand_prompt( continue; } + if( c=='H' ){ + /* \H becomes text needed to terminate current input */ + if( onoff ){ + sqlite3_int64 R = zPrior ? sqlite3_incomplete(zPrior) : 0; + int c = (R>>16)&0xff; + int nParen = R>>32; + int eSemi = (R>>8)&0xff; + if( c==0 ){ + /* no-op */ + }else if( c=='-' ){ + sqlite3_str_append(pOut,"\\n",3); + }else if( c=='/' ){ + sqlite3_str_append(pOut,"*/",2); + }else{ + sqlite3_str_appendchar(pOut, 1, c); + } + if( nParen>0 ){ + sqlite3_str_appendf(pOut, "%.*c",nParen,')'); + } + if( eSemi==1 ){ + sqlite3_str_append(pOut, ";", 1); + }else if( eSemi==2 ){ + sqlite3_str_append(pOut, "END;", 4); + }else if( eSemi==3 ){ + sqlite3_str_append(pOut, ";END;", 5); + } + } + zPrompt += 2; + i = -1; + continue; + } + /* No match to a known escape. Generate an error. */ if( onoff ) sqlite3_str_appendf(pOut,"UNKNOWN(\"\\%c\")",c); zPrompt += 2; @@ -1416,6 +1448,23 @@ static void shellAddSchemaName( sqlite3_result_value(pCtx, apVal[0]); } +/* +** SQL function: shell_expand_prompt(PROMPT,PRIOR) +** +** Invoke the internal expand_prompt() function, for testing purposes. +*/ +static void shellExpandPrompt( + sqlite3_context *pCtx, + int nVal, + sqlite3_value **apVal +){ + const char *zPrompt = (const char*)sqlite3_value_text(apVal[0]); + const char *zPrior = nVal>=2 ? (const char*)sqlite3_value_text(apVal[1]) : 0; + ShellState *p = (ShellState*)sqlite3_user_data(pCtx); + char *zRes = expand_prompt(p, zPrior, zPrompt); + sqlite3_result_text(pCtx, zRes, -1, SQLITE_TRANSIENT); + sqlite3_free(zRes); +} /************************* BEGIN PERFORMANCE TIMER *****************************/ #if !defined(_WIN32) && !defined(WIN32) && !defined(__minux) @@ -4638,6 +4687,11 @@ static void open_db(ShellState *p, int openFlags){ sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0, editFunc, 0, 0); #endif + sqlite3_create_function(p->db, "shell_expand_prompt", 1, SQLITE_UTF8, + p, shellExpandPrompt, 0, 0); + sqlite3_create_function(p->db, "shell_expand_prompt", 2, SQLITE_UTF8, + p, shellExpandPrompt, 0, 0); + if( p->openMode==SHELL_OPEN_ZIPFILE ){ char *zSql = sqlite3_mprintf( From bd574dbaee4c477714c864687072cf8e61516b1e Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 10 Apr 2026 20:06:34 +0000 Subject: [PATCH 09/19] Add the \B escape for CLI prompts. Change the default prompts to use \f, \H, and \B. FossilOrigin-Name: 354325b6f396bda38bbb82e7d38aa50d3d6441e1ebb9b578aed8e0bcf62f9911 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c.in | 35 +++++++++++++++++++++++++++++++++-- 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index e1b85d02e7..552e3e4a41 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\s\H\sescape\son\sa\sprompt\sstring\sfills\sin\swith\sthe\scharacters\sneeded\nto\smake\sthe\sinput\s"complete".\s\sAdd\sthe\sshell_expand_prompt()\sSQL\sfunction\nfor\stesting\spurposes. -D 2026-04-10T19:33:15.316 +C Add\sthe\s\B\sescape\sfor\sCLI\sprompts.\s\sChange\sthe\sdefault\sprompts\sto\nuse\s\f,\s\H,\sand\s\B. +D 2026-04-10T20:06:34.810 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 d94e528d5a6ad833228197794d9d6473d51902cc91a37baef0984574650e3896 +F src/shell.c.in ccadf849cfa03871c93f2869e27af177408ad028a4897626a1550d3fdbdcca18 F src/sqlite.h.in a5605faa9479bbaac16c4ab43eb09ff50632004a8e05084d3fde56063ef73766 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479 F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca @@ -2197,8 +2197,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P f3354ebf51e684ef680986bef9b606f63786c254f1c8774bcaf7a7f3d0d37056 -R eb9717568ba2a51cead72c45c6debdf8 +P 6aafb76c74b73aafef74250dae9c8cbe73226c0efb606e8f80ea761b3293cf9d +R 10023fb5872b0939880b2eb9aec2ef11 U drh -Z 98b23073eb30db46d4e741688a728681 +Z c3b3ebd71cd1378ad565509dcb2c7b21 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 8b5506f102..2c3268c216 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6aafb76c74b73aafef74250dae9c8cbe73226c0efb606e8f80ea761b3293cf9d +354325b6f396bda38bbb82e7d38aa50d3d6441e1ebb9b578aed8e0bcf62f9911 diff --git a/src/shell.c.in b/src/shell.c.in index 7c3f75b1c3..5170c2dde0 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -940,6 +940,7 @@ static char *expand_prompt( int i; char c; int onoff = 1; + int idxSpace = -1; for(i=0; zPrompt[i]; i++){ if( zPrompt[i]!='\\' ) continue; if( i>0 ){ @@ -1072,6 +1073,16 @@ static char *expand_prompt( continue; } + if( c=='B' ){ + /* \B is a no-op for the main prmopt. 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; + i = -1; + continue; + } + /* No match to a known escape. Generate an error. */ if( onoff ) sqlite3_str_appendf(pOut,"UNKNOWN(\"\\%c\")",c); zPrompt += 2; @@ -1080,6 +1091,26 @@ static char *expand_prompt( if( i>0 && onoff ){ sqlite3_str_append(pOut, zPrompt, i); } + + /* 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, p->mainPrompt); + int nOther = strlen30(zOther); + sqlite3_free(zOther); + if( nOther>sqlite3_str_length(pOut) ){ + char *z; + int nNew = nOther - sqlite3_str_length(pOut); + int len; + sqlite3_str_appendchar(pOut, nNew, ' '); + len = sqlite3_str_length(pOut); + if( len>idxSpace ){ + z = sqlite3_str_value(pOut); + memmove(z+idxSpace+nNew, z+idxSpace, len-nNew-idxSpace); + memset(z+idxSpace, ' ', nNew); + } + } + } + return sqlite3_str_finish(pOut); } @@ -12817,8 +12848,8 @@ static void main_init(ShellState *p) { #endif sqlite3_config(SQLITE_CONFIG_URI, 1); sqlite3_config(SQLITE_CONFIG_MULTITHREAD); - sqlite3_snprintf(sizeof(p->mainPrompt), p->mainPrompt,"sqlite> "); - sqlite3_snprintf(sizeof(p->contPrompt), p->contPrompt," ...> "); + sqlite3_snprintf(sizeof(p->mainPrompt), p->mainPrompt,"SQLite:\\f> "); + sqlite3_snprintf(sizeof(p->contPrompt), p->contPrompt,"\\B...\\H> "); } /* From 70868a5ae3c55d60d556f62b0eb5fb7c84fddab0 Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 10 Apr 2026 20:29:35 +0000 Subject: [PATCH 10/19] Fix prompt for in-memory databases. Fix the continuation mechanism so that it looks at all accumulated lines, not just the most recent line. FossilOrigin-Name: 166894725569cafa96c434aa14db0428db6791a8296fcc2990bec4ec819fd876 --- manifest | 13 ++++++------- manifest.uuid | 2 +- src/shell.c.in | 23 +++++++++++++++++------ 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index 02d304d612..7f18f4eedc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Replace\sthe\sformer\sdynamic-continuation\sprompt\slogic\swith\sbackslash-escape\nprompt\sexpansion,\sinclude\ssome\sexpansions\sthat\sserve\sthe\ssame\srole\sas\sthe\nold\sdynamic-continuation\sprompts.\s\sThis\sallows\sgreater\suser\nconfigurability. -D 2026-04-10T20:14:16.225 +C Fix\sprompt\sfor\sin-memory\sdatabases.\s\sFix\sthe\scontinuation\smechanism\sso\sthat\nit\slooks\sat\sall\saccumulated\slines,\snot\sjust\sthe\smost\srecent\sline. +D 2026-04-10T20:29:35.946 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 ccadf849cfa03871c93f2869e27af177408ad028a4897626a1550d3fdbdcca18 +F src/shell.c.in 335a0c427f7de16a574c40683e79f9d5e7efcd2764168b00f7bdf76dfa349818 F src/sqlite.h.in a5605faa9479bbaac16c4ab43eb09ff50632004a8e05084d3fde56063ef73766 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479 F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca @@ -2197,9 +2197,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P e2c9d4c6b731ea9afbb9cb22f86a3db3670ca67968f15891dc46ae1fc9ba34dc 354325b6f396bda38bbb82e7d38aa50d3d6441e1ebb9b578aed8e0bcf62f9911 -R 10023fb5872b0939880b2eb9aec2ef11 -T +closed 354325b6f396bda38bbb82e7d38aa50d3d6441e1ebb9b578aed8e0bcf62f9911 +P 052631202e4dd930d93434b7003e73b23557934421ace5d2f382f041638d5518 +R db2a870af126f19369636d4e3aa1216f U drh -Z 0caf1772228f87bb1b8b817e19db97e9 +Z af6eb6bd5da5f6fa8530eefe13136eb2 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 80d801332e..538f1770ec 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -052631202e4dd930d93434b7003e73b23557934421ace5d2f382f041638d5518 +166894725569cafa96c434aa14db0428db6791a8296fcc2990bec4ec819fd876 diff --git a/src/shell.c.in b/src/shell.c.in index 5170c2dde0..3b8731f7c5 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -1020,8 +1020,9 @@ static char *expand_prompt( /* \~ becomes the full pathname relative to $HOME */ if( onoff ){ sqlite3_filename pFN = p->db ? sqlite3_db_filename(p->db,0) : 0; - const char *zFN = pFN ? sqlite3_filename_database(pFN) : ":memory:"; + const char *zFN = pFN ? sqlite3_filename_database(pFN) : ""; if( zFN ){ + if( zFN[0]==0 ) zFN = "in-memory"; if( c=='f' ){ const char *zTail = strrchr(zFN,'/'); if( zTail && zTail[1] ) zFN = &zTail[1]; @@ -1129,14 +1130,19 @@ static char *expand_prompt( ** zPrior argument for reuse. */ #ifndef SQLITE_SHELL_FIDDLE -static char *one_input_line(ShellState *p, char *zPrior, int bContinue){ +static char *one_input_line( + ShellState *p, /* Shell state */ + char *zPrior, /* Just the previous line */ + const char *zAll, /* All statement text accumulated so far */ + int bContinue /* True for a continuation prompt */ +){ char *zResult; FILE *in = p->in; if( in!=0 ){ zResult = local_getline(zPrior, in); }else{ const char *zBase = bContinue ? p->contPrompt : p->mainPrompt; - char *zPrompt = expand_prompt(p, zPrior, zBase); + char *zPrompt = expand_prompt(p, zAll, zBase); shell_check_oom(zPrompt); #if SHELL_USE_LOCAL_GETLINE sputz(stdout, zPrompt); @@ -12414,7 +12420,12 @@ static void echo_group_input(ShellState *p, const char *zDo){ ** impl because we need the global shellState and cannot access it from that ** function without moving lots of code around (creating a larger/messier diff). */ -static char *one_input_line(ShellState *p, char *zPrior, int bContinue){ +static char *one_input_line( + ShellState *p, /* Shell state */ + char *zPrior, /* Just the prior line of text */ + const char *zAll, /* All accumulated statement text */ + int bContinue /* True if this is an accumulation */ +){ /* Parse the next line from shellState.wasm.zInput. */ const char *zBegin = shellState.wasm.zPos; const char *z = zBegin; @@ -12477,7 +12488,7 @@ static int process_input(ShellState *p, const char *zSrc){ p->lineno = 0; while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){ fflush(p->out); - zLine = one_input_line(p, zLine, nSql>0); + zLine = one_input_line(p, zLine, zSql, nSql>0); if( zLine==0 ){ /* End of input */ if( p->in==0 && stdin_is_interactive ) cli_puts("\n", p->out); @@ -12848,7 +12859,7 @@ static void main_init(ShellState *p) { #endif sqlite3_config(SQLITE_CONFIG_URI, 1); sqlite3_config(SQLITE_CONFIG_MULTITHREAD); - sqlite3_snprintf(sizeof(p->mainPrompt), p->mainPrompt,"SQLite:\\f> "); + sqlite3_snprintf(sizeof(p->mainPrompt), p->mainPrompt,"SQLite \\f> "); sqlite3_snprintf(sizeof(p->contPrompt), p->contPrompt,"\\B...\\H> "); } From 01e1be854b7ccf49b4f5e266208ab65b81b9ad21 Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 10 Apr 2026 20:44:38 +0000 Subject: [PATCH 11/19] Fix minor issues on Windows. FossilOrigin-Name: 48e40d3f6a193d6c4d1b8deda36415a690602dbe33d49984a9d92c6d40d8da5c --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c.in | 14 +++++++++----- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 7f18f4eedc..259f648d1b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sprompt\sfor\sin-memory\sdatabases.\s\sFix\sthe\scontinuation\smechanism\sso\sthat\nit\slooks\sat\sall\saccumulated\slines,\snot\sjust\sthe\smost\srecent\sline. -D 2026-04-10T20:29:35.946 +C Fix\sminor\sissues\son\sWindows. +D 2026-04-10T20:44:38.547 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 335a0c427f7de16a574c40683e79f9d5e7efcd2764168b00f7bdf76dfa349818 +F src/shell.c.in c36f64a3edfbf57d495570a3140aeba475f1982a3b25fad38e7dc96d6fd08c88 F src/sqlite.h.in a5605faa9479bbaac16c4ab43eb09ff50632004a8e05084d3fde56063ef73766 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479 F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca @@ -2197,8 +2197,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P 052631202e4dd930d93434b7003e73b23557934421ace5d2f382f041638d5518 -R db2a870af126f19369636d4e3aa1216f +P 166894725569cafa96c434aa14db0428db6791a8296fcc2990bec4ec819fd876 +R 2c75543b21d9df41c96d37c1e2521622 U drh -Z af6eb6bd5da5f6fa8530eefe13136eb2 +Z 9488bb6f8a2bd1c8cd9ed25f04693ceb # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 538f1770ec..2b3a4a7735 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -166894725569cafa96c434aa14db0428db6791a8296fcc2990bec4ec819fd876 +48e40d3f6a193d6c4d1b8deda36415a690602dbe33d49984a9d92c6d40d8da5c diff --git a/src/shell.c.in b/src/shell.c.in index 3b8731f7c5..b9202602b5 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -1024,7 +1024,11 @@ static char *expand_prompt( if( zFN ){ if( zFN[0]==0 ) zFN = "in-memory"; if( c=='f' ){ +#ifdef _WIN32 + const char *zTail = strrchr(zFN,'\\'); +#else const char *zTail = strrchr(zFN,'/'); +#endif if( zTail && zTail[1] ) zFN = &zTail[1]; }else if( c=='~' ){ const char *zHOME = getenv("HOME"); @@ -1046,17 +1050,17 @@ static char *expand_prompt( /* \H becomes text needed to terminate current input */ if( onoff ){ sqlite3_int64 R = zPrior ? sqlite3_incomplete(zPrior) : 0; - int c = (R>>16)&0xff; + int cc = (R>>16)&0xff; int nParen = R>>32; int eSemi = (R>>8)&0xff; - if( c==0 ){ + if( cc==0 ){ /* no-op */ - }else if( c=='-' ){ + }else if( cc=='-' ){ sqlite3_str_append(pOut,"\\n",3); - }else if( c=='/' ){ + }else if( cc=='/' ){ sqlite3_str_append(pOut,"*/",2); }else{ - sqlite3_str_appendchar(pOut, 1, c); + sqlite3_str_appendchar(pOut, 1, cc); } if( nParen>0 ){ sqlite3_str_appendf(pOut, "%.*c",nParen,')'); From 9d950aa13b7ea5d0a3ab5ec4ccd9a1f6fcf66c46 Mon Sep 17 00:00:00 2001 From: stephan Date: Fri, 10 Apr 2026 23:05:41 +0000 Subject: [PATCH 12/19] A protype of .prompt support in fiddle but its utility there is in doubt because .open does not work there, so there's very little dynamic info worth showing in a prompt. Also, ANSI colorization can't work there, nor can we colorize the prompts using HTML because of limitations in jquery.terminal. FossilOrigin-Name: 3b17500dc6338df23d1ed0572cd71593da5a9b048731f73242e27b9a76553a27 --- ext/wasm/api/EXPORTED_FUNCTIONS.c-pp | 1 + ext/wasm/fiddle/fiddle-worker.js | 4 +++- ext/wasm/fiddle/fiddle.js | 5 +++-- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- src/shell.c.in | 5 ++++- 6 files changed, 22 insertions(+), 15 deletions(-) diff --git a/ext/wasm/api/EXPORTED_FUNCTIONS.c-pp b/ext/wasm/api/EXPORTED_FUNCTIONS.c-pp index 2b8397a6d7..c489bdf83b 100644 --- a/ext/wasm/api/EXPORTED_FUNCTIONS.c-pp +++ b/ext/wasm/api/EXPORTED_FUNCTIONS.c-pp @@ -245,4 +245,5 @@ _fiddle_reset_db _fiddle_db_handle _fiddle_db_vfs _fiddle_export_db +_fiddle_get_prompt //#/if fiddle diff --git a/ext/wasm/fiddle/fiddle-worker.js b/ext/wasm/fiddle/fiddle-worker.js index 4b1ea2c538..0336379a9c 100644 --- a/ext/wasm/fiddle/fiddle-worker.js +++ b/ext/wasm/fiddle/fiddle-worker.js @@ -186,6 +186,7 @@ if(!f._){ if(!this.runMain()) return; f._ = sqlite3.wasm.xWrap('fiddle_exec', undefined, ['string']); + f.getPrompt = sqlite3.wasm.xWrap('fiddle_get_prompt', 'string:dealloc', []); } if(fiddleModule.isDead){ stderr("shell module has exit()ed. Cannot run SQL."); @@ -207,7 +208,8 @@ wMsg('working','end'); wMsg('wasm-info', { pointerSize: sqlite3.wasm.ptr.size, - heapSize: sqlite3.wasm.heap8().byteLength + heapSize: sqlite3.wasm.heap8().byteLength, + prompt: f.getPrompt() }); } }, diff --git a/ext/wasm/fiddle/fiddle.js b/ext/wasm/fiddle/fiddle.js index 84f125030c..1de5767885 100644 --- a/ext/wasm/fiddle/fiddle.js +++ b/ext/wasm/fiddle/fiddle.js @@ -349,9 +349,10 @@ SF.e.wasmInfo.innerText = 'WASM: '+( 4===v.pointerSize ? 32 : 64 )+'-bit' - //+' heap size: '+Number(v.heapSize) + +' heap: '+Number(v.heapSize) // Heap size is not changing even when loading a huge db? ; + SF.jqTerm?.set_prompt?.(v.prompt); }); /* querySelectorAll() proxy */ @@ -865,7 +866,7 @@ const jqeTerm = window.jQuery(SF.e.terminal).empty(); SF.jqTerm = jqeTerm.terminal(SF.dbExec.bind(SF),{ prompt: 'sqlite> ', - greetings: false /* note that the docs incorrectly call this 'greeting' */ + greetings: false /* the docs incorrectly call this 'greeting' */ }); EAll('.unhide-if-terminal-available').forEach(e=>{ e.classList.remove('hidden'); diff --git a/manifest b/manifest index 259f648d1b..61c22ba932 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sminor\sissues\son\sWindows. -D 2026-04-10T20:44:38.547 +C A\sprotype\sof\s.prompt\ssupport\sin\sfiddle\sbut\sits\sutility\sthere\sis\sin\sdoubt\sbecause\s.open\sdoes\snot\swork\sthere,\sso\sthere's\svery\slittle\sdynamic\sinfo\sworth\sshowing\sin\sa\sprompt.\sAlso,\sANSI\scolorization\scan't\swork\sthere,\snor\scan\swe\scolorize\sthe\sprompts\susing\sHTML\sbecause\sof\slimitations\sin\sjquery.terminal. +D 2026-04-10T23:05:41.450 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -582,7 +582,7 @@ F ext/wasm/SQLTester/SQLTester.mjs 6b3c52ed36a5573ca4883176f326332a8d4c0cecf5efd F ext/wasm/SQLTester/SQLTester.run.mjs 57f2adb33f43f2784abbf8026c1bfd049d8013af1998e7dcb8b50c89ffc332e0 F ext/wasm/SQLTester/index.html 64f3435084c7d6139b08d1f2a713828a73f68de2ae6a3112cbb5980d991ba06f F ext/wasm/SQLTester/touint8array.c 2d5ece04ec1393a6a60c4bf96385bda5e1a10ad49f3038b96460fc5e5aa7e536 -F ext/wasm/api/EXPORTED_FUNCTIONS.c-pp de2ce128aebeff9ef4161cff7a0ff0089be866121bcb8941ad44a38a65f1d436 +F ext/wasm/api/EXPORTED_FUNCTIONS.c-pp 189935d0106bca86661efc991ab13e1d5d6e1f55ec34dc7b5055a99321397edd F ext/wasm/api/README.md a905d5c6bfc3e2df875bd391d6d6b7b48d41b43bdee02ad115b47244781a7e81 F ext/wasm/api/extern-post-js.c-pp.js 80accc53cc6ea1e61c721595f42ba95baa7c7ea636807d9507e69403301f8c54 F ext/wasm/api/extern-pre-js.js cc61c09c7a24a07dbecb4c352453c3985170cec12b4e7e7e7a4d11d43c5c8f41 @@ -621,8 +621,8 @@ F ext/wasm/demo-worker1-promiser.c-pp.js d210aa1e8a74ea6244fe2290de5710bb55b3a9e F ext/wasm/demo-worker1.html 2c178c1890a2beb5a5fecb1453e796d067a4b8d3d2a04d65ca2eb1ab2c68ef5d F ext/wasm/demo-worker1.js fdfa90aa9d6b402bfed802cf1595fe4da6cc834ac38c8ff854bf1ee01f5ff9bb F ext/wasm/example_extra_init.c 2347cd69d19d839ef4e5e77b7855103a7fe3ef2af86f2e8c95839afd8b05862f -F ext/wasm/fiddle/fiddle-worker.js 6c72acac2d381480bc9f5eb538e3f2faf2c1f72dd4fcbd05d3b409818a9a8fd5 -F ext/wasm/fiddle/fiddle.js 84fd75967e0af8b69d3dd849818342227d0f81d13db92e0dcbc63649b31a4893 +F ext/wasm/fiddle/fiddle-worker.js 3cdd20c1e84494a1f28bd80265ae2a754764b08c67e146e61f99d864de4bf5f6 +F ext/wasm/fiddle/fiddle.js aa5df1e56f54d3ef8cf4ca6e58cc4977380297debcd4e39a9bda64ca50d7ebb2 F ext/wasm/fiddle/index.c-pp.html 02f063ef30b8124f311029855c4439e77bc6505d1bf65a163d88c064a63ee9d9 F ext/wasm/index-dist.html db23748044e286773f2768eec287669501703b5d5f72755e8db73607dc54d290 F ext/wasm/index.html 5bf6cf1b0a3c8b9f5f54d77f2219d7ae87a15162055ce308109c49b1dcab4239 @@ -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 c36f64a3edfbf57d495570a3140aeba475f1982a3b25fad38e7dc96d6fd08c88 +F src/shell.c.in 793a37b4db7a4e3c56ad997b2ff8b3210ab9954c7ea857558fa6ae3bb8750ccf F src/sqlite.h.in a5605faa9479bbaac16c4ab43eb09ff50632004a8e05084d3fde56063ef73766 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479 F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca @@ -2197,8 +2197,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P 166894725569cafa96c434aa14db0428db6791a8296fcc2990bec4ec819fd876 -R 2c75543b21d9df41c96d37c1e2521622 -U drh -Z 9488bb6f8a2bd1c8cd9ed25f04693ceb +P 48e40d3f6a193d6c4d1b8deda36415a690602dbe33d49984a9d92c6d40d8da5c +R 36c4b7bda37fe0a82332385d585e25c8 +U stephan +Z 116e2e61ae77c762ad7badc7376d6d1b # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 2b3a4a7735..55623f9645 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -48e40d3f6a193d6c4d1b8deda36415a690602dbe33d49984a9d92c6d40d8da5c +3b17500dc6338df23d1ed0572cd71593da5a9b048731f73242e27b9a76553a27 diff --git a/src/shell.c.in b/src/shell.c.in index b9202602b5..1d6af32b67 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -13602,7 +13602,6 @@ int SQLITE_CDECL main(int argc, char **argv){ if( rc ){ goto shell_main_exit; } - } if( data.nPopOutput && azCmd[i][0]!='.' ){ output_reset(&data); @@ -13861,4 +13860,8 @@ void fiddle_exec(const char * zSql){ shellState.wasm.zInput = shellState.wasm.zPos = 0; } } + +char *fiddle_get_prompt(void){ + return expand_prompt(&shellState, 0, &shellState.mainPrompt[0]); +} #endif /* SQLITE_SHELL_FIDDLE */ From 504cfd5ec72d41a26f42df27fe4c699e6172f4fd Mon Sep 17 00:00:00 2001 From: stephan Date: Fri, 10 Apr 2026 23:25:57 +0000 Subject: [PATCH 13/19] Ensure that sqlite3-opfs-async-proxy.js is copied into the fiddle target dirs. FossilOrigin-Name: 7c9998de1b839cfbe12c4328ac5176f5fae981e139c5f8888b100752f5e4756b --- ext/wasm/mkwasmbuilds.c | 6 +++++- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/ext/wasm/mkwasmbuilds.c b/ext/wasm/mkwasmbuilds.c index 1f60a89bb7..a9327a6fb0 100644 --- a/ext/wasm/mkwasmbuilds.c +++ b/ext/wasm/mkwasmbuilds.c @@ -1021,11 +1021,15 @@ static void mk_fiddle(void){ pf("\t@$(call b.call.wasm-strip,%s)\n", zBuildName); pf("\t@$(call b.strip-js-emcc-bindings,$(logtag.%s))\n", zBuildName); + pf("\t@$(call b.cp,%s,$(dir.dout)/sqlite3-opfs-async-proxy.js," + "$(dir $@)" + ")\n", zBuildName); if( isDebug ){ pf("\t@$(call b.cp,%s," "$(dir.fiddle)/index.html " "$(dir.fiddle)/fiddle.js " - "$(dir.fiddle)/fiddle-worker.js," + "$(dir.fiddle)/fiddle-worker.js " + "$(dir.fiddle)/sqlite3-opfs-async-proxy.js," "$(dir $@)" ")\n", zBuildName); diff --git a/manifest b/manifest index 61c22ba932..fd9c7473a9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C A\sprotype\sof\s.prompt\ssupport\sin\sfiddle\sbut\sits\sutility\sthere\sis\sin\sdoubt\sbecause\s.open\sdoes\snot\swork\sthere,\sso\sthere's\svery\slittle\sdynamic\sinfo\sworth\sshowing\sin\sa\sprompt.\sAlso,\sANSI\scolorization\scan't\swork\sthere,\snor\scan\swe\scolorize\sthe\sprompts\susing\sHTML\sbecause\sof\slimitations\sin\sjquery.terminal. -D 2026-04-10T23:05:41.450 +C Ensure\sthat\ssqlite3-opfs-async-proxy.js\sis\scopied\sinto\sthe\sfiddle\starget\sdirs. +D 2026-04-10T23:25:57.996 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -630,7 +630,7 @@ F ext/wasm/jaccwabyt/jaccwabyt.js 4e2b797dc170851c9c530c3567679f4aa509eec0fab73b F ext/wasm/jaccwabyt/jaccwabyt.md 6aa90fa1a973d0ad10d077088bea163b241d8470c75eafdef87620a1de1dea41 F ext/wasm/libcmpp.c 0e2cec7de7c9cbe7941e6a4dc0c123cec736578a3eeae7828ac18706acd3cea6 F ext/wasm/mkdist.sh f8883b077a2ca47cf92e6f0ce305fbf72ca648c3501810125056c4b09c2d5554 x -F ext/wasm/mkwasmbuilds.c d4479af2774a43104b819d9286961b7c09793ca39440e20191e693ceff21f911 +F ext/wasm/mkwasmbuilds.c 60706fb66db7f1e24d876e3cb2493484cfb27e7b103c7741c384505dd678769c F ext/wasm/module-symbols.html e54f42112e0aac2a31f850ab33e7f2630a2ea4f63496f484a12469a2501e07e2 F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96 F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63 @@ -2197,8 +2197,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P 48e40d3f6a193d6c4d1b8deda36415a690602dbe33d49984a9d92c6d40d8da5c -R 36c4b7bda37fe0a82332385d585e25c8 +P 3b17500dc6338df23d1ed0572cd71593da5a9b048731f73242e27b9a76553a27 +R 476d91cbd2e583bce4c47c269d3e9c58 U stephan -Z 116e2e61ae77c762ad7badc7376d6d1b +Z 2eee38e661f38d66a6834d873120875b # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 55623f9645..d406694df1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3b17500dc6338df23d1ed0572cd71593da5a9b048731f73242e27b9a76553a27 +7c9998de1b839cfbe12c4328ac5176f5fae981e139c5f8888b100752f5e4756b From c8b130f2550155b07174765be33ba7c52ec6bef3 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 11 Apr 2026 11:24:09 +0000 Subject: [PATCH 14/19] Fix the \B escape for prompts so that it uses wcwidth() instead of strlen() to compute spacing. FossilOrigin-Name: c6ff4f701d9cf963cf2472ed72ad4e201227560dde2ba8d48602af2e49170e89 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/shell.c.in | 7 ++++--- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index fd9c7473a9..d19732cd62 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Ensure\sthat\ssqlite3-opfs-async-proxy.js\sis\scopied\sinto\sthe\sfiddle\starget\sdirs. -D 2026-04-10T23:25:57.996 +C Fix\sthe\s\B\sescape\sfor\sprompts\sso\sthat\sit\suses\swcwidth()\sinstead\sof\nstrlen()\sto\scompute\sspacing. +D 2026-04-11T11:24:09.462 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 793a37b4db7a4e3c56ad997b2ff8b3210ab9954c7ea857558fa6ae3bb8750ccf +F src/shell.c.in 50505cdfdae8163b7c7476c7ad94c79c3b851274301e680dbb7b91c6d6bdc13b F src/sqlite.h.in a5605faa9479bbaac16c4ab43eb09ff50632004a8e05084d3fde56063ef73766 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479 F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca @@ -2197,8 +2197,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P 3b17500dc6338df23d1ed0572cd71593da5a9b048731f73242e27b9a76553a27 -R 476d91cbd2e583bce4c47c269d3e9c58 -U stephan -Z 2eee38e661f38d66a6834d873120875b +P 7c9998de1b839cfbe12c4328ac5176f5fae981e139c5f8888b100752f5e4756b +R effaffd5b612cee5e2c7467276ff636f +U drh +Z 38f50b0294cde0ae9e16e79e3a672fcb # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index d406694df1..723703ae42 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7c9998de1b839cfbe12c4328ac5176f5fae981e139c5f8888b100752f5e4756b +c6ff4f701d9cf963cf2472ed72ad4e201227560dde2ba8d48602af2e49170e89 diff --git a/src/shell.c.in b/src/shell.c.in index 1d6af32b67..4e5f913c6c 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -1100,12 +1100,13 @@ static char *expand_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, p->mainPrompt); - int nOther = strlen30(zOther); + size_t wOther = sqlite3_qrf_wcswidth(zOther); + size_t wThis = sqlite3_qrf_wcswidth(sqlite3_str_value(pOut)); sqlite3_free(zOther); - if( nOther>sqlite3_str_length(pOut) ){ + if( wOther>wThis ){ char *z; - int nNew = nOther - sqlite3_str_length(pOut); int len; + size_t nNew = wOther - wThis; sqlite3_str_appendchar(pOut, nNew, ' '); len = sqlite3_str_length(pOut); if( len>idxSpace ){ From cd2879711736b2a89af712271ba764fee99abb69 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 11 Apr 2026 12:35:53 +0000 Subject: [PATCH 15/19] Remove arbitrary limits on the length of CLI prompts. Use environment variables SQLITE_PS1 and SQLITE_PS2 (if they exist) as the default CLI prompts. FossilOrigin-Name: a46ceaeab968d8f376c5a225c23c0be8619fed4511b7e567baf3a8d7736c19d1 --- manifest | 12 ++++----- manifest.uuid | 2 +- src/shell.c.in | 68 +++++++++++++++++++++++++++++--------------------- 3 files changed, 46 insertions(+), 36 deletions(-) diff --git a/manifest b/manifest index d19732cd62..5e3013e532 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\s\B\sescape\sfor\sprompts\sso\sthat\sit\suses\swcwidth()\sinstead\sof\nstrlen()\sto\scompute\sspacing. -D 2026-04-11T11:24:09.462 +C Remove\sarbitrary\slimits\son\sthe\slength\sof\sCLI\sprompts.\s\sUse\senvironment\nvariables\sSQLITE_PS1\sand\sSQLITE_PS2\s(if\sthey\sexist)\sas\sthe\sdefault\nCLI\sprompts. +D 2026-04-11T12:35:53.197 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 50505cdfdae8163b7c7476c7ad94c79c3b851274301e680dbb7b91c6d6bdc13b +F src/shell.c.in 7ad3effc35e738c90d87b6b5336a0ddd7cc1bcb32cfc7c73cab4666e8c0afb22 F src/sqlite.h.in a5605faa9479bbaac16c4ab43eb09ff50632004a8e05084d3fde56063ef73766 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479 F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca @@ -2197,8 +2197,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P 7c9998de1b839cfbe12c4328ac5176f5fae981e139c5f8888b100752f5e4756b -R effaffd5b612cee5e2c7467276ff636f +P c6ff4f701d9cf963cf2472ed72ad4e201227560dde2ba8d48602af2e49170e89 +R 5b11b0f858f42d7a9b800b9821aa8115 U drh -Z 38f50b0294cde0ae9e16e79e3a672fcb +Z c8ef1c46f1e4fc036ec422f313143d28 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 723703ae42..734582b578 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c6ff4f701d9cf963cf2472ed72ad4e201227560dde2ba8d48602af2e49170e89 +a46ceaeab968d8f376c5a225c23c0be8619fed4511b7e567baf3a8d7736c19d1 diff --git a/src/shell.c.in b/src/shell.c.in index 4e5f913c6c..9db31bcf37 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -355,11 +355,6 @@ typedef struct Mode { #define MFLG_CRLF 0x02 /* Use CR/LF output line endings */ #define MFLG_HDR 0x04 /* .header used to change headers on/off */ -/* -** Size of the prompt strings -*/ -#define PROMPT_MAX 128 - /* ** State information about the database connection is contained in an ** instance of the following structure. @@ -403,6 +398,7 @@ struct ShellState { char *zErrPrefix; /* Alternative error message prefix */ sqlite3_stmt *pStmt; /* Current statement if any. */ FILE *pLog; /* Write log output here */ + char *azPrompt[2]; /* Main and continuation prompt strings */ Mode mode; /* Current display mode */ Mode modePrior; /* Backup */ struct SavedMode { /* Ability to define custom mode configurations */ @@ -442,8 +438,6 @@ struct ShellState { #endif char zTestcase[30]; /* Name of current test case */ char outfile[FILENAME_MAX]; /* Filename for *out */ - char mainPrompt[PROMPT_MAX]; /* Main prompt */ - char contPrompt[PROMPT_MAX]; /* Continuation prompt */ }; #ifdef SQLITE_SHELL_FIDDLE @@ -793,20 +787,6 @@ static sqlite3_int64 timeOfDay(void){ #endif } - - -/* This is variant of the standard-library strncpy() routine with the -** one change that the destination string is always zero-terminated, even -** if there is no zero-terminator in the first n-1 characters of the source -** string. -*/ -static char *shell_strncpy(char *dest, const char *src, size_t n){ - size_t i; - for(i=0; iazPrompt[bContinue] ){ + return p->azPrompt[bContinue]; + } +#ifndef SQLITE_SHELL_FIDDLE + zPS = getenv(bContinue ? "SQLITE_PS2" : "SQLITE_PS1"); + if( zPS ) return zPS; +#endif + if( bContinue ){ + return "\\B...\\H> "; + }else{ + return "SQLite \\f> "; + } +} + /* ** Expand escapes in the given input prompt string. Return the ** expanded prompt in memory obtained from sqlite3_malloc(). The @@ -1079,7 +1087,7 @@ static char *expand_prompt( } if( c=='B' ){ - /* \B is a no-op for the main prmopt. For 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); @@ -1099,7 +1107,7 @@ static char *expand_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, p->mainPrompt); + char *zOther = expand_prompt(p, 0, prompt_string(p,0)); size_t wOther = sqlite3_qrf_wcswidth(zOther); size_t wThis = sqlite3_qrf_wcswidth(sqlite3_str_value(pOut)); sqlite3_free(zOther); @@ -1146,7 +1154,7 @@ static char *one_input_line( if( in!=0 ){ zResult = local_getline(zPrior, in); }else{ - const char *zBase = bContinue ? p->contPrompt : p->mainPrompt; + const char *zBase = prompt_string(p, bContinue!=0); char *zPrompt = expand_prompt(p, zAll, zBase); shell_check_oom(zPrompt); #if SHELL_USE_LOCAL_GETLINE @@ -10562,10 +10570,12 @@ static int do_meta_command(const char *zLine, ShellState *p){ if( c=='p' && cli_strncmp(azArg[0], "prompt", n)==0 ){ if( nArg >= 2) { - shell_strncpy(p->mainPrompt,azArg[1],sizeof(p->mainPrompt)-1); + free(p->azPrompt[0]); + p->azPrompt[0] = strdup(azArg[1]); } if( nArg >= 3) { - shell_strncpy(p->contPrompt,azArg[2],sizeof(p->contPrompt)-1); + free(p->azPrompt[1]); + p->azPrompt[1] = strdup(azArg[2]); } }else @@ -12864,8 +12874,6 @@ static void main_init(ShellState *p) { #endif sqlite3_config(SQLITE_CONFIG_URI, 1); sqlite3_config(SQLITE_CONFIG_MULTITHREAD); - sqlite3_snprintf(sizeof(p->mainPrompt), p->mainPrompt,"SQLite \\f> "); - sqlite3_snprintf(sizeof(p->contPrompt), p->contPrompt,"\\B...\\H> "); } /* @@ -13702,6 +13710,8 @@ int SQLITE_CDECL main(int argc, char **argv){ free(data.dot.azArg); free(data.dot.aiOfst); free(data.dot.abQuot); + free(data.azPrompt[0]); + free(data.azPrompt[1]); if( data.nTestRun ){ sqlite3_fprintf(stdout, "%d test%s run with %d error%s\n", data.nTestRun, data.nTestRun==1 ? "" : "s", @@ -13863,6 +13873,6 @@ void fiddle_exec(const char * zSql){ } char *fiddle_get_prompt(void){ - return expand_prompt(&shellState, 0, &shellState.mainPrompt[0]); + return expand_prompt(&shellState, 0, prompt_string(&shellState,0)); } #endif /* SQLITE_SHELL_FIDDLE */ From fc2c730c87594cf18b2e327b2ade80d7c4e1b83f Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 11 Apr 2026 14:11:56 +0000 Subject: [PATCH 16/19] Enhancements to shell_prompt_test() for better testing. Enhance the ".open" command so that it does ~/ expansion on filenames. FossilOrigin-Name: ec6830fe60b73bc606d3c2a5d407a39db53f6dadee760829410abfa1df46389e --- manifest | 12 ++--- manifest.uuid | 2 +- src/shell.c.in | 120 +++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 104 insertions(+), 30 deletions(-) diff --git a/manifest b/manifest index 5e3013e532..9bdd902a79 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sarbitrary\slimits\son\sthe\slength\sof\sCLI\sprompts.\s\sUse\senvironment\nvariables\sSQLITE_PS1\sand\sSQLITE_PS2\s(if\sthey\sexist)\sas\sthe\sdefault\nCLI\sprompts. -D 2026-04-11T12:35:53.197 +C Enhancements\sto\sshell_prompt_test()\sfor\sbetter\stesting.\s\sEnhance\sthe\n".open"\scommand\sso\sthat\sit\sdoes\s~/\sexpansion\son\sfilenames. +D 2026-04-11T14:11:56.053 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 7ad3effc35e738c90d87b6b5336a0ddd7cc1bcb32cfc7c73cab4666e8c0afb22 +F src/shell.c.in 7145f12e0a923fca7f1716086796e279785d19d95dfaa3ac7314e59e29d086c0 F src/sqlite.h.in a5605faa9479bbaac16c4ab43eb09ff50632004a8e05084d3fde56063ef73766 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479 F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca @@ -2197,8 +2197,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P c6ff4f701d9cf963cf2472ed72ad4e201227560dde2ba8d48602af2e49170e89 -R 5b11b0f858f42d7a9b800b9821aa8115 +P a46ceaeab968d8f376c5a225c23c0be8619fed4511b7e567baf3a8d7736c19d1 +R b145f37224b01e5b0236a04795b472a6 U drh -Z c8ef1c46f1e4fc036ec422f313143d28 +Z 7ccada63678abda6f630b8ea89fca70f # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 734582b578..f91f7fa9a9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a46ceaeab968d8f376c5a225c23c0be8619fed4511b7e567baf3a8d7736c19d1 +ec6830fe60b73bc606d3c2a5d407a39db53f6dadee760829410abfa1df46389e diff --git a/src/shell.c.in b/src/shell.c.in index 9db31bcf37..89b3f47e34 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -410,6 +410,7 @@ struct ShellState { sqlite3 *db; /* Connection pointer */ const char *zDbFilename; /* Filename used to open the connection */ char *zFreeOnClose; /* Free this memory allocation on close */ + int mFlgs; /* 0x001: Use zDbFilenaem for prompt */ #if defined(SQLITE_ENABLE_SESSION) int nSession; /* Number of active sessions */ OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */ @@ -934,6 +935,24 @@ static const char *prompt_string(ShellState *p, int bContinue){ } } +/* +** Return the name of the open database file, to be used for prompt +** expansion purposes. +*/ +static const char *prompt_filename(ShellState *p){ + sqlite3_filename pFN; + const char *zFN = 0; + if( p->pAuxDb->mFlgs & 0x01 ){ + zFN = p->pAuxDb->zDbFilename; + }else if( p->db && (pFN = sqlite3_db_filename(p->db,0))!=0 ){ + zFN = sqlite3_filename_database(pFN); + } + if( zFN==0 || zFN[0]==0 ){ + zFN = "in-memory"; + } + return zFN; +} + /* ** Expand escapes in the given input prompt string. Return the ** expanded prompt in memory obtained from sqlite3_malloc(). The @@ -1027,27 +1046,23 @@ static char *expand_prompt( /* \F becomes the full pathname */ /* \~ becomes the full pathname relative to $HOME */ if( onoff ){ - sqlite3_filename pFN = p->db ? sqlite3_db_filename(p->db,0) : 0; - const char *zFN = pFN ? sqlite3_filename_database(pFN) : ""; - if( zFN ){ - if( zFN[0]==0 ) zFN = "in-memory"; - if( c=='f' ){ + const char *zFN = prompt_filename(p); + if( c=='f' ){ #ifdef _WIN32 - const char *zTail = strrchr(zFN,'\\'); + const char *zTail = strrchr(zFN,'\\'); #else - const char *zTail = strrchr(zFN,'/'); + const char *zTail = strrchr(zFN,'/'); #endif - if( zTail && zTail[1] ) zFN = &zTail[1]; - }else if( c=='~' ){ - const char *zHOME = getenv("HOME"); - size_t nHOME = zHOME ? strlen(zHOME) : 0; - if( nHOME=2 ? (const char*)sqlite3_value_text(apVal[1]) : 0; ShellState *p = (ShellState*)sqlite3_user_data(pCtx); - char *zRes = expand_prompt(p, zPrior, zPrompt); + const char *zPrompt; + const char *zPrior; + const char *zSavedDbFile; + int mSavedFlgs; + const char *zFName; + char *zRes; + + if( nVal<2 + || (zPrior = (const char*)sqlite3_value_text(apVal[1]))==0 + || zPrior[0]==0 + ){ + zPrior = 0; + } + zPrompt = (const char*)sqlite3_value_text(apVal[0]); + if( zPrompt==0 ){ + zPrompt = prompt_string(p, zPrior!=0); + } + zSavedDbFile = p->pAuxDb->zDbFilename; + mSavedFlgs = p->pAuxDb->mFlgs; + if( nVal>=3 && (zFName = (const char*)sqlite3_value_text(apVal[2]))!=0 ){ + p->pAuxDb->zDbFilename = zFName; + p->pAuxDb->mFlgs |= 0x001; + } + zRes = expand_prompt(p, zPrior, zPrompt); + p->pAuxDb->zDbFilename = zSavedDbFile; + p->pAuxDb->mFlgs = mSavedFlgs; sqlite3_result_text(pCtx, zRes, -1, SQLITE_TRANSIENT); sqlite3_free(zRes); } @@ -4604,6 +4650,31 @@ static void shellModuleSchema( static void open_db(ShellState *p, int openFlags){ if( p->db==0 ){ const char *zDbFilename = p->pAuxDb->zDbFilename; + const char *zHOME; /* Value of HOME environment variable */ + char *zToFree = 0; /* Filename with ~/ prefix expansion */ + + /* If the zDbFilename does not exist and begins with ~/ then replace + ** the ~ with the home directory. + */ + if( zDbFilename && zDbFilename[0]=='~' +#ifdef _WIN32 + && (zDbFilename[1]=='/' || zDbFilename[1]=='\\') +#else + && zDbFilename[1]=='/' +#endif + && access(zDbFilename,0)!=0 + && (zHOME = getenv("HOME"))!=0 && zHOME[0]!=0 + ){ + size_t nHOME = strlen(zHOME); + size_t nFN = strlen(zDbFilename); + zToFree = malloc(nHOME+nFN+1); + if( zToFree ){ + memcpy(zToFree, zHOME, nHOME); + memcpy(zToFree+nHOME, zDbFilename+1, nFN); + zDbFilename = zToFree; + } + } + if( p->openMode==SHELL_OPEN_UNSPEC ){ if( zDbFilename==0 || zDbFilename[0]==0 ){ p->openMode = SHELL_OPEN_NORMAL; @@ -4737,9 +4808,11 @@ static void open_db(ShellState *p, int openFlags){ sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0, editFunc, 0, 0); #endif - sqlite3_create_function(p->db, "shell_expand_prompt", 1, SQLITE_UTF8, + sqlite3_create_function(p->db, "shell_prompt_test", 1, SQLITE_UTF8, p, shellExpandPrompt, 0, 0); - sqlite3_create_function(p->db, "shell_expand_prompt", 2, SQLITE_UTF8, + sqlite3_create_function(p->db, "shell_prompt_test", 2, SQLITE_UTF8, + p, shellExpandPrompt, 0, 0); + sqlite3_create_function(p->db, "shell_prompt_test", 3, SQLITE_UTF8, p, shellExpandPrompt, 0, 0); @@ -4775,6 +4848,7 @@ static void open_db(ShellState *p, int openFlags){ } } #endif + free(zToFree); } if( p->db!=0 ){ #ifndef SQLITE_OMIT_AUTHORIZATION From 3b27ffa534c98cfd1766c3005efa888fc1395d21 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 11 Apr 2026 15:45:45 +0000 Subject: [PATCH 17/19] Add --reset, --show, and -- options to the ".prompt" command of the CLI. FossilOrigin-Name: 8075576ba2324a458440bae398baecc7872b6528574b7fe6681a3a30b62d58ef --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c.in | 46 +++++++++++++++++++++++++++++++++++++--------- 3 files changed, 44 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index 9bdd902a79..522720a9cc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhancements\sto\sshell_prompt_test()\sfor\sbetter\stesting.\s\sEnhance\sthe\n".open"\scommand\sso\sthat\sit\sdoes\s~/\sexpansion\son\sfilenames. -D 2026-04-11T14:11:56.053 +C Add\s--reset,\s--show,\sand\s--\soptions\sto\sthe\s".prompt"\scommand\sof\sthe\sCLI. +D 2026-04-11T15:45:45.725 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 7145f12e0a923fca7f1716086796e279785d19d95dfaa3ac7314e59e29d086c0 +F src/shell.c.in 0007932372e03af8a58060bacbc5cf66ce199b133f41835e28e2cf69eaa4e356 F src/sqlite.h.in a5605faa9479bbaac16c4ab43eb09ff50632004a8e05084d3fde56063ef73766 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479 F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca @@ -2197,8 +2197,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P a46ceaeab968d8f376c5a225c23c0be8619fed4511b7e567baf3a8d7736c19d1 -R b145f37224b01e5b0236a04795b472a6 +P ec6830fe60b73bc606d3c2a5d407a39db53f6dadee760829410abfa1df46389e +R 88ad9dd87efed80bbaec4531f930e2fd U drh -Z 7ccada63678abda6f630b8ea89fca70f +Z cfdc335f1af0530f176bbfd2d779b4ff # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index f91f7fa9a9..1f753ed0be 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ec6830fe60b73bc606d3c2a5d407a39db53f6dadee760829410abfa1df46389e +8075576ba2324a458440bae398baecc7872b6528574b7fe6681a3a30b62d58ef diff --git a/src/shell.c.in b/src/shell.c.in index 89b3f47e34..ee3951e9f6 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -4038,7 +4038,10 @@ static const char *(azHelp[]) = { " --reset Reset the count for each input and interrupt", " --timeout S Halt after running for S seconds", #endif - ".prompt MAIN CONTINUE Replace the standard prompts", + ".prompt MAIN CONTINUE Replace the standard prompts", + " --reset Revert to default prompts", + " --show Show the current prompt strings", + " -- No more options. Subsequent args are prompts", #ifndef SQLITE_SHELL_FIDDLE ".quit Stop interpreting input stream, exit if primary.", ".read FILE Read input from FILE or command output", @@ -10643,14 +10646,39 @@ static int do_meta_command(const char *zLine, ShellState *p){ #endif /* SQLITE_OMIT_PROGRESS_CALLBACK */ if( c=='p' && cli_strncmp(azArg[0], "prompt", n)==0 ){ - if( nArg >= 2) { - free(p->azPrompt[0]); - p->azPrompt[0] = strdup(azArg[1]); - } - if( nArg >= 3) { - free(p->azPrompt[1]); - p->azPrompt[1] = strdup(azArg[2]); - } + int i; + int cnt = 0; + int noOpt = 0; + for(i=1; iazPrompt[0]); + free(p->azPrompt[1]); + memset(p->azPrompt, 0, sizeof(p->azPrompt)); + }else + if( strcmp(z,"-show")==0 ){ + cli_printf(stdout,"Main prompt: '%s'\n", prompt_string(p, 0)); + cli_printf(stdout,"Continuation: '%s'\n", prompt_string(p, 1)); + }else + if( strcmp(z,"-")==0 ){ + noOpt = 1; + }else + { + dotCmdError(p, i, "unknown option", 0); + rc = 1; + goto meta_command_exit; + } + }else if( cnt>1 ){ + dotCmdError(p, i, "extra argument", 0); + rc = 1; + goto meta_command_exit; + }else{ + free(p->azPrompt[cnt]); + p->azPrompt[cnt] = strdup(z); + } + } }else #ifndef SQLITE_SHELL_FIDDLE From 28456958ca21a49d2f70f3ca0053ba47a429db70 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 11 Apr 2026 16:12:12 +0000 Subject: [PATCH 18/19] Initial test cases for the CLI prompt enhancements. FossilOrigin-Name: b7ecc84735d41e9cdb498020b86d8219efa18ca5b40aef1031a14809f1ac2d38 --- manifest | 13 +++---- manifest.uuid | 2 +- test/shell-prompt.sql | 84 +++++++++++++++++++++++++++++++++++++++++++ test/shellB.test | 1 + 4 files changed, 93 insertions(+), 7 deletions(-) create mode 100644 test/shell-prompt.sql diff --git a/manifest b/manifest index 522720a9cc..56c8c222eb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\s--reset,\s--show,\sand\s--\soptions\sto\sthe\s".prompt"\scommand\sof\sthe\sCLI. -D 2026-04-11T15:45:45.725 +C Initial\stest\scases\sfor\sthe\sCLI\sprompt\senhancements. +D 2026-04-11T16:12:12.307 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -1619,6 +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/shell1.test eda2e527435f139224dda67db6bbd2466597408d4fe5883d647d67fa32d88f7c F test/shell2.test dc541d2681503e55466a24d35a4cbf8ca5b90b8fcdef37fc4db07373a67d31d3 F test/shell3.test 91efdd545097a61a1f72cf79c9ad5b49da080f3f10282eaf4c3c272cd1012db2 @@ -1629,7 +1630,7 @@ F test/shell7.test 43fd8e511c533bab5232e95c7b4be93b243451709e89582600d4b6e67693d F test/shell8.test 38c9e4d7e85d2a3ecfacaa9f6cda4f7a81bf4fffb5f3f37f9cd76827c6883192 F test/shell9.test c0e8871061a92151450b3332279a893b516fa73a6c46d4f51a0998407cbf8c89 F test/shellA.test 05cdaafa1f79913654487ce3aefa038d4106245d58f52e02faf506140a76d480 -F test/shellB.test 31df04230f6062069bb7c5d0e5c5439ca44448fa9da1a55aa461a4b872fe6bd9 +F test/shellB.test a42be39e2332877d8ee239e1ca2a78d0a1feda21d90f3dd50f32f26cc3b433de F test/shmlock.test 9f1f729a7fe2c46c88b156af819ac9b72c0714ac6f7246638a73c5752b5fd13c F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3 F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5 @@ -2197,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 ec6830fe60b73bc606d3c2a5d407a39db53f6dadee760829410abfa1df46389e -R 88ad9dd87efed80bbaec4531f930e2fd +P 8075576ba2324a458440bae398baecc7872b6528574b7fe6681a3a30b62d58ef +R f48e042fefe94b7b0163646f453436c8 U drh -Z cfdc335f1af0530f176bbfd2d779b4ff +Z cc8f78fbdba944ff44e190e2f866d31e # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 1f753ed0be..08846a02ee 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8075576ba2324a458440bae398baecc7872b6528574b7fe6681a3a30b62d58ef +b7ecc84735d41e9cdb498020b86d8219efa18ca5b40aef1031a14809f1ac2d38 diff --git a/test/shell-prompt.sql b/test/shell-prompt.sql new file mode 100644 index 0000000000..215b54485f --- /dev/null +++ b/test/shell-prompt.sql @@ -0,0 +1,84 @@ +#!sqlite3 +# +# 2026-04-11 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# Tests for the .prompt command and prompt rendering. +# +# ./sqlite3 test/shell-prompt.sql +# + +.testcase setup +.open -new test.db +.mode list -quote off -escape ascii +.check '' + +.testcase 100 +.prompt +.check '' + +.testcase 110 +.prompt --show +.check < ' +Continuation: '\B...\H> ' +END + +.testcase 1000 +SELECT shell_prompt_test(NULL); +.check 'SQLite test.db> '; +.testcase 1001 +SELECT shell_prompt_test(NULL,'SELECT'); +.check ' ...;> '; +.testcase 1002 +SELECT shell_prompt_test(NULL,'SELECT ((("'); +.check ' ...")));> '; +.testcase 1003 +SELECT shell_prompt_test(NULL,'SELECT ((()['); +.check ' ...]));> '; +.testcase 1004 +SELECT shell_prompt_test(NULL,'SELECT '''); +.check " ...';> "; +.testcase 1005 +SELECT shell_prompt_test(NULL,'CREATE TRIGGER t1 BEGIN'); +.check " ...;END;> "; +.testcase 1006 +SELECT shell_prompt_test(NULL,'CREATE TRIGGER t1 BEGIN SELECT (((['); +.check " ...])));END;> "; +.testcase 1007 +SELECT shell_prompt_test(NULL,'CREATE TRIGGER t1 BEGIN SELECT ((/*a(((''bc'); +.check " ...*/));END;> "; +.testcase 1008 +SELECT shell_prompt_test(NULL,'CREATE TRIGGER t1 BEGIN SELECT 1;'); +.check " ...END;> "; + +.testcase 2000 +.prompt 'SQLite\x-txn$\:>\; ' +SELECT shell_prompt_test(NULL); +.check 'SQLite> '; +.testcase 2001 +BEGIN; +SELECT shell_prompt_test(NULL); +.check 'SQLite-txn$ '; +.testcase 2002 +ROLLBACK; +SELECT shell_prompt_test(NULL); +.check 'SQLite> '; +.testcase 2003 +.prompt -- '--show ' +SELECT shell_prompt_test(NULL); +.check '--show '; +.testcase 2004 +.prompt --reset +SELECT shell_prompt_test(NULL); +.check 'SQLite test.db> '; + +.testcase diff --git a/test/shellB.test b/test/shellB.test index 5be2f7b6da..566a7bc19e 100644 --- a/test/shellB.test +++ b/test/shellB.test @@ -49,5 +49,6 @@ ifcapable vtab { do_clitest intck01.sql } do_clitest fptest01.sql +do_clitest shell-prompt.sql finish_test From d08caad3a5451a70a31faf8d1dea09db8bb30a9a Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 11 Apr 2026 17:47:31 +0000 Subject: [PATCH 19/19] Fix harmless compiler warnings. FossilOrigin-Name: 3b4cc8d3beab8c910dd954bf8093f7ab499e4690b9cf882f981c4415dd7a7540 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c.in | 8 ++++++-- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 56c8c222eb..ce540d69ac 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Initial\stest\scases\sfor\sthe\sCLI\sprompt\senhancements. -D 2026-04-11T16:12:12.307 +C Fix\sharmless\scompiler\swarnings. +D 2026-04-11T17:47:31.596 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 0007932372e03af8a58060bacbc5cf66ce199b133f41835e28e2cf69eaa4e356 +F src/shell.c.in bed26ce3998b32fde83acbf7f4af3bd9e64902bec6bbfa1a834c9f30497b7231 F src/sqlite.h.in a5605faa9479bbaac16c4ab43eb09ff50632004a8e05084d3fde56063ef73766 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479 F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca @@ -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 8075576ba2324a458440bae398baecc7872b6528574b7fe6681a3a30b62d58ef -R f48e042fefe94b7b0163646f453436c8 +P b7ecc84735d41e9cdb498020b86d8219efa18ca5b40aef1031a14809f1ac2d38 +R 3f3e811020519b37271ba11ee0c7ac4e U drh -Z cc8f78fbdba944ff44e190e2f866d31e +Z 2c87724d0b9b70070b616de7a4951a24 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 08846a02ee..1153d7c031 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b7ecc84735d41e9cdb498020b86d8219efa18ca5b40aef1031a14809f1ac2d38 +3b4cc8d3beab8c910dd954bf8093f7ab499e4690b9cf882f981c4415dd7a7540 diff --git a/src/shell.c.in b/src/shell.c.in index ee3951e9f6..095b666da9 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -1057,7 +1057,10 @@ static char *expand_prompt( }else if( c=='~' ){ const char *zHOME = getenv("HOME"); size_t nHOME = zHOME ? strlen(zHOME) : 0; - if( nHOME0 && nNew<0x7fffffff ); + sqlite3_str_appendchar(pOut, (int)nNew, ' '); len = sqlite3_str_length(pOut); if( len>idxSpace ){ z = sqlite3_str_value(pOut);