From 4926fec967841ca7bea32447a14e29a057cb90a4 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 13 Apr 2016 15:33:42 +0000 Subject: [PATCH] Add the --indent option to the .schema and .fullschema commands in the shell, to enable simple but effective pretty-printing. FossilOrigin-Name: 83cfe82cd6d31ec0a6193525fd92e63a2a43b142 --- manifest | 16 +++---- manifest.uuid | 2 +- src/shell.c | 109 +++++++++++++++++++++++++++++++++++++++++------ test/shell1.test | 2 +- 4 files changed, 106 insertions(+), 23 deletions(-) diff --git a/manifest b/manifest index ef6f2bcf49..fd372f61ab 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Compilation\sfix\sfor\sa\sC99-ism\sin\sthe\s'fts3view'\stool. -D 2016-04-12T19:30:31.230 +C Add\sthe\s--indent\soption\sto\sthe\s.schema\sand\s.fullschema\scommands\sin\sthe\sshell,\nto\senable\ssimple\sbut\seffective\spretty-printing. +D 2016-04-13T15:33:42.000 F Makefile.in eba680121821b8a60940a81454316f47a341487a F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 71b8b16cf9393f68e2e2035486ca104872558836 @@ -376,7 +376,7 @@ F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20 F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e F src/select.c a07e6022e2b559f3c2ec80442472c5965fa7a3fc -F src/shell.c b7922fa264f8c8d72a5ec6dd0b091e15a93c4de5 +F src/shell.c aeaab68456010319cb71406cbaca05865b295154 F src/sqlite.h.in 64eb70a3b309751bebf73a5552a51244f68f0ea5 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 98f72cbfe00169c39089115427d06ea05fe4b4a2 @@ -1051,7 +1051,7 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5 F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e F test/shared_err.test 2f2aee20db294b9924e81f6ccbe60f19e21e8506 F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 -F test/shell1.test b3df199cef9bc722d4078c893a7093d31174ea11 +F test/shell1.test 023657b3f8ba108dbd5ff2ebc8fceb3cf6d4ff9f F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b F test/shell3.test da513d522ef6f01cee8475dcf8332bff8982b3dd F test/shell4.test 69995ee1cc278eb149aa8746ce1f935f4eaf98b9 @@ -1482,7 +1482,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P a18a6ce2271865d04cd75a8a5baa63798b7393db -R d725baf71b4a1cdc4415395863dd2840 -U mistachkin -Z 4008d4d2d72bf9083c3fc9e1b20a35f7 +P bedb88a4b9c808ea781ae69058399a1a3a3d15fa +R 3c29e35f34f5f72131dcf42e4c969859 +U drh +Z 8b78abfa618f6bd7144123bc68122527 diff --git a/manifest.uuid b/manifest.uuid index 42ae789fd7..37449ab981 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bedb88a4b9c808ea781ae69058399a1a3a3d15fa \ No newline at end of file +83cfe82cd6d31ec0a6193525fd92e63a2a43b142 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 001dd6d465..33010e5ff1 100644 --- a/src/shell.c +++ b/src/shell.c @@ -669,6 +669,7 @@ struct ShellState { #define MODE_Csv 7 /* Quote strings, numbers are plain */ #define MODE_Explain 8 /* Like MODE_Column, but do not truncate data */ #define MODE_Ascii 9 /* Use ASCII unit and record separators (0x1F/0x1E) */ +#define MODE_Pretty 10 /* Pretty-print schemas */ static const char *modeDescr[] = { "line", @@ -681,6 +682,7 @@ static const char *modeDescr[] = { "csv", "explain", "ascii", + "prettyprint", }; /* @@ -1054,7 +1056,71 @@ static int shell_callback( } break; } - case MODE_Semi: + case MODE_Semi: { /* .schema and .fullschema output */ + utf8_printf(p->out, "%s;\n", azArg[0]); + break; + } + case MODE_Pretty: { /* .schema and .fullschema with --indent */ + char *z; + int i,j; + int nParen = 0; + char cEnd = 0; + char c; + int nLine = 0; + assert( nArg==1 ); + if( azArg[0]==0 ) break; + if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0 + || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0 + ){ + utf8_printf(p->out, "%s;\n", azArg[0]); + break; + } + z = sqlite3_mprintf("%s", azArg[0]); + j = 0; + for(i=0; IsSpace(z[i]); i++){} + for(; (c = z[i])!=0; i++){ + if( IsSpace(c) ){ + if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue; + }else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){ + j--; + } + z[j++] = c; + } + while( j>0 && IsSpace(z[j-1]) ){ j--; } + z[j] = 0; + if( strlen30(z)>=79 ){ + for(i=j=0; z[i]; i++){ + char c = z[i]; + if( c==cEnd ){ + cEnd = 0; + }else if( c=='"' || c=='\'' || c=='`' ){ + cEnd = c; + }else if( c=='[' ){ + cEnd = ']'; + }else if( c=='(' ){ + nParen++; + }else if( c==')' ){ + nParen--; + if( nLine>0 && nParen==0 && j>0 ){ + utf8_printf(p->out, "%.*s\n", j, z); + j = 0; + } + } + z[j++] = c; + if( nParen==1 && (c=='(' || c==',' || c=='\n') ){ + if( c=='\n' ) j--; + utf8_printf(p->out, "%.*s\n ", j, z); + j = 0; + nLine++; + while( IsSpace(z[i+1]) ){ i++; } + } + } + z[j] = 0; + } + utf8_printf(p->out, "%s;\n", z); + sqlite3_free(z); + break; + } case MODE_List: { if( p->cnt++==0 && p->showHeader ){ for(i=0; iout, "%s", z); if( iout, "%s", p->colSeparator); - }else if( p->cMode==MODE_Semi ){ - utf8_printf(p->out, ";%s", p->rowSeparator); }else{ utf8_printf(p->out, "%s", p->rowSeparator); } @@ -2024,7 +2088,7 @@ static char zHelp[] = ".eqp on|off Enable or disable automatic EXPLAIN QUERY PLAN\n" ".exit Exit this program\n" ".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic\n" - ".fullschema Show schema and the content of sqlite_stat tables\n" + ".fullschema ?--indent? Show schema and the content of sqlite_stat tables\n" ".headers on|off Turn display of headers on or off\n" ".help Show this message\n" ".import FILE TABLE Import data from FILE into TABLE\n" @@ -2060,9 +2124,8 @@ static char zHelp[] = ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n" ".save FILE Write in-memory database into FILE\n" ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off\n" - ".schema ?TABLE? Show the CREATE statements\n" - " If TABLE specified, only show tables matching\n" - " LIKE pattern TABLE.\n" + ".schema ?PATTERN? Show the CREATE statements matching PATTERN\n" + " Add --indent for pretty-printing\n" ".separator COL ?ROW? Change the column separator and optionally the row\n" " separator for both the output mode and .import\n" #if defined(SQLITE_ENABLE_SESSION) @@ -2933,6 +2996,17 @@ static int shellNomemError(void){ return 1; } +/* +** Compare the string as a command-line option with either one or two +** initial "-" characters. +*/ +static int optionMatch(const char *zStr, const char *zOpt){ + if( zStr[0]!='-' ) return 0; + zStr++; + if( zStr[0]=='-' ) zStr++; + return strcmp(zStr, zOpt)==0; +} + /* ** If an input line begins with "." then invoke this routine to ** process that line. @@ -3219,15 +3293,19 @@ static int do_meta_command(char *zLine, ShellState *p){ ShellState data; char *zErrMsg = 0; int doStats = 0; + memcpy(&data, p, sizeof(data)); + data.showHeader = 0; + data.cMode = data.mode = MODE_Semi; + if( nArg==2 && optionMatch(azArg[1], "indent") ){ + data.cMode = data.mode = MODE_Pretty; + nArg = 1; + } if( nArg!=1 ){ - raw_printf(stderr, "Usage: .fullschema\n"); + raw_printf(stderr, "Usage: .fullschema ?--indent?\n"); rc = 1; goto meta_command_exit; } open_db(p, 0); - memcpy(&data, p, sizeof(data)); - data.showHeader = 0; - data.cMode = data.mode = MODE_Semi; rc = sqlite3_exec(p->db, "SELECT sql FROM" " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" @@ -3862,7 +3940,12 @@ static int do_meta_command(char *zLine, ShellState *p){ memcpy(&data, p, sizeof(data)); data.showHeader = 0; data.cMode = data.mode = MODE_Semi; - if( nArg==2 ){ + if( nArg>=2 && optionMatch(azArg[1], "indent") ){ + data.cMode = data.mode = MODE_Pretty; + nArg--; + if( nArg==2 ) azArg[1] = azArg[2]; + } + if( nArg==2 && azArg[1][0]!='-' ){ int i; for(i=0; azArg[1][i]; i++) azArg[1][i] = ToLower(azArg[1][i]); if( strcmp(azArg[1],"sqlite_master")==0 ){ @@ -3917,7 +4000,7 @@ static int do_meta_command(char *zLine, ShellState *p){ callback, &data, &zErrMsg ); }else{ - raw_printf(stderr, "Usage: .schema ?LIKE-PATTERN?\n"); + raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n"); rc = 1; goto meta_command_exit; } diff --git a/test/shell1.test b/test/shell1.test index 9dd0f42093..760c85fadc 100644 --- a/test/shell1.test +++ b/test/shell1.test @@ -568,7 +568,7 @@ do_test shell1-3.21.2 { do_test shell1-3.21.3 { # too many arguments catchcmd "test.db" ".schema FOO BAD" -} {1 {Usage: .schema ?LIKE-PATTERN?}} +} {1 {Usage: .schema ?--indent? ?LIKE-PATTERN?}} do_test shell1-3.21.4 { catchcmd "test.db" { -- 2.47.2