warp-dir 1.1.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.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/.atom-build.json +22 -0
  3. data/.codeclimate.yml +22 -0
  4. data/.gitignore +40 -0
  5. data/.idea/encodings.xml +6 -0
  6. data/.idea/misc.xml +14 -0
  7. data/.idea/modules.xml +8 -0
  8. data/.idea/runConfigurations/All_Specs.xml +33 -0
  9. data/.idea/vcs.xml +6 -0
  10. data/.idea/warp-dir.iml +224 -0
  11. data/.rspec +4 -0
  12. data/.rubocop.yml +1156 -0
  13. data/.travis.yml +13 -0
  14. data/Gemfile +4 -0
  15. data/Guardfile +14 -0
  16. data/LICENSE +22 -0
  17. data/README.md +114 -0
  18. data/ROADMAP.md +96 -0
  19. data/Rakefile +24 -0
  20. data/bin/console +11 -0
  21. data/bin/setup +8 -0
  22. data/bin/warp-dir +13 -0
  23. data/bin/warp-dir.bash +25 -0
  24. data/lib/warp.rb +4 -0
  25. data/lib/warp/dir.rb +65 -0
  26. data/lib/warp/dir/app/cli.rb +162 -0
  27. data/lib/warp/dir/app/response.rb +133 -0
  28. data/lib/warp/dir/command.rb +120 -0
  29. data/lib/warp/dir/command/add.rb +16 -0
  30. data/lib/warp/dir/command/help.rb +80 -0
  31. data/lib/warp/dir/command/install.rb +78 -0
  32. data/lib/warp/dir/command/list.rb +13 -0
  33. data/lib/warp/dir/command/ls.rb +31 -0
  34. data/lib/warp/dir/command/remove.rb +16 -0
  35. data/lib/warp/dir/command/warp.rb +24 -0
  36. data/lib/warp/dir/commander.rb +71 -0
  37. data/lib/warp/dir/config.rb +87 -0
  38. data/lib/warp/dir/errors.rb +60 -0
  39. data/lib/warp/dir/formatter.rb +77 -0
  40. data/lib/warp/dir/point.rb +53 -0
  41. data/lib/warp/dir/serializer.rb +14 -0
  42. data/lib/warp/dir/serializer/base.rb +43 -0
  43. data/lib/warp/dir/serializer/dotfile.rb +36 -0
  44. data/lib/warp/dir/store.rb +129 -0
  45. data/lib/warp/dir/version.rb +6 -0
  46. data/spec/fixtures/warprc +2 -0
  47. data/spec/spec_helper.rb +71 -0
  48. data/spec/support/cli_expectations.rb +118 -0
  49. data/spec/warp/dir/app/cli_spec.rb +225 -0
  50. data/spec/warp/dir/app/response_spec.rb +131 -0
  51. data/spec/warp/dir/command_spec.rb +62 -0
  52. data/spec/warp/dir/commands/add_spec.rb +40 -0
  53. data/spec/warp/dir/commands/install_spec.rb +20 -0
  54. data/spec/warp/dir/commands/list_spec.rb +37 -0
  55. data/spec/warp/dir/config_spec.rb +45 -0
  56. data/spec/warp/dir/errors_spec.rb +16 -0
  57. data/spec/warp/dir/formatter_spec.rb +38 -0
  58. data/spec/warp/dir/point_spec.rb +35 -0
  59. data/spec/warp/dir/store_spec.rb +105 -0
  60. data/warp-dir.gemspec +56 -0
  61. metadata +228 -0
@@ -0,0 +1,133 @@
1
+ require 'singleton'
2
+
3
+ module Warp
4
+ module Dir
5
+ module App
6
+ class Response
7
+
8
+ # Use Case exit code stream
9
+ #----------------------------------------------------------------
10
+ # Information / Help / List 0 STDOUT
11
+ # Error occured 1 STDERR
12
+ # Execute Shell Command 2 STDOUT
13
+
14
+ class Type < Struct.new(:exit_code, :stream)
15
+ def print(msg)
16
+ under_shell = ::Warp::Dir.eval_context?
17
+ if msg == ' '
18
+ under_shell ? stream.printf(%Q{printf '\\n'; }) : stream.printf("\n")
19
+ else
20
+ msg.split("\n").each do |line|
21
+ under_shell ? stream.printf(%Q{printf -- '#{line}\\n';}) : stream.printf("#{line}\n")
22
+ end
23
+ end
24
+ end
25
+
26
+ def to_s
27
+ "code:#{exit_code}, stream:#{stream == STDOUT ? "STDOUT" : "STDERR"}"
28
+ end
29
+ end
30
+
31
+ INFO = Type.new(0, STDOUT)
32
+ ERROR = Type.new(1, STDERR)
33
+ SHELL = Type.new(2, STDOUT)
34
+
35
+ SHELL.instance_eval do
36
+ def print(msg)
37
+ under_shell = ::Warp::Dir.eval_context?
38
+ if under_shell then
39
+ stream.printf("#{msg};")
40
+ else
41
+ stream.printf(
42
+ 'WARNING: '.red +
43
+ "This functionality is only available within shell eval{} context:\n\n\t#{msg.yellow.bold}\n\n" +
44
+ "Please install shell wrapper 'wd' via the 'install' command.\n")
45
+ end
46
+ end
47
+
48
+ # can't change exit code in SHELL
49
+ def exit_code=(value)
50
+ end
51
+ end
52
+
53
+ RETURN_TYPE = {
54
+ success: INFO,
55
+ error: ERROR,
56
+ shell: SHELL
57
+ }
58
+
59
+ attr_accessor :messages, :config
60
+
61
+ def initialize
62
+ @messages = []
63
+ end
64
+
65
+ # Public Methods
66
+ def print
67
+ raise ::ArgumentError.new('No type defined for Response object') unless @type
68
+ @type.print(@messages.shift) until @messages.empty?
69
+ self
70
+ end
71
+
72
+ def exit!
73
+ raise ::ArgumentError.new('No type defined for Response object') unless @type
74
+ system_exit!(@type.exit_code)
75
+ end
76
+
77
+ # Configure & Accessors
78
+ def configure(&block)
79
+ self.instance_eval(&block)
80
+ self
81
+ end
82
+
83
+ def self.configure(&block)
84
+ self.instance.configure(&block)
85
+ end
86
+
87
+ def message(message = nil)
88
+ if message
89
+ @messages << message
90
+ self
91
+ else
92
+ @messages.join('')
93
+ end
94
+ end
95
+
96
+ def type(a_type = nil)
97
+ if a_type
98
+ @type = a_type.kind_of?(Warp::Dir::App::Response::Type) ? a_type : RETURN_TYPE[a_type]
99
+ raise(::ArgumentError.new("Can't find response type #{a_type} #{@type}")) unless @type
100
+ self
101
+ else
102
+ @type
103
+ end
104
+ end
105
+
106
+ def code(value = nil)
107
+ if value
108
+ @type.exit_code = value
109
+ self
110
+ else
111
+ @type.exit_code
112
+ end
113
+ end
114
+
115
+ def inspect
116
+ "#{self.class.name}={#{type.inspect}, #{messages.inspect}}"
117
+ end
118
+
119
+ def to_s
120
+ "AppResponse[type: {#{type}}, messages: '#{messages.join(' ')}']"
121
+ end
122
+
123
+ private
124
+
125
+ def system_exit!(code)
126
+ Kernel.exit(code) unless self.class.instance_variable_defined?(:@exit_disabled) && self.class.exit_disabled?
127
+ self
128
+ end
129
+
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,120 @@
1
+ require 'set'
2
+ require 'warp/dir/errors'
3
+ require 'warp/dir/formatter'
4
+ require 'warp/dir/commander'
5
+ require 'warp/dir/point'
6
+ require 'forwardable'
7
+ require_relative 'app/response'
8
+
9
+ module Warp
10
+ module Dir
11
+ class Command
12
+ class << self
13
+ def command_name
14
+ self.name.gsub(/.*::/, '').downcase.to_sym
15
+ end
16
+
17
+ def help
18
+ sprintf('%16s %-20s %s%s',
19
+ self.command_name.to_s.yellow,
20
+ (self.send(:needs_a_point?) ? '<point>'.cyan : ' '.cyan),
21
+ self.send(:description).blue.bold,
22
+ (self.respond_to?(:aliases) && !aliases.empty? ? ", aka: " + aliases.join(', ').blue + '' : '')
23
+ )
24
+ end
25
+
26
+ def inherited(subclass)
27
+ ::Warp::Dir::Commander.instance.register(subclass)
28
+ subclass.class_eval do
29
+ extend Forwardable
30
+ def_delegators :@klazz, :command_name, :help, :description
31
+ end
32
+
33
+ subclass.instance_eval do
34
+ @description = nil
35
+ @aliases = []
36
+ @needs_a_point = false
37
+
38
+ class << self
39
+ def description(value = nil)
40
+ @description = value if value
41
+ @description
42
+ end
43
+
44
+ def aliases(*args)
45
+ if args
46
+ @aliases << args unless !args || args.empty?
47
+ @aliases.flatten!
48
+ end
49
+ @aliases
50
+ end
51
+
52
+ def needs_a_point?(value = nil)
53
+ @needs_a_point = value if value
54
+ @needs_a_point
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ def installed_commands
61
+ ::Warp::Dir::Commander.instance.commands
62
+ end
63
+ end
64
+
65
+ attr_accessor :store, :formatter, :point_name, :point_path, :point
66
+
67
+ def initialize(store, point_name = nil, point_path = nil)
68
+ @store = store
69
+ @formatter = ::Warp::Dir::Formatter.new(@store)
70
+ @klazz = self.class
71
+ if point_name
72
+ if point_name.is_a?(::Warp::Dir::Point)
73
+ self.point = point_name
74
+ else
75
+ self.point_name = point_name
76
+ end
77
+ self.point_path = point_path if point_path
78
+ end
79
+
80
+ if store.config.debug
81
+ require 'pp'
82
+ STDERR.printf 'Initialized Command: '.yellow.bold
83
+ pp self
84
+ end
85
+ end
86
+
87
+ def config
88
+ self.store.config
89
+ end
90
+
91
+ # def chain(another_command)
92
+ # command = Warp::Dir.commander.find(another_command.name)
93
+ # command.new(point_name, point_path).run
94
+ # end
95
+ def on(type, &block)
96
+ this_config = self.store.config
97
+ ::Warp::Dir.on(type, &block).configure do
98
+ self.config = this_config
99
+ end
100
+ end
101
+
102
+ def inspect
103
+ "#{self.class.name}[#{self.command_name}]->(#{self.description})"
104
+ end
105
+
106
+ def needs_point?
107
+ false # the default
108
+ end
109
+
110
+ def puts(stream, *args)
111
+ if store.shell
112
+ stream.printf("printf \"#{args.join(', ')}\n\"")
113
+ else
114
+ stream.printf("#{args.join(', ')}\n")
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
120
+ Warp::Dir.require_all_from '/dir/commands'
@@ -0,0 +1,16 @@
1
+ require 'warp/dir/command'
2
+
3
+ class Warp::Dir::Command::Add < Warp::Dir::Command
4
+ description %q(Adds the current directory as a new Warp Point)
5
+ needs_a_point? true
6
+ aliases :new, :save, :store
7
+
8
+ def run(*args)
9
+ self.point_path ||= Dir.pwd
10
+ store.insert point_name: point_name, point_path: point_path, overwrite: config.force
11
+
12
+ on :success do
13
+ message 'Warp point saved!'
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,80 @@
1
+ require 'warp/dir/command'
2
+ require 'warp/dir/command/install'
3
+ class Warp::Dir::Command::Help < Warp::Dir::Command
4
+ description 'Show this extremely unhelpful text'
5
+ aliases :wtf
6
+
7
+
8
+ def run(opts, flags = [])
9
+ commander = ::Warp::Dir.commander
10
+ on :success do
11
+ message USAGE
12
+ message ' '
13
+ message 'Warp Point Commands:'.bold.green
14
+ message ' '
15
+ commander.commands.select{|cmd| cmd.needs_a_point?}.map(&:command_name).each do |installed_commands|
16
+ message sprintf(" %s\n", commander.find(installed_commands).help)
17
+ end
18
+ message ' '
19
+ message 'Global Commands:'.bold.green
20
+ message ' '
21
+ commander.commands.reject{|cmd| cmd.needs_a_point?}.map(&:command_name).each do |installed_commands|
22
+ message sprintf(" %s\n", commander.find(installed_commands).help)
23
+ end
24
+ message EXAMPLES
25
+ message INSTALLATION
26
+ message opts.to_s
27
+ end
28
+ end
29
+
30
+ USAGE = <<EOF
31
+ #{"Usage:".bold.green} wd [ --command ] [ list | help ] [ wd-flags ]
32
+ wd [ --command ] [ [ warp ] | add [-f] | rm | ls ] [ wd flags ] <point> -- [ cmd-flags ]
33
+ wd --help | help
34
+ EOF
35
+
36
+ EXAMPLES = <<EOF
37
+
38
+ #{'Examples'.bold.green}
39
+ wd add proj add current directory as a warp point
40
+ cd ~/
41
+ wd proj jumps to proj
42
+ wd list lists all points
43
+ wd rm proj removes proj
44
+ EOF
45
+
46
+ if ::Warp::Dir::Command::Install.wrapper_installed?
47
+ INSTALLATION = <<EOF
48
+
49
+ #{'Installation'.bold.green}
50
+ It appears that you already have a wrapper installed in one of your
51
+ shell init files (#{::Warp::Dir::DOTFILES.join(', ')}
52
+
53
+ Which means that 'wd' should be working on your system. If not, edit your
54
+ shell init file, remove any lines related to warp-dir gem, and then reinstall:
55
+
56
+ #{'wd install [ --dotfile <filename> ]'.bold.green}
57
+
58
+ If you experience any problem, please log an issue at:
59
+ https://github.com/kigster/warp-dir/issues
60
+ EOF
61
+ else
62
+ INSTALLATION = <<EOF
63
+
64
+ #{'Installation'.bold.green}
65
+ In order for you to start warping all around, you must install the shell wrapper which
66
+ calls into the ruby to do the job. Shell wrapper function is required in order to
67
+ change directory in the outer shell (parent process). Do not worry about this if you
68
+ do not understand it, but please run this command:
69
+
70
+ #{'wd install [ --dotfile <filename> ]'.bold.green}
71
+
72
+ This command will ensure you have the wrapper installed in your ~/.bashrc or ~/.zshrc
73
+ files. Once installed, just restart your shell!
74
+
75
+ If you experience any problem, please log an issue at:
76
+ https://github.com/kigster/warp-dir/issues
77
+ EOF
78
+ end
79
+
80
+ end
@@ -0,0 +1,78 @@
1
+ require 'warp/dir/command'
2
+ require 'warp/dir'
3
+ class Warp::Dir::Command::Install < Warp::Dir::Command
4
+ description %q(Installs warp-dir shell wrapper in your ~/.bashrc)
5
+ needs_a_point? false
6
+
7
+ attr_accessor :installed, :existing, :wrapper, :shell_init_files
8
+
9
+ class << self
10
+ def wrapper_installed?
11
+ ::Warp::Dir::DOTFILES.any?{ |file| already_installed?(file) }
12
+ end
13
+
14
+ def already_installed?(file_path)
15
+ path = ::Warp::Dir.absolute(file_path)
16
+ matches = if File.exists?(path)
17
+ File.open path do |file|
18
+ file.find { |line| line =~ /warp-dir/ }
19
+ end
20
+ end
21
+ matches
22
+ end
23
+ end
24
+
25
+ def initialize(*args)
26
+ self.installed = []
27
+ self.existing = []
28
+ self.wrapper = File.read(::Warp::Dir::SHELL_WRAPPER)
29
+ self.shell_init_files = ::Warp::Dir::DOTFILES
30
+ super(*args)
31
+ end
32
+
33
+ def run(*args)
34
+ self.shell_init_files = config[:dotfile].split(',') if config[:dotfile]
35
+ self.shell_init_files.each { |dotfile| append_wrapper_to(dotfile) }
36
+ local_existing = self.existing
37
+ local_installed = self.installed
38
+ local_shell_files = self.shell_init_files
39
+ if installed.empty?
40
+ if existing.empty?
41
+ on :error do
42
+ if local_shell_files.size > 1 then
43
+ message "Shell init files #{local_shell_files.join(', ').yellow.bold} were not found on the filesystem.".red
44
+ else
45
+ message "Shell init file #{local_shell_files.join(', ').yellow.bold} was not found on the filesystem.".red
46
+ end
47
+ end
48
+ else
49
+ on :error do
50
+ message 'Looks like you already have shell support installed.'.red
51
+ message "#{local_existing.join(', ').yellow.bold} already warp-dir definition. Use --force to override."
52
+ end
53
+ end
54
+ else
55
+ on :success do
56
+ message 'Shell support is installed in the following files:'.green.bold
57
+ message "#{local_installed.join(', ')}".bold.yellow
58
+ end
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ def append_wrapper_to(shell_init_file)
65
+ file = ::Warp::Dir.absolute(shell_init_file)
66
+ pre_installed = self.class.already_installed?(file)
67
+ self.existing << file if pre_installed
68
+ if File.exists?(file)
69
+ if !pre_installed || config[:force]
70
+ File.open(file, 'a') do |f|
71
+ f.write(wrapper)
72
+ end
73
+ self.installed << shell_init_file
74
+ end
75
+ end
76
+ end
77
+
78
+ end
@@ -0,0 +1,13 @@
1
+ require 'warp/dir/command'
2
+ require 'warp/dir/formatter'
3
+
4
+ class Warp::Dir::Command::List < Warp::Dir::Command
5
+ description %q(Print all stored warp points)
6
+
7
+ def run(*args)
8
+ formatted_list = ::Warp::Dir::Formatter.new(store).format_store
9
+ on :success do
10
+ message formatted_list.blue.bold
11
+ end
12
+ end
13
+ end