Class: Rbnotes::Utils
- Inherits:
-
Object
- Object
- Rbnotes::Utils
- Includes:
- Singleton
- Defined in:
- lib/rbnotes/utils.rb
Overview
Defines several utility methods those are intended to be used in Rbnotes classes.
Constant Summary collapse
- TIMESTAMP_DELIMITERS =
Acceptable delimiters to separate a timestamp string for human being to read and input easily.
Here is some examples:
- "2021-04-15 15:34:56" -> "20210415153456" (a timestamp string) - "2020-04-15_15:34:56" -> (same as above) - "2020-04-15-15-34-56" -> (same as above) - "2020 04 15 15 34 56" -> (same as above) - "2020-04-15" -> "20200415" (a timestamp pattern)
/[-:_\s]/
Instance Method Summary collapse
-
#expand_keyword_in_args(args) ⇒ Object
Parses the given arguments and expand keywords if found.
-
#find_editor(preferred_editor) ⇒ Object
Finds a external editor program which is specified with the argument, then returns the absolute path of the editor.
-
#find_notes(timestamp_patterns, repo, num_of_notes = 0) ⇒ Object
Finds all notes those timestamps match to given patterns in the given repository.
-
#find_program(names) ⇒ Object
Finds a executable program in given names.
-
#make_headline(timestamp, text, pad = nil) ⇒ Object
Makes a headline with the timestamp and subject of the notes, it looks like as follows:.
-
#read_multiple_timestamps(args) ⇒ Object
Generates multiple Textrepo::Timestamp objects from the command line arguments.
-
#read_timestamp(args) ⇒ Object
Generates a Textrepo::Timestamp object from a String which comes from the command line arguments.
-
#read_timestamp_patterns(args, enum_week: false) ⇒ Object
Reads timestamp patterns in an array of arguments.
-
#run_with_tmpfile(prog, filename, initial_content = nil) ⇒ Object
Executes the program with passing the given filename as argument.
- #specified_recent?(args) ⇒ Boolean
-
#timestamp_patterns_in_week(arg) ⇒ Object
Enumerates all timestamp patterns in a week which contains a given timestamp as a day of the week.
Instance Method Details
#expand_keyword_in_args(args) ⇒ Object
Parses the given arguments and expand keywords if found. Each of the arguments is assumed to represent a timestamp pattern (or a keyword to be expand into several timestamp pattern). Returns an Array of timestamp partterns (each pattern is a String object).
A timestamp pattern looks like:
(a) full qualified timestamp (with suffix): "20201030160200"
(b) year and date part: "20201030"
(c) year and month part: "202010"
(d) year part only: "2020"
(e) date part only: "1030"
KEYWORD:
- "today" (or "to")
- "yeasterday" (or "ye")
- "this_week" (or "tw")
- "last_week" (or "lw")
- "this_month" (or "tm")
- "last_month" (or "lm")
- "all"
:call-seq:
expand_keyword_in_args(Array of Strings) -> Array of Strings
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 |
# File 'lib/rbnotes/utils.rb', line 261 def (args) args = args.dup patterns = [] while args.size > 0 arg = args.shift if arg == "all" or arg == "recent" or arg == "re" return [nil] elsif valid_keyword?(arg) patterns.concat((arg)) else patterns << arg end end patterns.uniq.sort end |
#find_editor(preferred_editor) ⇒ Object
Finds a external editor program which is specified with the argument, then returns the absolute path of the editor. If the specified editor was not found, then search default editors in the command search paths (i.e. ‘ENV). See also the document for `find_program`.
The default editors to search in the search paths are:
-
“nano”
-
“vi”
When all the default editors were not found, returns ‘nil`.
46 47 48 |
# File 'lib/rbnotes/utils.rb', line 46 def find_editor(preferred_editor) find_program([preferred_editor, ENV["EDITOR"], "nano", "vi"].compact) end |
#find_notes(timestamp_patterns, repo, num_of_notes = 0) ⇒ Object
Finds all notes those timestamps match to given patterns in the given repository. Returns an Array contains Timestamp objects. The returned Array is sorted by Timestamp.
When a positive number was specified as the 3rd argument, the number was used as the limitation count of enumerated notes.
:call-seq:
find_notes(Array of patterns, Textrepo::Repository, Integer)
319 320 321 322 323 324 325 326 327 328 329 |
# File 'lib/rbnotes/utils.rb', line 319 def find_notes(, repo, num_of_notes = 0) notes = .map { |pat| repo.entries(pat) }.flatten.sort{ |a, b| b <=> a }.uniq if num_of_notes > 0 notes[0,num_of_notes] else notes end end |
#find_program(names) ⇒ Object
Finds a executable program in given names. When the executable was found, it stops searching then returns an absolute path of the executable.
The actual searching is done in 2 cases. That is, a given name is:
-
an absolute path: returns the path itself if it exists and is executable.
-
just a program name: searchs the name in the search paths (ENV); if it is found in a path, construct an absolute path from the name and the path, then returns the path.
:call-seq:
["nano", "vi"] -> "/usr/bin/nano"
["vi", "/usr/local/bin/emacs"] -> "/usr/bin/vi"
["/usr/local/bin/emacs", "vi"] -> "/usr/bin/vi" (if emacs doesn't exist)
["/usr/local/bin/emacs", "vi"] -> "/usr/local/bin/emacs" (if exists)
70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/rbnotes/utils.rb', line 70 def find_program(names) names.each { |name| pathname = Pathname.new(name) if pathname.absolute? return pathname.to_path if pathname.exist? && pathname.executable? else abs = search_in_path(name) return abs unless abs.nil? end } nil end |
#make_headline(timestamp, text, pad = nil) ⇒ Object
Makes a headline with the timestamp and subject of the notes, it looks like as follows:
|<--------------- console column size -------------------->|
| |+-- timestamp ---+ +-subject (the 1st line of note) -+
| | | |
| |20101010001000_123: I love Macintosh. [EOL]
| |20100909090909_999: This is very very long looong subj[EOL]
|<->| | |
^--- pad ++
^--- delimiter (2 characters)
The subject part will truncate when it is long.
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 |
# File 'lib/rbnotes/utils.rb', line 292 def make_headline(, text, pad = nil) _, column = IO.console_size delimiter = ": " = .to_s.size subject_width = column - - delimiter.size - 1 subject_width -= pad.size unless pad.nil? subject = remove_heading_markup(text[0]) ts_part = "#{.to_s} "[0..( - 1)] ts_part.prepend(pad) unless pad.nil? sj_part = truncate_str(subject, subject_width) ts_part + delimiter + sj_part end |
#read_multiple_timestamps(args) ⇒ Object
Generates multiple Textrepo::Timestamp objects from the command line arguments. When no argument is given, try to read from STDIN.
When multiple strings those point the identical time are included the arguments (passed or read form STDIN), the redundant strings will be removed.
The order of the arguments will be preserved into the return value, even if the redundant strings were removed.
:call-seq:
read_multiple_timestamps(args) -> [String]
152 153 154 155 156 157 158 159 |
# File 'lib/rbnotes/utils.rb', line 152 def (args) strings = args.size < 1 ? read_multiple_args($stdin) : args raise NoArgumentError if (strings.nil? || strings.empty?) strings.uniq.map { |str| str = (str) Textrepo::Timestamp.parse_s(str) } end |
#read_timestamp(args) ⇒ Object
Generates a Textrepo::Timestamp object from a String which comes from the command line arguments. When no argument is given, then reads from STDIN.
:call-seq:
read_timestamp(args) -> String
127 128 129 130 131 132 133 134 135 |
# File 'lib/rbnotes/utils.rb', line 127 def (args) args = args.dup str = args.shift || read_arg($stdin) raise NoArgumentError if str.nil? str = (str) Textrepo::Timestamp.parse_s(str) end |
#read_timestamp_patterns(args, enum_week: false) ⇒ Object
Reads timestamp patterns in an array of arguments. It supports keywords expansion and enumeration of week. The function is intended to be used from Commands::List#execute and Commands::Pick#execute.
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/rbnotes/utils.rb', line 167 def (args, enum_week: false) args = args.dup validate_arguments(args) patterns = nil if enum_week args.unshift(Time.now.strftime("%Y%m%d")) if args.size == 0 patterns = [] while args.size > 0 arg = args.shift begin patterns.concat((arg.dup)) rescue InvalidTimestampPatternAsDateError => _e raise InvalidTimestampPatternAsDateError, args.unshift(arg) end end else patterns = (args) end patterns end |
#run_with_tmpfile(prog, filename, initial_content = nil) ⇒ Object
Executes the program with passing the given filename as argument. The file will be created into ‘Dir.tmpdir`.
If initial_content is not nil, it must be an array of strings then it provides the initial content of a temporary file.
:call-seq:
"/usr/bin/nano", "20201021131300.md", nil -> "/somewhere/tmpdir/20201021131300.md"
"/usr/bin/vi", "20201021131301.md", ["apple\n", "orange\n"] -> "/somewhere/tmpdir/20201021131301.md"
94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/rbnotes/utils.rb', line 94 def run_with_tmpfile(prog, filename, initial_content = nil) tmpfile = File.(add_extension(filename), Dir.tmpdir) unless initial_content.nil? File.open(tmpfile, "w") {|f| f.print(initial_content.join("\n"))} end rc = system(prog, tmpfile) raise ProgramAbortError, [prog, tmpfile] unless rc tmpfile end |
#specified_recent?(args) ⇒ Boolean
331 332 333 334 |
# File 'lib/rbnotes/utils.rb', line 331 def specified_recent?(args) validate_arguments(args) args.include?("recent") or args.include?("re") end |
#timestamp_patterns_in_week(arg) ⇒ Object
Enumerates all timestamp patterns in a week which contains a given timestamp as a day of the week.
The argument must be one of the followings:
- "yyyymodd" (eg. "20201220")
- "yymoddhhmiss" (eg. "20201220120048")
- "yymoddhhmiss_sfx" (eg. "20201220120048_012")
- "modd" (eg. "1220") (assums in the current year)
- nil (assumes today)
:call-seq:
timestamp_patterns_in_week(String) -> [Array of Strings]
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/rbnotes/utils.rb', line 203 def (arg) date_str = nil if arg date_str = (arg) else date_str = Textrepo::Timestamp.now[0, 8] end case date_str.size when "yyyymodd".size # nothing to do when "yyyymoddhhmiss".size, "yyyymoddhhmiss_sfx".size date_str = date_str[0, 8] when "modd".size this_year = Time.now.year.to_s date_str = "#{this_year}#{date_str}" else raise InvalidTimestampPatternAsDateError, arg end begin date = Date.parse(date_str) rescue Date::Error => _e raise InvalidTimestampPatternAsDateError, arg end dates_in_week(date).map { |date| (date) } end |