Skip to content

Commit

Permalink
Merge pull request #6 from inaka/ferigis.129082833.general_items
Browse files Browse the repository at this point in the history
[#129082833] Fulfil the general items on open-source checklist
  • Loading branch information
harenson authored Sep 5, 2016
2 parents a93d1f5 + b6faf9b commit 6964d35
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 7 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ rel/example_project
_build/
log/
*_plt
.DS_Store
.DS_Store
doc/
72 changes: 70 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,70 @@
# sheldon
Very Simple Erlang Spell Checker
![](http://i.giphy.com/M3EZtLUDLsYP6.gif)

# Sheldon

Very Simple Erlang Spell Checker.

## Contact Us
For **questions** or **general comments** regarding the use of this library,
please use our public [hipchat room](http://inaka.net/hipchat).

If you find any **bugs** or have a **problem** while using this library, please
[open an issue](https://github.com/inaka/sheldon/issues/new) in this repo
(or a pull request :)).

And you can check all of our open-source projects at [inaka.github.io](http://inaka.github.io).

## Installation

1. Clone the repo
2. `rebar3 compile`

## Usage

### Erlang Shell

First of all Sheldon is an application and it needs to be started. You can use `rebar3 shell` to set the necessary paths, then use `sheldon:start/0` or `application:ensure_all_started(sheldon)` in order to start Sheldon but if you are using Sheldon as a dependency you can let OTP starts it from your_app.app file too.

Sheldon only has two main methods, `sheldon:check/1` and `sheldon:check/2`. As a user, you just need to use those.

```erlang
1> sheldon:check("I want to check this correct text").
ok
2> sheldon:check("I want to check this misspellllled text").
#{bazinga => "Too bad, I'll have a virgin Cuba Libre.",
misspelled_words => [#{line_number => 1,word => "misspellllled"}]}
```

## Configuration

`sheldon:check/2` works like `sheldon:check/1` but it accepts a Configuration parameter.
With this Conf parameter we can apply some rules to the text we want to check. Those rules are ignore words, ignore patterns and ignore blocks.

This is the format (see [sheldon_config.erl](https://github.com/inaka/sheldon/blob/master/src/sheldon_config.erl)), no key is required:

```erlang
#{ ignore_words => [string()]
, ignore_patterns => [regex()]
, ignore_blocks => [ignore_block()]
}.
```
Then, if we call the previous `sheldon:check/1` but with configuration we can skip the error

```erlang
3> sheldon:check("I want to check this misspellllled text", #{ignore_words => ["misspellllled"]}).
ok
```

## Results

`sheldon:check/1` and `sheldon:check/2` have the same result type, you can see [sheldon_result.erl](https://github.com/inaka/sheldon/blob/master/src/sheldon_result.erl). Sheldon will return the `ok` atom if the check went well else it'll return
```erlang
#{ misspelled_words := [misspelled_word()]
, bazinga := string()
}.
```

## Dependencies

- Erlang/OTP 19+ in order to use it.
- Erlang/OTP 19.0.2+ in order to test it.
4 changes: 4 additions & 0 deletions src/sheldon.erl
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,14 @@ start() ->
{ok, _} = application:ensure_all_started(sheldon),
ok.

%% @doc Checks the spelling of the iodata() received as a parameter.
%% @equiv check(Text, sheldon_config:default())
-spec check(iodata()) -> sheldon_result:result().
check(Text) ->
check(Text, sheldon_config:default()).

%% @doc Checks the spelling of the iodata() received as a parameter.
%% It also accepts Config parameter
-spec check(iodata(), sheldon_config:config()) -> sheldon_result:result().
check(Text, Config1) ->
Config = sheldon_config:normalize(Config1),
Expand Down
6 changes: 4 additions & 2 deletions src/sheldon_config.erl
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
%%% @hidden
%%% @doc sheldon's module for config handling.
%%%
%%% Copyright 2016 Inaka <hello@inaka.net>
Expand Down Expand Up @@ -38,14 +37,15 @@
-type config() ::
#{ lang => sheldon_dictionary:language()
, ignore_words => [string()]
, ignore_patterns => [string()]
, ignore_patterns => [regex()]
, ignore_blocks => [ignore_block()]
}.

%%%===================================================================
%%% API
%%%===================================================================

%% @doc returns a default config
-spec default() -> config().
default() ->
#{ lang => default_lang()
Expand All @@ -54,6 +54,8 @@ default() ->
, ignore_blocks => default_ignore_blocks()
}.

%% @doc given a config map this method fills the missing keys
%% and convert to lowercase the ignore_words
-spec normalize(config()) -> config().
normalize(Config) ->
#{ lang => normalize_lang(Config)
Expand Down
5 changes: 5 additions & 0 deletions src/sheldon_dictionary.erl
Original file line number Diff line number Diff line change
Expand Up @@ -48,23 +48,28 @@
%%% API
%%%===================================================================

%% @doc starts the gen_server
-spec start_link(language()) ->
{ok, Pid :: pid()} | ignore | {error, Reason :: term()}.
start_link(Lang) ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [Lang], []).

%% @doc evaluates if a given string() is member of the dictionary
-spec member(string(), language()) -> boolean().
member(Word, Lang) ->
DictName = dictionary_name(Lang),
ets:lookup(DictName, string:to_lower(Word)) =/= [].

%% @doc returns a bazinga from the ETS
-spec get_bazinga(language()) -> string().
get_bazinga(Lang) ->
BazingaName = bazinga_name(Lang),
Keys = ets:tab2list(BazingaName),
{Bazinga} = lists:nth(rand:uniform(length(Keys)), Keys),
Bazinga.

%% @doc returns the name of the dictionary given the language() as a
%% parameter
-spec dictionary_name(language()) -> atom().
dictionary_name(Lang) ->
Bin = << (atom_to_binary(sheldon, utf8))/binary
Expand Down
2 changes: 1 addition & 1 deletion src/sheldon_result.erl
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
%%% @hidden
%%% @doc Result model.
%%%
%%% Copyright 2016 Inaka &lt;hello@inaka.net&gt;
Expand Down Expand Up @@ -43,6 +42,7 @@
%%% API
%%%===================================================================

%% @doc Returns a result() type given some misspelled words.
-spec result([misspelled_word()], sheldon_config:config()) -> result().
result([], _Config) -> ok;
result(MisspelledWords, _Config = #{lang := Lang}) ->
Expand Down
2 changes: 1 addition & 1 deletion src/sheldon_sup.erl
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
%%% @hidden
%%% @doc Main Sheldon's supervisor.
%%%
%%% Copyright 2016 Inaka &lt;hello@inaka.net&gt;
Expand Down Expand Up @@ -48,6 +47,7 @@ start_link() ->
%%% Supervisor callbacks
%%%===================================================================

%% @doc here one child will be created per each dictionary
-spec init(any()) ->
{ok, {supervisor:sup_flags(), [supervisor:child_spec()]}}.
init([]) ->
Expand Down
5 changes: 5 additions & 0 deletions src/sheldon_utils.erl
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
%%% API
%%%===================================================================

%% @doc normalizes the iodata() escaping some characters and converting
%% them to string().
-spec normalize(iodata()) -> string().
normalize(Word) ->
CharToScape = [ "\n"
Expand All @@ -54,10 +56,13 @@ normalize(Word) ->
Escaped = escape_chars(Word, CharToScape),
binary_to_list(Escaped).

%% @doc checks if iodata() is a number
-spec is_number(iodata()) -> boolean().
is_number(Word) ->
re:run(Word, "^[0-9]*$") =/= nomatch.

%% @doc checks if some string() matches in one of the patterns given as
%% a parameter
-spec match_in_patterns(string(), [string()]) -> boolean().
match_in_patterns(Word, Patterns) ->
MatchTuples = [{Word, Pattern} || Pattern <- Patterns],
Expand Down

0 comments on commit 6964d35

Please sign in to comment.