xapian-core  1.4.31
quest.cc
Go to the documentation of this file.
1 
4 /* Copyright (C) 2004-2026 Olly Betts
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
19  * USA
20  */
21 
22 #include <config.h>
23 
24 #include <xapian.h>
25 
26 #include <cstdlib>
27 #include <cstring>
28 
29 #include <algorithm>
30 #include <iostream>
31 
32 #include "gnu_getopt.h"
33 
34 using namespace std;
35 
36 #define PROG_NAME "quest"
37 #define PROG_DESC "Xapian command line search tool"
38 
39 // Stopwords:
40 static const char * const sw[] = {
41  "a", "about", "an", "and", "are", "as", "at",
42  "be", "by",
43  "en",
44  "for", "from",
45  "how",
46  "i", "in", "is", "it",
47  "of", "on", "or",
48  "that", "the", "this", "to",
49  "was", "what", "when", "where", "which", "who", "why", "will", "with"
50 };
51 
53 struct tab_entry {
54  const char* s;
55 
56  unsigned f;
57 
58  bool operator<(const char* s_) const {
59  return strcmp(s, s_) < 0;
60  }
61 };
62 
68 template<typename T, std::size_t N>
69 static int
70 decode(const T (&table)[N], const char* s)
71 {
72  auto p = lower_bound(begin(table), end(table), s);
73  if (p == end(table) || strcmp(s, p->s) != 0)
74  return -1;
75  return p->f;
76 }
77 
78 static const tab_entry flag_tab[] = {
79  { "accumulate", Xapian::QueryParser::FLAG_ACCUMULATE },
80  { "auto_multiword_synonyms", Xapian::QueryParser::FLAG_AUTO_MULTIWORD_SYNONYMS },
81  { "auto_synonyms", Xapian::QueryParser::FLAG_AUTO_SYNONYMS },
82  { "boolean", Xapian::QueryParser::FLAG_BOOLEAN },
83  { "boolean_any_case", Xapian::QueryParser::FLAG_BOOLEAN_ANY_CASE },
84  { "cjk_ngram", Xapian::QueryParser::FLAG_CJK_NGRAM },
85  { "default", Xapian::QueryParser::FLAG_DEFAULT },
86  { "lovehate", Xapian::QueryParser::FLAG_LOVEHATE },
88  { "no_positions", Xapian::QueryParser::FLAG_NO_POSITIONS },
89  { "partial", Xapian::QueryParser::FLAG_PARTIAL },
91  { "pure_not", Xapian::QueryParser::FLAG_PURE_NOT },
92  { "spelling_correction", Xapian::QueryParser::FLAG_SPELLING_CORRECTION },
93  { "synonym", Xapian::QueryParser::FLAG_SYNONYM },
95 };
96 
97 static const tab_entry default_op_tab[] = {
98  { "and", Xapian::Query::OP_AND },
99  { "elite_set", Xapian::Query::OP_ELITE_SET },
100  { "max", Xapian::Query::OP_MAX },
101  { "near", Xapian::Query::OP_NEAR },
102  { "or", Xapian::Query::OP_OR },
103  { "phrase", Xapian::Query::OP_PHRASE },
104  { "synonym", Xapian::Query::OP_SYNONYM }
105 };
106 
107 enum {
123 };
124 
125 static const tab_entry wt_tab[] = {
126  { "bb2", WEIGHT_BB2 },
127  { "bm25", WEIGHT_BM25 },
128  { "bm25+", WEIGHT_BM25PLUS },
129  { "bool", WEIGHT_BOOL },
130  { "coord", WEIGHT_COORD },
131  { "dlh", WEIGHT_DLH },
132  { "dph", WEIGHT_DPH },
133  { "ifb2", WEIGHT_IFB2 },
134  { "ineb2", WEIGHT_INEB2 },
135  { "inl2", WEIGHT_INL2 },
136  { "lm", WEIGHT_LM },
137  { "pl2", WEIGHT_PL2 },
138  { "pl2+", WEIGHT_PL2PLUS },
139  { "tfidf", WEIGHT_TFIDF },
140  { "trad", WEIGHT_TRAD }
141 };
142 
143 static const tab_entry stem_strategy_tab[] = {
145  { "all_z", Xapian::QueryParser::STEM_ALL_Z },
146  { "none", Xapian::QueryParser::STEM_NONE },
147  { "some", Xapian::QueryParser::STEM_SOME },
148  { "some_full_pos", Xapian::QueryParser::STEM_SOME_FULL_POS }
149 };
150 
155 #define INDENT \
156 " "
157 
162 template<typename T>
163 static char
164 print_table(const T& table)
165 {
166  size_t pos = 256;
167  for (auto& i : table) {
168  size_t len = strlen(i.s);
169  if (pos < 256) cout << ',';
170  if (pos + len >= 78) {
171  cout << "\n" INDENT;
172  pos = sizeof(INDENT) - 2;
173  } else {
174  cout << ' ';
175  }
176  cout << i.s;
177  pos += len + 2;
178  }
179  return '\n';
180 }
181 
183 static char
185 {
186  size_t pos = 256;
187  const string langs = Xapian::Stem::get_available_languages();
188  size_t p = 0;
189  while (p != string::npos) {
190  size_t space = langs.find(' ', p);
191  size_t len = (space != string::npos) ? space - p : langs.size() - p;
192  if (pos < 256) cout << ',';
193  if (pos + len >= 78) {
194  cout << "\n" INDENT;
195  pos = sizeof(INDENT) - 2;
196  } else {
197  cout << ' ';
198  }
199  cout << string(langs.data() + p, len);
200  pos += len + 2;
201  p = space;
202  if (p != string::npos) ++p;
203  }
204  return '\n';
205 }
206 
211 template<typename T>
212 static void
213 list_table(const T& table)
214 {
215  for (auto& i : table) {
216  cout << i.s << '\n';
217  }
218 }
219 
220 static void show_usage() {
221  cout << "Usage: " PROG_NAME " [OPTIONS] 'QUERY'\n"
222 "NB: QUERY should be quoted to protect it from the shell.\n\n"
223 "Options:\n"
224 " -d, --db=DIRECTORY database to search (multiple databases may\n"
225 " be specified)\n"
226 " -m, --msize=MSIZE maximum number of matches to return\n"
227 " -c, --check-at-least=HOWMANY minimum number of matches to check\n"
228 " -s, --stemmer=LANG set the stemming language, the default is\n"
229 " 'english' (pass 'none' to disable stemming).\n"
230 " Valid stemmers:"
231 << print_stemmers() <<
232 " -S, --stem-strategy=STRATEGY set the stemming strategy (default: some).\n"
233 " Valid strategies:"
235 " -p, --prefix=PFX:TERMPFX add a prefix\n"
236 " -b, --boolean-prefix=PFX:TERMPFX add a boolean prefix\n"
237 " -f, --flags=FLAG1[,FLAG2]... specify QueryParser flags (default:\n"
238 " default). Valid flags:"
239 << print_table(flag_tab) <<
240 " -o, --default-op=OP specify QueryParser default operator\n"
241 " (default: or). Valid operators:"
243 " -w, --weight=SCHEME specify weighting scheme to use\n"
244 " (default: bm25). Valid schemes:"
245 << print_table(wt_tab) <<
246 " -F, --freqs show query term frequencies\n"
247 " -h, --help display this help and exit\n"
248 " -v, --version output version information and exit\n";
249 }
250 
251 int
252 main(int argc, char **argv)
253 try {
254  const char * opts = "d:m:c:s:S:p:b:f:o:w:Fhv";
255  static const struct option long_opts[] = {
256  { "db", required_argument, 0, 'd' },
257  { "msize", required_argument, 0, 'm' },
258  { "check-at-least", required_argument, 0, 'c' },
259  { "stemmer", required_argument, 0, 's' },
260  { "stem-strategy", required_argument, 0, 'S' },
261  { "prefix", required_argument, 0, 'p' },
262  { "boolean-prefix", required_argument, 0, 'b' },
263  { "flags", required_argument, 0, 'f' },
264  { "default-op", required_argument, 0, 'o' },
265  { "weight", required_argument, 0, 'w' },
266  { "freqs", no_argument, 0, 'F' },
267  { "help", no_argument, 0, 'h' },
268  { "version", no_argument, 0, 'v' },
269  { NULL, 0, 0, 0}
270  };
271 
272  Xapian::SimpleStopper mystopper(sw, sw + sizeof(sw) / sizeof(sw[0]));
273  Xapian::Stem stemmer("english");
274  Xapian::doccount msize = 10;
275  Xapian::doccount check_at_least = 0;
276 
277  bool have_database = false;
278 
279  Xapian::Database db;
280  Xapian::QueryParser parser;
281  unsigned flags = 0;
282  bool flags_set = false;
283  bool show_termfreqs = false;
284  int weight = -1;
285 
286  int c;
287  while ((c = gnu_getopt_long(argc, argv, opts, long_opts, 0)) != -1) {
288  switch (c) {
289  case 'm': {
290  char * p;
291  unsigned long v = strtoul(optarg, &p, 10);
292  msize = static_cast<Xapian::doccount>(v);
293  if (*p || v != msize) {
294  cerr << PROG_NAME": Bad value '" << optarg
295  << "' passed for msize\n";
296  exit(1);
297  }
298  break;
299  }
300  case 'c': {
301  char * p;
302  unsigned long v = strtoul(optarg, &p, 10);
303  check_at_least = static_cast<Xapian::doccount>(v);
304  if (*p || v != check_at_least) {
305  cerr << PROG_NAME": Bad value '" << optarg
306  << "' passed for check_at_least\n";
307  exit(1);
308  }
309  break;
310  }
311  case 'd':
313  have_database = true;
314  break;
315  case 's':
316  try {
318  } catch (const Xapian::InvalidArgumentError &) {
319  cerr << "Unknown stemming language '" << optarg << "'.\n"
320  "Available language names are: "
322  exit(1);
323  }
324  break;
325  case 'b': case 'p': {
326  const char * colon = strchr(optarg, ':');
327  if (colon == NULL) {
328  cerr << argv[0] << ": need ':' when setting prefix\n";
329  exit(1);
330  }
331  string prefix(optarg, colon - optarg);
332  string termprefix(colon + 1);
333  if (c == 'b') {
334  parser.add_boolean_prefix(prefix, termprefix);
335  } else {
336  parser.add_prefix(prefix, termprefix);
337  }
338  break;
339  }
340  case 'f':
341  flags_set = true;
342  do {
343  char * comma = strchr(optarg, ',');
344  if (comma)
345  *comma++ = '\0';
346  int flag = decode(flag_tab, optarg);
347  if (flag < 0) {
348  cerr << "Unknown flag '" << optarg << "'\n"
349  "Available flags are:\n";
351  exit(1);
352  }
353  flags |= unsigned(flag);
354  optarg = comma;
355  } while (optarg);
356  break;
357  case 'o': {
358  int op = decode(default_op_tab, optarg);
359  if (op < 0) {
360  cerr << "Unknown operator '" << optarg << "'\n"
361  "Available operators are:\n";
363  exit(1);
364  }
365  parser.set_default_op(static_cast<Xapian::Query::op>(op));
366  break;
367  }
368  case 'S': {
369  int s = decode(stem_strategy_tab, optarg);
370  if (s < 0) {
371  cerr << "Unknown stem strategy '" << optarg << "'\n"
372  "Available stem strategies are:\n";
374  exit(1);
375  }
376  auto strategy =
377  static_cast<Xapian::QueryParser::stem_strategy>(s);
378  parser.set_stemming_strategy(strategy);
379  break;
380  }
381  case 'w': {
383  if (weight < 0) {
384  cerr << "Unknown weighting scheme '" << optarg << "'\n";
385  exit(1);
386  }
387  break;
388  }
389  case 'F':
390  show_termfreqs = true;
391  break;
392  case 'v':
393  cout << PROG_NAME " - " PACKAGE_STRING "\n";
394  exit(0);
395  case 'h':
396  cout << PROG_NAME " - " PROG_DESC "\n\n";
397  show_usage();
398  exit(0);
399  case ':': // missing parameter
400  case '?': // unknown option
401  show_usage();
402  exit(1);
403  }
404  }
405 
406  if (argc - optind != 1) {
407  show_usage();
408  exit(1);
409  }
410 
411  parser.set_database(db);
412  parser.set_stemmer(stemmer);
413  parser.set_stopper(&mystopper);
414 
415  if (!flags_set) {
417  }
418  Xapian::Query query = parser.parse_query(argv[optind], flags);
419  const string & correction = parser.get_corrected_query_string();
420  if (!correction.empty())
421  cout << "Did you mean: " << correction << "\n\n";
422 
423  cout << "Parsed Query: " << query.get_description() << '\n';
424 
425  if (!have_database) {
426  cout << "No database specified so not running the query.\n";
427  exit(0);
428  }
429 
430  Xapian::Enquire enquire(db);
431  enquire.set_query(query);
432 
433  switch (weight) {
434  case WEIGHT_BB2:
436  break;
437  case WEIGHT_BOOL:
439  break;
440  case WEIGHT_COORD:
442  break;
443  case WEIGHT_BM25:
445  break;
446  case WEIGHT_BM25PLUS:
448  break;
449  case WEIGHT_DLH:
451  break;
452  case WEIGHT_DPH:
454  break;
455  case WEIGHT_IFB2:
457  break;
458  case WEIGHT_INEB2:
460  break;
461  case WEIGHT_INL2:
463  break;
464  case WEIGHT_LM:
466  break;
467  case WEIGHT_PL2:
469  break;
470  case WEIGHT_PL2PLUS:
472  break;
473  case WEIGHT_TFIDF:
475  break;
476  case WEIGHT_TRAD:
478  break;
479  }
480 
481  Xapian::MSet mset = enquire.get_mset(0, msize, check_at_least);
482 
483  if (show_termfreqs) {
484  cout << "Query term frequencies:\n";
485  for (auto t = query.get_terms_begin();
486  t != query.get_terms_end();
487  ++t) {
488  const string& term = *t;
489  cout << " " << mset.get_termfreq(term) << '\t' << term << '\n';
490  }
491  }
492  auto lower_bound = mset.get_matches_lower_bound();
493  auto estimate = mset.get_matches_estimated();
494  auto upper_bound = mset.get_matches_upper_bound();
495  if (lower_bound == upper_bound) {
496  cout << "Exactly " << estimate << " matches\n";
497  } else {
498  cout << "Between " << lower_bound << " and " << upper_bound
499  << " matches, best estimate is " << estimate << '\n';
500  }
501 
502  cout << "MSet:\n";
503  for (Xapian::MSetIterator i = mset.begin(); i != mset.end(); ++i) {
504  Xapian::Document doc = i.get_document();
505  string data = doc.get_data();
506  cout << *i << ": [" << i.get_weight() << "]\n" << data << "\n";
507  }
508  cout << flush;
509 } catch (const Xapian::QueryParserError & e) {
510  cout << "Couldn't parse query: " << e.get_msg() << '\n';
511  exit(1);
512 } catch (const Xapian::Error & err) {
513  cout << err.get_description() << '\n';
514  exit(1);
515 }
static Xapian::Query query(Xapian::Query::op op, const string &t1=string(), const string &t2=string(), const string &t3=string(), const string &t4=string(), const string &t5=string(), const string &t6=string(), const string &t7=string(), const string &t8=string(), const string &t9=string(), const string &t10=string())
Definition: api_anydb.cc:63
This class implements the BB2 weighting scheme.
Definition: weight.h:1060
Xapian::Weight subclass implementing the BM25+ probabilistic formula.
Definition: weight.h:650
Xapian::Weight subclass implementing the BM25 probabilistic formula.
Definition: weight.h:546
Class implementing a "boolean" weighting scheme.
Definition: weight.h:433
Xapian::Weight subclass implementing Coordinate Matching.
Definition: weight.h:1516
This class implements the DLH weighting scheme, which is a representative scheme of the Divergence fr...
Definition: weight.h:1136
This class implements the DPH weighting scheme.
Definition: weight.h:1359
This class is used to access a database, or a group of databases.
Definition: database.h:68
void add_database(const Database &database)
Add an existing database (or group of databases) to those accessed by this object.
Definition: omdatabase.cc:148
A handle representing a document in a Xapian database.
Definition: document.h:61
std::string get_data() const
Get data stored in the document.
Definition: omdocument.cc:71
This class provides an interface to the information retrieval system for the purpose of searching.
Definition: enquire.h:152
void set_query(const Xapian::Query &query, Xapian::termcount qlen=0)
Set the query to run.
Definition: omenquire.cc:793
MSet get_mset(Xapian::doccount first, Xapian::doccount maxitems, Xapian::doccount checkatleast=0, const RSet *omrset=0, const MatchDecider *mdecider=0) const
Get (a portion of) the match set for the current query.
Definition: omenquire.cc:938
void set_weighting_scheme(const Weight &weight_)
Set the weighting scheme to use for queries.
Definition: omenquire.cc:819
All exceptions thrown by Xapian are subclasses of Xapian::Error.
Definition: error.h:43
const std::string & get_msg() const
Message giving details of the error, intended for human consumption.
Definition: error.h:122
std::string get_description() const
Return a string describing this object.
Definition: error.cc:93
This class implements the IfB2 weighting scheme.
Definition: weight.h:915
This class implements the InL2 weighting scheme.
Definition: weight.h:844
This class implements the IneB2 weighting scheme.
Definition: weight.h:988
InvalidArgumentError indicates an invalid parameter value was passed to the API.
Definition: error.h:241
Xapian::Weight subclass implementing the Language Model formula.
Definition: weight.h:1413
Iterator over a Xapian::MSet.
Definition: mset.h:368
Class representing a list of search results.
Definition: mset.h:44
Xapian::doccount get_termfreq(const std::string &term) const
Get the termfreq of a term.
Definition: omenquire.cc:206
Xapian::doccount get_matches_upper_bound() const
Upper bound on the total number of matching documents.
Definition: omenquire.cc:262
MSetIterator begin() const
Return iterator pointing to the first item in this MSet.
Definition: mset.h:624
Xapian::doccount get_matches_lower_bound() const
Lower bound on the total number of matching documents.
Definition: omenquire.cc:246
MSetIterator end() const
Return iterator pointing to just after the last item in this MSet.
Definition: mset.h:629
Xapian::doccount get_matches_estimated() const
Estimate of the total number of matching documents.
Definition: omenquire.cc:253
Xapian::Weight subclass implementing the PL2+ probabilistic formula.
Definition: weight.h:1263
This class implements the PL2 weighting scheme.
Definition: weight.h:1196
Indicates a query string can't be parsed.
Definition: error.h:887
Build a Xapian::Query object from a user query string.
Definition: queryparser.h:797
void set_database(const Database &db)
Specify the database being searched.
Definition: queryparser.cc:142
void set_stemmer(const Xapian::Stem &stemmer)
Set the stemmer.
Definition: queryparser.cc:85
void set_stemming_strategy(stem_strategy strategy)
Set the stemming strategy.
Definition: queryparser.cc:91
void add_boolean_prefix(const std::string &field, const std::string &prefix, const std::string *grouping=NULL)
Add a boolean term prefix allowing the user to restrict a search with a boolean filter specified in t...
Definition: queryparser.cc:206
void set_default_op(Query::op default_op)
Set the default operator.
Definition: queryparser.cc:103
void set_stopper(const Stopper *stop=NULL)
Set the stopper.
Definition: queryparser.cc:97
std::string get_corrected_query_string() const
Get the spelling-corrected query string.
Definition: queryparser.cc:261
void add_prefix(const std::string &field, const std::string &prefix)
Add a free-text field term prefix.
Definition: queryparser.cc:184
Query parse_query(const std::string &query_string, unsigned flags=FLAG_DEFAULT, const std::string &default_prefix=std::string())
Parse a query.
Definition: queryparser.cc:162
stem_strategy
Stemming strategies, for use with set_stemming_strategy().
Definition: queryparser.h:962
@ FLAG_LOVEHATE
Support + and -.
Definition: queryparser.h:811
@ FLAG_AUTO_SYNONYMS
Enable automatic use of synonyms for single terms.
Definition: queryparser.h:883
@ FLAG_AUTO_MULTIWORD_SYNONYMS
Enable automatic use of synonyms for single terms and groups of terms.
Definition: queryparser.h:890
@ FLAG_NGRAMS
Generate n-grams for scripts without explicit word breaks.
Definition: queryparser.h:914
@ FLAG_ACCUMULATE
Accumulate unstem and stoplist results.
Definition: queryparser.h:938
@ FLAG_CJK_NGRAM
Generate n-grams for scripts without explicit word breaks.
Definition: queryparser.h:923
@ FLAG_DEFAULT
The default flags.
Definition: queryparser.h:958
@ FLAG_BOOLEAN_ANY_CASE
Support AND, OR, etc even if they aren't in ALLCAPS.
Definition: queryparser.h:813
@ FLAG_WILDCARD
Support wildcards.
Definition: queryparser.h:828
@ FLAG_SYNONYM
Enable synonym operator '~'.
Definition: queryparser.h:877
@ FLAG_SPELLING_CORRECTION
Enable spelling correction.
Definition: queryparser.h:871
@ FLAG_PURE_NOT
Allow queries such as 'NOT apples'.
Definition: queryparser.h:835
@ FLAG_NO_POSITIONS
Produce a query which doesn't use positional information.
Definition: queryparser.h:949
@ FLAG_PHRASE
Support quoted phrases.
Definition: queryparser.h:809
@ FLAG_PARTIAL
Enable partial matching.
Definition: queryparser.h:856
@ FLAG_BOOLEAN
Support AND, OR, etc and bracketed subexpressions.
Definition: queryparser.h:807
Class representing a query.
Definition: query.h:56
const TermIterator get_terms_begin() const
Begin iterator for terms in the query object.
Definition: query.cc:135
const TermIterator get_terms_end() const
End iterator for terms in the query object.
Definition: query.h:515
std::string get_description() const
Return a string describing this object.
Definition: query.cc:232
op
Query operators.
Definition: query.h:88
@ OP_MAX
Pick the maximum weight of any subquery.
Definition: query.h:259
@ OP_NEAR
Match only documents where all subqueries match near each other.
Definition: query.h:150
@ OP_ELITE_SET
Pick the best N subqueries and combine with OP_OR.
Definition: query.h:225
@ OP_AND
Match only documents which all subqueries match.
Definition: query.h:94
@ OP_OR
Match documents which at least one subquery matches.
Definition: query.h:102
@ OP_PHRASE
Match only documents where all subqueries match near and in order.
Definition: query.h:162
@ OP_SYNONYM
Match like OP_OR but weighting as if a single term.
Definition: query.h:249
Simple implementation of Stopper class - this will suit most users.
Definition: queryparser.h:100
Class representing a stemming algorithm.
Definition: stem.h:62
static std::string get_available_languages()
Return a list of available languages.
Definition: stem.h:185
Xapian::Weight subclass implementing the tf-idf weighting scheme.
Definition: weight.h:458
Xapian::Weight subclass implementing the traditional probabilistic formula.
Definition: weight.h:774
#define PACKAGE_STRING
Definition: config.h:340
int optind
Definition: getopt.cc:94
char * optarg
Definition: getopt.cc:79
Wrappers to allow GNU getopt to be used cleanly from C++ code.
#define no_argument
Definition: gnu_getopt.h:79
#define required_argument
Definition: gnu_getopt.h:80
int gnu_getopt_long(int argc_, char *const *argv_, const char *shortopts_, const struct option *longopts_, int *optind_)
Definition: gnu_getopt.h:97
unsigned XAPIAN_DOCID_BASE_TYPE doccount
A count of documents.
Definition: types.h:38
double weight
The weight of a document or term.
Definition: types.h:122
@ WEIGHT_PL2PLUS
Definition: quest.cc:120
@ WEIGHT_PL2
Definition: quest.cc:119
@ WEIGHT_COORD
Definition: quest.cc:112
@ WEIGHT_BM25PLUS
Definition: quest.cc:110
@ WEIGHT_INEB2
Definition: quest.cc:116
@ WEIGHT_IFB2
Definition: quest.cc:115
@ WEIGHT_LM
Definition: quest.cc:118
@ WEIGHT_DPH
Definition: quest.cc:114
@ WEIGHT_BM25
Definition: quest.cc:109
@ WEIGHT_INL2
Definition: quest.cc:117
@ WEIGHT_BOOL
Definition: quest.cc:111
@ WEIGHT_TFIDF
Definition: quest.cc:121
@ WEIGHT_TRAD
Definition: quest.cc:122
@ WEIGHT_DLH
Definition: quest.cc:113
@ WEIGHT_BB2
Definition: quest.cc:108
static void list_table(const T &table)
List strings from a string to integer mapping table, one per line.
Definition: quest.cc:213
static char print_stemmers()
Print available stemmers, line wrapped.
Definition: quest.cc:184
static void show_usage()
Definition: quest.cc:220
static char print_table(const T &table)
Print strings from a string to integer mapping table.
Definition: quest.cc:164
int main(int argc, char **argv)
Definition: quest.cc:252
#define PROG_NAME
Definition: quest.cc:36
static const char *const sw[]
Definition: quest.cc:40
#define INDENT
The number of spaces to indent by in print_table.
Definition: quest.cc:155
static const tab_entry flag_tab[]
Definition: quest.cc:78
static const tab_entry wt_tab[]
Definition: quest.cc:125
static int decode(const T(&table)[N], const char *s)
Decode a string to an integer.
Definition: quest.cc:70
#define PROG_DESC
Definition: quest.cc:37
static const tab_entry stem_strategy_tab[]
Definition: quest.cc:143
static const tab_entry default_op_tab[]
Definition: quest.cc:97
static Xapian::Stem stemmer
Definition: stemtest.cc:42
int * flag
Definition: gnu_getopt.h:75
Common string to integer map entry for option decoding.
Definition: quest.cc:53
const char * s
Definition: quest.cc:54
unsigned f
Definition: quest.cc:56
bool operator<(const char *s_) const
Definition: quest.cc:58
static const char * opts
static const struct option long_opts[]
Public interfaces for the Xapian library.