aniview 3.0.1 → 3.1.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4b35aefbae5c33c60dd90e34e39ba25538fb537d
4
- data.tar.gz: f930e37c98cab765b2baaf880e1631e9b8cee308
3
+ metadata.gz: 827d5b9084b305647f640fd4cf3ba14ce15bcea5
4
+ data.tar.gz: 3e10b4ccf9d9f02cfee4260921eb7f22ae097339
5
5
  SHA512:
6
- metadata.gz: 0cb7100a4503b321ebac1a28582d856fc2b536fbae03ffa7dbc3d9bcacb5d5506e3ba8f75871822f749695afff13c9249bee1fc6bdb309c2d0265e366e49cace
7
- data.tar.gz: def2061bba9ae07a58886a26a0f8d468632d98623c1d13be405f895651be834e4d737aebc7df084fcf79b5bd44ac274012c264f35bdad467c245078b4428597c
6
+ metadata.gz: 69a1e2a4ba2c11f38811bb5eb951993f5ea41228796c77f397a9292c2f053993f653b8ecbe614df7c41a9fe3d3a88c481bc8379e73340d0ea580166974c57206
7
+ data.tar.gz: 6195b01dcd02520fb7119c4b690f2266c0459ea603b96c6eaea03ab9e6aa352314800cac6b6f3052f846306886a409b7772fa0d6534ae2d29f7ad18ff73dbb97
@@ -0,0 +1,12 @@
1
+ # aniview
2
+ command line anime library viewer
3
+
4
+ ![screenshot](https://raw.githubusercontent.com/annacrombie/aniview/master/screenshot.png)
5
+
6
+ ## installation
7
+ ### using rubygems
8
+ `gem install aniview`
9
+
10
+ ### Find out more on the wiki
11
+ + [Default Keybingings](https://github.com/annacrombie/aniview/wiki/Default-Keybindings)
12
+ + [Format Strings](https://github.com/annacrombie/aniview/wiki/Format-Strings)
@@ -1,3 +1,4 @@
1
+ require_relative 'aniview/util/error'
1
2
  require_relative 'application'
2
3
  require_relative 'daemon'
3
4
 
@@ -6,166 +6,183 @@ require_relative '../../view/color'
6
6
  require_relative '../bridge'
7
7
 
8
8
  module Aniview
9
+
9
10
  module Interface
11
+
12
+ ##
13
+ ## @brief Class for preferences.
14
+ ##
10
15
  class Pref < Bridge
11
16
 
12
17
  include Observable
13
18
 
14
- def initialize
15
- @home = Dir.home
16
- @conf = @home + "/.config/aniview"
17
-
18
- File.open(File.join(File.dirname(__FILE__), "/validate.json"), "r") {
19
- |f| @validate = JSON.parse(f.read)
20
- }
21
-
22
- FileUtils.mkdir_p(@conf) unless File.directory?(@conf)
19
+ attr_accessor :logger
23
20
 
24
- @pref_file = @conf + "/aniview.json"
21
+ ##
22
+ ## @brief Initializes pref object, with optional logger
23
+ ##
24
+ ## @param logger The logger
25
+ ##
26
+ ## @return A new pref object
27
+ ##
28
+ def initialize(logger: nil)
29
+ @logger = logger
30
+ conf = Dir.home + "/.config/aniview"
31
+ @default_file = File.join(File.dirname(__FILE__), "/defaults.json")
32
+ @pref_file = conf + "/aniview.json"
33
+ validation_file = File.join(File.dirname(__FILE__), "/validate.json")
34
+ @validations = read(validation_file)
25
35
 
26
- @saving = false
27
-
28
- defaults should_save: true if not File.exist?(@pref_file)
36
+ FileUtils.mkdir_p(conf) unless File.directory?(conf)
29
37
  load
38
+ save unless File.exist?(@pref_file)
30
39
  end
31
40
 
32
- def parseDir path
33
- path = path.gsub("$airing_dir", @pref["airing_dir"])
34
- path = path.gsub("$conf_dir", @pref["conf_dir"])
35
- path = path.gsub("~", Dir.home)
36
-
37
- return path
38
- end
39
-
40
- def defaults(should_save:false)
41
- File.open(File.join(File.dirname(__FILE__), "/defaults.json"), "r") {|f| @pref = JSON.parse(f.read)}
42
- save if should_save
41
+ ##
42
+ ## @brief converts a directory like "~/movies" to
43
+ ## "/users/shinji/movies/"
44
+ ##
45
+ ## @param path The path to parse
46
+ ##
47
+ ## @return the parsed directory string
48
+ ##
49
+ def parseDir(path)
50
+ {
51
+ "$airing_dir" => @pref["airing_dir"],
52
+ "$conf_dir" => @pref["conf_dir"],
53
+ "~" => Dir.home
54
+ }.inject(path) { |path, r| path.gsub(r[0], r[1]) }
43
55
  end
44
-
45
- def set(s, val)
46
- trail = [s] if s.class == String
47
- trail = s if s.class == Array
48
- if valpref(trail, val, @validate)
49
- @pref = setpref(trail, val, @pref)
50
- save
51
- changed
52
- notify_observers
53
- end
56
+
57
+ ##
58
+ ## @brief gets a preference
59
+ ##
60
+ ## @param key The key
61
+ ##
62
+ ## @return the preference at key or nil if there is no such preference
63
+ ##
64
+ def get(key)
65
+ @pref[key] if @pref.key?(key)
54
66
  end
55
67
 
56
- def setpref(trail, destination, map)
57
- if trail.length == 1
58
- map[trail[0]] = destination
59
- return map
60
- else
61
-
62
- blaze = trail[0]
63
- map[blaze] = setpref(trail[1..-1], destination, map[blaze])
64
-
65
- end
66
- return map
68
+ ##
69
+ ## @brief Validates and sets a preference
70
+ ##
71
+ ## @param trail The key or array of keys that specify where
72
+ ## the preference is stored
73
+ ## @param destination The new value for the preference
74
+ ##
75
+ ## @return nil
76
+ ##
77
+ def set(trail, destination)
78
+ trail = [trail] if trail.class == String
79
+ return unless valid_preference?(trail, destination)
80
+
81
+ trail[0...-1].inject(@pref, :fetch)[trail.last] = destination
82
+ save
83
+ changed
84
+ notify_observers
67
85
  end
68
86
 
69
- def valpref(trail, destination, map)
70
-
71
- if trail.length == 1
72
- skeys = [
73
- "space",
74
- "up",
75
- "down",
76
- "left",
77
- "right",
78
- "enter"
79
- ]
80
-
81
- case map[trail[0]]
82
- when "key"
83
- return false if destination.length != 1 and not skeys.include? destination
84
-
85
- when "path"
86
- destination.split(":").each { |d|
87
- return false if not Dir.exist?(parseDir d)
88
- }
89
-
90
- when "color"
91
- return false if not Aniview::View::Color.respond_to? destination
92
-
93
- when "int"
94
- return false if not destination.scan(/\D/).empty? and destination.length > 1
95
-
96
- when "locked"
97
- return false
98
-
99
- end
100
-
101
- return true
102
-
103
- else
104
- blaze = trail[0]
105
- return valpref(trail[1..-1], destination, map[blaze])
87
+ ##
88
+ ## @brief validates a preference
89
+ ##
90
+ ## @param trail The array of keys that specify where the
91
+ ## preference is stored
92
+ ## @param destination The new value for the preference
93
+ ##
94
+ ## @return true if preference is valid, false otherwise
95
+ ##
96
+ def valid_preference?(trail, destination)
97
+ skeys = [ "space", "up", "down", "left", "right", "enter" ]
98
+
99
+ case trail.inject(@validations, :fetch)
100
+ when "key"
101
+ destination.length == 1 or skeys.include?(destination)
102
+ when "path"
103
+ destination.split(":").map { |d| Dir.exist?(parseDir d) }.reduce { |m, n| m and n }
104
+ when "color"
105
+ Aniview::View::Color.respond_to?(destination)
106
+ when "int"
107
+ destination.scan(/\D/).empty? and destination.length > 1
108
+ when "locked"
109
+ false
110
+ else
111
+ true
106
112
  end
107
113
  end
108
-
109
- def get s
110
- return @pref[s] if @pref.key?(s)
111
- end
112
114
 
115
+ ##
116
+ ## @brief gets an array of PrefItems to be displayed in the menu
117
+ ##
118
+ ## @return an array of PrefItems
119
+ ##
113
120
  def items
114
121
  ignore = {
115
122
  "local_anime" => true,
116
123
  "schedule" => true,
117
124
  }
118
-
119
- r = {}
120
- @pref.each{ |item|
121
- next if ignore.key? item[0]
122
- title = item[0]
123
- if item[1].class == String
124
- val = item[1]
125
- elsif item[1].class == Array
126
- val = item[1].join(":")
127
- elsif item[1].class == Hash
128
- item[1].each { |subitem|
129
- subtitle = title + "_" + subitem[0]
130
- subval = subitem[1]
131
- r.merge!(PrefItem.new(subtitle, subval, []) => [PrefItem.new("", "", [item[0], subitem[0]])])
125
+ @pref.map{ |title, preference|
126
+ next if ignore.key? title
127
+ if preference.class == Hash
128
+ preference.map { |subtitle, subpreference|
129
+ PrefItem.new(title + "_" + subtitle, subpreference, [title, subtitle])
132
130
  }
133
- next
131
+ else
132
+ preference = preference.join(":") if preference.class == Array
133
+ PrefItem.new(title, preference, [title])
134
134
  end
135
- r.merge!(PrefItem.new(title, val, []) => [ PrefItem.new("", "", [item[0]]) ] )
136
- }
137
- return r
135
+ }.flatten.compact
138
136
  end
139
137
 
138
+ ##
139
+ ## @brief saves the prefs to disk
140
+ ##
141
+ ## @return nil
142
+ ##
140
143
  def save
141
- @saving = true
142
144
  File.open(@pref_file, "w") { |f| f.write(JSON.pretty_generate(@pref)) }
143
- @saving = false
144
145
  end
145
146
 
146
- def saving?
147
- @saving
148
- end
149
-
147
+ ##
148
+ ## @brief loads the prefs from file
149
+ ##
150
+ ## @param file The file
151
+ ##
152
+ ## @return nil
153
+ ##
150
154
  def load
151
- begin
152
- #json = ""
153
- json = File.open(@pref_file, "r") {|f| f.read}
154
- #puts json
155
- if json == ""
156
- #puts "going to defaults"
157
- defaults
158
- return
159
- end
160
- @pref = JSON.parse json
161
- rescue JSON::ParserError
162
- puts "severe! your preference file #{@pref_file} is corrupted,"
163
- puts "please fix the file or delete it to restore defaults"
164
- exit
165
- end
155
+ @pref = read(@pref_file) || read(@default_file)
166
156
  changed
167
157
  notify_observers
168
158
  end
159
+
160
+ ##
161
+ ## @brief reads json from a file
162
+ ##
163
+ ## @param file The file
164
+ ##
165
+ ## @return parsed json
166
+ ##
167
+ def read(file)
168
+ begin
169
+ File.open(file, "r") { |f|
170
+ json = f.read
171
+ if json.empty?
172
+ return nil
173
+ else
174
+ begin
175
+ JSON.parse json
176
+ rescue JSON::ParserError
177
+ raise Aniview::Error::InvalidPref.new
178
+ end
179
+ end
180
+ }
181
+ rescue Errno::ENOENT
182
+ return nil
183
+ end
184
+ end
185
+
169
186
  end
170
187
  end
171
188
  end
@@ -0,0 +1,9 @@
1
+ module Aniview
2
+ module Error
3
+ class InvalidPref < StandardError
4
+ def initialize(msg="Your preferences file is invalid")
5
+ super
6
+ end
7
+ end
8
+ end
9
+ end
@@ -11,9 +11,11 @@ module Aniview
11
11
 
12
12
  attr_accessor :visible
13
13
 
14
- def initialize(refresh_function: :items, interface:, name:, pref:, format:, term:, children: true, visible: false)
14
+ def initialize(refresh_function: :items, interface:, name:, pref:, format:, term:, children: true, visible: false, logger: nil)
15
15
  @attributes = {}
16
16
 
17
+ @logger = logger
18
+
17
19
  @visible = visible
18
20
 
19
21
  @refresh_function = refresh_function
@@ -111,7 +113,7 @@ module Aniview
111
113
  @items = @interface.send(@refresh_function)
112
114
  refreshFormats
113
115
  refresh_attributes
114
- @expanded = -1 if @items.values[@expanded] == nil
116
+ @expanded = -1 if @children and @items.values[@expanded] == nil
115
117
  fixCursor
116
118
  changed
117
119
  notify_observers
@@ -132,7 +134,7 @@ module Aniview
132
134
  notify_observers
133
135
  end
134
136
 
135
- def resolveSelected(resolve_me=@selected)
137
+ def resolve_selected(resolve_me=@selected)
136
138
  in_expanded=false
137
139
  inside = 0
138
140
  outside = resolve_me
@@ -274,7 +276,7 @@ module Aniview
274
276
  print lo + @cl["m"] + @title_formatted + "\e[K"
275
277
 
276
278
  #get the resolved start positions
277
- resolved_start_position = resolveSelected line_on
279
+ resolved_start_position = resolve_selected line_on
278
280
  outer_index = resolved_start_position["out"]
279
281
  inner_index = resolved_start_position["in"]
280
282
 
@@ -288,7 +290,7 @@ module Aniview
288
290
  while line_on < lines_to_draw
289
291
 
290
292
  in_outer_region = ! (line_on >= getLen)
291
- in_expanded_region = resolveSelected(line_on)["in_expanded"]
293
+ in_expanded_region = resolve_selected(line_on)["in_expanded"]
292
294
  line = line_on-offset+1
293
295
  selected = line_on == @selected
294
296
 
@@ -311,7 +313,7 @@ module Aniview
311
313
  end
312
314
 
313
315
  def control(key)
314
- sel = resolveSelected
316
+ sel = resolve_selected
315
317
  if key == @pref.get("keybindings")["menu_nav_up"]
316
318
  moveCursor("up")
317
319
  elsif key == @pref.get("keybindings")["menu_nav_down"]
@@ -7,10 +7,9 @@ module Aniview
7
7
  include Aniview::Util
8
8
 
9
9
  def customControl(key, sel)
10
- return if @items.keys[sel["out"]].attributes["t"] == ""
11
- path = @items.values[sel["out"]][0].path
12
- title = @items.keys[sel["out"]].attributes["t"]
13
- value = @items.keys[sel["out"]].attributes["v"]
10
+ path = @items[sel["out"]].path
11
+ title = @items[sel["out"]].attributes["t"]
12
+ value = @items[sel["out"]].attributes["v"]
14
13
  if key == "enter"
15
14
  newval = Util.readline(@term, title + ":", value)
16
15
  @interface.set(path, newval)
@@ -42,13 +42,14 @@ module Aniview
42
42
  #
43
43
  def initialize
44
44
 
45
- #@logger = Logger.new('aniview.log')
46
- #@logger.level = Logger::DEBUG
47
-
48
45
  @term = Util::Term.new
49
46
 
50
47
  @pref = Interface::Pref.new
51
48
 
49
+ @logger = Logger.new(@pref.parseDir(@pref.get("log_file")))
50
+ @logger.level = Logger::DEBUG
51
+ @pref.logger = @logger
52
+
52
53
  @mpvbridge = Interface::MPVBridge.new @pref
53
54
 
54
55
  @aio = Interface::AnimeIO.new @pref, @mpvbridge
@@ -78,7 +79,8 @@ module Aniview
78
79
  pref: @pref,
79
80
  format: "format_library_unwatched",
80
81
  term: @term,
81
- refresh_function: :unwatched
82
+ refresh_function: :unwatched,
83
+ logger: @logger
82
84
  )
83
85
  @prefmenu = View::PrefMenu.new(
84
86
  interface: @pref,
@@ -86,7 +88,8 @@ module Aniview
86
88
  pref: @pref,
87
89
  format: "format_preferences",
88
90
  term: @term,
89
- children: false
91
+ children: false,
92
+ logger: @logger
90
93
  )
91
94
  @delugemenu = View::DelugeMenu.new(
92
95
  interface: @delugec,
@@ -94,7 +97,8 @@ module Aniview
94
97
  pref: @pref,
95
98
  format: "format_torrents",
96
99
  term: @term,
97
- children: false
100
+ children: false,
101
+ logger: @logger
98
102
  )
99
103
  @schedulemenu = View::ScheduleMenu.new(
100
104
  interface: @schedule,
@@ -102,7 +106,8 @@ module Aniview
102
106
  pref: @pref,
103
107
  format: "format_schedule",
104
108
  term: @term,
105
- children: false
109
+ children: false,
110
+ logger: @logger
106
111
  )
107
112
  @subscriptionmenu = View::SubscriptionMenu.new(
108
113
  interface: @subscription,
@@ -110,7 +115,8 @@ module Aniview
110
115
  pref: @pref,
111
116
  format: "format_subscriptions",
112
117
  term: @term,
113
- children: false
118
+ children: false,
119
+ logger: @logger
114
120
  )
115
121
  @term.save.hide_cursor.echo_off
116
122
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aniview
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.1
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - annacrombie
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-24 00:00:00.000000000 Z
11
+ date: 2017-07-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: streamio-ffmpeg
@@ -137,6 +137,7 @@ executables:
137
137
  extensions: []
138
138
  extra_rdoc_files: []
139
139
  files:
140
+ - "./README.md"
140
141
  - "./lib/aniview.rb"
141
142
  - "./lib/aniview/client/aniclient.rb"
142
143
  - "./lib/aniview/interface/animeio/animefile.rb"
@@ -154,6 +155,7 @@ files:
154
155
  - "./lib/aniview/interface/schedule/schedule.rb"
155
156
  - "./lib/aniview/interface/schedule/scheduleitem.rb"
156
157
  - "./lib/aniview/interface/subscription/subscription.rb"
158
+ - "./lib/aniview/util/error.rb"
157
159
  - "./lib/aniview/util/term.rb"
158
160
  - "./lib/aniview/util/util.rb"
159
161
  - "./lib/aniview/view/aiomenu.rb"