konjac 0.2.9.5 → 0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,11 @@
1
+ # coding: utf-8
2
+ module Konjac
3
+ module Office
4
+ module Mac
5
+ autoload :Excel, "konjac/office/mac/excel"
6
+ autoload :PowerPoint, "konjac/office/mac/power_point"
7
+ autoload :Shared, "konjac/office/mac/shared"
8
+ autoload :Word, "konjac/office/mac/word"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,73 @@
1
+ # coding: utf-8
2
+ module Konjac
3
+ module Office
4
+ module Mac
5
+ class Excel < Shared
6
+ def initialize(path = nil)
7
+ super "Microsoft Excel", path
8
+ @strippable = //
9
+ @delimiter = "\r"
10
+ @parse_order = [:sheet, :row, :cell]
11
+ find 1, 1, 1
12
+ end
13
+
14
+ # Retrieves the active document and caches it
15
+ def active_document
16
+ @active_document ||= @application.active_workbook
17
+ end
18
+
19
+ def write(text, *args)
20
+ if args.empty?
21
+ @current.formula.set text
22
+ else
23
+ opts = parse_args(*args)
24
+ @document.sheets[opts[:sheet]]
25
+ .rows[opts[:row]]
26
+ .cells[opts[:cell]].formula.set text
27
+ end
28
+ end
29
+
30
+ # Creates a dump of the spreadsheet's data in Tag form
31
+ def data
32
+ tags = []
33
+ @document.sheets.get.each_with_index do |sheet, s|
34
+ sheet.used_range.rows.get.each_with_index do |row, r|
35
+ row.cells.get.each_with_index do |cell, c|
36
+ temp = Tag.new
37
+ temp.indices = [s + 1, r + 1, c + 1]
38
+ temp.removed = temp.added = read(s + 1, r + 1, c + 1)
39
+ tags << temp unless temp.blank?
40
+ end
41
+ end
42
+ end
43
+ tags
44
+ end
45
+
46
+ # Finds the paragraph indicated by the provided index
47
+ def find(*args)
48
+ unless args.empty?
49
+ @indices = args
50
+ opts = parse_args(*args)
51
+ @current = @document.sheets[opts[:sheet]]
52
+ .rows[opts[:row]]
53
+ .cells[opts[:cell]]
54
+ end
55
+
56
+ @current.formula.get
57
+ end
58
+
59
+ # Retrieves the number of cells in the document. Note that this method
60
+ # fetches all row and column elements and can thus be very expensive for
61
+ # large spreadsheets.
62
+ def size
63
+ @document.sheets.inject(0) do |result, sheet|
64
+ range = sheet.used_range
65
+ result += range.rows.get.size * range.columns.get.size
66
+ end
67
+ end
68
+ alias :length :size
69
+ end
70
+ end
71
+ end
72
+ end
73
+
@@ -0,0 +1,68 @@
1
+ # coding: utf-8
2
+ module Konjac
3
+ module Office
4
+ module Mac
5
+ class PowerPoint < Shared
6
+ def initialize(path = nil)
7
+ super "Microsoft PowerPoint", path
8
+ @strippable = //
9
+ @delimiter = "\r"
10
+ @parse_order = [:slide, :shape]
11
+ find 1, 1
12
+ end
13
+
14
+ # Retrieves the active document and caches it
15
+ def active_document
16
+ @active_document ||= @application.active_presentation
17
+ end
18
+
19
+ def write(text, *args)
20
+ if args.empty?
21
+ @current.text_frame.text_range.content.set text
22
+ else
23
+ opts = parse_args(*args)
24
+ @document.slides[opts[:slide]]
25
+ .shapes[opts[:shape]].text_frame.text_range.content.set text
26
+ end
27
+ end
28
+
29
+ # Creates a dump of the spreadsheet's data in Tag form
30
+ def data
31
+ tags = []
32
+ @document.slides.get.each_with_index do |slide, sl|
33
+ slide.shapes.get.each_with_index do |shape, sh|
34
+ temp = Tag.new
35
+ temp.indices = [sl + 1, sh + 1]
36
+ temp.removed = temp.added = read(sl + 1, sh + 1)
37
+ tags << temp unless temp.blank?
38
+ end
39
+ end
40
+ tags
41
+ end
42
+
43
+ # Finds the paragraph indicated by the provided index
44
+ def find(*args)
45
+ unless args.empty?
46
+ @indices = args
47
+ opts = parse_args(*args)
48
+ @current = @document.slides[opts[:slide]]
49
+ .shapes[opts[:shape]]
50
+ end
51
+
52
+ @current.text_frame.text_range.content.get
53
+ end
54
+
55
+ # Retrieves the number of cells in the document. Note that this method
56
+ # fetches all row and column elements and can thus be very expensive for
57
+ # large spreadsheets.
58
+ def size
59
+ end
60
+ alias :length :size
61
+
62
+ def delimiter(type = nil)
63
+ "\r"
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,36 @@
1
+ # coding: utf-8
2
+ require "appscript"
3
+
4
+ module Konjac
5
+ module Office
6
+ module Mac
7
+ class Shared < Generic
8
+ def initialize(app_name, path = nil)
9
+ @application = Appscript.app(app_name)
10
+ super path
11
+ end
12
+
13
+ def open(path)
14
+ @application.open path
15
+ end
16
+
17
+ # Retrieves the POSIX path of the document
18
+ def path
19
+ @path ||= posix_path(@document.full_name.get)
20
+ end
21
+
22
+ private
23
+
24
+ # Converts an HFS (Mac) path to a POSIX path
25
+ def posix_path(hfs_path)
26
+ %x[osascript -e 'POSIX path of "#{hfs_path}"'].chomp
27
+ end
28
+
29
+ # Converts a POSIX path to an HFS (Mac) path
30
+ def hfs_path(posix_path)
31
+ %x[osascript -e '(POSIX file "#{posix_path}") as string'].chomp
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,114 @@
1
+ # coding: utf-8
2
+ module Konjac
3
+ module Office
4
+ module Mac
5
+ class Word < Shared
6
+ def initialize(path = nil)
7
+ super "Microsoft Word", path
8
+ @strippable = /[\r\n\a]+$/
9
+ @index = 1
10
+ @current = @document.paragraphs[@index]
11
+ @parse_order = [:paragraph]
12
+ end
13
+
14
+ # Retrieves the active document and caches it
15
+ def active_document
16
+ @active_document ||= @application.active_document
17
+ end
18
+
19
+ def write(text, *args)
20
+ opts = super(text, *args)
21
+ if opts[:type].nil? || opts[:type].empty?
22
+ select opts
23
+ @application.selection.type_text :text => text
24
+ else
25
+ @document.shapes[opts[:paragraph]].text_frame.text_range.content.set text
26
+ end
27
+ end
28
+
29
+ # Creates a dump of the document's data in Tag form
30
+ def data
31
+ @index = 1
32
+ @current = @document.paragraphs[@index]
33
+
34
+ tags = []
35
+
36
+ # An open-ended loop is necessary because requesting a paragraphs
37
+ # enumerator will retrieve all paragraphs from the document,
38
+ # potentially consuming a large amount of memory and freezing Word
39
+ loop do
40
+ temp = Tag.new
41
+ temp.indices = [@index]
42
+ temp.removed = temp.added = read
43
+ tags << temp unless temp.blank?
44
+ break if succ.nil?
45
+ end
46
+
47
+ # TODO: I should optimize this later like above, to prevent large
48
+ # shapes from getting out of hand
49
+ @document.shapes.get.each_with_index do |shape, index|
50
+ temp = Tag.new
51
+ temp.indices = [index + 1]
52
+ temp.removed = temp.added =
53
+ clean(shape.text_frame.text_range.content.get)
54
+ temp.type = :shape
55
+ tags << temp unless temp.blank?
56
+ end
57
+
58
+ tags
59
+ end
60
+
61
+ # Finds the paragraph indicated by the provided index
62
+ def find(*args)
63
+ unless args.empty? || args.nil?
64
+ opts = parse_args(*args)
65
+ if (opts[:type].nil? || opts[:type].empty?) && !opts[:paragraph].nil?
66
+ @index = opts[:paragraph]
67
+ @current = @document.paragraphs[opts[:paragraph]]
68
+ elsif opts[:type] == :shape
69
+ return @document.shapes[opts[:paragraph]].text_frame.text_range.content.get
70
+ end
71
+ end
72
+
73
+ @current.text_object.content.get
74
+ end
75
+
76
+ # Retrieves the number of paragraphs in the document. Note that this
77
+ # method fetches all paragraphs elements and can thus be very expensive
78
+ # for large documents.
79
+ def size
80
+ @document.paragraphs.get.size
81
+ end
82
+ alias :length :size
83
+
84
+ # Goes to the next paragraph
85
+ def succ
86
+ @index += 1
87
+ @current = @current.next_paragraph
88
+ rescue
89
+ @index -= 1
90
+ nil
91
+ end
92
+ alias :next :succ
93
+
94
+ # Selects the paragraph indicated by an indicated, or +nil+ to select
95
+ # the current paragraph
96
+ def select(*args)
97
+ opts = parse_args(*args)
98
+ find opts
99
+ para_start = @current.text_object.start_of_content.get
100
+ para_end = @current.text_object.end_of_content.get
101
+ range = active_document.create_range(:start => para_start,
102
+ :end_ => para_end)
103
+
104
+ # Move in end of range by length of stripped content less end of table
105
+ # mark
106
+ strip_size = range.content.get[@strippable].gsub(/\a/, "").size
107
+ range = active_document.create_range(:start => para_start,
108
+ :end_ => para_end - strip_size)
109
+ range.select
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,53 @@
1
+ module Konjac
2
+ module Office
3
+ # A module for determining what OS we're using
4
+ module OS
5
+ class << self
6
+ # Override string output
7
+ def to_s
8
+ RbConfig::CONFIG["host_os"]
9
+ end
10
+
11
+ # OS is a version of Mac
12
+ def mac?
13
+ @mac ||= is? /mac|darwin/
14
+ end
15
+
16
+ # OS is a version of Linux
17
+ def linux?
18
+ @linux ||= is? /linux|cygwin/
19
+ end
20
+
21
+ # OS is a version of Windows
22
+ def windows?
23
+ @windows ||= is? /mswin|^win|mingw/
24
+ end
25
+
26
+ # OS is POSIX (well, actually, this makes the somewhat bad assumption
27
+ # that non-Windows OSes are POSIX)
28
+ def posix?
29
+ !windows?
30
+ end
31
+
32
+ # Throws a message if the computer is using a command restricted to Macs
33
+ def not_a_mac
34
+ if mac?
35
+ return false
36
+ else
37
+ puts I18n.t(:mac_only)
38
+ return true
39
+ end
40
+ end
41
+
42
+
43
+ private
44
+
45
+ # Test whether the +host_os+ configuration parameter matches a specified
46
+ # regular expression
47
+ def is?(match)
48
+ match === RbConfig::CONFIG["host_os"]
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,91 @@
1
+ # coding: utf-8
2
+ module Konjac
3
+ module Office
4
+ class Tag
5
+ attr_accessor :indices, :removed, :added, :type
6
+
7
+ def initialize
8
+ @indices = nil
9
+ @removed = []
10
+ @added = []
11
+ @type = nil
12
+ end
13
+
14
+ # Whether the tag has changed content
15
+ def changed?
16
+ @removed != @added
17
+ end
18
+
19
+ # Determines whether the tag is blank, that is, if it has no +indices+ or
20
+ # both +removed+ and +added+ are empty
21
+ def blank?
22
+ @indices.nil? || (@removed.join.empty? && @added.join.empty?)
23
+ end
24
+
25
+ # Converts the tag to a string
26
+ def to_s
27
+ <<-eos
28
+ @@ #{@type.nil? ? "" : "#{@type} "}#{@indices.join(",")} @@
29
+ -#{@removed.join("\n-")}
30
+ +#{@added.join("\n+")}
31
+ eos
32
+ end
33
+
34
+ # Whether the tag's content if for the default kind of object
35
+ def default?
36
+ @type.nil?
37
+ end
38
+
39
+ # Whether the tag's content if for a special kind of object
40
+ def special?
41
+ !!@type
42
+ end
43
+
44
+ class << self
45
+ TAG_MATCHES = {
46
+ :header => /^(?:---|\+\+\+)/,
47
+ :comment => /^\@\@ ([a-z]*) ?([\d, ]+) \@\@$/i,
48
+ :removed => /^-(.*)/,
49
+ :added => /^\+(.*)/,
50
+ }
51
+
52
+ # Loads the tags for the specified document path or the tags file itself
53
+ def load(path)
54
+ tags = []
55
+ temp = Tag.new
56
+ File.read("#{path.sub(/\.diff$/, "")}.diff").each_line do |line|
57
+ case line
58
+ when TAG_MATCHES[:header]
59
+ when TAG_MATCHES[:comment]
60
+ unless temp.blank?
61
+ tags << temp
62
+ temp = Tag.new
63
+ end
64
+ temp.type = $1.to_sym unless $1.nil?
65
+ temp.indices = $2.scan(/\d+/).map(&:to_i) # this changes $~
66
+ when TAG_MATCHES[:removed]
67
+ temp.removed << $1
68
+ when TAG_MATCHES[:added]
69
+ temp.added << $1
70
+ end
71
+ end
72
+ tags << temp unless temp.blank?
73
+ tags
74
+ end
75
+
76
+ def dump(tags, path, opts = {})
77
+ original_path = path.sub(/\.diff$/, "")
78
+ diff_path = "#{original_path}.diff"
79
+
80
+ File.open(diff_path, "w") do |file|
81
+ file.puts "--- #{original_path}"
82
+ file.puts "+++ #{original_path}"
83
+ tags.each do |tag|
84
+ file.puts tag.to_s
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end