htty 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|