woli 0.0.1.pre1

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,7 @@
1
+ /.bundle
2
+ /.config
3
+ /.yardoc
4
+ /Gemfile.lock
5
+ /doc
6
+ /pkg
7
+ /vendor/ruby
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in woli.gemspec
4
+ gemspec
@@ -0,0 +1,5 @@
1
+ guard 'minitest' do
2
+ watch(%r|^spec/(.*)_spec\.rb|)
3
+ watch(%r|^lib/(.*)\.rb|) { |m| "spec/#{m[1]}_spec.rb" }
4
+ watch(%r|^spec/spec_helper\.rb|) { "spec" }
5
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Jiří Stránský
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,26 @@
1
+ # Woli (as in WOrth LIving)
2
+
3
+ Geek's diary keeper, currently in pre-alpha state :)
4
+
5
+ ## Why would a grown person keep a diary?
6
+
7
+ * The ability to recall why a particular time of our life was worth living is crucial for your
8
+ long term happiness. Can you recall what you did during this week four years ago? If you can't,
9
+ it doesn't mean the week was not worth living, but it does mean that you can't derive a feeling
10
+ of happiness and satisfaction from knowing *why* it was worth living. Keeping a diary helps you
11
+ recall. You won't lose memories that are worth keeping.
12
+
13
+ * A diary helps you reflect on how you spent your time. In a long run, keeping a diary increases
14
+ your ability to recognize what's really important for you, what makes you happy. You will be
15
+ able to shape your days to contain more of those happy moments and important stuff. You will
16
+ be able to point your life in a direction that will bring you satisfaction and happiness.
17
+
18
+ The project was ignited by Radovan Bahbouh's inspiring TEDx talk "The Best Investment"
19
+ ([youtube video](http://www.youtube.com/watch?v=LNvExTsM2Xg), in Czech).
20
+
21
+ ## Tips
22
+
23
+ * At the end of the day, try to recall what important things happened. Recall why this day was
24
+ worth living. Write it down.
25
+
26
+ * Do not write just what happened, write also how you felt about it.
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rake/testtask'
4
+
5
+ task :default => [:test]
6
+
7
+ Rake::TestTask.new do |t|
8
+ t.pattern = "spec/**/*_spec.rb"
9
+ end
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ require "rubygems" # ruby1.9 doesn't "require" it though
3
+
4
+ require 'woli/cli'
5
+
6
+ Woli::Cli.start
@@ -0,0 +1,36 @@
1
+ if ENV['DEBUG']
2
+ require 'pry'
3
+ end
4
+ require "woli/config"
5
+ require "woli/diary"
6
+ require "woli/diary_entry"
7
+ require "woli/version"
8
+ require "woli/repositories/files"
9
+
10
+ module Woli
11
+ def self.config
12
+ @config ||= Woli::Config.load_user_config
13
+ end
14
+
15
+ def self.diary
16
+ @diary ||= Woli::Diary.new(self.repository)
17
+ end
18
+
19
+ def self.editor
20
+ config['editor'] || ENV['EDITOR'] || 'vim'
21
+ end
22
+
23
+ def self.repository
24
+ @repository ||= instantiate_repository
25
+ end
26
+
27
+ class << self
28
+ private
29
+ def instantiate_repository
30
+ repository_class = config['repository_class'].split('::').reduce(Kernel) do |result_const, nested_const|
31
+ result_const = result_const.const_get(nested_const.to_sym)
32
+ end
33
+ repository_class.new(config['repository_config'])
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,13 @@
1
+ require 'woli'
2
+ require 'woli/date_parser'
3
+ require 'thor'
4
+
5
+ module Woli
6
+ class Cli < Thor
7
+ end
8
+ end
9
+
10
+ require 'woli/cli/edit'
11
+ require 'woli/cli/list'
12
+ require 'woli/cli/notify'
13
+ require 'woli/cli/status'
@@ -0,0 +1,41 @@
1
+ module Woli
2
+ class Cli
3
+ desc 'edit DAY', 'Edit a diary entry for a given day.'
4
+ long_desc <<-END
5
+ Edit a diary entry for a given day.
6
+
7
+ #{DateParser.parse_date_long_desc}
8
+ END
9
+ def edit(fuzzy_date = 'today')
10
+ date = DateParser.parse_date(fuzzy_date)
11
+ entry = Woli.repository.load_entry(date) || DiaryEntry.new(date, '', Woli.repository)
12
+
13
+ temp_file_name = generate_temp_file_name(entry)
14
+ save_text_to_temp_file(entry, temp_file_name)
15
+ edit_file_in_editor(temp_file_name)
16
+ load_text_from_temp_file(entry, temp_file_name)
17
+
18
+ entry.persist
19
+ end
20
+
21
+ private
22
+
23
+ def save_text_to_temp_file(entry, temp_file_name)
24
+ File.write(temp_file_name, entry.text)
25
+ end
26
+
27
+ def load_text_from_temp_file(entry, temp_file_name)
28
+ entry.text = File.read(temp_file_name)
29
+ File.delete(temp_file_name)
30
+ end
31
+
32
+ def generate_temp_file_name(entry)
33
+ "/tmp/woli_edit_entry_#{entry.date.strftime('%Y_%m_%d')}.#{Woli.config['edit_entry_extension']}"
34
+ end
35
+
36
+ def edit_file_in_editor(file_name)
37
+ tty = `tty`.strip
38
+ `#{Woli.editor} < #{tty} > #{tty} #{file_name}`
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,10 @@
1
+ module Woli
2
+ class Cli
3
+ desc 'list', 'List dates for which there are entries in the diary.'
4
+ def list
5
+ Woli.diary.all_entries_dates.each do |date|
6
+ puts date.strftime('%d-%m-%Y')
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ module Woli
2
+ class Cli
3
+ desc 'notify', 'Get notified when you forget to write entries.'
4
+ def notify
5
+ notify_config = Woli.config['notification']['missing_entries']
6
+
7
+ if Woli.diary.missing_entries_count >= notify_config['days']
8
+ `#{notify_config['command']}`
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,17 @@
1
+ module Woli
2
+ class Cli
3
+ desc 'status', 'Print basic information about the diary.'
4
+ def status
5
+ entries_dates = Woli.diary.all_entries_dates
6
+ date_format = '%d-%m-%Y'
7
+ coverage = entries_dates.count / Float(entries_dates.last - entries_dates.first + 1)
8
+
9
+ puts "Woli Diary Status"
10
+ puts "================="
11
+ puts "First entry: #{entries_dates.first.strftime(date_format)}"
12
+ puts "Last entry: #{entries_dates.last.strftime(date_format)}"
13
+ puts "Coverage: %2d %" % (coverage * 100).round
14
+ puts "Missing entries since the last one: #{Woli.diary.missing_entries_count}"
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ require 'yaml'
2
+
3
+ module Woli
4
+ class Config
5
+ CONFIG_FILE_NAME = "#{ENV['HOME']}/.woli/config.yml"
6
+ DEFAULT_CONFIG_FILE_NAME = File.join(File.dirname(__FILE__),
7
+ '../../templates/default_config.yml')
8
+
9
+ def self.load_user_config
10
+ create_default_config_file(CONFIG_FILE_NAME) unless File.exists?(CONFIG_FILE_NAME)
11
+ YAML.load_file(CONFIG_FILE_NAME)
12
+ end
13
+
14
+ def self.create_default_config_file(file_name)
15
+ FileUtils.mkdir_p(File.dirname(file_name))
16
+ FileUtils.cp(DEFAULT_CONFIG_FILE_NAME, file_name)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,44 @@
1
+ module Woli
2
+ module DateParser
3
+ def self.parse_date_long_desc
4
+ <<-END
5
+ Specifying DAY:
6
+
7
+ 1) Implicitly: If no date is given, 'today' is assumed.
8
+
9
+ 2) Via a keyword: woli edit DAYNAME
10
+ (Where DAYNAME can be:
11
+ 'today' or 't';
12
+ 'yesterday' or 'y')
13
+
14
+ 3) Via a date: woli edit DD[-MM[-YYYY]]
15
+ (Use hyphens, dots or slashes to separate day/month/year.
16
+ If year or month is not given, current year / current month is assumed.)
17
+
18
+ 4) Via days ago: woli edit ^DAYS
19
+ (Where DAYS is a number of days ago. ^1 is yesterday, ^7 is a week ago etc.)
20
+ END
21
+ end
22
+
23
+ def self.parse_date(fuzzy_date)
24
+ case fuzzy_date
25
+ when 'today', 't', nil
26
+ Date.today
27
+ when 'yesterday', 'y'
28
+ Date.today - 1
29
+ when /\A\^(?<days_ago>\d+)/
30
+ Date.today - Integer($~[:days_ago])
31
+ when /\A(?<day>\d+)([-\.\/](?<month>\d+)([-\.\/](?<year>\d+))?)?\Z/
32
+ today = Date.today
33
+ year = $~[:year] ? Integer($~[:year]) : today.year
34
+ month = $~[:month] ? Integer($~[:month]) : today.month
35
+ day = $~[:day] ? Integer($~[:day]) : today.day
36
+ Date.new(year, month, day)
37
+ else
38
+ self.class.task_help(shell, 'edit')
39
+ puts
40
+ raise MalformattedArgumentError, "'#{fuzzy_date}' is not a valid way to specify a date."
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,30 @@
1
+ module Woli
2
+ class Diary
3
+ attr_reader :repository
4
+
5
+ def initialize(repository)
6
+ @repository = repository
7
+ end
8
+
9
+ def all_entries_dates
10
+ @repository.all_entries_dates
11
+ end
12
+
13
+ def entry(date)
14
+ @repository.load_entry(date)
15
+ end
16
+
17
+ def load_or_create_entry(date)
18
+ entry = @repository.load_entry(date)
19
+ return entry if entry
20
+
21
+ DiaryEntry.new(date, '', @repository)
22
+ end
23
+
24
+ def missing_entries_count
25
+ last_entry_date = @repository.all_entries_dates.last
26
+ return 0 unless last_entry_date
27
+ Date.today - last_entry_date
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,21 @@
1
+ module Woli
2
+ class DiaryEntry
3
+ attr_reader :repository, :date
4
+ attr_accessor :text
5
+
6
+ def initialize(date, text, repository)
7
+ @date = date
8
+ @text = text
9
+ @repository = repository
10
+ end
11
+
12
+ def persist
13
+ if text.strip.length > 0
14
+ repository.save_entry(self)
15
+ else
16
+ puts "Empty entry -- removing."
17
+ repository.delete_entry(self)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,61 @@
1
+ module Woli
2
+ module Repositories
3
+ class Files
4
+ attr_reader :config
5
+
6
+ def initialize(config)
7
+ @config = config
8
+ end
9
+
10
+ def all_entries_dates
11
+ all_entries_files.map { |filename|
12
+ match_data = filename.match /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2}).#{Regexp.escape(config['entry_extension'])}\Z/
13
+ Date.new(match_data[:year].to_i, match_data[:month].to_i, match_data[:day].to_i)
14
+ }.sort
15
+ end
16
+
17
+ def load_entry(date)
18
+ file_name = path_for_entry_date(date)
19
+ return nil unless File.exists? file_name
20
+
21
+ text = File.read(path_for_entry_date(date))
22
+ DiaryEntry.new(date, text, self)
23
+ end
24
+
25
+ def save_entry(entry)
26
+ File.write(path_for_entry_date(entry.date), entry.text)
27
+ end
28
+
29
+ def delete_entry(entry)
30
+ file_name = path_for_entry_date(entry.date)
31
+ return unless File.exists? file_name
32
+
33
+ File.delete(file_name)
34
+ end
35
+
36
+ private
37
+
38
+ def diary_path
39
+ File.expand_path(config['path'])
40
+ end
41
+
42
+ def path_for_entry_date(date)
43
+ File.join(
44
+ diary_path,
45
+ date.strftime('%Y'),
46
+ date.strftime('%m'),
47
+ date.strftime("%Y-%m-%d.#{config['entry_extension']}")
48
+ )
49
+ end
50
+
51
+ def all_entries_files
52
+ entry_like_filenames = Dir.glob(File.join(diary_path, '**', '*.' + config['entry_extension']))
53
+
54
+ # Globbing is not enough -> filter the results further with regexps.
55
+ entry_like_filenames.select do |filename|
56
+ filename =~ %r{#{Regexp.escape(diary_path)}/[0-9]{4}/[0-9]{2}/[0-9]{4}-[0-9]{2}-[0-9]{2}.#{Regexp.escape(config['entry_extension'])}\Z}
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,3 @@
1
+ module Woli
2
+ VERSION = "0.0.1.pre1"
3
+ end
@@ -0,0 +1,6 @@
1
+ require 'minitest/spec'
2
+ require 'minitest/autorun'
3
+ begin; require 'turn'; rescue LoadError; end
4
+ require 'mocha'
5
+ require 'timecop'
6
+
@@ -0,0 +1,68 @@
1
+ require_relative '../spec_helper'
2
+ require 'woli/date_parser'
3
+
4
+ describe Woli::DateParser do
5
+ before do
6
+ @parser = Woli::DateParser
7
+ @today = Date.new(2012, 7, 15)
8
+ Timecop.freeze(@today)
9
+ end
10
+
11
+ after do
12
+ Timecop.return
13
+ end
14
+
15
+ it "parses nil as today" do
16
+ @parser.parse_date(nil).must_equal @today
17
+ end
18
+
19
+ it "parses 't' and 'today' as today" do
20
+ @parser.parse_date('t').must_equal @today
21
+ @parser.parse_date('today').must_equal @today
22
+ end
23
+
24
+ it "parses 'y' and 'yesterday' as yesterday" do
25
+ @parser.parse_date('y').must_equal (@today - 1)
26
+ @parser.parse_date('yesterday').must_equal (@today - 1)
27
+ end
28
+
29
+ it "parses '^2' as 2 days ago" do
30
+ @parser.parse_date('^2').must_equal (@today - 2)
31
+ end
32
+
33
+ it "parses '^50' as 50 days ago" do
34
+ @parser.parse_date('^50').must_equal (@today - 50)
35
+ end
36
+
37
+ it "parses '20' as 20th day of current month" do
38
+ parsed = @parser.parse_date('20')
39
+ parsed.year.must_equal @today.year
40
+ parsed.month.must_equal @today.month
41
+ parsed.day.must_equal 20
42
+ end
43
+
44
+ it "parses '20.2' as 20th February of current year" do
45
+ parsed = @parser.parse_date('20.2')
46
+ parsed.year.must_equal @today.year
47
+ parsed.month.must_equal 2
48
+ parsed.day.must_equal 20
49
+ end
50
+
51
+ it "parses '20/2/2011' as 20th February 2011" do
52
+ parsed = @parser.parse_date('20/2/2011')
53
+ parsed.year.must_equal 2011
54
+ parsed.month.must_equal 2
55
+ parsed.day.must_equal 20
56
+ end
57
+
58
+ it "parses '20.4', '20-4', '20/4', '20-4-2012' as the same dates (current year is 2012)" do
59
+ date1 = @parser.parse_date('20.4')
60
+ date2 = @parser.parse_date('20-4')
61
+ date3 = @parser.parse_date('20/4')
62
+ date4 = @parser.parse_date('20-4-2012')
63
+
64
+ date1.must_equal date2
65
+ date1.must_equal date3
66
+ date1.must_equal date4
67
+ end
68
+ end
@@ -0,0 +1,47 @@
1
+ require_relative '../spec_helper'
2
+ require 'woli/diary_entry'
3
+
4
+ describe Woli::DiaryEntry do
5
+ before do
6
+ @repository = mock 'repository'
7
+ end
8
+
9
+ describe "empty entry" do
10
+ before do
11
+ @entry = Woli::DiaryEntry.new(Date.new(2012, 7, 14), '', @repository)
12
+ end
13
+
14
+ it "removes itself from the repository when persisting its state" do
15
+ @repository.expects(:delete_entry).with(@entry)
16
+ @entry.persist
17
+ end
18
+ end
19
+
20
+ describe "pseudoempty entry (whitespace only)" do
21
+ before do
22
+ @entry = Woli::DiaryEntry.new(Date.new(2012, 7, 14), "\n\n \n", @repository)
23
+ end
24
+
25
+ it "removes itself from the repository when persisting its state" do
26
+ @repository.expects(:delete_entry).with(@entry)
27
+ @entry.persist
28
+ end
29
+ end
30
+
31
+ describe "filled in entry" do
32
+ before do
33
+ text = <<-END
34
+ * Today I had the best ice cream.
35
+
36
+ * I slipped on a banana and didn't break anything. Yay!
37
+ END
38
+ @entry = Woli::DiaryEntry.new(Date.new(2012, 7, 14), text, @repository)
39
+ end
40
+
41
+ it "saves itself into the repository when persisting its state" do
42
+ @repository.expects(:save_entry).with(@entry)
43
+ @entry.persist
44
+ end
45
+ end
46
+ end
47
+
@@ -0,0 +1,69 @@
1
+ require_relative '../spec_helper'
2
+ require 'woli/diary'
3
+
4
+ describe Woli::Diary do
5
+ before do
6
+ @existing_entry = mock 'existing diary entry'
7
+ @existing_entry_date = Date.new(2012, 7, 1)
8
+ @nonexistent_entry_date = Date.new(2012, 7, 16)
9
+
10
+ @repository = mock 'repository'
11
+ @repository.stubs(:load_entry).with(@existing_entry_date).returns(@existing_entry)
12
+ @repository.stubs(:load_entry).with(@nonexistent_entry_date).returns(nil)
13
+ @repository.stubs(:all_entries_dates).returns([@existing_entry_date])
14
+
15
+ @diary = Woli::Diary.new(@repository)
16
+ end
17
+
18
+ describe "#entry" do
19
+ it "loads an existing entry" do
20
+ @diary.entry(@existing_entry_date).must_equal @existing_entry
21
+ end
22
+
23
+ it "returns nil for a non-existent entry" do
24
+ @diary.entry(@nonexistent_entry_date).must_equal nil
25
+ end
26
+ end
27
+
28
+ describe "#load_or_create_entry" do
29
+ before do
30
+ @new_entry = :fake_new_entry
31
+ class Woli::DiaryEntry ; end
32
+ Woli::DiaryEntry.stubs(:new).with(@nonexistent_entry_date, '', @repository).returns(@new_entry)
33
+ end
34
+
35
+ it "loads an existing entry" do
36
+ @diary.load_or_create_entry(@existing_entry_date).must_equal @existing_entry
37
+ end
38
+
39
+ it "creates a new entry for a non-existent entry" do
40
+ @diary.load_or_create_entry(@nonexistent_entry_date).must_equal @new_entry
41
+ end
42
+ end
43
+
44
+ describe "#all_entries_dates" do
45
+ it "delegates the call to the repository" do
46
+ @diary.all_entries_dates.must_equal @repository.all_entries_dates
47
+ end
48
+ end
49
+
50
+ describe "#missing_entries_count" do
51
+ it "returns 0 when the last entry is for today" do
52
+ Timecop.freeze(@repository.all_entries_dates.last) do
53
+ @diary.missing_entries_count.must_equal 0
54
+ end
55
+ end
56
+
57
+ it "returns 1 when the last entry is for yesterday" do
58
+ Timecop.freeze(@repository.all_entries_dates.last + 1) do
59
+ @diary.missing_entries_count.must_equal 1
60
+ end
61
+ end
62
+
63
+ it "returns 7 when the last entry is for a day week ago" do
64
+ Timecop.freeze(@repository.all_entries_dates.last + 7) do
65
+ @diary.missing_entries_count.must_equal 7
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,98 @@
1
+ require_relative '../../spec_helper'
2
+ require 'woli/repositories/files'
3
+
4
+ describe Woli::Repositories::Files do
5
+ before do
6
+ @config = {
7
+ 'path' => '/tmp/fake_diary_path',
8
+ 'entry_extension' => 'md'
9
+ }
10
+
11
+ @repository = Woli::Repositories::Files.new(@config)
12
+
13
+ @entry = stub(
14
+ :date => Date.new(2012, 7, 6),
15
+ :text => 'entry text',
16
+ :repository => @repository
17
+ )
18
+ @entry_path = "#{@config['path']}/2012/07/2012-07-06.#{@config['entry_extension']}"
19
+ end
20
+
21
+ describe "#all_entries_dates" do
22
+ before do
23
+ Dir.stubs(:glob)
24
+ .with("#{@config['path']}/**/*.#{@config['entry_extension']}")
25
+ .returns([
26
+ "#{@config['path']}/2012/07/2012-07-06.#{@config['entry_extension']}",
27
+ "#{@config['path']}/2012/07/2012-07-04.#{@config['entry_extension']}",
28
+ "#{@config['path']}/2012/07/2012-07-05.#{@config['entry_extension']}",
29
+ "#{@config['path']}/2012/07/maliciously_named_file.#{@config['entry_extension']}",
30
+ "#{@config['path']}/2012/07/2012-07-03-this-aint-right.#{@config['entry_extension']}"
31
+ ])
32
+ end
33
+
34
+ it "returns correct and sorted dates for correctly named entry files, ignores others" do
35
+ @repository.all_entries_dates.must_equal [
36
+ Date.new(2012, 7, 4),
37
+ Date.new(2012, 7, 5),
38
+ Date.new(2012, 7, 6)
39
+ ]
40
+ end
41
+ end
42
+
43
+ describe "#load_entry" do
44
+ it "loads an entry from a file" do
45
+ new_entry = :fake_new_entry
46
+
47
+ File.expects(:exists?)
48
+ .with(@entry_path)
49
+ .returns(true)
50
+
51
+ File.expects(:read)
52
+ .with(@entry_path)
53
+ .returns('entry text')
54
+
55
+ class Woli::DiaryEntry; end
56
+ Woli::DiaryEntry.expects(:new).with(@entry.date, 'entry text', @repository).returns(new_entry)
57
+
58
+ @repository.load_entry(@entry.date).must_equal(new_entry)
59
+ end
60
+
61
+ it "returns nil if file for that date doesn't exist" do
62
+ File.expects(:exists?)
63
+ .with(@entry_path)
64
+ .returns(false)
65
+
66
+ @repository.load_entry(@entry.date).must_be_nil
67
+ end
68
+ end
69
+
70
+ describe "#save_entry" do
71
+ it "writes the text into a file" do
72
+ File.expects(:write).with(@entry_path, @entry.text).returns(@entry.text.length)
73
+
74
+ @repository.save_entry(@entry)
75
+ end
76
+ end
77
+
78
+ describe "#delete_entry" do
79
+ it "does nothing if the file does not exist" do
80
+ File.expects(:exists?)
81
+ .with(@entry_path)
82
+ .returns(false)
83
+
84
+ @repository.delete_entry(@entry).must_be_nil
85
+ end
86
+
87
+ it "deletes the file with entry contents" do
88
+ File.expects(:exists?)
89
+ .with(@entry_path)
90
+ .returns(true)
91
+ File.expects(:delete)
92
+ .with(@entry_path)
93
+ .returns(1)
94
+
95
+ @repository.delete_entry(@entry)
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,12 @@
1
+ repository_class: 'Woli::Repositories::Files'
2
+ repository_config:
3
+ path: ~/.woli/diary
4
+ entry_extension: md
5
+
6
+ editor:
7
+ edit_entry_extension: md
8
+
9
+ notification:
10
+ missing_entries:
11
+ days: 1
12
+ command: "notify-send 'Woli diary is hungry for entries.'"
@@ -0,0 +1,44 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/woli/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Jiří Stránský"]
6
+ gem.email = ["jistr@jistr.com"]
7
+ gem.description = <<-END
8
+ Woli (as in WOrth LIving) helps you record your memories. Write
9
+ a short note about every day you live and make sure your days are worth
10
+ living. Later, review your notes to bring back the memories.
11
+ Change your life if you are not happy with what's in your diary.
12
+ END
13
+ gem.summary = "Woli, the diary keeper."
14
+ gem.homepage = "http://github.com/jistr/woli"
15
+
16
+ gem.files = `git ls-files`.split($\)
17
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
18
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
+ gem.name = "woli"
20
+ gem.require_paths = ["lib"]
21
+ gem.version = Woli::VERSION
22
+
23
+ gem.add_dependency 'thor', '~> 0.15.2'
24
+
25
+ # == DEVELOPMENT DEPENDENCIES ==
26
+ # Smart irb
27
+ gem.add_development_dependency 'pry'
28
+
29
+ # Specs
30
+ gem.add_development_dependency 'minitest'
31
+ gem.add_development_dependency 'mocha'
32
+ gem.add_development_dependency 'timecop'
33
+
34
+ # Running tests during development
35
+ gem.add_development_dependency 'guard'
36
+ gem.add_development_dependency 'guard-minitest'
37
+ # Linux Guard watching
38
+ gem.add_development_dependency 'rb-inotify'
39
+ # Linux Guard notifications
40
+ gem.add_development_dependency 'libnotify'
41
+
42
+ # Pretty printed test output
43
+ gem.add_development_dependency 'turn'
44
+ end
metadata ADDED
@@ -0,0 +1,193 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: woli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1.pre1
5
+ prerelease: 6
6
+ platform: ruby
7
+ authors:
8
+ - Jiří Stránský
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-16 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: thor
16
+ requirement: &16096140 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.15.2
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *16096140
25
+ - !ruby/object:Gem::Dependency
26
+ name: pry
27
+ requirement: &16095460 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *16095460
36
+ - !ruby/object:Gem::Dependency
37
+ name: minitest
38
+ requirement: &16094260 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *16094260
47
+ - !ruby/object:Gem::Dependency
48
+ name: mocha
49
+ requirement: &16093600 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *16093600
58
+ - !ruby/object:Gem::Dependency
59
+ name: timecop
60
+ requirement: &16092680 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *16092680
69
+ - !ruby/object:Gem::Dependency
70
+ name: guard
71
+ requirement: &16091900 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *16091900
80
+ - !ruby/object:Gem::Dependency
81
+ name: guard-minitest
82
+ requirement: &16091300 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: *16091300
91
+ - !ruby/object:Gem::Dependency
92
+ name: rb-inotify
93
+ requirement: &16106680 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ type: :development
100
+ prerelease: false
101
+ version_requirements: *16106680
102
+ - !ruby/object:Gem::Dependency
103
+ name: libnotify
104
+ requirement: &16106120 !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: *16106120
113
+ - !ruby/object:Gem::Dependency
114
+ name: turn
115
+ requirement: &16105220 !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ! '>='
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ type: :development
122
+ prerelease: false
123
+ version_requirements: *16105220
124
+ description: ! " Woli (as in WOrth LIving) helps you record your memories. Write\n
125
+ \ a short note about every day you live and make sure your days are worth\n living.
126
+ Later, review your notes to bring back the memories.\n Change your life if you
127
+ are not happy with what's in your diary.\n"
128
+ email:
129
+ - jistr@jistr.com
130
+ executables:
131
+ - woli
132
+ extensions: []
133
+ extra_rdoc_files: []
134
+ files:
135
+ - .gitignore
136
+ - Gemfile
137
+ - Guardfile
138
+ - LICENSE
139
+ - README.md
140
+ - Rakefile
141
+ - bin/woli
142
+ - lib/woli.rb
143
+ - lib/woli/cli.rb
144
+ - lib/woli/cli/edit.rb
145
+ - lib/woli/cli/list.rb
146
+ - lib/woli/cli/notify.rb
147
+ - lib/woli/cli/status.rb
148
+ - lib/woli/config.rb
149
+ - lib/woli/date_parser.rb
150
+ - lib/woli/diary.rb
151
+ - lib/woli/diary_entry.rb
152
+ - lib/woli/repositories/files.rb
153
+ - lib/woli/version.rb
154
+ - spec/spec_helper.rb
155
+ - spec/woli/date_parser_spec.rb
156
+ - spec/woli/diary_entry_spec.rb
157
+ - spec/woli/diary_spec.rb
158
+ - spec/woli/repositories/files_spec.rb
159
+ - templates/default_config.yml
160
+ - woli.gemspec
161
+ homepage: http://github.com/jistr/woli
162
+ licenses: []
163
+ post_install_message:
164
+ rdoc_options: []
165
+ require_paths:
166
+ - lib
167
+ required_ruby_version: !ruby/object:Gem::Requirement
168
+ none: false
169
+ requirements:
170
+ - - ! '>='
171
+ - !ruby/object:Gem::Version
172
+ version: '0'
173
+ segments:
174
+ - 0
175
+ hash: -2448595754877266534
176
+ required_rubygems_version: !ruby/object:Gem::Requirement
177
+ none: false
178
+ requirements:
179
+ - - ! '>'
180
+ - !ruby/object:Gem::Version
181
+ version: 1.3.1
182
+ requirements: []
183
+ rubyforge_project:
184
+ rubygems_version: 1.8.11
185
+ signing_key:
186
+ specification_version: 3
187
+ summary: Woli, the diary keeper.
188
+ test_files:
189
+ - spec/spec_helper.rb
190
+ - spec/woli/date_parser_spec.rb
191
+ - spec/woli/diary_entry_spec.rb
192
+ - spec/woli/diary_spec.rb
193
+ - spec/woli/repositories/files_spec.rb