htty 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE.rdoc +9 -0
- data/README.rdoc +199 -0
- data/VERSION +1 -0
- data/app/htty.rb +14 -0
- data/app/htty/cli.rb +77 -0
- data/app/htty/cli/command.rb +185 -0
- data/app/htty/cli/commands.rb +43 -0
- data/app/htty/cli/commands/address.rb +84 -0
- data/app/htty/cli/commands/body_clear.rb +20 -0
- data/app/htty/cli/commands/body_request.rb +51 -0
- data/app/htty/cli/commands/body_response.rb +59 -0
- data/app/htty/cli/commands/body_set.rb +58 -0
- data/app/htty/cli/commands/body_unset.rb +45 -0
- data/app/htty/cli/commands/cd.rb +20 -0
- data/app/htty/cli/commands/cookie_add.rb +20 -0
- data/app/htty/cli/commands/cookie_remove.rb +20 -0
- data/app/htty/cli/commands/cookies.rb +68 -0
- data/app/htty/cli/commands/cookies_add.rb +62 -0
- data/app/htty/cli/commands/cookies_clear.rb +20 -0
- data/app/htty/cli/commands/cookies_remove.rb +60 -0
- data/app/htty/cli/commands/cookies_remove_all.rb +50 -0
- data/app/htty/cli/commands/cookies_use.rb +57 -0
- data/app/htty/cli/commands/delete.rb +20 -0
- data/app/htty/cli/commands/exit.rb +20 -0
- data/app/htty/cli/commands/follow.rb +56 -0
- data/app/htty/cli/commands/form.rb +20 -0
- data/app/htty/cli/commands/form_add.rb +20 -0
- data/app/htty/cli/commands/form_clear.rb +26 -0
- data/app/htty/cli/commands/form_remove.rb +20 -0
- data/app/htty/cli/commands/form_remove_all.rb +20 -0
- data/app/htty/cli/commands/fragment_clear.rb +20 -0
- data/app/htty/cli/commands/fragment_set.rb +59 -0
- data/app/htty/cli/commands/fragment_unset.rb +48 -0
- data/app/htty/cli/commands/get.rb +20 -0
- data/app/htty/cli/commands/header_set.rb +20 -0
- data/app/htty/cli/commands/header_unset.rb +20 -0
- data/app/htty/cli/commands/headers_clear.rb +20 -0
- data/app/htty/cli/commands/headers_request.rb +70 -0
- data/app/htty/cli/commands/headers_response.rb +65 -0
- data/app/htty/cli/commands/headers_set.rb +57 -0
- data/app/htty/cli/commands/headers_unset.rb +54 -0
- data/app/htty/cli/commands/headers_unset_all.rb +48 -0
- data/app/htty/cli/commands/help.rb +100 -0
- data/app/htty/cli/commands/history.rb +60 -0
- data/app/htty/cli/commands/history_verbose.rb +81 -0
- data/app/htty/cli/commands/host_set.rb +59 -0
- data/app/htty/cli/commands/http_delete.rb +40 -0
- data/app/htty/cli/commands/http_get.rb +42 -0
- data/app/htty/cli/commands/http_head.rb +36 -0
- data/app/htty/cli/commands/http_options.rb +36 -0
- data/app/htty/cli/commands/http_post.rb +34 -0
- data/app/htty/cli/commands/http_put.rb +29 -0
- data/app/htty/cli/commands/http_trace.rb +36 -0
- data/app/htty/cli/commands/path_set.rb +54 -0
- data/app/htty/cli/commands/port_set.rb +55 -0
- data/app/htty/cli/commands/post.rb +20 -0
- data/app/htty/cli/commands/put.rb +20 -0
- data/app/htty/cli/commands/query_clear.rb +20 -0
- data/app/htty/cli/commands/query_set.rb +59 -0
- data/app/htty/cli/commands/query_unset.rb +56 -0
- data/app/htty/cli/commands/query_unset_all.rb +50 -0
- data/app/htty/cli/commands/quit.rb +24 -0
- data/app/htty/cli/commands/reuse.rb +74 -0
- data/app/htty/cli/commands/scheme_set.rb +69 -0
- data/app/htty/cli/commands/status.rb +52 -0
- data/app/htty/cli/commands/undo.rb +13 -0
- data/app/htty/cli/commands/userinfo_clear.rb +20 -0
- data/app/htty/cli/commands/userinfo_set.rb +56 -0
- data/app/htty/cli/commands/userinfo_unset.rb +47 -0
- data/app/htty/cli/cookie_clearing_command.rb +26 -0
- data/app/htty/cli/display.rb +182 -0
- data/app/htty/cli/http_method_command.rb +75 -0
- data/app/htty/cli/url_escaping.rb +27 -0
- data/app/htty/cookies_util.rb +36 -0
- data/app/htty/no_location_header_error.rb +12 -0
- data/app/htty/no_response_error.rb +12 -0
- data/app/htty/no_set_cookie_header_error.rb +13 -0
- data/app/htty/ordered_hash.rb +69 -0
- data/app/htty/payload.rb +48 -0
- data/app/htty/request.rb +471 -0
- data/app/htty/requests_util.rb +92 -0
- data/app/htty/response.rb +34 -0
- data/app/htty/session.rb +29 -0
- data/bin/htty +5 -0
- data/spec/unit/htty/cli_spec.rb +27 -0
- data/spec/unit/htty/ordered_hash_spec.rb +54 -0
- data/spec/unit/htty/request_spec.rb +1236 -0
- data/spec/unit/htty/response_spec.rb +0 -0
- data/spec/unit/htty/session_spec.rb +13 -0
- metadata +158 -0
@@ -0,0 +1,24 @@
|
|
1
|
+
# Defines HTTY::CLI::Commands::Quit.
|
2
|
+
|
3
|
+
require File.expand_path("#{File.dirname __FILE__}/../command")
|
4
|
+
|
5
|
+
module HTTY; end
|
6
|
+
|
7
|
+
class HTTY::CLI; end
|
8
|
+
|
9
|
+
module HTTY::CLI::Commands; end
|
10
|
+
|
11
|
+
# Encapsulates the _quit_ command.
|
12
|
+
class HTTY::CLI::Commands::Quit < HTTY::CLI::Command
|
13
|
+
|
14
|
+
# Returns the help text for the _quit_ command.
|
15
|
+
def self.help
|
16
|
+
'Quits htty'
|
17
|
+
end
|
18
|
+
|
19
|
+
# Performs the _quit_ command.
|
20
|
+
def perform
|
21
|
+
throw :quit
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# Defines HTTY::CLI::Commands::Reuse.
|
2
|
+
|
3
|
+
require File.expand_path("#{File.dirname __FILE__}/../command")
|
4
|
+
require File.expand_path("#{File.dirname __FILE__}/../display")
|
5
|
+
require File.expand_path("#{File.dirname __FILE__}/history")
|
6
|
+
require File.expand_path("#{File.dirname __FILE__}/history_verbose")
|
7
|
+
|
8
|
+
module HTTY; end
|
9
|
+
|
10
|
+
class HTTY::CLI; end
|
11
|
+
|
12
|
+
module HTTY::CLI::Commands; end
|
13
|
+
|
14
|
+
# Encapsulates the _reuse_ command.
|
15
|
+
class HTTY::CLI::Commands::Reuse < HTTY::CLI::Command
|
16
|
+
|
17
|
+
include HTTY::CLI::Display
|
18
|
+
|
19
|
+
# Returns the name of a category under which help for the _reuse_ command
|
20
|
+
# should appear.
|
21
|
+
def self.category
|
22
|
+
'Navigation'
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns the arguments for the command-line usage of the _reuse_ command.
|
26
|
+
def self.command_line_arguments
|
27
|
+
'index'
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns the help text for the _reuse_ command.
|
31
|
+
def self.help
|
32
|
+
'Copies a previous request by the index number shown in history'
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns the extended help text for the _reuse_ command.
|
36
|
+
def self.help_extended
|
37
|
+
'Copies the properties of a previous request to be used for the request, ' +
|
38
|
+
'using the request index number shown in history. Does not communicate ' +
|
39
|
+
"with the endpoint.\n" +
|
40
|
+
"\n" +
|
41
|
+
'The argument is an index number that appears when you type ' +
|
42
|
+
"#{strong HTTY::CLI::Commands::History.command_line}."
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns related command classes for the _reuse_ command.
|
46
|
+
def self.see_also_commands
|
47
|
+
[HTTY::CLI::Commands::History, HTTY::CLI::Commands::HistoryVerbose]
|
48
|
+
end
|
49
|
+
|
50
|
+
# Performs the _reuse_ command.
|
51
|
+
def perform
|
52
|
+
unless arguments.length == 1
|
53
|
+
raise ArgumentError,
|
54
|
+
"wrong number of arguments (#{arguments.length} for 1)"
|
55
|
+
end
|
56
|
+
|
57
|
+
requests = session.requests
|
58
|
+
requests_with_responses = requests.select do |r|
|
59
|
+
r.response
|
60
|
+
end
|
61
|
+
raise 'no requests in history' if requests_with_responses.empty?
|
62
|
+
|
63
|
+
index = arguments.first.to_i
|
64
|
+
unless (1..requests_with_responses.length).include?(index)
|
65
|
+
raise ArgumentError,
|
66
|
+
"index must be between 1 and #{requests_with_responses.length}"
|
67
|
+
end
|
68
|
+
|
69
|
+
add_request_if_has_response do
|
70
|
+
requests[index - 1].send :dup_without_response
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# Defines HTTY::CLI::Commands::SchemeSet.
|
2
|
+
|
3
|
+
require File.expand_path("#{File.dirname __FILE__}/../command")
|
4
|
+
require File.expand_path("#{File.dirname __FILE__}/address")
|
5
|
+
require File.expand_path("#{File.dirname __FILE__}/port_set")
|
6
|
+
|
7
|
+
module HTTY; end
|
8
|
+
|
9
|
+
class HTTY::CLI; end
|
10
|
+
|
11
|
+
module HTTY::CLI::Commands; end
|
12
|
+
|
13
|
+
# Encapsulates the _scheme-set_ command.
|
14
|
+
class HTTY::CLI::Commands::SchemeSet < HTTY::CLI::Command
|
15
|
+
|
16
|
+
# Returns the name of a category under which help for the _scheme-set_ command
|
17
|
+
# should appear.
|
18
|
+
def self.category
|
19
|
+
'Navigation'
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns the arguments for the command-line usage of the _scheme-set_ command.
|
23
|
+
def self.command_line_arguments
|
24
|
+
'scheme'
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns the help text for the _scheme-set_ command.
|
28
|
+
def self.help
|
29
|
+
"Changes the scheme (protocol identifier) of the request's address"
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns the extended help text for the _scheme-set_ command.
|
33
|
+
def self.help_extended
|
34
|
+
'Changes the scheme, or protocol identifier, used for the request. Does ' +
|
35
|
+
"not communicate with the endpoint.\n" +
|
36
|
+
"\n" +
|
37
|
+
"The scheme you supply must be either 'http' or 'https'. Changing the " +
|
38
|
+
"scheme has no effect on the port, and vice versa.\n" +
|
39
|
+
"\n" +
|
40
|
+
'The console prompt shows the address for the current request.'
|
41
|
+
end
|
42
|
+
|
43
|
+
# Returns related command classes for the _scheme-set_ command.
|
44
|
+
def self.see_also_commands
|
45
|
+
[HTTY::CLI::Commands::Address, HTTY::CLI::Commands::PortSet]
|
46
|
+
end
|
47
|
+
|
48
|
+
# Initializes a new HTTY::CLI::SchemeSet with attribute values specified in
|
49
|
+
# the _attributes_ hash.
|
50
|
+
#
|
51
|
+
# Valid _attributes_ keys include:
|
52
|
+
#
|
53
|
+
# * <tt>:arguments</tt>
|
54
|
+
# * <tt>:session</tt>
|
55
|
+
def initialize(attributes={})
|
56
|
+
super attributes
|
57
|
+
@arguments.collect! do |a|
|
58
|
+
a.gsub(/:\/\/$/, '')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Performs the _scheme-set_ command.
|
63
|
+
def perform
|
64
|
+
add_request_if_has_response do |request|
|
65
|
+
request.scheme_set(*arguments)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# Defines HTTY::CLI::Commands::Status.
|
2
|
+
|
3
|
+
require File.expand_path("#{File.dirname __FILE__}/../command")
|
4
|
+
require File.expand_path("#{File.dirname __FILE__}/../display")
|
5
|
+
require File.expand_path("#{File.dirname __FILE__}/body_response")
|
6
|
+
require File.expand_path("#{File.dirname __FILE__}/headers_response")
|
7
|
+
|
8
|
+
module HTTY; end
|
9
|
+
|
10
|
+
class HTTY::CLI; end
|
11
|
+
|
12
|
+
module HTTY::CLI::Commands; end
|
13
|
+
|
14
|
+
# Encapsulates the _status_ command.
|
15
|
+
class HTTY::CLI::Commands::Status < HTTY::CLI::Command
|
16
|
+
|
17
|
+
include HTTY::CLI::Display
|
18
|
+
|
19
|
+
# Returns the name of a category under which help for the _status_ command
|
20
|
+
# should appear.
|
21
|
+
def self.category
|
22
|
+
'Inspecting Responses'
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns the help text for the _status_ command.
|
26
|
+
def self.help
|
27
|
+
'Displays the status of the response'
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns the extended help text for the _status_ command.
|
31
|
+
def self.help_extended
|
32
|
+
'Displays the status signal received in the response. Does not ' +
|
33
|
+
"communicate with the endpoint.\n" +
|
34
|
+
"\n" +
|
35
|
+
'Status is displayed automatically when a response is received.'
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns related command classes for the _status_ command.
|
39
|
+
def self.see_also_commands
|
40
|
+
[HTTY::CLI::Commands::BodyResponse, HTTY::CLI::Commands::HeadersResponse]
|
41
|
+
end
|
42
|
+
|
43
|
+
# Performs the _status_ command.
|
44
|
+
def perform
|
45
|
+
unless (response = session.last_response)
|
46
|
+
raise HTTY::NoResponseError
|
47
|
+
end
|
48
|
+
show_response response
|
49
|
+
self
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# Defines HTTY::CLI::Commands::Undo.
|
2
|
+
|
3
|
+
require File.expand_path("#{File.dirname __FILE__}/../command")
|
4
|
+
|
5
|
+
module HTTY; end
|
6
|
+
|
7
|
+
class HTTY::CLI; end
|
8
|
+
|
9
|
+
module HTTY::CLI::Commands; end
|
10
|
+
|
11
|
+
# Encapsulates the _undo_ command.
|
12
|
+
class HTTY::CLI::Commands::Undo < HTTY::CLI::Command
|
13
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Defines HTTY::CLI::Commands::UserinfoClear.
|
2
|
+
|
3
|
+
require File.expand_path("#{File.dirname __FILE__}/../command")
|
4
|
+
require File.expand_path("#{File.dirname __FILE__}/userinfo_unset")
|
5
|
+
|
6
|
+
module HTTY; end
|
7
|
+
|
8
|
+
class HTTY::CLI; end
|
9
|
+
|
10
|
+
module HTTY::CLI::Commands; end
|
11
|
+
|
12
|
+
# Encapsulates the _userinfo-clear_ command.
|
13
|
+
class HTTY::CLI::Commands::UserinfoClear < HTTY::CLI::Command
|
14
|
+
|
15
|
+
# Returns the command that the _userinfo-clear_ command is an alias for.
|
16
|
+
def self.alias_for
|
17
|
+
HTTY::CLI::Commands::UserinfoUnset
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# Defines HTTY::CLI::Commands::UserinfoSet.
|
2
|
+
|
3
|
+
require File.expand_path("#{File.dirname __FILE__}/../command")
|
4
|
+
require File.expand_path("#{File.dirname __FILE__}/../url_escaping")
|
5
|
+
require File.expand_path("#{File.dirname __FILE__}/address")
|
6
|
+
require File.expand_path("#{File.dirname __FILE__}/userinfo_unset")
|
7
|
+
|
8
|
+
module HTTY; end
|
9
|
+
|
10
|
+
class HTTY::CLI; end
|
11
|
+
|
12
|
+
module HTTY::CLI::Commands; end
|
13
|
+
|
14
|
+
# Encapsulates the _userinfo-set_ command.
|
15
|
+
class HTTY::CLI::Commands::UserinfoSet < HTTY::CLI::Command
|
16
|
+
|
17
|
+
include HTTY::CLI::UrlEscaping
|
18
|
+
|
19
|
+
# Returns the name of a category under which help for the _userinfo-set_
|
20
|
+
# command should appear.
|
21
|
+
def self.category
|
22
|
+
'Navigation'
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns the arguments for the command-line usage of the _userinfo-set_
|
26
|
+
# command.
|
27
|
+
def self.command_line_arguments
|
28
|
+
'userinfo'
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns the help text for the _userinfo-set_ command.
|
32
|
+
def self.help
|
33
|
+
"Sets the userinfo of the request's address"
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns the extended help text for the _userinfo-set_ command.
|
37
|
+
def self.help_extended
|
38
|
+
'Sets the userinfo used for the request. Does not communicate with the ' +
|
39
|
+
"endpoint.\n" +
|
40
|
+
"\n" +
|
41
|
+
'The console prompt shows the address for the current request.'
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns related command classes for the _userinfo-set_ command.
|
45
|
+
def self.see_also_commands
|
46
|
+
[HTTY::CLI::Commands::UserinfoUnset, HTTY::CLI::Commands::Address]
|
47
|
+
end
|
48
|
+
|
49
|
+
# Performs the _userinfo-set_ command.
|
50
|
+
def perform
|
51
|
+
add_request_if_has_response do |request|
|
52
|
+
request.userinfo_set(*escape_or_warn_of_escape_sequences(arguments))
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# Defines HTTY::CLI::Commands::UserinfoUnset.
|
2
|
+
|
3
|
+
require File.expand_path("#{File.dirname __FILE__}/../command")
|
4
|
+
require File.expand_path("#{File.dirname __FILE__}/address")
|
5
|
+
require File.expand_path("#{File.dirname __FILE__}/userinfo_set")
|
6
|
+
|
7
|
+
module HTTY; end
|
8
|
+
|
9
|
+
class HTTY::CLI; end
|
10
|
+
|
11
|
+
module HTTY::CLI::Commands; end
|
12
|
+
|
13
|
+
# Encapsulates the _userinfo-unset_ command.
|
14
|
+
class HTTY::CLI::Commands::UserinfoUnset < HTTY::CLI::Command
|
15
|
+
|
16
|
+
# Returns the name of a category under which help for the _userinfo-unset_
|
17
|
+
# command should appear.
|
18
|
+
def self.category
|
19
|
+
'Navigation'
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns the help text for the _userinfo-unset_ command.
|
23
|
+
def self.help
|
24
|
+
"Removes the userinfo from the request's address"
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns the extended help text for the _userinfo-unset_ command.
|
28
|
+
def self.help_extended
|
29
|
+
'Removes the userinfo used for the request. Does not communicate with ' +
|
30
|
+
"the endpoint.\n" +
|
31
|
+
"\n" +
|
32
|
+
'The console prompt shows the address for the current request.'
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns related command classes for the _userinfo-unset_ command.
|
36
|
+
def self.see_also_commands
|
37
|
+
[HTTY::CLI::Commands::UserinfoSet, HTTY::CLI::Commands::Address]
|
38
|
+
end
|
39
|
+
|
40
|
+
# Performs the _userinfo-unset_ command.
|
41
|
+
def perform
|
42
|
+
add_request_if_has_response do |request|
|
43
|
+
request.userinfo_unset(*arguments)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Defines HTTY::CLI::CookieClearingCommand.
|
2
|
+
|
3
|
+
require File.expand_path("#{File.dirname __FILE__}/display")
|
4
|
+
|
5
|
+
module HTTY; end
|
6
|
+
|
7
|
+
class HTTY::CLI; end
|
8
|
+
|
9
|
+
# Encapsulates behavior common to all HTTY::CLI::Command subclasses that can
|
10
|
+
# result in cookies being cleared automatically.
|
11
|
+
module HTTY::CLI::CookieClearingCommand
|
12
|
+
|
13
|
+
include HTTY::CLI::Display
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
def notify_if_cookies_cleared(request)
|
18
|
+
had_cookies = !request.cookies.empty?
|
19
|
+
new_request = yield
|
20
|
+
if (had_cookies && new_request.cookies.empty?)
|
21
|
+
puts notice('Cookies cleared')
|
22
|
+
end
|
23
|
+
new_request
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
# Defines HTTY::CLI::Display.
|
2
|
+
|
3
|
+
module HTTY; end
|
4
|
+
|
5
|
+
class HTTY::CLI; end
|
6
|
+
|
7
|
+
# Encapsulates the display logic of _htty_'s command-line interface.
|
8
|
+
module HTTY::CLI::Display
|
9
|
+
|
10
|
+
FORMATS = {:bold => '1',
|
11
|
+
:underlined => '4',
|
12
|
+
:blinking => '5',
|
13
|
+
:inverse => '7',
|
14
|
+
:foreground_black => '30',
|
15
|
+
:foreground_dark_red => '31',
|
16
|
+
:foreground_dark_green => '32',
|
17
|
+
:foreground_dark_yellow => '33',
|
18
|
+
:foreground_dark_blue => '34',
|
19
|
+
:foreground_dark_magenta => '35',
|
20
|
+
:foreground_dark_cyan => '36',
|
21
|
+
:foreground_light_gray => '37',
|
22
|
+
:foreground_dark_default => '39',
|
23
|
+
:foreground_dark_gray => '1;30',
|
24
|
+
:foreground_red => '1;31',
|
25
|
+
:foreground_green => '1;32',
|
26
|
+
:foreground_yellow => '1;33',
|
27
|
+
:foreground_blue => '1;34',
|
28
|
+
:foreground_magenta => '1;35',
|
29
|
+
:foreground_cyan => '1;36',
|
30
|
+
:foreground_white => '1;37',
|
31
|
+
:foreground_default => '1;39',
|
32
|
+
:background_black => '40',
|
33
|
+
:background_dark_red => '41',
|
34
|
+
:background_dark_green => '42',
|
35
|
+
:background_dark_yellow => '43',
|
36
|
+
:background_dark_blue => '44',
|
37
|
+
:background_dark_magenta => '45',
|
38
|
+
:background_dark_cyan => '46',
|
39
|
+
:background_light_gray => '47',
|
40
|
+
:background_default => '49'}
|
41
|
+
|
42
|
+
def format(string, *attributes)
|
43
|
+
segments = attributes.collect do |a|
|
44
|
+
"\x1b[#{FORMATS[a]}m"
|
45
|
+
end
|
46
|
+
segments << string
|
47
|
+
segments << "\x1b[0m"
|
48
|
+
segments.join ''
|
49
|
+
end
|
50
|
+
|
51
|
+
def rescuing_from(*exception_classes)
|
52
|
+
yield
|
53
|
+
rescue Interrupt
|
54
|
+
nil
|
55
|
+
rescue *exception_classes => e
|
56
|
+
$stderr.puts notice(sentence_case(e.message))
|
57
|
+
nil
|
58
|
+
end
|
59
|
+
|
60
|
+
def indent(string, column=2)
|
61
|
+
"#{' ' * column}#{string}"
|
62
|
+
end
|
63
|
+
|
64
|
+
def logotype
|
65
|
+
format ' htty ', :bold, :background_dark_red, :foreground_yellow
|
66
|
+
end
|
67
|
+
|
68
|
+
def notice(string)
|
69
|
+
"*** #{string}"
|
70
|
+
end
|
71
|
+
|
72
|
+
def normal(string)
|
73
|
+
return string
|
74
|
+
# format string, :foreground_dark_default
|
75
|
+
end
|
76
|
+
|
77
|
+
def say(message, style=:normal)
|
78
|
+
puts send(style, notice(message))
|
79
|
+
end
|
80
|
+
|
81
|
+
def say_goodbye
|
82
|
+
say 'Happy Trails To You!'
|
83
|
+
end
|
84
|
+
|
85
|
+
def say_header(message, style=:normal)
|
86
|
+
puts send(style, notice('')) + highlight(messag)
|
87
|
+
end
|
88
|
+
|
89
|
+
def say_hello
|
90
|
+
puts normal(notice('Welcome to ')) + logotype + normal(', the ') +
|
91
|
+
strong('HTTP TTY') + normal('. Heck To The Yeah!')
|
92
|
+
end
|
93
|
+
|
94
|
+
def show_headers(headers, show_asterisk_next_to=nil)
|
95
|
+
asterisk_symbol = nil
|
96
|
+
margin = headers.inject 0 do |result, header|
|
97
|
+
header_name = header.first
|
98
|
+
asterisk_symbol ||= (header_name == show_asterisk_next_to) ? '*' : nil
|
99
|
+
asterisk = (header_name == show_asterisk_next_to) ? asterisk_symbol : ''
|
100
|
+
[(header_name.length + asterisk.length), result].max
|
101
|
+
end
|
102
|
+
headers.each do |name, value|
|
103
|
+
asterisk = (name == show_asterisk_next_to) ? asterisk_symbol : nil
|
104
|
+
puts "#{name.rjust margin - asterisk.to_s.length}:#{strong asterisk} " +
|
105
|
+
value
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def show_request(request)
|
110
|
+
method = format(" #{request.request_method.to_s.upcase} ", :inverse)
|
111
|
+
print "#{method} "
|
112
|
+
cookies_asterisk = request.cookies.empty? ? '' : strong('*')
|
113
|
+
body_length = request.body.to_s.length
|
114
|
+
body_size = body_length.zero? ? 'empty' : "#{body_length}-character"
|
115
|
+
puts [request.uri,
|
116
|
+
pluralize('header', request.headers.length) + cookies_asterisk,
|
117
|
+
"#{body_size} body"].join(' -- ')
|
118
|
+
end
|
119
|
+
|
120
|
+
def show_response(response)
|
121
|
+
code, description = response.status
|
122
|
+
case code.to_i
|
123
|
+
when 100...200, 300...400
|
124
|
+
print format(" #{code} ", :background_dark_blue, :foreground_white)
|
125
|
+
when 200...300
|
126
|
+
print format(" #{code} ", :background_dark_green, :foreground_black)
|
127
|
+
when 500...600
|
128
|
+
print format(" #{code} ", :inverse, :blinking,
|
129
|
+
:background_black, :foreground_yellow)
|
130
|
+
else
|
131
|
+
print format(" #{code} ", :background_dark_red, :foreground_white)
|
132
|
+
end
|
133
|
+
print ' '
|
134
|
+
cookies_asterisk = response.cookies.empty? ? '' : strong('*')
|
135
|
+
body_length = response.body.to_s.length
|
136
|
+
body_size = body_length.zero? ? 'empty' : "#{body_length}-character"
|
137
|
+
puts([description,
|
138
|
+
pluralize('header', response.headers.length) + cookies_asterisk,
|
139
|
+
"#{body_size} body"].join(' -- '))
|
140
|
+
end
|
141
|
+
|
142
|
+
def strong(string)
|
143
|
+
format string, :bold
|
144
|
+
end
|
145
|
+
|
146
|
+
def word_wrap(text, column=nil)
|
147
|
+
word_wrap_indented(text, (0..(column || 80)))
|
148
|
+
end
|
149
|
+
|
150
|
+
# Adapted from
|
151
|
+
# http://api.rubyonrails.org/classes/ActionView/Helpers/TextHelper.html#M002281
|
152
|
+
def word_wrap_indented(text, columns=2..80)
|
153
|
+
indent_by, wrap_at = columns.min, columns.max - columns.min
|
154
|
+
text.split("\n").collect do |line|
|
155
|
+
(wrap_at < line.length) ?
|
156
|
+
line.gsub(/(.{1,#{wrap_at}})(\s+|$)/, "\\1\n").strip :
|
157
|
+
line
|
158
|
+
end.join("\n").split("\n").collect do |line|
|
159
|
+
indent line, indent_by
|
160
|
+
end.join "\n"
|
161
|
+
end
|
162
|
+
|
163
|
+
private
|
164
|
+
|
165
|
+
def pluralize(word, number)
|
166
|
+
case number
|
167
|
+
when 0
|
168
|
+
"no #{word}s"
|
169
|
+
when 1
|
170
|
+
"1 #{word}"
|
171
|
+
else
|
172
|
+
"#{number} #{word}s"
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def sentence_case(text)
|
177
|
+
text.gsub(/^./) do |letter|
|
178
|
+
letter.upcase
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|