aniview 3.0.1 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
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"