Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Teach the CLI that VT100-escape codes that do things like change font colors have zero-width for the purpose of laying out the columns of a table. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
2d0a8a6c38981552748ff5fc2eeba865 |
User & Date: | drh 2025-03-21 18:15:13.290 |
Context
2025-03-21
| ||
21:13 | Fix a multi-arg expr call in proj-current-proc-name (must be single-arg for portability). (check-in: 914768f3f5 user: stephan tags: trunk) | |
18:15 | Teach the CLI that VT100-escape codes that do things like change font colors have zero-width for the purpose of laying out the columns of a table. (check-in: 2d0a8a6c38 user: drh tags: trunk) | |
16:49 | Flesh out the new proc-debug and its infrastructure a bit. (check-in: ba7f1ff0d7 user: stephan tags: trunk) | |
Changes
Changes to src/shell.c.in.
︙ | ︙ | |||
779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 | }else{ i++; } } return n; } #endif /* ** Output string zUtf to stdout as w characters. If w is negative, ** then right-justify the text. W is the width in UTF-8 characters, not ** in bytes. This is different from the %*.*s specification in printf ** since with %*.*s the width is measured in bytes, not characters. ** ** Take into account zero-width and double-width Unicode characters. ** In other words, a zero-width character does not count toward the ** the w limit. A double-width character counts as two. */ static void utf8_width_print(FILE *out, int w, const char *zUtf){ const unsigned char *a = (const unsigned char*)zUtf; unsigned char c; int i = 0; int n = 0; int aw = w<0 ? -w : w; if( zUtf==0 ) zUtf = ""; while( (c = a[i])!=0 ){ if( (c&0xc0)==0xc0 ){ int u; int len = decodeUtf8(a+i, &u); int x = cli_wcwidth(u); if( x+n>aw ){ break; } i += len; n += x; }else if( n>=aw ){ break; }else{ n++; i++; } } | > > > > > > > > > > > > > > > > > > > > | 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 | }else{ i++; } } return n; } #endif /* ** Check to see if z[] is a valid VT100 escape. If it is, then ** return the number of bytes in the escape sequence. Return 0 if ** z[] is not a VT100 escape. ** ** This routine assumes that z[0] is \033 (ESC). */ static int isVt100(const unsigned char *z){ int i; if( z[1]!='[' ) return 0; i = 2; while( z[i]>=0x30 && z[i]<=0x3f ){ i++; } while( z[i]>=0x20 && z[i]<=0x2f ){ i++; } if( z[i]<0x40 || z[i]>0x7e ) return 0; return i+1; } /* ** Output string zUtf to stdout as w characters. If w is negative, ** then right-justify the text. W is the width in UTF-8 characters, not ** in bytes. This is different from the %*.*s specification in printf ** since with %*.*s the width is measured in bytes, not characters. ** ** Take into account zero-width and double-width Unicode characters. ** In other words, a zero-width character does not count toward the ** the w limit. A double-width character counts as two. */ static void utf8_width_print(FILE *out, int w, const char *zUtf){ const unsigned char *a = (const unsigned char*)zUtf; unsigned char c; int i = 0; int n = 0; int k; int aw = w<0 ? -w : w; if( zUtf==0 ) zUtf = ""; while( (c = a[i])!=0 ){ if( (c&0xc0)==0xc0 ){ int u; int len = decodeUtf8(a+i, &u); int x = cli_wcwidth(u); if( x+n>aw ){ break; } i += len; n += x; }else if( c==0x1b && (k = isVt100(&a[i]))>0 ){ i += k; }else if( n>=aw ){ break; }else{ n++; i++; } } |
︙ | ︙ | |||
3994 3995 3996 3997 3998 3999 4000 | do{ n++; j++; }while( (n&7)!=0 && n<mxWidth ); i++; continue; } | > > > > | | | > | 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 | do{ n++; j++; }while( (n&7)!=0 && n<mxWidth ); i++; continue; } if( c==0x1b && p->eEscMode==SHELL_ESC_OFF && (k = isVt100(&z[i]))>0 ){ i += k; j += k; }else{ n++; j += 3; i++; } } if( n>=mxWidth && bWordWrap ){ /* Perhaps try to back up to a better place to break the line */ for(k=i; k>i/2; k--){ if( IsSpace(z[k-1]) ) break; } if( k<=i/2 ){ |
︙ | ︙ | |||
4062 4063 4064 4065 4066 4067 4068 | zOut[j++] = 0x90; zOut[j++] = 0x80 + c; break; case SHELL_ESC_ASCII: zOut[j++] = '^'; zOut[j++] = 0x40 + c; break; | | > > > > > > | > > | 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 | zOut[j++] = 0x90; zOut[j++] = 0x80 + c; break; case SHELL_ESC_ASCII: zOut[j++] = '^'; zOut[j++] = 0x40 + c; break; case SHELL_ESC_OFF: { int nn; if( c==0x1b && (nn = isVt100(&z[i]))>0 ){ memcpy(&zOut[j], &z[i], nn); j += nn; i += nn - 1; }else{ zOut[j++] = c; } break; } } i++; } zOut[j] = 0; return (char*)zOut; } |
︙ | ︙ |
Added test/vt100-a.sql.
> > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ** Run this script using the "sqlite3" command-line shell ** test test formatting of output text that contains ** vt100 escape sequences. */ .mode box -escape off CREATE TEMP TABLE t1(a,b,c); INSERT INTO t1 VALUES ('one','twotwotwo','thirty-three'), (unistr('\u001b[91mRED\u001b[0m'),'fourfour','fifty-five'), ('six','seven','eighty-eight'); .print With -escape off SELECT * FROM t1; .mode box -escape ascii .print With -escape ascii SELECT * FROM t1; .mode box -escape symbol .print With -escape symbol SELECT * FROM t1; |