bixbite 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (194) hide show
  1. data/LICENSE +20 -0
  2. data/README.markdown +49 -0
  3. data/VERSION +1 -0
  4. data/bin/bixbite +73 -0
  5. data/lib/bixbite.rb +13 -0
  6. data/lib/bixbite/command.rb +14 -0
  7. data/lib/bixbite/create.rb +76 -0
  8. data/template/Rakefile +25 -0
  9. data/template/assets/bixbite/Rakefile.rb +297 -0
  10. data/template/assets/naturaldocs/NaturalDocs/Config/Languages.txt +286 -0
  11. data/template/assets/naturaldocs/NaturalDocs/Config/Topics.txt +382 -0
  12. data/template/assets/naturaldocs/NaturalDocs/Help/customizinglanguages.html +52 -0
  13. data/template/assets/naturaldocs/NaturalDocs/Help/customizingtopics.html +74 -0
  14. data/template/assets/naturaldocs/NaturalDocs/Help/documenting.html +58 -0
  15. data/template/assets/naturaldocs/NaturalDocs/Help/documenting/reference.html +146 -0
  16. data/template/assets/naturaldocs/NaturalDocs/Help/documenting/walkthrough.html +180 -0
  17. data/template/assets/naturaldocs/NaturalDocs/Help/example/Default.css +528 -0
  18. data/template/assets/naturaldocs/NaturalDocs/Help/example/NaturalDocs.js +204 -0
  19. data/template/assets/naturaldocs/NaturalDocs/Help/examples.css +90 -0
  20. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/background.png +0 -0
  21. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/leftside.png +0 -0
  22. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/logo.png +0 -0
  23. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overbody.png +0 -0
  24. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overbodybg.png +0 -0
  25. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overleftmargin.png +0 -0
  26. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overmenu.png +0 -0
  27. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overmenubg.png +0 -0
  28. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/rightside.png +0 -0
  29. data/template/assets/naturaldocs/NaturalDocs/Help/images/logo.gif +0 -0
  30. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/about.png +0 -0
  31. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/background.png +0 -0
  32. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/bottomleft.png +0 -0
  33. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/bottomright.png +0 -0
  34. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/community.png +0 -0
  35. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/customizing.png +0 -0
  36. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/using.png +0 -0
  37. data/template/assets/naturaldocs/NaturalDocs/Help/index.html +9 -0
  38. data/template/assets/naturaldocs/NaturalDocs/Help/javascript/BrowserStyles.js +77 -0
  39. data/template/assets/naturaldocs/NaturalDocs/Help/javascript/PNGHandling.js +72 -0
  40. data/template/assets/naturaldocs/NaturalDocs/Help/keywords.html +38 -0
  41. data/template/assets/naturaldocs/NaturalDocs/Help/languages.html +32 -0
  42. data/template/assets/naturaldocs/NaturalDocs/Help/menu.html +79 -0
  43. data/template/assets/naturaldocs/NaturalDocs/Help/output.html +84 -0
  44. data/template/assets/naturaldocs/NaturalDocs/Help/running.html +40 -0
  45. data/template/assets/naturaldocs/NaturalDocs/Help/styles.css +290 -0
  46. data/template/assets/naturaldocs/NaturalDocs/Help/styles.html +52 -0
  47. data/template/assets/naturaldocs/NaturalDocs/Help/troubleshooting.html +18 -0
  48. data/template/assets/naturaldocs/NaturalDocs/Info/CSSGuide.txt +947 -0
  49. data/template/assets/naturaldocs/NaturalDocs/Info/File Parsing.txt +83 -0
  50. data/template/assets/naturaldocs/NaturalDocs/Info/HTMLTestCases.pm +269 -0
  51. data/template/assets/naturaldocs/NaturalDocs/Info/Languages.txt +107 -0
  52. data/template/assets/naturaldocs/NaturalDocs/Info/NDMarkup.txt +91 -0
  53. data/template/assets/naturaldocs/NaturalDocs/Info/Symbol Management.txt +59 -0
  54. data/template/assets/naturaldocs/NaturalDocs/Info/images/Logo.png +0 -0
  55. data/template/assets/naturaldocs/NaturalDocs/JavaScript/NaturalDocs.js +836 -0
  56. data/template/assets/naturaldocs/NaturalDocs/License-GPL.txt +341 -0
  57. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/BinaryFile.pm +294 -0
  58. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder.pm +280 -0
  59. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder/Base.pm +348 -0
  60. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder/FramedHTML.pm +345 -0
  61. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder/HTML.pm +398 -0
  62. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder/HTMLBase.pm +3693 -0
  63. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ClassHierarchy.pm +860 -0
  64. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ClassHierarchy/Class.pm +412 -0
  65. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ClassHierarchy/File.pm +157 -0
  66. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ConfigFile.pm +497 -0
  67. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Constants.pm +165 -0
  68. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/DefineMembers.pm +100 -0
  69. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Error.pm +305 -0
  70. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/File.pm +540 -0
  71. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ImageReferenceTable.pm +383 -0
  72. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ImageReferenceTable/Reference.pm +44 -0
  73. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ImageReferenceTable/String.pm +110 -0
  74. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages.pm +1475 -0
  75. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/ActionScript.pm +1473 -0
  76. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Ada.pm +38 -0
  77. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Advanced.pm +828 -0
  78. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Advanced/Scope.pm +95 -0
  79. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Advanced/ScopeChange.pm +70 -0
  80. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Base.pm +832 -0
  81. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/CSharp.pm +1484 -0
  82. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/PLSQL.pm +319 -0
  83. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Pascal.pm +143 -0
  84. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Perl.pm +1370 -0
  85. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Prototype.pm +92 -0
  86. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Prototype/Parameter.pm +87 -0
  87. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Simple.pm +503 -0
  88. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Tcl.pm +219 -0
  89. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Menu.pm +3406 -0
  90. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Menu/Entry.pm +201 -0
  91. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/NDMarkup.pm +76 -0
  92. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Parser.pm +1331 -0
  93. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Parser/JavaDoc.pm +464 -0
  94. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Parser/Native.pm +1060 -0
  95. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Parser/ParsedTopic.pm +253 -0
  96. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Project.pm +1402 -0
  97. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Project/ImageFile.pm +160 -0
  98. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Project/SourceFile.pm +113 -0
  99. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ReferenceString.pm +334 -0
  100. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Settings.pm +1418 -0
  101. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Settings/BuildTarget.pm +66 -0
  102. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB.pm +678 -0
  103. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/Extension.pm +84 -0
  104. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/File.pm +129 -0
  105. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/Item.pm +201 -0
  106. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/ItemDefinition.pm +45 -0
  107. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/WatchedFileDefinitions.pm +159 -0
  108. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/StatusMessage.pm +102 -0
  109. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolString.pm +212 -0
  110. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable.pm +1984 -0
  111. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/File.pm +186 -0
  112. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/IndexElement.pm +522 -0
  113. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/Reference.pm +273 -0
  114. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/ReferenceTarget.pm +97 -0
  115. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/Symbol.pm +428 -0
  116. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/SymbolDefinition.pm +96 -0
  117. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Topics.pm +1319 -0
  118. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Topics/Type.pm +151 -0
  119. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Version.pm +384 -0
  120. data/template/assets/naturaldocs/NaturalDocs/NaturalDocs +400 -0
  121. data/template/assets/naturaldocs/NaturalDocs/NaturalDocs.bat +17 -0
  122. data/template/assets/naturaldocs/NaturalDocs/Styles/Default.css +767 -0
  123. data/template/assets/naturaldocs/NaturalDocs/Styles/Roman.css +765 -0
  124. data/template/assets/naturaldocs/NaturalDocs/Styles/Small.css +763 -0
  125. data/template/assets/utilities/pngout +0 -0
  126. data/template/deploy/public_html/.htaccess +0 -0
  127. data/template/documentation/js/.htaccess +0 -0
  128. data/template/src/html/.htaccess +76 -0
  129. data/template/src/html/css/cmn/global.css +96 -0
  130. data/template/src/html/css/cmn/ie.css +15 -0
  131. data/template/src/html/css/cmn/ie6.css +15 -0
  132. data/template/src/html/images/cmn/.htaccess +0 -0
  133. data/template/src/html/images/tmp/.htaccess +0 -0
  134. data/template/src/html/includes/debug.inc +5 -0
  135. data/template/src/html/includes/footer.inc +52 -0
  136. data/template/src/html/includes/header.inc +61 -0
  137. data/template/src/html/includes/html.inc +3 -0
  138. data/template/src/html/includes/namespace.inc +19 -0
  139. data/template/src/html/includes/page.inc +151 -0
  140. data/template/src/html/index.html +35 -0
  141. data/template/src/html/js/cmn/bootstrap.js +74 -0
  142. data/template/src/html/js/cmn/global.js +142 -0
  143. data/template/src/html/js/cmn/lib/LAB.js +348 -0
  144. data/template/src/html/min/.htaccess +4 -0
  145. data/template/src/html/min/MinifyCLI.php +19 -0
  146. data/template/src/html/min/README.txt +132 -0
  147. data/template/src/html/min/builder/_index.js +242 -0
  148. data/template/src/html/min/builder/bm.js +36 -0
  149. data/template/src/html/min/builder/index.php +182 -0
  150. data/template/src/html/min/builder/ocCheck.php +36 -0
  151. data/template/src/html/min/builder/rewriteTest.js +1 -0
  152. data/template/src/html/min/config.php +187 -0
  153. data/template/src/html/min/groupsConfig.php +34 -0
  154. data/template/src/html/min/index.php +66 -0
  155. data/template/src/html/min/lib/FirePHP.php +1370 -0
  156. data/template/src/html/min/lib/HTTP/ConditionalGet.php +348 -0
  157. data/template/src/html/min/lib/HTTP/Encoder.php +326 -0
  158. data/template/src/html/min/lib/JSMin.php +314 -0
  159. data/template/src/html/min/lib/JSMinPlus.php +1872 -0
  160. data/template/src/html/min/lib/Minify.php +532 -0
  161. data/template/src/html/min/lib/Minify/Build.php +103 -0
  162. data/template/src/html/min/lib/Minify/CSS.php +83 -0
  163. data/template/src/html/min/lib/Minify/CSS/Compressor.php +250 -0
  164. data/template/src/html/min/lib/Minify/CSS/UriRewriter.php +270 -0
  165. data/template/src/html/min/lib/Minify/Cache/APC.php +130 -0
  166. data/template/src/html/min/lib/Minify/Cache/File.php +125 -0
  167. data/template/src/html/min/lib/Minify/Cache/Memcache.php +137 -0
  168. data/template/src/html/min/lib/Minify/ClosureCompiler.php +85 -0
  169. data/template/src/html/min/lib/Minify/CommentPreserver.php +90 -0
  170. data/template/src/html/min/lib/Minify/Controller/Base.php +202 -0
  171. data/template/src/html/min/lib/Minify/Controller/Files.php +78 -0
  172. data/template/src/html/min/lib/Minify/Controller/Groups.php +94 -0
  173. data/template/src/html/min/lib/Minify/Controller/MinApp.php +132 -0
  174. data/template/src/html/min/lib/Minify/Controller/Page.php +82 -0
  175. data/template/src/html/min/lib/Minify/Controller/Version1.php +118 -0
  176. data/template/src/html/min/lib/Minify/HTML.php +245 -0
  177. data/template/src/html/min/lib/Minify/ImportProcessor.php +157 -0
  178. data/template/src/html/min/lib/Minify/Lines.php +131 -0
  179. data/template/src/html/min/lib/Minify/Logger.php +45 -0
  180. data/template/src/html/min/lib/Minify/Packer.php +37 -0
  181. data/template/src/html/min/lib/Minify/Source.php +187 -0
  182. data/template/src/html/min/lib/Minify/YUICompressor.php +139 -0
  183. data/template/src/html/min/lib/Solar/Dir.php +199 -0
  184. data/template/src/html/min/lib/closure-compiler.jar +0 -0
  185. data/template/src/html/min/lib/yuicompressor-2.4.2.jar +0 -0
  186. data/template/src/html/min/utils.php +90 -0
  187. data/template/src/templates/css/template.css +7 -0
  188. data/template/src/templates/js/template.js +72 -0
  189. data/template/src/templates/template.html +18 -0
  190. data/template/src/yaml/config.yml +46 -0
  191. data/template/src/yaml/deploy.yml +35 -0
  192. data/test/bixbite_test.rb +7 -0
  193. data/test/test_helper.rb +10 -0
  194. metadata +278 -0
@@ -0,0 +1,96 @@
1
+ ###############################################################################
2
+ #
3
+ # Package: NaturalDocs::SymbolTable::SymbolDefinition
4
+ #
5
+ ###############################################################################
6
+ #
7
+ # A class representing a symbol definition. This does not store the definition symbol, class, or file.
8
+ #
9
+ ###############################################################################
10
+
11
+ # This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
12
+ # Natural Docs is licensed under the GPL
13
+
14
+ use strict;
15
+ use integer;
16
+
17
+ package NaturalDocs::SymbolTable::SymbolDefinition;
18
+
19
+
20
+ ###############################################################################
21
+ # Group: Implementation
22
+
23
+ #
24
+ # Constants: Members
25
+ #
26
+ # The class is implemented as a blessed arrayref. The following constants are its members.
27
+ #
28
+ # TYPE - The symbol <TopicType>.
29
+ # PROTOTYPE - The symbol's prototype, if applicable. Will be undef otherwise.
30
+ # SUMMARY - The symbol's summary, if applicable. Will be undef otherwise.
31
+ #
32
+ use constant TYPE => 0;
33
+ use constant PROTOTYPE => 1;
34
+ use constant SUMMARY => 2;
35
+ # New depends on the order of the constants.
36
+
37
+
38
+ ###############################################################################
39
+ # Group: Functions
40
+
41
+ #
42
+ # Function: New
43
+ #
44
+ # Creates and returns a new object.
45
+ #
46
+ # Parameters:
47
+ #
48
+ # type - The symbol <TopicType>.
49
+ # prototype - The symbol prototype, if applicable. Undef otherwise.
50
+ # summary - The symbol's summary, if applicable. Undef otherwise.
51
+ #
52
+ sub New #(type, prototype, summary)
53
+ {
54
+ # This depends on the parameter list being the same as the constant order.
55
+
56
+ my $package = shift;
57
+
58
+ my $object = [ @_ ];
59
+ bless $object, $package;
60
+
61
+ return $object;
62
+ };
63
+
64
+
65
+ # Function: Type
66
+ # Returns the definition's <TopicType>.
67
+ sub Type
68
+ { return $_[0]->[TYPE]; };
69
+
70
+ # Function: SetType
71
+ # Changes the <TopicType>.
72
+ sub SetType #(type)
73
+ { $_[0]->[TYPE] = $_[1]; };
74
+
75
+ # Function: Prototype
76
+ # Returns the definition's prototype, or undef if it doesn't have one.
77
+ sub Prototype
78
+ { return $_[0]->[PROTOTYPE]; };
79
+
80
+ # Function: SetPrototype
81
+ # Changes the prototype.
82
+ sub SetPrototype #(prototype)
83
+ { $_[0]->[PROTOTYPE] = $_[1]; };
84
+
85
+ # Function: Summary
86
+ # Returns the definition's summary, or undef if it doesn't have one.
87
+ sub Summary
88
+ { return $_[0]->[SUMMARY]; };
89
+
90
+ # Function: SetSummary
91
+ # Changes the summary.
92
+ sub SetSummary #(summary)
93
+ { $_[0]->[SUMMARY] = $_[1]; };
94
+
95
+
96
+ 1;
@@ -0,0 +1,1319 @@
1
+ ###############################################################################
2
+ #
3
+ # Package: NaturalDocs::Topics
4
+ #
5
+ ###############################################################################
6
+ #
7
+ # The topic constants and functions to convert them to and from strings used throughout the script. All constants are exported
8
+ # by default.
9
+ #
10
+ ###############################################################################
11
+
12
+ # This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
13
+ # Natural Docs is licensed under the GPL
14
+
15
+ use Text::Wrap ( );
16
+ use Tie::RefHash ( );
17
+
18
+ use strict;
19
+ use integer;
20
+
21
+ use NaturalDocs::Topics::Type;
22
+
23
+ package NaturalDocs::Topics;
24
+
25
+ use base 'Exporter';
26
+ our @EXPORT = ( 'TOPIC_GENERAL', 'TOPIC_GENERIC', 'TOPIC_GROUP', 'TOPIC_CLASS', 'TOPIC_FILE', 'TOPIC_FUNCTION',
27
+ 'TOPIC_VARIABLE', 'TOPIC_PROPERTY', 'TOPIC_TYPE', 'TOPIC_ENUMERATION', 'TOPIC_CONSTANT',
28
+ 'TOPIC_INTERFACE', 'TOPIC_EVENT', 'TOPIC_DELEGATE', 'TOPIC_SECTION' );
29
+
30
+
31
+
32
+ ###############################################################################
33
+ # Group: Types
34
+
35
+
36
+ #
37
+ # Type: TopicType
38
+ #
39
+ # A string representing a topic type as defined in <Topics.txt>. It's format should be treated as opaque; use <MakeTopicType()>
40
+ # to get them from topic names. However, they can be compared for equality with string functions.
41
+ #
42
+
43
+
44
+ #
45
+ # Constants: Default TopicTypes
46
+ #
47
+ # Exported constants of the default <TopicTypes>, so you don't have to go through <TypeFromName()> every time.
48
+ #
49
+ # TOPIC_GENERAL - The general <TopicType>, which has the special meaning of none in particular.
50
+ # TOPIC_GENERIC - Generic <TopicType>.
51
+ # TOPIC_GROUP - Group <TopicType>.
52
+ # TOPIC_CLASS - Class <TopicType>.
53
+ # TOPIC_INTERFACE - Interface <TopicType>.
54
+ # TOPIC_FILE - File <TopicType>.
55
+ # TOPIC_SECTION - Section <TopicType>.
56
+ # TOPIC_FUNCTION - Function <TopicType>.
57
+ # TOPIC_VARIABLE - Variable <TopicType>.
58
+ # TOPIC_PROPERTY - Property <TopicType>.
59
+ # TOPIC_TYPE - Type <TopicType>.
60
+ # TOPIC_CONSTANT - Constant <TopicType>.
61
+ # TOPIC_ENUMERATION - Enum <TopicType>.
62
+ # TOPIC_DELEGATE - Delegate <TopicType>.
63
+ # TOPIC_EVENT - Event <TopicType>.
64
+ #
65
+ use constant TOPIC_GENERAL => 'general';
66
+ use constant TOPIC_GENERIC => 'generic';
67
+ use constant TOPIC_GROUP => 'group';
68
+ use constant TOPIC_CLASS => 'class';
69
+ use constant TOPIC_INTERFACE => 'interface';
70
+ use constant TOPIC_FILE => 'file';
71
+ use constant TOPIC_SECTION => 'section';
72
+ use constant TOPIC_FUNCTION => 'function';
73
+ use constant TOPIC_VARIABLE => 'variable';
74
+ use constant TOPIC_PROPERTY => 'property';
75
+ use constant TOPIC_TYPE => 'type';
76
+ use constant TOPIC_CONSTANT => 'constant';
77
+ use constant TOPIC_ENUMERATION => 'enumeration';
78
+ use constant TOPIC_DELEGATE => 'delegate';
79
+ use constant TOPIC_EVENT => 'event';
80
+ # Dependency: The values of these constants must match what is generated by MakeTopicType().
81
+ # Dependency: These types must be added to requiredTypeNames so that they always exist.
82
+
83
+
84
+
85
+
86
+ ###############################################################################
87
+ # Group: Variables
88
+
89
+
90
+ #
91
+ # handle: FH_TOPICS
92
+ #
93
+ # The file handle used when writing to <Topics.txt>.
94
+ #
95
+
96
+
97
+ #
98
+ # hash: types
99
+ #
100
+ # A hashref that maps <TopicTypes> to <NaturalDocs::Topics::Type>s.
101
+ #
102
+ my %types;
103
+
104
+
105
+ #
106
+ # hash: names
107
+ #
108
+ # A hashref that maps various forms of the all-lowercase type names to <TopicTypes>. All are in the same hash because
109
+ # two names that reduce to the same thing it would cause big problems, and we need to catch that. Keys include
110
+ #
111
+ # - Topic names
112
+ # - Plural topic names
113
+ # - Alphanumeric-only topic names
114
+ # - Alphanumeric-only plural topic names
115
+ #
116
+ my %names;
117
+
118
+
119
+ #
120
+ # hash: keywords
121
+ #
122
+ # A hashref that maps all-lowercase keywords to their <TopicTypes>. Must not have any of the same keys as
123
+ # <pluralKeywords>.
124
+ #
125
+ my %keywords;
126
+
127
+
128
+ #
129
+ # hash: pluralKeywords
130
+ #
131
+ # A hashref that maps all-lowercase plural keywords to their <TopicTypes>. Must not have any of the same keys as
132
+ # <keywords>.
133
+ #
134
+ my %pluralKeywords;
135
+
136
+
137
+ #
138
+ # hash: indexable
139
+ #
140
+ # An existence hash of all the indexable <TopicTypes>.
141
+ #
142
+ my %indexable;
143
+
144
+
145
+ #
146
+ # array: requiredTypeNames
147
+ #
148
+ # An array of the <TopicType> names which are required to be defined in the main file. Are in the order they should appear
149
+ # when reformatting.
150
+ #
151
+ my @requiredTypeNames = ( 'Generic', 'Class', 'Interface', 'Section', 'File', 'Group', 'Function', 'Variable', 'Property', 'Type',
152
+ 'Constant', 'Enumeration', 'Event', 'Delegate' );
153
+
154
+
155
+ #
156
+ # array: legacyTypes
157
+ #
158
+ # An array that converts the legacy topic types, which were numeric constants prior to 1.3, to the current <TopicTypes>.
159
+ # The legacy types are used as an index into the array. Note that this does not support list type values.
160
+ #
161
+ my @legacyTypes = ( TOPIC_GENERAL, TOPIC_CLASS, TOPIC_SECTION, TOPIC_FILE, TOPIC_GROUP, TOPIC_FUNCTION,
162
+ TOPIC_VARIABLE, TOPIC_GENERIC, TOPIC_TYPE, TOPIC_CONSTANT, TOPIC_PROPERTY );
163
+
164
+
165
+ #
166
+ # array: mainTopicNames
167
+ #
168
+ # An array of the <TopicType> names that are defined in the main <Topics.txt>.
169
+ #
170
+ my @mainTopicNames;
171
+
172
+
173
+
174
+ ###############################################################################
175
+ # Group: Files
176
+
177
+
178
+ #
179
+ # File: Topics.txt
180
+ #
181
+ # The configuration file that defines or overrides the topic definitions for Natural Docs. One version sits in Natural Docs'
182
+ # configuration directory, and another can be in a project directory to add to or override them.
183
+ #
184
+ # > # [comments]
185
+ #
186
+ # Everything after a # symbol is ignored.
187
+ #
188
+ # Except when specifying topic names, everything below is case-insensitive.
189
+ #
190
+ # > Format: [version]
191
+ #
192
+ # Specifies the file format version of the file.
193
+ #
194
+ #
195
+ # Sections:
196
+ #
197
+ # > Ignore[d] Keyword[s]: [keyword], [keyword] ...
198
+ # > [keyword]
199
+ # > [keyword], [keyword]
200
+ # > ...
201
+ #
202
+ # Ignores the keywords so that they're not recognized as Natural Docs topics anymore. Can be specified as a list on the same
203
+ # line and/or following like a normal Keywords section.
204
+ #
205
+ # > Topic Type: [name]
206
+ # > Alter Topic Type: [name]
207
+ #
208
+ # Creates a new topic type or alters an existing one. The name can only contain <CFChars> and isn't case sensitive, although
209
+ # the original case is remembered for presentation.
210
+ #
211
+ # The name General is reserved. There are a number of default types that must be defined in the main file as well, but those
212
+ # are governed by <NaturalDocs::Topics> and are not included here. The default types can have their keywords or behaviors
213
+ # changed, though, either by editing the default file or by overriding them in the user file.
214
+ #
215
+ # Enumeration is a special type. It is indexed with Types and its definition list members are listed with Constants according
216
+ # to the rules in <Languages.txt>.
217
+ #
218
+ #
219
+ # Topic Type Sections:
220
+ #
221
+ # > Plural: [name]
222
+ #
223
+ # Specifies the plural name of the topic type. Defaults to the singular name. Has the same restrictions as the topic type
224
+ # name.
225
+ #
226
+ # > Index: [yes|no]
227
+ #
228
+ # Whether the topic type gets an index. Defaults to yes.
229
+ #
230
+ # > Scope: [normal|start|end|always global]
231
+ #
232
+ # How the topic affects scope. Defaults to normal.
233
+ #
234
+ # normal - The topic stays within the current scope.
235
+ # start - The topic starts a new scope for all the topics beneath it, like class topics.
236
+ # end - The topic resets the scope back to global for all the topics beneath it, like section topics.
237
+ # always global - The topic is defined as a global symbol, but does not change the scope for any other topics.
238
+ #
239
+ # > Class Hierarchy: [yes|no]
240
+ #
241
+ # Whether the topic is part of the class hierarchy. Defaults to no.
242
+ #
243
+ # > Page Title if First: [yes|no]
244
+ #
245
+ # Whether the title of this topic becomes the page title if it is the first topic in a file. Defaults to no.
246
+ #
247
+ # > Break Lists: [yes|no]
248
+ #
249
+ # Whether list topics should be broken into individual topics in the output. Defaults to no.
250
+ #
251
+ # > Can Group With: [topic type], [topic type], ...
252
+ #
253
+ # The list of <TopicTypes> the topic can possibly be grouped with.
254
+ #
255
+ # > [Add] Keyword[s]:
256
+ # > [keyword]
257
+ # > [keyword], [plural keyword]
258
+ # > ...
259
+ #
260
+ # A list of the topic type's keywords. Each line after the heading is the keyword and optionally its plural form. This continues
261
+ # until the next line in "keyword: value" format. "Add" isn't required.
262
+ #
263
+ # - Keywords can only have letters and numbers. No punctuation or spaces are allowed.
264
+ # - Keywords are not case sensitive.
265
+ # - Subsequent keyword sections add to the list. They don't replace it.
266
+ # - Keywords can be redefined by other keyword sections.
267
+ #
268
+ #
269
+ # Revisions:
270
+ #
271
+ # 1.3:
272
+ #
273
+ # The initial version of this file.
274
+ #
275
+
276
+
277
+ ###############################################################################
278
+ # Group: File Functions
279
+
280
+
281
+ #
282
+ # Function: Load
283
+ #
284
+ # Loads both the master and the project version of <Topics.txt>.
285
+ #
286
+ sub Load
287
+ {
288
+ my $self = shift;
289
+
290
+ # Add the special General topic type.
291
+
292
+ $types{::TOPIC_GENERAL()} = NaturalDocs::Topics::Type->New('General', 'General', 1, ::SCOPE_NORMAL(), undef);
293
+ $names{'general'} = ::TOPIC_GENERAL();
294
+ $indexable{::TOPIC_GENERAL()} = 1;
295
+ # There are no keywords for the general topic.
296
+
297
+
298
+ $self->LoadFile(1); # Main
299
+
300
+ # Dependency: All the default topic types must be checked for existence.
301
+
302
+ # Check to see if the required types are defined.
303
+ foreach my $name (@requiredTypeNames)
304
+ {
305
+ if (!exists $names{lc($name)})
306
+ { NaturalDocs::ConfigFile->AddError('The ' . $name . ' topic type must be defined in the main topics file.'); };
307
+ };
308
+
309
+ my $errorCount = NaturalDocs::ConfigFile->ErrorCount();
310
+
311
+ if ($errorCount)
312
+ {
313
+ NaturalDocs::ConfigFile->PrintErrorsAndAnnotateFile();
314
+ NaturalDocs::Error->SoftDeath('There ' . ($errorCount == 1 ? 'is an error' : 'are ' . $errorCount . ' errors')
315
+ . ' in ' . NaturalDocs::Project->MainConfigFile('Topics.txt'));
316
+ }
317
+
318
+
319
+ $self->LoadFile(); # User
320
+
321
+ $errorCount = NaturalDocs::ConfigFile->ErrorCount();
322
+
323
+ if ($errorCount)
324
+ {
325
+ NaturalDocs::ConfigFile->PrintErrorsAndAnnotateFile();
326
+ NaturalDocs::Error->SoftDeath('There ' . ($errorCount == 1 ? 'is an error' : 'are ' . $errorCount . ' errors')
327
+ . ' in ' . NaturalDocs::Project->UserConfigFile('Topics.txt'));
328
+ }
329
+ };
330
+
331
+
332
+ #
333
+ # Function: LoadFile
334
+ #
335
+ # Loads a particular version of <Topics.txt>.
336
+ #
337
+ # Parameters:
338
+ #
339
+ # isMain - Whether the file is the main file or not.
340
+ #
341
+ sub LoadFile #(isMain)
342
+ {
343
+ my ($self, $isMain) = @_;
344
+
345
+ my ($file, $status);
346
+
347
+ if ($isMain)
348
+ {
349
+ $file = NaturalDocs::Project->MainConfigFile('Topics.txt');
350
+ $status = NaturalDocs::Project->MainConfigFileStatus('Topics.txt');
351
+ }
352
+ else
353
+ {
354
+ $file = NaturalDocs::Project->UserConfigFile('Topics.txt');
355
+ $status = NaturalDocs::Project->UserConfigFileStatus('Topics.txt');
356
+ };
357
+
358
+ my $version;
359
+
360
+ if ($version = NaturalDocs::ConfigFile->Open($file))
361
+ {
362
+ # The format hasn't changed since the file was introduced.
363
+
364
+ if ($status == ::FILE_CHANGED())
365
+ { NaturalDocs::Project->ReparseEverything(); };
366
+
367
+ my ($topicTypeKeyword, $topicTypeName, $topicType, $topicTypeObject, $inKeywords, $inIgnoredKeywords);
368
+
369
+ # Keys are topic type objects, values are unparsed strings.
370
+ my %canGroupWith;
371
+ tie %canGroupWith, 'Tie::RefHash';
372
+
373
+ while (my ($keyword, $value) = NaturalDocs::ConfigFile->GetLine())
374
+ {
375
+ if ($keyword)
376
+ {
377
+ $inKeywords = 0;
378
+ $inIgnoredKeywords = 0;
379
+ };
380
+
381
+ if ($keyword eq 'topic type')
382
+ {
383
+ $topicTypeKeyword = $keyword;
384
+ $topicTypeName = $value;
385
+
386
+ # Resolve conflicts and create the type if necessary.
387
+
388
+ $topicType = $self->MakeTopicType($topicTypeName);
389
+ my $lcTopicTypeName = lc($topicTypeName);
390
+
391
+ my $lcTopicTypeAName = $lcTopicTypeName;
392
+ $lcTopicTypeAName =~ tr/a-z0-9//cd;
393
+
394
+ if (!NaturalDocs::ConfigFile->HasOnlyCFChars($topicTypeName))
395
+ {
396
+ NaturalDocs::ConfigFile->AddError('Topic names can only have ' . NaturalDocs::ConfigFile->CFCharNames() . '.');
397
+ }
398
+ elsif ($topicType eq ::TOPIC_GENERAL())
399
+ {
400
+ NaturalDocs::ConfigFile->AddError('You cannot define a General topic type.');
401
+ }
402
+ elsif (defined $types{$topicType} || defined $names{$lcTopicTypeName} || defined $names{$lcTopicTypeAName})
403
+ {
404
+ NaturalDocs::ConfigFile->AddError('Topic type ' . $topicTypeName . ' is already defined or its name is too '
405
+ . 'similar to an existing name. Use Alter Topic Type if you meant to override '
406
+ . 'its settings.');
407
+ }
408
+ else
409
+ {
410
+ $topicTypeObject = NaturalDocs::Topics::Type->New($topicTypeName, $topicTypeName, 1, ::SCOPE_NORMAL(),
411
+ 0, 0);
412
+
413
+ $types{$topicType} = $topicTypeObject;
414
+ $names{$lcTopicTypeName} = $topicType;
415
+ $names{$lcTopicTypeAName} = $topicType;
416
+
417
+ $indexable{$topicType} = 1;
418
+
419
+ if ($isMain)
420
+ { push @mainTopicNames, $topicTypeName; };
421
+ };
422
+ }
423
+
424
+ elsif ($keyword eq 'alter topic type')
425
+ {
426
+ $topicTypeKeyword = $keyword;
427
+ $topicTypeName = $value;
428
+
429
+ # Resolve conflicts and create the type if necessary.
430
+
431
+ $topicType = $names{lc($topicTypeName)};
432
+
433
+ if (!defined $topicType)
434
+ { NaturalDocs::ConfigFile->AddError('Topic type ' . $topicTypeName . ' doesn\'t exist.'); }
435
+ elsif ($topicType eq ::TOPIC_GENERAL())
436
+ { NaturalDocs::ConfigFile->AddError('You cannot alter the General topic type.'); }
437
+ else
438
+ {
439
+ $topicTypeObject = $types{$topicType};
440
+ };
441
+ }
442
+
443
+ elsif ($keyword =~ /^ignored? keywords?$/)
444
+ {
445
+ $inIgnoredKeywords = 1;
446
+
447
+ my @ignoredKeywords = split(/ ?, ?/, lc($value));
448
+
449
+ foreach my $ignoredKeyword (@ignoredKeywords)
450
+ {
451
+ delete $keywords{$ignoredKeyword};
452
+ delete $pluralKeywords{$ignoredKeyword};
453
+ };
454
+ }
455
+
456
+ # We continue even if there are errors in the topic type line so that we can find any other errors in the file as well. We'd
457
+ # rather them all show up at once instead of them showing up one at a time between Natural Docs runs. So we just ignore
458
+ # the settings if $topicTypeObject is undef.
459
+
460
+
461
+ elsif ($keyword eq 'plural')
462
+ {
463
+ my $pluralName = $value;
464
+ my $lcPluralName = lc($pluralName);
465
+
466
+ my $lcPluralAName = $lcPluralName;
467
+ $lcPluralAName =~ tr/a-zA-Z0-9//cd;
468
+
469
+ if (!NaturalDocs::ConfigFile->HasOnlyCFChars($pluralName))
470
+ {
471
+ NaturalDocs::ConfigFile->AddError('Plural names can only have '
472
+ . NaturalDocs::ConfigFile->CFCharNames() . '.');
473
+ }
474
+ elsif ($lcPluralAName eq 'general')
475
+ {
476
+ NaturalDocs::ConfigFile->AddError('You cannot use General as a plural name for ' . $topicTypeName . '.');
477
+ }
478
+ elsif ( (defined $names{$lcPluralName} && $names{$lcPluralName} ne $topicType) ||
479
+ (defined $names{$lcPluralAName} && $names{$lcPluralAName} ne $topicType) )
480
+ {
481
+ NaturalDocs::ConfigFile->AddError($topicTypeName . "'s plural name, " . $pluralName
482
+ . ', is already defined or is too similar to an existing name.');
483
+ }
484
+
485
+ elsif (defined $topicTypeObject)
486
+ {
487
+ $topicTypeObject->SetPluralName($pluralName);
488
+
489
+ $names{$lcPluralName} = $topicType;
490
+ $names{$lcPluralAName} = $topicType;
491
+ };
492
+ }
493
+
494
+ elsif ($keyword eq 'index')
495
+ {
496
+ $value = lc($value);
497
+
498
+ if ($value eq 'yes')
499
+ {
500
+ if (defined $topicTypeObject)
501
+ {
502
+ $topicTypeObject->SetIndex(1);
503
+ $indexable{$topicType} = 1;
504
+ };
505
+ }
506
+ elsif ($value eq 'no')
507
+ {
508
+ if (defined $topicTypeObject)
509
+ {
510
+ $topicTypeObject->SetIndex(0);
511
+ delete $indexable{$topicType};
512
+ };
513
+ }
514
+ else
515
+ {
516
+ NaturalDocs::ConfigFile->AddError('Index lines can only be "yes" or "no".');
517
+ };
518
+ }
519
+
520
+ elsif ($keyword eq 'class hierarchy')
521
+ {
522
+ $value = lc($value);
523
+
524
+ if ($value eq 'yes')
525
+ {
526
+ if (defined $topicTypeObject)
527
+ { $topicTypeObject->SetClassHierarchy(1); };
528
+ }
529
+ elsif ($value eq 'no')
530
+ {
531
+ if (defined $topicTypeObject)
532
+ { $topicTypeObject->SetClassHierarchy(0); };
533
+ }
534
+ else
535
+ {
536
+ NaturalDocs::ConfigFile->AddError('Class Hierarchy lines can only be "yes" or "no".');
537
+ };
538
+ }
539
+
540
+ elsif ($keyword eq 'scope')
541
+ {
542
+ $value = lc($value);
543
+
544
+ if ($value eq 'normal')
545
+ {
546
+ if (defined $topicTypeObject)
547
+ { $topicTypeObject->SetScope(::SCOPE_NORMAL()); };
548
+ }
549
+ elsif ($value eq 'start')
550
+ {
551
+ if (defined $topicTypeObject)
552
+ { $topicTypeObject->SetScope(::SCOPE_START()); };
553
+ }
554
+ elsif ($value eq 'end')
555
+ {
556
+ if (defined $topicTypeObject)
557
+ { $topicTypeObject->SetScope(::SCOPE_END()); };
558
+ }
559
+ elsif ($value eq 'always global')
560
+ {
561
+ if (defined $topicTypeObject)
562
+ { $topicTypeObject->SetScope(::SCOPE_ALWAYS_GLOBAL()); };
563
+ }
564
+ else
565
+ {
566
+ NaturalDocs::ConfigFile->AddError('Scope lines can only be "normal", "start", "end", or "always global".');
567
+ };
568
+ }
569
+
570
+ elsif ($keyword eq 'page title if first')
571
+ {
572
+ $value = lc($value);
573
+
574
+ if ($value eq 'yes')
575
+ {
576
+ if (defined $topicTypeObject)
577
+ { $topicTypeObject->SetPageTitleIfFirst(1); };
578
+ }
579
+ elsif ($value eq 'no')
580
+ {
581
+ if (defined $topicTypeObject)
582
+ { $topicTypeObject->SetPageTitleIfFirst(undef); };
583
+ }
584
+ else
585
+ {
586
+ NaturalDocs::ConfigFile->AddError('Page Title if First lines can only be "yes" or "no".');
587
+ };
588
+ }
589
+
590
+ elsif ($keyword eq 'break lists')
591
+ {
592
+ $value = lc($value);
593
+
594
+ if ($value eq 'yes')
595
+ {
596
+ if (defined $topicTypeObject)
597
+ { $topicTypeObject->SetBreakLists(1); };
598
+ }
599
+ elsif ($value eq 'no')
600
+ {
601
+ if (defined $topicTypeObject)
602
+ { $topicTypeObject->SetBreakLists(undef); };
603
+ }
604
+ else
605
+ {
606
+ NaturalDocs::ConfigFile->AddError('Break Lists lines can only be "yes" or "no".');
607
+ };
608
+ }
609
+
610
+ elsif ($keyword eq 'can group with')
611
+ {
612
+ if (defined $topicTypeObject)
613
+ { $canGroupWith{$topicTypeObject} = lc($value); };
614
+ }
615
+
616
+ elsif ($keyword =~ /^(?:add )?keywords?$/)
617
+ {
618
+ $inKeywords = 1;
619
+ }
620
+
621
+ elsif (defined $keyword)
622
+ { NaturalDocs::ConfigFile->AddError($keyword . ' is not a valid keyword.'); }
623
+
624
+ elsif (!$inKeywords && !$inIgnoredKeywords)
625
+ {
626
+ NaturalDocs::ConfigFile->AddError('All lines in ' . $topicTypeKeyword . ' sections must begin with a keyword.');
627
+ }
628
+
629
+ else # No keyword but in keyword section.
630
+ {
631
+ $value = lc($value);
632
+
633
+ if ($value =~ /^([a-z0-9 ]*[a-z0-9]) ?, ?([a-z0-9 ]+)$/)
634
+ {
635
+ my ($singular, $plural) = ($1, $2);
636
+
637
+ if ($inIgnoredKeywords)
638
+ {
639
+ delete $keywords{$singular};
640
+ delete $keywords{$plural};
641
+ delete $pluralKeywords{$singular};
642
+ delete $pluralKeywords{$plural};
643
+ }
644
+ elsif (defined $topicTypeObject)
645
+ {
646
+ $keywords{$singular} = $topicType;
647
+ delete $pluralKeywords{$singular};
648
+
649
+ $pluralKeywords{$plural} = $topicType;
650
+ delete $keywords{$plural};
651
+ };
652
+ }
653
+ elsif ($value =~ /^[a-z0-9 ]+$/)
654
+ {
655
+ if ($inIgnoredKeywords)
656
+ {
657
+ delete $keywords{$value};
658
+ delete $pluralKeywords{$value};
659
+ }
660
+ elsif (defined $topicType)
661
+ {
662
+ $keywords{$value} = $topicType;
663
+ delete $pluralKeywords{$value};
664
+ };
665
+ }
666
+ else
667
+ {
668
+ NaturalDocs::ConfigFile->AddError('Keywords can only have letters, numbers, and spaces. '
669
+ . 'Plurals must be separated by a comma.');
670
+ };
671
+ };
672
+ };
673
+
674
+ NaturalDocs::ConfigFile->Close();
675
+
676
+
677
+ # Parse out the Can Group With lines now that everything's defined.
678
+
679
+ while (my ($typeObject, $value) = each %canGroupWith)
680
+ {
681
+ my @values = split(/ ?, ?/, $value);
682
+ my @types;
683
+
684
+ foreach my $value (@values)
685
+ {
686
+ # We're just going to ignore invalid items.
687
+ if (exists $names{$value})
688
+ { push @types, $names{$value}; };
689
+ };
690
+
691
+ if (scalar @types)
692
+ { $typeObject->SetCanGroupWith(\@types); };
693
+ };
694
+ }
695
+
696
+ else # couldn't open file
697
+ {
698
+ if ($isMain)
699
+ { die "Couldn't open topics file " . $file . "\n"; }
700
+ else
701
+ { NaturalDocs::Project->ReparseEverything(); };
702
+ };
703
+ };
704
+
705
+
706
+ #
707
+ # Function: Save
708
+ #
709
+ # Saves the main and user versions of <Topics.txt>.
710
+ #
711
+ sub Save
712
+ {
713
+ my $self = shift;
714
+
715
+ $self->SaveFile(1); # Main
716
+ $self->SaveFile(0); # User
717
+ };
718
+
719
+
720
+ #
721
+ # Function: SaveFile
722
+ #
723
+ # Saves a particular version of <Topics.txt>.
724
+ #
725
+ # Parameters:
726
+ #
727
+ # isMain - Whether the file is the main file or not.
728
+ #
729
+ sub SaveFile #(isMain)
730
+ {
731
+ my ($self, $isMain) = @_;
732
+
733
+ my $file;
734
+
735
+ if ($isMain)
736
+ {
737
+ if (NaturalDocs::Project->MainConfigFileStatus('Topics.txt') == ::FILE_SAME())
738
+ { return; };
739
+ $file = NaturalDocs::Project->MainConfigFile('Topics.txt');
740
+ }
741
+ else
742
+ {
743
+ # We have to check the main one two because this lists the topics defined in it.
744
+ if (NaturalDocs::Project->UserConfigFileStatus('Topics.txt') == ::FILE_SAME() &&
745
+ NaturalDocs::Project->MainConfigFileStatus('Topics.txt') == ::FILE_SAME())
746
+ { return; };
747
+ $file = NaturalDocs::Project->UserConfigFile('Topics.txt');
748
+ };
749
+
750
+
751
+ # Array of topic type names in the order they appear in the file. If Alter Topic Type is used, the name will end with an asterisk.
752
+ my @topicTypeOrder;
753
+
754
+ # Keys are topic type names, values are property hashrefs. Hashref keys are the property names, values the value.
755
+ # For keywords, the key is Keywords and the values are arrayrefs of singular and plural pairs. If no plural is defined, the entry
756
+ # will be undef.
757
+ my %properties;
758
+
759
+ # List of ignored keywords specified as Ignore Keywords: [keyword], [keyword], ...
760
+ my @inlineIgnoredKeywords;
761
+
762
+ # List of ignored keywords specified in [keyword], [plural keyword] lines. Done in pairs, like for regular keywords.
763
+ my @separateIgnoredKeywords;
764
+
765
+ my $inIgnoredKeywords;
766
+
767
+ if (NaturalDocs::ConfigFile->Open($file))
768
+ {
769
+ # We can assume the file is valid.
770
+
771
+ my ($keyword, $value, $topicTypeName);
772
+
773
+ while (($keyword, $value) = NaturalDocs::ConfigFile->GetLine())
774
+ {
775
+ $keyword = lc($keyword);
776
+
777
+ if ($keyword eq 'topic type' || $keyword eq 'alter topic type')
778
+ {
779
+ $topicTypeName = $types{ $names{lc($value)} }->Name();
780
+
781
+ if ($keyword eq 'alter topic type')
782
+ { $topicTypeName .= '*'; };
783
+
784
+ push @topicTypeOrder, $topicTypeName;
785
+
786
+ if (!exists $properties{$topicTypeName})
787
+ { $properties{$topicTypeName} = { 'keywords' => [ ] }; };
788
+ }
789
+
790
+ elsif ($keyword eq 'plural')
791
+ {
792
+ $properties{$topicTypeName}->{$keyword} = $value;
793
+ }
794
+
795
+ elsif ($keyword eq 'index' ||
796
+ $keyword eq 'scope' ||
797
+ $keyword eq 'page title if first' ||
798
+ $keyword eq 'class hierarchy' ||
799
+ $keyword eq 'break lists' ||
800
+ $keyword eq 'can group with')
801
+ {
802
+ $properties{$topicTypeName}->{$keyword} = lc($value);
803
+ }
804
+
805
+ elsif ($keyword =~ /^(?:add )?keywords?$/)
806
+ {
807
+ $inIgnoredKeywords = 0;
808
+ }
809
+
810
+ elsif ($keyword =~ /^ignored? keywords?$/)
811
+ {
812
+ $inIgnoredKeywords = 1;
813
+ if ($value)
814
+ { push @inlineIgnoredKeywords, split(/ ?, ?/, $value); };
815
+ }
816
+
817
+ elsif (!$keyword)
818
+ {
819
+ my ($singular, $plural) = split(/ ?, ?/, lc($value));
820
+
821
+ if ($inIgnoredKeywords)
822
+ { push @separateIgnoredKeywords, $singular, $plural; }
823
+ else
824
+ { push @{$properties{$topicTypeName}->{'keywords'}}, $singular, $plural; };
825
+ };
826
+ };
827
+
828
+ NaturalDocs::ConfigFile->Close();
829
+ };
830
+
831
+
832
+ if (!open(FH_TOPICS, '>' . $file))
833
+ {
834
+ # The main file may be on a shared volume or some other place the user doesn't have write access to. Since this is only to
835
+ # reformat the file, we can ignore the failure.
836
+ if ($isMain)
837
+ { return; }
838
+ else
839
+ { die "Couldn't save " . $file; };
840
+ };
841
+
842
+ print FH_TOPICS 'Format: ' . NaturalDocs::Settings->TextAppVersion() . "\n\n";
843
+
844
+ # Remember the 80 character limit.
845
+
846
+ if ($isMain)
847
+ {
848
+ print FH_TOPICS
849
+ "# This is the main Natural Docs topics file. If you change anything here, it\n"
850
+ . "# will apply to EVERY PROJECT you use Natural Docs on. If you'd like to\n"
851
+ . "# change something for just one project, edit the Topics.txt in its project\n"
852
+ . "# directory instead.\n";
853
+ }
854
+ else
855
+ {
856
+ print FH_TOPICS
857
+ "# This is the Natural Docs topics file for this project. If you change anything\n"
858
+ . "# here, it will apply to THIS PROJECT ONLY. If you'd like to change something\n"
859
+ . "# for all your projects, edit the Topics.txt in Natural Docs' Config directory\n"
860
+ . "# instead.\n\n\n";
861
+
862
+ if (scalar @inlineIgnoredKeywords || scalar @separateIgnoredKeywords)
863
+ {
864
+ if (scalar @inlineIgnoredKeywords == 1 && !scalar @separateIgnoredKeywords)
865
+ {
866
+ print FH_TOPICS 'Ignore Keyword: ' . $inlineIgnoredKeywords[0] . "\n";
867
+ }
868
+ else
869
+ {
870
+ print FH_TOPICS
871
+ 'Ignore Keywords: ' . join(', ', @inlineIgnoredKeywords) . "\n";
872
+
873
+ for (my $i = 0; $i < scalar @separateIgnoredKeywords; $i += 2)
874
+ {
875
+ print FH_TOPICS ' ' . $separateIgnoredKeywords[$i];
876
+
877
+ if (defined $separateIgnoredKeywords[$i + 1])
878
+ { print FH_TOPICS ', ' . $separateIgnoredKeywords[$i + 1]; };
879
+
880
+ print FH_TOPICS "\n";
881
+ };
882
+ };
883
+ }
884
+ else
885
+ {
886
+ print FH_TOPICS
887
+ "# If you'd like to prevent keywords from being recognized by Natural Docs, you\n"
888
+ . "# can do it like this:\n"
889
+ . "# Ignore Keywords: [keyword], [keyword], ...\n"
890
+ . "#\n"
891
+ . "# Or you can use the list syntax like how they are defined:\n"
892
+ . "# Ignore Keywords:\n"
893
+ . "# [keyword]\n"
894
+ . "# [keyword], [plural keyword]\n"
895
+ . "# ...\n";
896
+ };
897
+ };
898
+
899
+ print FH_TOPICS # [CFChars]
900
+ "\n\n"
901
+ . "#-------------------------------------------------------------------------------\n"
902
+ . "# SYNTAX:\n"
903
+ . "#\n";
904
+
905
+ if ($isMain)
906
+ {
907
+ print FH_TOPICS
908
+ "# Topic Type: [name]\n"
909
+ . "# Creates a new topic type. Each type gets its own index and behavior\n"
910
+ . "# settings. Its name can have letters, numbers, spaces, and these\n"
911
+ . "# charaters: - / . '\n"
912
+ . "#\n"
913
+ . "# The Enumeration type is special. It's indexed with Types but its members\n"
914
+ . "# are indexed with Constants according to the rules in Languages.txt.\n"
915
+ . "#\n"
916
+ }
917
+ else
918
+ {
919
+ print FH_TOPICS
920
+ "# Topic Type: [name]\n"
921
+ . "# Alter Topic Type: [name]\n"
922
+ . "# Creates a new topic type or alters one from the main file. Each type gets\n"
923
+ . "# its own index and behavior settings. Its name can have letters, numbers,\n"
924
+ . "# spaces, and these charaters: - / . '\n"
925
+ . "#\n";
926
+ };
927
+
928
+ print FH_TOPICS
929
+ "# Plural: [name]\n"
930
+ . "# Sets the plural name of the topic type, if different.\n"
931
+ . "#\n"
932
+ . "# Keywords:\n"
933
+ . "# [keyword]\n"
934
+ . "# [keyword], [plural keyword]\n"
935
+ . "# ...\n";
936
+
937
+ if ($isMain)
938
+ {
939
+ print FH_TOPICS
940
+ "# Defines a list of keywords for the topic type. They may only contain\n"
941
+ . "# letters, numbers, and spaces and are not case sensitive. Plural keywords\n"
942
+ . "# are used for list topics.\n";
943
+ }
944
+ else
945
+ {
946
+ print FH_TOPICS
947
+ "# Defines or adds to the list of keywords for the topic type. They may only\n"
948
+ . "# contain letters, numbers, and spaces and are not case sensitive. Plural\n"
949
+ . "# keywords are used for list topics. You can redefine keywords found in the\n"
950
+ . "# main topics file.\n";
951
+ }
952
+
953
+ print FH_TOPICS
954
+ "#\n"
955
+ . "# Index: [yes|no]\n"
956
+ . "# Whether the topics get their own index. Defaults to yes. Everything is\n"
957
+ . "# included in the general index regardless of this setting.\n"
958
+ . "#\n"
959
+ . "# Scope: [normal|start|end|always global]\n"
960
+ . "# How the topics affects scope. Defaults to normal.\n"
961
+ . "# normal - Topics stay within the current scope.\n"
962
+ . "# start - Topics start a new scope for all the topics beneath it,\n"
963
+ . "# like class topics.\n"
964
+ . "# end - Topics reset the scope back to global for all the topics\n"
965
+ . "# beneath it.\n"
966
+ . "# always global - Topics are defined as global, but do not change the scope\n"
967
+ . "# for any other topics.\n"
968
+ . "#\n"
969
+ . "# Class Hierarchy: [yes|no]\n"
970
+ . "# Whether the topics are part of the class hierarchy. Defaults to no.\n"
971
+ . "#\n"
972
+ . "# Page Title If First: [yes|no]\n"
973
+ . "# Whether the topic's title becomes the page title if it's the first one in\n"
974
+ . "# a file. Defaults to no.\n"
975
+ . "#\n"
976
+ . "# Break Lists: [yes|no]\n"
977
+ . "# Whether list topics should be broken into individual topics in the output.\n"
978
+ . "# Defaults to no.\n"
979
+ . "#\n"
980
+ . "# Can Group With: [type], [type], ...\n"
981
+ . "# Defines a list of topic types that this one can possibly be grouped with.\n"
982
+ . "# Defaults to none.\n"
983
+ . "#-------------------------------------------------------------------------------\n\n";
984
+
985
+ my $listToPrint;
986
+
987
+ if ($isMain)
988
+ {
989
+ print FH_TOPICS
990
+ "# The following topics MUST be defined in this file:\n"
991
+ . "#\n";
992
+ $listToPrint = \@requiredTypeNames;
993
+ }
994
+ else
995
+ {
996
+ print FH_TOPICS
997
+ "# The following topics are defined in the main file, if you'd like to alter\n"
998
+ . "# their behavior or add keywords:\n"
999
+ . "#\n";
1000
+ $listToPrint = \@mainTopicNames;
1001
+ }
1002
+
1003
+ print FH_TOPICS
1004
+ Text::Wrap::wrap('# ', '# ', join(', ', @$listToPrint)) . "\n"
1005
+ . "\n"
1006
+ . "# If you add something that you think would be useful to other developers\n"
1007
+ . "# and should be included in Natural Docs by default, please e-mail it to\n"
1008
+ . "# topics [at] naturaldocs [dot] org.\n";
1009
+
1010
+ # Existence hash. We do this because we want the required ones to go first by adding them to @topicTypeOrder, but we don't
1011
+ # want them to appear twice.
1012
+ my %doneTopicTypes;
1013
+ my ($altering, $numberOfProperties);
1014
+
1015
+ if ($isMain)
1016
+ { unshift @topicTypeOrder, @requiredTypeNames; };
1017
+
1018
+ my @propertyOrder = ('Plural', 'Index', 'Scope', 'Class Hierarchy', 'Page Title If First', 'Break Lists');
1019
+
1020
+ foreach my $topicType (@topicTypeOrder)
1021
+ {
1022
+ if (!exists $doneTopicTypes{$topicType})
1023
+ {
1024
+ if (substr($topicType, -1) eq '*')
1025
+ {
1026
+ print FH_TOPICS "\n\n"
1027
+ . 'Alter Topic Type: ' . substr($topicType, 0, -1) . "\n\n";
1028
+
1029
+ $altering = 1;
1030
+ $numberOfProperties = 0;
1031
+ }
1032
+ else
1033
+ {
1034
+ print FH_TOPICS "\n\n"
1035
+ . 'Topic Type: ' . $topicType . "\n\n";
1036
+
1037
+ $altering = 0;
1038
+ $numberOfProperties = 0;
1039
+ };
1040
+
1041
+ foreach my $property (@propertyOrder)
1042
+ {
1043
+ if (exists $properties{$topicType}->{lc($property)})
1044
+ {
1045
+ print FH_TOPICS
1046
+ ' ' . $property . ': ' . ucfirst( $properties{$topicType}->{lc($property)} ) . "\n";
1047
+
1048
+ $numberOfProperties++;
1049
+ };
1050
+ };
1051
+
1052
+ if (exists $properties{$topicType}->{'can group with'})
1053
+ {
1054
+ my @typeStrings = split(/ ?, ?/, lc($properties{$topicType}->{'can group with'}));
1055
+ my @types;
1056
+
1057
+ foreach my $typeString (@typeStrings)
1058
+ {
1059
+ if (exists $names{$typeString})
1060
+ { push @types, $names{$typeString}; };
1061
+ };
1062
+
1063
+ if (scalar @types)
1064
+ {
1065
+ for (my $i = 0; $i < scalar @types; $i++)
1066
+ {
1067
+ my $name = NaturalDocs::Topics->NameOfType($types[$i], 1);
1068
+
1069
+ if ($i == 0)
1070
+ { print FH_TOPICS ' Can Group With: ' . $name; }
1071
+ else
1072
+ { print FH_TOPICS ', ' . $name; };
1073
+ };
1074
+
1075
+ print FH_TOPICS "\n";
1076
+ $numberOfProperties++;
1077
+ };
1078
+ };
1079
+
1080
+ if (scalar @{$properties{$topicType}->{'keywords'}})
1081
+ {
1082
+ if ($numberOfProperties > 1)
1083
+ { print FH_TOPICS "\n"; };
1084
+
1085
+ print FH_TOPICS
1086
+ ' ' . ($altering ? 'Add ' : '') . 'Keywords:' . "\n";
1087
+
1088
+ my $keywords = $properties{$topicType}->{'keywords'};
1089
+
1090
+ for (my $i = 0; $i < scalar @$keywords; $i += 2)
1091
+ {
1092
+ print FH_TOPICS ' ' . $keywords->[$i];
1093
+
1094
+ if (defined $keywords->[$i + 1])
1095
+ { print FH_TOPICS ', ' . $keywords->[$i + 1]; };
1096
+
1097
+ print FH_TOPICS "\n";
1098
+ };
1099
+ };
1100
+
1101
+ $doneTopicTypes{$topicType} = 1;
1102
+ };
1103
+ };
1104
+
1105
+ close(FH_TOPICS);
1106
+ };
1107
+
1108
+
1109
+
1110
+ ###############################################################################
1111
+ # Group: Functions
1112
+
1113
+
1114
+ #
1115
+ # Function: KeywordInfo
1116
+ #
1117
+ # Returns information about a topic keyword.
1118
+ #
1119
+ # Parameters:
1120
+ #
1121
+ # keyword - The keyword, which may be plural.
1122
+ #
1123
+ # Returns:
1124
+ #
1125
+ # The array ( topicType, info, isPlural ), or an empty array if the keyword doesn't exist.
1126
+ #
1127
+ # topicType - The <TopicType> of the keyword.
1128
+ # info - The <NaturalDocs::Topics::Type> of its type.
1129
+ # isPlural - Whether the keyword was plural or not.
1130
+ #
1131
+ sub KeywordInfo #(keyword)
1132
+ {
1133
+ my ($self, $keyword) = @_;
1134
+
1135
+ $keyword = lc($keyword);
1136
+
1137
+ my $type = $keywords{$keyword};
1138
+
1139
+ if (defined $type)
1140
+ { return ( $type, $types{$type}, undef ); };
1141
+
1142
+ $type = $pluralKeywords{$keyword};
1143
+
1144
+ if (defined $type)
1145
+ { return ( $type, $types{$type}, 1 ); };
1146
+
1147
+ return ( );
1148
+ };
1149
+
1150
+
1151
+ #
1152
+ # Function: NameInfo
1153
+ #
1154
+ # Returns information about a topic name.
1155
+ #
1156
+ # Parameters:
1157
+ #
1158
+ # name - The topic type name, which can be plural and/or alphanumeric only.
1159
+ #
1160
+ # Returns:
1161
+ #
1162
+ # The array ( topicType, info ), or an empty array if the name doesn't exist. Note that unlike <KeywordInfo()>, this
1163
+ # does *not* tell you whether the name is plural or not.
1164
+ #
1165
+ # topicType - The <TopicType> of the name.
1166
+ # info - The <NaturalDocs::Topics::Type> of the type.
1167
+ #
1168
+ sub NameInfo #(name)
1169
+ {
1170
+ my ($self, $name) = @_;
1171
+
1172
+ my $type = $names{lc($name)};
1173
+
1174
+ if (defined $type)
1175
+ { return ( $type, $types{$type} ); }
1176
+ else
1177
+ { return ( ); };
1178
+ };
1179
+
1180
+
1181
+ #
1182
+ # Function: TypeInfo
1183
+ #
1184
+ # Returns information about a <TopicType>.
1185
+ #
1186
+ # Parameters:
1187
+ #
1188
+ # type - The <TopicType>.
1189
+ #
1190
+ # Returns:
1191
+ #
1192
+ # The <NaturalDocs::Topics::Type> of the type, or undef if it didn't exist.
1193
+ #
1194
+ sub TypeInfo #(type)
1195
+ {
1196
+ my ($self, $type) = @_;
1197
+ return $types{$type};
1198
+ };
1199
+
1200
+
1201
+ #
1202
+ # Function: NameOfType
1203
+ #
1204
+ # Returns the name of the passed <TopicType>, or undef if it doesn't exist.
1205
+ #
1206
+ # Parameters:
1207
+ #
1208
+ # topicType - The <TopicType>.
1209
+ # plural - Whether to return the plural instead of the singular.
1210
+ # alphanumericOnly - Whether to strips everything but alphanumeric characters out. Case isn't modified.
1211
+ #
1212
+ # Returns:
1213
+ #
1214
+ # The topic type name, according to what was specified in the parameters, or undef if it doesn't exist.
1215
+ #
1216
+ sub NameOfType #(topicType, plural, alphanumericOnly)
1217
+ {
1218
+ my ($self, $topicType, $plural, $alphanumericOnly) = @_;
1219
+
1220
+ my $topicObject = $types{$topicType};
1221
+
1222
+ if (!defined $topicObject)
1223
+ { return undef; };
1224
+
1225
+ my $topicName = ($plural ? $topicObject->PluralName() : $topicObject->Name());
1226
+
1227
+ if ($alphanumericOnly)
1228
+ { $topicName =~ tr/a-zA-Z0-9//cd; };
1229
+
1230
+ return $topicName;
1231
+ };
1232
+
1233
+
1234
+ #
1235
+ # Function: TypeFromName
1236
+ #
1237
+ # Returns a <TopicType> for the passed topic name.
1238
+ #
1239
+ # Parameters:
1240
+ #
1241
+ # topicName - The name of the topic, which can be plural and/or alphanumeric only.
1242
+ #
1243
+ # Returns:
1244
+ #
1245
+ # The <TopicType>. It does not specify whether the name was plural or not.
1246
+ #
1247
+ sub TypeFromName #(topicName)
1248
+ {
1249
+ my ($self, $topicName) = @_;
1250
+
1251
+ return $names{lc($topicName)};
1252
+ };
1253
+
1254
+
1255
+ #
1256
+ # Function: IsValidType
1257
+ #
1258
+ # Returns whether the passed <TopicType> is defined.
1259
+ #
1260
+ sub IsValidType #(type)
1261
+ {
1262
+ my ($self, $type) = @_;
1263
+ return exists $types{$type};
1264
+ };
1265
+
1266
+
1267
+ #
1268
+ # Function: TypeFromLegacy
1269
+ #
1270
+ # Returns a <TopicType> for the passed legacy topic type integer. <TopicTypes> were changed from integer constants to
1271
+ # strings in 1.3.
1272
+ #
1273
+ sub TypeFromLegacy #(legacyInt)
1274
+ {
1275
+ my ($self, $int) = @_;
1276
+ return $legacyTypes[$int];
1277
+ };
1278
+
1279
+
1280
+ #
1281
+ # Function: AllIndexableTypes
1282
+ #
1283
+ # Returns an array of all possible indexable <TopicTypes>.
1284
+ #
1285
+ sub AllIndexableTypes
1286
+ {
1287
+ my ($self) = @_;
1288
+ return keys %indexable;
1289
+ };
1290
+
1291
+
1292
+
1293
+ ###############################################################################
1294
+ # Group: Support Functions
1295
+
1296
+
1297
+ #
1298
+ # Function: MakeTopicType
1299
+ #
1300
+ # Returns a <TopicType> for the passed topic name. It does not check to see if it exists already.
1301
+ #
1302
+ # Parameters:
1303
+ #
1304
+ sub MakeTopicType #(topicName)
1305
+ {
1306
+ my ($self, $topicName) = @_;
1307
+
1308
+ # Dependency: The values of the default topic type constants must match what is generated here.
1309
+
1310
+ # Turn everything to lowercase and strip non-alphanumeric characters.
1311
+ $topicName = lc($topicName);
1312
+ $topicName =~ tr/a-z0-9//cd;
1313
+
1314
+ return $topicName;
1315
+ };
1316
+
1317
+
1318
+
1319
+ 1;