DirTagger 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/dir_tagger +4 -0
- data/lib/dir_tagger.rb +257 -0
- metadata +50 -0
data/bin/dir_tagger
ADDED
data/lib/dir_tagger.rb
ADDED
@@ -0,0 +1,257 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'ostruct'
|
3
|
+
require 'pathname'
|
4
|
+
require 'tempfile'
|
5
|
+
|
6
|
+
module DirTagger # :nodoc:
|
7
|
+
Profile_Name = '.tag_dir_profile'
|
8
|
+
class DirTagger
|
9
|
+
include Comparable
|
10
|
+
attr_accessor :tag, :dir, :children
|
11
|
+
def initialize(tag, dir, children = DirTaggers.new)
|
12
|
+
@tag = tag
|
13
|
+
@dir = dir
|
14
|
+
@children = children
|
15
|
+
end
|
16
|
+
|
17
|
+
def <=> (another_dir_tagger)
|
18
|
+
tag.length <=> another_dir_tagger.tag.length
|
19
|
+
end
|
20
|
+
|
21
|
+
def length
|
22
|
+
tag.length
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# == Test Data ==
|
27
|
+
# dts = DirTaggers.new
|
28
|
+
# dts.take_in DirTagger.new('first', 'Dir1')
|
29
|
+
# dts.take_in DirTagger.new('second', 'Dir2')
|
30
|
+
# dts.take_in DirTagger.new('third', 'Dir3')
|
31
|
+
# dts.take_in DirTagger.new('forth', 'Dir4'), ['first']
|
32
|
+
# dts.take_in DirTagger.new('fifth', 'Dir5'), %w(first forth)
|
33
|
+
class DirTaggers < Array
|
34
|
+
# Push a new TaggedDirs
|
35
|
+
def initialize
|
36
|
+
@empty = true
|
37
|
+
end
|
38
|
+
|
39
|
+
def take_in (dir_tagger, parent_tags = [])
|
40
|
+
if parent_tags.empty?
|
41
|
+
self << dir_tagger
|
42
|
+
else
|
43
|
+
searching_tag = parent_tags.shift
|
44
|
+
each { |dt|
|
45
|
+
if dt.tag == searching_tag
|
46
|
+
dt.children.take_in dir_tagger, parent_tags
|
47
|
+
break
|
48
|
+
end
|
49
|
+
}
|
50
|
+
end
|
51
|
+
@empty = false
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
def max_tag_length
|
56
|
+
@max_tag_length ||= sort.last.length
|
57
|
+
end
|
58
|
+
|
59
|
+
def empty?
|
60
|
+
@empty
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class DirTaggerOperator
|
65
|
+
attr_accessor :options, :profile, :dir_taggers
|
66
|
+
def initialize(argv) # :nodoc:
|
67
|
+
argv.push('-l') if argv.length.zero?
|
68
|
+
@options = OpenStruct.new(:actions => [], :parent_tags => [])
|
69
|
+
(OptionParser.new do |opts|
|
70
|
+
opts.banner = 'Usage: tagdir tag[,directory] [options]'
|
71
|
+
opts.separator ''
|
72
|
+
opts.separator 'SPECIFIC OPTIONS:'
|
73
|
+
|
74
|
+
opts.on('-a', '--add tag[,directory]', :REQUIRED, Array, 'Tag a directory, the defaualt directory is the current directory') do |tag, dir|
|
75
|
+
options.actions.push :new_tag
|
76
|
+
options.tag = tag
|
77
|
+
options.dir = dir.nil? ? Dir.pwd : dir
|
78
|
+
end
|
79
|
+
|
80
|
+
opts.on('-u', '--under tag[,tag2, ..]', Array, 'Operate tag within parent tags') do |tags|
|
81
|
+
options.parent_tags = tags # .split(',')
|
82
|
+
end
|
83
|
+
|
84
|
+
opts.on('-r', '--remove tag,[tag2, ..]', :REQUIRED, Array, 'Remove one or more tags') do |tags|
|
85
|
+
options.actions.push :remove_tag
|
86
|
+
options.tag_patterns = tags # .split(',')
|
87
|
+
end
|
88
|
+
|
89
|
+
# opts.on('-c', '--rename old_tag,new_tag', :REQUIRED, Array, 'Rename tag') do |old_tag, new_tag|
|
90
|
+
# options.actions.push :rename_tag
|
91
|
+
# options.old_tag = old_tag
|
92
|
+
# options.new_tag = new_tag
|
93
|
+
# end
|
94
|
+
|
95
|
+
opts.on('-l', '--list', 'List all the saved paths') do
|
96
|
+
options.actions.push :list_tags_and_dirs
|
97
|
+
end
|
98
|
+
|
99
|
+
# ToDo => Support listing all saved keys
|
100
|
+
# List all or specified tags
|
101
|
+
opts.on('-t', '--tags [pattern1, ..]', Array, '') do |pattern|
|
102
|
+
options.actions.push :list_tags
|
103
|
+
pattern = pattern.nil? ? '' : pattern
|
104
|
+
options.pattern = pattern
|
105
|
+
end
|
106
|
+
|
107
|
+
# List all or specified directories
|
108
|
+
opts.on('-d', '--dir [pattern1, ..]', Array, '') do |pattern|
|
109
|
+
options.actions.push :list_dirs
|
110
|
+
pattern = pattern.nil? ? '' : pattern
|
111
|
+
options.pattern = pattern
|
112
|
+
end
|
113
|
+
|
114
|
+
opts.on('-v', '--version', 'List current TagDir Version') do
|
115
|
+
puts '2.0.0'
|
116
|
+
exit
|
117
|
+
end
|
118
|
+
|
119
|
+
opts.on('-h', '--help', 'Display help message') do
|
120
|
+
puts opts
|
121
|
+
exit
|
122
|
+
end
|
123
|
+
|
124
|
+
# To Solve => Why options is empty when it is invoked in this block?
|
125
|
+
# if options.actions.empty?
|
126
|
+
# options.actions << :get_dir
|
127
|
+
# options.tags = argv
|
128
|
+
# end
|
129
|
+
end).parse(argv)
|
130
|
+
|
131
|
+
# Preparing for the running environment
|
132
|
+
@profile = Pathname.new(Dir.home).join(Profile_Name) # profile path
|
133
|
+
@dir_taggers = DirTaggers.new
|
134
|
+
# Run actions
|
135
|
+
if options.actions.empty?
|
136
|
+
options.actions << :get_dir
|
137
|
+
options.tags = argv
|
138
|
+
end
|
139
|
+
options.actions.each { |action| send action }
|
140
|
+
end
|
141
|
+
|
142
|
+
def new_tag
|
143
|
+
mode = profile.exist? ? 'a' : 'w'
|
144
|
+
profile.open(mode) do |f|
|
145
|
+
f << (options.parent_tags.empty? ? '' : "#{options.parent_tags.join(',')},") \
|
146
|
+
<< "#{options.tag};#{options.dir}\n"
|
147
|
+
end
|
148
|
+
puts "\e[32m Add Success"
|
149
|
+
end
|
150
|
+
|
151
|
+
def remove_tag
|
152
|
+
tmp_paths_profile = Tempfile.new(Profile_Name)
|
153
|
+
removed_tag = ''
|
154
|
+
profile.each_line do |l|
|
155
|
+
tags = tags_and_dir(l)[0]
|
156
|
+
if removed_tag.empty? && tag_match?(tags, options.tag_patterns, false)
|
157
|
+
removed_tag = tags.join(',')
|
158
|
+
next
|
159
|
+
end
|
160
|
+
next if !removed_tag.empty? && l.match(/^#{removed_tag}/)
|
161
|
+
tmp_paths_profile << l
|
162
|
+
end
|
163
|
+
FileUtils.mv(tmp_paths_profile.to_path, profile.to_path)
|
164
|
+
puts "\e[31m " + (removed_tag.empty? ? "Tagged Directory Not Existed" : "Remove Success")
|
165
|
+
end
|
166
|
+
|
167
|
+
# def rename_tag
|
168
|
+
# tmp_paths_profile = Tempfile.new(Profile_Name)
|
169
|
+
# profile.each_line do |line|
|
170
|
+
# if line.split(',').first.match(Regexp.new(options.old_key))
|
171
|
+
# tmp_paths_profile << "#{options.new_key},#{line.split(',')[1]}"
|
172
|
+
# else
|
173
|
+
# tmp_paths_profile << line
|
174
|
+
# end
|
175
|
+
# end
|
176
|
+
# FileUtils.mv(tmp_paths_profile.to_path, profile.to_path)
|
177
|
+
# puts "\e[32m Rename Success"
|
178
|
+
# end
|
179
|
+
|
180
|
+
def list_tags_and_dirs
|
181
|
+
puts 'All the Tagged Directories:'
|
182
|
+
tag_dir_printer saved_dir_taggers
|
183
|
+
end
|
184
|
+
|
185
|
+
# Get instance of DirTaggers, init
|
186
|
+
def saved_dir_taggers
|
187
|
+
unless profile.exist?
|
188
|
+
puts "\e[031m Not Any Directory Tagged"
|
189
|
+
exit
|
190
|
+
end
|
191
|
+
if dir_taggers.empty?
|
192
|
+
profile.each_line do |l|
|
193
|
+
tags, dir = tags_and_dir(l)
|
194
|
+
dir_taggers.take_in DirTagger.new(tags.pop, dir.first), tags
|
195
|
+
end
|
196
|
+
end
|
197
|
+
dir_taggers
|
198
|
+
end
|
199
|
+
|
200
|
+
def tag_dir_printer(dir_taggers, prefix = 0)
|
201
|
+
dir_taggers.each do |dt|
|
202
|
+
puts sprintf("\e[032m%#{dir_taggers.max_tag_length + prefix}s\e[0m %s", dt.tag, dt.dir)
|
203
|
+
tag_dir_printer dt.children, dir_taggers.max_tag_length + prefix
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
# def list_tags
|
208
|
+
#
|
209
|
+
# end
|
210
|
+
|
211
|
+
# def list_dirs
|
212
|
+
#
|
213
|
+
# end
|
214
|
+
|
215
|
+
# def get_tag
|
216
|
+
# profile_parser(options.pattern, 0)
|
217
|
+
# end
|
218
|
+
|
219
|
+
def get_dir
|
220
|
+
puts profile_parser(options.tags, 1)
|
221
|
+
end
|
222
|
+
|
223
|
+
private
|
224
|
+
def profile_parser(tag_patterns, index)
|
225
|
+
tags_or_dir = ''
|
226
|
+
profile.each_line do |line|
|
227
|
+
tags, dir = tags_and_dir(line)
|
228
|
+
if tag_match?(tags, tag_patterns, tag_patterns.count == 1)
|
229
|
+
tags_or_dir = [tags, dir][index]
|
230
|
+
break
|
231
|
+
end
|
232
|
+
end
|
233
|
+
tags_or_dir
|
234
|
+
end
|
235
|
+
|
236
|
+
# Check if the nested tags match the patterns of tag
|
237
|
+
def tag_match?(tags, tag_patterns, last_only)
|
238
|
+
if last_only
|
239
|
+
tags.last.match(Regexp.new(tag_patterns.last))
|
240
|
+
else
|
241
|
+
return false if tags.count != tag_patterns.count
|
242
|
+
all_match = true
|
243
|
+
tags.each_with_index do |tag, i|
|
244
|
+
unless tag.match(Regexp.new(tag_patterns[i]))
|
245
|
+
all_match = false
|
246
|
+
break
|
247
|
+
end
|
248
|
+
end
|
249
|
+
all_match
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
def tags_and_dir(line)
|
254
|
+
line.split(';').map { |s| s.split(',') }
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
metadata
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: DirTagger
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Van Hu
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-08-22 00:00:00.000000000Z
|
13
|
+
dependencies: []
|
14
|
+
description: ! "A gem saving some frequent used paths and keeping them at hand, both
|
15
|
+
in a very ease and comportable way. The concept is to give your directory a tag,
|
16
|
+
and then store it in '~/.tag_dir_profile'. After that, you can retrieve the path
|
17
|
+
of the directory by a shell command with the tag as parameter.\n https://github.com/bom-d-van/dir_tagger"
|
18
|
+
email: bom.d.van@gmail.com
|
19
|
+
executables:
|
20
|
+
- dir_tagger
|
21
|
+
extensions: []
|
22
|
+
extra_rdoc_files: []
|
23
|
+
files:
|
24
|
+
- lib/dir_tagger.rb
|
25
|
+
- bin/dir_tagger
|
26
|
+
homepage: https://github.com/bom-d-van/dir_tagger
|
27
|
+
licenses: []
|
28
|
+
post_install_message:
|
29
|
+
rdoc_options: []
|
30
|
+
require_paths:
|
31
|
+
- lib
|
32
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
requirements: []
|
45
|
+
rubyforge_project:
|
46
|
+
rubygems_version: 1.8.17
|
47
|
+
signing_key:
|
48
|
+
specification_version: 3
|
49
|
+
summary: ! '*nix system file system helper'
|
50
|
+
test_files: []
|