From: drh <> Date: Thu, 9 Apr 2026 23:37:48 +0000 (+0000) Subject: A prototype of code that shows how to expand backslash escapes in the X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=850104bbad3627b868b2588de0d7a99a4ee6c487;p=thirdparty%2Fsqlite.git A prototype of code that shows how to expand backslash escapes in the CLI prompt. FossilOrigin-Name: 9cf28959671920b4909521bb1db6f0cbbc85448fbf3594c43b4000505b4e055b --- 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; }