├── .gitignore
├── .rspec
├── .travis.yml
├── CHANGELOG.txt
├── Gemfile
├── Gemfile.lock
├── LICENSE.txt
├── README.md
├── Rakefile
├── bin
└── klipbook
├── example.png
├── features
├── export_html.feature
├── export_json.feature
├── export_markdown.feature
├── fixtures
│ └── clippings-for-three-books.txt
├── list.feature
├── step_definitions
│ ├── export_steps.rb
│ └── list_steps.rb
└── support
│ └── env.rb
├── klipbook.gemspec
├── lib
├── klipbook.rb
└── klipbook
│ ├── cli.rb
│ ├── commands
│ ├── command.rb
│ ├── export.rb
│ ├── exporters
│ │ ├── exporter.rb
│ │ ├── html_book_summary.erb
│ │ ├── html_exporter.rb
│ │ ├── json_exporter.rb
│ │ ├── markdown_book_summary.erb
│ │ └── markdown_exporter.rb
│ └── list.rb
│ ├── config.rb
│ ├── logger.rb
│ ├── sources
│ ├── book.rb
│ ├── clipping.rb
│ ├── kindle_device
│ │ ├── entry.rb
│ │ ├── entry_parser.rb
│ │ ├── file.rb
│ │ └── file_parser.rb
│ └── source.rb
│ ├── util
│ ├── blank.rb
│ └── struct_to_json.rb
│ └── version.rb
└── spec
├── lib
└── klipbook
│ └── sources
│ ├── book_spec.rb
│ └── kindle_device
│ ├── entry_parser_spec.rb
│ ├── file_parser_spec.rb
│ └── file_spec.rb
└── spec_helper.rb
/.gitignore:
--------------------------------------------------------------------------------
1 | /.bundle/
2 | /.yardoc
3 | /_yardoc/
4 | /coverage/
5 | /doc/
6 | /pkg/
7 | /spec/reports/
8 | /tmp/
9 | /vendor/
10 |
--------------------------------------------------------------------------------
/.rspec:
--------------------------------------------------------------------------------
1 | --colour --format documentation
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: ruby
2 | rvm:
3 | - 2.5.2
4 |
--------------------------------------------------------------------------------
/CHANGELOG.txt:
--------------------------------------------------------------------------------
1 | == 4.0.0 / 2018-11-07
2 |
3 | * Breaking changes
4 |
5 | * Remove site scraping feature.
6 |
7 | * Minor changes
8 |
9 | * Tested on Ruby 2.5.2
10 |
11 | == 3.0.0 / 2016-09-18
12 |
13 | * Feature Changes
14 |
15 | * Added markdown as an export format.
16 |
17 | * Breaking changes
18 |
19 | * Changed command flags to make things more consistent.
20 | * Changed JSON export to export into individual files rather than a single file. Again for consistency with other export formats.
21 |
22 | == 2.1.3 / 2014-07-25
23 |
24 | * Minor changes
25 |
26 | * Removed Rainbow, RR, pry-debugger gems
27 | * Updated dependent gems
28 | * Updated tests to use RSpec 3
29 | * Tested on Ruby 2.1.2
30 |
31 | == 2.1.0 / 2013-12-11
32 |
33 | * Feature changes
34 |
35 | * Reworked parameters for better clarity. tosjon and tohtml are now supported.
36 |
37 | == 2.0.0 / 2013-02-12
38 |
39 | * Feature changes
40 |
41 | * Renamed the collate command to pretty print which describes what it does better.
42 |
43 | * Introduces a _new_ collate command that collates all clippings into a single JSON
44 | file.
45 |
46 | * Other unexposed changes
47 |
48 | * Internally refactored much of the codebase into a more sensible structure.
49 |
50 | == 1.0.2 / 2012-12-12
51 |
52 | * Bug fixes
53 |
54 | * Updated site scraping code to ensure it still works
55 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gemspec
4 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | PATH
2 | remote: .
3 | specs:
4 | klipbook (4.0.0)
5 | commander
6 |
7 | GEM
8 | remote: https://rubygems.org/
9 | specs:
10 | activesupport (6.0.3.2)
11 | concurrent-ruby (~> 1.0, >= 1.0.2)
12 | i18n (>= 0.7, < 2)
13 | minitest (~> 5.1)
14 | tzinfo (~> 1.1)
15 | zeitwerk (~> 2.2, >= 2.2.2)
16 | aruba (1.0.2)
17 | childprocess (>= 2.0, < 5.0)
18 | contracts (~> 0.16.0)
19 | cucumber (>= 2.4, < 5.0)
20 | ffi (~> 1.9)
21 | rspec-expectations (~> 3.4)
22 | thor (~> 1.0)
23 | builder (3.2.4)
24 | byebug (11.1.3)
25 | childprocess (4.0.0)
26 | coderay (1.1.3)
27 | commander (4.5.2)
28 | highline (~> 2.0.0)
29 | concurrent-ruby (1.1.6)
30 | contracts (0.16.0)
31 | cucumber (4.0.1)
32 | builder (~> 3.2, >= 3.2.3)
33 | cucumber-core (~> 7.0, >= 7.0.0)
34 | cucumber-cucumber-expressions (~> 10.1, >= 10.1.0)
35 | cucumber-gherkin (~> 13.0, >= 13.0.0)
36 | cucumber-html-formatter (~> 6.0, >= 6.0.1)
37 | cucumber-messages (~> 12.1, >= 12.1.1)
38 | cucumber-wire (~> 3.0, >= 3.0.0)
39 | diff-lcs (~> 1.3, >= 1.3, < 1.4)
40 | multi_test (~> 0.1, >= 0.1.2)
41 | sys-uname (~> 1.0, >= 1.0.2)
42 | cucumber-core (7.0.0)
43 | cucumber-gherkin (~> 13.0, >= 13.0.0)
44 | cucumber-messages (~> 12.1, >= 12.1.1)
45 | cucumber-tag-expressions (~> 2.0, >= 2.0.4)
46 | cucumber-cucumber-expressions (10.2.1)
47 | cucumber-gherkin (13.0.0)
48 | cucumber-messages (~> 12.0, >= 12.0.0)
49 | cucumber-html-formatter (6.0.3)
50 | cucumber-messages (~> 12.1, >= 12.1.1)
51 | cucumber-messages (12.2.0)
52 | protobuf-cucumber (~> 3.10, >= 3.10.8)
53 | cucumber-tag-expressions (2.0.4)
54 | cucumber-wire (3.0.0)
55 | cucumber-core (~> 7.0, >= 7.0.0)
56 | cucumber-cucumber-expressions (~> 10.1, >= 10.1.0)
57 | cucumber-messages (~> 12.1, >= 12.1.1)
58 | diff-lcs (1.3)
59 | ffi (1.13.1)
60 | highline (2.0.3)
61 | i18n (1.8.3)
62 | concurrent-ruby (~> 1.0)
63 | method_source (1.0.0)
64 | middleware (0.1.0)
65 | minitest (5.14.1)
66 | multi_test (0.1.2)
67 | protobuf-cucumber (3.10.8)
68 | activesupport (>= 3.2)
69 | middleware
70 | thor
71 | thread_safe
72 | pry (0.13.1)
73 | coderay (~> 1.1)
74 | method_source (~> 1.0)
75 | pry-byebug (3.9.0)
76 | byebug (~> 11.0)
77 | pry (~> 0.13.0)
78 | rake (13.0.1)
79 | rspec (3.9.0)
80 | rspec-core (~> 3.9.0)
81 | rspec-expectations (~> 3.9.0)
82 | rspec-mocks (~> 3.9.0)
83 | rspec-core (3.9.2)
84 | rspec-support (~> 3.9.3)
85 | rspec-expectations (3.9.2)
86 | diff-lcs (>= 1.2.0, < 2.0)
87 | rspec-support (~> 3.9.0)
88 | rspec-mocks (3.9.1)
89 | diff-lcs (>= 1.2.0, < 2.0)
90 | rspec-support (~> 3.9.0)
91 | rspec-support (3.9.3)
92 | sys-uname (1.2.1)
93 | ffi (>= 1.0.0)
94 | thor (1.0.1)
95 | thread_safe (0.3.6)
96 | tzinfo (1.2.7)
97 | thread_safe (~> 0.1)
98 | zeitwerk (2.3.1)
99 |
100 | PLATFORMS
101 | ruby
102 |
103 | DEPENDENCIES
104 | aruba
105 | bundler
106 | cucumber
107 | klipbook!
108 | pry-byebug
109 | rake
110 | rspec
111 |
112 | BUNDLED WITH
113 | 2.1.4
114 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Ray Grasso
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Klipbook
2 |
3 | [](https://travis-ci.org/grassdog/klipbook)
4 |
5 | Klipbook takes the highlights and notes that you've created on your Kindle and
6 | outputs them into nice HTML, Markdown, or JSON.
7 |
8 | ## An example of a HTML clippings file generated by Klipbook
9 |
10 |
12 |
13 | ## What sources does it support?
14 |
15 | Klipbook can take your highlights from a clippings file off a physical Kindle device.
16 |
17 | ## How does it work?
18 |
19 | Klipbook supports two commands: `list` and `export`.
20 |
21 | `list` shows the books in the specified source and `export` exports books to a different format.
22 |
23 | ## Specifying an Input Source
24 |
25 | Both commands require you to specify the source of your clippings.
26 |
27 | ### Reading from a clippings file
28 |
29 | Copy your clippings file (called "My Clippings.txt" on a 3rd generation Kindle) from your Kindle device to your local drive via USB.
30 |
31 | Then specify the path to your clippings via:
32 |
33 | ```sh
34 | $ klipbook list --from-file "My Clippings.txt"
35 | ```
36 |
37 | ## List
38 |
39 | The `list` command lists the books available in the specified source.
40 |
41 | ```sh
42 | $ klipbook list --from-file "My Clippings.txt"
43 |
44 | Book list:
45 | [1] The Big Sleep by Raymond Chandler
46 | [2] How to jump out of a plane without a parachute and survive by Rip Rockjaw
47 | ```
48 |
49 | By default it will only list the latest book. This can be overrided with the `--count` switch.
50 |
51 | ## Export
52 |
53 | `export` reads the clippings from your source and writes them out in the specified format.
54 |
55 | You can specify the directory to export into with the `--output-dir` switch. This defaults to the current directory.
56 |
57 | You can also specify a maximum number of books you'd like exported with the `--count` switch.
58 |
59 | Klipbook will not overwrite an exiting file by default. You can change this with the `--force` flag.
60 |
61 | ### Export to Html
62 |
63 | You can export clippings into a pretty html file for each book.
64 |
65 | ```sh
66 | $ klipbook export --from-file "My Clippings.txt" --format html
67 | ```
68 |
69 | ### Export to JSON
70 |
71 | You can export clippings into a JSON file for each book.
72 |
73 | ```sh
74 | $ klipbook export --from-file "My Clippings.txt" --format json
75 | ```
76 |
77 | ### Export to Markdown
78 |
79 | You can export clippings into a markdown file for each book.
80 |
81 | ```sh
82 | $ klipbook export --from-file "My Clippings.txt" --format markdown
83 | ```
84 |
85 | ## Set defaults
86 |
87 | You can set your defaults in the klipbook rc file: `~/.klipbookrc`.
88 |
89 | This is a YAML file and you can specify default values for the source and the output directory (note the use of snake case) e.g.
90 |
91 | ```sh
92 | $ cat ~/.klipbookrc
93 |
94 | :output_dir: /path/to/my/default/output/directory
95 | ```
96 |
97 | Command line options override the defaults stored in the rc file.
98 |
99 | ## Installation
100 |
101 | Klipbook is a Ruby gem. To install simply run:
102 |
103 | ```sh
104 | $ gem install klipbook
105 | ```
106 |
107 | ## Supported Devices
108 |
109 | Klipbook has been tested on clippings files from 3rd generation Kindles and the Kindle Touch.
110 |
111 | ## Tested platforms
112 |
113 | Klipbook has been tested on Mac OS High Sierra using Ruby 2.5.1.
114 |
115 | ## Contributing to Klipbook
116 |
117 | Fork the project on [Github](https://github.com/grassdog/klipbook), add tests for your changes, and submit a well described pull request.
118 |
119 | ## Copyright
120 |
121 | Copyright (c) 2018 Ray Grasso. See LICENSE.txt for further details.
122 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | require "bundler/gem_tasks"
2 |
3 | require "rspec/core/rake_task"
4 | require 'cucumber/rake/task'
5 |
6 | desc 'Run specs'
7 | RSpec::Core::RakeTask.new(:spec)
8 |
9 | Cucumber::Rake::Task.new(:features) do |t|
10 | t.cucumber_opts = '--format pretty'
11 | end
12 |
13 | desc 'Default: run specs'
14 | task :default => [ :spec, :features ]
15 |
16 |
--------------------------------------------------------------------------------
/bin/klipbook:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | require "bundler/setup"
4 | require "klipbook"
5 |
6 | Klipbook::CLI.new.execute!
7 |
--------------------------------------------------------------------------------
/example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grassdog/klipbook/44a39446398d6c089359782934f45f747198081c/example.png
--------------------------------------------------------------------------------
/features/export_html.feature:
--------------------------------------------------------------------------------
1 | Feature: klipbook outputs the clippings from a clippings file into a set of HTML files
2 | As an avid reader and note taker
3 | I want to see a pretty html summary for each of the 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 export clippings for "3" books from the file "input.txt" as "html" to the output directory "output"
10 | Then I should find a "html" file in the folder "output" named "Lean Software Development An Agile Toolkit.html" that contains "13" clippings
11 | Then I should find a "html" file in the folder "output" named "Instapaper Long Reads.html" that contains "4" clippings
12 | Then I should find a "html" file in the folder "output" named "Clean Code A Handbook of Agile Software Craftsmanship.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.html"
18 | And a file that contains clippings for 3 books called "input.txt"
19 | When I export clippings for "3" books from the file "input.txt" as "html" to the output directory "output"
20 | Then the output should contain "- Skipping Clean Code A Handbook of Agile Software Craftsmanship.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.html"
26 | And a file that contains clippings for 3 books called "input.txt"
27 | When I export clippings for "3" books from the file "input.txt" as "html" to the output directory "output" forcefully
28 | Then the output should contain "+ Writing Clean Code A Handbook of Agile Software Craftsmanship.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 export clippings for "notanumber" books from the file "input.txt" as "html" to the output directory "output"
35 | Then the output should contain "invalid argument: -c notanumber"
36 | And the exit status should be non-zero
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 export clippings for "3" books from the file "input.txt" as "html" to the output directory "output"
42 | Then the output should contain "Error: Output directory 'output' does not exist."
43 | And the exit status should be non-zero
44 |
--------------------------------------------------------------------------------
/features/export_json.feature:
--------------------------------------------------------------------------------
1 | Feature: klipbook outputs clippings from a clippings file into a JSON file
2 | As an avid reader and note taker
3 | I want to see a JSON summary for each of the books that I've read
4 | So that I can export them to other tools for my enjoyment
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 export clippings for "3" books from the file "input.txt" as "json" to the output directory "output"
10 | Then I should find a "json" file in the folder "output" named "Lean Software Development An Agile Toolkit.json" that contains "13" clippings
11 | Then I should find a "json" file in the folder "output" named "Instapaper Long Reads.json" that contains "4" clippings
12 | Then I should find a "json" file in the folder "output" named "Clean Code A Handbook of Agile Software Craftsmanship.json" 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.json"
18 | And a file that contains clippings for 3 books called "input.txt"
19 | When I export clippings for "3" books from the file "input.txt" as "json" to the output directory "output"
20 | Then the output should contain "- Skipping Clean Code A Handbook of Agile Software Craftsmanship.json"
21 | And the exit status should be 0
22 |
--------------------------------------------------------------------------------
/features/export_markdown.feature:
--------------------------------------------------------------------------------
1 | Feature: klipbook outputs clippings from a clippings file into a Markdown file
2 | As an avid reader and note taker
3 | I want to see a Markdown summary for each of the books that I've read
4 | So that I can export them to other tools for my enjoyment
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 export clippings for "3" books from the file "input.txt" as "markdown" to the output directory "output"
10 | Then I should find a "markdown" file in the folder "output" named "Lean Software Development An Agile Toolkit.md" that contains "13" clippings
11 | Then I should find a "markdown" file in the folder "output" named "Instapaper Long Reads.md" that contains "4" clippings
12 | Then I should find a "markdown" file in the folder "output" named "Clean Code A Handbook of Agile Software Craftsmanship.md" 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.md"
18 | And a file that contains clippings for 3 books called "input.txt"
19 | When I export clippings for "3" books from the file "input.txt" as "markdown" to the output directory "output"
20 | Then the output should contain "- Skipping Clean Code A Handbook of Agile Software Craftsmanship.md"
21 | And the exit status should be 0
22 |
--------------------------------------------------------------------------------
/features/fixtures/clippings-for-three-books.txt:
--------------------------------------------------------------------------------
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 | ==========
106 |
--------------------------------------------------------------------------------
/features/list.feature:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/features/step_definitions/export_steps.rb:
--------------------------------------------------------------------------------
1 | CLIPPING_FILE = File.join(
2 | File.dirname(__FILE__),
3 | '../fixtures/clippings-for-three-books.txt'
4 | )
5 |
6 | Given(/^a file in "([^"]*)" named "([^"]*)"$/) do |output_dir, file_name|
7 | cd('.') { FileUtils.touch(File.join(output_dir, file_name)) }
8 | end
9 |
10 | Given(/^there is not a directory named "([^"]*)"$/) do |directory_name|
11 | cd('.') { FileUtils.rm_f(directory_name) }
12 | end
13 |
14 | Given(/^a file that contains clippings for 3 books called "([^"]*)"$/) do |file_name|
15 | cd('.') { FileUtils.cp(CLIPPING_FILE, file_name) }
16 | end
17 |
18 | #
19 | # Whens
20 | #
21 |
22 | When(/^I export clippings for "([^"]*)" books from the file "([^"]*)" as "([^"]*)" to the output directory "([^"]*)"$/) do |book_count, input_file, format, output_dir|
23 | run_export_file(book_count, output_dir, input_file, format, false)
24 | end
25 |
26 | When(/^I export clippings for "([^"]*)" books from the file "([^"]*)" as "([^"]*)" to the output directory "([^"]*)" forcefully$/) do |book_count, input_file, format, output_dir|
27 | run_export_file(book_count, output_dir, input_file, format, true)
28 | end
29 |
30 |
31 | #
32 | # Thens
33 | #
34 |
35 | Then(/^I should find a "([^"]*)" file in the folder "([^"]*)" named "([^"]*)" that contains "([^"]*)" clippings$/) do |format, output_folder, file_name, clipping_count|
36 | cd('.') do
37 | file_path = File.join(output_folder, file_name)
38 | expect(File.exist?(file_path)).to be_truthy
39 | File.open(file_path, 'r') do |f|
40 | confirm_clipping_count(f, format, clipping_count)
41 | end
42 | end
43 | end
44 |
45 | Then(/^the exit status should be non\-zero$/) do
46 | expect(last_command_started).not_to be_successfully_executed
47 | end
48 |
49 | Then(/^I should find "([^"]*)" "([^"]*)" files containing clippings in the directory "([^"]*)"$/) do |file_count, format, output_dir|
50 | extension = format == "markdown" ? "md" : format
51 |
52 | cd('.') do
53 | files = Dir["#{output_dir}/*.#{extension}"]
54 | expect(files.size).to eq(file_count.to_i)
55 | files.each do |fname|
56 | File.open(fname, 'r') do |f|
57 | confirm_clipping_exist(f, format)
58 | end
59 | end
60 | end
61 | end
62 |
63 | def run_export_file(book_count, output_dir, input_file, format, force=false)
64 | force_str = force ? '-f' : ''
65 |
66 | run_command_and_stop(sanitize_text("klipbook export --format #{format} -c #{book_count} #{force_str} --output-dir #{output_dir} --from-file #{input_file}"), fail_on_error: false)
67 | end
68 |
69 |
70 |
71 | def confirm_clipping_count(file, format, expected_count)
72 | if format == 'html'
73 | expect(file.read).to match(/