rwdlanguage 0.01

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.
Files changed (187) hide show
  1. data/Readme.txt +475 -0
  2. data/bin/rwdlanguage +19 -0
  3. data/code/01rwdcore/01rwdcore.rb +29 -0
  4. data/code/01rwdcore/02helptexthashbegin.rb +16 -0
  5. data/code/01rwdcore/03helptexthash.rb +21 -0
  6. data/code/01rwdcore/jumplinkcommand.rb +36 -0
  7. data/code/01rwdcore/openhelpwindow.rb +38 -0
  8. data/code/01rwdcore/returntomain.rb +10 -0
  9. data/code/01rwdcore/rundocuments.rb +10 -0
  10. data/code/01rwdcore/runeditconfiguration.rb +10 -0
  11. data/code/01rwdcore/runhelpabout.rb +15 -0
  12. data/code/01rwdcore/runopentinkerdocument.rb +7 -0
  13. data/code/01rwdcore/runtab.rb +15 -0
  14. data/code/01rwdcore/rwdtinkerversion.rb +22 -0
  15. data/code/01rwdcore/rwdwindowreturn.rb +9 -0
  16. data/code/01rwdcore/selectiontab.rb +11 -0
  17. data/code/01rwdcore/setuphelpaboutoptions.rb +15 -0
  18. data/code/01rwdcore/setuptinkerdocuments.rb +7 -0
  19. data/code/01rwdcore/test_cases.rb +158 -0
  20. data/code/01rwdcore/test_harness.rb +20 -0
  21. data/code/01rwdcore/uploadreturns.rb +65 -0
  22. data/code/dd0viewphoto/dd0viewphoto.rb +5 -0
  23. data/code/superant.com.language/0uninstallapplet.rb +22 -0
  24. data/code/superant.com.language/googlelang.rb +25 -0
  25. data/code/superant.com.language/helptexthashload.rb +22 -0
  26. data/code/superant.com.language/loadconfigurationrecord.rb +22 -0
  27. data/code/superant.com.language/loadconfigurationvariables.rb +14 -0
  28. data/code/superant.com.language/openhelpwindow.rb +24 -0
  29. data/code/superant.com.language/rubySteak.rb +40 -0
  30. data/code/superant.com.language/runappletwindow.rb +12 -0
  31. data/code/superant.com.language/runrwdshellwindow.rb +12 -0
  32. data/code/superant.com.language/runrwdwordsbackwindow.rb +10 -0
  33. data/code/superant.com.language/rwdtinkerversion.rb +10 -0
  34. data/code/superant.com.language/saveconfigurationrecord.rb +20 -0
  35. data/code/superant.com.language/test_cases.rb +20 -0
  36. data/code/superant.com.rwdtinkerbackwindow/changelocale.rb +84 -0
  37. data/code/superant.com.rwdtinkerbackwindow/diagnostictab.rb +19 -0
  38. data/code/superant.com.rwdtinkerbackwindow/initiateapplets.rb +169 -0
  39. data/code/superant.com.rwdtinkerbackwindow/installgemapplet.rb +38 -0
  40. data/code/superant.com.rwdtinkerbackwindow/installremotegem.rb +20 -0
  41. data/code/superant.com.rwdtinkerbackwindow/listgemdirs.rb +12 -0
  42. data/code/superant.com.rwdtinkerbackwindow/listgemzips.rb +55 -0
  43. data/code/superant.com.rwdtinkerbackwindow/listinstalledfiles.rb +14 -0
  44. data/code/superant.com.rwdtinkerbackwindow/listzips.rb +37 -0
  45. data/code/superant.com.rwdtinkerbackwindow/loadconfigurationrecord.rb +24 -0
  46. data/code/superant.com.rwdtinkerbackwindow/loadconfigurationvariables.rb +14 -0
  47. data/code/superant.com.rwdtinkerbackwindow/network.rb +87 -0
  48. data/code/superant.com.rwdtinkerbackwindow/openappletname.rb +19 -0
  49. data/code/superant.com.rwdtinkerbackwindow/openhelpwindowtinkerwin2.rb +40 -0
  50. data/code/superant.com.rwdtinkerbackwindow/remotegemlist.rb +24 -0
  51. data/code/superant.com.rwdtinkerbackwindow/removeapplet.rb +46 -0
  52. data/code/superant.com.rwdtinkerbackwindow/removeappletvariables.rb +52 -0
  53. data/code/superant.com.rwdtinkerbackwindow/runremoteinstall.rb +11 -0
  54. data/code/superant.com.rwdtinkerbackwindow/runrwdtinkerbackwindow.rb +15 -0
  55. data/code/superant.com.rwdtinkerbackwindow/rwdtinkerwin2version.rb +13 -0
  56. data/code/superant.com.rwdtinkerbackwindow/saveconfigurationrecord.rb +19 -0
  57. data/code/superant.com.rwdtinkerbackwindow/showlocaleoptions.rb +9 -0
  58. data/code/superant.com.rwdtinkerbackwindow/viewappletcontents.rb +23 -0
  59. data/code/superant.com.rwdtinkerbackwindow/viewgemappletcontents.rb +24 -0
  60. data/code/superant.com.rwdtinkerbackwindow/viewlogfile.rb +16 -0
  61. data/code/superant.com.thesaurus/clearhttpview3.rb +9 -0
  62. data/code/superant.com.thesaurus/listwordlookup.rb +37 -0
  63. data/code/superant.com.thesaurus/runappletwindow.rb +12 -0
  64. data/code/superant.com.words/dictlookup.rb +20 -0
  65. data/code/superant.com.words/runrwdwordsbackwindow.rb +10 -0
  66. data/code/superant.com.words/rwdtinkerversion.rb +10 -0
  67. data/code/zz0applicationend/zz0end.rb +5 -0
  68. data/configuration/rwdtinker.dist +15 -0
  69. data/configuration/rwdwlanguage.dist +21 -0
  70. data/configuration/tinkerwin2variables.dist +23 -0
  71. data/gui/00coreguibegin/applicationguitop.rwd +9 -0
  72. data/gui/frontwindow0/cc0openphoto.rwd +22 -0
  73. data/gui/frontwindowselections/00selectiontabbegin.rwd +11 -0
  74. data/gui/frontwindowselections/jumplinkcommands.rwd +15 -0
  75. data/gui/frontwindowselections/wwselectionend.rwd +3 -0
  76. data/gui/frontwindowtdocuments/00documentbegin.rwd +6 -0
  77. data/gui/frontwindowtdocuments/tinkerdocuments.rwd +14 -0
  78. data/gui/frontwindowtdocuments/zzdocumentend.rwd +8 -0
  79. data/gui/helpaboutbegin/zzzrwdlasttab.rwd +6 -0
  80. data/gui/helpaboutbegin/zzzzhelpscreenstart.rwd +3 -0
  81. data/gui/helpaboutbegin/zzzzzzhelpabouttab.rwd +15 -0
  82. data/gui/helpaboutzend/helpscreenend.rwd +3 -0
  83. data/gui/helpaboutzend/zhelpscreenstart2.rwd +3 -0
  84. data/gui/helpaboutzend/zzzzhelpabout2.rwd +15 -0
  85. data/gui/helpaboutzend/zzzzhelpscreen2end.rwd +3 -0
  86. data/gui/tinkerbackwindows/superant.com.language/1appname.rwd +4 -0
  87. data/gui/tinkerbackwindows/superant.com.language/22google.rwd +38 -0
  88. data/gui/tinkerbackwindows/superant.com.language/44germany.rwd +19 -0
  89. data/gui/tinkerbackwindows/superant.com.language/67viewconfiguration.rwd +27 -0
  90. data/gui/tinkerbackwindows/superant.com.language/77jumplinkcommands.rwd +17 -0
  91. data/gui/tinkerbackwindows/superant.com.language/z9end.rwd +6 -0
  92. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/1appname.rwd +5 -0
  93. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/40rwdlistzips.rwd +41 -0
  94. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/45installremotezip.rwd +44 -0
  95. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/50rwdlistapplets.rwd +44 -0
  96. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/60editconfiguration.rwd +30 -0
  97. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/70rwddiagnostics.rwd +29 -0
  98. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/75rwdlogfile.rwd +20 -0
  99. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/80localechanger.rwd +17 -0
  100. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/81jumplinkcommands.rwd +17 -0
  101. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/9backend.rwd +6 -0
  102. data/gui/tinkerbackwindows/superant.com.tinkerhelpwindow/1appname.rwd +31 -0
  103. data/gui/tinkerbackwindows/superant.com.tinkerhelpwindow/9end.rwd +4 -0
  104. data/gui/tinkerbackwindows/superant.com.versionwindow/1appname.rwd +19 -0
  105. data/gui/tinkerbackwindows/superant.com.versionwindow/helpaboutwindow.rwd +17 -0
  106. data/gui/tinkerbackwindows/superant.com.words/1appname.rwd +4 -0
  107. data/gui/tinkerbackwindows/superant.com.words/1dictionary.rwd +19 -0
  108. data/gui/tinkerbackwindows/superant.com.words/4thesaurus.rwd +36 -0
  109. data/gui/tinkerbackwindows/superant.com.words/77jumplinkcommands.rwd +17 -0
  110. data/gui/tinkerbackwindows/superant.com.words/z9end.rwd +6 -0
  111. data/gui/zzcoreguiend/yy9rwdend.rwd +4 -0
  112. data/init.rb +179 -0
  113. data/installed/rwdwlanguage.inf +24 -0
  114. data/installed/temp.rb +1 -0
  115. data/lang/en/rwdcore/en.po +197 -0
  116. data/lang/en/rwdlanguage/en.po +32 -0
  117. data/lang/es/rwdcore/es.po +184 -0
  118. data/lang/es/rwdlanguage/en.po +32 -0
  119. data/lang/fr/rwdcore/fr.po +169 -0
  120. data/lang/fr/rwdlanguage/en.po +32 -0
  121. data/lang/hi/rwdcore/hi.po +173 -0
  122. data/lang/hi/rwdlanguage/en.po +32 -0
  123. data/lang/ja/rwdcore/ja.po +171 -0
  124. data/lang/ja/rwdlanguage/en.po +32 -0
  125. data/lang/nl/rwdcore/nl.po +169 -0
  126. data/lang/nl/rwdlanguage/en.po +32 -0
  127. data/lib/dict.rb +438 -0
  128. data/lib/g_translate.rb +43 -0
  129. data/lib/g_translate/client.rb +84 -0
  130. data/lib/g_translate/translator.rb +57 -0
  131. data/lib/ger-eng.txt +111283 -0
  132. data/lib/oothesaurus.rb +76 -0
  133. data/lib/rconftool.rb +387 -0
  134. data/lib/rwd/browser.rb +123 -0
  135. data/lib/rwd/ftools.rb +174 -0
  136. data/lib/rwd/mime.rb +328 -0
  137. data/lib/rwd/net.rb +877 -0
  138. data/lib/rwd/ruby.rb +889 -0
  139. data/lib/rwd/rwd.rb +1425 -0
  140. data/lib/rwd/sgml.rb +236 -0
  141. data/lib/rwd/thread.rb +63 -0
  142. data/lib/rwd/tree.rb +371 -0
  143. data/lib/rwd/xml.rb +101 -0
  144. data/lib/rwdthemes/default.rwd +317 -0
  145. data/lib/rwdthemes/pda.rwd +72 -0
  146. data/lib/rwdthemes/windowslike.rwd +171 -0
  147. data/lib/rwdtinker/rwdcodedir.rb +56 -0
  148. data/lib/rwdtinker/rwdguidir.rb +57 -0
  149. data/lib/rwdtinker/rwdlangdir.rb +60 -0
  150. data/lib/rwdtinker/rwdtinkertools.rb +25 -0
  151. data/lib/zip/ioextras.rb +155 -0
  152. data/lib/zip/stdrubyext.rb +111 -0
  153. data/lib/zip/tempfile_bugfixed.rb +195 -0
  154. data/lib/zip/zip.rb +1847 -0
  155. data/lib/zip/zipfilesystem.rb +609 -0
  156. data/lib/zip/ziprequire.rb +90 -0
  157. data/rwd_files/HowTo_Language.txt +179 -0
  158. data/rwd_files/HowTo_Tinker.txt +515 -0
  159. data/rwd_files/HowTo_TinkerWin2.txt +202 -0
  160. data/rwd_files/Readme.txt +57 -0
  161. data/rwd_files/RubyWebDialogs.html +6 -0
  162. data/rwd_files/Tinkerhelptexthash.txt +84 -0
  163. data/rwd_files/favicon.ico +0 -0
  164. data/rwd_files/log/rwdtinker.log +726 -0
  165. data/rwd_files/rdoc-style.css +175 -0
  166. data/rwd_files/rwdapplications.html +76 -0
  167. data/rwd_files/rwdlanguagehelpfiles.txt +34 -0
  168. data/rwd_files/tinker.png +0 -0
  169. data/rwdconfig.dist +24 -0
  170. data/rwdlanguage.rb +1 -0
  171. data/tests/RubyGauge.rb +179 -0
  172. data/tests/checkdepends.sh +4 -0
  173. data/tests/cleancnf.sh +6 -0
  174. data/tests/makedist-rwdwlanguage.rb +56 -0
  175. data/tests/makedist.rb +66 -0
  176. data/tests/rdep.rb +354 -0
  177. data/tests/totranslate.lang +93 -0
  178. data/zips/rwdwcalc-0.63.zip +0 -0
  179. data/zips/rwdwfoldeditor-0.08.zip +0 -0
  180. data/zips/rwdwhypernote-0.16.zip +0 -0
  181. data/zips/rwdwlanguage-0.01.zip +0 -0
  182. data/zips/rwdwmovies-0.98.zip +0 -0
  183. data/zips/rwdwruby-1.08.zip +0 -0
  184. data/zips/temp.rb +1 -0
  185. data/zips/tinkerbellw-0.04.zip +0 -0
  186. data/zips/wrubyslippers-1.08.zip +0 -0
  187. metadata +246 -0
@@ -0,0 +1,76 @@
1
+
2
+ # The Open Office Thesaurus object. Create a new object with idx file and
3
+ # main database file name and search words with "lookup".
4
+ # Works with OO Thesaurus files 2.x
5
+ # by kesiev at http://www.kesiev.com/
6
+
7
+ class OOThesaurus
8
+
9
+ def dosearch(the,history,word,add,filepathidx,filepathdat)
10
+ a = []
11
+ if add then history.push(word) end
12
+ word=word
13
+ #$itemslist.clear
14
+ rt=the.lookup(word,filepathidx,filepathdat)
15
+ if rt.length>0
16
+ rt.each { |ent|
17
+ ent.each_with_index { |line,i|
18
+ # a=itemslist.append
19
+ a[0]=(i!=0 ? "\t" : "" )+ line
20
+ }
21
+ }
22
+ else
23
+ # a=$itemslist.append
24
+ a[0]="No hits."
25
+ end
26
+ end
27
+
28
+
29
+ def lookup(word,idxfile,datfile)
30
+ Dir.chdir($progdir)
31
+ if $DEBUG
32
+ $stderr.puts "in lookup\n"
33
+ $stderr.puts idxfile.to_s
34
+ end
35
+ seek=-1
36
+ ret=[]
37
+ if File::exist?(idxfile) && File::exist?(datfile)
38
+
39
+ open(idxfile,"r").each { |f|
40
+ f.each { |line|
41
+ line=line.split("|")
42
+ if line[0]==word
43
+ seek=line[1].to_i
44
+ break
45
+ end
46
+ }
47
+ }
48
+ ret=[]
49
+ ret2 = []
50
+ if seek!=-1
51
+ open(datfile,"r") { |a|
52
+ a.seek(seek)
53
+ data=a.gets.split("|")
54
+ data[1].to_i.times {
55
+ ret << a.gets.strip.split("|")
56
+
57
+ }
58
+ }
59
+
60
+ end
61
+ end
62
+
63
+ ret
64
+ end
65
+ end
66
+
67
+
68
+
69
+
70
+ def back(history)
71
+ if word=history.pop then
72
+ #$box.text=word
73
+ dosearch(false)
74
+ end
75
+ end
76
+
data/lib/rconftool.rb ADDED
@@ -0,0 +1,387 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ # Copyright (c) 2005 Brian Candler
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
7
+ # deal in the Software without restriction, including without limitation the
8
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9
+ # sell 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
20
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
+ # IN THE SOFTWARE.
22
+
23
+ ##########################################################################
24
+ # rconftool is a reimplementation of Sam Varshavchik's sysconftool in Ruby.
25
+ # See http://www.courier-mta.org/sysconftool/ for details of the original.
26
+ # Its purpose is to keep configuration files "fresh" when upgrading an
27
+ # application from one version to another, ensuring that all necessary
28
+ # settings are present and obsolete ones removed.
29
+ #
30
+ # rconftool can be called as a library function or from the command line. It
31
+ # can also install groups of files recursively from one directory tree into
32
+ # another.
33
+ ##########################################################################
34
+
35
+ require 'fileutils'
36
+
37
+ module Rconftool
38
+ VERSION = "0.1"
39
+ class NoVersionLine < RuntimeError; end
40
+
41
+ # This module function installs a single source (.dist) file to a target
42
+ # location, having first merged in any compatible settings from the
43
+ # target file if it existed previously [if it does not exist, any settings
44
+ # from 'oldfile' are used instead]
45
+ #
46
+ # If the distfile is not in sysconftool format (i.e. doesn't have a
47
+ # ##VERSION: header within the first 20 lines), then for safety it is only
48
+ # installed if the target file does not already exist. No attempt at data
49
+ # merging is made in that case.
50
+
51
+ def self.install(distfile, targetfile=nil, oldfile=nil, opt={})
52
+ debug = opt[:debug] || $stdout
53
+
54
+ targetfile ||= distfile
55
+ if opt[:strip_regexp]
56
+ targetfile = targetfile.sub(opt[:strip_regexp], '')
57
+ oldfile = oldfile.sub(opt[:strip_regexp], '') if oldfile
58
+ end
59
+ if opt[:add_suffix]
60
+ targetfile = targetfile + opt[:add_suffix]
61
+ oldfile = oldfile + opt[:add_suffix] if oldfile
62
+ end
63
+ raise Errno::EEXIST, "#{distfile}: dist and target filenames are the same" if distfile == targetfile
64
+
65
+ # Read in the source (.dist) file
66
+ begin
67
+ src = ConfigFile.new(distfile)
68
+ rescue NoVersionLine
69
+ # Fallback behaviour when installing a file which is not in sysconftool
70
+ # format: we install the file only if it doesn't already exist
71
+ if File.exist?(targetfile)
72
+ debug << "#{targetfile}: already exists, skipping\n"
73
+ return
74
+ end
75
+ return if opt[:noclobber]
76
+ copyfrom = (oldfile and File.exist?(oldfile)) ? oldfile : distfile
77
+ if File.symlink?(copyfrom)
78
+ File.symlink(File.readlink(copyfrom), targetfile)
79
+ debug << "#{targetfile}: symlink copied from #{copyfrom}\n"
80
+ else
81
+ FileUtils.cp copyfrom, targetfile, :preserve=>true
82
+ debug << "#{targetfile}: copied from #{copyfrom}\n"
83
+ end
84
+ return
85
+ end
86
+
87
+ # OK, so we have a sysconftool file to install. Read in the existing
88
+ # target file, or if that does not exist, the oldfile
89
+ begin
90
+ old = ConfigFile.new
91
+ old.read(targetfile)
92
+ rescue NoVersionLine
93
+ # That's OK; the old target will be renamed to .bak
94
+ rescue Errno::ENOENT
95
+ begin
96
+ target_missing = true
97
+ old.read(oldfile) if oldfile
98
+ rescue Errno::ENOENT, NoVersionLine
99
+ end
100
+ end
101
+
102
+ # Same VERSION? No merge is required
103
+ if src.version == old.version and not opt[:force]
104
+ if target_missing
105
+ FileUtils.cp oldfile, targetfile, :preserve=>true
106
+ debug << "#{targetfile}: same VERSION, copied from #{oldfile}\n"
107
+ return
108
+ end
109
+ debug << "#{targetfile}: same VERSION, no change\n"
110
+ return
111
+ end
112
+
113
+ # Merge in old settings (note: any settings which are in targetfile but
114
+ # not in distfile will be silently dropped)
115
+ debug << "#{targetfile}:\n"
116
+ src.settings[1..-1].each do |src_setting|
117
+ name = src_setting.name
118
+ old_setting = old[name]
119
+ unless old_setting
120
+ debug << " #{name}: new\n"
121
+ next
122
+ end
123
+ if old_setting.version == src_setting.version
124
+ if $DEBUG
125
+ $stderr.puts "old setting: #{old_setting.version}"
126
+ $stderr.puts "src setting: #{src_setting.version}"
127
+ end
128
+ debug << " #{name}: unchanged\n"
129
+ src_setting.add_comment("\n DEFAULT SETTING from #{distfile}:\n")
130
+ src_setting.add_comment(src_setting.content)
131
+ src_setting.content = old_setting.content
132
+ next
133
+ end
134
+ # Otherwise, must install updated setting and comment out
135
+ # the current setting for reference
136
+ debug << " #{name}: UPDATED\n"
137
+ src_setting.add_comment("\n Previous setting (inserted by rconftool):\n\n")
138
+ src_setting.add_comment(old_setting.content)
139
+ end
140
+
141
+ return if opt[:noclobber]
142
+
143
+ # Write out the new file and carry forward permissions
144
+ begin
145
+ tempfile = targetfile+".new#{$$}"
146
+ src.write(tempfile)
147
+ st = File.stat(distfile)
148
+ begin
149
+ File.chown(st.uid, st.gid, tempfile)
150
+ rescue Errno::EPERM
151
+ end
152
+ File.chmod(st.mode, tempfile)
153
+ File.rename(targetfile, targetfile+".bak") unless target_missing
154
+ File.rename(tempfile, targetfile)
155
+ rescue
156
+ File.delete(tempfile) rescue nil
157
+ raise
158
+ end
159
+ end
160
+
161
+ HEADER_ID = '__header__'
162
+
163
+ # Object to represent a single setting
164
+
165
+ class Setting
166
+ attr_reader :name, :version
167
+ attr_accessor :content
168
+
169
+ def initialize(name, version)
170
+ @name = name.gsub(/\s+/,'')
171
+ @version = version.gsub(/s+/,'')
172
+ @comment = ""
173
+ @content = ""
174
+ @in_content = false
175
+ end
176
+ def <<(str)
177
+ @in_content = true unless /\A#/ =~ str
178
+ if @in_content
179
+ @content << str
180
+ else
181
+ @comment << str
182
+ end
183
+ end
184
+ # Add text to 'comment' portion of setting, prefixing each line with '#'
185
+ def add_comment(str)
186
+ @comment << str.gsub(/^/,'#')
187
+ end
188
+ def to_s
189
+ return "#{@comment}#{@content}" if @name == HEADER_ID
190
+ return "##NAME: #{@name}:#{@version}\n#{@comment}#{@content}"
191
+ end
192
+ end # class Setting
193
+
194
+ # Object to represent an entire configuration file. It consists of
195
+ # an array of Setting objects, with the first one having a special name
196
+ # (__header__). We also keep a hash of setting name => setting object
197
+ # to enable us to find a particular setting quickly.
198
+
199
+ class ConfigFile
200
+ attr_reader :version, :settings
201
+
202
+ def initialize(filename=nil)
203
+ read(filename) if filename
204
+ end
205
+
206
+ # fetch a setting by name
207
+ def [](item)
208
+ @settings_hash[item]
209
+ end
210
+
211
+ def read(filename)
212
+ @version = nil
213
+ curr_setting = Setting.new(HEADER_ID,'')
214
+ @settings = [curr_setting]
215
+ @settings_hash = {}
216
+
217
+ File.open(filename) do |f|
218
+ # VERSION header must occur within first 20 lines
219
+ 20.times do
220
+ line = f.gets
221
+ break unless line
222
+ linetmp = line.chop + "\r\n"
223
+ curr_setting << linetmp
224
+ if line =~ /\A##VERSION:/
225
+ @version = line.chop
226
+ break
227
+ end
228
+ end
229
+ raise NoVersionLine, "#{filename}: No VERSION line found" unless @version
230
+
231
+ while line = f.gets
232
+ unless line =~ /\A##NAME:(.*):(.*)/
233
+ linetmp = line.chop + "\r\n"
234
+ curr_setting << linetmp
235
+ next
236
+ end
237
+ curr_setting = Setting.new($1,$2)
238
+ @settings << curr_setting
239
+ @settings_hash[curr_setting.name] = curr_setting
240
+ end
241
+ end
242
+ end
243
+
244
+ def write(filename)
245
+ File.open(filename,"w") do |f|
246
+ @settings.each do |s|
247
+ stmp = s.to_s.chop + "\r\n"
248
+ f << stmp
249
+ end
250
+ end
251
+ end
252
+ end # class ConfigFile
253
+
254
+ # Yield directory contents recursively, without doing chdir(). Note
255
+ # that yielded pathnames are relative to the base directory given;
256
+ # so that, for example, you can simulate 'cp -r /foo/bar/ /baz/' by
257
+ # recurse_dir("/foo/bar") { |n| copy("/foo/bar/"+n,"/baz/"+n) unless
258
+ # File.directory?("/foo/bar/"+n) }
259
+ # Current behaviour is that if a directory is a symlink, we follow it.
260
+ # (Perhaps the block we yield should return true/false?)
261
+
262
+ def self.recurse_dir(base)
263
+ base = base+File::SEPARATOR unless base[-1,1] == File::SEPARATOR
264
+ dirs = ['']
265
+ while dir = dirs.pop
266
+ yield dir unless dir == ''
267
+ Dir.foreach(base+dir) do |n|
268
+ next if n == '.' || n == '..'
269
+ target = dir + n
270
+ if File.directory?(base+target)
271
+ dirs << target+File::SEPARATOR
272
+ next
273
+ end
274
+ yield target
275
+ end
276
+ end
277
+ end
278
+
279
+ class Processor
280
+ attr_reader :o
281
+
282
+ # Parse command-line options and set the @o options hash
283
+
284
+ def initialize(argv=nil)
285
+ require 'optparse'
286
+
287
+ @o = { :strip_regexp => /\.dist\z/ }
288
+ return unless argv
289
+ opts = OptionParser.new do |opts|
290
+ opts.banner = "rconftool version #{VERSION}"
291
+ opts.separator "Usage: #{$0} [options]"
292
+ opts.separator ""
293
+ opts.separator "Specific options:"
294
+
295
+ opts.on("-n", "--noclobber", "Dummy run") do
296
+ @o[:noclobber] = true
297
+ end
298
+ opts.on("-f", "--force", "Update files even if VERSION is same") do
299
+ @o[:force] = true
300
+ end
301
+ opts.on("-q", "--quiet", "No progress reporting") do
302
+ @o[:debug] = ""
303
+ end
304
+ opts.on("--targetdir DIR", "Where to write merged config files") do |dir|
305
+ @o[:targetdir] = dir
306
+ end
307
+ opts.on("--olddir DIR", "If file does not exist in targetdir,",
308
+ "try to merge from here") do |dir|
309
+ @o[:olddir] = dir
310
+ end
311
+ opts.on("--[no-]recursive", "Traverse directories recursively") do |v|
312
+ @o[:recursive] = v
313
+ end
314
+ opts.on("--strip-suffix FOO", "Remove suffix FOO from target filenames",
315
+ "(default .dist)") do |suffix|
316
+ @o[:strip_regexp] = /#{Regexp.escape(suffix)}\z/
317
+ end
318
+ opts.on("-a", "--add-suffix FOO", "Add suffix FOO to target filenames") do |suffix|
319
+ @o[:add_suffix] = suffix
320
+ end
321
+
322
+ opts.on_tail("-?", "--help", "Show this message") do
323
+ puts opts
324
+ exit
325
+ end
326
+ end
327
+ opts.parse!(argv)
328
+ end
329
+
330
+ # Process a list of files, [src1,src2,...]. If recursive mode has been
331
+ # enabled, then subdirectories of destdir are created as necessary
332
+ # when 'src' is a directory, and the mode/ownership of these newly
333
+ # created directories is copied from the original.
334
+
335
+ def run(files)
336
+ done_work = false
337
+ files.each do |f|
338
+ if not File.directory?(f)
339
+ dst = old = nil
340
+ dst = @o[:targetdir] + File::SEPARATOR + File.basename(f) if @o[:targetdir]
341
+ old = @o[:olddir] + File::SEPARATOR + File.basename(f) if @o[:olddir]
342
+ Rconftool::install(f, dst, old, @o)
343
+ elsif not @o[:recursive]
344
+ raise Errno::EISDIR, "#{f} (not copied). Need --recursive?"
345
+ else
346
+ Rconftool::recurse_dir(f) do |nf|
347
+ src = f + File::SEPARATOR + nf
348
+ dst = old = nil
349
+ dst = @o[:targetdir] + File::SEPARATOR + nf if @o[:targetdir]
350
+ old = @o[:olddir] + File::SEPARATOR + nf if @o[:olddir]
351
+ if File.directory?(src)
352
+ if dst and not File.directory?(dst)
353
+ orig = File.stat(src)
354
+ Dir.mkdir(dst, orig.mode)
355
+ begin
356
+ File.chown(orig.uid, orig.gid, dst)
357
+ rescue Errno::EPERM
358
+ end
359
+ end
360
+ else
361
+ Rconftool::install(src, dst, old, @o)
362
+ end
363
+ end
364
+ end
365
+ done_work = true
366
+ end
367
+ unless done_work
368
+ $stderr.puts "Usage: #{$0} [options] src1 src2 ...\n"+
369
+ "Try #{$0} --help for more information\n"
370
+ exit 1
371
+ end
372
+ end
373
+ end # class Processor
374
+
375
+ end # module Rconftool
376
+
377
+ # Run from command line?
378
+ if __FILE__ == $0
379
+
380
+ begin
381
+ s = Rconftool::Processor.new(ARGV)
382
+ s.run(ARGV)
383
+ rescue Exception => e
384
+ $stderr.puts "#{$0}: #{e}"
385
+ end
386
+
387
+ end