rbnotes 0.4.10 → 0.4.15

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.
@@ -4,9 +4,12 @@ module Rbnotes::Commands
4
4
  # Imports a existing file which specified by the argument as a note.
5
5
  #
6
6
  # A timestamp is generated referring to the birthtime of the given
7
- # file. If birthtime is not available on the system, use mtime
7
+ # file. If birthtime is not available on the system, uses mtime
8
8
  # (modification time).
9
9
  #
10
+ # When the option, "-m" (or "--use-mtime") is specified, uses mtime
11
+ # instead of birthtime.
12
+ #
10
13
  # Occasionally, there is another note which has the same timestmap
11
14
  # in the repository. Then, tries to create a new timestamp with a
12
15
  # suffix. Unluckily, when such timestamp with a suffix already
@@ -25,11 +28,20 @@ module Rbnotes::Commands
25
28
  # execute([PATHNAME], Rbnotes::Conf or Hash) -> nil
26
29
 
27
30
  def execute(args, conf)
31
+ @opts = {}
32
+ parse_opts(args)
33
+
28
34
  file = args.shift
29
35
  unless file.nil?
30
36
  st = File::Stat.new(file)
31
- btime = st.respond_to?(:birthtime) ? st.birthtime : st.mtime
32
- stamp = Textrepo::Timestamp.new(btime)
37
+ time = nil
38
+ if @opts[:use_mtime]
39
+ time = st.mtime
40
+ else
41
+ time = st.respond_to?(:birthtime) ? st.birthtime : st.mtime
42
+ end
43
+
44
+ stamp = Textrepo::Timestamp.new(time)
33
45
  puts "Import [%s] (timestamp [%s]) ..." % [file, stamp]
34
46
 
35
47
  repo = Textrepo.init(conf)
@@ -72,7 +84,7 @@ module Rbnotes::Commands
72
84
  puts "Cannot create a text into the repository with the" \
73
85
  " specified file [%s]." % file
74
86
  puts "For, the birthtime [%s] is identical to some notes" \
75
- " already exists in the reopsitory." % btime
87
+ " already exists in the reopsitory." % time
76
88
  puts "Change the birthtime of the target file, then retry."
77
89
  else
78
90
  puts "... Done."
@@ -86,7 +98,7 @@ module Rbnotes::Commands
86
98
  def help # :nodoc:
87
99
  puts <<HELP
88
100
  usage:
89
- #{Rbnotes::NAME} import FILE
101
+ #{Rbnotes::NAME} import [-m|--use-mtime] FILE
90
102
 
91
103
  Imports a existing file which specified by the argument as a note.
92
104
 
@@ -95,5 +107,25 @@ If birthtime is not available on the system, use mtime (modification
95
107
  time).
96
108
  HELP
97
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
+
98
130
  end
99
131
  end
@@ -24,10 +24,12 @@ module Rbnotes::Commands
24
24
  #
25
25
  # A keyword must be one of them:
26
26
  #
27
- # - "today" (or "to")
28
- # - "yeasterday" (or "ye")
29
- # - "this_week" (or "tw")
30
- # - "last_week" (or "lw")
27
+ # - "today" (or "to")
28
+ # - "yeasterday" (or "ye")
29
+ # - "this_week" (or "tw")
30
+ # - "last_week" (or "lw")
31
+ # - "this_month" (or "tm")
32
+ # - "last_month" (or "lm")
31
33
  #
32
34
  # Here is several examples of timestamp patterns.
33
35
  #
@@ -52,38 +54,30 @@ module Rbnotes::Commands
52
54
 
53
55
  def execute(args, conf)
54
56
  @opts = {}
55
- while args.size > 0
56
- arg = args.shift
57
- case arg
58
- when "-w", "--week"
59
- @opts[:enum_week] = true
60
- else
61
- args.unshift(arg)
62
- break
63
- end
64
- end
57
+ parse_opts(args)
65
58
 
66
- patterns = nil
67
- if @opts[:enum_week]
68
- arg = args.shift || Textrepo::Timestamp.now[0, 8]
69
- case arg.size
70
- when "yyyymodd".size, "yyyymoddhhmiss".size, "yyyymoddhhmiss_sfx".size
71
- stamp_str = "#{arg}000000"[0, 14]
72
- timestamp = Textrepo::Timestamp.parse_s(stamp_str)
73
- patterns = Rbnotes.utils.timestamp_patterns_in_week(timestamp)
74
- else
75
- raise InvalidTimestampPatternError,
76
- "cannot convert to a date [%s]" % args.unshift(arg)
77
- end
78
- else
79
- patterns = Rbnotes.utils.expand_keyword_in_args(args)
80
- end
59
+ utils = Rbnotes.utils
60
+ patterns = utils.read_timestamp_patterns(args, enum_week: @opts[:enum_week])
81
61
 
82
62
  @repo = Textrepo.init(conf)
83
- # newer stamp shoud be above
84
- Rbnotes.utils.find_notes(patterns, @repo).each { |timestamp|
85
- puts Rbnotes.utils.make_headline(timestamp, @repo.read(timestamp))
86
- }
63
+ notes = utils.find_notes(patterns, @repo)
64
+ output = []
65
+ if @opts[:verbose]
66
+ collect_timestamps_by_date(notes).each { |date, timestamps|
67
+ output << "#{date} (#{timestamps.size})"
68
+ timestamps.each { |timestamp|
69
+ pad = " "
70
+ output << utils.make_headline(timestamp,
71
+ @repo.read(timestamp), pad)
72
+ }
73
+ }
74
+ else
75
+ notes.each { |timestamp|
76
+ output << utils.make_headline(timestamp,
77
+ @repo.read(timestamp))
78
+ }
79
+ end
80
+ puts output
87
81
  end
88
82
 
89
83
  def help # :nodoc:
@@ -110,6 +104,8 @@ KEYWORD:
110
104
  - "yeasterday" (or "ye")
111
105
  - "this_week" (or "tw")
112
106
  - "last_week" (or "lw")
107
+ - "this_month" (or "tm")
108
+ - "last_month" (or "lm")
113
109
 
114
110
  An option "--week" is also acceptable. It specifies to enumerate all
115
111
  days of a week. Typically, the option is used with a STAMP_PATTERN
@@ -124,5 +120,39 @@ would be as same as the KEYWORD, "this_week" was specified.
124
120
  HELP
125
121
  end
126
122
 
123
+ # :stopdoc:
124
+
125
+ private
126
+
127
+ def parse_opts(args)
128
+ while args.size > 0
129
+ arg = args.shift
130
+ case arg
131
+ when "-w", "--week"
132
+ @opts[:enum_week] = true
133
+ when "-v", "--verbose"
134
+ @opts[:verbose] = true
135
+ else
136
+ args.unshift(arg)
137
+ break
138
+ end
139
+ end
140
+ end
141
+
142
+ def collect_timestamps_by_date(timestamps)
143
+ result = {}
144
+ timestamps.map { |ts|
145
+ [ts.strftime("%Y-%m-%d"), ts]
146
+ }.reduce(result) { |r, pair|
147
+ date, stamp = pair
148
+ r[date] ||= []
149
+ r[date] << stamp
150
+ r
151
+ }
152
+ result
153
+ end
154
+
155
+ # :startdoc:
156
+
127
157
  end
128
158
  end
@@ -10,18 +10,27 @@ module Rbnotes::Commands
10
10
  end
11
11
 
12
12
  def execute(args, conf)
13
- patterns = Rbnotes.utils.expand_keyword_in_args(args)
13
+ @opts = {}
14
+ parse_opts(args)
15
+
16
+ utils = Rbnotes.utils
17
+ patterns = utils.read_timestamp_patterns(args, enum_week: @opts[:enum_week])
18
+
14
19
  @repo = Textrepo.init(conf)
15
20
 
16
21
  list = []
17
- Rbnotes.utils.find_notes(patterns, @repo).each { |timestamp|
18
- list << Rbnotes.utils.make_headline(timestamp, @repo.read(timestamp))
22
+ utils.find_notes(patterns, @repo).each { |timestamp|
23
+ list << utils.make_headline(timestamp, @repo.read(timestamp))
19
24
  }
20
25
 
21
26
  picker = conf[:picker]
22
27
  unless picker.nil?
28
+ picker_opts = conf[:picker_option]
29
+ cmds = [picker]
30
+ cmds.concat(picker_opts.split) unless picker_opts.nil?
31
+
23
32
  require 'open3'
24
- result = Open3.pipeline_rw(picker) { |stdin, stdout, _|
33
+ result = Open3.pipeline_rw(cmds) { |stdin, stdout, _|
25
34
  stdin.puts list
26
35
  stdin.close
27
36
  stdout.read
@@ -43,5 +52,25 @@ is specified, it will behave as same as "list" command.
43
52
 
44
53
  HELP
45
54
  end
55
+
56
+ # :stopdoc:
57
+
58
+ private
59
+
60
+ def parse_opts(args)
61
+ while args.size > 0
62
+ arg = args.shift
63
+ case arg
64
+ when "-w", "--week"
65
+ @opts[:enum_week] = true
66
+ else
67
+ args.unshift(arg)
68
+ break
69
+ end
70
+ end
71
+ end
72
+
73
+ # :startdoc:
74
+
46
75
  end
47
76
  end
@@ -1,52 +1,139 @@
1
1
  module Rbnotes::Commands
2
2
 
3
3
  ##
4
- # Shows the content of the note specified by the argument. The
4
+ # Shows the content of the notes specified by arguments. Each
5
5
  # argument must be a string which can be converted into
6
6
  # Textrepo::Timestamp object.
7
7
  #
8
- # A string for Timestamp must be:
8
+ # Accepts an option with `-n NUMBER` (or `--num-of-lines`), to show
9
+ # the first NUMBER lines of the content of each note.
10
+ #
11
+ # A string for Textrepo::Timestamp must be:
9
12
  #
10
13
  # "20201106112600" : year, date, time and sec
11
14
  # "20201106112600_012" : with suffix
12
15
  #
13
- # If no argument is passed, reads the standard input for an argument.
14
-
16
+ # If no argument is passed, reads the standard input for arguments.
17
+ # If a specified timestamp does not exist in the repository as a key,
18
+ # Rbnotes::MissingTimestampError will occur.
15
19
  class Show < Command
16
20
 
17
21
  def description # :nodoc:
18
- "Show the content of a note"
22
+ "Show the content of notes"
19
23
  end
20
24
 
21
25
  def execute(args, conf)
22
- stamp = Rbnotes.utils.read_timestamp(args)
26
+ @opts = {}
27
+ parse_opts(args)
23
28
 
29
+ stamps = Rbnotes.utils.read_multiple_timestamps(args)
24
30
  repo = Textrepo.init(conf)
25
- content = repo.read(stamp)
31
+
32
+ content = stamps.map { |stamp|
33
+ begin
34
+ text = repo.read(stamp)
35
+ rescue Textrepo::MissingTimestampError => _
36
+ raise Rbnotes::MissingTimestampError, stamp
37
+ end
38
+
39
+ lines = text.size
40
+ if @opts[:num_of_lines].to_i > 0
41
+ lines = [@opts[:num_of_lines], lines].min
42
+ end
43
+
44
+ [stamp, text[0, lines]]
45
+ }.to_h
26
46
 
27
47
  pager = conf[:pager]
28
48
  unless pager.nil?
29
- require 'open3'
30
- Open3.pipeline_w(pager) { |stdin|
31
- stdin.puts content
32
- stdin.close
33
- }
49
+ puts_with_pager(pager, make_output(content))
34
50
  else
35
- puts content
51
+ puts make_output(content)
36
52
  end
37
53
  end
38
54
 
39
55
  def help # :nodoc:
40
56
  puts <<HELP
41
57
  usage:
42
- #{Rbnotes::NAME} show [TIMESTAMP]
58
+ #{Rbnotes::NAME} show [(-n|--num-of-lines) NUMBER] [TIMESTAMP...]
43
59
 
44
- Show the content of given note. TIMESTAMP must be a fully qualified
60
+ Show the content of given notes. TIMESTAMP must be a fully qualified
45
61
  one, such "20201016165130" or "20201016165130_012" if it has a suffix.
46
62
 
63
+ Accept an option with `-n NUMBER` (or `--num-of-lines`), to show the
64
+ first NUMBER lines of the content of each note.
65
+
47
66
  The command try to read its argument from the standard input when no
48
67
  argument was passed in the command line.
49
68
  HELP
50
69
  end
70
+
71
+ # :stopdoc:
72
+
73
+ private
74
+
75
+ def parse_opts(args)
76
+ while args.size > 0
77
+ arg = args.shift
78
+ case arg
79
+ when "-n", "--num-of-lines"
80
+ num_of_lines = args.shift
81
+ raise ArgumentError, "missing number: %s" % args.unshift(arg) if num_of_lines.nil?
82
+
83
+ num_of_lines = num_of_lines.to_i
84
+ raise ArgumentError, "illegal number (must be greater than 0): %d" % num_of_lines unless num_of_lines > 0
85
+
86
+ @opts[:num_of_lines] = num_of_lines
87
+ else
88
+ args.unshift(arg)
89
+ break
90
+ end
91
+ end
92
+ end
93
+
94
+ def puts_with_pager(pager, output)
95
+ require "open3"
96
+ Open3.pipeline_w(pager) { |stdin|
97
+ stdin.puts output
98
+ stdin.close
99
+ }
100
+ end
101
+
102
+ require "io/console/size"
103
+
104
+ def make_output(content)
105
+ if content.size <= 1
106
+ return content.values[0]
107
+ end
108
+
109
+ _, column = IO.console_size
110
+ output = content.map { |timestamp, text|
111
+ ary = [make_heading(timestamp, [column, 72].min)]
112
+ ary.concat(text)
113
+ ary
114
+ }
115
+
116
+ output = insert_delimiter(output, "")
117
+ output.flatten
118
+ end
119
+
120
+ def make_heading(timestamp, column)
121
+ stamp_str = timestamp.to_s
122
+ length = column - (stamp_str.size + 2)
123
+ "#{stamp_str} #{Array.new(length, '-').join}"
124
+ end
125
+
126
+ def insert_delimiter(ary, delimiter = "")
127
+ result = []
128
+ ary.each { |e|
129
+ result << e
130
+ result << delimiter
131
+ }
132
+ result.delete_at(-1)
133
+ result
134
+ end
135
+
136
+ # :startdoc:
137
+
51
138
  end
52
139
  end
@@ -0,0 +1,74 @@
1
+ module Rbnotes::Commands
2
+ ##
3
+ # Shows statistics.
4
+
5
+ class Statistics < Command
6
+
7
+ def description # :nodoc:
8
+ "Show statistics values"
9
+ end
10
+
11
+ def execute(args, conf)
12
+ @opts = {}
13
+ parse_opts(args)
14
+
15
+ report = :total
16
+ if @opts[:yearly]
17
+ report = :yearly
18
+ elsif @opts[:monthly]
19
+ report = :monthly
20
+ end
21
+
22
+ stats = Rbnotes::Statistics.new(conf)
23
+ case report
24
+ when :yearly
25
+ stats.yearly_report
26
+ when :monthly
27
+ stats.monthly_report
28
+ else
29
+ stats.total_report
30
+ end
31
+ end
32
+
33
+ def help
34
+ puts <<HELP
35
+ usage:
36
+ #{Rbnotes::NAME} statistics ([-y|--yearly]|[-m|--monthly])
37
+
38
+ option:
39
+ -y, --yearly : print yearly report
40
+ -m, --monthly : print monthly report
41
+
42
+ Show statistics.
43
+
44
+ In the version #{Rbnotes::VERSION}, only number of notes is supported.
45
+ HELP
46
+ end
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
+
73
+ end
74
+ end