warp-dir 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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