rwdlanguage 0.01

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