working_set 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.ruby-version +1 -0
- data/API_FOR_EDITOR_INTEGRATION.md +97 -0
- data/CHANGELOG.md +15 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +107 -0
- data/Rakefile +2 -0
- data/bin/working_set +4 -0
- data/lib/api_input_actor.rb +75 -0
- data/lib/basic_actor.rb +8 -0
- data/lib/colors.rb +16 -0
- data/lib/live_updater_actor.rb +29 -0
- data/lib/set_builder_actor.rb +23 -0
- data/lib/set_builder_adapter.rb +2 -0
- data/lib/set_builder_adapter/ag.rb +132 -0
- data/lib/set_viewer_actor.rb +146 -0
- data/lib/user_input_actor.rb +177 -0
- data/lib/view/base.rb +13 -0
- data/lib/view/help.rb +28 -0
- data/lib/view/welcome_user.rb +40 -0
- data/lib/view/working_set.rb +313 -0
- data/lib/working_set.rb +34 -0
- data/lib/working_set_cli.rb +205 -0
- data/lib/working_set_item.rb +40 -0
- data/working_set.gemspec +35 -0
- metadata +226 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a8d080e5e195b802c64757728b39a21a747e029c9a067bd523a115208aed4038
|
4
|
+
data.tar.gz: b02705986887a8ff43aeb8945e3356032f97b2ed6e05458f4438e2b55e1f5ded
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b5699a5b2f85909e67ec262ed787ba94e47015874fb4e931b0bd646229bb09ae8b1737705273d3152bcbc54dabda3a50adc3033c49332c4d2133cd03c1e5963a
|
7
|
+
data.tar.gz: 119b23428f7bbbae2025c186371c0a857927cd58230b153c6b327c77d0234b17054a50ae81760d8e9f8b27554dcea8f7cef73be61db0f99838cacecbfa354c1a
|
data/.gitignore
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.7.1
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# API for Editor Integration
|
2
|
+
|
3
|
+
Most advanced text editors can be extended with plugins and other
|
4
|
+
customizations. Working Set was built to be a companion to your text editor.
|
5
|
+
Since the original author of Working Set uses Vim, that's the first editor
|
6
|
+
integration that was created.
|
7
|
+
|
8
|
+
At time of writing, it's also the only one that exists.
|
9
|
+
|
10
|
+
Should someone wish to integrate another editor, e.g. Emacs, this is the
|
11
|
+
information they'd need to know.
|
12
|
+
|
13
|
+
## Overview
|
14
|
+
|
15
|
+
When `working_set` (WS) starts, it creates a socket file in the current
|
16
|
+
directory (named `.working_set_socket` by default). WS listens to the socket for
|
17
|
+
`message`s. When it receives a `message`, it will asyncronously perform whatever
|
18
|
+
task is required, and then (possibly) send a `message` as a response to the
|
19
|
+
client via the socket file.
|
20
|
+
|
21
|
+
You can see a working client implementation in the [Vim
|
22
|
+
plugin](https://github.com/coderifous/working-set.vim).
|
23
|
+
|
24
|
+
## Message Format
|
25
|
+
|
26
|
+
Messages to Working Set are serialized JSON and have these keys:
|
27
|
+
|
28
|
+
message: a single word, often a command
|
29
|
+
|
30
|
+
args: optional object, specific to a command.
|
31
|
+
|
32
|
+
options: optional object, specific to a command.
|
33
|
+
|
34
|
+
Replies from Working Set will be similiar, always having a `message` key, but
|
35
|
+
additional keys may vary.
|
36
|
+
|
37
|
+
## Messages from Client to Server (Working Set)
|
38
|
+
|
39
|
+
#### search_changed
|
40
|
+
|
41
|
+
This message tells Working Set to update the search results.
|
42
|
+
|
43
|
+
Examples:
|
44
|
+
|
45
|
+
{ "message": "search_changed", "args": "foo" }
|
46
|
+
|
47
|
+
{ "message": "search_changed", "args": "foo", "options": { "whole_word": true } }
|
48
|
+
|
49
|
+
#### select_next_item, et al
|
50
|
+
|
51
|
+
This message tells Working Set to select the next item in the list. There are a
|
52
|
+
few similar messages.
|
53
|
+
|
54
|
+
Example:
|
55
|
+
|
56
|
+
{ "message": "select_next_item" }
|
57
|
+
|
58
|
+
Similar messages:
|
59
|
+
* select_prev_item
|
60
|
+
* select_next_file
|
61
|
+
* select_prev_file
|
62
|
+
|
63
|
+
### tell_selected_item
|
64
|
+
|
65
|
+
Working Set will respond to this message with a "selected_item" message.
|
66
|
+
|
67
|
+
### tell_selected_item_content
|
68
|
+
|
69
|
+
Working Set will respond to this message with a "selected_item_content" message.
|
70
|
+
|
71
|
+
### show_match_lines_toggled
|
72
|
+
|
73
|
+
Working Set will toggle whether match lines are showed.
|
74
|
+
|
75
|
+
### refresh
|
76
|
+
|
77
|
+
Working Set will re-run the current search and update results.
|
78
|
+
|
79
|
+
## Messages from Server to Client (editor)
|
80
|
+
|
81
|
+
### selected_item
|
82
|
+
|
83
|
+
Example:
|
84
|
+
|
85
|
+
{ "message": "selected_item", "file_path": "app/foo.rb", "row": 1, "column": 10 }
|
86
|
+
|
87
|
+
Clients can do whatever they want when they recieve this message, one useful
|
88
|
+
response might be to jump to the specified file and location.
|
89
|
+
|
90
|
+
### selected_item_content
|
91
|
+
|
92
|
+
Example:
|
93
|
+
|
94
|
+
{ "message": "selected_item_content", data: "foo bar baz" }
|
95
|
+
|
96
|
+
Clients can do whatever they want when they recieve this message, one useful
|
97
|
+
response might be to insert the requested content where the user is typing.
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# Change log
|
2
|
+
|
3
|
+
## [v1.0.1] - 2020-09-07
|
4
|
+
|
5
|
+
### Fixed
|
6
|
+
* Fix issue with scrolling via up/down arrows
|
7
|
+
* Fix issue with preserving whole_word option on refresh
|
8
|
+
|
9
|
+
## [v1.0.0] - 2020-09-05
|
10
|
+
|
11
|
+
### Initial Release
|
12
|
+
* Refactoring and prep for release.
|
13
|
+
* Features search and navigation features.
|
14
|
+
|
15
|
+
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Jim Garvin
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
# working_set
|
2
|
+
|
3
|
+
Companion to your editor that makes searching, and using search results for
|
4
|
+
jumping around, super nice.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Installing the gem adds the working_set command to your path.
|
9
|
+
|
10
|
+
$ gem install working_set
|
11
|
+
|
12
|
+
Install the plugin for your editor.
|
13
|
+
|
14
|
+
* [Vim Plugin](https://github.com/coderifous/working-set.vim)
|
15
|
+
|
16
|
+
Note: Currently there's only a plugin for Vim, however Working Set will be
|
17
|
+
compatible with any editor that can be extended and communicate via socket.
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Run the working_set command in your project's directory.
|
22
|
+
|
23
|
+
$ cd my-project
|
24
|
+
$ working_set
|
25
|
+
|
26
|
+
working_set is now running, listening on a file socket, ready to receive
|
27
|
+
commands from your text editor which you should run in a separate terminal but
|
28
|
+
in the same directory.
|
29
|
+
|
30
|
+
$ cd my-project
|
31
|
+
$ vim
|
32
|
+
|
33
|
+
## Options
|
34
|
+
|
35
|
+
Run `working_set -h` to see a list of command line options:
|
36
|
+
|
37
|
+
--watch | -w
|
38
|
+
|
39
|
+
Tells working_set to monitor the filesystem for changes and refresh the
|
40
|
+
search results automatically when changes are detected. The value should be
|
41
|
+
point at the directory you want to monitor.
|
42
|
+
|
43
|
+
Example: --watch=app
|
44
|
+
|
45
|
+
Default: none, search results will not automatically refresh.
|
46
|
+
|
47
|
+
--context | -c
|
48
|
+
|
49
|
+
Sets number of contextual lines to show around matches.
|
50
|
+
|
51
|
+
Example: --count=3
|
52
|
+
|
53
|
+
Default: 1
|
54
|
+
|
55
|
+
--socket | -s
|
56
|
+
|
57
|
+
Sets the path for the socket file to create.
|
58
|
+
|
59
|
+
Example: --socket=/tmp/my-special-project
|
60
|
+
|
61
|
+
Default: .working_set_socket
|
62
|
+
|
63
|
+
--help | -h
|
64
|
+
|
65
|
+
Show help.
|
66
|
+
|
67
|
+
## Commands in working_set
|
68
|
+
|
69
|
+
You can press '?' in working_set to see key bindings:
|
70
|
+
|
71
|
+
? - display help
|
72
|
+
q - quit
|
73
|
+
j - select next match
|
74
|
+
k - select previous match
|
75
|
+
ctrl-n - select first match in next file
|
76
|
+
ctrl-p - select first match in previous file
|
77
|
+
enter - Tell editor to jump to match
|
78
|
+
down arrow - scroll down without changing selection
|
79
|
+
up arrow - scroll up without changing selection
|
80
|
+
r - refresh search results
|
81
|
+
[ - decrease context lines
|
82
|
+
] - increase context lines
|
83
|
+
z - toggle showing match lines vs just matched files
|
84
|
+
y - copy selected match to system clipboard
|
85
|
+
Y - copy selected match + context to system clipboard
|
86
|
+
|
87
|
+
## Todo
|
88
|
+
* Add support for searching straight from working_set using "/" key.
|
89
|
+
* Add support for setting search argument prefix as working_set command argument.
|
90
|
+
e.g. --prefix="--ignore=tmp,vendor"
|
91
|
+
* Add support for bookmarks.
|
92
|
+
* Add support for search history.
|
93
|
+
* Add support for customizing key bindings.
|
94
|
+
* Document protocol so other plugin editors can exist.
|
95
|
+
* Document adapter so other search tools can be used.
|
96
|
+
|
97
|
+
## Development
|
98
|
+
|
99
|
+
1) Fork the repo, clone the source code.
|
100
|
+
2) run `bundle install` to install dependencies.
|
101
|
+
3) run `bin/working_set -d` to execute the program with debug logging enabled
|
102
|
+
4) watch the debug messages: `tail -f working_set.log`
|
103
|
+
5) make code changes, restart `working_set` to see their effect.
|
104
|
+
|
105
|
+
Please do submit pull requests to add features, fix bugs, etc. Please discuss
|
106
|
+
before spending lots of time on large changes.
|
107
|
+
|
data/Rakefile
ADDED
data/bin/working_set
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
class ApiInputActor
|
5
|
+
include BasicActor
|
6
|
+
include Celluloid::IO
|
7
|
+
|
8
|
+
finalizer :close_server
|
9
|
+
|
10
|
+
# Since the inputs are translated into internal actor messages, we can have a
|
11
|
+
# little extra security by only permitting certain messages, because some
|
12
|
+
# messages are really for internal use only.
|
13
|
+
PERMITTED_MESSAGES_LIST = %w(
|
14
|
+
search_changed
|
15
|
+
select_next_item
|
16
|
+
select_prev_item
|
17
|
+
select_next_file
|
18
|
+
select_prev_file
|
19
|
+
tell_selected_item
|
20
|
+
tell_selected_item_content
|
21
|
+
show_match_lines_toggled
|
22
|
+
refresh
|
23
|
+
)
|
24
|
+
|
25
|
+
def initialize
|
26
|
+
subscribe "respond_client", :respond_client
|
27
|
+
@server = UNIXServer.new $SOCKET_PATH
|
28
|
+
async.watch_input
|
29
|
+
end
|
30
|
+
|
31
|
+
def watch_input
|
32
|
+
loop do
|
33
|
+
@client = @server.accept
|
34
|
+
while input = @client.gets
|
35
|
+
process_input(input.chomp)
|
36
|
+
end
|
37
|
+
@client.close
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def process_input(input)
|
42
|
+
debug_message "input: #{input.inspect}"
|
43
|
+
|
44
|
+
parsed = JSON.parse(input)
|
45
|
+
message = parsed["message"]
|
46
|
+
args = parsed["args"]
|
47
|
+
options = parsed["options"]
|
48
|
+
|
49
|
+
debug_message "message: #{message.inspect}\nargs: #{args.inspect}\noptions: #{options.inspect}"
|
50
|
+
|
51
|
+
unless PERMITTED_MESSAGES_LIST.include?(message)
|
52
|
+
debug_message "Message not permitted, ignoring."
|
53
|
+
return
|
54
|
+
end
|
55
|
+
|
56
|
+
publish *[message, args, options].compact
|
57
|
+
end
|
58
|
+
|
59
|
+
def close_server
|
60
|
+
debug_message "closing server" if @server
|
61
|
+
@server.close if @server
|
62
|
+
File.delete($SOCKET_PATH)
|
63
|
+
end
|
64
|
+
|
65
|
+
def respond_client(_, message, extras={})
|
66
|
+
payload = { message: message }.merge(extras)
|
67
|
+
debug_message "Responding #{payload.inspect}"
|
68
|
+
@client.puts payload.to_json if @client
|
69
|
+
end
|
70
|
+
|
71
|
+
def send_message(msg, arg)
|
72
|
+
debug_message "Sending #{msg}, #{arg}"
|
73
|
+
@client.puts [msg, arg].join("|") if @client
|
74
|
+
end
|
75
|
+
end
|
data/lib/basic_actor.rb
ADDED
data/lib/colors.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
if defined?(Ncurses)
|
2
|
+
Colors = {
|
3
|
+
blue: { pair: [Ncurses::COLOR_BLUE, -1] },
|
4
|
+
cyan: { pair: [Ncurses::COLOR_CYAN, -1] },
|
5
|
+
red: { pair: [Ncurses::COLOR_RED, -1] },
|
6
|
+
white: { pair: [Ncurses::COLOR_WHITE, -1] },
|
7
|
+
green: { pair: [Ncurses::COLOR_GREEN, -1] },
|
8
|
+
yellow: { pair: [Ncurses::COLOR_YELLOW, -1] }
|
9
|
+
}
|
10
|
+
|
11
|
+
Colors.each_with_index do |(k,v),i|
|
12
|
+
v[:number] = i + 1
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
API_PORT_NUMBER = 3930
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'listen'
|
2
|
+
|
3
|
+
class LiveUpdaterActor
|
4
|
+
include BasicActor
|
5
|
+
|
6
|
+
finalizer :stop
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@listener = build
|
10
|
+
start
|
11
|
+
end
|
12
|
+
|
13
|
+
def build
|
14
|
+
Listen.to($LIVE_UPDATE_WATCH_PATH) do |modified, added, removed|
|
15
|
+
debug_message "modified absolute path: #{modified}"
|
16
|
+
debug_message "added absolute path: #{added}"
|
17
|
+
debug_message "removed absolute path: #{removed}"
|
18
|
+
publish "refresh"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def start
|
23
|
+
@listener.start
|
24
|
+
end
|
25
|
+
|
26
|
+
def stop
|
27
|
+
@listener.stop
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class SetBuilderActor
|
2
|
+
include BasicActor
|
3
|
+
|
4
|
+
attr_accessor :adapter
|
5
|
+
|
6
|
+
DEFAULT_ADAPTER_CLASS = SetBuilderAdapter::Ag
|
7
|
+
|
8
|
+
def initialize(initial_adapter = DEFAULT_ADAPTER_CLASS.new)
|
9
|
+
subscribe "search_changed", :build_working_set
|
10
|
+
self.adapter = initial_adapter
|
11
|
+
end
|
12
|
+
|
13
|
+
def build_working_set(_, search, options={})
|
14
|
+
debug_message "search: #{search.inspect} options: #{options.inspect}"
|
15
|
+
begin
|
16
|
+
working_set = adapter.build_working_set(search, options)
|
17
|
+
publish "set_build_finished", working_set
|
18
|
+
rescue StandardError => e
|
19
|
+
publish "set_build_failed", e
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|