/** * Returns the found command or throws an exception. * * @param cmp possible completions * @param par parent command * @param <E> token type * @return index * @throws QueryException query exception */ private <E extends Enum<E>> E consume(final Class<E> cmp, final Cmd par) throws QueryException { final String token = command(null); if (!suggest || token == null || !token.isEmpty()) { try { // return command reference; allow empty strings as input ("NULL") return Enum.valueOf(cmp, token == null ? "NULL" : token.toUpperCase(Locale.ENGLISH)); } catch (final IllegalArgumentException ignore) { } } final Enum<?>[] alt = startWith(cmp, token); // handle empty input if (token == null) { if (par != null) throw help(alt, par); if (suggest) throw error(alt, EXPECTING_CMD); return null; } // output error for similar commands final byte[] name = uc(token(token)); final Levenshtein ls = new Levenshtein(); for (final Enum<?> s : startWith(cmp, null)) { final byte[] sm = uc(token(s.name())); if (ls.similar(name, sm) && Cmd.class.isInstance(s)) { throw error(alt, UNKNOWN_SIMILAR_X, name, sm); } } // show unknown command error or available command extensions throw par == null ? error(alt, UNKNOWN_TRY_X, token) : help(alt, par); }
/** * Performs a fuzzy search for the specified token with a maximum number of errors. * * @param token token to look for * @param k number of errors allowed * @return iterator */ private synchronized IndexIterator fuzzy(final byte[] token, final int k) { FTIndexIterator it = FTIndexIterator.FTEMPTY; final int tokl = token.length, tl = tp.length; final int e = Math.min(tl - 1, tokl + k); int s = Math.max(1, tokl - k) - 1; while (++s <= e) { int p = tp[s]; if (p == -1) continue; int t = s + 1, r = -1; while (t < tl && r == -1) r = tp[t++]; while (p < r) { if (ls.similar(inY.readBytes(p, s), token, k)) { it = FTIndexIterator.union(iter(pointer(p, s), size(p, s), inZ, token), it); } p += s + ENTRY; } } return it; }