pirka 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.document +3 -0
- data/.gitignore +6 -0
- data/.yardopts +1 -0
- data/COPYING.txt +674 -0
- data/ChangeLog.md +4 -0
- data/Gemfile +14 -0
- data/README.md +201 -0
- data/Rakefile +27 -0
- data/app/detect.rb +166 -0
- data/app/highlight.rb +161 -0
- data/app/lib.rb +52 -0
- data/app/subcommand.rb +35 -0
- data/app/update.rb +67 -0
- data/app.rb +74 -0
- data/bin/pirka +17 -0
- data/lib/pirka/config.rb +110 -0
- data/lib/pirka/library.rb +152 -0
- data/lib/pirka/version.rb +22 -0
- data/lib/pirka.rb +1 -0
- data/pirka.gemspec +49 -0
- data/test/fixtures/YWJj.yaml +10 -0
- data/test/helper.rb +18 -0
- data/test/test_library.rb +152 -0
- data/test/test_pirka.rb +12 -0
- metadata +296 -0
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,201 @@
|
|
1
|
+
Pirka
|
2
|
+
=====
|
3
|
+
|
4
|
+
* [Homepage](https://gitlab.com/KitaitiMakoto/pirka)
|
5
|
+
* [Documentation](http://www.rubydoc.info/gems/pirka)
|
6
|
+
* [Email](mailto:KitaitiMakoto at gmail.com)
|
7
|
+
|
8
|
+
Description
|
9
|
+
-----------
|
10
|
+
|
11
|
+
Pirka highlights source code syntax in EPUB books
|
12
|
+
|
13
|
+
Features
|
14
|
+
--------
|
15
|
+
|
16
|
+
* Highlights synatax in EPUB files
|
17
|
+
* Extracts `<code>` elements from EPUB files and asks you which programing language they are, and then uses them to highlight
|
18
|
+
* Downloads shared code and language information from Git repository
|
19
|
+
|
20
|
+
Examples
|
21
|
+
--------
|
22
|
+
|
23
|
+
### Highlighting source code syntax in EPUB books ###
|
24
|
+
|
25
|
+
$ pirka path/to/book.epub
|
26
|
+
|
27
|
+
It's a short cut to:
|
28
|
+
|
29
|
+
$ pirka highlight path/to/book.epub
|
30
|
+
|
31
|
+
### Detecting source code from EPUB books ###
|
32
|
+
|
33
|
+
$ pirka detect path/to/book.epub
|
34
|
+
Detecting code from "Book Title"
|
35
|
+
Library file was saved to:
|
36
|
+
path/to/library.yaml
|
37
|
+
|
38
|
+
`library.yaml` here includes:
|
39
|
+
|
40
|
+
* location of `<code>` element(expressed by [EPUB CFI][] but you don't need to undarstand it.)
|
41
|
+
* `language` field with blank value
|
42
|
+
* file path in EPUB file(zip archive)
|
43
|
+
* source code
|
44
|
+
|
45
|
+
Example:
|
46
|
+
|
47
|
+
epubcfi(/6/64!/4/2/30/2): # location
|
48
|
+
language: # language name. blank at first
|
49
|
+
item: OEBPS/text/p-003-003.xhtml # file path in zip archive
|
50
|
+
code: | # source code
|
51
|
+
f1 = open("|cat", "w")
|
52
|
+
f2 = open("|sed 's/a/b/'", "w")
|
53
|
+
f1.print "Hello\n"
|
54
|
+
f2.print "abc\n"
|
55
|
+
f1.close
|
56
|
+
f2.close
|
57
|
+
|
58
|
+
In Pirka context, the file is called *library*.
|
59
|
+
|
60
|
+
`pirka highlight` command determines programming languages of source code according to this file.
|
61
|
+
Read source code, determine languages, write it at `language` field, remove `code` field, and then
|
62
|
+
you can highlight the EPUB file by `pirka highlight`.
|
63
|
+
|
64
|
+
You also determine languages interactively. Set `-i`(`--interactive`) option:
|
65
|
+
|
66
|
+
$ pirka detect -i path/to/book.epub
|
67
|
+
|
68
|
+
[EPUB CFI]: http://www.idpf.org/epub/linking/cfi/
|
69
|
+
|
70
|
+
### Updating libraries ###
|
71
|
+
|
72
|
+
$ pirka update
|
73
|
+
|
74
|
+
Pirka provides official library files for some EPUB books as Git repository((https://gitlab.com/KitaitiMakoto/pirka-library)[https://gitlab.com/KitaitiMakoto/pirka-library]). `pirka update` command fethes the files from the repository and you benefit from it.
|
75
|
+
|
76
|
+
Additionally, you can host library files by your own and make Pirka recognizes it by configuration file. See later section for that.
|
77
|
+
|
78
|
+
### Listing supported books ###
|
79
|
+
|
80
|
+
$ pirka lib
|
81
|
+
|
82
|
+
`pirka lib` command lists books Pirka can highlight with:
|
83
|
+
|
84
|
+
* Release Identifier(special identifier for EPUB books)
|
85
|
+
* location of library file
|
86
|
+
* title
|
87
|
+
* some other metadata
|
88
|
+
|
89
|
+
### Configuration ###
|
90
|
+
|
91
|
+
Pirka can be configured by environment variables, config file and command-line options.
|
92
|
+
|
93
|
+
#### Environment variables ####
|
94
|
+
|
95
|
+
XDG_DATA_HOME
|
96
|
+
: Affects directory to save library files.
|
97
|
+
: Library files are saved to `$XDG_DATA_HOME/pirka/local`
|
98
|
+
: The directory is used to search library, too.
|
99
|
+
: Default: `$HOME/.local/share`
|
100
|
+
|
101
|
+
XDG_DATA_DIRS
|
102
|
+
: Affects directory to save library files.
|
103
|
+
: You can specify multiple directory by seperating with a colon like `XDG_DATA_DIRS=/dir1:/dir2`.
|
104
|
+
: `/dir1/pirka/local` and `/dir2/pirka/local` are used to search library, for example.
|
105
|
+
: Default: `/usr/local/share:/usr/share`
|
106
|
+
|
107
|
+
XDG_CONFIG_HOME
|
108
|
+
: Affects directory to search and save config file.
|
109
|
+
: `$XDG_CONFIG_DIRS/pirka.yaml` is recognized as config file.
|
110
|
+
: Default: `$HOME/.config`
|
111
|
+
|
112
|
+
XDG_CONFIG_DIRS
|
113
|
+
: Affects directory to search config file.
|
114
|
+
: You can specify multiple directory by seperating with a colon like `XDG_CONFIG_DIRS=/dir1:/dir2`.
|
115
|
+
: `/dir1/pirka.yaml` and `/dir2/pirka.yaml` are searched as config file.
|
116
|
+
: Default: `/etc/xdg`
|
117
|
+
|
118
|
+
#### Config file ####
|
119
|
+
|
120
|
+
Config file is a YAML file. Properties below are recognized:
|
121
|
+
|
122
|
+
data_home
|
123
|
+
: Directory to save and search library files.
|
124
|
+
: Default: `$XDG_CONFIG_HOME/pirka/local`
|
125
|
+
|
126
|
+
additional_directories
|
127
|
+
: Directories to search library files.
|
128
|
+
: Expressed by sequence(array).
|
129
|
+
: Default: `[]`
|
130
|
+
|
131
|
+
library_repositories
|
132
|
+
: Git repository URIs used by `pirka lib` command.
|
133
|
+
: Expressed by sequence(array).
|
134
|
+
: Default: `[]`
|
135
|
+
|
136
|
+
#### Command-line options ####
|
137
|
+
|
138
|
+
You can configure Pirka by `pirka` command's global options:
|
139
|
+
|
140
|
+
`-c`, `--config=FILE`
|
141
|
+
: Path to config file.
|
142
|
+
: Default: /Users/ikeda/.config/pirka.yaml
|
143
|
+
|
144
|
+
`-s`, `--data-home=DIRECTORY`
|
145
|
+
: Same to config file's `data_home` property.
|
146
|
+
|
147
|
+
`-d`, `--directory=DIRECTORY`
|
148
|
+
: Same to config file's `additional_directories` property.
|
149
|
+
: Able to multilpe times.
|
150
|
+
|
151
|
+
You can also see help by
|
152
|
+
|
153
|
+
$ pirka --help
|
154
|
+
Pirka highlights source code syntax in EPUB files
|
155
|
+
|
156
|
+
Usage: pirka [global options] [<command>] [options]
|
157
|
+
|
158
|
+
Global options:
|
159
|
+
-c, --config=FILE Config file. Defaults to /Users/ikeda/.config/pirka.yaml
|
160
|
+
-s, --data-home=DIRECTORY Directory to *SAVE* library data
|
161
|
+
-d, --directory=DIRECTORY Directory to *SEARCH* library data.
|
162
|
+
Specify multiple times to add multiple directories.
|
163
|
+
|
164
|
+
Commands:
|
165
|
+
highlight Highlights source code in EPUB file
|
166
|
+
detect Detects source code from EPUB file and generate library file
|
167
|
+
update Update library files by remote files
|
168
|
+
lib Show library infomation
|
169
|
+
If command is ommitted, highlight is used with no option
|
170
|
+
|
171
|
+
Requirements
|
172
|
+
------------
|
173
|
+
|
174
|
+
* Ruby 2.2 or later
|
175
|
+
* C compiler to compile [Nokogiri][] gem
|
176
|
+
|
177
|
+
[Nokogiri]: http://www.nokogiri.org/
|
178
|
+
|
179
|
+
Install
|
180
|
+
-------
|
181
|
+
|
182
|
+
$ gem install pirka
|
183
|
+
|
184
|
+
### Make faster ###
|
185
|
+
|
186
|
+
By default, Pirka uses [archive-zip][] gem, a pure Ruby implementation, for zip archive but you can make command execution faster by using [Zip/Ruby][] gem, a C implementation. Just install Zip/Ruby:
|
187
|
+
|
188
|
+
$ gem install zipruby
|
189
|
+
|
190
|
+
Pirka, actually internally-used [EPUB Parser][], tries to load Zip/Ruby and use it if available.
|
191
|
+
|
192
|
+
[archive-zip]: https://github.com/javanthropus/archive-zip
|
193
|
+
[Zip/Ruby]: https://bitbucket.org/winebarrel/zip-ruby/wiki/Home
|
194
|
+
[EPUB Parser]: http://www.rubydoc.info/gems/epub-parser/file/docs/Home.markdown
|
195
|
+
|
196
|
+
Copyright
|
197
|
+
---------
|
198
|
+
|
199
|
+
Copyright (c) 2017 KITAITI Makoto
|
200
|
+
|
201
|
+
See {file:COPYING.txt} for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'bundler/setup'
|
7
|
+
rescue LoadError => e
|
8
|
+
abort e.message
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'rake'
|
12
|
+
|
13
|
+
task :default => :test
|
14
|
+
|
15
|
+
require 'rubygems/tasks'
|
16
|
+
Gem::Tasks.new
|
17
|
+
|
18
|
+
require 'rake/testtask'
|
19
|
+
Rake::TestTask.new do |test|
|
20
|
+
test.libs << 'test'
|
21
|
+
test.pattern = 'test/**/test_*.rb'
|
22
|
+
test.verbose = true
|
23
|
+
end
|
24
|
+
|
25
|
+
require 'yard'
|
26
|
+
YARD::Rake::YardocTask.new
|
27
|
+
task :doc => :yard
|
data/app/detect.rb
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
require "optparse"
|
2
|
+
require "optparse/pathname"
|
3
|
+
require "epub/parser"
|
4
|
+
require "epub/cfi"
|
5
|
+
require "epub/searcher"
|
6
|
+
require "rouge"
|
7
|
+
require "rouge/lexers/fluentd"
|
8
|
+
require "colored"
|
9
|
+
require "pirka/library"
|
10
|
+
require_relative "subcommand"
|
11
|
+
|
12
|
+
module Pirka
|
13
|
+
class App
|
14
|
+
class Detect
|
15
|
+
PROGRAM_NAME = "detect"
|
16
|
+
DESCRIPTION = "Detects source code from EPUB file and generate library file"
|
17
|
+
ARGS = %w[EPUB_FILE]
|
18
|
+
|
19
|
+
include Subcommand
|
20
|
+
|
21
|
+
def initialize(config)
|
22
|
+
super
|
23
|
+
|
24
|
+
@library_path = nil
|
25
|
+
@interactive = false
|
26
|
+
|
27
|
+
@available_lexers = Rouge::Lexer.all.sort_by(&:tag).each_with_object({}).with_index {|(lexer, lexers), index|
|
28
|
+
lexers[(index + 1).to_s] = lexer
|
29
|
+
}
|
30
|
+
initial = nil
|
31
|
+
@lexers_display = @available_lexers.collect {|(index, lexer)|
|
32
|
+
init = lexer.title[0].upcase
|
33
|
+
if initial == init
|
34
|
+
option = ""
|
35
|
+
else
|
36
|
+
option = "\n"
|
37
|
+
initial = init
|
38
|
+
end
|
39
|
+
option << "#{index})".bold << " " << lexer.title
|
40
|
+
option << "(#{lexer.aliases.join(', ')})" unless lexer.aliases.empty?
|
41
|
+
option
|
42
|
+
}.join(" ")
|
43
|
+
@commands = ["s) skip", "q) quit", "c) show code", "o) show options"].join(" ")
|
44
|
+
@commands = {
|
45
|
+
"s" => "skip",
|
46
|
+
"q" => "quit",
|
47
|
+
"c" => "show code",
|
48
|
+
"o" => "show options"
|
49
|
+
}.collect {|(key, command)|
|
50
|
+
"#{key})".bold << " " << command
|
51
|
+
}.join(" ")
|
52
|
+
end
|
53
|
+
|
54
|
+
def run(argv)
|
55
|
+
parse_options! argv
|
56
|
+
|
57
|
+
epub_path = argv.shift
|
58
|
+
raise ArgumentError, 'Specify EPUB file' unless epub_path
|
59
|
+
|
60
|
+
begin
|
61
|
+
# @todo Make this optional
|
62
|
+
require 'epub/maker/ocf/physical_container/zipruby'
|
63
|
+
EPUB::OCF::PhysicalContainer.adapter = :Zipruby
|
64
|
+
rescue LoadError
|
65
|
+
end
|
66
|
+
epub = EPUB::Parser.parse(epub_path)
|
67
|
+
$stderr.puts "Detecting code from \"#{epub.title}\""
|
68
|
+
|
69
|
+
codelist = {}
|
70
|
+
library = Library.new
|
71
|
+
library.metadata["Release Identifier"] = epub.release_identifier
|
72
|
+
library.metadata["title"] = epub.title
|
73
|
+
catch do |quit|
|
74
|
+
EPUB::Searcher.search_element(epub, css: 'code').each do |result|
|
75
|
+
item = result[:itemref].item
|
76
|
+
if @interactive
|
77
|
+
catch do |skip|
|
78
|
+
show_item item
|
79
|
+
show_code result[:element]
|
80
|
+
show_options
|
81
|
+
show_commands
|
82
|
+
i = ask
|
83
|
+
|
84
|
+
while true
|
85
|
+
case i
|
86
|
+
when "s"
|
87
|
+
throw skip
|
88
|
+
when "q"
|
89
|
+
throw quit
|
90
|
+
when "c"
|
91
|
+
show_item item
|
92
|
+
show_code(result[:element])
|
93
|
+
show_options
|
94
|
+
show_commands
|
95
|
+
i = ask
|
96
|
+
when "o"
|
97
|
+
show_options
|
98
|
+
show_commands
|
99
|
+
i = ask
|
100
|
+
else
|
101
|
+
lexer = @available_lexers[i]
|
102
|
+
unless lexer
|
103
|
+
i = ask
|
104
|
+
next
|
105
|
+
end
|
106
|
+
library.codelist[result[:location]] = {"language" => lexer.tag}
|
107
|
+
break
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
else
|
112
|
+
library.codelist[result[:location]] = ({
|
113
|
+
"language" => nil,
|
114
|
+
"item" => result[:itemref].item.entry_name,
|
115
|
+
"code" => result[:element].content
|
116
|
+
})
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
path = library.save(@library_path)
|
121
|
+
$stderr.puts "Library file was saved to:"
|
122
|
+
$stdout.puts path
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
private
|
127
|
+
|
128
|
+
def parse_options!(argv)
|
129
|
+
super do |opt|
|
130
|
+
opt.separator ""
|
131
|
+
opt.on "-i", "--interactive" do
|
132
|
+
@interactive = true
|
133
|
+
end
|
134
|
+
opt.on "-o", "--output=FILE", "File to save library data", Pathname do |path|
|
135
|
+
@library_path = path
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def show_item(item)
|
141
|
+
$stderr.puts
|
142
|
+
$stderr.puts item.entry_name
|
143
|
+
end
|
144
|
+
|
145
|
+
def show_code(code)
|
146
|
+
$stderr.puts
|
147
|
+
$stderr.puts code.content
|
148
|
+
$stderr.puts
|
149
|
+
end
|
150
|
+
|
151
|
+
def show_options
|
152
|
+
$stderr.puts @lexers_display
|
153
|
+
end
|
154
|
+
|
155
|
+
def show_commands
|
156
|
+
$stderr.puts
|
157
|
+
$stderr.puts @commands
|
158
|
+
end
|
159
|
+
|
160
|
+
def ask
|
161
|
+
$stderr.print "Which language? "
|
162
|
+
$stdin.gets.chomp
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
data/app/highlight.rb
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
require "pathname"
|
2
|
+
require "optparse"
|
3
|
+
require "optparse/pathname"
|
4
|
+
require "epub/parser"
|
5
|
+
require "epub/maker"
|
6
|
+
require "rouge"
|
7
|
+
require "rouge/lexers/fluentd"
|
8
|
+
require "pirka/library"
|
9
|
+
require_relative "subcommand"
|
10
|
+
|
11
|
+
module Pirka
|
12
|
+
class App
|
13
|
+
class Highlight
|
14
|
+
PROGRAM_NAME = "highlight"
|
15
|
+
DESCRIPTION = "Highlights source code in EPUB file"
|
16
|
+
ARGS = %w[EPUB_FILE]
|
17
|
+
|
18
|
+
include Subcommand
|
19
|
+
|
20
|
+
DUMMY_ORIGIN = Addressable::URI.parse("file:///")
|
21
|
+
CSS_PATH = "pirka/style.css" # @todo Avoid conflict with existing item by other than Pirka
|
22
|
+
CSS_CLASS_NAME = "pirka"
|
23
|
+
SCOPE = "code.#{CSS_CLASS_NAME}"
|
24
|
+
THEME = "github"
|
25
|
+
|
26
|
+
def initialize(config)
|
27
|
+
super
|
28
|
+
@library_path = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
# @todo Handle multiple renditions
|
32
|
+
def run(argv)
|
33
|
+
parse_options! argv
|
34
|
+
|
35
|
+
epub_path = argv.shift
|
36
|
+
raise ArgumentError, 'Specify EPUB file' unless epub_path
|
37
|
+
|
38
|
+
begin
|
39
|
+
# @todo Make this optional
|
40
|
+
require 'epub/maker/ocf/physical_container/zipruby'
|
41
|
+
EPUB::OCF::PhysicalContainer.adapter = :Zipruby
|
42
|
+
rescue LoadError
|
43
|
+
end
|
44
|
+
epub = EPUB::Parser.parse(epub_path)
|
45
|
+
library = find_library(epub.unique_identifier, epub.modified)
|
46
|
+
raise RuntimeError, "Cannot find code list #{Library.filename(epub.release_identifier)} for #{epub.release_identifier}(#{epub_path}) in any directory of #{Library.directories.join(", ")}" unless library
|
47
|
+
|
48
|
+
css_item = add_css_file(epub)
|
49
|
+
need_save = highlight_contents(epub, css_item, library)
|
50
|
+
need_save << css_item
|
51
|
+
need_save.uniq!
|
52
|
+
update_modified_date(epub, Time.now)
|
53
|
+
|
54
|
+
save_file epub, need_save
|
55
|
+
end
|
56
|
+
|
57
|
+
# @param [EPUB::Book, EPUB::Book::Features] epub
|
58
|
+
# @return [EPUB::Publication::Package::Manifest::Item] item indicating added CSS file
|
59
|
+
def add_css_file(epub)
|
60
|
+
rootfile_path = DUMMY_ORIGIN + epub.ocf.container.rootfile.full_path
|
61
|
+
style = Rouge::Theme.find(THEME).new(scope: SCOPE).render
|
62
|
+
|
63
|
+
epub.package.manifest.make_item {|item|
|
64
|
+
item.href = (DUMMY_ORIGIN + CSS_PATH).route_from(rootfile_path)
|
65
|
+
# IMPROVEMENT: Want to call item.entry_name = css_path
|
66
|
+
item.media_type = 'text/css'
|
67
|
+
item.id = CSS_PATH.gsub('/', '-') # @todo Avoid conflict with existing items
|
68
|
+
item.content = style
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
# @todo Do the best when file for release identifier is not find but for unique identifier found
|
73
|
+
def find_library(unique_identifier, modified)
|
74
|
+
@library_path ? Library.load_file(@library_path) :
|
75
|
+
Library.find_by_release_identifier("#{unique_identifier}@#{modified}")
|
76
|
+
end
|
77
|
+
|
78
|
+
# @todo Consider descendant elements of code
|
79
|
+
def highlight_contents(epub, css_item, library)
|
80
|
+
need_save = []
|
81
|
+
|
82
|
+
formatter = Rouge::Formatters::HTML.new
|
83
|
+
|
84
|
+
library.each.reverse_each do |(cfi, data)|
|
85
|
+
lang = data["language"]
|
86
|
+
unless lang
|
87
|
+
warn "Language for #{cfi} is not detected"
|
88
|
+
next
|
89
|
+
end
|
90
|
+
itemref, elem, _ = EPUB::Searcher.search_by_cfi(epub, cfi)
|
91
|
+
item = itemref.item
|
92
|
+
doc = elem.document
|
93
|
+
lexer = Rouge::Lexer.find(lang) || Rouge::Lexer.guess(source: elem.content)
|
94
|
+
unless lexer
|
95
|
+
warn "Cannot find lexer for #{lang}"
|
96
|
+
next
|
97
|
+
end
|
98
|
+
elem.inner_html = formatter.format(lexer.lex(elem.content)) # @todo Consider the case `elem` has descendants
|
99
|
+
|
100
|
+
classes = (elem["class"] || "").split(/\s+/)
|
101
|
+
unless classes.include? CSS_CLASS_NAME
|
102
|
+
classes << CSS_CLASS_NAME
|
103
|
+
elem["class"] = classes.join(" ")
|
104
|
+
end
|
105
|
+
|
106
|
+
link = doc.at('#pirka') # @todo Avoid conflict with existing link
|
107
|
+
unless link
|
108
|
+
item_entry_name = DUMMY_ORIGIN + item.entry_name
|
109
|
+
entry_name = DUMMY_ORIGIN + css_item.entry_name
|
110
|
+
href = entry_name.route_from(item_entry_name)
|
111
|
+
link = Nokogiri::XML::Node.new('link', doc)
|
112
|
+
link['href'] = href
|
113
|
+
link['type'] = 'text/css'
|
114
|
+
link['rel'] = 'stylesheet'
|
115
|
+
link['id'] = 'pirka'
|
116
|
+
head = (doc/'head').first
|
117
|
+
head << link
|
118
|
+
end
|
119
|
+
item.content = doc.to_xml
|
120
|
+
need_save << item
|
121
|
+
end
|
122
|
+
|
123
|
+
need_save
|
124
|
+
end
|
125
|
+
|
126
|
+
def update_modified_date(epub, time = Time.now)
|
127
|
+
modified = epub.modified
|
128
|
+
unless modified
|
129
|
+
modified = EPUB::Publication::Package::Metadata::Meta.new
|
130
|
+
modified.property = 'dcterms:modified'
|
131
|
+
epub.package.metadata.metas << modified
|
132
|
+
end
|
133
|
+
modified.content = time.utc.iso8601
|
134
|
+
|
135
|
+
modified
|
136
|
+
end
|
137
|
+
|
138
|
+
def save_file(epub, need_save)
|
139
|
+
need_save.each do |item|
|
140
|
+
item.save
|
141
|
+
epub.package.manifest << item
|
142
|
+
end
|
143
|
+
epub.package.edit
|
144
|
+
end
|
145
|
+
|
146
|
+
private
|
147
|
+
|
148
|
+
# @todo theme
|
149
|
+
# @todo CSS file path
|
150
|
+
# @todo scope
|
151
|
+
def parse_options!(argv)
|
152
|
+
super do |opt|
|
153
|
+
opt.separator ""
|
154
|
+
opt.on "-l", "--library=FILE", "library file", Pathname do |path|
|
155
|
+
@library_path = path
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
data/app/lib.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require "pirka/library"
|
2
|
+
|
3
|
+
module Pirka
|
4
|
+
class App
|
5
|
+
class Lib
|
6
|
+
PROGRAM_NAME = "lib"
|
7
|
+
DESCRIPTION = "Show library infomation"
|
8
|
+
|
9
|
+
include Subcommand
|
10
|
+
|
11
|
+
def run(argv)
|
12
|
+
# show all
|
13
|
+
# show remote repos
|
14
|
+
# show data dirs
|
15
|
+
# show data home
|
16
|
+
# show books
|
17
|
+
# show book metadata
|
18
|
+
|
19
|
+
no_dir_file_length = Library::SUBDIR_LENGTH + Library::EXT.length
|
20
|
+
Library.directories.each do |dir|
|
21
|
+
next unless dir.directory?
|
22
|
+
|
23
|
+
dir.each_child do |child|
|
24
|
+
if child.to_path.length < no_dir_file_length && child.extname != Library::EXT
|
25
|
+
show_info child
|
26
|
+
next
|
27
|
+
end
|
28
|
+
next unless child.directory?
|
29
|
+
next unless child.basename.to_path.length == Library::SUBDIR_LENGTH
|
30
|
+
child.each_child do |lib|
|
31
|
+
next unless lib.extname == Library::EXT
|
32
|
+
next unless lib.file?
|
33
|
+
show_info lib
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def show_info(path)
|
40
|
+
$stdout.puts Library.load_file(path).metadata.to_yaml
|
41
|
+
$stdout.puts "library: #{path}"
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def parse_options!(argv)
|
47
|
+
super do |opt|
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/app/subcommand.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
module Pirka
|
2
|
+
class App
|
3
|
+
module Subcommand
|
4
|
+
class << self
|
5
|
+
def included(base)
|
6
|
+
APPS[base::PROGRAM_NAME] = base
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
# @param [Config]
|
11
|
+
def initialize(config)
|
12
|
+
@config = config
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
# @todo Consider the case the subcommand has no option
|
18
|
+
def parse_options!(argv)
|
19
|
+
parser = OptionParser.new {|opt|
|
20
|
+
usage = "Usage: #{opt.program_name} [options] #{self.class::PROGRAM_NAME}"
|
21
|
+
usage << " " << self.class::ARGS.join(" ") if self::class.const_defined?(:ARGS)
|
22
|
+
|
23
|
+
opt.program_name = "#{opt.program_name} [global options] #{self.class::PROGRAM_NAME}"
|
24
|
+
opt.banner = <<EOB
|
25
|
+
#{self::class::DESCRIPTION}
|
26
|
+
|
27
|
+
#{usage}
|
28
|
+
EOB
|
29
|
+
yield opt if block_given?
|
30
|
+
}
|
31
|
+
parser.order! argv
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|