Re: AbiSource, Ispell, Aspell and beyond...


Subject: Re: AbiSource, Ispell, Aspell and beyond...
From: Kevin Atkinson (kevinatk@home.com)
Date: Wed Feb 23 2000 - 14:12:25 CST


On Tue, 22 Feb 2000, Paul Rohr wrote:

> However, I think you're radically overestimating our API needs for swapping
> out spell checkers. Have you seen what our current API into ispell is?

I have included a new draft. Hopefully this time it be clearer how to use
it. I have also simplified it a bit. Don't count on it getting any
simpler.

/*
Overview:
  Create a new Config class and set the necessary parameters such as
  the language to use.
  Create a new manager class passing in a config class as the parameters.
  There should be 1 manager per language per document.
  The manager class uses the config class for getting its initial
  options. It does NOT take ownership of it so you must delete it
  with delete when done with it.
*/
 
// All class names will be prefixed by the name of my portable library
// or an abbreviation of it.

class Object {
  virtual Object * clone() const = 0;
  // if the two objects are not of the exact same type
  // the assign method is undefined.
  virtual void assign(const Object *) = 0;
  virtual int error_num() {return 0;}
  virtaul const char * error_message() {return "";}
  // string valid until the next error
  ~Object() {}
}

// The Config class is used to hold configuration information.
// it has a set of keys which it will except. Inserting are even
// trying to look at a key that it does not know will produce
// an error. Extra accepted keys can be added with the set_extra
// method.

// NOTE: methods that return a bool generally return false on error and
// true other wise. To find out what went wrong use the
// error_num and error_message methods.
// Unless otherwise stated mathods that return a const char * will
// return null on error. The charter string returned is only valid
// until the next method which returns a const char * is called.

class Config : public Object {
public:
  void set_extra(const KeyInfo * begin, const KeyInfo * end);
  
  virtual const KeyInfo * keyinfo(const char * key) const = 0
  virtual KeyInfoEmulation * possible_elements(bool include_extra = true) const = 0;
  // allocates with new
  
  virtual const char * get_default(const char * key) const = 0;
  PairEmulation * elements() const;
  // allocated with new

  virtual bool insert(const char * key, const char * value) = 0;
  // note: insert will NOT overwrite an existing entry
  virtual bool replace(const char * key, const char * value) = 0;

  virtual bool remove(const char * key) = 0;
  
  virtual void clear() = 0;

  virtual bool merge(const StringMap & other);
  
  // these will
  // a) return the default if the value is not set
  // b) give an error if the key is not requested as known
  // c) give an error if the value is not in the right format

  virtual const char * retrieve (const char * key) const = 0;
  virtual const char * retrieve_list (const char * key) const = 0;

  virtual bool retrieve_list (const char * key, MutableContainer &) const = 0;

  virtual int retrieve_bool(const char * key) const = 0;
  // return -1 on error, 0 if false, 1 if true

  virtual int retrieve_int(const char * key) const = 0;
  // return -1 on error

};

Config * new_config();
// returns a new config class for setting things up before a manager class
// is created

// This class is responsible for keeping track of the dictionaries
// coming up with suggestions and the like
// Its methods are NOT meant to be used my multiple threads and/or
// documents.
// Most all if the manipulation of options is done via the Config
// class, thus this class has precious few methods

class Manager : public Object {

  virtual Config & config() = 0;
  virtual const Config & config () const = 0;
  // this config returned is NOT the same object
  // as the one you pass in.
  
  virtual const char * lang_name() const = 0;

  virtual bool check(const char * word) const = 0;
  virtual bool check(const ShortUniChar * word) const = 0;
  virtual bool check(const UniChar * word) const = 0

  virtual bool add_to_personal(const char *) = 0;
  virtual bool add_to_session(const char *) = 0;

  virtual bool add_to_personal(const ShortUniChar *) = 0;
  virtual bool add_to_session(const ShortUniChar *) = 0;

  virtual bool add_to_personal(const UniChar *) = 0;
  virtual bool add_to_session(const UniChar *) = 0;
  
  virtual bool save_all_wls() = 0;

  virtual void clear_session() = 0;
  
  virtual SuggestionList & suggest(const char * word) = 0;
  virtual ShortUniSuggestionList & suggest(const ShortUniChar * word) = 0;
  virtual UniSuggestionList & suggest(const UniChar * word) = 0;
  // the suggestion list and the elements in it are only
  // valid until the next call to suggest.
  
  virtual bool store_repl(const char * mis, const char * cor);
  virtual bool store_repl(const ShortUniChar * mis, const ShortUniChar * cor);
  virtual bool store_repl(const UniChar * mis, const UniChar * cor);
};

new_manager(const Config *)
// returns a new manager class, allocated with new,
// based on the settings in conig

// An emulation is an efficient way to iterate through elements much
// like a forward iterator. The at_end method is a convince method
// as emulations will return a null pointer when they are at the end.
// Unlike an iterator iterating through x elements on a list can be
// done in x function calls while an iterator will require 3*x.
// function calls.
// Example of emulator usage
// const char * word;
// while ( (word = elements->next()) != 0) { // one function call
// cout << word << endl;
// }
// And an iterator
// iterator i = container->begin();
// iterator end = container->end();
// while (i != end) { // comparison, one function call
// cout << *i << endl; // deref, total of two function calls
// ++i; // increment, total of three function calls.
// }
// Normally all three calls are inline so it doesn't really matter
// but when the container type is not visible there are not inline
// and probably even virtual.
// If you really love iterators you can very easily wrap an emulation
// in a forward iterator.

// The strings return generally remain valid as long as the underlying
// container remains valid.

typedef unsigned short ShortUniChar;
typedef unsigned int UniChar;

class StringEmulation : public Object {
public:
  virtual const char * next() = 0;
  virtual bool at_end() const = 0;
};

class ShortUniStringEmulation : public Object {
public:
  virtual const ShortUniChar * next() = 0;
  virtual bool at_end() const = 0;
};

class UniStringEmulation : public Object {
public:
  virtual const UniChar * next() = 0;
  virtual bool at_end() const = 0;
};

class SuggestionList {
public:
  virtual bool empty() const = 0;
  virtual int size() const = 0;
  virtual StringEmulation * elements() const = 0;
  virtual ShortUniStringEmulation * short_uni_elements() const = 0;
  virtual UniStringEmulation * uni_elements() const = 0;
};

class StringPair {
  const char * first;
  const char * second;
}

class StringPairEmulation : public Object {
public:
  virtual StringPair next() = 0;
  virtual bool at_end() const = 0;
};

// Used by the Config class below...
class MutableContainer {
public:
  virtual void insert(const char *) = 0;
  virtual void remove(const char *) = 0;
  virtual void clear() = 0;
  virtual ~MutableContainer();
};

struct KeyInfo {
  const char * name;
  enum Type {Bool, String, Int, List};
  Type type;
  const char * def;
  const char * desc; // null if internal value
};

class KeyInfoEmulation {
...
};

// Should I provide classes to directly access the individual word lists?

// There will also be classes to spell string complete documents
// which will allow the spell checker to skip over TeX commands, HTML
// tags, etc...

  



This archive was generated by hypermail 2b25 : Wed Feb 23 2000 - 14:09:37 CST