klipbook 0.3.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/Gemfile +6 -5
  2. data/Gemfile.lock +62 -25
  3. data/Guardfile +1 -2
  4. data/README.md +66 -18
  5. data/Rakefile +5 -1
  6. data/bin/klipbook +85 -1
  7. data/example.png +0 -0
  8. data/features/collate.feature +51 -0
  9. data/features/fixtures/clippings-for-three-books.txt +105 -0
  10. data/features/list.feature +31 -0
  11. data/features/step_definitions/collate_steps.rb +61 -0
  12. data/features/step_definitions/list_steps.rb +15 -0
  13. data/features/support/env.rb +5 -1
  14. data/klipbook.gemspec +49 -32
  15. data/lib/klipbook/book.rb +18 -0
  16. data/lib/klipbook/clipping.rb +4 -10
  17. data/lib/klipbook/collator.rb +17 -0
  18. data/lib/klipbook/config.rb +22 -0
  19. data/lib/klipbook/fetcher.rb +29 -0
  20. data/lib/klipbook/invalid_source_error.rb +12 -0
  21. data/lib/klipbook/output/book_helpers.rb +12 -0
  22. data/lib/klipbook/{book_summary.erb → output/html_book_summary.erb} +65 -11
  23. data/lib/klipbook/output/html_summary_writer.rb +42 -0
  24. data/lib/klipbook/printer.rb +18 -0
  25. data/lib/klipbook/sources/amazon_site/book_scraper.rb +67 -0
  26. data/lib/klipbook/sources/amazon_site/scraper.rb +78 -0
  27. data/lib/klipbook/sources/kindle_device/entry.rb +11 -0
  28. data/lib/klipbook/sources/kindle_device/entry_parser.rb +85 -0
  29. data/lib/klipbook/sources/kindle_device/file.rb +57 -0
  30. data/lib/klipbook/sources/kindle_device/file_parser.rb +33 -0
  31. data/lib/klipbook/version.rb +1 -1
  32. data/lib/klipbook.rb +18 -5
  33. data/spec/lib/klipbook/book_spec.rb +33 -0
  34. data/spec/lib/klipbook/collator_spec.rb +40 -0
  35. data/spec/lib/klipbook/fetcher_spec.rb +81 -0
  36. data/spec/lib/klipbook/output/html_summary_writer_spec.rb +90 -0
  37. data/spec/lib/klipbook/printer_spec.rb +45 -0
  38. data/spec/lib/klipbook/sources/kindle_device/entry_parser_spec.rb +275 -0
  39. data/spec/lib/klipbook/sources/kindle_device/file_parser_spec.rb +68 -0
  40. data/spec/lib/klipbook/sources/kindle_device/file_spec.rb +163 -0
  41. metadata +158 -58
  42. data/features/list_books.feature +0 -23
  43. data/features/print_book_summary.feature +0 -10
  44. data/features/step_definitions/klipbook_steps.rb +0 -87
  45. data/lib/klipbook/book_summary.rb +0 -35
  46. data/lib/klipbook/cli.rb +0 -49
  47. data/lib/klipbook/clippings_file.rb +0 -50
  48. data/lib/klipbook/clippings_parser.rb +0 -98
  49. data/lib/klipbook/runner.rb +0 -29
  50. data/spec/lib/klipbook/book_summary_spec.rb +0 -30
  51. data/spec/lib/klipbook/clipping_spec.rb +0 -17
  52. data/spec/lib/klipbook/clippings_file_spec.rb +0 -60
  53. data/spec/lib/klipbook/clippings_parser_spec.rb +0 -367
  54. data/spec/lib/klipbook/runner_spec.rb +0 -87
data/Gemfile CHANGED
@@ -1,6 +1,8 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
- gem 'thor'
3
+ gem 'gli'
4
+ gem 'mechanize'
5
+ gem 'rainbow'
4
6
 
5
7
  group :development do
6
8
  gem 'rspec'
@@ -8,12 +10,11 @@ group :development do
8
10
  gem 'bundler'
9
11
  gem 'jeweler', '~> 1.6.4'
10
12
  gem 'rcov', '>= 0'
13
+ gem 'pry'
11
14
  gem 'cucumber'
15
+ gem 'aruba'
12
16
  gem 'guard'
13
17
  gem 'guard-rspec'
14
18
  gem 'guard-cucumber'
15
- gem 'rb-inotify', :require => false
16
- gem 'rb-fsevent', :require => false
17
- gem 'rb-fchange', :require => false
18
- gem 'growl_notify'
19
+ gem 'terminal-notifier-guard' if RUBY_PLATFORM.downcase.include?('darwin12')
19
20
  end
data/Gemfile.lock CHANGED
@@ -1,37 +1,68 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
+ aruba (0.4.11)
5
+ childprocess (>= 0.2.3)
6
+ cucumber (>= 1.1.1)
7
+ ffi (>= 1.0.11)
8
+ rspec (>= 2.7.0)
4
9
  builder (3.0.0)
5
- cucumber (1.1.3)
10
+ childprocess (0.3.5)
11
+ ffi (~> 1.0, >= 1.0.6)
12
+ coderay (1.0.7)
13
+ cucumber (1.2.1)
6
14
  builder (>= 2.1.2)
7
- diff-lcs (>= 1.1.2)
8
- gherkin (~> 2.6.7)
15
+ diff-lcs (>= 1.1.3)
16
+ gherkin (~> 2.11.0)
9
17
  json (>= 1.4.6)
10
- term-ansicolor (>= 1.0.6)
11
18
  diff-lcs (1.1.3)
12
- ffi (1.0.11)
13
- gherkin (2.6.7)
19
+ domain_name (0.5.3)
20
+ unf (~> 0.0.3)
21
+ ffi (1.1.5)
22
+ gherkin (2.11.2)
14
23
  json (>= 1.4.6)
15
24
  git (1.2.5)
16
- growl_notify (0.0.3)
17
- rb-appscript
18
- guard (0.8.8)
19
- thor (~> 0.14.6)
20
- guard-cucumber (0.7.4)
21
- cucumber (>= 0.10)
22
- guard (>= 0.8.3)
23
- guard-rspec (0.5.5)
24
- guard (>= 0.8.4)
25
+ gli (2.0.0)
26
+ guard (1.3.2)
27
+ listen (>= 0.4.2)
28
+ thor (>= 0.14.6)
29
+ guard-cucumber (1.2.0)
30
+ cucumber (>= 1.2.0)
31
+ guard (>= 1.1.0)
32
+ guard-rspec (1.2.1)
33
+ guard (>= 1.1)
25
34
  jeweler (1.6.4)
26
35
  bundler (~> 1.0)
27
36
  git (>= 1.2.5)
28
37
  rake
29
- json (1.6.1)
38
+ json (1.7.5)
39
+ listen (0.4.7)
40
+ rb-fchange (~> 0.0.5)
41
+ rb-fsevent (~> 0.9.1)
42
+ rb-inotify (~> 0.8.8)
43
+ mechanize (2.5.1)
44
+ domain_name (~> 0.5, >= 0.5.1)
45
+ mime-types (~> 1.17, >= 1.17.2)
46
+ net-http-digest_auth (~> 1.1, >= 1.1.1)
47
+ net-http-persistent (~> 2.5, >= 2.5.2)
48
+ nokogiri (~> 1.4)
49
+ ntlm-http (~> 0.1, >= 0.1.1)
50
+ webrobots (~> 0.0, >= 0.0.9)
51
+ method_source (0.8)
52
+ mime-types (1.19)
53
+ net-http-digest_auth (1.2.1)
54
+ net-http-persistent (2.7)
55
+ nokogiri (1.5.5)
56
+ ntlm-http (0.1.1)
57
+ pry (0.9.10)
58
+ coderay (~> 1.0.5)
59
+ method_source (~> 0.8)
60
+ slop (~> 3.3.1)
61
+ rainbow (1.1.4)
30
62
  rake (0.9.2.2)
31
- rb-appscript (0.6.1)
32
63
  rb-fchange (0.0.5)
33
64
  ffi
34
- rb-fsevent (0.4.3.1)
65
+ rb-fsevent (0.9.1)
35
66
  rb-inotify (0.8.8)
36
67
  ffi (>= 0.5.0)
37
68
  rcov (0.9.11)
@@ -44,24 +75,30 @@ GEM
44
75
  rspec-expectations (2.7.0)
45
76
  diff-lcs (~> 1.1.2)
46
77
  rspec-mocks (2.7.0)
47
- term-ansicolor (1.0.7)
48
- thor (0.14.6)
78
+ slop (3.3.3)
79
+ terminal-notifier-guard (1.5.3)
80
+ thor (0.16.0)
81
+ unf (0.0.5)
82
+ unf_ext
83
+ unf_ext (0.0.5)
84
+ webrobots (0.0.13)
49
85
 
50
86
  PLATFORMS
51
87
  ruby
52
88
 
53
89
  DEPENDENCIES
90
+ aruba
54
91
  bundler
55
92
  cucumber
56
- growl_notify
93
+ gli
57
94
  guard
58
95
  guard-cucumber
59
96
  guard-rspec
60
97
  jeweler (~> 1.6.4)
61
- rb-fchange
62
- rb-fsevent
63
- rb-inotify
98
+ mechanize
99
+ pry
100
+ rainbow
64
101
  rcov
65
102
  rr
66
103
  rspec
67
- thor
104
+ terminal-notifier-guard
data/Guardfile CHANGED
@@ -6,11 +6,10 @@ group 'backend' do
6
6
  watch(%r{^spec/.+_spec\.rb$})
7
7
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
8
8
 
9
- # String watch patterns are matched with simple '=='
10
9
  watch('spec/spec_helper.rb') { "spec" }
11
10
  end
12
11
 
13
- guard 'cucumber' do
12
+ guard 'cucumber', :cli => '--tags ~@slow' do
14
13
  watch(%r{^features/.+\.feature$})
15
14
  watch(%r{^features/support/.+$}) { 'features' }
16
15
  watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
data/README.md CHANGED
@@ -1,30 +1,82 @@
1
1
  # Klipbook
2
2
 
3
- Klipbook creates a nice html summary of the clippings you've created on your Kindle.
3
+ Klipbook collates highlights and notes that you've created on your Kindle into a nice html file.
4
+
5
+ ## An example of a clippings file generated by Klipbook
6
+
7
+ <img src="https://github.com/grassdog/klipbook/raw/master/example.png" alt="Example of a clippings file" />
8
+
9
+ ## What sources does it support?
10
+
11
+ Klipbook can take your highlights from a clippings file off a physical Kindle device
12
+ or from the [Kindle highlights site](https://kindle.amazon.com/your_highlights) itself.
13
+
14
+ ## When should I use the file and when should I use the site?
15
+
16
+ If your books are purchased from Amazon directly then use the site. The site is the
17
+ canonical source and will contain all of your notes and highlights from across all of
18
+ your Kindle devices and applications. Currently the Amazon highlights site only shows
19
+ clippings for books you've purchased on Amazon.
20
+
21
+ If your books are personal documents and you've read them on your kindle device
22
+ itself then you should use the file from that device as a source i.e. you Kindle
23
+ device only keeps clippings that you made directly on it.
4
24
 
5
25
  ## How does it work?
6
26
 
27
+ Klipbook supports two main commands: `collate` and `list`.
28
+
29
+ ### Collate
30
+
31
+ `collate` pulls together the clippings from your latest annotated book and combines them
32
+ into a simple html file.
33
+
34
+ #### From a file
35
+
7
36
  Copy your clippings file (called "My Clippings.txt" on a 3rd generation Kindle) from your Kindle device to your local drive via USB.
8
37
 
9
- **List the books in your clippings file:**
38
+ Then write out a list of your clippings via:
10
39
 
11
- $ klipbook list "My Clippings.txt"
40
+ $ klipbook collate "file:My Clippings.txt"
12
41
 
13
- The list of books in your clippings file:
14
- [1] The Big Sleep by Raymond Chandler
15
- [2] How to jump out of a plane without a parachute and survive by Rip Rockjaw
42
+ This command will write the collected clippings for the latest annotated book to a file in the current
43
+ directory. You can override the output directory with the `--output-dir` flag.
44
+
45
+ Klipbook will not overwrite an exiting file by default. You can change this with
46
+ the `--force` flag.
47
+
48
+ You can also specify a maximum count of books you'd like collated with the `--num-books` flag.
49
+
50
+ #### From the site
51
+
52
+ Specify your amazon username and password to klipbook and it will scrape the site and
53
+ output a clippings file.
54
+
55
+ $ klipbook collate site:my-username@blah.com:my-password
56
+
57
+ The same flags above apply.
16
58
 
17
- **Print a html summary for the book of your choice:**
59
+ If you don't feel like having your credentials in your shell history you can set your
60
+ default source in the klipbook rc file: `~/.klipbookrc`.
18
61
 
19
- Choose the number of the book you are interested in and print a html summary with the `summarise` command:
62
+ This is simply a YAML file and you can specify default values for the source and the
63
+ output directory, e.g.
20
64
 
21
- $ klipbook summarise "My Clippings.txt" 1 big-sleep-clippings.html
65
+ $ cat ~/.klipbookrc
66
+ source: site:my-username@blah.com:my-password
67
+ output: my/default/output/directory
22
68
 
23
- Keep the nicely formatted html version of your clippings for your own reference.
69
+ Command line options override the defaults stored in the rc file.
24
70
 
25
- ## Example of a summary file generated by Klipbook
71
+ ### List
26
72
 
27
- <img src="https://github.com/grassdog/klipbook/raw/master/example.png" alt="Example of a summary file" />
73
+ The list command lists the books avaiable in the specified source.
74
+
75
+ $ klipbook list file:"My Clippings.txt"
76
+
77
+ Book list:
78
+ [1] The Big Sleep by Raymond Chandler
79
+ [2] How to jump out of a plane without a parachute and survive by Rip Rockjaw
28
80
 
29
81
  ## Installation
30
82
 
@@ -32,17 +84,13 @@ Klipbook is a Ruby gem. To install simply run:
32
84
 
33
85
  gem install klipbook
34
86
 
35
- ## Why not just see your clippings on the Amazon site?
36
-
37
- Currently [the Amazon highlights site](https://kindle.amazon.com/your_highlights) only shows clippings for books you've purchased on Amazon.
38
-
39
87
  ## Supported Devices
40
88
 
41
89
  Klipbook has been tested on clippings files from 3rd generation Kindles and the Kindle Touch.
42
90
 
43
91
  ## Tested platforms
44
92
 
45
- Klipbook has been tested on Mac OSX Lion and Ubuntu using MRI 1.9.3.
93
+ Klipbook has been tested on Mac OSX Mountain Lion using MRI 1.9.3.
46
94
 
47
95
  ## Contributing to Klipbook
48
96
 
@@ -50,5 +98,5 @@ Fork the project on [Github](https://github.com/grassdog/klipbook), add tests fo
50
98
 
51
99
  ## Copyright
52
100
 
53
- Copyright (c) 2011 Ray Grasso. See LICENSE.txt for further details.
101
+ Copyright (c) 2012 Ray Grasso. See LICENSE.txt for further details.
54
102
 
data/Rakefile CHANGED
@@ -42,7 +42,11 @@ RSpec::Core::RakeTask.new(:spec)
42
42
 
43
43
  require 'cucumber/rake/task'
44
44
  Cucumber::Rake::Task.new(:features) do |t|
45
- t.cucumber_opts = '--format progress'
45
+ t.cucumber_opts = '--format pretty --tags ~@slow'
46
+ end
47
+
48
+ Cucumber::Rake::Task.new(:allfeatures) do |t|
49
+ t.cucumber_opts = '--format pretty'
46
50
  end
47
51
 
48
52
  desc 'Default: run specs'
data/bin/klipbook CHANGED
@@ -1,7 +1,91 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  $LOAD_PATH << File.expand_path('../../lib', __FILE__)
4
+
5
+ require 'gli'
4
6
  require 'klipbook'
5
7
 
6
- Klipbook::CLI.start
8
+ include GLI::App
9
+
10
+ program_desc "Collates the clippings you've saved on your Kindle into a nice html summary for each book."
11
+
12
+ SOURCE_HELP = "Two sources are currently supported: a file from a Kindle device and the Kindle site itself.\n\n" +
13
+ "Example file formats:\n\n" +
14
+ " file:path/to/my-clippings-file.txt\n\n" +
15
+ " site:my-kindle-user@blah.com:my-kindle-password\n\n" +
16
+ "Note that source and output file defaults can be stored in a file called ~/.klipbookrc\n\n" +
17
+ "This file is YAML formatted e.g.\n\n" +
18
+ "source: site:my-kindle-user@blah.com:my-kindle-password\n\n" +
19
+ "output: my/default/output/directory"
20
+
21
+ version Klipbook::VERSION
22
+
23
+ desc 'Number of books to process'
24
+ arg_name 'count'
25
+ default_value 1
26
+ flag [:n, :'num-books']
27
+
28
+ desc 'Collate your clippings into a html file for each book'
29
+ arg_name 'source'
30
+ long_desc "Clippings are fetched from the specified source before being collated into html " +
31
+ "files and written into the current directory.\n\n" + SOURCE_HELP
32
+ command :collate do |c|
33
+
34
+ c.desc 'Override the directory path where collated files are written'
35
+ c.arg_name 'Directory'
36
+ c.flag [:o, :'output-dir']
37
+
38
+ c.desc 'Force overwrite of any existing collated files'
39
+ c.switch [:f, :force]
40
+
41
+ c.action do |globals,options,args|
42
+ books = fetch_books(args, globals)
43
+ Klipbook::Collator.new(books).collate_books(output_dir(options), options[:f])
44
+ end
45
+ end
46
+
47
+ desc 'List available books'
48
+ arg_name 'source'
49
+ long_desc "Clippings are fetched from the specified source before being listed to screen.\n\n" + SOURCE_HELP
50
+ command :list do |c|
51
+ c.action do |globals,options,args|
52
+ books = fetch_books(args, globals)
53
+ Klipbook::Printer.new(books).print
54
+ end
55
+ end
56
+
57
+ pre do |globals,command,options,args|
58
+ unless source_spec(args)
59
+ raise InvalidSourceError
60
+ end
61
+
62
+ odir = output_dir(options)
63
+ if odir && !File.exists?(odir)
64
+ raise "Output directory doesn't exist: #{odir}"
65
+ end
66
+
67
+ if globals[:n].to_i == 0
68
+ raise 'Specify a number of books greater than 0'
69
+ end
70
+
71
+ true
72
+ end
73
+
74
+ def source_spec(args)
75
+ @source_spec ||= (args[0] || Klipbook::Config.new.read[:source])
76
+ end
77
+
78
+ def fetch_books(args, globals)
79
+ Klipbook::Fetcher.new(source_spec(args), globals[:n].to_i).fetch_books
80
+ end
81
+
82
+ def output_dir(options)
83
+ @output_dir ||= unless options[:o] == 'Current directory'
84
+ options[:o]
85
+ else
86
+ Klipbook::Config.new.read[:output] || Dir.pwd
87
+ end
88
+ end
89
+
90
+ exit run(ARGV)
7
91
 
data/example.png CHANGED
Binary file
@@ -0,0 +1,51 @@
1
+ Feature: klipbook collates the clippings from a clippings file
2
+ As an avid reader and note taker
3
+ I want to see a pretty html collation for books that I've read
4
+ So that I can refer to a nice summary of passages I enjoyed in the book
5
+
6
+ Scenario: File with clippings for a book
7
+ Given a directory named "output"
8
+ And a file that contains clippings for 3 books called "input.txt"
9
+ When I collate clippings for "3" books from the file "input.txt" to the output directory "output"
10
+ Then I should find a file in the folder "output" named "Lean Software Development: An Agile Toolkit by Mary Poppendieck and Tom Poppendieck.html" that contains "13" clippings
11
+ Then I should find a file in the folder "output" named "Instapaper: Long Reads by Instapaper: Long Reads.html" that contains "4" clippings
12
+ Then I should find a file in the folder "output" named "Clean Code: A Handbook of Agile Software Craftsmanship by Robert C. Martin.html" that contains "3" clippings
13
+ And the exit status should be 0
14
+
15
+ Scenario: Attempting to write to an existing file
16
+ Given a directory named "output"
17
+ And a file in "output" named "Clean Code: A Handbook of Agile Software Craftsmanship by Robert C. Martin.html"
18
+ And a file that contains clippings for 3 books called "input.txt"
19
+ When I collate clippings for "3" books from the file "input.txt" to the output directory "output"
20
+ Then the output should contain "Skipping Clean Code: A Handbook of Agile Software Craftsmanship by Robert C. Martin.html"
21
+ And the exit status should be 0
22
+
23
+ Scenario: Force overwrite of an existing file
24
+ Given a directory named "output"
25
+ And a file in "output" named "Clean Code: A Handbook of Agile Software Craftsmanship by Robert C. Martin.html"
26
+ And a file that contains clippings for 3 books called "input.txt"
27
+ When I collate clippings for "3" books from the file "input.txt" to the output directory "output" forcefully
28
+ Then the output should contain "Writing Clean Code: A Handbook of Agile Software Craftsmanship by Robert C. Martin.html"
29
+ And the exit status should be 0
30
+
31
+ Scenario: Attempt to write with a bad number of books
32
+ Given a directory named "output"
33
+ And a file that contains clippings for 3 books called "input.txt"
34
+ When I collate clippings for "notanumber" books from the file "input.txt" to the output directory "output"
35
+ Then the output should contain "error: Specify a number of books greater than 0"
36
+ And the exit status should be 1
37
+
38
+ Scenario: Attempt to write to a non-existent directory
39
+ Given there is not a directory named "output"
40
+ And a file that contains clippings for 3 books called "input.txt"
41
+ When I collate clippings for "3" books from the file "input.txt" to the output directory "output"
42
+ Then the output should contain "error: Output directory doesn't exist: output"
43
+ And the exit status should be 1
44
+
45
+ @slow
46
+ Scenario: Site with clippings for a book
47
+ Given a directory named "output"
48
+ When I collate clippings for "1" books from the kindle site to the output directory "output"
49
+ Then I should find "1" collated files containing clippings in the directory "output"
50
+ And the exit status should be 0
51
+
@@ -0,0 +1,105 @@
1
+ Clean Code: A Handbook of Agile Software Craftsmanship (Robert C. Martin)
2
+ - Highlight Loc. 4536-37 | Added on Tuesday, August 21, 2012, 09:32 PM
3
+
4
+ Concurrency can sometimes improve performance, but only when there is a lot of wait time that can be shared between multiple threads or multiple processors. Neither situation is trivial.
5
+ ==========
6
+ Clean Code: A Handbook of Agile Software Craftsmanship (Robert C. Martin)
7
+ - Note Loc. 4713 | Added on Tuesday, August 21, 2012, 09:43 PM
8
+
9
+ Recommendations for developing concurrent systems
10
+ ==========
11
+ Clean Code: A Handbook of Agile Software Craftsmanship (Robert C. Martin)
12
+ - Highlight Loc. 4745-46 | Added on Tuesday, August 21, 2012, 09:45 PM
13
+
14
+ Things happen when the system switches between tasks. To encourage task swapping, run with more threads than processors or cores. The more frequently your tasks swap, the more likely you’ll encounter code that is missing a critical section or causes deadlock.
15
+ ==========
16
+ Instapaper: Long Reads (Instapaper: Long Reads)
17
+ - Highlight Loc. 91-93 | Added on Sunday, April 24, 2011, 02:20 PM
18
+
19
+ 3. Do not freeze work design into code! Leave as much work design as possible for work teams to determine and modify. If that is not possible, make sure that the people who will live with the new system are involved in the design of their work.
20
+ ==========
21
+ Instapaper: Long Reads (Instapaper: Long Reads)
22
+ - Highlight Loc. 90-91 | Added on Sunday, April 24, 2011, 02:20 PM
23
+
24
+ 2. Simplify before you automate. Never automate a work process until the work teams have devised as simple a work process as they possibly can. Automating the right thing is at least as important as automating it right.
25
+ ==========
26
+ Instapaper: Long Reads (Instapaper: Long Reads)
27
+ - Highlight Loc. 150-51 | Added on Sunday, April 24, 2011, 02:25 PM
28
+
29
+ Roll-in of progressive change They started off with small teams (4 people in the beginning) so not a big bang approach. 
30
+ ==========
31
+ Instapaper: Long Reads (Instapaper: Long Reads)
32
+ - Highlight Loc. 167-72 | Added on Sunday, April 24, 2011, 02:28 PM
33
+
34
+ What is management’s role? The hardest part is working with managers and helping them see their new role.  Their role becomes understanding demand, thinking outside in, engage staff, walk the process, allow staff to experiment with design and evaluate etc.  Previously managers used to be specialists at solving tricky decisions, but now they have to become a specialist in training (moving from ‘disablers’ to ‘enablers).  They now need to create conditions that enable workers to reach their goals.  They need to support and encourage the initiative of the workers.  They need to ensure that the process / initiative is end to end.  Also, building agreement with others outside the process.
35
+ ==========
36
+ Lean Software Development: An Agile Toolkit (Mary Poppendieck and Tom Poppendieck)
37
+ - Highlight Loc. 921-23 | Added on Monday, April 25, 2011, 09:18 AM
38
+
39
+ Your objective should be to balance experimentation with deliberation and review. In order to do this, consider how you can generate the most knowledge at the least cost in your circumstances.
40
+ ==========
41
+ Lean Software Development: An Agile Toolkit (Mary Poppendieck and Tom Poppendieck)
42
+ - Highlight Loc. 930-32 | Added on Monday, April 25, 2011, 01:10 PM
43
+
44
+ There are many ways to represent the system, from models to prototypes, to incremental deliveries, but the important thing is to select the representation that gathers the most knowledge. Most users relate better to seeing working screens than to a requirements document, so working software tends to generate better knowledge faster.
45
+ ==========
46
+ Lean Software Development: An Agile Toolkit (Mary Poppendieck and Tom Poppendieck)
47
+ - Highlight Loc. 1035-44 | Added on Monday, April 25, 2011, 01:21 PM
48
+
49
+ In most cases, increasing feedback, not decreasing it, is the single most effective way to deal with troubled software development projects and environments. Instead of letting defects accumulate, run tests as soon as the code is written. Instead of adding more documentation or detailed planning, try checking out ideas by writing code. Instead of gathering more requirements from users, show them an assortment of potential user screens and get their input. Instead of studying more carefully which tool to use, bring the top three candidates inhouse and test them. Instead of trying to figure out how to convert an entire system in a single massive effort, create a Web front end to the legacy system and try the new idea out.
50
+ ==========
51
+ Lean Software Development: An Agile Toolkit (Mary Poppendieck and Tom Poppendieck)
52
+ - Highlight Loc. 1066-67 | Added on Monday, April 25, 2011, 01:24 PM
53
+
54
+ One reason just-in-time flow is so effective is that it requires significantly improved worker-to-worker communication and surfaces quality problems as soon as they occur.
55
+ ==========
56
+ Lean Software Development: An Agile Toolkit (Mary Poppendieck and Tom Poppendieck)
57
+ - Highlight Loc. 1074-77 | Added on Monday, April 25, 2011, 01:28 PM
58
+
59
+ An iteration is a useful increment of software that is designed, programmed, tested, integrated, and delivered during a short, fixed timeframe. It is very similar to a prototype in product development except that an iteration produces a working portion of the final product. This software will be improved in future iterations, but it is working, tested, integrated code from the beginning.
60
+ ==========
61
+ Lean Software Development: An Agile Toolkit (Mary Poppendieck and Tom Poppendieck)
62
+ - Highlight Loc. 1180-81 | Added on Monday, April 25, 2011, 02:34 PM
63
+
64
+ A Standish Group study found that 45 percent of features in a typical system are never used and 19 percent are rarely used.
65
+ ==========
66
+ Lean Software Development: An Agile Toolkit (Mary Poppendieck and Tom Poppendieck)
67
+ - Highlight Loc. 1359-62 | Added on Tuesday, April 26, 2011, 08:34 AM
68
+
69
+ When you have a difficult problem, try this: Develop a set of alternative solutions to a problem, see how well they actually work, and then merge the best features of the solutions or choose one of the alternatives. It might seem wasteful to develop multiple solutions to the same problem, but set-based development can lead to better solutions faster,
70
+ ==========
71
+ Lean Software Development: An Agile Toolkit (Mary Poppendieck and Tom Poppendieck)
72
+ - Bookmark Loc. 1364 | Added on Tuesday, April 26, 2011, 08:36 AM
73
+
74
+
75
+ ==========
76
+ Lean Software Development: An Agile Toolkit (Mary Poppendieck and Tom Poppendieck)
77
+ - Highlight Loc. 1392-93 | Added on Tuesday, April 26, 2011, 08:42 AM
78
+
79
+ Set-based development means that you communicate constraints, not solutions.
80
+ ==========
81
+ Lean Software Development: An Agile Toolkit (Mary Poppendieck and Tom Poppendieck)
82
+ - Highlight Loc. 1535-36 | Added on Tuesday, April 26, 2011, 08:59 AM
83
+
84
+ This presents us with a new category of waste: waste caused by software that is difficult to change.
85
+ ==========
86
+ Lean Software Development: An Agile Toolkit (Mary Poppendieck and Tom Poppendieck)
87
+ - Highlight Loc. 1586-88 | Added on Tuesday, April 26, 2011, 09:10 AM
88
+
89
+ Lean software development emphasizes developing a robust, change-tolerant design, one that accepts the inevitability of change and structures the system so that it can be readily adapted to the most likely kinds of changes.
90
+ ==========
91
+ Lean Software Development: An Agile Toolkit (Mary Poppendieck and Tom Poppendieck)
92
+ - Highlight Loc. 1588-89 | Added on Tuesday, April 26, 2011, 09:11 AM
93
+
94
+ The main reason software changes throughout its lifecycle is that the business process in which it is used evolves over time.
95
+ ==========
96
+ Lean Software Development: An Agile Toolkit (Mary Poppendieck and Tom Poppendieck)
97
+ - Highlight Loc. 1627-28 | Added on Tuesday, April 26, 2011, 09:19 AM
98
+
99
+ the underlying economic mechanism for controlling complexity in just-in-time systems is minimizing irreversible actions.
100
+ ==========
101
+ Lean Software Development: An Agile Toolkit (Mary Poppendieck and Tom Poppendieck)
102
+ - Highlight Loc. 1722-23 | Added on Tuesday, April 26, 2011, 09:48 AM
103
+
104
+ Good design is a discovery process, done through short, repeated exploratory cycles.
105
+ ==========
@@ -0,0 +1,31 @@
1
+ Feature: klipbook lists the books in a clipping file
2
+ As an avid reader and note taker
3
+ I want to be shown an indexed list of books
4
+ So that I can see which books are available for collation
5
+
6
+ Scenario: Empty file
7
+ Given I have a clippings file "input.txt" that contains no clippings
8
+ When I list "1" books in the file "input.txt"
9
+ Then the output should contain "No books available"
10
+ And the exit status should be 0
11
+
12
+ Scenario: File with one book
13
+ Given a file that contains clippings for 3 books called "input.txt"
14
+ When I list "5" books in the file "input.txt"
15
+ Then the output should contain "[1] Clean Code: A Handbook of Agile Software Craftsmanship by Robert C. Martin"
16
+ Then the output should contain "[2] Lean Software Development: An Agile Toolkit by Mary Poppendieck and Tom Poppendieck"
17
+ Then the output should contain "[3] Instapaper: Long Reads by Instapaper: Long Reads"
18
+ And the exit status should be 0
19
+
20
+ Scenario: File with one book
21
+ Given a file that contains clippings for 3 books called "input.txt"
22
+ When I list "5" books in the file "input.txt"
23
+ Then the output should match /\[1\] .+ by .+/
24
+ And the exit status should be 0
25
+
26
+ @slow
27
+ Scenario: Site with one book
28
+ When I list "1" books from the kindle site
29
+ Then the output should match /\[1\] .+ by .+/
30
+ And the exit status should be 0
31
+
@@ -0,0 +1,61 @@
1
+ CLIPPING_FILE = File.join(File.dirname(__FILE__), '../fixtures/clippings-for-three-books.txt')
2
+
3
+ Given /^a file in "([^"]*)" named "([^"]*)"$/ do |output_dir, file_name|
4
+ in_current_dir { FileUtils.touch(File.join(output_dir, file_name)) }
5
+ end
6
+
7
+ Given /^there is not a directory named "([^"]*)"$/ do |directory_name|
8
+ in_current_dir do
9
+ FileUtils.rm_f(directory_name)
10
+ end
11
+ end
12
+
13
+ Given /^a file that contains clippings for 3 books called "([^"]*)"$/ do |file_name|
14
+ in_current_dir { FileUtils.cp(CLIPPING_FILE, file_name) }
15
+ end
16
+
17
+ When /^I collate clippings for "([^"]*)" books from the file "([^"]*)" to the output directory "([^"]*)"$/ do |book_count, input_file, output_dir|
18
+ run_collate_file(book_count, output_dir, input_file, false)
19
+ end
20
+
21
+ When /^I collate clippings for "([^"]*)" books from the file "([^"]*)" to the output directory "([^"]*)" forcefully$/ do |book_count, input_file, output_dir|
22
+ run_collate_file(book_count, output_dir, input_file, true)
23
+ end
24
+
25
+ Then /^I should find a file in the folder "([^"]*)" named "([^"]*)" that contains "([^"]*)" clippings$/ do |output_folder, file_name, clipping_count|
26
+ in_current_dir do
27
+ file_path = File.join(output_folder, file_name)
28
+ File.exists?(file_path).should be_true
29
+ File.open(file_path, 'r') do |f|
30
+ f.read.should match(/<footer>\s+#{clipping_count} clippings &bull;/m)
31
+ end
32
+ end
33
+ end
34
+
35
+ # FIXME This step currently assumes you have site: set up in your klipbookrc
36
+ When /^I collate clippings for "([^"]*)" books from the kindle site to the output directory "([^"]*)"$/ do |book_count, output_dir|
37
+ run_simple(unescape("klipbook -n #{book_count} collate -o #{output_dir}"), false)
38
+ end
39
+
40
+ Then /^I should find "([^"]*)" collated files containing clippings in the directory "([^"]*)"$/ do |file_count, output_dir|
41
+ in_current_dir do
42
+ files = Dir['output/*.html']
43
+ files.should have(file_count.to_i).items
44
+ files.each do |fname|
45
+ File.open(fname, 'r') do |f|
46
+ f.read.should match(/<footer>\s+\d+ clippings &bull;/m)
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ def run_collate_file(book_count, output, input, force=false)
53
+ force_str = if force
54
+ '-f'
55
+ else
56
+ ''
57
+ end
58
+
59
+ run_simple(unescape("klipbook -n #{book_count} collate #{force_str} -o #{output} file:#{input}"), false)
60
+ end
61
+
@@ -0,0 +1,15 @@
1
+
2
+ Given /^I have a clippings file "([^"]*)" that contains no clippings$/ do |input_file|
3
+ in_current_dir do
4
+ FileUtils.touch(input_file)
5
+ end
6
+ end
7
+
8
+ When /^I list "([^"]*)" books in the file "([^"]*)"$/ do |book_count, input_file|
9
+ run_simple(unescape("klipbook -n #{book_count} list file:#{input_file}"), false)
10
+ end
11
+
12
+ # FIXME This step currently assumes you have site: set up in your klipbookrc
13
+ When /^I list "([^"]*)" books from the kindle site$/ do |book_count|
14
+ run_simple(unescape("klipbook -n #{book_count} list"), false)
15
+ end