rbnotes 0.4.12 → 0.4.17

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: 517b5866c81f76286f87b2ed7d2e695c4dd09d5c7ab86f9557079232a58fde37
4
- data.tar.gz: 1d89412445d155501f67cd0978a8070975ed722ee7440119cf5a9ba89ca946eb
3
+ metadata.gz: 65aec23d03fa8672d8aada42a39d6d0f97643ca3481050926ae11aa2a05dc433
4
+ data.tar.gz: c28a9209d1374f351a87e0a0a696312bdc37f70b2d55c97e5e2920703c83643b
5
5
  SHA512:
6
- metadata.gz: 1f0bab361e6f4a7f22a59433369b221b6dffc1e16b79f9d4bdc4027d78c3d61a6e949ab2b81ae1ab3be4c5d52af6bd74aed4b36c70a93f31e710a42b7bb23731
7
- data.tar.gz: af38ba13276090ae653fee8b1b3f67f3de57596851ce8b645f4ed3463c38d71c4a950b3382bff55ad98853c42e2cb3f2df0e7e7652f756f385d53ef15f917085
6
+ metadata.gz: 285b05aee90d97dcf11fca4d753e2265ae11253d504e9a787b34f4d64a74e47486cd6a127d652f6f746b934f90c6c699342ea8621b13ef06da2816ef3f91eb98
7
+ data.tar.gz: 581f9192f023a4a50f43ea475b72aa5a145c054520c6b25f9a59c2f758f980c81259df788c34c47c08b7a901b55f6f77ae60e39de0e5e230727d990fcd9f54d3
@@ -0,0 +1,18 @@
1
+ name: Build
2
+
3
+ on: [push,pull_request]
4
+
5
+ jobs:
6
+ build:
7
+ runs-on: ubuntu-latest
8
+ steps:
9
+ - uses: actions/checkout@v2
10
+ - name: Set up Ruby
11
+ uses: ruby/setup-ruby@v1
12
+ with:
13
+ ruby-version: 3.0.0
14
+ - name: Run the default task
15
+ run: |
16
+ gem install bundler -v 2.2.3
17
+ bundle install
18
+ bundle exec rake
data/.gitignore CHANGED
@@ -35,7 +35,6 @@ build-iPhoneSimulator/
35
35
  ## Documentation cache and generated files:
36
36
  /.yardoc/
37
37
  /_yardoc/
38
- /doc/
39
38
  /rdoc/
40
39
 
41
40
  ## Environment normalization:
data/CHANGELOG.md CHANGED
@@ -5,7 +5,53 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/)
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/).
6
6
 
7
7
  ## [Unreleased]
8
- Nothing to record here.
8
+ - nothing to record here.
9
+
10
+ ## [0.4.17] - 2021-04-21
11
+ ### Added
12
+ - Change for the `show` command to accept keywords. (#84)
13
+ - Add `-r` option to the `show` command. (#110)
14
+ - which specifies to enable "raw" output mode.
15
+
16
+ ### Fixed
17
+ - Update the help text for the `list` command. (#112, #113)
18
+ - Remove trailing spaces. (#108)
19
+ - Fix minor bugs:
20
+ - remove redundant use of an instance variable,
21
+ - change the behavior to exit when no notes found in the repo,
22
+ - `pick` and `show`
23
+ - change delimiter line size according to terminal column.
24
+ - `show`
25
+
26
+ ## [0.4.16] - 2021-04-17
27
+ ### Added
28
+ - Add a new configuration setting to change the default behavior of
29
+ the `list` (and `pick`) command. (#109)
30
+
31
+ ## [0.4.15] - 2021-04-15
32
+ ### Added
33
+ - Enable to use delimiters within a timestamp string. (#104)
34
+
35
+ ### Fixed
36
+ - Fix issue #105: `list` ignores the 2nd arg when specified `-w`
37
+ option.
38
+
39
+ ## [0.4.14] - 2021-04-10
40
+ ### Added
41
+ - Add `-n` option to `show` command. (#102)
42
+
43
+ ### Fixed
44
+ - Fix issue #100: modify to catch Textrepo::MissingTimestampError.
45
+
46
+ ## [0.4.13] - 2021-03-30
47
+ ### Changed
48
+ - Use GitHub/Actions instead of Travis-CI.
49
+ - Add `--week` option to `pick` command. (#88)
50
+
51
+ ### Fixed
52
+ - Fix issue #98: remove redundant args
53
+ (Rbnotes::Utils.read_multiple_timestamps). (#98)
54
+ - Update `textrepo`. -> 0.5.8 (#97)
9
55
 
10
56
  ## [0.4.12] - 2020-12-18
11
57
  ### Changed
data/Gemfile CHANGED
@@ -6,4 +6,4 @@ gemspec
6
6
  gem "rake", "~> 13.0"
7
7
  gem "minitest", "~> 5.0"
8
8
 
9
- gem 'textrepo', "~> 0.5.4"
9
+ gem 'textrepo', "~> 0.5.8"
data/Gemfile.lock CHANGED
@@ -1,16 +1,16 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rbnotes (0.4.12)
5
- textrepo (~> 0.5.4)
4
+ rbnotes (0.4.17)
5
+ textrepo (~> 0.5.8)
6
6
  unicode-display_width (~> 1.7)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- minitest (5.14.2)
12
- rake (13.0.1)
13
- textrepo (0.5.7)
11
+ minitest (5.14.4)
12
+ rake (13.0.3)
13
+ textrepo (0.5.8)
14
14
  unicode-display_width (1.7.0)
15
15
 
16
16
  PLATFORMS
@@ -20,7 +20,7 @@ DEPENDENCIES
20
20
  minitest (~> 5.0)
21
21
  rake (~> 13.0)
22
22
  rbnotes!
23
- textrepo (~> 0.5.4)
23
+ textrepo (~> 0.5.8)
24
24
 
25
25
  BUNDLED WITH
26
- 2.1.4
26
+ 2.2.15
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Rbnotes
2
2
 
3
- [![Build Status](https://travis-ci.org/mnbi/rbnotes.svg?branch=main)](https://travis-ci.org/mnbi/rbnotes)
3
+ [![Build Status](https://github.com/mnbi/rbnotes/workflows/Build/badge.svg)](https://github.com/mnbi/rbnotes/actions?query=workflow%3A"Build")
4
+ [![CodeFactor](https://www.codefactor.io/repository/github/mnbi/rbnotes/badge)](https://www.codefactor.io/repository/github/mnbi/rbnotes)
4
5
 
5
6
  Rbnotes is a simple utility to write a note in the single repository.
6
7
 
data/Rakefile CHANGED
@@ -25,6 +25,6 @@ require "rdoc/task"
25
25
 
26
26
  RDoc::Task.new do |rdoc|
27
27
  rdoc.generator = "ri"
28
- rdoc.rdoc_dir = "doc"
28
+ rdoc.rdoc_dir = "rdoc"
29
29
  rdoc.rdoc_files.include("lib/**/*.rb")
30
30
  end
data/exe/rbnotes CHANGED
@@ -21,7 +21,7 @@ class App
21
21
  file = args.shift
22
22
  raise ArgumentError, args.unshift(arg) if file.nil?
23
23
  file = File.expand_path(file)
24
- raise ArgumentError, "no such file: %s" % file unless FileTest.exist?(file)
24
+ raise ArgumentError, "no such file: %s" % file unless FileTest.exist?(file)
25
25
  @gopts[:conf_file] = file
26
26
  when "-v", "--version"
27
27
  args.clear
data/lib/rbnotes.rb CHANGED
@@ -10,9 +10,4 @@ module Rbnotes
10
10
  require_relative "rbnotes/commands"
11
11
  require_relative "rbnotes/statistics"
12
12
 
13
- class << self
14
- def utils
15
- Utils.instance
16
- end
17
- end
18
13
  end
@@ -192,7 +192,7 @@ string could be used as an argument of some rbnotes commands, such
192
192
  "2020-11-06" -> "20201106000000"
193
193
  "20201106" -> "20201106000000"
194
194
  "2020-11-06 16" -> "20201106160000"
195
- "2020-11-06 16:51" -> "20201106165100"
195
+ "2020-11-06 16:51" -> "20201106165100"
196
196
  STAMP
197
197
  end
198
198
  end
@@ -34,22 +34,7 @@ module Rbnotes::Commands
34
34
 
35
35
  def execute(args, conf)
36
36
  @opts = {}
37
- while args.size > 0
38
- arg = args.shift
39
- case arg
40
- when "-t", "--timestamp"
41
- stamp_str = args.shift
42
- raise ArgumentError, "missing timestamp: %s" % args.unshift(arg) if stamp_str.nil?
43
- stamp_str = complement_timestamp_pattern(stamp_str)
44
- @opts[:timestamp] = Textrepo::Timestamp.parse_s(stamp_str)
45
- when "-f", "--template-file"
46
- template_path = args.shift
47
- @opts[:template] = template_path
48
- else
49
- args.unshift(arg)
50
- break
51
- end
52
- end
37
+ parse_opts(args)
53
38
 
54
39
  stamp = @opts[:timestamp] || Textrepo::Timestamp.new(Time.now)
55
40
 
@@ -116,7 +101,28 @@ HELP
116
101
  end
117
102
 
118
103
  # :stopdoc:
104
+
119
105
  private
106
+
107
+ def parse_opts(args)
108
+ while args.size > 0
109
+ arg = args.shift
110
+ case arg
111
+ when "-t", "--timestamp"
112
+ stamp_str = args.shift
113
+ raise ArgumentError, "missing timestamp: %s" % args.unshift(arg) if stamp_str.nil?
114
+ stamp_str = complement_timestamp_pattern(stamp_str)
115
+ @opts[:timestamp] = Textrepo::Timestamp.parse_s(stamp_str)
116
+ when "-f", "--template-file"
117
+ template_path = args.shift
118
+ @opts[:template] = template_path
119
+ else
120
+ args.unshift(arg)
121
+ break
122
+ end
123
+ end
124
+ end
125
+
120
126
  def complement_timestamp_pattern(pattern)
121
127
  stamp_str = nil
122
128
  case pattern.to_s.size
@@ -12,18 +12,7 @@ module Rbnotes::Commands
12
12
 
13
13
  def execute(args, conf)
14
14
  @opts = {}
15
- while args.size > 0
16
- arg = args.shift
17
- case arg.to_s
18
- when "" # no options
19
- break
20
- when "-d", "--deve-commands"
21
- @opts[:print_deve_commands] = true
22
- else # invalid options or args
23
- args.unshift(arg)
24
- raise ArgumentError, "invalid option or argument: %s" % args.join(" ")
25
- end
26
- end
15
+ parse_opts(args)
27
16
 
28
17
  puts commands(@opts[:print_deve_commands]).join(" ")
29
18
  end
@@ -42,8 +31,24 @@ HELP
42
31
  end
43
32
 
44
33
  # :stopdoc:
34
+
45
35
  private
46
36
 
37
+ def parse_opts(args)
38
+ while args.size > 0
39
+ arg = args.shift
40
+ case arg.to_s
41
+ when "" # no options
42
+ break
43
+ when "-d", "--deve-commands"
44
+ @opts[:print_deve_commands] = true
45
+ else # invalid options or args
46
+ args.unshift(arg)
47
+ raise ArgumentError, "invalid option or argument: %s" % args.join(" ")
48
+ end
49
+ end
50
+ end
51
+
47
52
  ##
48
53
  # Enumerates all command names.
49
54
  #
@@ -29,16 +29,7 @@ module Rbnotes::Commands
29
29
 
30
30
  def execute(args, conf)
31
31
  @opts = {}
32
- while args.size > 0
33
- arg = args.shift
34
- case arg
35
- when "-m", "--use-mtime"
36
- @opts[:use_mtime] = true
37
- else
38
- args.unshift(arg)
39
- break
40
- end
41
- end
32
+ parse_opts(args)
42
33
 
43
34
  file = args.shift
44
35
  unless file.nil?
@@ -116,5 +107,25 @@ If birthtime is not available on the system, use mtime (modification
116
107
  time).
117
108
  HELP
118
109
  end
110
+
111
+ # :stopdoc:
112
+
113
+ private
114
+
115
+ def parse_opts(args)
116
+ while args.size > 0
117
+ arg = args.shift
118
+ case arg
119
+ when "-m", "--use-mtime"
120
+ @opts[:use_mtime] = true
121
+ else
122
+ args.unshift(arg)
123
+ break
124
+ end
125
+ end
126
+ end
127
+
128
+ # :startdoc:
129
+
119
130
  end
120
131
  end
@@ -10,13 +10,16 @@ module Rbnotes::Commands
10
10
  "List notes"
11
11
  end
12
12
 
13
+ DEFAULT_BEHAVIOR = "today" # :nodoc:
14
+
13
15
  ##
14
16
  # Shows a list of notes in the repository. Arguments are
15
17
  # optional. If several args are passed, each of them must be a
16
18
  # timestamp pattern or a keyword.
17
19
  #
18
20
  # Any order of timestamp patterns and keywords mixture is
19
- # acceptable. The redundant patterns are just ignored.
21
+ # acceptable. The redundant patterns or invalid patterns are just
22
+ # ignored.
20
23
  #
21
24
  # A timestamp pattern is a string which would match several
22
25
  # Timestamp objects. A timestamp is an instance of
@@ -54,58 +57,31 @@ module Rbnotes::Commands
54
57
 
55
58
  def execute(args, conf)
56
59
  @opts = {}
57
- while args.size > 0
58
- arg = args.shift
59
- case arg
60
- when "-w", "--week"
61
- @opts[:enum_week] = true
62
- when "-v", "--verbose"
63
- @opts[:verbose] = true
64
- else
65
- args.unshift(arg)
66
- break
67
- end
68
- end
60
+ parse_opts(args)
69
61
 
70
- patterns = nil
71
- if @opts[:enum_week]
72
- arg = args.shift || Textrepo::Timestamp.now[0, 8]
73
- case arg.size
74
- when "yyyymodd".size, "yyyymoddhhmiss".size, "yyyymoddhhmiss_sfx".size
75
- stamp_str = "#{arg}000000"[0, 14]
76
- timestamp = Textrepo::Timestamp.parse_s(stamp_str)
77
- when "modd".size
78
- this_year = Time.now.year.to_s
79
- stamp_str = "#{this_year}#{arg}000000"
80
- begin
81
- timestamp = Textrepo::Timestamp.parse_s(stamp_str)
82
- rescue Textrepo::InvalidTimestampStringError => _e
83
- raise InvalidTimestampPatternAsDateError, arg
84
- end
85
- else
86
- raise InvalidTimestampPatternAsDateError, args.unshift(arg)
87
- end
88
- patterns = Rbnotes.utils.timestamp_patterns_in_week(timestamp)
89
- else
90
- patterns = Rbnotes.utils.expand_keyword_in_args(args)
62
+ if args.empty? and !@opts[:enum_week]
63
+ default_behavior = conf[:list_default] || DEFAULT_BEHAVIOR
64
+ args << default_behavior
91
65
  end
92
66
 
93
- @repo = Textrepo.init(conf)
94
- notes = Rbnotes.utils.find_notes(patterns, @repo)
67
+ utils = Rbnotes.utils
68
+ patterns = utils.read_timestamp_patterns(args, enum_week: @opts[:enum_week])
69
+
70
+ repo = Textrepo.init(conf)
71
+ stamps = utils.find_notes(patterns, repo)
95
72
  output = []
96
73
  if @opts[:verbose]
97
- collect_timestamps_by_date(notes).each { |date, timestamps|
74
+ collect_timestamps_by_date(stamps).each { |date, timestamps|
98
75
  output << "#{date} (#{timestamps.size})"
99
76
  timestamps.each { |timestamp|
100
77
  pad = " "
101
- output << Rbnotes.utils.make_headline(timestamp,
102
- @repo.read(timestamp), pad)
78
+ output << utils.make_headline(timestamp,
79
+ repo.read(timestamp), pad)
103
80
  }
104
81
  }
105
82
  else
106
- notes.each { |timestamp|
107
- output << Rbnotes.utils.make_headline(timestamp,
108
- @repo.read(timestamp))
83
+ stamps.each { |timestamp|
84
+ output << utils.make_headline(timestamp, repo.read(timestamp))
109
85
  }
110
86
  end
111
87
  puts output
@@ -114,13 +90,17 @@ module Rbnotes::Commands
114
90
  def help # :nodoc:
115
91
  puts <<HELP
116
92
  usage:
117
- #{Rbnotes::NAME} list [-w|--week][STAMP_PATTERN|KEYWORD]
93
+ #{Rbnotes::NAME} list [OPTIONS] [STAMP_PATTERN|KEYWORD]
118
94
 
119
95
  Show a list of notes. When no arguments, make a list with all notes
120
96
  in the repository. When specified STAMP_PATTERN, only those match the
121
97
  pattern are listed. Instead of STAMP_PATTERN, some KEYWORDs could be
122
98
  used.
123
99
 
100
+ OPTIONS:
101
+ -v, --verbose
102
+ -w, --week
103
+
124
104
  STAMP_PATTERN must be:
125
105
 
126
106
  (a) full qualified timestamp (with suffix): "20201030160200"
@@ -138,6 +118,24 @@ KEYWORD:
138
118
  - "this_month" (or "tm")
139
119
  - "last_month" (or "lm")
140
120
 
121
+ An option "--verbose" is acceptable. It specifies to counts number of
122
+ notes by each day, then put it with the date before notes. It looks
123
+ like as follows:
124
+
125
+ 2021-04-19 (3)
126
+ 20210419134222: Foo
127
+ 20210419120235: Bar
128
+ 20210419110057: Baz
129
+ 2021-04-18 (1)
130
+ 20210418125353: Hoge
131
+ :
132
+
133
+ When no STAMP_PATTERN or KEYWORD was specified, the behavior of this
134
+ command could be specified with a configuration setting,
135
+ ":list_default:". The value must be one of valid keywords. If no
136
+ settings was also given, this command would behave like "today" was
137
+ specified as the setting.
138
+
141
139
  An option "--week" is also acceptable. It specifies to enumerate all
142
140
  days of a week. Typically, the option is used with a STAMP_PATTERN
143
141
  which specifies a date, such "20201117", then it enumerates all days
@@ -155,6 +153,21 @@ HELP
155
153
 
156
154
  private
157
155
 
156
+ def parse_opts(args)
157
+ while args.size > 0
158
+ arg = args.shift
159
+ case arg
160
+ when "-w", "--week"
161
+ @opts[:enum_week] = true
162
+ when "-v", "--verbose"
163
+ @opts[:verbose] = true
164
+ else
165
+ args.unshift(arg)
166
+ break
167
+ end
168
+ end
169
+ end
170
+
158
171
  def collect_timestamps_by_date(timestamps)
159
172
  result = {}
160
173
  timestamps.map { |ts|
@@ -9,13 +9,28 @@ module Rbnotes::Commands
9
9
  "Pick a timestamp with a picker program"
10
10
  end
11
11
 
12
+ DEFAULT_BEHAVIOR = "today" # :nodoc:
13
+
12
14
  def execute(args, conf)
13
- patterns = Rbnotes.utils.expand_keyword_in_args(args)
14
- @repo = Textrepo.init(conf)
15
+ @opts = {}
16
+ parse_opts(args)
17
+
18
+ if args.empty?
19
+ default_behavior = conf[:list_default] || DEFAULT_BEHAVIOR
20
+ args << default_behavior
21
+ end
22
+
23
+ utils = Rbnotes.utils
24
+ patterns = utils.read_timestamp_patterns(args, enum_week: @opts[:enum_week])
25
+
26
+ repo = Textrepo.init(conf)
27
+
28
+ stamps = utils.find_notes(patterns, repo)
29
+ return if stamps.empty?
15
30
 
16
31
  list = []
17
- Rbnotes.utils.find_notes(patterns, @repo).each { |timestamp|
18
- list << Rbnotes.utils.make_headline(timestamp, @repo.read(timestamp))
32
+ stamps.each { |timestamp|
33
+ list << utils.make_headline(timestamp, repo.read(timestamp))
19
34
  }
20
35
 
21
36
  picker = conf[:picker]
@@ -47,5 +62,25 @@ is specified, it will behave as same as "list" command.
47
62
 
48
63
  HELP
49
64
  end
65
+
66
+ # :stopdoc:
67
+
68
+ private
69
+
70
+ def parse_opts(args)
71
+ while args.size > 0
72
+ arg = args.shift
73
+ case arg
74
+ when "-w", "--week"
75
+ @opts[:enum_week] = true
76
+ else
77
+ args.unshift(arg)
78
+ break
79
+ end
80
+ end
81
+ end
82
+
83
+ # :startdoc:
84
+
50
85
  end
51
86
  end
@@ -1,17 +1,16 @@
1
1
  module Rbnotes::Commands
2
2
 
3
3
  ##
4
- # Shows the content of the notes specified by arguments. Each
5
- # argument must be a string which can be converted into
6
- # Textrepo::Timestamp object.
4
+ # Shows the content of the notes specified by arguments. Arguments
5
+ # should be timestamp patterns or keywords. See the document for
6
+ # the `list` command to know about such arguments.
7
7
  #
8
- # A string for Textrepo::Timestamp must be:
9
- #
10
- # "20201106112600" : year, date, time and sec
11
- # "20201106112600_012" : with suffix
8
+ # Accepts an option with `-n NUMBER` (or `--num-of-lines`), to show
9
+ # the first NUMBER lines of the content of each note.
12
10
  #
13
11
  # If no argument is passed, reads the standard input for arguments.
14
-
12
+ # If a specified timestamp does not exist in the repository as a key,
13
+ # Rbnotes::MissingTimestampError will occur.
15
14
  class Show < Command
16
15
 
17
16
  def description # :nodoc:
@@ -19,13 +18,30 @@ module Rbnotes::Commands
19
18
  end
20
19
 
21
20
  def execute(args, conf)
22
- stamps = Rbnotes.utils.read_multiple_timestamps(args)
21
+ @opts = {}
22
+ parse_opts(args)
23
+
23
24
  repo = Textrepo.init(conf)
25
+ stamps = read_timestamps(args, repo)
26
+ return if stamps.empty?
27
+
28
+ content = stamps.map { |stamp|
29
+ begin
30
+ text = repo.read(stamp)
31
+ rescue Textrepo::MissingTimestampError => _
32
+ raise Rbnotes::MissingTimestampError, stamp
33
+ end
24
34
 
25
- content = stamps.map { |stamp| [stamp, repo.read(stamp)] }.to_h
35
+ lines = text.size
36
+ if @opts[:num_of_lines].to_i > 0
37
+ lines = [@opts[:num_of_lines], lines].min
38
+ end
39
+
40
+ [stamp, text[0, lines]]
41
+ }.to_h
26
42
 
27
43
  pager = conf[:pager]
28
- unless pager.nil?
44
+ unless pager.nil? or @opts[:raw]
29
45
  puts_with_pager(pager, make_output(content))
30
46
  else
31
47
  puts make_output(content)
@@ -35,10 +51,22 @@ module Rbnotes::Commands
35
51
  def help # :nodoc:
36
52
  puts <<HELP
37
53
  usage:
38
- #{Rbnotes::NAME} show [TIMESTAMP...]
54
+ #{Rbnotes::NAME} show [OPTIONS] [STAMP_PATTERN|KEYWORD...]
55
+
56
+ Show the content of given notes. It accepts timestamp patterns and
57
+ keywords like the `list` (or `pick`) command. See the help for the
58
+ `list` command to know more about stamp patterns and keywords.
59
+
60
+ OPTIONS:
61
+ -n, --num-of-lines NUMBER
62
+ -r, --raw
63
+
64
+ Accept an option with `-n NUMBER` (or `--num-of-lines`), to show the
65
+ first NUMBER lines of the content of each note.
39
66
 
40
- Show the content of given notes. TIMESTAMP must be a fully qualified
41
- one, such "20201016165130" or "20201016165130_012" if it has a suffix.
67
+ Also accepts `-r` (or `--raw`) option to specify to use "raw" output,
68
+ which means no use any pager, no apply to any process to make output.
69
+ The behavior is intended to be used within a pipeline.
42
70
 
43
71
  The command try to read its argument from the standard input when no
44
72
  argument was passed in the command line.
@@ -49,6 +77,38 @@ HELP
49
77
 
50
78
  private
51
79
 
80
+ def parse_opts(args)
81
+ while args.size > 0
82
+ arg = args.shift
83
+ case arg
84
+ when "-n", "--num-of-lines"
85
+ num_of_lines = args.shift
86
+ raise ArgumentError, "missing number: %s" % args.unshift(arg) if num_of_lines.nil?
87
+
88
+ num_of_lines = num_of_lines.to_i
89
+ raise ArgumentError, "illegal number (must be greater than 0): %d" % num_of_lines unless num_of_lines > 0
90
+
91
+ @opts[:num_of_lines] = num_of_lines
92
+ when "-r", "--raw"
93
+ @opts[:raw] = true
94
+ else
95
+ args.unshift(arg)
96
+ break
97
+ end
98
+ end
99
+ end
100
+
101
+ def read_timestamps(args, repo)
102
+ utils = Rbnotes.utils
103
+ if args.empty?
104
+ stamps = utils.read_multiple_timestamps(args)
105
+ else
106
+ patterns = utils.read_timestamp_patterns(args)
107
+ stamps = utils.find_notes(patterns, repo)
108
+ end
109
+ stamps
110
+ end
111
+
52
112
  def puts_with_pager(pager, output)
53
113
  require "open3"
54
114
  Open3.pipeline_w(pager) { |stdin|
@@ -66,7 +126,7 @@ HELP
66
126
 
67
127
  _, column = IO.console_size
68
128
  output = content.map { |timestamp, text|
69
- ary = [make_heading(timestamp, [column, 72].min)]
129
+ ary = [make_heading(timestamp, column - 10)]
70
130
  ary.concat(text)
71
131
  ary
72
132
  }
@@ -9,20 +9,14 @@ module Rbnotes::Commands
9
9
  end
10
10
 
11
11
  def execute(args, conf)
12
+ @opts = {}
13
+ parse_opts(args)
14
+
12
15
  report = :total
13
- while args.size > 0
14
- arg = args.shift
15
- case arg
16
- when "-y", "--yearly"
17
- report = :yearly
18
- break
19
- when "-m", "--monthly"
20
- report = :monthly
21
- break
22
- else
23
- args.unshift(arg)
24
- raise ArgumentError, "invalid option or argument: %s" % args.join(" ")
25
- end
16
+ if @opts[:yearly]
17
+ report = :yearly
18
+ elsif @opts[:monthly]
19
+ report = :monthly
26
20
  end
27
21
 
28
22
  stats = Rbnotes::Statistics.new(conf)
@@ -51,5 +45,30 @@ In the version #{Rbnotes::VERSION}, only number of notes is supported.
51
45
  HELP
52
46
  end
53
47
 
48
+ # :stopdoc:
49
+
50
+ private
51
+
52
+ def parse_opts(args)
53
+ while args.size > 0
54
+ arg = args.shift
55
+ case arg
56
+ when "-y", "--yearly"
57
+ @opts[:yearly] = true
58
+ @opts[:monthly] = false
59
+ break
60
+ when "-m", "--monthly"
61
+ @opts[:yearly] = false
62
+ @opts[:monthly] = true
63
+ break
64
+ else
65
+ args.unshift(arg)
66
+ raise ArgumentError, "invalid option or argument: %s" % args.join(" ")
67
+ end
68
+ end
69
+ end
70
+
71
+ # :startdoc:
72
+
54
73
  end
55
74
  end
@@ -32,16 +32,7 @@ module Rbnotes::Commands
32
32
 
33
33
  def execute(args, conf)
34
34
  @opts = {}
35
- while args.size > 0
36
- arg = args.shift
37
- case arg
38
- when "-k", "--keep"
39
- @opts[:keep_timestamp] = true
40
- else
41
- args.unshift(arg)
42
- break
43
- end
44
- end
35
+ parse_opts(args)
45
36
 
46
37
  target_stamp = Rbnotes.utils.read_timestamp(args)
47
38
  editor = Rbnotes.utils.find_editor(conf[:editor])
@@ -100,5 +91,25 @@ editor program will be searched as same as add command. If none of
100
91
  editors is available, the execution fails.
101
92
  HELP
102
93
  end
94
+
95
+ # :stopdoc:
96
+
97
+ private
98
+
99
+ def parse_opts(args)
100
+ while args.size > 0
101
+ arg = args.shift
102
+ case arg
103
+ when "-k", "--keep"
104
+ @opts[:keep_timestamp] = true
105
+ else
106
+ args.unshift(arg)
107
+ break
108
+ end
109
+ end
110
+ end
111
+
112
+ # :startdoc:
113
+
103
114
  end
104
115
  end
data/lib/rbnotes/utils.rb CHANGED
@@ -7,6 +7,20 @@ require "io/console/size"
7
7
  require "unicode/display_width"
8
8
 
9
9
  module Rbnotes
10
+
11
+ class << self
12
+
13
+ ##
14
+ # Retrieves the singleton instance of Rbnotes::Utils class.
15
+ # Typical usage is as follows:
16
+ #
17
+ # Rbnotes.utils.find_editor("emacsclient")
18
+ #
19
+ def utils
20
+ Utils.instance
21
+ end
22
+ end
23
+
10
24
  ##
11
25
  # Defines several utility methods those are intended to be used in
12
26
  # Rbnotes classes.
@@ -89,6 +103,19 @@ module Rbnotes
89
103
  tmpfile
90
104
  end
91
105
 
106
+ # Acceptable delimiters to separate a timestamp string for human
107
+ # being to read and input easily.
108
+ #
109
+ # Here is some examples:
110
+ #
111
+ # - "2021-04-15 15:34:56" -> "20210415153456" (a timestamp string)
112
+ # - "2020-04-15_15:34:56" -> (same as above)
113
+ # - "2020-04-15-15-34-56" -> (same as above)
114
+ # - "2020 04 15 15 34 56" -> (same as above)
115
+ # - "2020-04-15" -> "20200415" (a timestamp pattern)
116
+
117
+ TIMESTAMP_DELIMITERS = /[-:_\s]/
118
+
92
119
  ##
93
120
  # Generates a Textrepo::Timestamp object from a String which comes
94
121
  # from the command line arguments. When no argument is given,
@@ -100,6 +127,8 @@ module Rbnotes
100
127
  def read_timestamp(args)
101
128
  str = args.shift || read_arg($stdin)
102
129
  raise NoArgumentError if str.nil?
130
+
131
+ str = remove_delimiters_from_timestamp_string(str)
103
132
  Textrepo::Timestamp.parse_s(str)
104
133
  end
105
134
 
@@ -108,13 +137,92 @@ module Rbnotes
108
137
  # line arguments. When no argument is given, try to read from
109
138
  # STDIN.
110
139
  #
140
+ # When multiple strings those point the identical time are
141
+ # included the arguments (passed or read form STDIN), the
142
+ # redundant strings will be removed.
143
+ #
144
+ # The order of the arguments will be preserved into the return
145
+ # value, even if the redundant strings were removed.
146
+ #
111
147
  # :call-seq:
112
148
  # read_multiple_timestamps(args) -> [String]
113
149
 
114
150
  def read_multiple_timestamps(args)
115
151
  strings = args.size < 1 ? read_multiple_args($stdin) : args
116
152
  raise NoArgumentError if (strings.nil? || strings.empty?)
117
- strings.map { |str| Textrepo::Timestamp.parse_s(str) }
153
+ strings.uniq.map { |str|
154
+ str = remove_delimiters_from_timestamp_string(str)
155
+ Textrepo::Timestamp.parse_s(str)
156
+ }
157
+ end
158
+
159
+ ##
160
+ # Reads timestamp patterns in an array of arguments. It supports
161
+ # keywords expansion and enumeration of week. The function is
162
+ # intended to be used from Commands::List#execute and
163
+ # Commands::Pick#execute.
164
+ #
165
+ def read_timestamp_patterns(args, enum_week: false)
166
+ patterns = nil
167
+ if enum_week
168
+ args.unshift(Time.now.strftime("%Y%m%d")) if args.size == 0
169
+ patterns = []
170
+ while args.size > 0
171
+ arg = args.shift
172
+ begin
173
+ patterns.concat(timestamp_patterns_in_week(arg.dup))
174
+ rescue InvalidTimestampPatternAsDateError => _e
175
+ raise InvalidTimestampPatternAsDateError, args.unshift(arg)
176
+ end
177
+ end
178
+ else
179
+ patterns = expand_keyword_in_args(args)
180
+ end
181
+ patterns
182
+ end
183
+
184
+ ##
185
+ # Enumerates all timestamp patterns in a week which contains a
186
+ # given timestamp as a day of the week.
187
+ #
188
+ # The argument must be one of the followings:
189
+ # - "yyyymodd" (eg. "20201220")
190
+ # - "yymoddhhmiss" (eg. "20201220120048")
191
+ # - "yymoddhhmiss_sfx" (eg. "20201220120048_012")
192
+ # - "modd" (eg. "1220") (assums in the current year)
193
+ # - nil (assumes today)
194
+ #
195
+ # :call-seq:
196
+ # timestamp_patterns_in_week(String) -> [Array of Strings]
197
+ #
198
+ def timestamp_patterns_in_week(arg)
199
+ date_str = nil
200
+
201
+ if arg
202
+ date_str = remove_delimiters_from_timestamp_string(arg)
203
+ else
204
+ date_str = Textrepo::Timestamp.now[0, 8]
205
+ end
206
+
207
+ case date_str.size
208
+ when "yyyymodd".size
209
+ # nothing to do
210
+ when "yyyymoddhhmiss".size, "yyyymoddhhmiss_sfx".size
211
+ date_str = date_str[0, 8]
212
+ when "modd".size
213
+ this_year = Time.now.year.to_s
214
+ date_str = "#{this_year}#{date_str}"
215
+ else
216
+ raise InvalidTimestampPatternAsDateError, arg
217
+ end
218
+
219
+ begin
220
+ date = Date.parse(date_str)
221
+ rescue Date::Error => _e
222
+ raise InvalidTimestampPatternAsDateError, arg
223
+ end
224
+
225
+ dates_in_week(date).map { |date| timestamp_pattern(date) }
118
226
  end
119
227
 
120
228
  ##
@@ -140,52 +248,24 @@ module Rbnotes
140
248
  # - "last_week" (or "lw")
141
249
  # - "this_month" (or "tm")
142
250
  # - "last_month" (or "lm")
251
+ # - "all"
143
252
  #
144
253
  # :call-seq:
145
254
  # expand_keyword_in_args(Array of Strings) -> Array of Strings
146
-
255
+ #
147
256
  def expand_keyword_in_args(args)
148
- return [nil] if args.empty?
149
-
150
257
  patterns = []
151
258
  while args.size > 0
152
259
  arg = args.shift
153
- if ["today", "to", "yesterday", "ye",
154
- "this_week", "tw", "last_week", "lw",
155
- "this_month", "tm", "last_month", "lm"].include?(arg)
156
- patterns.concat(Rbnotes.utils.expand_keyword(arg))
260
+ if arg == "all"
261
+ return [nil]
262
+ elsif KEYWORDS.include?(arg)
263
+ patterns.concat(expand_keyword(arg))
157
264
  else
158
265
  patterns << arg
159
266
  end
160
267
  end
161
- patterns.sort.uniq
162
- end
163
-
164
- ##
165
- # Expands a keyword to timestamp strings.
166
- #
167
- # :call-seq:
168
- # expand_keyword(keyword as String) -> Array of timestamp Strings
169
-
170
- def expand_keyword(keyword)
171
- patterns = []
172
- case keyword
173
- when "today", "to"
174
- patterns << timestamp_pattern(date_of_today)
175
- when "yesterday", "ye"
176
- patterns << timestamp_pattern(date_of_yesterday)
177
- when "this_week", "tw"
178
- patterns.concat(dates_in_this_week.map { |d| timestamp_pattern(d) })
179
- when "last_week", "lw"
180
- patterns.concat(dates_in_last_week.map { |d| timestamp_pattern(d) })
181
- when "this_month", "tm"
182
- patterns.concat(dates_in_this_month.map { |d| timestamp_pattern(d) })
183
- when "last_month", "lm"
184
- patterns.concat(dates_in_last_month.map { |d| timestamp_pattern(d) })
185
- else
186
- raise UnknownKeywordError, keyword
187
- end
188
- patterns
268
+ patterns.uniq.sort
189
269
  end
190
270
 
191
271
  ##
@@ -233,17 +313,6 @@ module Rbnotes
233
313
  }.flatten.sort{ |a, b| b <=> a }.uniq
234
314
  end
235
315
 
236
- ##
237
- # Enumerates all timestamp patterns in a week which contains a
238
- # given timestamp as a day of the week.
239
- #
240
- # :call-seq:
241
- # timestamp_patterns_in_week(timestamp) -> [Array of Strings]
242
-
243
- def timestamp_patterns_in_week(timestamp)
244
- dates_in_week(start_date_in_the_week(timestamp.time)).map { |date| timestamp_pattern(date) }
245
- end
246
-
247
316
  # :stopdoc:
248
317
 
249
318
  private
@@ -282,6 +351,48 @@ module Rbnotes
282
351
  }.compact
283
352
  end
284
353
 
354
+ def remove_delimiters_from_timestamp_string(stamp_str) # :nodoc:
355
+ str = stamp_str.gsub(TIMESTAMP_DELIMITERS, "")
356
+ base_size = "yyyymiddhhmoss".size
357
+ if str.size > base_size # when suffix is specified
358
+ str = str[0...base_size] + "_" + str[base_size..-1]
359
+ end
360
+ str
361
+ end
362
+
363
+ ##
364
+ # Expands a keyword to timestamp strings.
365
+ #
366
+ # :call-seq:
367
+ # expand_keyword(keyword as String) -> Array of timestamp Strings
368
+ #
369
+ def expand_keyword(keyword)
370
+ patterns = []
371
+ case keyword
372
+ when "today", "to"
373
+ patterns << timestamp_pattern(Date.today)
374
+ when "yesterday", "ye"
375
+ patterns << timestamp_pattern(Date.today.prev_day)
376
+ when "this_week", "tw"
377
+ patterns.concat(dates_in_this_week.map { |d| timestamp_pattern(d) })
378
+ when "last_week", "lw"
379
+ patterns.concat(dates_in_last_week.map { |d| timestamp_pattern(d) })
380
+ when "this_month", "tm"
381
+ patterns.concat(dates_in_this_month.map { |d| timestamp_pattern(d) })
382
+ when "last_month", "lm"
383
+ patterns.concat(dates_in_last_month.map { |d| timestamp_pattern(d) })
384
+ else
385
+ raise UnknownKeywordError, keyword
386
+ end
387
+ patterns
388
+ end
389
+
390
+ KEYWORDS = %w(
391
+ today to yesterday ye
392
+ this_week tw last_week lw
393
+ this_month tm last_month lm
394
+ )
395
+
285
396
  def search_in_path(name)
286
397
  search_paths = ENV["PATH"].split(":")
287
398
  found = search_paths.map { |path|
@@ -299,58 +410,40 @@ module Rbnotes
299
410
  date.strftime("%Y%m%d")
300
411
  end
301
412
 
302
- def date_of_today
303
- date(Time.now)
304
- end
305
-
306
- def date_of_yesterday
307
- date(Time.now).prev_day
308
- end
309
-
310
413
  def date(time)
311
414
  Date.new(time.year, time.mon, time.day)
312
415
  end
313
416
 
314
417
  def dates_in_this_week
315
- dates_in_week(start_date_in_this_week)
418
+ dates_in_week(Date.today)
316
419
  end
317
420
 
318
421
  def dates_in_last_week
319
- dates_in_week(start_date_in_last_week)
320
- end
321
-
322
- def start_date_in_this_week
323
- start_date_in_the_week(Time.now)
422
+ dates_in_week(Date.today.prev_day(7))
324
423
  end
325
424
 
326
- def start_date_in_last_week
327
- start_date_in_this_week.prev_day(7)
328
- end
329
-
330
- def start_date_in_the_week(time)
331
- parts = [:year, :mon, :day].map { |sym| time.send(sym) }
332
- Date.new(*parts).prev_day(wday(time))
425
+ def dates_in_week(date)
426
+ start_date = start_date_of_week(date)
427
+ dates = [start_date]
428
+ 1.upto(6) { |i| dates << start_date.next_day(i) }
429
+ dates
333
430
  end
334
431
 
335
- def wday(time)
336
- (time.wday - 1) % 7
432
+ def start_date_of_week(date)
433
+ # week day in monday start calendar
434
+ date.prev_day((date.wday - 1) % 7)
337
435
  end
338
436
 
339
- def dates_in_week(start_date)
340
- dates = [start_date]
341
- 1.upto(6) { |i| dates << start_date.next_day(i) }
342
- dates
437
+ def first_date_of_this_month
438
+ today = Time.now
439
+ date(Time.new(today.year, today.mon, 1))
343
440
  end
344
441
 
345
442
  def dates_in_this_month
346
- today = Time.now
347
- first_date = date(Time.new(today.year, today.mon, 1))
348
- dates_in_month(first_date)
443
+ dates_in_month(first_date_of_this_month)
349
444
  end
350
445
 
351
446
  def dates_in_last_month
352
- today = Time.now
353
- first_date_of_this_month = date(Time.new(today.year, today.mon, 1))
354
447
  dates_in_month(first_date_of_this_month.prev_month)
355
448
  end
356
449
 
@@ -1,4 +1,4 @@
1
1
  module Rbnotes
2
- VERSION = "0.4.12"
3
- RELEASE = "2020-12-18"
2
+ VERSION = "0.4.17"
3
+ RELEASE = "2021-04-21"
4
4
  end
data/rbnotes.gemspec CHANGED
@@ -25,6 +25,6 @@ Gem::Specification.new do |spec|
25
25
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
26
  spec.require_paths = ["lib"]
27
27
 
28
- spec.add_dependency "textrepo", "~> 0.5.4"
28
+ spec.add_dependency "textrepo", "~> 0.5.8"
29
29
  spec.add_dependency "unicode-display_width", "~> 1.7"
30
30
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbnotes
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.12
4
+ version: 0.4.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - mnbi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-12-18 00:00:00.000000000 Z
11
+ date: 2021-04-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: textrepo
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.5.4
19
+ version: 0.5.8
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.5.4
26
+ version: 0.5.8
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: unicode-display_width
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -46,8 +46,8 @@ executables:
46
46
  extensions: []
47
47
  extra_rdoc_files: []
48
48
  files:
49
+ - ".github/workflows/main.yml"
49
50
  - ".gitignore"
50
- - ".travis.yml"
51
51
  - CHANGELOG.md
52
52
  - Gemfile
53
53
  - Gemfile.lock
@@ -106,7 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
106
106
  - !ruby/object:Gem::Version
107
107
  version: '0'
108
108
  requirements: []
109
- rubygems_version: 3.1.4
109
+ rubygems_version: 3.2.15
110
110
  signing_key:
111
111
  specification_version: 4
112
112
  summary: A simple utility to write a note.
data/.travis.yml DELETED
@@ -1,6 +0,0 @@
1
- ---
2
- language: ruby
3
- cache: bundler
4
- rvm:
5
- - 2.7.2
6
- before_install: gem install bundler -v 2.1.4