rbnotes 0.3.0 → 0.4.3

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.
@@ -1,9 +1,20 @@
1
1
  module Rbnotes::Commands
2
+
2
3
  ##
3
- # Adds a new note to the repository. A new timestamp is generated
4
- # at the execution time, then it is attached to the note. If the
5
- # timestamp has already existed in the repository, the command
6
- # fails.
4
+ # Adds a new note to the repository. If no options, a new timestamp
5
+ # is generated at the execution time, then it is attached to the
6
+ # note. If the timestamp has already existed in the repository, the
7
+ # command fails.
8
+ #
9
+ # Accepts an option with `-t STAMP_PATTERN` (or `--timestamp`), a
10
+ # timestamp is generated according to `STAMP_PATTERN`.
11
+ #
12
+ # STAMP_PATTERN could be one of followings:
13
+ #
14
+ # "20201104172230_078" : full qualified timestamp string
15
+ # "20201104172230" : full qualified timestamp string (no suffix)
16
+ # "202011041722" : year, date and time (omit second part)
17
+ # "11041722" : date and time (omit year and second part)
7
18
  #
8
19
  # This command starts the external editor program to prepare text to
9
20
  # store. The editor program will be searched in the following order:
@@ -14,23 +25,48 @@ module Rbnotes::Commands
14
25
  # 4. "vi"
15
26
  #
16
27
  # If none of the above editor is available, the command fails.
17
- #
28
+
18
29
  class Add < Command
19
30
  include ::Rbnotes::Utils
20
31
 
32
+ def description # :nodoc:
33
+ "Add a new note"
34
+ end
35
+
21
36
  def execute(args, conf)
22
- newstamp = Textrepo::Timestamp.new(Time.now)
37
+ @opts = {}
38
+ while args.size > 0
39
+ arg = args.shift
40
+ case arg
41
+ when "-t", "--timestamp"
42
+ stamp_str = args.shift
43
+ raise ArgumentError, "missing timestamp: %s" % args.unshift(arg) if stamp_str.nil?
44
+ stamp_str = complement_timestamp_pattern(stamp_str)
45
+ @opts[:timestamp] = Textrepo::Timestamp.parse_s(stamp_str)
46
+ else
47
+ args.unshift(arg)
48
+ break
49
+ end
50
+ end
51
+
52
+ stamp = @opts[:timestamp] || Textrepo::Timestamp.new(Time.now)
23
53
 
24
54
  candidates = [conf[:editor], ENV["EDITOR"], "nano", "vi"].compact
25
55
  editor = find_program(candidates)
26
56
  raise Rbnotes::NoEditorError, candidates if editor.nil?
27
57
 
28
- tmpfile = run_with_tmpfile(editor, newstamp.to_s)
58
+ tmpfile = run_with_tmpfile(editor, stamp.to_s)
59
+
60
+ unless FileTest.exist?(tmpfile)
61
+ puts "Cancel adding, since nothing to store"
62
+ return
63
+ end
64
+
29
65
  text = File.readlines(tmpfile)
30
66
 
31
67
  repo = Textrepo.init(conf)
32
68
  begin
33
- repo.create(newstamp, text)
69
+ repo.create(stamp, text)
34
70
  rescue Textrepo::DuplicateTimestampError => e
35
71
  puts e.message
36
72
  puts "Just wait a second, then retry."
@@ -39,11 +75,58 @@ module Rbnotes::Commands
39
75
  rescue StandardError => e
40
76
  puts e.message
41
77
  else
42
- puts "Add a note [%s]" % newstamp.to_s
78
+ puts "Add a note [%s]" % stamp.to_s
43
79
  ensure
44
80
  # Don't forget to remove the temporary file.
45
81
  File.delete(tmpfile)
46
82
  end
47
83
  end
84
+
85
+ def help # :nodoc:
86
+ puts <<HELP
87
+ usage:
88
+ #{Rbnotes::NAME} add [(-t|--timestamp) STAMP_PATTERN]
89
+
90
+ Add a new note to the repository. If no options, a new timestamp is
91
+ generated at the execution time, then it is attached to the note.
92
+
93
+ Accept an option with `-t STAMP_PATTERN` (or `--timestamp`), a
94
+ timestamp is generated according to `STAMP_PATTERN`.
95
+
96
+ STAMP_PATTERN could be one of followings:
97
+
98
+ "20201104172230_078" : full qualified timestamp string
99
+ "20201104172230" : full qualified timestamp string (no suffix)
100
+ "202011041722" : year, date and time (omit second part)
101
+ "11041722" : date and time (omit year and second part)
102
+
103
+ This command starts the external editor program to prepare text to
104
+ store. The editor program will be searched in the following order:
105
+
106
+ 1. configuration setting of ":editor"
107
+ 2. ENV["EDITOR"]
108
+ 3. "nano"
109
+ 4. "vi"
110
+
111
+ If none of the above editor is available, the execution fails.
112
+ HELP
113
+ end
114
+
115
+ # :stopdoc:
116
+ private
117
+ def complement_timestamp_pattern(pattern)
118
+ stamp_str = nil
119
+ case pattern.to_s.size
120
+ when "yyyymoddhhmiss_lll".size, "yyyymoddhhmiss".size
121
+ stamp_str = pattern.dup
122
+ when "yyyymoddhhmi".size # omit sec part
123
+ stamp_str = "#{pattern}00"
124
+ when "moddhhmi".size # omit year and sec part
125
+ stamp_str = "#{Time.now.year}#{pattern}00"
126
+ else
127
+ raise Textrepo::InvalidTimestampStringError, pattern
128
+ end
129
+ stamp_str
130
+ end
48
131
  end
49
132
  end
@@ -1,18 +1,17 @@
1
- # :markup: markdown
1
+ module Rbnotes::Commands
2
2
 
3
- # Delete command deletes one note in the repository, which specified
4
- # with a given timestamp string. The timestamp string must be a fully
5
- # qualified one, like "20201016165130". The argument to specify a
6
- # note is mandatory. If no argument was passed, it would print help
7
- # message and exit.
8
- #
9
- # It does nothing when the specified note does not exist except to
10
- # print error message.
3
+ # Deletes a given note in the repository. The timestamp string must
4
+ # be a fully qualified one, like "20201016165130". If no argument
5
+ # was passed, it would try to read from the standard input.
6
+ #
7
+ # It does nothing to change the repository when the specified note
8
+ # does not exist.
11
9
 
12
- # :stopdoc:
10
+ class Delete < Command
11
+ def description # :nodoc:
12
+ "Delete a note"
13
+ end
13
14
 
14
- module Rbnotes
15
- class Commands::Delete < Commands::Command
16
15
  def execute(args, conf)
17
16
  stamp = Rbnotes::Utils.read_timestamp(args)
18
17
 
@@ -27,5 +26,18 @@ module Rbnotes
27
26
  puts "Delete [%s]" % stamp.to_s
28
27
  end
29
28
  end
29
+
30
+ def help # :nodoc:
31
+ puts <<HELP
32
+ usage:
33
+ #{Rbnotes::NAME} delete [TIMESTAMP]
34
+
35
+ Delete a given note. TIMESTAMP must be a fully qualified one, such
36
+ "20201016165130" or "20201016165130_012" if it has a suffix.
37
+
38
+ Delete reads its argument from the standard input when no argument was
39
+ passed in the command line.
40
+ HELP
41
+ end
30
42
  end
31
43
  end
@@ -0,0 +1,58 @@
1
+ require "pathname"
2
+
3
+ module Rbnotes::Commands
4
+
5
+ ##
6
+ # Writes out a given note into a specified file. The file will be
7
+ # created in the current working directory unless an absolute path
8
+ # is specified as a filename.
9
+ #
10
+ # When no argument was passed, would try to read a timestamp string
11
+ # from the standard input.
12
+
13
+ class Export < Command
14
+
15
+ def description # :nodoc:
16
+ "Write out a note into a file"
17
+ end
18
+
19
+ #
20
+ # :call-seq:
21
+ # execute([a String as timestring], Rbnotes::Conf or Hash) -> nil
22
+
23
+ def execute(args, conf)
24
+ stamp = Rbnotes::Utils.read_timestamp(args)
25
+
26
+ repo = Textrepo.init(conf)
27
+ begin
28
+ content = repo.read(stamp)
29
+ rescue Textrepo::MissingTimestampError => _
30
+ raise MissingTimestampError, stamp
31
+ end
32
+
33
+ pathname = Pathname.new(args.shift || "#{stamp}.md")
34
+ pathname.parent.mkpath
35
+ pathname.open("w"){ |f| f.puts content }
36
+ puts "Export a note [%s] into a file [%s]" % [stamp, pathname]
37
+ end
38
+
39
+ def help # :nodoc:
40
+ puts <<HELP
41
+ usage:
42
+ #{Rbnotes::NAME} export [TIMESTAMP [FILENAME]]
43
+
44
+ Write out a given note into a specified file. TIMESTAMP must be a
45
+ fully qualified one, such "20201108141600", or "20201108141600_012" if
46
+ it has a suffix. FILENAME is optional. When it omitted, the filename
47
+ would be a timestamp string with ".md" as its extension, such
48
+ "20201108141600.md"
49
+
50
+ The file will be created into the current working directory unless an
51
+ absolute path is specified as FILENAME.
52
+
53
+ When no argument was passed, it would try to read a timestamp string
54
+ from the standard input. Then, FILENAME would be regarded as omitted.
55
+ HELP
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,98 @@
1
+ module Rbnotes::Commands
2
+
3
+ ##
4
+ # Shows help message for the command which specifies with the
5
+ # argument.
6
+
7
+ class Help < Command
8
+
9
+ def description # :nodoc:
10
+ "Provide help on each command"
11
+ end
12
+
13
+ ##
14
+ # :call-seq:
15
+ # execute(["add"], Rbnotes::Conf or Hash) -> nil
16
+ # execute(["delete"], Rbnotes::Conf or Hash) -> nil
17
+
18
+ def execute(args, conf)
19
+ cmd_name = args.shift
20
+ case cmd_name
21
+ when nil
22
+ self.help
23
+ when "commands"
24
+ print_commands
25
+ else
26
+ Commands.load(cmd_name).help
27
+ end
28
+ end
29
+
30
+ def help # :nodoc:
31
+ puts <<HELP
32
+ #{Rbnotes::NAME.capitalize} is a simple tool to write a note into a single repository.
33
+
34
+ When creates a new note, a timestamp is attached to the note. #{Rbnotes::NAME.capitalize}
35
+ manages notes with those timestamps, such update, delete, ...etc.
36
+
37
+ Timestamp is a series of digits which represents year, date, and time.
38
+ It looks like "20201106121100", means "2020-11-06 12:11:00". It is
39
+ generated in the local time.
40
+
41
+ usage:
42
+ #{Rbnotes::NAME} [option] [command] [args]
43
+
44
+ option:
45
+ -c, --conf [CONF_FILE] : specifiy the configuration file
46
+ -v, --version : print version
47
+ -h, --help : show this message
48
+
49
+ CONF_FILE must be written in YAML. To know about details of the
50
+ configuration file, see README.md or Wiki page.
51
+
52
+ Further help:
53
+ #{Rbnotes::NAME} help commands
54
+ #{Rbnotes::NAME} help COMMAND
55
+ #{Rbnotes::NAME} usage
56
+
57
+ Further information:
58
+ https://github.com/mnbi/rbnotes/wiki
59
+ HELP
60
+ end
61
+
62
+ # :stopdoc:
63
+ private
64
+
65
+ def print_commands
66
+ Dir.glob("*.rb", :base => __dir__) { |rb|
67
+ next if rb == "help.rb"
68
+ require_relative rb
69
+ }
70
+ commands = Commands.constants.difference([:Builtins, :Command])
71
+ builtins = Commands::Builtins.constants
72
+
73
+ puts "#{Rbnotes::NAME.capitalize} Commands:"
74
+ print_commands_desc(commands.sort)
75
+ puts
76
+ puts "for development purpose"
77
+ print_builtins_desc(builtins.sort)
78
+ end
79
+
80
+ def print_commands_desc(commands)
81
+ print_desc(Commands, commands)
82
+ end
83
+
84
+ def print_builtins_desc(builtins)
85
+ print_desc(Commands::Builtins, builtins)
86
+ end
87
+
88
+ def print_desc(mod, commands)
89
+ commands.map { |cmd|
90
+ name = "#{cmd.to_s.downcase} "[0, 8]
91
+ desc = mod.const_get(cmd, false).new.description
92
+ puts " #{name} #{desc}"
93
+ }
94
+ end
95
+
96
+ # :startdoc:
97
+ end
98
+ end
@@ -1,5 +1,29 @@
1
- module Rbnotes
2
- class Commands::Import < Commands::Command
1
+ module Rbnotes::Commands
2
+
3
+ ##
4
+ # Imports a existing file which specified by the argument as a note.
5
+ #
6
+ # A timestamp is generated referring to the birthtime of the given
7
+ # file. If birthtime is not available on the system, use mtime
8
+ # (modification time).
9
+ #
10
+ # Occasionally, there is another note which has the same timestmap
11
+ # in the repository. Then, tries to create a new timestamp with a
12
+ # suffix. Unluckily, when such timestamp with a suffix already
13
+ # exists, tries to create a new one with increasing suffix. Suffix
14
+ # will be "001", "002", ..., or "999". In worst case, all suffix
15
+ # might have been already used. Then, abandons to import.
16
+
17
+ class Import < Command
18
+
19
+ def description # :nodoc:
20
+ "Import a file as a note"
21
+ end
22
+
23
+ ##
24
+ # :call-seq:
25
+ # execute([PATHNAME], Rbnotes::Conf or Hash) -> nil
26
+
3
27
  def execute(args, conf)
4
28
  file = args.shift
5
29
  unless file.nil?
@@ -58,5 +82,18 @@ module Rbnotes
58
82
  super
59
83
  end
60
84
  end
85
+
86
+ def help # :nodoc:
87
+ puts <<HELP
88
+ usage:
89
+ #{Rbnotes::NAME} import FILE
90
+
91
+ Imports a existing file which specified by the argument as a note.
92
+
93
+ A timestamp is generated referring to the birthtime of the given file.
94
+ If birthtime is not available on the system, use mtime (modification
95
+ time).
96
+ HELP
97
+ end
61
98
  end
62
99
  end
@@ -1,15 +1,20 @@
1
1
  require "unicode/display_width"
2
2
  require "io/console/size"
3
3
 
4
- module Rbnotes
4
+ module Rbnotes::Commands
5
+
5
6
  ##
6
7
  # Defines `list` command for `rbnotes`. See the document of execute
7
8
  # method to know about the behavior of this command.
8
9
 
9
- class Commands::List < Commands::Command
10
+ class List < Command
11
+
12
+ def description # :nodoc:
13
+ "List notes"
14
+ end
10
15
 
11
16
  ##
12
- # Shows the list of notes in the repository. The only argument is
17
+ # Shows a list of notes in the repository. The only argument is
13
18
  # optional. If it passed, it must be an timestamp pattern. A
14
19
  # timestamp is an instance of Textrepo::Timestamp class. A
15
20
  # timestamp pattern is a string which would match several
@@ -24,6 +29,9 @@ module Rbnotes
24
29
  # "20201027": specifies year and date
25
30
  # - all Timestamps those have the same year and date would match
26
31
  #
32
+ # "202011": specifies year and month
33
+ # - all Timestamps those have the same year and month would match
34
+ #
27
35
  # "2020": specifies year only
28
36
  # - all Timestamps those have the same year would match
29
37
  #
@@ -45,6 +53,25 @@ module Rbnotes
45
53
  }
46
54
  end
47
55
 
56
+ def help # :nodoc:
57
+ puts <<HELP
58
+ usage:
59
+ #{Rbnotes::NAME} list [STAMP_PATTERN]
60
+
61
+ Show a list of notes. When no arguments, make a list with all notes
62
+ in the repository. When specified STAMP_PATTERN, only those match the
63
+ pattern are listed.
64
+
65
+ STAMP_PATTERN must be:
66
+
67
+ (a) full qualified timestamp (with suffix): "20201030160200"
68
+ (b) year and date part: "20201030"
69
+ (c) year and month part: "202010"
70
+ (d) year part only: "2020"
71
+ (e) date part only: "1030"
72
+ HELP
73
+ end
74
+
48
75
  # :stopdoc:
49
76
 
50
77
  private