Class: Yornal

Inherits:
Object
  • Object
show all
Defined in:
lib/yornal.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name) ⇒ Yornal

instance methods



78
79
80
81
# File 'lib/yornal.rb', line 78

def initialize(name)
  @name = name
  @type = Yornal.list[name]
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



2
3
4
# File 'lib/yornal.rb', line 2

def name
  @name
end

#typeObject (readonly)

Returns the value of attribute type.



2
3
4
# File 'lib/yornal.rb', line 2

def type
  @type
end

Class Method Details

.create(name, type) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/yornal.rb', line 16

def self.create(name, type)
  { /^\./ => "begin with a dot",
   %r{^/} => "begin with /",
   %r{/$} => "end with /",
   /\^/ => "contain ^",
   %r{//} => "contain consecutive /",
   /\.git/ => "contain '.git'",
   /^git$/ => "be 'git'",
   /^\d+$/ => "be digits only",
   %r{[^/._A-za-z0-9-]} => "have chars not in [a-z], [0-9] or [/_-.]" }.each do |regex, message|
    err "name cannot #{message}" if name =~ regex
  end

  err "yornal '#{name}' already exists" if Yornal.list.find { |n, _| n == name }

  [$yornalPath, name]
    .jomp("/").tap(&method(type == :box ? :touch : :mkdir))
    .then { |f| git(:add, f) if type == :box }

  message = "Create #{type} yornal '#{name}'"
  Yornal.dotYornalEdit(message) { |h| h[name] = type }
end

.delete(name, ask = true) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/yornal.rb', line 39

def self.delete(name, ask = true)
  Yornal.list.any? { |n, _| n == name } or err "'#{name}' yornal doesn't exist"
  pre = "You are about to delete yornal '#{name}'."
  question = "Are you sure you want to delete it?"

  if !ask || yes_or_no?(question, pre)
    Yornal.new(name).entries.each { |e| e.delete(ask = false) }
    message = "Delete #{name} yornal"
    Yornal.dotYornalEdit(message) do |h|
      h.delete name
    end

    system "rm -rf #{name} 2> /dev/null"
  end
end

.dotYornalEdit(message, &block) ⇒ Object

class methods



6
7
8
9
10
11
12
13
14
# File 'lib/yornal.rb', line 6

def self.dotYornalEdit(message, &block)
  File.write(
    $dotyornal,
    Yornal.list.tap(&block)
  )

  git(:add, $dotyornal)
  git(:commit, "-m '#{message}'")
end

.listObject



55
56
57
58
59
# File 'lib/yornal.rb', line 55

def self.list
  eval(File.read($dotyornal)).assert(Hash)
rescue Exception
  err "Malformed .yornal file"
end

.reportObject



61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/yornal.rb', line 61

def self.report
  spacing = nil
  countSpacing = nil
  Yornal.list.keys
        .map { |y| [y, Yornal.new(y).entries.size] }
        .tap do |ycs|
    die { puts "No yornals available. Create one with --create" } if ycs.empty?
    spacing = (ycs + [["yornal"]]).map(&:first).map(&:size).max + 1
    countSpacing = ycs.map(&:last).map(&:to_s).map(&:size).max
    printf "%-#{spacing}s %-#{countSpacing}s  type\n", "yornal", "#"
  end.each do |y, c|
    printf "%-#{spacing}s %-#{countSpacing}d  %s\n", y, c, Yornal.new(y).type
  end
end

Instance Method Details

#edit(editor = editor(), time = Time.now, ignore = nil) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/yornal.rb', line 87

def edit(editor = editor(), time = Time.now, ignore = nil)
  entryParent = [path, time.path(@type)].jomp("/")
  mkdir(entryParent) unless @type == :box
  entry = [entryParent, time.send(@type).to_s].jomp("/")

  if File.exist? entry
    Entry.fromPath(entry).edit(editor, :Modify, ignore)
  else
    system "touch #{entry}"
    Entry.fromPath(entry).edit(editor, :Create, ignore)
    File.delete entry if File.size(entry) == 0
  end
end

#entries(query = "@") ⇒ Object



101
102
103
# File 'lib/yornal.rb', line 101

def entries(query = "@")
  self.query(query).map { |p| Entry.fromPath p }.sort
end

#first(x, n = 1, from = entries) ⇒ Object



127
128
129
130
131
132
# File 'lib/yornal.rb', line 127

def first(x, n = 1, from = entries)
  return from[..(n - 1)] if x == :entry

  t = from[0].to_t
  from.filter { |e| e < (t + n) }
end

#last(x, n = 1, from = entries) ⇒ Object



134
135
136
137
138
139
# File 'lib/yornal.rb', line 134

def last(x, n = 1, from = entries)
  return from[(-n)..] if x == :entry

  t = Time.now
  from.filter { |e| e > (t - n) }
end

#pathObject



83
84
85
# File 'lib/yornal.rb', line 83

def path
  $yornalPath + "/" + @name
end

#query(pattern) ⇒ Object

e.g. pattern: @/@/8, 2022/09/@ ; depends on yornal type (depth)



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/yornal.rb', line 106

def query(pattern)
  dateStructure = i[year month day hour min]
  datehash = ->(x) { x.zip(dateStructure).to_h.flip }

  tree(path).filter do |path|
    entry = path[$yornalPath.size + @name.size + 1..]
    unless entry.split("/").join =~ /\D/ # remove nested yornals
      entryHash = datehash.call(entry.stlip("/"))
      patternHash = datehash.call(pattern.downcase.stlip("/"))

      patternHash.map do |k, v|
        !entryHash[k] or (v == "@") or
          v.split(",").map do |x|
            l, r = x.split("-")
            (l..(r or l)) # ranges work for integer strings
          end.any? { |range| range.include? entryHash[k] }
      end.all? true
    end
  end
end