Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support keyword arguments partially #46

Merged
33 commits merged into from
Oct 24, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
92893e0
Edit specs to route command "random" to :route_random
Jun 25, 2015
78566b4
Move implementation of command "random" to single route
Jun 25, 2015
cc215b3
Disable cop Style/LambdaCall
Jun 25, 2015
b146368
Add dependency "lita-keyword-arguments"
Jun 25, 2015
1203947
Edit specs for command "random"
Jun 25, 2015
3c8c1fc
Add defenition of keyword arguments for command "random"
Jun 25, 2015
493e9fc
Configure specs to use extension "lita-keyword-arguments"
Jun 25, 2015
2b40803
Implement keyword arguments for command "random"
Jun 25, 2015
8c2cc1e
Refactor Lita::Handlers::Random#extract_argument
Jun 25, 2015
320f6af
Split spec for Lita::Handler::Random into several files
Jun 25, 2015
b73ae22
Add specs for command "random base64"
Jun 26, 2015
bb80d3e
Implement keyword arguments for command "random base64"
Jun 26, 2015
ff21897
Allow only spaces or line ends after commands
Jun 26, 2015
52bca3c
Add specs for command "random hex"
Jun 26, 2015
1df5f8d
Implement keyword arguments for command "random hex"
Jun 26, 2015
ca95422
rename keyword argument for command "random base64"
Jun 26, 2015
6bfb017
Add specs for command "random smart password"
Jun 26, 2015
9f1b2ec
Implement keyword arguments for command "random smart password"
Jun 26, 2015
0b42d17
Add specs for command "random password"
Jun 26, 2015
213f150
Implement keuword arguments for command "random password"
Jun 26, 2015
52b3b56
Remove defult value for internal functions
Jun 26, 2015
06f0519
Simplify regexes
Jun 26, 2015
756b720
Merge branch 'development' into support_named_arguments
Oct 24, 2015
5cfcc2e
Fix RuboCop offenses
Oct 24, 2015
725b57f
Merge branch 'development' into support_named_arguments
Oct 24, 2015
f6d44bb
Conform argument names in documentation
Oct 24, 2015
8e9cf74
Remove unnecessary private access modifier
Oct 24, 2015
87fb1b8
Add specs for cases when both positional and keyword arguments present
Oct 24, 2015
98f136c
Add spec to not route foreign commands to :route_random
Oct 24, 2015
6f6eeff
Fix routing
Oct 24, 2015
2429ce8
Conform argument names in specs
Oct 24, 2015
8c24f94
Add instructions for named arguments
Oct 24, 2015
5b9c8f8
Conform argument names in README
Oct 24, 2015
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ AllCops:
Exclude:
- vendor/**/*

Style/AccessModifierIndentation:
EnforcedStyle: outdent

Style/AndOr:
Enabled: false

Style/LambdaCall:
Enabled: false

Style/TrailingComma:
Enabled: false

Style/AccessModifierIndentation:
EnforcedStyle: outdent
56 changes: 37 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,27 @@ gem 'lita-random', '~> 0.5.1'

### Commands

The space between instructions can be skiiped, so you can write
The space between instructions can be skipped, so you can write
`random hex` as `randomhex`, `rand b64` as `randb64`

Arguments for all commands (excluding `random case`, `shuffle` and `sample`)
can be passed as keyword arguments too. Put them after
positional arguments with two dashes before, or the first letter
of argument name with one dash. Examples:

```
You: lita random 5 10
Lita: 7
You: lita random 5 --to 5
Lita: 9
You: lita random 5 -t 10
Lita: 5
You: lita random --to 10 --from 5
Lita: 6
You: lita random -f 5 -t 10
Lita: 9
```

Command `random` has alias `rand`

* `random` -
Expand All @@ -36,19 +54,19 @@ Command `random` has alias `rand`
* `random <from> <to>` -
random integer or float number, greater or equal to `from` and lesser than `to`

* `random case <s>` -
randomize case of each character of string `s`
* `random case <string>` -
randomize case of each character of string `string`

Command `base64` has alias `b64`

* `random base64 <n=16>` -
random base64 string, length of source string is `n`,
length of result is about `n * 4 / 3` (24 with default value of `n`)
* `random base64 <size=16>` -
random base64 string, length of source string is `size`,
length of result is about `size * 4 / 3` (24 with default value of `size`)

Command `hex` has aliases `hx` and `x`

* `random hex <n=16>` -
random hexadecimal string with length `n * 2`
* `random hex <size=16>` -
random hexadecimal string with length `size * 2`

Command `uuid` has alias `uid`

Expand All @@ -59,18 +77,18 @@ Command `uuid` has alias `uid`

Command `password` has alias `pass`

* `random password <n=16>` -
random password with length `n` containing characters
* `random password <length=16>` -
random password with length `length` containing characters
in upper and lower case, and digits

* `random smart password <n=8>` -
random pronounceable password with a minimum length of `n`
* `random smart password <length=8>` -
random pronounceable password with a minimum length of `length`

* `shuffle <array, ...>` -
new array with elements of `array` shuffled

* `sample <n=1> <array, ...>` -
choose `n` random elements from `array`
* `sample <count=1> <array, ...>` -
choose `count` random elements from `array`

### Examples

Expand All @@ -82,12 +100,12 @@ Lita: 0.8332672468501509

You: lita random 5
Lita: 2
You: lita rand 100
You: lita rand --to 100
Lita: 24

You: lita random 1.5
You: lita random -f 1.5
Lita: 1.1828046952104034
You: lita random 5 10
You: lita random 10 --from 5
Lita: 8
You: lita rand 1000 2000
Lita: 1240
Expand All @@ -104,15 +122,15 @@ Lita: NMkIhB+iG2VNpg==

You: lita random hex
Lita: 7d6f39cf53303db862bac5e1b36eb0fa
You: lita randx 10
You: lita randx -s 10
Lita: 0d8297837d6e63b8c25b

You: lita random uuid
Lita: f1281565-3c8a-475d-a1aa-565ff840a42c

You: lita random password
Lita: TXXBu7XEBdwFF7fP
You: lita randpass 8
You: lita randpass --length 8
Lita: 7lFateFs

You: lita random smart password
Expand Down
190 changes: 109 additions & 81 deletions lib/lita/handlers/random.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require 'lita-keyword-arguments'

##
# Lita module.
#
Expand All @@ -22,72 +24,61 @@ class Random < Handler # rubocop:disable Metrics/ClassLength
'random integer or float number, ' \
'greater or equal to `from` and lesser than `to`',

'random case <s>' =>
'randomize case of each character of string `s`',
'random case <string>' =>
'randomize case of each character of string `string`',

'random base64 <n=16>' =>
'random base64 string, length of source string is n, ' \
'length of result is about `n * 4 / 3` ' \
'(24 with default value of `n`)',
'random base64 <size=16>' =>
'random base64 string, length of source string is `size`, ' \
'length of result is about `size * 4 / 3` ' \
'(24 with default value of `size`)',

'random hex <n=16>' =>
'random hexadecimal string with length `n * 2`',
'random hex <size=16>' =>
'random hexadecimal string with length `size * 2`',

'random uuid' =>
'v4 random UUID (Universally Unique IDentifier). ' \
'The version 4 UUID is purely random (except the version). ' \
'It doesn’t contain meaningful information ' \
'such as MAC address, time, etc.',

'random password <n=16>' =>
'random password with length `n` containing characters ' \
'random password <length=16>' =>
'random password with length `length` containing characters ' \
'in upper and lower case, and digits',

'random smart password <n=8>' =>
'random pronounceable password with a minimum length of `n`',
'random smart password <length=8>' =>
'random pronounceable password with a minimum length of `length`',

'shuffle <array, ...>' =>
'new array with elements of `array` shuffled',

'sample <n=1> <array, ...>' =>
'choose `n` random elements from `array`',
'sample <count=1> <array, ...>' =>
'choose `count` random elements from `array`',
}

route(/^rand(om)?$/i, :route_random, command: true, help: HELP)
def route_random(response)
response.reply(::Random.rand.to_s)
end

route(/^rand(om)?\s+(\d+)?$/i, :route_random_to, command: true)
def route_random_to(response)
to = response.matches[0][1].to_i
response.reply(::Random.rand(to).to_s)
end

route(/^rand(om)?\s+(\d+\.\d+)?$/i, :route_random_float_to, command: true)
def route_random_float_to(response)
to = response.matches[0][1].to_f
response.reply(::Random.rand(to).to_s)
end
route(
/^rand(om)?((\s+(?<from>\d+(\.\d+)?))?\s+(?<to>\d+(\.\d+)?))?($|\s*-)/i,
:route_random,
command: true, help: HELP,
kwargs: {
from: { short: 'f' },
to: { short: 't' },
}
)

route(/^rand(om)?\s+(\d+)\s+(\d+)?$/i,
:route_random_from_to, command: true)
def route_random_from_to(response)
from = response.matches[0][1].to_i
to = response.matches[0][2].to_i
response.reply(::Random.rand(from...to).to_s)
end
def route_random(response)
from = extract_argument(response, 0, :from, &method(:str_to_num)) || 0
to = extract_argument(response, 1, :to, &method(:str_to_num)) || 1.0

rescue RuntimeError # rubocop:disable Lint/HandleExceptions
else
result = if from.is_a?(Float) || to.is_a?(Float)
# In Rubinius,
# ::Random.rand can not exclude non Integer end value
::Random.rand(from..(to - Float::EPSILON))
else
::Random.rand(from...to)
end

route(/^rand(om)?\s+(?<from>\d+\.\d+)\s+(?<to>\d+)?$/i,
:route_random_float_from_to, command: true)
route(/^rand(om)?\s+(?<from>\d+(\.\d+)?)\s+(?<to>\d+\.\d+)?$/i,
:route_random_float_from_to, command: true)
def route_random_float_from_to(response)
matches = response.matches[0]
from = matches[0].to_f
to = matches[1].to_f
# In Rubinius, ::Random.rand can not exclude non Integer end value
result = ::Random.rand(from..(to - Float::EPSILON))
response.reply(result.to_s)
end

Expand All @@ -97,57 +88,76 @@ def route_random_case(response)
response.reply(random_case(response.matches[0][0] || ''))
end

route(/^rand(om)?\s*b(ase)?64$/i, :route_random_base64, command: true)
route(
/^rand(om)?\s*b(ase)?64(\s+(?<n>\d+))?($|\s)/i,
:route_random_base64,
command: true,
kwargs: {
size: { short: 's' },
}
)

def route_random_base64(response)
response.reply(SecureRandom.base64)
end
size = extract_argument(response, 0, :size, &:to_i) || 16

route(/^rand(om)?\s*b(ase)?64\s+(?<n>\d+)$/i,
:route_random_base64_n, command: true)
def route_random_base64_n(response)
n = response.matches[0][0].to_i
response.reply(SecureRandom.base64(n))
rescue RuntimeError # rubocop:disable Lint/HandleExceptions
else
response.reply(SecureRandom.base64(size))
end

route(/^rand(om)?\s*(he?)?x$/i, :route_random_hex, command: true)
route(
/^rand(om)?\s*(he?)?x(\s+(?<n>\d+))?($|\s)/i,
:route_random_hex,
command: true,
kwargs: {
size: { short: 's' },
}
)

def route_random_hex(response)
response.reply(SecureRandom.hex)
end
size = extract_argument(response, 0, :size, &:to_i) || 16

route(/^rand(om)?\s*(he?)?x\s+(?<n>\d+)$/i,
:route_random_hex_n, command: true)
def route_random_hex_n(response)
n = response.matches[0][0].to_i
response.reply(SecureRandom.hex(n))
rescue RuntimeError # rubocop:disable Lint/HandleExceptions
else
response.reply(SecureRandom.hex(size))
end

route(/^rand(om)?\s*u?uid$/i, :route_random_uuid, command: true)
def route_random_uuid(response)
response.reply(SecureRandom.uuid)
end

route(/^rand(om)?\s*smart\s*pass(word)?$/i,
:route_random_smart_pass, command: true)
route(
/^rand(om)?\s*smart\s*pass(word)?(\s+(?<n>\d+))?($|\s)/i,
:route_random_smart_pass,
command: true,
kwargs: {
length: { short: 'l' },
}
)

def route_random_smart_pass(response)
response.reply(smart_password)
end
length = extract_argument(response, 0, :length, &:to_i) || 8

route(/^rand(om)?\s*smart\s*pass(word)?\s+(?<n>\d+)$/i,
:route_random_smart_pass_n, command: true)
def route_random_smart_pass_n(response)
min_length = response.matches[0][0].to_i
response.reply(smart_password(min_length))
rescue RuntimeError # rubocop:disable Lint/HandleExceptions
else
response.reply(smart_password(length))
end

route(/^rand(om)?\s*pass(word)?$/i, :route_random_pass, command: true)
route(
/^rand(om)?\s*pass(word)?(\s+(?<n>\d+))?($|\s)/i,
:route_random_pass,
command: true,
kwargs: {
length: { short: 'l' },
}
)

def route_random_pass(response)
response.reply(password)
end
length = extract_argument(response, 0, :length, &:to_i) || 16

route(/^rand(om)?\s*pass(word)?\s+(?<n>\d+)$/i,
:route_random_pass_n, command: true)
def route_random_pass_n(response)
length = response.matches[0][0].to_i
rescue RuntimeError # rubocop:disable Lint/HandleExceptions
else
response.reply(password(length))
end

Expand Down Expand Up @@ -185,7 +195,7 @@ def random_case(s)
true => %w(a e i o u y),
}

def smart_password(min_length = 8)
def smart_password(min_length)
password = ''
sequence_id = false
while password.length < min_length
Expand All @@ -198,9 +208,27 @@ def smart_password(min_length = 8)

PASS_CHARS = [*'a'..'z', *'A'..'Z', *'0'..'9']

def password(length = 16)
def password(length)
(0...length).map { |_| PASS_CHARS.sample }.join
end

def extract_argument(response, index, name)
matches = response.matches[0]
kwargs = response.extensions[:kwargs]

positional = matches[index]
kw = kwargs[name]

fail if positional && kw

s = positional || kw

block_given? && s ? yield(s) : s
end

def str_to_num(s)
s =~ /\./ ? s.to_f : s.to_i
end
end

Lita.register_handler(Random)
Expand Down
Loading