konjac 0.2.9.5 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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