moodwall 0.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.
@@ -0,0 +1,39 @@
1
+ # Moodwall
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/moodwall`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'moodwall'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install moodwall
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/moodwall. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
36
+
37
+ ## Code of Conduct
38
+
39
+ Everyone interacting in the Moodwall project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/moodwall/blob/master/CODE_OF_CONDUCT.md).
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "moodwall"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ require "pry"
11
+ Pry.start
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ begin
4
+ require "bundler/setup"
5
+ require "moodwall"
6
+ rescue LoadError
7
+ require "rubygems"
8
+ require "moodwall"
9
+ end
10
+
11
+ require "optparse"
12
+ require 'ostruct'
13
+ require 'pp'
14
+
15
+ class Moodwall::Optparse
16
+ class ScriptOptions
17
+ attr_accessor :change, :add, :mood, :wallpaper,
18
+ :path, :mood_name
19
+
20
+
21
+ def initialize
22
+ self.change = true
23
+ self.add = false
24
+ self.mood = false
25
+ self.wallpaper = true
26
+ end
27
+
28
+ def define_options(parser)
29
+ parser.banner = "Usage: moodwall [options]\nDefaults: moodwall -c -w"
30
+ parser.separator ""
31
+ parser.separator "Specific options:"
32
+
33
+ # additional commands
34
+ change_option(parser)
35
+ add_option(parser)
36
+ wallpaper_option(parser)
37
+ mood_option(parser)
38
+
39
+ parser.separator ""
40
+ parser.separator "Common options:"
41
+
42
+ parser.on_tail("-h", "--help", "Show this message") do
43
+ puts parser
44
+ exit
45
+ end
46
+
47
+ parser.on_tail("-v", "--version", "Show version") do
48
+ puts Moodwall::VERSION
49
+ exit
50
+ end
51
+ end
52
+
53
+ def change_option(parser)
54
+ parser.on("-c", "--change", "Change [target]") do
55
+ self.change = true
56
+ self.add = false
57
+ end
58
+ end
59
+
60
+ def add_option(parser)
61
+ parser.on("-a", "--add", "Add [target]") do
62
+ self.add = true
63
+ self.change = false
64
+ end
65
+ end
66
+
67
+ def wallpaper_option(parser)
68
+ parser.on("-w", "--wallpaper [PATH]", "Specifies wallpaper path") do |path, mood_name|
69
+ self.wallpaper = true
70
+ self.path = path
71
+ self.mood_name = mood_name
72
+ end
73
+ end
74
+
75
+ def mood_option(parser)
76
+ parser.on("-m", "--mood NAME", "Specifies mood name") do |mood_name|
77
+ self.mood = true
78
+ self.mood_name = mood_name
79
+ end
80
+ end
81
+ end
82
+
83
+ def parse(args)
84
+ @options = ScriptOptions.new
85
+ @args = OptionParser.new do |parser|
86
+ @options.define_options(parser)
87
+ parser.parse!(args)
88
+ end
89
+ @options
90
+ end
91
+
92
+ attr_reader :parser, :options
93
+ end
94
+
95
+ options = Moodwall::Optparse.new.parse(ARGV)
96
+
97
+ case
98
+ when options.add && options.mood && !options.mood_name.nil? && options.path.nil?
99
+ Moodwall::Mood.new({name: options.mood_name}).save
100
+ when options.change && options.mood && !options.mood_name.nil?
101
+ Moodwall::Mood.set_current(name: options.mood_name)
102
+ when options.add && options.wallpaper && !options.path.nil? && !options.mood_name.nil?
103
+ mood = Moodwall::Mood.find_by_name(options.mood_name)
104
+ Moodwall::Wallpaper.new({path: options.path, mood_id: mood.id}).save
105
+ when options.change && options.wallpaper
106
+ executable = Moodwall::Executable.new({ command: "feh", arguments: "--bg-fill" })
107
+ wallpaper = Moodwall::Wallpaper.sample
108
+ executable.execute(wallpaper.path)
109
+ end
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,10 @@
1
+ require "moodwall/executable"
2
+ require "moodwall/version"
3
+ require "moodwall/repository"
4
+ require "moodwall/record"
5
+ require "moodwall/mood"
6
+ require "moodwall/wallpaper"
7
+
8
+ module Moodwall
9
+ # Your code goes here...
10
+ end
@@ -0,0 +1,28 @@
1
+ module Moodwall
2
+ class MissingExecutableError < StandardError; end
3
+
4
+ class Executable
5
+ attr_reader :command, :arguments
6
+
7
+ def initialize(options = {})
8
+ @command = options.fetch(:command, nil)
9
+ @arguments = options.fetch(:arguments, nil)
10
+ error_if_missing
11
+ end
12
+
13
+ def error_if_missing
14
+ raise(MissingExecutableError, "Can't find the `#{ command }`") unless installed?
15
+ end
16
+
17
+ def execute(path)
18
+ system "#{ command } #{ arguments } #{ path }"
19
+ end
20
+
21
+ private
22
+
23
+ def installed?
24
+ system "which #{ command }"
25
+ $?.success?
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,19 @@
1
+ module Moodwall
2
+ class Mood < Record
3
+ attr_reader :name
4
+ attr_accessor :current
5
+
6
+ def initialize(name:, current: false)
7
+ @name = name
8
+ @current = current
9
+ end
10
+
11
+ def self.current
12
+ all.find { |m| m.current == true }
13
+ end
14
+
15
+ def self.find_by_name(name)
16
+ all.find { |m| m.name.casecmp(name).zero? }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,86 @@
1
+ require "pstore"
2
+
3
+ module Moodwall
4
+ class RecordNotFoundError < StandardError; end
5
+
6
+ class Record
7
+ include Comparable
8
+
9
+ attr_writer :repository
10
+ attr_reader :id
11
+
12
+ class << self
13
+ def repository
14
+ Thread.current[:repository] ||= PStore.new("database.store")
15
+ end
16
+
17
+ def all
18
+ transaction(read_only: true) do |store|
19
+ Array store[name]
20
+ end
21
+ end
22
+
23
+ def reset
24
+ transaction do |store|
25
+ store.delete name
26
+ end
27
+ end
28
+
29
+ def find!(id)
30
+ all.find { |r| r.id == id.to_i } ||
31
+ raise(RecordNotFoundError, "Can't find the record with id: #{ id }")
32
+ end
33
+
34
+ def next_id
35
+ all.map(&:id).max.to_i + 1
36
+ end
37
+
38
+ def transaction(read_only: false, &transaction_body)
39
+ repository.transaction(read_only, &transaction_body)
40
+ end
41
+ end
42
+
43
+ def ==(other)
44
+ id == other.id
45
+ end
46
+
47
+ def save
48
+ if new_record?
49
+ @id = self.class.next_id
50
+
51
+ transaction do |store|
52
+ store[self.class.name] ||= []
53
+ store[self.class.name] << self
54
+ end
55
+ else
56
+ transaction do |store|
57
+ store[self.class.name].delete_if { |r| r.id == @id }
58
+ store[self.class.name] << self
59
+ end
60
+ end
61
+ self
62
+ end
63
+ alias save! save
64
+
65
+ def delete
66
+ self.class.repository.transaction do |store|
67
+ Array(store[self.class.name]).delete self
68
+ end
69
+ self
70
+ end
71
+
72
+ def new_record?
73
+ @id.nil?
74
+ end
75
+
76
+ def reload
77
+ self.class.find! @id
78
+ end
79
+
80
+ private
81
+
82
+ def transaction(**options, &transaction_body)
83
+ self.class.transaction(**options, &transaction_body)
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,22 @@
1
+ require "pstore"
2
+
3
+ module Moodwall
4
+ class Repository
5
+ attr_reader :store
6
+
7
+ def initialize(store = PStore.new("database.pstore"))
8
+ @store = store
9
+ end
10
+
11
+ def self.store
12
+ new.store
13
+ end
14
+
15
+ def self.reset
16
+ store = self.store
17
+ store.transaction do
18
+ store.roots.each { |r| store.delete r }
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ module Moodwall
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,51 @@
1
+ module Moodwall
2
+ class WallpaperNotFoundError < StandardError; end
3
+ class MissingPathError < StandardError; end
4
+ class MissingFileError < StandardError; end
5
+
6
+ class Wallpaper < Record
7
+ include Comparable
8
+
9
+ attr_reader :mood_id, :path, :weight
10
+
11
+ def initialize(options)
12
+ @path = options.fetch(:path) { raise(MissingPathError, "Wallpaper path is required") }
13
+ @mood_id = options.fetch(:mood_id) { Moodwall::Mood.current }
14
+ @weight = options.fetch(:weight, 0)
15
+ end
16
+
17
+ class << self
18
+ def sample
19
+ record = all.shuffle.min
20
+ raise(WallpaperNotFoundError, "Can't find wallpaper.") if record.nil?
21
+ record.increment_weight!
22
+ record
23
+ end
24
+ end
25
+
26
+ def save
27
+ check_file
28
+ super
29
+ end
30
+
31
+ def <=>(other)
32
+ other_weight = other.weight
33
+ if other_weight != weight
34
+ -(other_weight <=> weight)
35
+ else
36
+ [-1, 0, 1].sample
37
+ end
38
+ end
39
+
40
+ def increment_weight!
41
+ @weight += 1
42
+ save
43
+ end
44
+
45
+ private
46
+
47
+ def check_file
48
+ raise(MissingFileError, "Can't find the `#{ path }`") unless File.exist?(path)
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,29 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "moodwall/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "moodwall"
7
+ spec.version = Moodwall::VERSION
8
+ spec.authors = ["Valiantsin Mikhaliuk"]
9
+ spec.email = ["valiantsin.mikhaliuk@gmail.com"]
10
+
11
+ spec.summary = %q{Change wallpapers randomly depending on the moods.}
12
+ spec.homepage = "https://github.com/vmikhaliuk/moodwall"
13
+
14
+ # Specify which files should be added to the gem when it is released.
15
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
16
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
17
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ end
19
+ spec.executables = %w[moodwall]
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.17"
23
+ spec.add_development_dependency "coveralls"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "rspec", "~> 3.0"
26
+ spec.add_development_dependency "factory_bot"
27
+ spec.add_development_dependency "byebug"
28
+ spec.add_development_dependency "pry"
29
+ end
metadata ADDED
@@ -0,0 +1,163 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: moodwall
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Valiantsin Mikhaliuk
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-12-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.17'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.17'
27
+ - !ruby/object:Gem::Dependency
28
+ name: coveralls
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: factory_bot
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: byebug
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description:
112
+ email:
113
+ - valiantsin.mikhaliuk@gmail.com
114
+ executables:
115
+ - moodwall
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - ".gitignore"
120
+ - ".rspec"
121
+ - ".ruby-version"
122
+ - ".travis.yml"
123
+ - CODE_OF_CONDUCT.md
124
+ - Gemfile
125
+ - Gemfile.lock
126
+ - LICENSE
127
+ - README.md
128
+ - Rakefile
129
+ - bin/console
130
+ - bin/moodwall
131
+ - bin/setup
132
+ - lib/moodwall.rb
133
+ - lib/moodwall/executable.rb
134
+ - lib/moodwall/mood.rb
135
+ - lib/moodwall/record.rb
136
+ - lib/moodwall/repository.rb
137
+ - lib/moodwall/version.rb
138
+ - lib/moodwall/wallpaper.rb
139
+ - moodwall.gemspec
140
+ homepage: https://github.com/vmikhaliuk/moodwall
141
+ licenses: []
142
+ metadata: {}
143
+ post_install_message:
144
+ rdoc_options: []
145
+ require_paths:
146
+ - lib
147
+ required_ruby_version: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ required_rubygems_version: !ruby/object:Gem::Requirement
153
+ requirements:
154
+ - - ">="
155
+ - !ruby/object:Gem::Version
156
+ version: '0'
157
+ requirements: []
158
+ rubyforge_project:
159
+ rubygems_version: 2.7.6
160
+ signing_key:
161
+ specification_version: 4
162
+ summary: Change wallpapers randomly depending on the moods.
163
+ test_files: []