Fossil SCM

Improvements the "fossil search --fts": Add the --scope and --debug options and improve output formatting.

drh 2024-01-09 17:05 trunk
Commit b7ef90c71679bfc8366f446d636c7a9d796f50b091d352284832cbe340959673
1 file changed +60 -4
+60 -4
--- src/search.c
+++ src/search.c
@@ -558,10 +558,28 @@
558558
sqlite3_create_function(db, "body", 3, enc, 0,
559559
search_body_sqlfunc, 0, 0);
560560
sqlite3_create_function(db, "urlencode", 1, enc, 0,
561561
search_urlencode_sqlfunc, 0, 0);
562562
}
563
+
564
+/*
565
+** Search scope abbreviations and names.
566
+*/
567
+static const struct {
568
+ const char *z;
569
+ const char *zNm;
570
+ unsigned m;
571
+} aScope[] = {
572
+ { "all", "All", SRCH_ALL },
573
+ { "c", "Check-ins", SRCH_CKIN },
574
+ { "d", "Docs", SRCH_DOC },
575
+ { "t", "Tickets", SRCH_TKT },
576
+ { "w", "Wiki", SRCH_WIKI },
577
+ { "e", "Tech Notes", SRCH_TECHNOTE },
578
+ { "f", "Forum", SRCH_FORUM },
579
+};
580
+
563581
564582
/*
565583
** Testing the search function.
566584
**
567585
** COMMAND: search*
@@ -583,12 +601,15 @@
583601
** returned. The -width option can be used to set the output width used
584602
** when printing matches.
585603
**
586604
** Options:
587605
** -a|--all Output all matches, not just best matches
606
+** --debug Show additional debug content on --fts search
588607
** --fts Use the full-text search mechanism (testing only)
589608
** -n|--limit N Limit output to N matches
609
+** --scope SCOPE Scope of search. Valid for --fts only. One or
610
+** more of: all, c, d, e, f, t, w. Defaults to all.
590611
** -W|--width WIDTH Set display width to WIDTH columns, 0 for
591612
** unlimited. Defaults the terminal's width.
592613
*/
593614
void search_cmd(void){
594615
Blob pattern;
@@ -597,10 +618,12 @@
597618
Stmt q;
598619
int iBest;
599620
char fAll = NULL != find_option("all", "a", 0);
600621
const char *zLimit = find_option("limit","n",1);
601622
const char *zWidth = find_option("width","W",1);
623
+ const char *zScope = find_option("scope",0,1);
624
+ int bDebug = find_option("debug",0,0)!=0;
602625
int nLimit = zLimit ? atoi(zLimit) : -1000;
603626
int width;
604627
int bFts = find_option("fts",0,0)!=0;
605628
606629
if( zWidth ){
@@ -619,12 +642,29 @@
619642
blob_appendf(&pattern, " %s", g.argv[i]);
620643
}
621644
if( bFts ){
622645
/* Search using FTS */
623646
Blob com;
647
+ Blob snip;
624648
const char *zPattern = blob_str(&pattern);
625
- int srchFlags = SRCH_ALL;
649
+ int srchFlags;
650
+ if( zScope==0 ){
651
+ srchFlags = SRCH_ALL;
652
+ }else{
653
+ srchFlags = 0;
654
+ for(i=0; zScope[i]; i++){
655
+ switch( zScope[i] ){
656
+ case 'a': srchFlags = SRCH_ALL; break;
657
+ case 'c': srchFlags |= SRCH_CKIN; break;
658
+ case 'd': srchFlags |= SRCH_DOC; break;
659
+ case 'e': srchFlags |= SRCH_TECHNOTE; break;
660
+ case 'f': srchFlags |= SRCH_FORUM; break;
661
+ case 't': srchFlags |= SRCH_TKT; break;
662
+ case 'w': srchFlags |= SRCH_WIKI; break;
663
+ }
664
+ }
665
+ }
626666
search_sql_setup(g.db);
627667
add_content_sql_commands(g.db);
628668
db_multi_exec(
629669
"CREATE TEMP TABLE x(label,url,score,id,date,snip);"
630670
);
@@ -632,27 +672,43 @@
632672
search_fullscan(zPattern, srchFlags); /* Full-scan search */
633673
}else{
634674
search_update_index(srchFlags); /* Update the index */
635675
search_indexed(zPattern, srchFlags); /* Indexed search */
636676
}
637
- db_prepare(&q, "SELECT snip, label, score, id, substr(date,1,10)"
677
+ db_prepare(&q, "SELECT snip, label, score, id, date"
638678
" FROM x"
639679
" ORDER BY score DESC, date DESC;");
640680
blob_init(&com, 0, 0);
681
+ blob_init(&snip, 0, 0);
641682
if( width<0 ) width = 80;
642683
while( db_step(&q)==SQLITE_ROW ){
643684
const char *zSnippet = db_column_text(&q, 0);
644685
const char *zLabel = db_column_text(&q, 1);
645686
const char *zDate = db_column_text(&q, 4);
646687
const char *zScore = db_column_text(&q, 2);
647688
const char *zId = db_column_text(&q, 3);
648
- blob_appendf(&com, "%s\n%s\n%s score=%s id=%d", zLabel, zSnippet,
649
- zDate, zScore, zId);
689
+ blob_appendf(&snip, "%s", zSnippet);
690
+ for(i=0; i<snip.nUsed; i++){
691
+ if( snip.aData[i]=='\n' ){
692
+ if( i>0 && snip.aData[i-1]=='\r' ) snip.aData[i-1] = ' ';
693
+ snip.aData[i] = ' ';
694
+ }
695
+ }
696
+ blob_appendf(&com, "%s\n%s\n%s", zLabel, blob_str(&snip), zDate);
697
+ if( bDebug ){
698
+ blob_appendf(&com," score: %s id: %s", zScore, zId);
699
+ }
650700
comment_print(blob_str(&com), 0, 5, width,
651701
COMMENT_PRINT_TRIM_CRLF |
702
+ COMMENT_PRINT_WORD_BREAK |
652703
COMMENT_PRINT_TRIM_SPACE);
653704
blob_reset(&com);
705
+ blob_reset(&snip);
706
+ if( nLimit>=1 ){
707
+ nLimit--;
708
+ if( nLimit==0 ) break;
709
+ }
654710
}
655711
db_finalize(&q);
656712
blob_reset(&pattern);
657713
}else{
658714
/* Legacy timeline search (the default) */
659715
--- src/search.c
+++ src/search.c
@@ -558,10 +558,28 @@
558 sqlite3_create_function(db, "body", 3, enc, 0,
559 search_body_sqlfunc, 0, 0);
560 sqlite3_create_function(db, "urlencode", 1, enc, 0,
561 search_urlencode_sqlfunc, 0, 0);
562 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
563
564 /*
565 ** Testing the search function.
566 **
567 ** COMMAND: search*
@@ -583,12 +601,15 @@
583 ** returned. The -width option can be used to set the output width used
584 ** when printing matches.
585 **
586 ** Options:
587 ** -a|--all Output all matches, not just best matches
 
588 ** --fts Use the full-text search mechanism (testing only)
589 ** -n|--limit N Limit output to N matches
 
 
590 ** -W|--width WIDTH Set display width to WIDTH columns, 0 for
591 ** unlimited. Defaults the terminal's width.
592 */
593 void search_cmd(void){
594 Blob pattern;
@@ -597,10 +618,12 @@
597 Stmt q;
598 int iBest;
599 char fAll = NULL != find_option("all", "a", 0);
600 const char *zLimit = find_option("limit","n",1);
601 const char *zWidth = find_option("width","W",1);
 
 
602 int nLimit = zLimit ? atoi(zLimit) : -1000;
603 int width;
604 int bFts = find_option("fts",0,0)!=0;
605
606 if( zWidth ){
@@ -619,12 +642,29 @@
619 blob_appendf(&pattern, " %s", g.argv[i]);
620 }
621 if( bFts ){
622 /* Search using FTS */
623 Blob com;
 
624 const char *zPattern = blob_str(&pattern);
625 int srchFlags = SRCH_ALL;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
626 search_sql_setup(g.db);
627 add_content_sql_commands(g.db);
628 db_multi_exec(
629 "CREATE TEMP TABLE x(label,url,score,id,date,snip);"
630 );
@@ -632,27 +672,43 @@
632 search_fullscan(zPattern, srchFlags); /* Full-scan search */
633 }else{
634 search_update_index(srchFlags); /* Update the index */
635 search_indexed(zPattern, srchFlags); /* Indexed search */
636 }
637 db_prepare(&q, "SELECT snip, label, score, id, substr(date,1,10)"
638 " FROM x"
639 " ORDER BY score DESC, date DESC;");
640 blob_init(&com, 0, 0);
 
641 if( width<0 ) width = 80;
642 while( db_step(&q)==SQLITE_ROW ){
643 const char *zSnippet = db_column_text(&q, 0);
644 const char *zLabel = db_column_text(&q, 1);
645 const char *zDate = db_column_text(&q, 4);
646 const char *zScore = db_column_text(&q, 2);
647 const char *zId = db_column_text(&q, 3);
648 blob_appendf(&com, "%s\n%s\n%s score=%s id=%d", zLabel, zSnippet,
649 zDate, zScore, zId);
 
 
 
 
 
 
 
 
 
650 comment_print(blob_str(&com), 0, 5, width,
651 COMMENT_PRINT_TRIM_CRLF |
 
652 COMMENT_PRINT_TRIM_SPACE);
653 blob_reset(&com);
 
 
 
 
 
654 }
655 db_finalize(&q);
656 blob_reset(&pattern);
657 }else{
658 /* Legacy timeline search (the default) */
659
--- src/search.c
+++ src/search.c
@@ -558,10 +558,28 @@
558 sqlite3_create_function(db, "body", 3, enc, 0,
559 search_body_sqlfunc, 0, 0);
560 sqlite3_create_function(db, "urlencode", 1, enc, 0,
561 search_urlencode_sqlfunc, 0, 0);
562 }
563
564 /*
565 ** Search scope abbreviations and names.
566 */
567 static const struct {
568 const char *z;
569 const char *zNm;
570 unsigned m;
571 } aScope[] = {
572 { "all", "All", SRCH_ALL },
573 { "c", "Check-ins", SRCH_CKIN },
574 { "d", "Docs", SRCH_DOC },
575 { "t", "Tickets", SRCH_TKT },
576 { "w", "Wiki", SRCH_WIKI },
577 { "e", "Tech Notes", SRCH_TECHNOTE },
578 { "f", "Forum", SRCH_FORUM },
579 };
580
581
582 /*
583 ** Testing the search function.
584 **
585 ** COMMAND: search*
@@ -583,12 +601,15 @@
601 ** returned. The -width option can be used to set the output width used
602 ** when printing matches.
603 **
604 ** Options:
605 ** -a|--all Output all matches, not just best matches
606 ** --debug Show additional debug content on --fts search
607 ** --fts Use the full-text search mechanism (testing only)
608 ** -n|--limit N Limit output to N matches
609 ** --scope SCOPE Scope of search. Valid for --fts only. One or
610 ** more of: all, c, d, e, f, t, w. Defaults to all.
611 ** -W|--width WIDTH Set display width to WIDTH columns, 0 for
612 ** unlimited. Defaults the terminal's width.
613 */
614 void search_cmd(void){
615 Blob pattern;
@@ -597,10 +618,12 @@
618 Stmt q;
619 int iBest;
620 char fAll = NULL != find_option("all", "a", 0);
621 const char *zLimit = find_option("limit","n",1);
622 const char *zWidth = find_option("width","W",1);
623 const char *zScope = find_option("scope",0,1);
624 int bDebug = find_option("debug",0,0)!=0;
625 int nLimit = zLimit ? atoi(zLimit) : -1000;
626 int width;
627 int bFts = find_option("fts",0,0)!=0;
628
629 if( zWidth ){
@@ -619,12 +642,29 @@
642 blob_appendf(&pattern, " %s", g.argv[i]);
643 }
644 if( bFts ){
645 /* Search using FTS */
646 Blob com;
647 Blob snip;
648 const char *zPattern = blob_str(&pattern);
649 int srchFlags;
650 if( zScope==0 ){
651 srchFlags = SRCH_ALL;
652 }else{
653 srchFlags = 0;
654 for(i=0; zScope[i]; i++){
655 switch( zScope[i] ){
656 case 'a': srchFlags = SRCH_ALL; break;
657 case 'c': srchFlags |= SRCH_CKIN; break;
658 case 'd': srchFlags |= SRCH_DOC; break;
659 case 'e': srchFlags |= SRCH_TECHNOTE; break;
660 case 'f': srchFlags |= SRCH_FORUM; break;
661 case 't': srchFlags |= SRCH_TKT; break;
662 case 'w': srchFlags |= SRCH_WIKI; break;
663 }
664 }
665 }
666 search_sql_setup(g.db);
667 add_content_sql_commands(g.db);
668 db_multi_exec(
669 "CREATE TEMP TABLE x(label,url,score,id,date,snip);"
670 );
@@ -632,27 +672,43 @@
672 search_fullscan(zPattern, srchFlags); /* Full-scan search */
673 }else{
674 search_update_index(srchFlags); /* Update the index */
675 search_indexed(zPattern, srchFlags); /* Indexed search */
676 }
677 db_prepare(&q, "SELECT snip, label, score, id, date"
678 " FROM x"
679 " ORDER BY score DESC, date DESC;");
680 blob_init(&com, 0, 0);
681 blob_init(&snip, 0, 0);
682 if( width<0 ) width = 80;
683 while( db_step(&q)==SQLITE_ROW ){
684 const char *zSnippet = db_column_text(&q, 0);
685 const char *zLabel = db_column_text(&q, 1);
686 const char *zDate = db_column_text(&q, 4);
687 const char *zScore = db_column_text(&q, 2);
688 const char *zId = db_column_text(&q, 3);
689 blob_appendf(&snip, "%s", zSnippet);
690 for(i=0; i<snip.nUsed; i++){
691 if( snip.aData[i]=='\n' ){
692 if( i>0 && snip.aData[i-1]=='\r' ) snip.aData[i-1] = ' ';
693 snip.aData[i] = ' ';
694 }
695 }
696 blob_appendf(&com, "%s\n%s\n%s", zLabel, blob_str(&snip), zDate);
697 if( bDebug ){
698 blob_appendf(&com," score: %s id: %s", zScore, zId);
699 }
700 comment_print(blob_str(&com), 0, 5, width,
701 COMMENT_PRINT_TRIM_CRLF |
702 COMMENT_PRINT_WORD_BREAK |
703 COMMENT_PRINT_TRIM_SPACE);
704 blob_reset(&com);
705 blob_reset(&snip);
706 if( nLimit>=1 ){
707 nLimit--;
708 if( nLimit==0 ) break;
709 }
710 }
711 db_finalize(&q);
712 blob_reset(&pattern);
713 }else{
714 /* Legacy timeline search (the default) */
715

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button