search_ui 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/lib/search_ui/search.rb +67 -41
- data/lib/search_ui/version.rb +1 -1
- data/search_ui.gemspec +4 -4
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e7d5feb21158fa490f48360724a1e4bd0110a1dd64d89c6bbb79be5bf8de3019
|
|
4
|
+
data.tar.gz: e162cee1ef6035b7ea1305360c88d260b5ebb0b5ecf91fe573a2d0be5c50eaca
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 66b6d79977ab604dc5cb1fec8bb6c5e9467ac80af1a7ad4e95dab2466aa6c5d48f98e5b4e3fd820a1522f16dfcd88e02690759a09ef8d906f21a3d8e6d32a079
|
|
7
|
+
data.tar.gz: eebad124b4790a0059b7ce0fd7b337cbb55d439035a04e869ca6d040130a333b3d63531ed21d40b0745200493831cc653513ff3c4b7d2324a94172ac67d8fa38
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.2.0
|
data/lib/search_ui/search.rb
CHANGED
|
@@ -18,35 +18,54 @@ class SearchUI::Search
|
|
|
18
18
|
include Term::ANSIColor
|
|
19
19
|
extend Term::ANSIColor
|
|
20
20
|
|
|
21
|
-
#
|
|
21
|
+
# Represents the current state of the search interface.
|
|
22
22
|
#
|
|
23
|
-
# @
|
|
24
|
-
#
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
#
|
|
23
|
+
# @attr answer [ String ] the current input string entered by the user
|
|
24
|
+
# @attr selector [ Integer ] the index of the currently selected match
|
|
25
|
+
State = Struct.new(:answer, :selector)
|
|
26
|
+
|
|
27
|
+
# Initializes a new SearchUI::Search instance to manage an interactive
|
|
28
|
+
# console search interface. This method sets up the filtering logic, display
|
|
29
|
+
# formatting, and selection criteria required to drive the search loop, as
|
|
30
|
+
# well as the output stream and prompt.
|
|
31
|
+
#
|
|
32
|
+
# @param match [ Proc ] a procedure that accepts a search pattern string and returns
|
|
33
|
+
# an array of matching objects.
|
|
34
|
+
# @param query [ Proc ] a procedure that accepts the current answer, the list of
|
|
35
|
+
# matches, and the current selector index to generate the string representation
|
|
36
|
+
# of the results list.
|
|
37
|
+
# @param found [ Proc ] a procedure that accepts the current answer, the list of
|
|
38
|
+
# matches, and the current selector index to determine the final selected object.
|
|
39
|
+
# @param output [ IO ] the output stream where the interface will be rendered.
|
|
40
|
+
# Defaults to STDOUT.
|
|
41
|
+
# @param prompt [ String ] a format string used as the user prompt.
|
|
42
|
+
# Defaults to 'Search? %s'.
|
|
43
|
+
# @param state [ SearchUI::Search::State, nil ] an initial state object containing
|
|
44
|
+
# the starting answer and selector position. Defaults to a new State with an
|
|
45
|
+
# empty answer and selector set to 0.
|
|
33
46
|
def initialize(
|
|
34
47
|
match:,
|
|
35
48
|
query:,
|
|
36
49
|
found:,
|
|
37
50
|
output: STDOUT,
|
|
38
|
-
prompt: 'Search? %s'
|
|
51
|
+
prompt: 'Search? %s',
|
|
52
|
+
state: nil
|
|
39
53
|
)
|
|
40
54
|
@match = match
|
|
41
55
|
@query = query
|
|
42
56
|
@found = found
|
|
43
57
|
@output = output
|
|
44
58
|
@prompt = prompt
|
|
45
|
-
@
|
|
46
|
-
@max_selector = nil
|
|
47
|
-
@answer = ''
|
|
59
|
+
@state = state || State.new('', 0)
|
|
48
60
|
end
|
|
49
61
|
|
|
62
|
+
# Reads the current internal state of the search interface, containing the
|
|
63
|
+
# current input answer and the active selection index.
|
|
64
|
+
#
|
|
65
|
+
# @return [ SearchUI::Search::State ] the current state object tracking
|
|
66
|
+
# the user's search progress and cursor position
|
|
67
|
+
attr_reader :state
|
|
68
|
+
|
|
50
69
|
# Starts the interactive search interface and handles user input until a
|
|
51
70
|
# selection is made or the process is cancelled.
|
|
52
71
|
#
|
|
@@ -54,16 +73,16 @@ class SearchUI::Search
|
|
|
54
73
|
# is made, or nil if the process is cancelled
|
|
55
74
|
def start
|
|
56
75
|
@output.print reset
|
|
57
|
-
@matches = @match.(@answer)
|
|
58
|
-
@selector = @selector.clamp(0, [ @matches.size - 1, 0 ].max)
|
|
59
|
-
result = @query.(@answer, @matches, @selector)
|
|
76
|
+
@matches = @match.(@state.answer)
|
|
77
|
+
@state.selector = @state.selector.clamp(0, [ @matches.size - 1, 0 ].max)
|
|
78
|
+
result = @query.(@state.answer, @matches, @state.selector)
|
|
60
79
|
loop do
|
|
61
80
|
@output.print clear_screen
|
|
62
|
-
@output.print move_home { @prompt % @answer + ?\n + result }
|
|
81
|
+
@output.print move_home { @prompt % @state.answer + ?\n + result }
|
|
63
82
|
case getc
|
|
64
83
|
when true
|
|
65
84
|
@output.print clear_screen, move_home, reset
|
|
66
|
-
if result = @found.(@answer, @matches, @selector)
|
|
85
|
+
if result = @found.(@state.answer, @matches, @state.selector)
|
|
67
86
|
return result
|
|
68
87
|
else
|
|
69
88
|
return nil
|
|
@@ -71,26 +90,33 @@ class SearchUI::Search
|
|
|
71
90
|
when false
|
|
72
91
|
return nil
|
|
73
92
|
end
|
|
74
|
-
@matches = @match.(@answer)
|
|
75
|
-
@selector = @selector.clamp(0, [ @matches.size - 1, 0 ].max)
|
|
76
|
-
result = @query.(@answer, @matches, @selector)
|
|
93
|
+
@matches = @match.(@state.answer)
|
|
94
|
+
@state.selector = @state.selector.clamp(0, [ @matches.size - 1, 0 ].max)
|
|
95
|
+
result = @query.(@state.answer, @matches, @state.selector)
|
|
77
96
|
end
|
|
78
97
|
end
|
|
79
98
|
|
|
80
99
|
private
|
|
81
100
|
|
|
82
|
-
# Reads and processes a single character input from
|
|
101
|
+
# Reads and processes a single character input from STDIN, handling special
|
|
83
102
|
# key sequences and updating the search state accordingly.
|
|
84
103
|
#
|
|
85
104
|
# This method manages raw terminal input to capture user keystrokes,
|
|
86
|
-
# interpreting control characters and escape sequences
|
|
87
|
-
#
|
|
88
|
-
#
|
|
105
|
+
# interpreting control characters and ANSI escape sequences:
|
|
106
|
+
# - Up/Down arrows: Navigate the result selector.
|
|
107
|
+
# - Enter (`\r`): Confirms the current selection.
|
|
108
|
+
# - Ctrl-C (`\x03`): Cancels the search operation.
|
|
109
|
+
# - Ctrl-K (`\v`): Clears the current search answer.
|
|
110
|
+
# - Backspace (`\x7f`): Deletes the last character of the answer.
|
|
111
|
+
# - Note: Any modification to the search answer resets the selector to 0.
|
|
112
|
+
#
|
|
113
|
+
# It temporarily disables terminal echo and sets raw mode to ensure proper
|
|
114
|
+
# input handling.
|
|
89
115
|
#
|
|
90
|
-
# @return [ Boolean, nil ]
|
|
91
|
-
#
|
|
92
|
-
#
|
|
93
|
-
#
|
|
116
|
+
# @return [ Boolean, nil ]
|
|
117
|
+
# - `true`: The Enter key was pressed to confirm selection.
|
|
118
|
+
# - `false`: Ctrl-C was pressed to cancel the operation.
|
|
119
|
+
# - `nil`: Input updated the search state or was ignored.
|
|
94
120
|
def getc
|
|
95
121
|
print hide_cursor
|
|
96
122
|
system 'stty raw -echo'
|
|
@@ -103,27 +129,27 @@ class SearchUI::Search
|
|
|
103
129
|
STDIN.getc == ?[ or return nil
|
|
104
130
|
STDIN.getc =~ /\A([AB])\z/ or return nil
|
|
105
131
|
if $1 == ?A
|
|
106
|
-
@selector -= 1
|
|
132
|
+
@state.selector -= 1
|
|
107
133
|
else
|
|
108
|
-
@selector += 1
|
|
134
|
+
@state.selector += 1
|
|
109
135
|
end
|
|
110
|
-
@selector = [ @selector, 0 ].max
|
|
136
|
+
@state.selector = [ @state.selector, 0 ].max
|
|
111
137
|
nil
|
|
112
138
|
when ?\r
|
|
113
139
|
true
|
|
114
140
|
when "\x7f"
|
|
115
|
-
@selector = 0
|
|
116
|
-
@answer.chop!
|
|
141
|
+
@state.selector = 0
|
|
142
|
+
@state.answer.chop!
|
|
117
143
|
nil
|
|
118
|
-
when
|
|
119
|
-
@selector = 0
|
|
120
|
-
@answer.clear
|
|
144
|
+
when ?\v
|
|
145
|
+
@state.selector = 0
|
|
146
|
+
@state.answer.clear
|
|
121
147
|
nil
|
|
122
148
|
when /\A[\x00-\x1f]\z/
|
|
123
149
|
nil
|
|
124
150
|
else
|
|
125
|
-
@selector = 0
|
|
126
|
-
@answer << c
|
|
151
|
+
@state.selector = 0
|
|
152
|
+
@state.answer << c
|
|
127
153
|
nil
|
|
128
154
|
end
|
|
129
155
|
ensure
|
data/lib/search_ui/version.rb
CHANGED
data/search_ui.gemspec
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
-
# stub: search_ui 0.
|
|
2
|
+
# stub: search_ui 0.2.0 ruby lib
|
|
3
3
|
|
|
4
4
|
Gem::Specification.new do |s|
|
|
5
5
|
s.name = "search_ui".freeze
|
|
6
|
-
s.version = "0.
|
|
6
|
+
s.version = "0.2.0".freeze
|
|
7
7
|
|
|
8
8
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
|
9
9
|
s.require_paths = ["lib".freeze]
|
|
@@ -18,13 +18,13 @@ Gem::Specification.new do |s|
|
|
|
18
18
|
s.licenses = ["MIT".freeze]
|
|
19
19
|
s.rdoc_options = ["--title".freeze, "SearchUI -- Search User Interface".freeze, "--main".freeze, "README.md".freeze]
|
|
20
20
|
s.required_ruby_version = Gem::Requirement.new(">= 2.0".freeze)
|
|
21
|
-
s.rubygems_version = "4.0.
|
|
21
|
+
s.rubygems_version = "4.0.10".freeze
|
|
22
22
|
s.summary = "Library to provide a user interface for searching in a console".freeze
|
|
23
23
|
s.test_files = ["spec/search_ui/wrapper_spec.rb".freeze, "spec/spec_helper.rb".freeze]
|
|
24
24
|
|
|
25
25
|
s.specification_version = 4
|
|
26
26
|
|
|
27
|
-
s.add_development_dependency(%q<gem_hadar>.freeze, [">= 2.17.
|
|
27
|
+
s.add_development_dependency(%q<gem_hadar>.freeze, [">= 2.17.1".freeze])
|
|
28
28
|
s.add_development_dependency(%q<rspec>.freeze, ["~> 3.0".freeze])
|
|
29
29
|
s.add_development_dependency(%q<simplecov>.freeze, ["~> 0.0".freeze])
|
|
30
30
|
s.add_development_dependency(%q<debug>.freeze, [">= 0".freeze])
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: search_ui
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Florian Frank
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 2.17.
|
|
18
|
+
version: 2.17.1
|
|
19
19
|
type: :development
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - ">="
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 2.17.
|
|
25
|
+
version: 2.17.1
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: rspec
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -158,7 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
158
158
|
- !ruby/object:Gem::Version
|
|
159
159
|
version: '0'
|
|
160
160
|
requirements: []
|
|
161
|
-
rubygems_version: 4.0.
|
|
161
|
+
rubygems_version: 4.0.10
|
|
162
162
|
specification_version: 4
|
|
163
163
|
summary: Library to provide a user interface for searching in a console
|
|
164
164
|
test_files:
|