abouttreesummaryrefslogcommitdiff
path: root/srcs/juloo.keyboard2/suggestions/Suggestions.java
blob: 41a79414cf894c43f8a91b03b4f0ee6cbfcb5baf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package juloo.keyboard2.suggestions;

import java.util.Arrays;
import java.util.List;
import juloo.cdict.Cdict;
import juloo.keyboard2.dict.Dictionaries;
import juloo.keyboard2.Config;
import juloo.keyboard2.ComposeKey;
import juloo.keyboard2.ComposeKeyData;

/** Keep track of the word being typed and provide suggestions for
    [CandidatesView]. */
public final class Suggestions
{
  Callback _callback;
  Config _config;
  boolean _enabled;

  /** The suggestion displayed at the center of the candidates view and entered
      by the space bar. */
  public String best_suggestion = null;

  public Suggestions(Callback c, Config conf)
  {
    _callback = c;
    _config = conf;
  }

  public void started()
  {
    _enabled = _config.editor_config.should_show_candidates_view;
    best_suggestion = null;
  }

  public void currently_typed_word(String word)
  {
    if (!_enabled)
      return;
    Cdict dict = _config.current_dictionary;
    if (word.length() < 2 || dict == null)
    {
      set_suggestions(NO_SUGGESTIONS);
    }
    else
    {
      String[] dst = new String[3];
      query_suggestions(dict, word, dst, 3);
      set_suggestions(Arrays.asList(dst));
    }
  }

  int query_suggestions(Cdict dict, String word, String[] dst, int max_count)
  {
    boolean first_char_upper = Character.isUpperCase(word.charAt(0));
    word = apply_substitutions(word);
    Cdict.Result r = dict.find(word);
    int i = 0;
    if (r.found)
      dst[i++] = dict.word(r.index);
    int[] suffixes = dict.suffixes(r, max_count);
    // Disable distance search for small words
    int[] dist = (word.length() < 3 || i + 1 >= max_count) ? NO_RESULTS :
      dict.distance(word, 1, max_count);
    for (int j = 0; j < max_count && i < max_count; j++)
    {
      if (suffixes.length > j)
        dst[i++] = dict.word(suffixes[j]);
      if (dist.length > j && i < max_count)
        dst[i++] = dict.word(dist[j]);
    }
    if (first_char_upper)
      capitalize_results(dst);
    return i;
  }

  void capitalize_results(String[] rs)
  {
    for (int i = 0; i < rs.length; i++)
      if (rs[i] != null)
        rs[i] = rs[i].substring(0, 1).toUpperCase() + rs[i].substring(1);
  }

  /** Apply the same substitutions that were used when building the
      dictionaries to find word aliases. This catches missing diacritics for
      example. */
  String apply_substitutions(String w)
  {
    StringBuilder b = new StringBuilder(w);
    int len = w.length();
    for (int i = 0; i < len; i++)
    {
      char r =
        ComposeKey.transform_char(ComposeKeyData.substitutions, b.charAt(i));
      if (r != 0) b.setCharAt(i, r);
    }
    return b.toString();
  }

  void set_suggestions(List<String> ws)
  {
    _callback.set_suggestions(ws);
    best_suggestion = (ws.size() > 0) ? ws.get(0) : null;
  }

  static final List<String> NO_SUGGESTIONS = Arrays.asList();
  static final int[] NO_RESULTS = new int[0];

  public static interface Callback
  {
    public void set_suggestions(List<String> suggestions);
  }
}