Fossil SCM
Improvements the "fossil search --fts": Add the --scope and --debug options and improve output formatting.
Commit
b7ef90c71679bfc8366f446d636c7a9d796f50b091d352284832cbe340959673
Parent
eb2100db425fc15…
1 file changed
+60
-4
+60
-4
| --- src/search.c | ||
| +++ src/search.c | ||
| @@ -558,10 +558,28 @@ | ||
| 558 | 558 | sqlite3_create_function(db, "body", 3, enc, 0, |
| 559 | 559 | search_body_sqlfunc, 0, 0); |
| 560 | 560 | sqlite3_create_function(db, "urlencode", 1, enc, 0, |
| 561 | 561 | search_urlencode_sqlfunc, 0, 0); |
| 562 | 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 | + | |
| 563 | 581 | |
| 564 | 582 | /* |
| 565 | 583 | ** Testing the search function. |
| 566 | 584 | ** |
| 567 | 585 | ** COMMAND: search* |
| @@ -583,12 +601,15 @@ | ||
| 583 | 601 | ** returned. The -width option can be used to set the output width used |
| 584 | 602 | ** when printing matches. |
| 585 | 603 | ** |
| 586 | 604 | ** Options: |
| 587 | 605 | ** -a|--all Output all matches, not just best matches |
| 606 | +** --debug Show additional debug content on --fts search | |
| 588 | 607 | ** --fts Use the full-text search mechanism (testing only) |
| 589 | 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. | |
| 590 | 611 | ** -W|--width WIDTH Set display width to WIDTH columns, 0 for |
| 591 | 612 | ** unlimited. Defaults the terminal's width. |
| 592 | 613 | */ |
| 593 | 614 | void search_cmd(void){ |
| 594 | 615 | Blob pattern; |
| @@ -597,10 +618,12 @@ | ||
| 597 | 618 | Stmt q; |
| 598 | 619 | int iBest; |
| 599 | 620 | char fAll = NULL != find_option("all", "a", 0); |
| 600 | 621 | const char *zLimit = find_option("limit","n",1); |
| 601 | 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; | |
| 602 | 625 | int nLimit = zLimit ? atoi(zLimit) : -1000; |
| 603 | 626 | int width; |
| 604 | 627 | int bFts = find_option("fts",0,0)!=0; |
| 605 | 628 | |
| 606 | 629 | if( zWidth ){ |
| @@ -619,12 +642,29 @@ | ||
| 619 | 642 | blob_appendf(&pattern, " %s", g.argv[i]); |
| 620 | 643 | } |
| 621 | 644 | if( bFts ){ |
| 622 | 645 | /* Search using FTS */ |
| 623 | 646 | Blob com; |
| 647 | + Blob snip; | |
| 624 | 648 | 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 | + } | |
| 626 | 666 | search_sql_setup(g.db); |
| 627 | 667 | add_content_sql_commands(g.db); |
| 628 | 668 | db_multi_exec( |
| 629 | 669 | "CREATE TEMP TABLE x(label,url,score,id,date,snip);" |
| 630 | 670 | ); |
| @@ -632,27 +672,43 @@ | ||
| 632 | 672 | search_fullscan(zPattern, srchFlags); /* Full-scan search */ |
| 633 | 673 | }else{ |
| 634 | 674 | search_update_index(srchFlags); /* Update the index */ |
| 635 | 675 | search_indexed(zPattern, srchFlags); /* Indexed search */ |
| 636 | 676 | } |
| 637 | - db_prepare(&q, "SELECT snip, label, score, id, substr(date,1,10)" | |
| 677 | + db_prepare(&q, "SELECT snip, label, score, id, date" | |
| 638 | 678 | " FROM x" |
| 639 | 679 | " ORDER BY score DESC, date DESC;"); |
| 640 | 680 | blob_init(&com, 0, 0); |
| 681 | + blob_init(&snip, 0, 0); | |
| 641 | 682 | if( width<0 ) width = 80; |
| 642 | 683 | while( db_step(&q)==SQLITE_ROW ){ |
| 643 | 684 | const char *zSnippet = db_column_text(&q, 0); |
| 644 | 685 | const char *zLabel = db_column_text(&q, 1); |
| 645 | 686 | const char *zDate = db_column_text(&q, 4); |
| 646 | 687 | const char *zScore = db_column_text(&q, 2); |
| 647 | 688 | 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 | + } | |
| 650 | 700 | comment_print(blob_str(&com), 0, 5, width, |
| 651 | 701 | COMMENT_PRINT_TRIM_CRLF | |
| 702 | + COMMENT_PRINT_WORD_BREAK | | |
| 652 | 703 | COMMENT_PRINT_TRIM_SPACE); |
| 653 | 704 | blob_reset(&com); |
| 705 | + blob_reset(&snip); | |
| 706 | + if( nLimit>=1 ){ | |
| 707 | + nLimit--; | |
| 708 | + if( nLimit==0 ) break; | |
| 709 | + } | |
| 654 | 710 | } |
| 655 | 711 | db_finalize(&q); |
| 656 | 712 | blob_reset(&pattern); |
| 657 | 713 | }else{ |
| 658 | 714 | /* Legacy timeline search (the default) */ |
| 659 | 715 |
| --- 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 |