Fossil SCM

Add a link to the [http://fuelscm.org/] project on the Fossil homepage.

drh 2014-12-11 14:59 trunk
Commit 85f265625bc7653657139e3125a2c6d8be2ba497
2 files changed +53 -37 +4
+53 -37
--- src/search.c
+++ src/search.c
@@ -13,27 +13,32 @@
1313
** [email protected]
1414
** http://www.hwaci.com/drh/
1515
**
1616
*******************************************************************************
1717
**
18
-** This file contains code to implement the "/doc" web page and related
19
-** pages.
18
+** This file contains code to implement a very simple search function
19
+** against timeline comments, checkin content, wiki pages, and/or tickets.
20
+**
21
+** The search is full-text like in that it is looking for words and ignores
22
+** punctuation and capitalization. But it is more akin to "grep" in that
23
+** it scans the entire corpus for the search, and it does not support the
24
+** full functionality of FTS4.
2025
*/
2126
#include "config.h"
2227
#include "search.h"
2328
#include <assert.h>
2429
2530
#if INTERFACE
2631
/*
27
-** A compiled search patter
32
+** A compiled search pattern
2833
*/
2934
struct Search {
30
- int nTerm;
31
- struct srchTerm {
32
- char *z;
33
- int n;
34
- } a[8];
35
+ int nTerm; /* Number of search terms */
36
+ struct srchTerm { /* For each search term */
37
+ char *z; /* Text */
38
+ int n; /* length */
39
+ } a[8];
3540
};
3641
#endif
3742
3843
/*
3944
** Compile a search pattern
@@ -98,43 +103,47 @@
98103
** * 10 bonus points if the first occurrence is an exact match
99104
** * 1 additional point for each subsequent match of the same word
100105
** * Extra points of two consecutive words of the pattern are consecutive
101106
** in the document
102107
*/
103
-int search_score(Search *p, const char *zDoc){
108
+int search_score(Search *p, int nDoc, const char **azDoc){
104109
int iPrev = 999;
105110
int score = 10;
106111
int iBonus = 0;
107
- int i, j;
112
+ int i, j, k;
113
+ const char *zDoc;
108114
unsigned char seen[8];
109115
110116
memset(seen, 0, sizeof(seen));
111
- if( zDoc==0 ) return score;
112
- for(i=0; zDoc[i]; i++){
113
- char c = zDoc[i];
114
- if( isBoundary[c&0xff] ) continue;
115
- for(j=0; j<p->nTerm; j++){
116
- int n = p->a[j].n;
117
- if( sqlite3_strnicmp(p->a[j].z, &zDoc[i], n)==0 ){
118
- score += 1;
119
- if( !seen[j] ){
120
- if( isBoundary[zDoc[i+n]&0xff] ) score += 10;
121
- seen[j] = 1;
122
- }
123
- if( j==iPrev+1 ){
124
- score += iBonus;
125
- }
126
- i += n-1;
127
- iPrev = j;
128
- iBonus = 50;
129
- break;
130
- }
131
- }
132
- iBonus /= 2;
133
- while( !isBoundary[zDoc[i]&0xff] ){ i++; }
134
- }
135
-
117
+ for(k=0; k<nDoc; k++){
118
+ zDoc = azDoc[k];
119
+ if( zDoc==0 ) continue;
120
+ for(i=0; zDoc[i]; i++){
121
+ char c = zDoc[i];
122
+ if( isBoundary[c&0xff] ) continue;
123
+ for(j=0; j<p->nTerm; j++){
124
+ int n = p->a[j].n;
125
+ if( sqlite3_strnicmp(p->a[j].z, &zDoc[i], n)==0 ){
126
+ score += 1;
127
+ if( !seen[j] ){
128
+ if( isBoundary[zDoc[i+n]&0xff] ) score += 10;
129
+ seen[j] = 1;
130
+ }
131
+ if( j==iPrev+1 ){
132
+ score += iBonus;
133
+ }
134
+ i += n-1;
135
+ iPrev = j;
136
+ iBonus = 50;
137
+ break;
138
+ }
139
+ }
140
+ iBonus /= 2;
141
+ while( !isBoundary[zDoc[i]&0xff] ){ i++; }
142
+ }
143
+ }
144
+
136145
/* Every term must be seen or else the score is zero */
137146
for(j=0; j<p->nTerm; j++){
138147
if( !seen[j] ) return 0;
139148
}
140149
@@ -149,21 +158,28 @@
149158
sqlite3_context *context,
150159
int argc,
151160
sqlite3_value **argv
152161
){
153162
Search *p = (Search*)sqlite3_user_data(context);
154
- int score = search_score(p, (const char*)sqlite3_value_text(argv[0]));
163
+ conts char **azDoc;
164
+ int score;
165
+ int i;
166
+
167
+ azDoc = fossil_malloc( sizeof(const char*)*(argc+1) );
168
+ for(i=0; i<argc; i++) azDoc[i] = (const char*)sqlite3_value_text(argv[i]);
169
+ score = search_score(p, argc, azDoc);
170
+ fossil_free(azDoc);
155171
sqlite3_result_int(context, score);
156172
}
157173
158174
/*
159175
** Register the "score()" SQL function to score its input text
160176
** using the given Search object. Once this function is registered,
161177
** do not delete the Search object.
162178
*/
163179
void search_sql_setup(Search *p){
164
- sqlite3_create_function(g.db, "score", 1, SQLITE_UTF8, p,
180
+ sqlite3_create_function(g.db, "score", -1, SQLITE_UTF8, p,
165181
search_score_sqlfunc, 0, 0);
166182
}
167183
168184
/*
169185
** Testing the search function.
170186
--- src/search.c
+++ src/search.c
@@ -13,27 +13,32 @@
13 ** [email protected]
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This file contains code to implement the "/doc" web page and related
19 ** pages.
 
 
 
 
 
20 */
21 #include "config.h"
22 #include "search.h"
23 #include <assert.h>
24
25 #if INTERFACE
26 /*
27 ** A compiled search patter
28 */
29 struct Search {
30 int nTerm;
31 struct srchTerm {
32 char *z;
33 int n;
34 } a[8];
35 };
36 #endif
37
38 /*
39 ** Compile a search pattern
@@ -98,43 +103,47 @@
98 ** * 10 bonus points if the first occurrence is an exact match
99 ** * 1 additional point for each subsequent match of the same word
100 ** * Extra points of two consecutive words of the pattern are consecutive
101 ** in the document
102 */
103 int search_score(Search *p, const char *zDoc){
104 int iPrev = 999;
105 int score = 10;
106 int iBonus = 0;
107 int i, j;
 
108 unsigned char seen[8];
109
110 memset(seen, 0, sizeof(seen));
111 if( zDoc==0 ) return score;
112 for(i=0; zDoc[i]; i++){
113 char c = zDoc[i];
114 if( isBoundary[c&0xff] ) continue;
115 for(j=0; j<p->nTerm; j++){
116 int n = p->a[j].n;
117 if( sqlite3_strnicmp(p->a[j].z, &zDoc[i], n)==0 ){
118 score += 1;
119 if( !seen[j] ){
120 if( isBoundary[zDoc[i+n]&0xff] ) score += 10;
121 seen[j] = 1;
122 }
123 if( j==iPrev+1 ){
124 score += iBonus;
125 }
126 i += n-1;
127 iPrev = j;
128 iBonus = 50;
129 break;
130 }
131 }
132 iBonus /= 2;
133 while( !isBoundary[zDoc[i]&0xff] ){ i++; }
134 }
135
 
 
 
136 /* Every term must be seen or else the score is zero */
137 for(j=0; j<p->nTerm; j++){
138 if( !seen[j] ) return 0;
139 }
140
@@ -149,21 +158,28 @@
149 sqlite3_context *context,
150 int argc,
151 sqlite3_value **argv
152 ){
153 Search *p = (Search*)sqlite3_user_data(context);
154 int score = search_score(p, (const char*)sqlite3_value_text(argv[0]));
 
 
 
 
 
 
 
155 sqlite3_result_int(context, score);
156 }
157
158 /*
159 ** Register the "score()" SQL function to score its input text
160 ** using the given Search object. Once this function is registered,
161 ** do not delete the Search object.
162 */
163 void search_sql_setup(Search *p){
164 sqlite3_create_function(g.db, "score", 1, SQLITE_UTF8, p,
165 search_score_sqlfunc, 0, 0);
166 }
167
168 /*
169 ** Testing the search function.
170
--- src/search.c
+++ src/search.c
@@ -13,27 +13,32 @@
13 ** [email protected]
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This file contains code to implement a very simple search function
19 ** against timeline comments, checkin content, wiki pages, and/or tickets.
20 **
21 ** The search is full-text like in that it is looking for words and ignores
22 ** punctuation and capitalization. But it is more akin to "grep" in that
23 ** it scans the entire corpus for the search, and it does not support the
24 ** full functionality of FTS4.
25 */
26 #include "config.h"
27 #include "search.h"
28 #include <assert.h>
29
30 #if INTERFACE
31 /*
32 ** A compiled search pattern
33 */
34 struct Search {
35 int nTerm; /* Number of search terms */
36 struct srchTerm { /* For each search term */
37 char *z; /* Text */
38 int n; /* length */
39 } a[8];
40 };
41 #endif
42
43 /*
44 ** Compile a search pattern
@@ -98,43 +103,47 @@
103 ** * 10 bonus points if the first occurrence is an exact match
104 ** * 1 additional point for each subsequent match of the same word
105 ** * Extra points of two consecutive words of the pattern are consecutive
106 ** in the document
107 */
108 int search_score(Search *p, int nDoc, const char **azDoc){
109 int iPrev = 999;
110 int score = 10;
111 int iBonus = 0;
112 int i, j, k;
113 const char *zDoc;
114 unsigned char seen[8];
115
116 memset(seen, 0, sizeof(seen));
117 for(k=0; k<nDoc; k++){
118 zDoc = azDoc[k];
119 if( zDoc==0 ) continue;
120 for(i=0; zDoc[i]; i++){
121 char c = zDoc[i];
122 if( isBoundary[c&0xff] ) continue;
123 for(j=0; j<p->nTerm; j++){
124 int n = p->a[j].n;
125 if( sqlite3_strnicmp(p->a[j].z, &zDoc[i], n)==0 ){
126 score += 1;
127 if( !seen[j] ){
128 if( isBoundary[zDoc[i+n]&0xff] ) score += 10;
129 seen[j] = 1;
130 }
131 if( j==iPrev+1 ){
132 score += iBonus;
133 }
134 i += n-1;
135 iPrev = j;
136 iBonus = 50;
137 break;
138 }
139 }
140 iBonus /= 2;
141 while( !isBoundary[zDoc[i]&0xff] ){ i++; }
142 }
143 }
144
145 /* Every term must be seen or else the score is zero */
146 for(j=0; j<p->nTerm; j++){
147 if( !seen[j] ) return 0;
148 }
149
@@ -149,21 +158,28 @@
158 sqlite3_context *context,
159 int argc,
160 sqlite3_value **argv
161 ){
162 Search *p = (Search*)sqlite3_user_data(context);
163 conts char **azDoc;
164 int score;
165 int i;
166
167 azDoc = fossil_malloc( sizeof(const char*)*(argc+1) );
168 for(i=0; i<argc; i++) azDoc[i] = (const char*)sqlite3_value_text(argv[i]);
169 score = search_score(p, argc, azDoc);
170 fossil_free(azDoc);
171 sqlite3_result_int(context, score);
172 }
173
174 /*
175 ** Register the "score()" SQL function to score its input text
176 ** using the given Search object. Once this function is registered,
177 ** do not delete the Search object.
178 */
179 void search_sql_setup(Search *p){
180 sqlite3_create_function(g.db, "score", -1, SQLITE_UTF8, p,
181 search_score_sqlfunc, 0, 0);
182 }
183
184 /*
185 ** Testing the search function.
186
--- www/index.wiki
+++ www/index.wiki
@@ -110,10 +110,14 @@
110110
a Fossil repository.
111111
112112
<hr>
113113
<h3>Links For Fossil Users:</h3>
114114
115
+ * "Fuel" is cross-platform GUI front-end for Fossil
116
+ written in Qt. [http://fuelscm.org/].
117
+ Fuel is an independent project run by a different group of
118
+ developers.
115119
* [./reviews.wiki | Testimonials] from satisfied fossil users and
116120
[./quotes.wiki | Quotes] about Fossil and other DVCSes.
117121
* [./faq.wiki | FAQ]
118122
* The [./concepts.wiki | concepts] behind fossil
119123
* [./quickstart.wiki | Quick Start] guide to using fossil
120124
--- www/index.wiki
+++ www/index.wiki
@@ -110,10 +110,14 @@
110 a Fossil repository.
111
112 <hr>
113 <h3>Links For Fossil Users:</h3>
114
 
 
 
 
115 * [./reviews.wiki | Testimonials] from satisfied fossil users and
116 [./quotes.wiki | Quotes] about Fossil and other DVCSes.
117 * [./faq.wiki | FAQ]
118 * The [./concepts.wiki | concepts] behind fossil
119 * [./quickstart.wiki | Quick Start] guide to using fossil
120
--- www/index.wiki
+++ www/index.wiki
@@ -110,10 +110,14 @@
110 a Fossil repository.
111
112 <hr>
113 <h3>Links For Fossil Users:</h3>
114
115 * "Fuel" is cross-platform GUI front-end for Fossil
116 written in Qt. [http://fuelscm.org/].
117 Fuel is an independent project run by a different group of
118 developers.
119 * [./reviews.wiki | Testimonials] from satisfied fossil users and
120 [./quotes.wiki | Quotes] about Fossil and other DVCSes.
121 * [./faq.wiki | FAQ]
122 * The [./concepts.wiki | concepts] behind fossil
123 * [./quickstart.wiki | Quick Start] guide to using fossil
124

Keyboard Shortcuts

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