patheditor 1.0.0 → 1.0.1

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 (4) hide show
  1. data/Rakefile +1 -1
  2. data/bin/path_editor +40 -17
  3. data/lib/windows_path.rb +62 -58
  4. metadata +2 -2
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ require 'rake/gempackagetask'
5
5
  spec = Gem::Specification.new do |s|
6
6
  s.name = "patheditor"
7
7
  s.summary = "A simple program to manage the Windows PATH environment variable."
8
- s.version = "1.0.0"
8
+ s.version = "1.0.1"
9
9
  s.author = "Justin Bailey"
10
10
  s.email = "jgbailey@nospam@gmail.com"
11
11
 
data/bin/path_editor CHANGED
@@ -63,18 +63,33 @@ Forces changes to occur with confirmation. True by default unless paths are bein
63
63
 
64
64
  def main
65
65
  @hl = HighLine.new
66
- @paths = WindowsPath.new
66
+ @currPath = WindowsPath.new
67
67
 
68
68
  if @clean || @add || @remove
69
69
  if @clean
70
- paths_to_remove = []
71
- @paths.each { |p| paths_to_remove << p unless Pathname.new(p).exist? }
72
- remove_paths(paths_to_remove) unless paths_to_remove.empty?
70
+ nonexistent = []
71
+ found = WindowsPathArray.new
72
+ duplicates = []
73
+ idx = 0
74
+ @currPath.paths.each do |p|
75
+ pathname = Pathname.new(p).cleanpath
76
+ if ! pathname.exist?
77
+ nonexistent << p
78
+ elsif found.include?(pathname)
79
+ duplicates << idx
80
+ else
81
+ found << pathname
82
+ end
83
+ idx += 1
84
+ end
85
+
86
+ remove_paths(duplicates) unless duplicates.empty?
87
+ remove_paths(nonexistent) unless nonexistent.empty?
73
88
  end
74
89
 
75
90
  if @add
76
- unless @paths.include? @add
77
- @paths.add(@add)
91
+ unless @currPath.paths.include? @add
92
+ @currPath.paths.add(@add)
78
93
  @path_updated = true
79
94
  @hl.say "Added #{@add} to path."
80
95
  else
@@ -91,26 +106,26 @@ Forces changes to occur with confirmation. True by default unless paths are bein
91
106
  exp = @case_sensitive ? Regexp.new("^#{@remove}$") : Regexp.new("^#{@remove}$", Regexp::IGNORECASE)
92
107
  paths_to_remove = []
93
108
 
94
- @paths.each { |p| paths_to_remove << p if exp.match(p) }
109
+ @currPath.paths.each { |p| paths_to_remove << p if exp.match(p) }
95
110
  remove_paths(paths_to_remove) unless paths_to_remove.empty?
96
- elsif @paths.include?(@remove)
111
+ elsif @currPath.paths.include?(@remove)
97
112
  @hl.say "Removing path #{@remove}"
98
- @paths.remove(@remove)
113
+ @currPath.paths.remove(@remove)
99
114
  @path_updated = true
100
115
  end
101
116
  end
102
117
 
103
118
  if @path_updated
104
119
  if confirmation_needed?
105
- @paths.update if @hl.agree("Would you like to commit the changes made? [Yn] ", true)
120
+ @currPath.update if @hl.agree("Would you like to commit the changes made? [Yn] ", true)
106
121
  else
107
- @paths.update
122
+ @currPath.update
108
123
  end
109
124
  end
110
125
  else
111
126
  # Print path
112
127
  @hl.say "Current path entries:"
113
- @paths.each { |p| @hl.say "\t#{p}" }
128
+ @currPath.paths.each { |p| @hl.say "\t#{p}" }
114
129
  end
115
130
  rescue
116
131
  puts "Exception: #{$!.message}"
@@ -123,14 +138,22 @@ Forces changes to occur with confirmation. True by default unless paths are bein
123
138
  (@automatic_confirm && ! @confirm_disabled) || false
124
139
  end
125
140
 
141
+ # Takes an array of paths or indices and removes them from the current path
126
142
  def remove_paths(paths_to_remove)
127
143
  cnt = 0
128
144
  paths_to_remove.each do |p|
129
- @hl.say "Removing #{p}"
130
- @paths.remove p
131
- @path_updated = true
132
- # If more than one path matches and the user did not specify "--no-confirmation", make
133
- # sure to enable it here.
145
+ if p.is_a?(Fixnum)
146
+ idx = p - cnt # adjust index based on paths removed so far.
147
+ @hl.say "Removing #{@currPath.paths[idx]}"
148
+ @currPath.paths.delete_at(idx)
149
+ else
150
+ @hl.say "Removing #{p}"
151
+ @currPath.paths.delete p
152
+ end
153
+
154
+ # If more than one path matches and the user did not specify "--no-confirmation", make
155
+ # sure to enable it here.
156
+ @path_updated = true
134
157
  @automatic_confirm = true if cnt > 0
135
158
  cnt += 1
136
159
  end
data/lib/windows_path.rb CHANGED
@@ -1,74 +1,78 @@
1
1
  require 'win32ole'
2
+ require 'pathname'
2
3
 
3
- # Manages access to and updating of windows path setting. Also manages
4
- # enumerating paths available, and checking if a given path exists.
5
- class WindowsPath
6
- include Enumerable
7
- FILE_SEPARATOR = File::ALT_SEPARATOR
4
+ # Specialized array that knows how to compare paths.
5
+ class WindowsPathArray < Array
6
+
7
+ def include?(path)
8
+ # Compare paths case-insensitive, and also checking
9
+ # trailing separators (so c:\program files == c:\program files\)
10
+ self.any? { |p| compare_paths(path, p) }
11
+ end
8
12
 
9
- def initialize
10
- @shell = WIN32OLE.new("WScript.Shell")
11
- @system = @shell.Environment("System")
12
- @paths = []
13
- @paths = @system.Item("Path").split(";").collect { |p| p.strip }
14
- end
15
-
16
- def expand_vars(val)
17
- while m = val.match(/%.*?%/)
18
- val = val.gsub(m[0], @shell.ExpandEnvironmentStrings(m[0]))
19
- end
13
+ def compare_paths(left, right)
14
+ left = Pathname.new(WindowsPath.expand_vars(left.to_s).downcase).cleanpath
15
+ right = Pathname.new(WindowsPath.expand_vars(right.to_s).downcase).cleanpath
20
16
 
21
- val
17
+ return left.eql?(right)
22
18
  end
23
19
 
24
- def add(p)
25
- @paths << p.to_s unless self.include?(p)
20
+ def <<(p)
21
+ super(p.to_s)
26
22
  end
23
+
24
+ alias_method :add, :<<
27
25
 
28
- alias_method :<<, :add
29
-
30
- def remove(r)
31
- # Find all paths that match and delete them.
32
- @paths = @paths.delete_if { |p| compare_paths(r, p) }
33
- end
34
-
35
- # Update any changes
36
- def update
37
- @system["Item", "Path"] = @paths.join(";")
38
- end
39
-
40
- def each
41
- @paths.each { |p| yield expand_vars(p) }
42
- end
26
+ def delete(path)
27
+ self.delete_if { |p| compare_paths(path, p) }
28
+ end
29
+
30
+ def each
31
+ for i in 0..size - 1
32
+ yield WindowsPath.expand_vars(raw_item(i))
33
+ end
34
+ end
35
+
36
+ # Preserve access to base class definition of []
37
+ alias_method :raw_item, :[]
38
+
39
+ def [](idx)
40
+ WindowsPath.expand_vars(super)
41
+ end
42
+ end
43
43
 
44
- def compare_paths(left, right)
45
- left = expand_vars(left.to_s).downcase
46
- right = expand_vars(right.to_s).downcase
47
-
48
- if left == right
49
- true
50
- else
51
- left_sep = left.length > 1 && left.rindex(FILE_SEPARATOR) == left.length - 1
52
- right_sep = right.length > 1 && right.rindex(FILE_SEPARATOR) == right.length - 1
53
-
54
- if ! left_sep && right_sep
55
- left == right[0, right.length - 1]
56
- elsif left_sep && ! right_sep
57
- left[0, left.length - 1] == right
58
- else
59
- false
60
- end
44
+ # Manages access to and updating of windows path setting.
45
+ class WindowsPath
46
+ include Enumerable
47
+ FILE_SEPARATOR = File::ALT_SEPARATOR
48
+
49
+ # paths is a WindowsPathArray holding all paths in the system.
50
+ attr_accessor :paths
51
+
52
+ # Holds a reference to the Win32 Shell COM object.
53
+ def self.shell
54
+ @shell ||= WIN32OLE.new("WScript.Shell")
55
+ end
56
+
57
+ # Given a path, expands any environment variables found in it.
58
+ # Returns the expanded path.
59
+ def self.expand_vars(path)
60
+ while m = path.match(/%.*?%/)
61
+ path = path.gsub(m[0], shell.ExpandEnvironmentStrings(m[0]))
61
62
  end
63
+
64
+ path
62
65
  end
63
-
64
- def include?(path)
65
- # Compare paths case-insensitive, and also checking
66
- # trailing separators (so c:\program files == c:\program files\)
67
- @paths.any? { |p| compare_paths(path, p) }
66
+
67
+ def initialize
68
+ @system = WindowsPath.shell.Environment("System")
69
+ @paths = WindowsPathArray.new
70
+ @system.Item("Path").split(";").each { |p| @paths.add(p.strip) }
68
71
  end
69
72
 
70
- def inspect
71
- @paths.inspect
73
+ # Update any changes
74
+ def update
75
+ @system["Item", "Path"] = @paths.join(";")
72
76
  end
73
77
 
74
78
  end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
3
3
  specification_version: 1
4
4
  name: patheditor
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.0.0
7
- date: 2007-02-05 00:00:00 -08:00
6
+ version: 1.0.1
7
+ date: 2007-02-06 00:00:00 -08:00
8
8
  summary: A simple program to manage the Windows PATH environment variable.
9
9
  require_paths:
10
10
  - lib