1st full version of aspell support

This commit is contained in:
dockes
2006-10-11 14:16:26 +00:00
parent 9fe5404390
commit 99372e587b
25 changed files with 975 additions and 145 deletions
+106 -50
View File
@@ -1,17 +1,24 @@
#ifndef TEST_RCLASPELL
#ifndef lint
static char rcsid[] = "@(#$Id: rclaspell.cpp,v 1.2 2006-10-09 16:37:08 dockes Exp $ (C) 2006 J.F.Dockes";
static char rcsid[] = "@(#$Id: rclaspell.cpp,v 1.3 2006-10-11 14:16:25 dockes Exp $ (C) 2006 J.F.Dockes";
#endif
#ifdef HAVE_CONFIG_H
#include "autoconfig.h"
#endif
#ifdef RCL_USE_ASPELL
#include <unistd.h>
#include <dlfcn.h>
#include <iostream>
#include "aspell.h"
#include ASPELL_INCLUDE
#include "pathut.h"
#include "execmd.h"
#include "rclaspell.h"
// Stuff that we don't wish to see in the .h (possible sysdeps, etc.)
class AspellData {
public:
AspellData() : m_handle(0) {}
@@ -62,22 +69,54 @@ static AspellApi aapi;
badnames += #NM + string(" "); \
}
bool Aspell::init(const string &basedir, string &reason)
const char *aspell_progs[] = {
#ifdef ASPELL_PROG
ASPELL_PROG ,
#endif
"/usr/local/bin/aspell",
"/usr/bin/aspell"
};
bool Aspell::init(string &reason)
{
if (m_data == 0)
m_data = new AspellData;
if (m_data->m_handle) {
dlclose(m_data->m_handle);
m_data->m_handle = 0;
delete m_data;
m_data = 0;
// Language: we get this from the configuration, else from the NLS
// environment. The aspell language names used for selecting language
// definition files (used to create dictionaries) are like en, fr
if (!m_config->getConfParam("aspellLanguage", m_lang)) {
string lang = "en";
const char *cp;
if (cp = getenv("LC_ALL"))
lang = cp;
else if (cp = getenv("LANG"))
lang = cp;
if (!lang.compare("C"))
lang = "en";
m_lang = lang.substr(0, lang.find_first_of("_"));
} else {
if (!m_lang.compare("disable")) {
reason = "Aspell disabled in recoll configuration file";
return false;
}
}
m_data->m_exec = path_cat(basedir, "bin");
m_data->m_exec = path_cat(m_data->m_exec, "aspell");
if (access(m_data->m_exec.c_str(), X_OK) != 0) {
reason = m_data->m_exec + " not found or not executable";
m_data = new AspellData;
for (unsigned int i = 0; i < sizeof(aspell_progs) / sizeof(char*); i++) {
if (access(aspell_progs[i], X_OK) == 0) {
m_data->m_exec = aspell_progs[i];
break;
}
}
if (m_data->m_exec.empty()) {
reason = "aspell program not found or not executable";
return false;
}
string lib = path_cat(basedir, "lib");
// For now, the aspell library has to live under the same prefix as the
// aspell program.
string aspellPrefix = path_getfather(path_getfather(m_data->m_exec));
string lib = path_cat(aspellPrefix, "lib");
lib = path_cat(lib, "libaspell.so");
if ((m_data->m_handle = dlopen(lib.c_str(), RTLD_LAZY)) == 0) {
reason = "Could not open shared library [";
@@ -120,6 +159,7 @@ bool Aspell::init(const string &basedir, string &reason)
reason = string("Aspell::init: symbols not found:") + badnames;
return false;
}
return true;
}
@@ -130,51 +170,58 @@ bool Aspell::ok()
string Aspell::dicPath()
{
return path_cat(m_conf->getConfDir(),
return path_cat(m_config->getConfDir(),
string("aspdict.") + m_lang + string(".rws"));
}
bool Aspell::buildDict(Rcl::Db &db, string &reason)
{
string term;
if (!ok())
return false;
// Il faut nettoyer la liste, peut-etre faire un tri unique (verifier),
// puis construire le dico
Rcl::TermIter *tit = db.termWalkOpen();
if (tit == 0) {
reason = "termWalkOpen failed\n";
return false;
}
ExecCmd aspell;
list<string> args;
// aspell --lang=[lang] create master [dictApath]
args.push_back(string("--lang=")+ m_lang);
args.push_back("create");
args.push_back("master");
args.push_back(dicPath());
// aspell.setStderr("/dev/null");
string allterms;
while (db.termWalkNext(tit, term)) {
// Filter out terms beginning with upper case (special stuff) and
// containing numbers
if (term.empty())
continue;
if ('A' <= term.at(0) && term.at(0) <= 'Z')
continue;
if (term.find_first_of("0123456789+-._@") != string::npos)
continue;
allterms += term + "\n";
// std::cout << "[" << term << "]" << std::endl;
}
db.termWalkClose(tit);
aspell.doexec(m_data->m_exec, args, &allterms);
return true;
// We create the dictionary by executing the aspell command:
// aspell --lang=[lang] create master [dictApath]
ExecCmd aspell;
list<string> args;
args.push_back(string("--lang=")+ m_lang);
args.push_back("create");
args.push_back("master");
args.push_back(dicPath());
aspell.setStderr("/dev/null");
Rcl::TermIter *tit = db.termWalkOpen();
if (tit == 0) {
reason = "termWalkOpen failed\n";
return false;
}
string allterms, term;
while (db.termWalkNext(tit, term)) {
// Filter out terms beginning with upper case (special stuff) and
// containing numbers
if (term.empty())
continue;
if ('A' <= term.at(0) && term.at(0) <= 'Z')
continue;
if (term.find_first_of("0123456789+-._@") != string::npos)
continue;
allterms += term + "\n";
// std::cout << "[" << term << "]" << std::endl;
}
db.termWalkClose(tit);
if (aspell.doexec(m_data->m_exec, args, &allterms)) {
reason = string("aspell dictionary creation command failed. Check the language data files for lang = ") + m_lang;
return false;
}
return true;
}
bool Aspell::suggest(Rcl::Db &db,
string &term, list<string> &suggestions, string &reason)
{
if (!ok())
return false;
AspellCanHaveError *ret;
AspellSpeller *speller;
AspellConfig *config;
@@ -221,9 +268,16 @@ bool Aspell::suggest(Rcl::Db &db,
return true;
}
#endif // RCL_USE_ASPELL
#else // TEST_RCLASPELL test driver ->
#ifdef HAVE_CONFIG_H
#include "autoconfig.h"
#endif
#ifdef RCL_USE_ASPELL
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -304,11 +358,9 @@ int main(int argc, char **argv)
exit(1);
}
string lang = "en";
Aspell aspell(rclconfig);
Aspell aspell(rclconfig, lang);
if (!aspell.init("/usr/local", reason)) {
if (!aspell.init(reason)) {
cerr << "Init failed: " << reason << endl;
exit(1);
}
@@ -331,5 +383,9 @@ int main(int argc, char **argv)
}
exit(0);
}
#else
int main(int argc, char **argv)
{return 1;}
#endif // RCL_USE_ASPELL
#endif // TEST_RCLASPELL test driver
+9 -5
View File
@@ -1,6 +1,9 @@
#ifndef _RCLASPELL_H_INCLUDED_
#define _RCLASPELL_H_INCLUDED_
/* @(#$Id: rclaspell.h,v 1.2 2006-10-09 16:37:08 dockes Exp $ (C) 2006 J.F.Dockes */
/* @(#$Id: rclaspell.h,v 1.3 2006-10-11 14:16:25 dockes Exp $ (C) 2006 J.F.Dockes */
/* autoconfig.h must be included before this file */
#ifdef RCL_USE_ASPELL
/**
* Aspell speller interface class.
@@ -28,15 +31,15 @@ class AspellData;
class Aspell {
public:
Aspell(RclConfig *cnf, const string &lang)
: m_conf(cnf), m_lang(lang), m_data(0) {};
Aspell(RclConfig *cnf)
: m_config(cnf), m_data(0) {};
~Aspell();
/** Check health */
bool ok();
/** Find the aspell command and shared library, init function pointers */
bool init(const string &basedir, string &reason);
bool init(string &reason);
/** Build dictionary out of index term list. This is done at the end
* of an indexing pass. */
@@ -48,9 +51,10 @@ class Aspell {
private:
string dicPath();
RclConfig *m_conf;
RclConfig *m_config;
string m_lang;
AspellData *m_data;
};
#endif /* RCL_USE_ASPELL */
#endif /* _RCLASPELL_H_INCLUDED_ */