oktags 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 68dace0200066373c4f27abc74ffb4fbb5faa9599b6a2771bf436d89ce92dcbe
4
- data.tar.gz: 1f50358bc643e20f55fa8d9f909f12e43600a44460cbb8b2c82dee6e3ce0c7e3
3
+ metadata.gz: e7c1bf8fa36aa3489c778e0b12a19d353ddfd05df9fc21ef1a86e9b207a094ee
4
+ data.tar.gz: c9c873a9d5db3d4703544d95eb8f1bfa3b86903ba85dcd46ad4030766a1ad5da
5
5
  SHA512:
6
- metadata.gz: b6213c7ff2043dcec1246a771b9919212098152672ab590fc89c3910094a940b984be2ca7b67acda67e78d21db54461036b378f6de33327f399cedb9216eb5c8
7
- data.tar.gz: 19e306cf0c524f9f67ca951606bbad2aed2342346b0c85b0c4cbba028eb47a8ccabf7375a42e4d0719c4db0595ed662ee8b362479b077d5421ba4bf7a60fa937
6
+ metadata.gz: 792329f1c8911835393d37e47b7f6c40f3f8ce8108ac38320178704f830be794a35cf1a6bb639006f6024543e89ed19ab144ad0fb64cbdd469c5986b19b1e9d5
7
+ data.tar.gz: 49fc86f66ba0634bc4d3f7344f432a14aa67e270ea15158ccbc0cd716d8c452a4dd68125796db6ba8e4ebc4d11065e48cdb1fcb26d03735fdda136610e91ab05
@@ -5,7 +5,7 @@
5
5
  # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
6
6
  # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
7
7
 
8
- name: Ruby
8
+ name: CI
9
9
 
10
10
  on:
11
11
  push:
data/README.org CHANGED
@@ -7,6 +7,9 @@
7
7
  |___/
8
8
  #+end_example
9
9
 
10
+ #+html: <img src="https://github.com/200ok-ch/oktags/workflows/CI/badge.svg"/>
11
+ #+html: <a href="https://rubygems.org/gems/oktags"> <img src="https://badge.fury.io/rb/oktags.svg"/></a>
12
+
10
13
  * NAME
11
14
 
12
15
  =oktags= - manage tags on plain old files
@@ -26,10 +29,10 @@
26
29
 
27
30
  * DESCRIPTION
28
31
 
29
- =oktags= helps you organize your files by managing tags on them.
30
- It works by adding/removing tags at the end of the filename after a
31
- =--= qualifier. The implementation is OS-agnostic, so it should work
32
- on Linux, macOS and Windows.
32
+ =oktags= helps you organize your files by managing tags on them. It
33
+ works by adding/removing at the end of the filename into a
34
+ =--[tag1,tag2]= construct. The implementation is OS-agnostic, so it
35
+ should work on Linux, macOS and Windows.
33
36
 
34
37
  * EXAMPLES
35
38
 
@@ -38,8 +41,8 @@ Listing all tags in the current folder.
38
41
  #+begin_example
39
42
  $ touch foo
40
43
  $ touch bar.txt
41
- $ touch foobar--tag1,tag2.pdf
42
- $ touch baz--tag1.txt
44
+ $ touch foobar--[tag1,tag2].pdf
45
+ $ touch baz--[tag1].txt
43
46
  $ oktags -l
44
47
  tag1(2)
45
48
  tag2(1)
@@ -55,9 +58,9 @@ Listing all tags for a given path glob (assuming the same data set as above).
55
58
  Adding tags to a file. NB: Tags are always unique.
56
59
 
57
60
  #+begin_example
58
- oktags -a tag3,tag2 foobar--tag1,tag2.pdf
61
+ oktags -a tag3,tag2 foobar--[tag1,tag2].pdf
59
62
  $ ls foobar*
60
- foobar--tag1,tag2,tag3.pdf
63
+ foobar--[tag1,tag2,tag3].pdf
61
64
  #+end_example
62
65
 
63
66
  Interactively adding tags (with auto-completion through readline) to a file.
@@ -68,7 +71,7 @@ Interactively adding tags (with auto-completion through readline) to a file.
68
71
  tag1 tag2 tag3
69
72
  > tag2, new tag
70
73
  $ ls foo* | grep new
71
- foo--new tag,tag2
74
+ foo--[new tag,tag2]
72
75
  #+end_example
73
76
 
74
77
  Renaming tags.
@@ -88,10 +91,10 @@ Remove a tag from a file.
88
91
 
89
92
  #+begin_example
90
93
  $ find . | grep business_card | head -n 1
91
- ./archiv/Cyrill_Schwitter--business_card,somedia,seo.pdf
92
- $ oktags -d seo ./archiv/Cyrill_Schwitter--business_card,somedia,seo.pdf
94
+ ./archiv/Cyrill_Schwitter--[business_card,somedia,seo].pdf
95
+ $ oktags -d seo ./archiv/Cyrill_Schwitter--[business_card,somedia,seo].pdf
93
96
  $ find . | grep business_card | head -n 1
94
- ./archiv/Cyrill_Schwitter--business_card,somedia.pdf
97
+ ./archiv/Cyrill_Schwitter--[business_card,somedia].pdf
95
98
  #+end_example
96
99
 
97
100
  * INSTALLATION
@@ -111,8 +114,8 @@ You can also run =bin/console= for an interactive prompt that will
111
114
  allow you to experiment.
112
115
 
113
116
  To install this gem onto your local machine, run =bundle exec rake
114
- install=. To release a new version, update the version number in
115
- =version.rb=, and then run =bundle exec rake release=, which will
117
+ install=. To publish a new version, update the version number in
118
+ =version.rb=, and then run =bundle exec rake publish=, which will
116
119
  create a git tag for the version, push git commits and tags, and push
117
120
  the =.gem= file to [[https://rubygems.org][rubygems.org]].
118
121
 
@@ -121,11 +124,10 @@ the =.gem= file to [[https://rubygems.org][rubygems.org]].
121
124
  Tests are implemented with [[https://rspec.info/][RSpec]] and can be run like this:
122
125
 
123
126
  #+begin_src shell
124
- $ rpsec spec
125
- .....
127
+ ......
126
128
 
127
- Finished in 0.00351 seconds (files took 0.06834 seconds to load)
128
- 5 examples, 0 failures
129
+ Finished in 0.00408 seconds (files took 0.07109 seconds to load)
130
+ 6 examples, 0 failures
129
131
  #+end_src
130
132
 
131
133
  * NOTES
@@ -10,33 +10,41 @@ module OK
10
10
  class Error < StandardError; end
11
11
  extend self
12
12
 
13
- def find_tags_for(path)
13
+ # oktags uses --[] as the place to save tags. [] does have special
14
+ # meaning for Ruby Dir.glob, though. Hence, it's escaped.
15
+ def escape_glob(s)
16
+ s&.gsub(/[\[\]]/) { |x| "\\" + x }
17
+ end
18
+
19
+ def find_tags_for(path = '**/*')
14
20
  tags = []
15
- Dir.glob(path).each do |file|
16
- file = File.basename(file, ".*")
17
- file_tags = file.split('--')[1]&.split(',')&.map(&:strip)&.map(&:downcase)
21
+ Dir.glob(escape_glob(path)).each do |file|
22
+ file = File.basename(file, '.*')
23
+ file_tags =
24
+ file.match(/--\[(.*)\]/)&.to_a&.at(1)&.split(',')&.map(&:strip)&.map(
25
+ &:downcase
26
+ )
18
27
  tags << file_tags if file_tags
19
28
  end
20
29
 
21
- tags = tags.flatten.compact
30
+ tags.flatten.compact.sort
22
31
  end
23
32
 
24
33
  def count_tags(tags)
25
- tags.inject({}) { |acc, tag|
34
+ tags.inject({}) do |acc, tag|
26
35
  acc[tag] = acc[tag].to_i + 1
27
36
  acc
28
- }
37
+ end
29
38
  end
30
39
 
31
- def list_pretty_tags(path = nil)
32
- tags = find_tags_for(path || '**/*')
40
+ def list_pretty_tags(path = '**/*')
41
+ tags = find_tags_for(path)
33
42
  counts = count_tags(tags)
34
43
 
35
- pretty_counts = counts.sort_by { |tag, count| count }
36
- .reverse
37
- .map do |tag, count|
38
- "#{tag}(#{count})"
39
- end
44
+ pretty_counts =
45
+ counts.sort_by { |tag, count| count }.reverse.map do |tag, count|
46
+ "#{tag}(#{count})"
47
+ end
40
48
 
41
49
  puts pretty_counts
42
50
  end
@@ -44,58 +52,75 @@ module OK
44
52
  def filename_with_tags(file, tags)
45
53
  dirname = File.dirname(file)
46
54
  ext = File.extname(file)
47
- basename = File.basename(file, ".*").split('--')[0]
48
- File.join(dirname, "#{basename}--#{tags.join(',')}#{ext}")
55
+
56
+ basename = File.basename(file, '.*')
57
+ tag_part = basename.match(/--\[(.*)\]/)&.to_a&.at(0)
58
+ basename = basename.gsub(tag_part, '') if tag_part
59
+ File.join(dirname, "#{basename}--[#{tags.join(',')}]#{ext}")
49
60
  end
50
61
 
51
62
  def add_tags_to_file(new_tags, file)
52
- (puts "Needs a FILE input; i.e. `-a tag filename`"; exit) unless file
63
+ unless file
64
+ (
65
+ puts 'Needs a FILE input; i.e. `-a tag filename`'
66
+ exit
67
+ )
68
+ end
53
69
 
54
70
  tags = find_tags_for(file)
55
71
  tags << new_tags.split(',')&.map(&:strip)&.map(&:downcase)
56
72
  tags = tags.flatten.uniq.sort
57
73
 
58
74
  new_filename = filename_with_tags(file, tags)
59
- if file != new_filename
60
- FileUtils.mv(file, new_filename)
61
- end
75
+ FileUtils.mv(file, new_filename) if file != new_filename
62
76
 
63
77
  new_filename
64
78
  end
65
79
 
66
- def read_and_add_tags_for(file, tags_path = nil)
67
- (puts "File '#{file}' does not exist."; exit 1) unless File.exist?(file)
68
-
69
- tags = find_tags_for(tags_path || '**/*')
70
- Readline.completion_proc = proc do |input|
71
- tags.select { |tag| tag.start_with?(input) }
80
+ def read_and_add_tags_for(file, tags_path = '**/*')
81
+ unless File.exist?(file)
82
+ (
83
+ puts "File '#{file}' does not exist."
84
+ exit 1
85
+ )
72
86
  end
73
87
 
74
- puts "Add new tags:"
75
- new_tags = Readline.readline("> ", false)
88
+ tags = find_tags_for(tags_path)
89
+ Readline.completion_proc =
90
+ proc { |input| tags.select { |tag| tag.start_with?(input) } }
91
+
92
+ puts 'Add new tags:'
93
+ new_tags = Readline.readline('> ', false)
76
94
  new_filename = add_tags_to_file(new_tags, file)
77
95
  [new_tags, new_filename]
78
96
  end
79
97
 
80
98
  def delete_tag_from_file(tag, file)
81
- (puts "Needs a FILE input; i.e. `-d tag1 filename`"; exit) unless file
99
+ unless file
100
+ (
101
+ puts 'Needs a FILE input; i.e. `-d tag1 filename`'
102
+ exit
103
+ )
104
+ end
82
105
 
83
106
  tags = find_tags_for(file)
84
107
  tags = tags.reject { |t| t == tag }
85
108
 
86
109
  new_filename = filename_with_tags(file, tags)
87
- if file != new_filename
88
- FileUtils.mv(file, new_filename)
89
- end
110
+ FileUtils.mv(file, new_filename) if file != new_filename
90
111
 
91
112
  new_filename
92
113
  end
93
114
 
94
-
95
115
  def rename_tag(path, old_tag, new_tag)
96
- (puts "Needs a NEW_TAG input; i.e. `-r old_tag new_tag`"; exit) unless new_tag
116
+ unless new_tag
117
+ (
118
+ puts 'Needs a NEW_TAG input; i.e. `-r old_tag new_tag`'
119
+ exit
120
+ )
121
+ end
97
122
 
98
- Dir.glob("#{path}/**/*--*#{old_tag}*").each do |file|
123
+ Dir.glob("#{path}/**/*--\\[*#{old_tag}*\\]*").each do |file|
99
124
  file = add_tags_to_file(new_tag, file)
100
125
  delete_tag_from_file(old_tag, file)
101
126
  end
@@ -104,28 +129,47 @@ module OK
104
129
  def main
105
130
  OptionParser.new do |opts|
106
131
  opts.banner = 'Usage: oktags [options]'
107
- opts.on('-l', "--list [PATH]", 'List file tags (optionally for PATH)') do |path|
108
- list_pretty_tags(path)
132
+ opts.on(
133
+ '-l',
134
+ '--list [PATH]',
135
+ 'List file tags (optionally for PATH)'
136
+ ) do |path|
137
+ path ? list_pretty_tags(path) : list_pretty_tags
109
138
  exit
110
139
  end
111
- opts.on('-a', '--add-tags TAGS FILE', 'Add comma-separated TAGS to FILE') do |tags|
140
+ opts.on(
141
+ '-a',
142
+ '--add-tags TAGS FILE',
143
+ 'Add comma-separated TAGS to FILE'
144
+ ) do |tags|
112
145
  add_tags_to_file(tags, ARGV[0])
113
146
  exit
114
147
  end
115
- opts.on('-i', '--add-tags-interactively FILE', 'Auto-complete tags and add them to FILE') do |file|
148
+ opts.on(
149
+ '-i',
150
+ '--add-tags-interactively FILE',
151
+ 'Auto-complete tags and add them to FILE'
152
+ ) do |file|
116
153
  read_and_add_tags_for(file)
117
154
  exit
118
155
  end
119
- opts.on('-r', '--rename-tag OLD_TAG NEW_TAG', 'Rename OLD_TAG to NEW_TAG(S) recursively for all files') do |old_tag|
156
+ opts.on(
157
+ '-r',
158
+ '--rename-tag OLD_TAG NEW_TAG',
159
+ 'Rename OLD_TAG to NEW_TAG(S) recursively for all files'
160
+ ) do |old_tag|
120
161
  rename_tag('.', old_tag, ARGV[0])
121
162
  exit
122
163
  end
123
- opts.on('-d', '--delete-tag-from-file TAG FILE', 'Delete TAG from FILE') do |tag|
164
+ opts.on(
165
+ '-d',
166
+ '--delete-tag-from-file TAG FILE',
167
+ 'Delete TAG from FILE'
168
+ ) do |tag|
124
169
  delete_tag_from_file(tag, ARGV[0])
125
170
  exit
126
171
  end
127
172
  end.parse!
128
-
129
173
  end
130
174
  end
131
175
  end
@@ -1,5 +1,5 @@
1
1
  module OK
2
2
  module Tags
3
- VERSION = '0.1.0'
3
+ VERSION = '0.1.1'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oktags
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alain M. Lafon
@@ -20,7 +20,7 @@ executables:
20
20
  extensions: []
21
21
  extra_rdoc_files: []
22
22
  files:
23
- - ".github/workflows/ruby.yml"
23
+ - ".github/workflows/ci.yml"
24
24
  - ".gitignore"
25
25
  - ".rspec"
26
26
  - ".ruby-version"