oktags 0.1.0 → 0.1.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.
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"