yap-shell 0.3.1 → 0.4.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/Gemfile +1 -1
- data/addons/history/README.md +16 -0
- data/addons/history/history.rb +31 -77
- data/addons/keyboard_macros/keyboard_macros.rb +115 -43
- data/addons/keyboard_macros/lib/keyboard_macros/cycle.rb +38 -0
- data/addons/prompt_updates/prompt_updates.rb +1 -1
- data/addons/tab_completion/lib/tab_completion/basic_completion.rb +151 -0
- data/addons/tab_completion/tab_completion.rb +11 -7
- data/bin/yap +1 -12
- data/bin/yap-dev +12 -0
- data/lib/yap/configuration.rb +33 -0
- data/lib/yap/shell/aliases.rb +5 -1
- data/lib/yap/shell/builtins/alias.rb +2 -1
- data/lib/yap/shell/builtins.rb +2 -2
- data/lib/yap/shell/commands.rb +4 -4
- data/lib/yap/shell/evaluation.rb +22 -11
- data/lib/yap/shell/execution/builtin_command_execution.rb +2 -2
- data/lib/yap/shell/execution/file_system_command_execution.rb +2 -1
- data/lib/yap/shell/execution.rb +8 -8
- data/lib/yap/shell/repl.rb +13 -2
- data/lib/yap/shell/version.rb +1 -1
- data/lib/yap/shell.rb +3 -2
- data/lib/yap/world.rb +30 -5
- data/lib/yap.rb +9 -7
- data/rcfiles/.yaprc +42 -10
- data/yap-shell.gemspec +44 -4
- metadata +27 -51
- data/addons/history/Gemfile +0 -2
- data/addons/history/lib/history/buffer.rb +0 -204
- data/addons/history/lib/history/events.rb +0 -13
- data/addons/tab_completion/lib/tab_completion/file_completion.rb +0 -75
@@ -4,7 +4,7 @@ class TabCompletion < Addon
|
|
4
4
|
require 'tab_completion/completer'
|
5
5
|
require 'tab_completion/dsl_methods'
|
6
6
|
require 'tab_completion/custom_completion'
|
7
|
-
require 'tab_completion/
|
7
|
+
require 'tab_completion/basic_completion'
|
8
8
|
|
9
9
|
class CompletionResult
|
10
10
|
attr_accessor :text, :type, :descriptive_text
|
@@ -28,7 +28,7 @@ class TabCompletion < Addon
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
COMPLETIONS = [
|
31
|
+
COMPLETIONS = [ BasicCompletion ]
|
32
32
|
|
33
33
|
Color = Term::ANSIColor
|
34
34
|
|
@@ -37,15 +37,19 @@ class TabCompletion < Addon
|
|
37
37
|
)
|
38
38
|
|
39
39
|
STYLE_PROCS = Hash.new{ |h,k| h[k] = ->(text){ text } }.merge(
|
40
|
+
alias: -> (text){ Color.bold(Color.color("#ff00d7"){ text } ) },
|
41
|
+
builtin: -> (text){ Color.bold(Color.color("#d7af00"){ text } ) },
|
40
42
|
directory: -> (text){ Color.bold(Color.red(text)) },
|
41
43
|
command: -> (text){ Color.bold(Color.green(text)) },
|
44
|
+
shell_command: -> (text){ Color.bold(Color.color("#ffafff"){ text } ) },
|
42
45
|
symlink: -> (text){ Color.bold(Color.cyan(text)) },
|
43
46
|
selected: -> (text){ Color.negative(text) }
|
44
47
|
)
|
45
48
|
|
46
49
|
DECORATION_PROCS = Hash.new{ |h,k| h[k] = ->(text){ text } }.merge(
|
47
50
|
directory: -> (text){ text + "/" },
|
48
|
-
command: -> (text){ text + "@" }
|
51
|
+
command: -> (text){ text + "@" },
|
52
|
+
shell_command: -> (text) { text + "🐚" }
|
49
53
|
)
|
50
54
|
|
51
55
|
attr_reader :editor, :world
|
@@ -54,8 +58,8 @@ class TabCompletion < Addon
|
|
54
58
|
@world = world
|
55
59
|
@world.extend TabCompletion::DslMethods
|
56
60
|
@editor = @world.editor
|
57
|
-
@editor.completion_proc = -> (word, line){
|
58
|
-
complete(word, line)
|
61
|
+
@editor.completion_proc = -> (word, line, word_index){
|
62
|
+
complete(word, line, word_index)
|
59
63
|
}
|
60
64
|
@editor.bind(:tab){ @editor.complete }
|
61
65
|
@completions = COMPLETIONS.dup
|
@@ -116,7 +120,7 @@ class TabCompletion < Addon
|
|
116
120
|
@style_procs[type] = blk
|
117
121
|
end
|
118
122
|
|
119
|
-
def complete(word,
|
123
|
+
def complete(word, words, word_index)
|
120
124
|
matches = @completions.sort_by(&:priority).reverse.map do |completion|
|
121
125
|
if completion.respond_to?(:call)
|
122
126
|
completion.call
|
@@ -124,7 +128,7 @@ class TabCompletion < Addon
|
|
124
128
|
completions = completion.new(
|
125
129
|
world: @world,
|
126
130
|
word_break_characters: editor.word_break_characters
|
127
|
-
).completions_for(word,
|
131
|
+
).completions_for(word, words, word_index)
|
128
132
|
completions.each do |completion|
|
129
133
|
completion.text = display_text_for_match(completion)
|
130
134
|
end
|
data/bin/yap
CHANGED
@@ -1,29 +1,18 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require 'bundler'
|
4
|
-
Bundler.setup
|
5
|
-
require 'pry'
|
6
|
-
|
7
3
|
file = __FILE__
|
8
4
|
if File.symlink?(file)
|
9
5
|
file = File.readlink(file)
|
10
6
|
end
|
11
7
|
|
12
|
-
$z = File.open("/tmp/z.log", "w+")
|
13
|
-
$z.sync = true
|
14
|
-
|
15
8
|
trap "SIGTSTP", "IGNORE"
|
16
9
|
trap "SIGINT", "IGNORE"
|
17
10
|
trap "SIGTTIN", "IGNORE"
|
18
11
|
trap "SIGTTOU", "IGNORE"
|
19
12
|
|
20
|
-
#ENV["PATH"] = "/Applications/Postgres.app/Contents/MacOS/bin:/usr/local/share/npm/bin/:/usr/local/heroku/bin:/Users/zdennis/.bin:/Users/zdennis/.rvm/gems/ruby-2.1.5/bin:/Users/zdennis/.rvm/gems/ruby-2.1.5@global/bin:/Users/zdennis/.rvm/rubies/ruby-2.1.5/bin:/usr/local/bin:/usr/local/sbin:/Users/zdennis/bin:/bin:/opt/local/bin:/opt/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/usr/local/CrossPack-AVR/bin:/private/tmp/.tidbits/bin:/Users/zdennis/source/playground/AdobeAir/AdobeAIRSDK/bin:/Users/zdennis/.rvm/bin:/Users/zdennis/Downloads/adt-bundle-mac-x86_64-20130219/sdk/tools/:/Users/zdennis/.rvm/bin"
|
21
|
-
|
22
13
|
$LOAD_PATH.unshift File.dirname(file) + '/../lib'
|
23
|
-
# $LOAD_PATH.unshift File.dirname(file) + '/../../yap-shell-parser/lib'
|
24
14
|
|
25
15
|
require "yap"
|
26
16
|
|
27
|
-
|
28
|
-
|
17
|
+
STDOUT.sync = true
|
29
18
|
Yap.run_shell
|
data/bin/yap-dev
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
module Yap
|
4
|
+
require 'yap/world'
|
5
|
+
|
6
|
+
def self.configuration
|
7
|
+
@configuration ||= Configuration.new
|
8
|
+
end
|
9
|
+
|
10
|
+
class Configuration
|
11
|
+
attr_accessor :addon_paths
|
12
|
+
attr_accessor :rcfiles
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@addon_paths = [
|
16
|
+
Dir["#{File.dirname(__FILE__)}/../../addons/*"],
|
17
|
+
Dir["#{ENV['HOME']}/.yap/addons/*"]
|
18
|
+
].flatten
|
19
|
+
|
20
|
+
@rcfiles = [
|
21
|
+
Dir["#{ENV['HOME']}/.yaprc"]
|
22
|
+
].flatten
|
23
|
+
end
|
24
|
+
|
25
|
+
def path_for(part)
|
26
|
+
yap_path.join(part)
|
27
|
+
end
|
28
|
+
|
29
|
+
def yap_path
|
30
|
+
Pathname.new "#{ENV['HOME']}/.yap"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/yap/shell/aliases.rb
CHANGED
@@ -13,6 +13,10 @@ module Yap::Shell
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
+
def names
|
17
|
+
@aliases.keys
|
18
|
+
end
|
19
|
+
|
16
20
|
def fetch_alias(name)
|
17
21
|
@aliases[name]
|
18
22
|
end
|
@@ -31,7 +35,7 @@ module Yap::Shell
|
|
31
35
|
end
|
32
36
|
|
33
37
|
def to_h
|
34
|
-
@aliases.keys.sort.inject(Hash.new) do |h,k|
|
38
|
+
@aliases.keys.compact.sort.inject(Hash.new) do |h,k|
|
35
39
|
h[k] = @aliases[k]
|
36
40
|
h
|
37
41
|
end
|
data/lib/yap/shell/builtins.rb
CHANGED
data/lib/yap/shell/commands.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
require 'shellwords'
|
2
|
-
require 'yap/shell/aliases'
|
3
|
-
require 'yap/shell/execution/result'
|
4
2
|
|
5
3
|
module Yap::Shell
|
4
|
+
require 'yap/shell/aliases'
|
5
|
+
require 'yap/shell/execution/result'
|
6
|
+
|
6
7
|
class CommandError < StandardError ; end
|
7
8
|
class CommandUnknownError < CommandError ; end
|
8
9
|
|
@@ -102,10 +103,9 @@ module Yap::Shell
|
|
102
103
|
(@registered_functions ||= {}).freeze
|
103
104
|
end
|
104
105
|
|
105
|
-
def self.define_shell_function(name_or_pattern, &blk)
|
106
|
+
def self.define_shell_function(name_or_pattern, name: nil, &blk)
|
106
107
|
raise ArgumentError, "Must provide block when defining a shell function" unless blk
|
107
108
|
name_or_pattern = name_or_pattern.to_s if name_or_pattern.is_a?(Symbol)
|
108
|
-
name_or_pattern = /^#{Regexp.escape(name_or_pattern)}$/ if name_or_pattern.is_a?(String)
|
109
109
|
(@registered_functions ||= {})[name_or_pattern] = blk
|
110
110
|
end
|
111
111
|
|
data/lib/yap/shell/evaluation.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
require 'yap/shell/parser'
|
2
|
-
require 'yap/shell/commands'
|
3
|
-
require 'yap/shell/aliases'
|
4
|
-
require 'yap/shell/evaluation/shell_expansions'
|
5
|
-
|
6
1
|
module Yap::Shell
|
2
|
+
require 'yap/shell/parser'
|
3
|
+
require 'yap/shell/commands'
|
4
|
+
require 'yap/shell/aliases'
|
5
|
+
require 'yap/shell/evaluation/shell_expansions'
|
6
|
+
|
7
7
|
class Evaluation
|
8
8
|
attr_reader :world
|
9
9
|
|
@@ -54,9 +54,7 @@ module Yap::Shell
|
|
54
54
|
@aliases_expanded ||= []
|
55
55
|
@command_node_args_stack ||= []
|
56
56
|
with_standard_streams do |stdin, stdout, stderr|
|
57
|
-
args = node.args
|
58
|
-
shell_expand(arg, escape_directory_expansions: false)
|
59
|
-
end
|
57
|
+
args = process_ArgumentNodes(node.args)
|
60
58
|
if !node.literal? && !@aliases_expanded.include?(node.command) && _alias=Aliases.instance.fetch_alias(node.command)
|
61
59
|
@suppress_events = true
|
62
60
|
@command_node_args_stack << args
|
@@ -197,7 +195,9 @@ module Yap::Shell
|
|
197
195
|
#
|
198
196
|
def visit_EnvWrapperNode(node)
|
199
197
|
with_env do
|
200
|
-
node.env.each_pair
|
198
|
+
node.env.each_pair do |env_var_name, arg_node|
|
199
|
+
world.env[env_var_name] = process_ArgumentNode(arg_node)
|
200
|
+
end
|
201
201
|
node.node.accept(self)
|
202
202
|
end
|
203
203
|
end
|
@@ -213,8 +213,8 @@ module Yap::Shell
|
|
213
213
|
# they cleared or overridden.
|
214
214
|
#
|
215
215
|
def visit_EnvNode(node)
|
216
|
-
node.env.each_pair do |key,
|
217
|
-
world.env[key] =
|
216
|
+
node.env.each_pair do |key, arg_node|
|
217
|
+
world.env[key] = process_ArgumentNode(arg_node)
|
218
218
|
end
|
219
219
|
Yap::Shell::Execution::Result.new(status_code:0, directory:Dir.pwd, n:1, of:1)
|
220
220
|
end
|
@@ -276,6 +276,17 @@ module Yap::Shell
|
|
276
276
|
# #
|
277
277
|
######################################################################
|
278
278
|
|
279
|
+
def process_ArgumentNodes(nodes)
|
280
|
+
nodes.map { |arg_node| process_ArgumentNode(arg_node) }
|
281
|
+
end
|
282
|
+
|
283
|
+
def process_ArgumentNode(node)
|
284
|
+
if node.quoted?
|
285
|
+
variable_expand(node.lvalue)
|
286
|
+
else
|
287
|
+
shell_expand(node.lvalue, escape_directory_expansions: false).first
|
288
|
+
end
|
289
|
+
end
|
279
290
|
|
280
291
|
# +pipeline_stack+ is used to determine if we are about go inside of a
|
281
292
|
# pipeline. It will be empty when we are coming out of a pipeline node.
|
@@ -1,6 +1,6 @@
|
|
1
|
-
require 'yap/shell/execution/result'
|
2
|
-
|
3
1
|
module Yap::Shell::Execution
|
2
|
+
require 'yap/shell/execution/result'
|
3
|
+
|
4
4
|
class BuiltinCommandExecution < CommandExecution
|
5
5
|
on_execute do |command:, n:, of:, wait:|
|
6
6
|
status_code = command.execute(stdin:@stdin, stdout:@stdout, stderr:@stderr)
|
@@ -1,7 +1,8 @@
|
|
1
|
-
require 'yap/shell/execution/result'
|
2
1
|
require 'termios'
|
3
2
|
|
4
3
|
module Yap::Shell::Execution
|
4
|
+
require 'yap/shell/execution/result'
|
5
|
+
|
5
6
|
class FileSystemCommandExecution < CommandExecution
|
6
7
|
on_execute do |command:, n:, of:, wait:, resume_blk:nil|
|
7
8
|
stdin, stdout, stderr, world = @stdin, @stdout, @stderr, @world
|
data/lib/yap/shell/execution.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
|
-
require "yap/shell/execution/context"
|
2
|
-
require "yap/shell/execution/command_execution"
|
3
|
-
require "yap/shell/execution/builtin_command_execution"
|
4
|
-
require "yap/shell/execution/file_system_command_execution"
|
5
|
-
require "yap/shell/execution/ruby_command_execution"
|
6
|
-
require "yap/shell/execution/shell_command_execution"
|
7
|
-
require "yap/shell/execution/result"
|
8
|
-
|
9
1
|
module Yap::Shell
|
10
2
|
module Execution
|
3
|
+
require "yap/shell/execution/context"
|
4
|
+
require "yap/shell/execution/command_execution"
|
5
|
+
require "yap/shell/execution/builtin_command_execution"
|
6
|
+
require "yap/shell/execution/file_system_command_execution"
|
7
|
+
require "yap/shell/execution/ruby_command_execution"
|
8
|
+
require "yap/shell/execution/shell_command_execution"
|
9
|
+
require "yap/shell/execution/result"
|
10
|
+
|
11
11
|
Context.register BuiltinCommandExecution, command_type: :BuiltinCommand
|
12
12
|
Context.register FileSystemCommandExecution, command_type: :FileSystemCommand
|
13
13
|
Context.register ShellCommandExecution, command_type: :ShellCommand
|
data/lib/yap/shell/repl.rb
CHANGED
@@ -21,12 +21,17 @@ module Yap::Shell
|
|
21
21
|
|
22
22
|
@world.editor.on_read_line do |event|
|
23
23
|
# editor.history = true?
|
24
|
-
line = event[:payload][:line]
|
24
|
+
line = event[:payload][:line] << "\n"
|
25
25
|
begin
|
26
26
|
@blk.call(line)
|
27
27
|
@world.editor.redraw_prompt
|
28
|
+
rescue Yap::Shell::Parser::Lexer::NonterminatedString, Yap::Shell::Parser::Lexer::LineContinuationFound
|
29
|
+
line << read_another_line_of_input
|
30
|
+
retry
|
28
31
|
rescue ::Yap::Shell::CommandUnknownError => ex
|
29
32
|
puts " CommandError: #{ex.message}"
|
33
|
+
rescue ::Yap::Shell::Parser::ParseError => ex
|
34
|
+
puts " Parse error: #{ex.message}"
|
30
35
|
ensure
|
31
36
|
@world.editor.reset_line
|
32
37
|
end
|
@@ -38,6 +43,11 @@ module Yap::Shell
|
|
38
43
|
|
39
44
|
private
|
40
45
|
|
46
|
+
def read_another_line_of_input
|
47
|
+
print @world.secondary_prompt.update.text
|
48
|
+
gets
|
49
|
+
end
|
50
|
+
|
41
51
|
def kill_ring
|
42
52
|
@kill_ring ||= []
|
43
53
|
end
|
@@ -187,7 +197,8 @@ module Yap::Shell
|
|
187
197
|
# if we haven't been made the process group controlling the TTY that we
|
188
198
|
# become so. This method intentionally blocks.
|
189
199
|
def ensure_process_group_controls_the_tty
|
190
|
-
|
200
|
+
tty_pgrp = Termios.tcgetpgrp(STDIN)
|
201
|
+
while ![Process.pid, Process.getpgrp].include?(tty_pgrp)
|
191
202
|
Termios.tcsetpgrp(STDIN, Process.pid)
|
192
203
|
sleep 0.1
|
193
204
|
end
|
data/lib/yap/shell/version.rb
CHANGED
data/lib/yap/shell.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
require 'readline'
|
2
2
|
require 'yaml'
|
3
|
-
require 'yap/shell/version'
|
4
|
-
require 'yap/shell/builtins'
|
5
3
|
require 'fcntl'
|
6
4
|
|
7
5
|
module Yap
|
8
6
|
module Shell
|
7
|
+
require 'yap/shell/version'
|
8
|
+
require 'yap/shell/builtins'
|
9
|
+
|
9
10
|
autoload :Aliases, "yap/shell/aliases"
|
10
11
|
|
11
12
|
autoload :CommandFactory, "yap/shell/commands"
|
data/lib/yap/world.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
require 'term/ansicolor'
|
2
2
|
require 'forwardable'
|
3
|
-
|
4
3
|
require 'rawline'
|
5
|
-
require 'yap/shell/execution'
|
6
|
-
require 'yap/shell/prompt'
|
7
|
-
require 'yap/world/addons'
|
8
4
|
require 'termios'
|
9
5
|
|
10
6
|
module Yap
|
7
|
+
require 'yap/shell/execution'
|
8
|
+
require 'yap/shell/prompt'
|
9
|
+
require 'yap/world/addons'
|
10
|
+
|
11
11
|
class World
|
12
12
|
include Term::ANSIColor
|
13
13
|
extend Forwardable
|
@@ -46,10 +46,26 @@ module Yap
|
|
46
46
|
addons.each { |addon| addon.initialize_world(self) }
|
47
47
|
end
|
48
48
|
|
49
|
+
def configuration
|
50
|
+
::Yap.configuration
|
51
|
+
end
|
52
|
+
|
49
53
|
def [](addon_name)
|
50
54
|
@addons.fetch(addon_name){ raise(ArgumentError, "No addon loaded registered as #{addon_name}") }
|
51
55
|
end
|
52
56
|
|
57
|
+
def aliases
|
58
|
+
Yap::Shell::Aliases.instance
|
59
|
+
end
|
60
|
+
|
61
|
+
def builtins
|
62
|
+
Yap::Shell::BuiltinCommand.builtins.keys.map(&:to_s)
|
63
|
+
end
|
64
|
+
|
65
|
+
def shell_commands
|
66
|
+
Yap::Shell::ShellCommand.registered_functions.keys.map(&:to_s)
|
67
|
+
end
|
68
|
+
|
53
69
|
def events
|
54
70
|
@editor.events
|
55
71
|
end
|
@@ -111,7 +127,6 @@ module Yap
|
|
111
127
|
end
|
112
128
|
|
113
129
|
def prompt=(prompt=nil, &blk)
|
114
|
-
# TODO if prompt_controller then undefine, cancel events, etc
|
115
130
|
if prompt.is_a?(Yap::Shell::Prompt)
|
116
131
|
@prompt = prompt
|
117
132
|
elsif prompt.respond_to?(:call) # proc
|
@@ -121,6 +136,16 @@ module Yap
|
|
121
136
|
end
|
122
137
|
end
|
123
138
|
|
139
|
+
def secondary_prompt=(prompt=nil, &blk)
|
140
|
+
if prompt.is_a?(Yap::Shell::Prompt)
|
141
|
+
@secondary_prompt = prompt
|
142
|
+
elsif prompt.respond_to?(:call) # proc
|
143
|
+
@secondary_prompt = Yap::Shell::Prompt.new(text:prompt.call, &prompt)
|
144
|
+
else # text
|
145
|
+
@secondary_prompt = Yap::Shell::Prompt.new(text:prompt, &blk)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
124
149
|
def refresh_prompt
|
125
150
|
@editor.prompt = @prompt.update.text
|
126
151
|
end
|
data/lib/yap.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
|
-
require 'yap/shell'
|
2
|
-
require 'yap/world'
|
3
|
-
|
4
1
|
module Yap
|
2
|
+
require 'yap/configuration'
|
3
|
+
require 'yap/shell'
|
4
|
+
require 'yap/world'
|
5
|
+
|
5
6
|
def self.run_shell
|
6
|
-
addons = [
|
7
|
-
|
8
|
-
|
7
|
+
addons = [
|
8
|
+
World::Addons.load_directories(configuration.addon_paths),
|
9
|
+
World::Addons.load_rcfiles(configuration.rcfiles)
|
10
|
+
].flatten
|
9
11
|
|
10
|
-
Shell::Impl.new(addons: addons
|
12
|
+
Shell::Impl.new(addons: addons).repl
|
11
13
|
end
|
12
14
|
end
|
data/rcfiles/.yaprc
CHANGED
@@ -29,7 +29,11 @@ require 'term/ansicolor'
|
|
29
29
|
require 'terminfo'
|
30
30
|
|
31
31
|
env.delete("BUNDLE_GEMFILE")
|
32
|
-
|
32
|
+
env.delete("BUNDLE_BIN_PATH")
|
33
|
+
|
34
|
+
# Resize history to be infinite
|
35
|
+
infinity = 1 / 0.0
|
36
|
+
world.history.resize(infinity)
|
33
37
|
|
34
38
|
func :reload! do |args:, stdin:, stdout:, stderr:|
|
35
39
|
stdout.puts "Reloading shell:"
|
@@ -39,6 +43,7 @@ func :reload! do |args:, stdin:, stdout:, stderr:|
|
|
39
43
|
exec File.expand_path($0)
|
40
44
|
end
|
41
45
|
|
46
|
+
|
42
47
|
completion_cache = {}
|
43
48
|
|
44
49
|
# tab_completion_display do |matches|
|
@@ -91,6 +96,14 @@ self.prompt = -> do
|
|
91
96
|
last_prompt = "#{dark(green('£'))} #{yellow(pwd)} #{git_branch}#{red(arrow)} "
|
92
97
|
end
|
93
98
|
|
99
|
+
#
|
100
|
+
# The secondary_prompt is equivalent to the PS2 prompt in bash. It is what
|
101
|
+
# is displayed when entering a multiline command. It can be set to a string
|
102
|
+
# or a proc. It defaults to '> '
|
103
|
+
#
|
104
|
+
# To see it in action, type "echo 'foo" with no completing single quote and
|
105
|
+
# hit enter.
|
106
|
+
self.secondary_prompt = '> '
|
94
107
|
|
95
108
|
###############################################################################
|
96
109
|
# KEYBOARD MACROS
|
@@ -139,6 +152,15 @@ world.addons[:keyboard_macros].timeout_in_ms = nil
|
|
139
152
|
# set to false you can keep attempting to type in your macro.
|
140
153
|
world.addons[:keyboard_macros].cancel_on_unknown_sequences = true
|
141
154
|
|
155
|
+
keyboard_macros = world.addons[:keyboard_macros]
|
156
|
+
keyboard_macros.cycle(:recent_git_branches) { `git recent`.lines.map(&:chomp) }
|
157
|
+
world.editor.bind(:alt_up_arrow) do
|
158
|
+
keyboard_macros.cycle(:recent_git_branches).next
|
159
|
+
end
|
160
|
+
world.editor.bind(:alt_down_arrow) do
|
161
|
+
keyboard_macros.cycle(:recent_git_branches).previous
|
162
|
+
end
|
163
|
+
|
142
164
|
# Or, you can set the trigger key for a particular set of macros
|
143
165
|
# by specifying it when you call .configure(...).
|
144
166
|
world.addons[:keyboard_macros].configure(trigger_key: ?\C-g) do |macro|
|
@@ -155,22 +177,30 @@ world.addons[:keyboard_macros].configure(trigger_key: ?\C-g) do |macro|
|
|
155
177
|
world.editor.content_box.children = []
|
156
178
|
end
|
157
179
|
|
158
|
-
macro.define 'z',
|
159
|
-
|
160
|
-
|
161
|
-
|
180
|
+
macro.define 'z', "git open-pull\n"
|
181
|
+
macro.define 'abc', 'echo abc'
|
182
|
+
macro.define 'u', -> { world.editor.undo }
|
183
|
+
|
184
|
+
macro.define 'b' do |macro|
|
185
|
+
macro.start { macro.cycle(:recent_git_branches).reset }
|
186
|
+
|
187
|
+
macro.cycle(:recent_git_branches) { `git recent`.lines.map(&:chomp) }
|
188
|
+
macro.fragment :up_arrow, -> { macro.cycle(:recent_git_branches).next }
|
189
|
+
macro.fragment :down_arrow, -> { macro.cycle(:recent_git_branches).previous }
|
190
|
+
end
|
162
191
|
|
163
192
|
macro.define 'l', 'git log ' do |macro|
|
164
193
|
macro.fragment 'n', '--name-status '
|
194
|
+
macro.fragment 'm', 'master..HEAD '
|
165
195
|
macro.fragment 'o', '--oneline '
|
166
196
|
macro.fragment /\d/, -> (a) { "-n#{a} " }
|
167
197
|
end
|
168
198
|
|
169
199
|
macro.define 'd', 'git diff ' do |macro|
|
170
|
-
macro.
|
171
|
-
|
172
|
-
|
173
|
-
macro.
|
200
|
+
macro.fragment 'n', '--name-status '
|
201
|
+
macro.fragment 'm', 'master..HEAD '
|
202
|
+
macro.fragment 'o', '--oneline '
|
203
|
+
macro.fragment /\d/, -> (a) { "-n#{a} " }
|
174
204
|
end
|
175
205
|
end
|
176
206
|
|
@@ -267,7 +297,9 @@ end
|
|
267
297
|
func history_matcher do |world:, args:, stdout:|
|
268
298
|
num_commands = args.first.to_i
|
269
299
|
num_commands = world.history.length - 1 if num_commands == 0
|
300
|
+
history_size = world.history.length
|
270
301
|
world.history[-(num_commands + 1)...-1].each_with_index do |command, i|
|
271
|
-
|
302
|
+
position = history_size - num_commands + i
|
303
|
+
stdout.puts " #{position} #{command}"
|
272
304
|
end
|
273
305
|
end
|
data/yap-shell.gemspec
CHANGED
@@ -13,21 +13,61 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.homepage = "https://github.com/zdennis/yap-shell"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
|
+
spec.post_install_message = <<-POST_INSTALL_MESSAGE.gsub(/^\s*\|/, '')
|
17
|
+
|
|
18
|
+
|Greetings forward-thinking traveler!
|
19
|
+
|
|
20
|
+
|Let's waste no time and get right to it.
|
21
|
+
|
|
22
|
+
|\e[033mFirstly\e[0m, thank you for installing the yap shell!
|
23
|
+
|
|
24
|
+
|\e[033mSecondly\e[0m, this is my beta's beta. Yap has many cool ideas. I dare
|
25
|
+
|say some of those made it into this very release.
|
26
|
+
|
|
27
|
+
|\e[033mLastly\e[0m, create an alias to the yap executable using the ruby version
|
28
|
+
|you just installed it for. For example, with rbenv I use the below
|
29
|
+
|alias in my ~/.profile file:
|
30
|
+
|
|
31
|
+
| alias yap='~/.rbenv/versions/2.2.3/bin/ruby ~/.rbenv/shims/yap'
|
32
|
+
|
|
33
|
+
|Then, `source ~/.profile` or reload your shell. Now you can finally run:
|
34
|
+
|
|
35
|
+
| yap
|
36
|
+
|
|
37
|
+
|You know your tooling better than me. If you need things to go a little
|
38
|
+
|differently than above you go right ahead. If any questions arise don't
|
39
|
+
|hesitate to holler over at Github. I may not always be home, but there will
|
40
|
+
|always be a cozy textarea with dozens of emoji friends waiting to hear your
|
41
|
+
|thoughts. All day. All night.
|
42
|
+
|
|
43
|
+
|Until the next update: Happy coding!
|
44
|
+
|
|
45
|
+
|Sincerely,
|
46
|
+
|
|
47
|
+
| \e[51mThe Lagniappe (Yap) Shell\e[0m
|
48
|
+
|
|
49
|
+
|\e[033mP.S.\e[0m If you have ideas for loading other than the hard-coded
|
50
|
+
|alias, do tell, right over here:
|
51
|
+
|
|
52
|
+
| \e[1mhttp://github.com/zdennis/yap-shell/issues\e[0m
|
53
|
+
|
|
54
|
+
|\e[033mP.P.S.\e[0m OSX support? YES! Linux? I assume YES! Windows? Um...
|
55
|
+
|
|
56
|
+
POST_INSTALL_MESSAGE
|
57
|
+
|
16
58
|
spec.files = `git ls-files -z`.split("\x0")
|
17
59
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
60
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
61
|
spec.require_paths = ["lib"]
|
20
62
|
|
21
|
-
spec.add_dependency "yap-shell-parser", "~> 0.
|
63
|
+
spec.add_dependency "yap-shell-parser", "~> 0.5.0"
|
22
64
|
spec.add_dependency "term-ansicolor", "~> 1.3"
|
23
65
|
spec.add_dependency "ruby-termios", "~> 0.9.6"
|
24
66
|
spec.add_dependency "ruby-terminfo", "~> 0.1.1"
|
25
|
-
spec.
|
26
|
-
spec.add_dependency "yap-rawline", "~> 0.2.0"
|
67
|
+
spec.add_dependency "yap-rawline", "~> 0.3.1"
|
27
68
|
|
28
69
|
spec.add_development_dependency "bundler", "~> 1.6"
|
29
70
|
spec.add_development_dependency "rake", "~> 10"
|
30
|
-
spec.add_development_dependency 'pry-byebug', '~> 3.3', '>= 3.3.0'
|
31
71
|
|
32
72
|
#--BEGIN_ADDON_GEM_DEPENDENCIES--#
|
33
73
|
spec.add_dependency "chronic", "~> 0.10.2"
|