fox 0.4.0 → 0.6.2

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: 958a7a559e25d833355bdf0fffd38dac5a54d6d6
4
- data.tar.gz: af8ee1fde1f1f28701dce0549736b9e6f536f15d
3
+ metadata.gz: 857965e1b8fd0f5c481aa1675971cb6e6479cec3
4
+ data.tar.gz: 0e1b11db7c1a364d0ee09eea0a2bbdfcf092d8d5
5
5
  SHA512:
6
- metadata.gz: 587e812e9e989e5e936a3503af624fe4d4848b7243c679d23034076cbb9807a9b5f82f9b9e27f140c651f47bf50cbcc6a878949378826d4c038966c41498d2fd
7
- data.tar.gz: de4e187eb5304bac91fffd4475ed344af4f05ea7305fa31eb0ea564d528d4baaa4136959f748db5e265ec5772750b00b60626e542fd435f0338acae6a6670328
6
+ metadata.gz: 31e854ae25a1280da10618176c53d4edba426e9b2e3b6f598bb1d5dbbeb671bd2e265ff0e6e150ae4c7b5aad630e7c69f2f9118ca16781c5258f692c925d7b4f
7
+ data.tar.gz: 8174e3766090b9d87a1649a1f4a08bd305829dcea65b4c8b10773eedac3c0fb0522c93b7b901cb50ec74cce5be625abc747b0d9489e4f6875a4da121476e8695
@@ -58,7 +58,8 @@ Gem::Specification.new do |spec|
58
58
 
59
59
  spec.files += Dir.glob( 'spec/**/*' )
60
60
 
61
- spec.files += Dir.glob( 'data/**/*' )
61
+ # Exclude data folder (too big)
62
+ # spec.files += Dir.glob( 'data/**/*' )
62
63
 
63
64
  spec.files += Dir.glob( 'documentation/**/*' )
64
65
 
@@ -88,6 +89,8 @@ Gem::Specification.new do |spec|
88
89
  # Shell
89
90
  spec.add_runtime_dependency 'ptools'
90
91
  spec.add_runtime_dependency 'os'
92
+ spec.add_runtime_dependency 'progressbar'
93
+
91
94
 
92
95
  # Database ORM (Persistent)
93
96
  spec.add_runtime_dependency 'datamapper'
@@ -127,6 +130,9 @@ Gem::Specification.new do |spec|
127
130
  spec.add_runtime_dependency 'andand'
128
131
  # spec.add_runtime_dependency 'ick'
129
132
 
133
+ # Audio
134
+ spec.add_runtime_dependency 'taglib-ruby'
135
+
130
136
  # Misc System
131
137
  # spec.add_runtime_dependency 'awesome_print'
132
138
  # spec.add_runtime_dependency 'uuid'
@@ -5,7 +5,6 @@
5
5
  # @brief Fox module namespace
6
6
  module Fox
7
7
 
8
-
9
8
  class FoxError < StandardError
10
9
 
11
10
  class << self
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env ruby
2
+
3
+
4
+ # System
5
+ require 'taglib'
6
+ require 'progressbar'
7
+
8
+
9
+ # @module module Mixin
10
+ # @brief Mixin module contains various functions to be used in other components
11
+ module Mixin
12
+
13
+ # @module Audio Module
14
+ # @brief Module wrapper around audio tasks
15
+ module Audio
16
+
17
+ # @fn def initialize *args {{{
18
+ # @brief Default constructor
19
+ #
20
+ # @param [Array] args Argument array
21
+ def initialize *args
22
+ super
23
+ end # }}}
24
+
25
+ # @fn def play_remote url {{{
26
+ # @brief Play audio content from remote URL
27
+ #
28
+ # @param [String] url Remote URL
29
+ def play_remote url
30
+ play( url, :url )
31
+ end # }}}
32
+
33
+ # @fn def play_local file {{{
34
+ # @brief Play audio content file
35
+ #
36
+ # @param [String] file Filename incl. path
37
+ def play_local file
38
+
39
+ duration = get_duration( file ) # in sec
40
+
41
+ if( duration.nil? )
42
+ play( file, :file )
43
+ else
44
+
45
+ threads = []
46
+
47
+ threads << Thread.new { play( file, :file ) }
48
+ threads << Thread.new do
49
+ ProgressBar.new( "Pomodoro", duration.to_i ) do |bar|
50
+ duration.to_i.times { sleep(1); bar.inc }
51
+ end
52
+ end
53
+
54
+ threads.each { |thread| thread.join }
55
+
56
+ end # if( duration.nil? )
57
+
58
+ end # }}}
59
+
60
+
61
+ private
62
+
63
+ # in sec
64
+ def get_duration file
65
+
66
+ duration = nil
67
+
68
+ begin
69
+ TagLib::FileRef.open( file ) do |fileref|
70
+
71
+ unless fileref.null?
72
+ tag = fileref.tag
73
+ properties = fileref.audio_properties
74
+
75
+ duration = properties.length
76
+ end
77
+
78
+ end # of TagLib
79
+ rescue
80
+ end
81
+
82
+ return duration
83
+ end
84
+
85
+
86
+ def play identifier, type
87
+
88
+ # Check if we are able to playback
89
+ sanity_check
90
+
91
+ if( type == :url )
92
+ # FIXME: Caching!
93
+ `wget #{identifier} -O - | mplayer -really-quiet -cache 8192 -`
94
+ end
95
+
96
+ if( type == :file )
97
+ `mplayer -really-quiet #{identifier}`
98
+ end
99
+
100
+ end
101
+
102
+ def sanity_check
103
+ players = detect_available_players
104
+ # FIXME
105
+ end
106
+
107
+ # sorted after user preference
108
+ def detect_available_players
109
+ # FIXME
110
+ [ "mplayer" ]
111
+ end
112
+
113
+ end # of module Audio
114
+
115
+ end # of module Mixin
116
+
117
+
118
+ # vim:ts=2:tw=100:wm=100:syntax=ruby
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env ruby
2
+
3
+
4
+ # System
5
+ require 'fileutils'
6
+ require 'ostruct'
7
+
8
+
9
+ # @module module Mixin
10
+ # @brief Mixin module contains various functions to be used in other components
11
+ module Mixin
12
+
13
+ # @module Config Module
14
+ # @brief Module wrapper around tasks which demands config file
15
+ module Config
16
+
17
+ # @fn def initialize *args {{{
18
+ # @brief Default constructor
19
+ #
20
+ # @param [Array] args Argument array
21
+ def initialize *args
22
+
23
+ super
24
+
25
+ # Store all config paths and relevant filenames (global)
26
+ @paths = OpenStruct.new
27
+
28
+ # Level 1
29
+ @paths.user_home = Dir.home
30
+ @paths.fox_home = options[:'config-path']
31
+
32
+ # Level 2
33
+ @paths.assets = File.join( @paths.fox_home, 'assets' )
34
+ @paths.databases = File.join( @paths.fox_home, 'databases' )
35
+
36
+ # Level 3
37
+ @paths.pomodoro_assets = File.join( @paths.assets, 'pomodoro' )
38
+ @paths.coffeeshop_assets = File.join( @paths.assets, 'coffeeshop' )
39
+
40
+ # Sanity check, create if doesn't exist in $HOME
41
+ @paths.to_h.each do |tag, uri|
42
+ FileUtils.mkdir_p( uri ) unless( File.exists?( uri ) )
43
+ end
44
+
45
+
46
+ # Remote Assets URLs
47
+ @urls = OpenStruct.new
48
+
49
+ @urls.pomodoro = OpenStruct.new
50
+ @urls.pomodoro.short = 'https://github.com/rennhak/fox/raw/master/data/pomodoro/pomodoro_5.mp3'
51
+ @urls.pomodoro.normal = 'https://github.com/rennhak/fox/raw/master/data/pomodoro/pomodoro_25.mp3'
52
+
53
+ @urls.coffeeshop = OpenStruct.new
54
+ @urls.coffeeshop.morning_murmur = 'https://github.com/rennhak/fox/raw/master/data/coffeeshop/morning_murmur.mp3'
55
+
56
+
57
+ # Assets
58
+ @assets = OpenStruct.new
59
+
60
+ @assets.pomodoro = OpenStruct.new
61
+ @assets.pomodoro.short = File.join( @paths.pomodoro_assets, File.basename( @urls.pomodoro.short ) )
62
+ @assets.pomodoro.normal = File.join( @paths.pomodoro_assets, File.basename( @urls.pomodoro.normal ) )
63
+
64
+ # Config
65
+ @config = OpenStruct.new
66
+
67
+ @config.pomodoro = OpenStruct.new
68
+ @config.pomodoro.default = :normal
69
+
70
+ end # }}}
71
+
72
+ Thor::class_option :'config-path', :type => :string, :required => false, :default => "#{Dir.home}/.fox", :desc => 'Change default config path'
73
+
74
+ end # of module Configuration
75
+
76
+ end # of module Mixin
77
+
78
+
79
+ # vim:ts=2:tw=100:wm=100:syntax=ruby
@@ -15,6 +15,7 @@ module Mixin
15
15
  # @param [Array] args Argument array
16
16
  def initialize *args
17
17
  super
18
+
18
19
  unless File.exist?("~/.fox/config.yaml")
19
20
  abort("Could not find configuration file in ~/.fox/config.yaml. Please run 'fox config:generate' to generate it.")
20
21
  end
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'fox/error/errors'
3
+ # require 'fox/error/errors'
4
4
 
5
5
  module Mixin
6
6
 
@@ -0,0 +1,117 @@
1
+ #!/usr/bin/env ruby
2
+
3
+
4
+ # System
5
+ require 'open-uri'
6
+ require 'net/http'
7
+ require 'net/ftp'
8
+ require 'uri'
9
+ require 'progressbar'
10
+ require 'date'
11
+ require 'tempfile'
12
+ require 'timeout'
13
+
14
+
15
+
16
+ # @module module Mixin
17
+ # @brief Mixin module contains various functions to be used in other components
18
+ module Mixin
19
+
20
+ # @module Network Module
21
+ # @brief Module wrapper around network tasks
22
+ module Network
23
+
24
+ # @fn def initialize *args {{{
25
+ # @brief Default constructor
26
+ #
27
+ # @param [Array] args Argument array
28
+ def initialize *args
29
+ super
30
+ end # }}}
31
+
32
+ # @fn def online? {{{
33
+ # @brief Checks if user is online so we can download assets
34
+ #
35
+ # @return [boolean] True if online, otherwise false
36
+ def online?
37
+
38
+ begin
39
+ true if open( "http://www.google.com/", { read_timeout: 5 } )
40
+ rescue
41
+ false
42
+ end
43
+
44
+ end # }}}
45
+
46
+ # @fn def download url, target_filename # {{{
47
+ # @brief The function get retrieves the given URL content and returns it to the caller
48
+ #
49
+ # @param [String] url Requires a string containing a uri which will be downloaded.
50
+ #
51
+ # @return [OpenStruct] Returns an OpenStruct containing content and many other meta information
52
+ def download url, target_filename, progress_indicator = true
53
+
54
+ # Pre-condition
55
+ raise ArgumentError, "The function expects a string, but got a (#{url.class.to_s})" unless( url.is_a?(String) )
56
+
57
+ # Main
58
+ content = OpenStruct.new
59
+ request = nil
60
+
61
+ begin
62
+ # wait 900s or 15min before timeout
63
+ status = Timeout::timeout( 900 ) {
64
+
65
+ if( progress_indicator )
66
+
67
+ # Inspired by http://www.ruby-doc.org/stdlib-1.9.3/libdoc/open-uri/rdoc/OpenURI/OpenRead.html
68
+ pbar = nil
69
+ request = open( url,
70
+ "r",
71
+ :read_timeout => nil,
72
+ :content_length_proc => lambda {|t|
73
+ if( t && 0 < t )
74
+ pbar = ProgressBar.new("...", t)
75
+ pbar.file_transfer_mode
76
+ end
77
+ },
78
+ :progress_proc => lambda {|s|
79
+ pbar.set s if pbar
80
+ }
81
+ )
82
+
83
+ else
84
+ request = open( url, "r", :read_timeout => nil )
85
+ end
86
+
87
+ STDOUT.puts ""
88
+
89
+ } # end of Timeout::timeout
90
+ rescue Timeout::Error
91
+ puts 'Time out error - That took too long (>=15min) - fatal abort'
92
+ exit
93
+ end
94
+
95
+ content.url = url
96
+ content.content = request.read
97
+ content.content_type = request.content_type
98
+ content.charset = request.charset
99
+ content.content_encoding = request.content_encoding
100
+ content.last_modified = request.last_modified
101
+ content.date = DateTime.now
102
+
103
+ @logger.message :debug, "Writing content to (file, #{target_filename.to_s})"
104
+ File.open( target_filename, "w+" ) { |f| f.write( content.content ) }
105
+
106
+ # Post-condition
107
+ raise ArgumentError, "Result should be of type OpenStruct, but is (#{content.class.to_s})" unless( content.is_a?(OpenStruct) )
108
+
109
+ [ content, target_filename ]
110
+ end # }}}
111
+
112
+ end # of module Network
113
+
114
+ end # of module Mixin
115
+
116
+
117
+ # vim:ts=2:tw=100:wm=100:syntax=ruby
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # System
4
+ require 'open-uri'
5
+
6
+ # Custom includes
7
+ require File.expand_path( File.dirname( __FILE__ ) + '/mixin/logger' )
8
+ require File.expand_path( File.dirname( __FILE__ ) + '/mixin/config' )
9
+ require File.expand_path( File.dirname( __FILE__ ) + '/mixin/network' )
10
+ require File.expand_path( File.dirname( __FILE__ ) + '/mixin/audio' )
11
+
12
+
13
+ # @class Pomodoro command class
14
+ # @brief Allows you to get more productivity with a ticking egg timer
15
+ class Pomodoro < Thor
16
+
17
+ # Include various traits
18
+ include Thor::Actions
19
+ include ::Mixin::Logger
20
+ include ::Mixin::Config
21
+ include ::Mixin::Network
22
+ include ::Mixin::Audio
23
+
24
+ class_option :stream, :type => :boolean, :desc => 'Stream from github.com remote', :default => false
25
+ class_option :download, :type => :boolean, :desc => 'Download from github.com remote', :default => true
26
+
27
+ # @fn def default {{{
28
+ # @brief Plays default Pomodoro clock (25 min)
29
+ desc 'default', 'Plays default Pomodoro clock (25 min) so that you can concentrate'
30
+ def default
31
+
32
+ @logger.message :debug, 'Running sanity check for Pomodoro task'
33
+ sanity_check
34
+
35
+ if( options[:stream] )
36
+ @logger.message :info, 'Streaming from Remote via github.com raw (use CTRL+C to abort)'
37
+ @logger.message :warning, 'Please do not hammer github.com, download if possible instead'
38
+
39
+ play_remote( @urls.pomodoro.send( @config.pomodoro.default ) )
40
+ else
41
+ @logger.message :info, 'Playing local file (use CTRL+C to abort)'
42
+
43
+ play_local( @assets.pomodoro.send( @config.pomodoro.default ) )
44
+ end
45
+
46
+ end # }}}
47
+
48
+ # @fn def short {{{
49
+ # @brief Plays short Pomodoro clock (5 min)
50
+ desc 'short', 'Plays short Pomodoro clock (5 min) so that you can concentrate'
51
+ def short
52
+
53
+ @logger.message :debug, 'Running sanity check for Pomodoro task'
54
+ sanity_check
55
+
56
+ if( options[:stream] )
57
+ @logger.message :info, 'Streaming from Remote via github.com raw (use CTRL+C to abort)'
58
+ @logger.message :warning, 'Please do not hammer github.com, download if possible instead'
59
+
60
+ play_remote( @urls.pomodoro.short )
61
+ else
62
+ @logger.message :info, 'Playing local file (use CTRL+C to abort)'
63
+
64
+ play_local( @assets.pomodoro.short )
65
+ end
66
+
67
+ end # }}}
68
+
69
+
70
+ private
71
+
72
+ no_tasks do
73
+
74
+ # @fn def sanity_check {{{
75
+ # @brief Performs sanity check on online status and required assets
76
+ def sanity_check
77
+
78
+ # Either we stream or we use download / cached version
79
+ if( options[:stream] )
80
+ raise ArgumentError, 'Need to have access to Internet to be able to stream' unless( online? )
81
+ else
82
+ # Download needed?
83
+ broken = check_assets
84
+
85
+ unless( broken.empty? )
86
+ raise ArgumentError, "Need to have access to Internet to be able to download missing assets" unless( online? )
87
+
88
+ # Download!
89
+ broken.each do |type|
90
+ @logger.message :trace, "Downloading missing pomodoro asset (#{type})"
91
+ download @urls.pomodoro.send( type ), @assets.pomodoro.send( type )
92
+ end # of broken.each
93
+
94
+ end # of unless broken.empty?
95
+ end # of if( options[:stream] )
96
+
97
+ end # of def sanity_check }}}
98
+
99
+ # @fn def check_assets {{{
100
+ # @brief Checks local assets for pomodoro task, and if missing returns array with missing keyword
101
+ #
102
+ # @return [Array] Returns array with missing keywords, e.g. "short", "normal"
103
+ def check_assets
104
+ broken = []
105
+
106
+ %w[short normal].each do |type|
107
+ broken << type unless( File.exist?( @assets.pomodoro.send( type ) ) )
108
+ end # of %w[]
109
+
110
+ broken
111
+ end # def check_assets }}}
112
+
113
+ end # of no_tasks do
114
+
115
+ end # of Class New
116
+
117
+
118
+ # vim:ts=2:tw=100:wm=100:syntax=ruby
@@ -7,30 +7,10 @@ require 'andand'
7
7
  require 'fileutils'
8
8
 
9
9
 
10
-
10
+ # @fn class ProjectBuilder
11
+ # @brief Handles project bootstrapping via convenient Fox DSL
11
12
  class ProjectBuilder
12
13
 
13
- attr_reader :name
14
-
15
- TEMPLATES = {
16
- :exe =>
17
- <<-EOT
18
- #!/usr/bin/ruby -w
19
-
20
- require 'rubygems'
21
- require 'commandline
22
- require '%name%'
23
-
24
- class %name.capitalize%App < CommandLine::Application
25
- def initialize
26
- end
27
-
28
- def main
29
- end
30
- end#class %name.capitalize%App
31
- EOT
32
- }
33
-
34
14
  def initialize name
35
15
  @name = name
36
16
  @top_level_dir = Dir.pwd
@@ -41,16 +21,17 @@ EOT
41
21
  @cwd = @project_dir
42
22
  end
43
23
 
44
- def create_project
45
- yield
46
- end # of def create_project }}}
47
-
48
24
  def self.load project_name, dsl
49
25
  proj = new( project_name )
50
26
  proj = proj.instance_eval( File.read(dsl), dsl )
51
27
  proj
52
28
  end # of def self.load }}}
53
29
 
30
+
31
+ def create_project
32
+ yield
33
+ end # of def create_project }}}
34
+
54
35
  def dir dir_name
55
36
  old_cwd = @cwd
56
37
  @cwd = File.join(@cwd, dir_name)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bjoern Rennhak
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: progressbar
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: datamapper
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -346,6 +360,20 @@ dependencies:
346
360
  - - ">="
347
361
  - !ruby/object:Gem::Version
348
362
  version: '0'
363
+ - !ruby/object:Gem::Dependency
364
+ name: taglib-ruby
365
+ requirement: !ruby/object:Gem::Requirement
366
+ requirements:
367
+ - - ">="
368
+ - !ruby/object:Gem::Version
369
+ version: '0'
370
+ type: :runtime
371
+ prerelease: false
372
+ version_requirements: !ruby/object:Gem::Requirement
373
+ requirements:
374
+ - - ">="
375
+ - !ruby/object:Gem::Version
376
+ version: '0'
349
377
  description: Commandline interface and library to the Fox Scientific Paper Suite
350
378
  email:
351
379
  - bjoern@clothesnetwork.com
@@ -389,6 +417,8 @@ files:
389
417
  - lib/fox/interface/thor/default.rb
390
418
  - lib/fox/interface/thor/info.thor
391
419
  - lib/fox/interface/thor/init.rb
420
+ - lib/fox/interface/thor/mixin/audio.rb
421
+ - lib/fox/interface/thor/mixin/config.rb
392
422
  - lib/fox/interface/thor/mixin/config_choice.rb
393
423
  - lib/fox/interface/thor/mixin/configuration.rb
394
424
  - lib/fox/interface/thor/mixin/database.rb
@@ -402,8 +432,10 @@ files:
402
432
  - lib/fox/interface/thor/mixin/history.rb
403
433
  - lib/fox/interface/thor/mixin/logger.rb
404
434
  - lib/fox/interface/thor/mixin/model.rb
435
+ - lib/fox/interface/thor/mixin/network.rb
405
436
  - lib/fox/interface/thor/mixin/shell.rb
406
437
  - lib/fox/interface/thor/new.thor
438
+ - lib/fox/interface/thor/pomodoro.thor
407
439
  - lib/fox/interface/thor/version.rb
408
440
  - lib/fox/library/choice.rb
409
441
  - lib/fox/library/logger.rb