From b7ca4cfb6d0ed414af48e7526d0a0d4149a06e63 Mon Sep 17 00:00:00 2001 From: Vladimir Sibirov Date: Sun, 8 Jul 2012 13:34:10 +0400 Subject: [PATCH] Added a few dictionary handling functions. --- aspell.go | 94 +++++++++++++++++++++++++++++++++++++++++++------- aspell_test.go | 45 +++++++++++++++++++++--- 2 files changed, 123 insertions(+), 16 deletions(-) diff --git a/aspell.go b/aspell.go index 4a71ad1..7786484 100644 --- a/aspell.go +++ b/aspell.go @@ -1,4 +1,4 @@ -// Package aspell is simplified bindings to GNU Aspell spell checking library. +// Package aspell provides simplified bindings to GNU Aspell spell checking library. package aspell /* @@ -85,8 +85,8 @@ func NewSpeller(options map[string]string) (Speller, error) { return s, nil } -// SetOption sets Aspell configuration option for the speller. -// All options should be changed before calling spell checking methods. +// Config returns current Aspell configuration option value for the speller. +// It returns nil in case of error. // See available options at http://aspell.net/man-html/The-Options.html func (s Speller) Config(name string) string { cName := C.CString(name) @@ -116,22 +116,92 @@ func (s Speller) Delete() { // s.config is deleted automatically } +// wordListToSlice converts Aspell word list into Go slice. +func wordListToSlice(list *C.AspellWordList) []string { + if list == nil { + return nil + } + count := int(C.aspell_word_list_size(list)) + result := make([]string, count) + + elems := C.aspell_word_list_elements(list) + for i := 0; i < count; i++ { + word := C.aspell_string_enumeration_next(elems) + if word == nil { + break + } + result[i] = C.GoString(word) + } + C.delete_aspell_string_enumeration(elems) + + return result +} + // Suggest returns a slice of possible suggestions for the given word. +// Nil is returned on error. func (s Speller) Suggest(word string) []string { cword := C.CString(word) defer C.free(unsafe.Pointer(cword)) suggestions := C.aspell_speller_suggest(s.speller, cword, -1) - count := uint(C.aspell_word_list_size(suggestions)) - result := make([]string, count) - elements := C.aspell_word_list_elements(suggestions) - for i := 0; ; i++ { - alt := C.aspell_string_enumeration_next(elements) - if alt == nil { + return wordListToSlice(suggestions) +} + +// Replace saves a replacement pair to the spell checker so that it would +// get higher probability on next Suggest call. +// Returns true on success or false on error. +func (s Speller) Replace(misspelled, correct string) bool { + cmis := C.CString(misspelled) + defer C.free(unsafe.Pointer(cmis)) + ccor := C.CString(correct) + defer C.free(unsafe.Pointer(ccor)) + + ret := C.aspell_speller_store_replacement(s.speller, cmis, -1, ccor, -1) + + return ret != -1 +} + +// MainWordList returns the main word list used by the speller. +func (s Speller) MainWordList() ([]string, error) { + list := C.aspell_speller_main_word_list(s.speller) + if list == nil { + return nil, errors.New("Failed getting the main word list") + } + return wordListToSlice(list), nil +} + +// Dict represents Aspell dictionary info. +type Dict struct { + name string + code string + jargon string + size string + module string +} + +// Dicts returns the list of available aspell dictionaries. +func Dicts() []Dict { + config := C.new_aspell_config() + dlist := C.get_aspell_dict_info_list(config) + C.delete_aspell_config(config) + + count := int(C.aspell_dict_info_list_size(dlist)) + result := make([]Dict, count) + + dels := C.aspell_dict_info_list_elements(dlist) + for i := 0; i < count; i++ { + entry := C.aspell_dict_info_enumeration_next(dels) + if entry == nil { break } - result[i] = C.GoString(alt) - // C.free(unsafe.Pointer(alt)) + result[i] = Dict{ + name: C.GoString(entry.name), + code: C.GoString(entry.code), + jargon: C.GoString(entry.jargon), + size: C.GoString(entry.size_str), + module: C.GoString(entry.module.name), + } } - C.delete_aspell_string_enumeration(elements) + C.delete_aspell_dict_info_enumeration(dels) + return result } diff --git a/aspell_test.go b/aspell_test.go index 21c7aa4..df7843d 100644 --- a/aspell_test.go +++ b/aspell_test.go @@ -3,6 +3,8 @@ package aspell import ( "strings" "testing" + +// "fmt" ) // This is a test for basic Aspell initialization @@ -17,7 +19,7 @@ func TestBasic(t *testing.T) { t.Errorf("Aspell error: %s", err.Error()) return } - //defer speller.Delete() + defer speller.Delete() // Test config getter enc := speller.Config("encoding") @@ -42,10 +44,10 @@ func TestBasic(t *testing.T) { } // This is a test for the list of suggestions -func TestSuggest(t *testing.T) { +func TestSuggestReplace(t *testing.T) { // Initialization opts := map[string]string{ - "lang": "en_US", + "lang": "en_US", "sug-mode": "slow", } speller, err := NewSpeller(opts) @@ -53,7 +55,7 @@ func TestSuggest(t *testing.T) { t.Errorf("Aspell error: %s", err.Error()) return } - //defer speller.Delete() + defer speller.Delete() // A "must have" dictionary dict := map[string]string{ @@ -80,4 +82,39 @@ func TestSuggest(t *testing.T) { t.Errorf("Missing suggestion for '%s': expected '%s', suggested '%s'", incorrect, correct, strings.Join(suggs, ", ")) } } + + // Store and test a new replacement + if speller.Replace("juse", "juice") { + sugJuse := speller.Suggest("juse") + found := false + for _, word := range sugJuse { + if word == "juice" { + found = true + break + } + } + if !found { + t.Errorf("Missing replacement for 'juse': expected 'juse', suggested '%s'", strings.Join(sugJuse, ", ")) + } + + } else { + t.Error("Storing a replacement failed") + } + + // // Print dict list + // dicts := Dicts() + // fmt.Printf("Dicts count: %d\n", len(dicts)) + // for _, dict := range dicts { + // fmt.Printf("Name: %s\nCode: %s\nJargon: %s\nSize: %s\nModule: %s\n\n", dict.name, dict.code, dict.jargon, dict.size, dict.module) + // } + + // // Print main word list + // words, err := speller.MainWordList() + // if err != nil { + // t.Error(err.Error()) + // } else { + // for _, word := range words { + // fmt.Printf("%s, ", word) + // } + // } }