docbook_status 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.bnsignore ADDED
@@ -0,0 +1,18 @@
1
+ # The list of files that should be ignored by Mr Bones.
2
+ # Lines that start with '#' are comments.
3
+ #
4
+ # A .gitignore file can be used instead by setting it as the ignore
5
+ # file in your Rakefile:
6
+ #
7
+ # Bones {
8
+ # ignore_file '.gitignore'
9
+ # }
10
+ #
11
+ # For a project with a C extension, the following would be a good set of
12
+ # exclude patterns (uncomment them if you want to use them):
13
+ # *.[oa]
14
+ # *~
15
+ announcement.txt
16
+ coverage
17
+ doc
18
+ pkg
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "http://rubygems.org"
2
+ gem "libxml-ruby", "~> 2.2.2", :require => 'xml'
3
+ gem "directory_watcher"
4
+
5
+ group :development do
6
+ gem "bones"
7
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,16 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ directory_watcher (1.4.1)
5
+ hoe (2.12.3)
6
+ rake (~> 0.8)
7
+ libxml-ruby (2.2.2)
8
+ rake (0.9.2)
9
+
10
+ PLATFORMS
11
+ ruby
12
+
13
+ DEPENDENCIES
14
+ directory_watcher
15
+ hoe
16
+ libxml-ruby (~> 2.2.2)
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ == 0.1.0 / 2011-09-07
2
+
3
+ * Initial version
4
+
data/README.txt ADDED
@@ -0,0 +1,59 @@
1
+ = docbook_status
2
+
3
+ A utility for DocBook authors/publishers showing the document structure (sections) and word count of a DocBook project. It is intended to provide an overview of a DocBook project's structure and volume while you are writing or editing it.
4
+
5
+
6
+ == Features
7
+
8
+ * lists all sections (set, book, ... section, simplesect) in a DocBook file
9
+ * calculates a word count for each section (words in paras, simparas and formalparas)
10
+ * works with included sections (XInclude)
11
+
12
+ == Examples
13
+
14
+ The package includes a comandline application, bin/docbook_status, that can be used in two ways:
15
+
16
+ to run it manually, once:
17
+ docbook_status <DocBook file>
18
+
19
+ to run the application in demon mode, continually:
20
+ docbook_status --demon --glob "*.xml" --dir "." <DocBook file>
21
+
22
+ In demon-mode the application checks the files matched by the _glob_ pattern in the directory specified by _dir_ for changes, and redisplays the document analysis whenever a change occures. The demon can be termanted by simply pressing RETURN.
23
+
24
+ == Download
25
+
26
+ https://rubygems.org/gem/docbook_status
27
+
28
+ == Requirements
29
+
30
+ * libxml2
31
+
32
+ == Install
33
+
34
+ * gem install docbook_status
35
+
36
+ == License
37
+
38
+ The MIT License
39
+
40
+ Copyright (c) 2011 Rainer Volz
41
+
42
+ Permission is hereby granted, free of charge, to any person obtaining
43
+ a copy of this software and associated documentation files (the
44
+ 'Software'), to deal in the Software without restriction, including
45
+ without limitation the rights to use, copy, modify, merge, publish,
46
+ distribute, sublicense, and/or sell copies of the Software, and to
47
+ permit persons to whom the Software is furnished to do so, subject to
48
+ the following conditions:
49
+
50
+ The above copyright notice and this permission notice shall be
51
+ included in all copies or substantial portions of the Software.
52
+
53
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
54
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
55
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
56
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
57
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
58
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
59
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+
2
+ begin
3
+ require 'bones'
4
+ rescue LoadError
5
+ abort '### Please install the "bones" gem ###'
6
+ end
7
+
8
+ task :default => 'test:run'
9
+ task 'gem:release' => 'test:run'
10
+
11
+ Bones {
12
+ name 'docbook_status'
13
+ authors 'Rainer Volz'
14
+ email 'dev@textmulch.de'
15
+ url 'http://projekte.textmuch.de/docbook_status/'
16
+ }
17
+
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env ruby
2
+ # -*-encoding:utf-8 ; mode:ruby-*-
3
+ ##
4
+ # docbook_status is the commandline application for the library.
5
+ # Its main purpose is to display the structure and word counts for DocBook 5 documents.
6
+ # docbook_status can be used in single-run mode or demon-mode. In demon_mode it stays active
7
+ # and looks for changes in the filesystem.
8
+ #
9
+
10
+ require 'rubygems'
11
+ require "bundler/setup"
12
+ require 'optparse'
13
+ require 'directory_watcher'
14
+
15
+ require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib docbook_status]))
16
+
17
+ @demon = false
18
+ @glob = '*.xml'
19
+ @dir = '.'
20
+ @pre = []
21
+ banner = <<EOB
22
+ docbook_status, Version #{DocbookStatus.version}
23
+
24
+ Display DocBook 5 document structure and word counts.
25
+
26
+ Usage: docbook_status [--demon] [--glob <PATTERN>] [--dir <DIR>] [--pre COMMAND] <DOCBOOK-FILE>
27
+ EOB
28
+
29
+ opts = OptionParser.new
30
+ opts.banner = banner
31
+ opts.on('--demon', 'Keep running, act when files change') {|val| @demon = true}
32
+ opts.on('--glob PATTERN', String, 'File mask for demon mode, default = "*.xml"') {|val| @glob = val}
33
+ opts.on('--dir DIR', String, 'Source directory for demon mode, default = "." ') {|val| @dir = val}
34
+ opts.on('--pre COMMAND', String, 'A shell command that should be executed before') {|val| @pre << val}
35
+ rest = opts.parse(ARGV)
36
+
37
+ def run(file)
38
+ @pre.each {|cmd| system(cmd)}
39
+ doc = XML::Document.file(file)
40
+ dbs = DocbookStatus.new
41
+ if !dbs.is_docbook?(doc)
42
+ puts "Error: #{file} is apparently not DocBook 5."
43
+ return
44
+ end
45
+ doc.xinclude if dbs.has_xinclude?(doc)
46
+ sections = dbs.analyze_document(doc)
47
+ puts
48
+ puts "File: #{file}"
49
+ puts "Modified: #{File.ctime(file)}"
50
+ puts "Document structure:"
51
+ puts "%-50.50s %-16s %5s" % ['Title','Tag','Words']
52
+ puts "-"*73
53
+ sections.each do |s|
54
+ puts "%-50.50s %-16s %5d" % [(' ' * s[2])+s[0], s[3], s[1]]
55
+ end
56
+ end
57
+
58
+ def demon(file)
59
+ dw = DirectoryWatcher.new @dir, :glob => @glob, :pre_load => true
60
+ dw.interval = 5.0
61
+ dw.stable = 2
62
+ dw.persist = "dw_state.yml"
63
+ dw.add_observer {|*args|
64
+ args.each {|event|
65
+ #puts event
66
+ if event.type == :stable
67
+ run(file)
68
+ end
69
+ }
70
+ }
71
+ dw.start # loads state from dw_state.yml
72
+ STDIN.gets # when the user hits "enter" the script will terminate
73
+ dw.stop # stores state to dw_state.yml
74
+ end
75
+
76
+ # Print banner if called without arguments
77
+ if rest.length < 1
78
+ puts opts.to_s
79
+ exit 1
80
+ end
81
+
82
+ puts("docbook_status, Version #{DocbookStatus.version}")
83
+ run(rest[0])
84
+ if (@demon)
85
+ demon(rest[0])
86
+ end
87
+ exit 0
@@ -0,0 +1,35 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{docbook_status}
5
+ s.version = "0.1.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Rainer Volz"]
9
+ s.date = %q{2011-09-08}
10
+ s.default_executable = %q{docbook_status}
11
+ s.description = %q{A utility for DocBook authors/publishers showing the document structure (sections) and word count of a DocBook project. It is intended to provide an overview of a DocBook project's structure and volume while you are writing or editing it.}
12
+ s.email = %q{dev@textmulch.de}
13
+ s.executables = ["docbook_status"]
14
+ s.extra_rdoc_files = ["History.txt", "README.txt", "bin/docbook_status"]
15
+ s.files = [".bnsignore", "Gemfile", "Gemfile.lock", "History.txt", "README.txt", "Rakefile", "bin/docbook_status", "lib/docbook_status.rb", "spec/docbook_status_spec.rb", "spec/spec_helper.rb", "test/fixtures/book.xml", "test/fixtures/chapter2.xml", "test/test_docbook_status.rb", "version.txt"]
16
+ s.homepage = %q{http://projekte.textmuch.de/docbook_status/}
17
+ s.rdoc_options = ["--main", "README.txt"]
18
+ s.require_paths = ["lib"]
19
+ s.rubyforge_project = %q{docbook_status}
20
+ s.rubygems_version = %q{1.6.2}
21
+ s.summary = %q{A utility for DocBook authors/publishers showing the document structure (sections) and word count of a DocBook project.}
22
+ s.test_files = ["test/test_docbook_status.rb"]
23
+
24
+ if s.respond_to? :specification_version then
25
+ s.specification_version = 3
26
+
27
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
28
+ s.add_development_dependency(%q<bones>, [">= 3.7.1"])
29
+ else
30
+ s.add_dependency(%q<bones>, [">= 3.7.1"])
31
+ end
32
+ else
33
+ s.add_dependency(%q<bones>, [">= 3.7.1"])
34
+ end
35
+ end
@@ -0,0 +1,143 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'xml'
4
+
5
+ # Analyzes DocBook 5 documents for document structure (sections) and text length.
6
+ #
7
+ class DocbookStatus
8
+
9
+ # :stopdoc
10
+ #
11
+ PATH = File.expand_path('../..', __FILE__) + File::SEPARATOR
12
+ LIBPATH = File.expand_path('..', __FILE__) + File::SEPARATOR
13
+ VERSION = File.read(PATH + '/version.txt').strip
14
+ HOME = File.expand_path(ENV['HOME'] || ENV['USERPROFILE'])
15
+ #
16
+ # :startdoc
17
+
18
+ # The DocBook 5 namespace URL
19
+ DOCBOOK_NS = 'http://docbook.org/ns/docbook'
20
+ # The XInclude namespace URL
21
+ XINCLUDE_NS = 'http://www.w3.org/2001/XInclude'
22
+
23
+ # Elements whose contents is counted as text
24
+ @@text_elements = ['para','simpara','formalpara']
25
+
26
+ # Section elements, following the list given in http://docbook.org/tdg5/en/html/ch02.html#roots
27
+ # except for the refsect... elements.
28
+ @@section_elements = %w[
29
+ acknowledgements appendix article
30
+ bibliography book
31
+ chapter colophon
32
+ dedication
33
+ glossary
34
+ index
35
+ preface
36
+ section sect1 sect2 sect3 sect4 set simplesect
37
+ toc
38
+ ]
39
+
40
+ def initialize
41
+ @sections = []
42
+ end
43
+
44
+ # Returns the version of docbook_status
45
+ #
46
+ def self.version
47
+ VERSION
48
+ end
49
+
50
+ # Counts the words in the contents of the given node. _Word_ in this
51
+ # context means something that is delimited by _space_ charactes and starts with
52
+ # _word_ characters (in the regexp sense).
53
+ #
54
+ def count_words(node)
55
+ words = node.content.strip.split(/[[:space:]]+/).find_all {|w| w =~ /\w+/}
56
+ words.size
57
+ end
58
+
59
+ # Find the _title_ of the current section. That element is either
60
+ # directly following or inside an _info_ element. Return the empty
61
+ # string if no title can be found.
62
+ #
63
+ def find_section_title(node)
64
+ title = node.find_first('./db:title')
65
+ if title.nil?
66
+ title = node.find_first './db:info/db:title'
67
+ end
68
+ if title.nil?
69
+ ""
70
+ else
71
+ title.content
72
+ end
73
+ end
74
+
75
+ # Check the document elements for content and type recursively,
76
+ # starting at the current node. Returns an array with paragraph and
77
+ # section maps.
78
+ #
79
+ def check_node(node, level, ctr)
80
+ if (@@text_elements.include? node.name)
81
+ ctr << {:type => :para, :level => level, :words => count_words(node)}
82
+ elsif (@@section_elements.include? node.name)
83
+ title = find_section_title(node)
84
+ ctr << {:type => :section, :level => level, :title => title, :name => node.name}
85
+ end
86
+ node.children.each {|inner_elem| check_node(inner_elem, level+1, ctr)} if node.children?
87
+ ctr
88
+ end
89
+
90
+ # Check whether the document has a DocBook default namespace
91
+ def is_docbook?(doc)
92
+ dbns = doc.root.namespaces.default
93
+ (!dbns.nil? && (dbns.href.casecmp(DOCBOOK_NS) == 0))
94
+ end
95
+
96
+ # Check whether the document has a XInclude namespace
97
+ def has_xinclude?(doc)
98
+ ret = false
99
+ doc.root.namespaces.each do |ns|
100
+ if (ns.href.casecmp(XINCLUDE_NS) == 0)
101
+ ret = true
102
+ break
103
+ end
104
+ end
105
+ ret
106
+ end
107
+
108
+ # Searches the XML document for sections and word counts. Returns an
109
+ # array of sections with their word counts.
110
+ #
111
+ def analyze_document(doc)
112
+ # Add a namespace declaration for XPath expressions
113
+ doc.root.namespaces.default_prefix = 'db'
114
+ # Analyze the document starting with the root node
115
+ doc_maps = check_node(doc.root,0,[])
116
+ @sections = []
117
+ section_name = doc_maps[0][:title]
118
+ section_type = doc_maps[0][:name]
119
+ section_ctr = 0
120
+ section_level = 0
121
+ doc_ctr = 0
122
+ #puts doc_maps.inspect
123
+ xms = doc_maps.drop(1)
124
+ # Compute word counts per section
125
+ xms.each do |m|
126
+ if (m[:type] == :para)
127
+ doc_ctr += m[:words]
128
+ section_ctr += m[:words]
129
+ else
130
+ @sections << [section_name,section_ctr,section_level,section_type]
131
+ section_name = m[:title]
132
+ section_ctr = 0
133
+ section_level = m[:level]
134
+ section_type = m[:name]
135
+ end
136
+ end
137
+ @sections << [section_name,section_ctr,section_level,section_type]
138
+ # Put the document word count near the document type
139
+ @sections[0][1] = doc_ctr
140
+ @sections
141
+ end
142
+
143
+ end
@@ -0,0 +1,6 @@
1
+
2
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
3
+
4
+ describe DocbookStatus do
5
+ end
6
+
@@ -0,0 +1,15 @@
1
+
2
+ require File.expand_path(
3
+ File.join(File.dirname(__FILE__), %w[.. lib docbook_status]))
4
+
5
+ Spec::Runner.configure do |config|
6
+ # == Mock Framework
7
+ #
8
+ # RSpec uses it's own mocking framework by default. If you prefer to
9
+ # use mocha, flexmock or RR, uncomment the appropriate line:
10
+ #
11
+ # config.mock_with :mocha
12
+ # config.mock_with :flexmock
13
+ # config.mock_with :rr
14
+ end
15
+
@@ -0,0 +1,14 @@
1
+ <?xml version="1.0" encoding="utf-8" ?>
2
+ <book xmlns="http://docbook.org/ns/docbook"
3
+ xmlns:xi="http://www.w3.org/2001/XInclude"
4
+ version="5.0">
5
+ <title>B1</title>
6
+ <chapter>
7
+ <title>C1</title>
8
+ <para>
9
+ Dies ist ein Test .. Dies ist ein Test.
10
+ In den Jahren 1900-1901 geschahen viele Überfälle von O`Reillys.
11
+ </para>
12
+ </chapter>
13
+ <xi:include href="chapter2.xml"/>
14
+ </book>
@@ -0,0 +1,7 @@
1
+ <chapter xmlns="http://docbook.org/ns/docbook" version="5.0">
2
+ <title>C2</title>
3
+ <para>
4
+ Dies ist ein Test .. Dies ist ein Test.
5
+ In den Jahren 1900-1901 geschahen viele Überfälle von O`Reillys.
6
+ </para>
7
+ </chapter>
@@ -0,0 +1,55 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'minitest/spec'
3
+ require 'minitest/autorun'
4
+ require "docbook_status"
5
+
6
+ describe DocbookStatus do
7
+ it "works" do
8
+ true
9
+ end
10
+
11
+ it "complains if the input is not DocBook 5" do
12
+ non5 = XML::Document.string '<?xml version="1.0"?><article/>'
13
+ dbs = DocbookStatus.new()
14
+ status = dbs.is_docbook?(non5)
15
+ status.must_be :==, false
16
+ end
17
+
18
+ it "input is DocBook 5" do
19
+ non5 = XML::Document.string '<?xml version="1.0"?><article xmlns="http://docbook.org/ns/docbook"/>'
20
+ dbs = DocbookStatus.new()
21
+ status = dbs.is_docbook?(non5)
22
+ status.must_be :==, true
23
+ end
24
+
25
+ it "counts correctly" do
26
+ input = <<EOI
27
+ <?xml version="1.0" ?>
28
+ <article xmlns="http://docbook.org/ns/docbook" version="5.0">
29
+ <title>A1</title>
30
+ <section>
31
+ <title>S1</title>
32
+ <para>
33
+ Dies ist ein Test .. Dies ist ein Test.
34
+ In den Jahren 1900-1901 geschahen viele Überfälle von O`Reillys.
35
+ </para>
36
+ </section>
37
+ </article>
38
+ EOI
39
+ dbs = DocbookStatus.new()
40
+ ind = XML::Document.string(input)
41
+ sections = dbs.analyze_document(ind)
42
+ sections.must_equal([['A1', 17, 0, 'article'],['S1', 17, 1, 'section']])
43
+ end
44
+
45
+ it "processes includes" do
46
+ dbs = DocbookStatus.new()
47
+ ind = XML::Document.file('test/fixtures/book.xml')
48
+ if (dbs.has_xinclude?(ind))
49
+ ind.xinclude
50
+ end
51
+ sections = dbs.analyze_document(ind)
52
+ sections.must_equal([['B1', 34, 0, 'book'],['C1', 17, 1, 'chapter'],['C2', 17, 1, 'chapter']])
53
+ end
54
+
55
+ end
data/version.txt ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: docbook_status
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Rainer Volz
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-09-08 00:00:00.000000000 +02:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: bones
17
+ requirement: &2169388760 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: 3.7.1
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: *2169388760
26
+ description: A utility for DocBook authors/publishers showing the document structure
27
+ (sections) and word count of a DocBook project. It is intended to provide an overview
28
+ of a DocBook project's structure and volume while you are writing or editing it.
29
+ email: dev@textmulch.de
30
+ executables:
31
+ - docbook_status
32
+ extensions: []
33
+ extra_rdoc_files:
34
+ - History.txt
35
+ - README.txt
36
+ - bin/docbook_status
37
+ files:
38
+ - .bnsignore
39
+ - Gemfile
40
+ - Gemfile.lock
41
+ - History.txt
42
+ - README.txt
43
+ - Rakefile
44
+ - bin/docbook_status
45
+ - docbook_status.gemspec
46
+ - lib/docbook_status.rb
47
+ - spec/docbook_status_spec.rb
48
+ - spec/spec_helper.rb
49
+ - test/fixtures/book.xml
50
+ - test/fixtures/chapter2.xml
51
+ - test/test_docbook_status.rb
52
+ - version.txt
53
+ has_rdoc: true
54
+ homepage: http://projekte.textmuch.de/docbook_status/
55
+ licenses: []
56
+ post_install_message:
57
+ rdoc_options:
58
+ - --main
59
+ - README.txt
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ! '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ requirements: []
75
+ rubyforge_project: docbook_status
76
+ rubygems_version: 1.6.2
77
+ signing_key:
78
+ specification_version: 3
79
+ summary: A utility for DocBook authors/publishers showing the document structure (sections)
80
+ and word count of a DocBook project.
81
+ test_files:
82
+ - test/test_docbook_status.rb