cf-mcp 0.10.1 → 0.12.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -2
- data/Manifest.txt +4 -0
- data/README.md +3 -5
- data/config.ru +6 -0
- data/lib/cf/mcp/cli.rb +21 -113
- data/lib/cf/mcp/index_builder.rb +89 -0
- data/lib/cf/mcp/models/doc_item.rb +46 -21
- data/lib/cf/mcp/models/enum_doc.rb +11 -48
- data/lib/cf/mcp/models/function_doc.rb +31 -54
- data/lib/cf/mcp/models/struct_doc.rb +11 -48
- data/lib/cf/mcp/server.rb +23 -59
- data/lib/cf/mcp/templates/index.erb +2 -6
- data/lib/cf/mcp/tools/find_related.rb +3 -8
- data/lib/cf/mcp/tools/get_details.rb +3 -8
- data/lib/cf/mcp/tools/get_topic.rb +3 -8
- data/lib/cf/mcp/tools/list_category.rb +3 -8
- data/lib/cf/mcp/tools/list_topics.rb +3 -8
- data/lib/cf/mcp/tools/member_search.rb +3 -8
- data/lib/cf/mcp/tools/parameter_search.rb +3 -8
- data/lib/cf/mcp/tools/response_helpers.rb +19 -0
- data/lib/cf/mcp/tools/search_enums.rb +14 -23
- data/lib/cf/mcp/tools/search_functions.rb +14 -23
- data/lib/cf/mcp/tools/search_result_formatter.rb +30 -0
- data/lib/cf/mcp/tools/search_structs.rb +14 -23
- data/lib/cf/mcp/tools/search_tool.rb +14 -23
- data/lib/cf/mcp/version.rb +1 -1
- data/lib/cf/mcp.rb +1 -0
- metadata +5 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 30c68992a64d36c8265af4bdcd018dd116c7d2e59479ab1fd83213896028b86d
|
|
4
|
+
data.tar.gz: 4a4e5b715cdca959296e1043bf3173a2c4c314a40ab5c1cb76154dd20b823557
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1704a19c8b49fb37258b247e5689a15f7ed67a2cce9ff226ee5ac0c4689dbc45b547150d426cc91e15e09a2f36405752f58a98e5b14596e5282dc7b9784c4e15
|
|
7
|
+
data.tar.gz: d1c5c7f81871cddb2f0a1bb81b98272b7d3d07a8d7d40bfafd08c338ef2e6b8073d296407ae2dd74575b7ec2738864c1c5bd941408f9f681e373002af363a70d
|
data/CHANGELOG.md
CHANGED
|
@@ -5,19 +5,41 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.12.1] - 2026-01-14
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- Refactored tool classes to use shared `ResponseHelpers` module, removing duplicate code
|
|
13
|
+
- Extracted `IndexBuilder` class to consolidate index building logic from CLI and HTTPServer
|
|
14
|
+
- Extracted `SearchResultFormatter` module for consistent search result formatting
|
|
15
|
+
- Simplified model `to_text()` methods using template method pattern in `DocItem` base class
|
|
16
|
+
|
|
17
|
+
## [0.12.0] - 2026-01-14
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- Renamed `CombinedServer` to `HTTPServer` for clarity
|
|
22
|
+
- Updated config.ru to use the new `HTTPServer` class
|
|
23
|
+
|
|
24
|
+
### Removed
|
|
25
|
+
|
|
26
|
+
- SSE transport endpoint (HTTP streamable transport is now the only HTTP option)
|
|
27
|
+
|
|
8
28
|
## [0.10.1] - 2026-01-14
|
|
9
29
|
|
|
10
30
|
### Added
|
|
11
31
|
|
|
12
32
|
- `--host` CLI option for binding address (defaults to `0.0.0.0`)
|
|
33
|
+
- `CombinedServer.build_rack_app` class method for shared boot logic
|
|
13
34
|
|
|
14
35
|
### Changed
|
|
15
36
|
|
|
16
|
-
- Unified boot process:
|
|
37
|
+
- Unified boot process: config.ru and CLI now share the same initialization logic
|
|
38
|
+
- Simplified config.ru to a single line using `CombinedServer.build_rack_app`
|
|
17
39
|
|
|
18
40
|
### Removed
|
|
19
41
|
|
|
20
|
-
- `
|
|
42
|
+
- `Procfile` (Fly.io uses config.ru directly)
|
|
21
43
|
|
|
22
44
|
## [0.10.0] - 2026-01-14
|
|
23
45
|
|
|
@@ -126,6 +148,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
126
148
|
- `cf_list_category` - List items by category
|
|
127
149
|
- `cf_get_details` - Get full documentation by name
|
|
128
150
|
|
|
151
|
+
[0.12.1]: https://github.com/pusewicz/cf-mcp/compare/v0.12.0...v0.12.1
|
|
152
|
+
[0.12.0]: https://github.com/pusewicz/cf-mcp/compare/v0.10.1...v0.12.0
|
|
129
153
|
[0.10.1]: https://github.com/pusewicz/cf-mcp/compare/v0.10.0...v0.10.1
|
|
130
154
|
[0.10.0]: https://github.com/pusewicz/cf-mcp/compare/v0.9.3...v0.10.0
|
|
131
155
|
[0.9.3]: https://github.com/pusewicz/cf-mcp/compare/v0.9.2...v0.9.3
|
data/Manifest.txt
CHANGED
|
@@ -3,11 +3,13 @@ LICENSE.txt
|
|
|
3
3
|
Manifest.txt
|
|
4
4
|
README.md
|
|
5
5
|
Rakefile
|
|
6
|
+
config.ru
|
|
6
7
|
exe/cf-mcp
|
|
7
8
|
lib/cf/mcp.rb
|
|
8
9
|
lib/cf/mcp/cli.rb
|
|
9
10
|
lib/cf/mcp/downloader.rb
|
|
10
11
|
lib/cf/mcp/index.rb
|
|
12
|
+
lib/cf/mcp/index_builder.rb
|
|
11
13
|
lib/cf/mcp/models/doc_item.rb
|
|
12
14
|
lib/cf/mcp/models/enum_doc.rb
|
|
13
15
|
lib/cf/mcp/models/function_doc.rb
|
|
@@ -25,8 +27,10 @@ lib/cf/mcp/tools/list_category.rb
|
|
|
25
27
|
lib/cf/mcp/tools/list_topics.rb
|
|
26
28
|
lib/cf/mcp/tools/member_search.rb
|
|
27
29
|
lib/cf/mcp/tools/parameter_search.rb
|
|
30
|
+
lib/cf/mcp/tools/response_helpers.rb
|
|
28
31
|
lib/cf/mcp/tools/search_enums.rb
|
|
29
32
|
lib/cf/mcp/tools/search_functions.rb
|
|
33
|
+
lib/cf/mcp/tools/search_result_formatter.rb
|
|
30
34
|
lib/cf/mcp/tools/search_structs.rb
|
|
31
35
|
lib/cf/mcp/tools/search_tool.rb
|
|
32
36
|
lib/cf/mcp/topic_parser.rb
|
data/README.md
CHANGED
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
CF::MCP is an MCP server providing documentation tools for the [Cute Framework](https://github.com/RandyGaul/cute_framework), a C/C++ 2D game framework.
|
|
4
4
|
|
|
5
|
-
The MCP server supports
|
|
5
|
+
The MCP server supports two modes of operation:
|
|
6
6
|
|
|
7
7
|
- **STDIO Mode**: Communicates via standard input and output streams, suitable for integration with CLI tools and desktop applications.
|
|
8
|
-
- **HTTP Mode**: Operates as
|
|
9
|
-
- **SSE Mode**: Operates as a stateful HTTP server with Server-Sent Events support, enabling real-time notifications and streaming responses.
|
|
8
|
+
- **HTTP Mode**: Operates as an HTTP server with a web interface at the root and MCP endpoint at `/http`.
|
|
10
9
|
|
|
11
10
|
## Features
|
|
12
11
|
|
|
@@ -33,8 +32,7 @@ To start the MCP server, run the following command in your terminal:
|
|
|
33
32
|
|
|
34
33
|
```bash
|
|
35
34
|
cf-mcp stdio --root /path/to/cute_framework_project # STDIO mode
|
|
36
|
-
cf-mcp http --root /path/to/cute_framework_project # HTTP mode
|
|
37
|
-
cf-mcp sse --root /path/to/cute_framework_project # SSE mode (stateful, real-time)
|
|
35
|
+
cf-mcp http --root /path/to/cute_framework_project # HTTP mode with web UI
|
|
38
36
|
```
|
|
39
37
|
|
|
40
38
|
## Development
|
data/config.ru
ADDED
data/lib/cf/mcp/cli.rb
CHANGED
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "optparse"
|
|
4
|
-
require_relative "
|
|
5
|
-
require_relative "topic_parser"
|
|
6
|
-
require_relative "index"
|
|
4
|
+
require_relative "index_builder"
|
|
7
5
|
require_relative "server"
|
|
8
|
-
require_relative "downloader"
|
|
9
6
|
|
|
10
7
|
module CF
|
|
11
8
|
module MCP
|
|
12
9
|
class CLI
|
|
13
|
-
DEFAULT_HEADERS_PATH = File.expand_path("~/Work/GitHub/pusewicz/cute_framework/include")
|
|
14
|
-
|
|
15
10
|
def initialize(args)
|
|
16
11
|
@args = args
|
|
17
12
|
@options = parse_args
|
|
@@ -22,11 +17,7 @@ module CF
|
|
|
22
17
|
when :stdio
|
|
23
18
|
run_server(:stdio)
|
|
24
19
|
when :http
|
|
25
|
-
|
|
26
|
-
when :sse
|
|
27
|
-
run_server(:sse)
|
|
28
|
-
when :combined
|
|
29
|
-
run_combined_server
|
|
20
|
+
run_http_server
|
|
30
21
|
when :help
|
|
31
22
|
puts @option_parser
|
|
32
23
|
else
|
|
@@ -51,9 +42,7 @@ module CF
|
|
|
51
42
|
opts.separator ""
|
|
52
43
|
opts.separator "Commands:"
|
|
53
44
|
opts.separator " stdio Run in STDIO mode (for CLI integration)"
|
|
54
|
-
opts.separator " http Run as HTTP server
|
|
55
|
-
opts.separator " sse Run as SSE server (stateful with real-time updates)"
|
|
56
|
-
opts.separator " combined Run as combined server (SSE + HTTP with web interface)"
|
|
45
|
+
opts.separator " http Run as HTTP server with web interface"
|
|
57
46
|
opts.separator ""
|
|
58
47
|
opts.separator "Options:"
|
|
59
48
|
|
|
@@ -61,7 +50,7 @@ module CF
|
|
|
61
50
|
options[:root] = path
|
|
62
51
|
end
|
|
63
52
|
|
|
64
|
-
opts.on("-p", "--port PORT", Integer, "Port for HTTP
|
|
53
|
+
opts.on("-p", "--port PORT", Integer, "Port for HTTP server (default: 9292)") do |port|
|
|
65
54
|
options[:port] = port
|
|
66
55
|
end
|
|
67
56
|
|
|
@@ -88,7 +77,7 @@ module CF
|
|
|
88
77
|
# Parse command from remaining args
|
|
89
78
|
if options[:command].nil? && !@args.empty?
|
|
90
79
|
command = @args.shift.to_sym
|
|
91
|
-
options[:command] = command if [:stdio, :http
|
|
80
|
+
options[:command] = command if [:stdio, :http].include?(command)
|
|
92
81
|
end
|
|
93
82
|
|
|
94
83
|
options[:command] ||= :help
|
|
@@ -96,122 +85,41 @@ module CF
|
|
|
96
85
|
end
|
|
97
86
|
|
|
98
87
|
def run_server(mode)
|
|
99
|
-
|
|
88
|
+
builder = IndexBuilder.new(root: @options[:root], download: @options[:download])
|
|
100
89
|
|
|
101
|
-
unless
|
|
102
|
-
warn "Error: Headers directory not found: #{headers_path}"
|
|
90
|
+
unless builder.valid?
|
|
91
|
+
warn "Error: Headers directory not found: #{builder.headers_path}"
|
|
103
92
|
warn "Use --root to specify the path to Cute Framework headers"
|
|
104
93
|
warn "Or use --download to fetch headers from GitHub"
|
|
105
94
|
exit 1
|
|
106
95
|
end
|
|
107
96
|
|
|
108
|
-
warn "Parsing headers from: #{headers_path}"
|
|
109
|
-
index =
|
|
97
|
+
warn "Parsing headers from: #{builder.headers_path}"
|
|
98
|
+
index = builder.build do |event, path, count|
|
|
99
|
+
warn "Indexed #{count} topics from: #{path}" if event == :topics_indexed
|
|
100
|
+
end
|
|
110
101
|
warn "Indexed #{index.stats[:total]} items (#{index.stats[:functions]} functions, #{index.stats[:structs]} structs, #{index.stats[:enums]} enums)"
|
|
111
102
|
|
|
112
103
|
server = Server.new(index)
|
|
113
|
-
|
|
114
|
-
case mode
|
|
115
|
-
when :stdio
|
|
116
|
-
server.run_stdio
|
|
117
|
-
when :http
|
|
118
|
-
port = @options[:port] || 9292
|
|
119
|
-
server.run_http(port: port)
|
|
120
|
-
when :sse
|
|
121
|
-
port = @options[:port] || 9393
|
|
122
|
-
server.run_sse(port: port)
|
|
123
|
-
end
|
|
104
|
+
server.run_stdio
|
|
124
105
|
end
|
|
125
106
|
|
|
126
|
-
def
|
|
127
|
-
require "rack"
|
|
107
|
+
def run_http_server
|
|
128
108
|
require "rackup"
|
|
129
109
|
|
|
130
|
-
headers_path = resolve_headers_path
|
|
131
|
-
|
|
132
|
-
unless File.directory?(headers_path)
|
|
133
|
-
warn "Error: Headers directory not found: #{headers_path}"
|
|
134
|
-
warn "Use --root to specify the path to Cute Framework headers"
|
|
135
|
-
warn "Or use --download to fetch headers from GitHub"
|
|
136
|
-
exit 1
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
warn "Parsing headers from: #{headers_path}"
|
|
140
|
-
index = build_index(headers_path)
|
|
141
|
-
warn "Indexed #{index.stats[:total]} items (#{index.stats[:functions]} functions, #{index.stats[:structs]} structs, #{index.stats[:enums]} enums)"
|
|
142
|
-
|
|
143
110
|
port = @options[:port] || 9292
|
|
144
111
|
host = @options[:host]
|
|
145
|
-
server = CombinedServer.new(index)
|
|
146
|
-
app = server.rack_app
|
|
147
112
|
|
|
148
|
-
|
|
113
|
+
app = HTTPServer.build_rack_app(
|
|
114
|
+
root: @options[:root],
|
|
115
|
+
download: @options[:download]
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
warn "Starting HTTP server on #{host}:#{port}..."
|
|
149
119
|
warn "Web interface available at http://localhost:#{port}/"
|
|
120
|
+
warn "MCP endpoint available at http://localhost:#{port}/http"
|
|
150
121
|
Rackup::Server.start(app: app, Host: host, Port: port, Logger: $stderr)
|
|
151
122
|
end
|
|
152
|
-
|
|
153
|
-
def resolve_headers_path
|
|
154
|
-
return @options[:root] if @options[:root]
|
|
155
|
-
return ENV["CF_HEADERS_PATH"] if ENV["CF_HEADERS_PATH"]
|
|
156
|
-
|
|
157
|
-
if @options[:download]
|
|
158
|
-
warn "Downloading Cute Framework headers from GitHub..."
|
|
159
|
-
downloader = Downloader.new
|
|
160
|
-
path = downloader.download_and_extract
|
|
161
|
-
warn "Downloaded headers to: #{path}"
|
|
162
|
-
return path
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
DEFAULT_HEADERS_PATH
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
def build_index(headers_path)
|
|
169
|
-
parser = Parser.new
|
|
170
|
-
index = Index.new
|
|
171
|
-
|
|
172
|
-
parser.parse_directory(headers_path).each do |item|
|
|
173
|
-
index.add(item)
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
# Parse topics if available
|
|
177
|
-
topics_path = find_topics_path(headers_path)
|
|
178
|
-
if topics_path && File.directory?(topics_path)
|
|
179
|
-
topic_parser = TopicParser.new
|
|
180
|
-
topic_parser.parse_directory(topics_path).each do |topic|
|
|
181
|
-
refine_topic_references(topic, index)
|
|
182
|
-
index.add(topic)
|
|
183
|
-
end
|
|
184
|
-
warn "Indexed #{index.stats[:topics]} topics from: #{topics_path}"
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
index
|
|
188
|
-
end
|
|
189
|
-
|
|
190
|
-
def find_topics_path(headers_path)
|
|
191
|
-
# If headers_path is .../cute_framework/include, topics is at .../cute_framework/docs/topics
|
|
192
|
-
base = File.dirname(headers_path)
|
|
193
|
-
topics_path = File.join(base, "docs", "topics")
|
|
194
|
-
return topics_path if File.directory?(topics_path)
|
|
195
|
-
|
|
196
|
-
# Alternative: topics directly under headers parent
|
|
197
|
-
topics_path = File.join(base, "topics")
|
|
198
|
-
return topics_path if File.directory?(topics_path)
|
|
199
|
-
|
|
200
|
-
nil
|
|
201
|
-
end
|
|
202
|
-
|
|
203
|
-
def refine_topic_references(topic, index)
|
|
204
|
-
# Move items from struct_references to enum_references if they're actually enums
|
|
205
|
-
topic.struct_references.dup.each do |ref|
|
|
206
|
-
item = index.find(ref)
|
|
207
|
-
next unless item
|
|
208
|
-
|
|
209
|
-
if item.type == :enum
|
|
210
|
-
topic.struct_references.delete(ref)
|
|
211
|
-
topic.enum_references << ref unless topic.enum_references.include?(ref)
|
|
212
|
-
end
|
|
213
|
-
end
|
|
214
|
-
end
|
|
215
123
|
end
|
|
216
124
|
end
|
|
217
125
|
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "parser"
|
|
4
|
+
require_relative "topic_parser"
|
|
5
|
+
require_relative "index"
|
|
6
|
+
require_relative "downloader"
|
|
7
|
+
|
|
8
|
+
module CF
|
|
9
|
+
module MCP
|
|
10
|
+
class IndexBuilder
|
|
11
|
+
DEFAULT_HEADERS_PATH = File.expand_path("~/Work/GitHub/pusewicz/cute_framework/include")
|
|
12
|
+
|
|
13
|
+
attr_reader :headers_path
|
|
14
|
+
|
|
15
|
+
def initialize(root: nil, download: false)
|
|
16
|
+
@headers_path = resolve_headers_path(root: root, download: download)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def build
|
|
20
|
+
parser = Parser.new
|
|
21
|
+
index = Index.new
|
|
22
|
+
|
|
23
|
+
parser.parse_directory(headers_path).each do |item|
|
|
24
|
+
index.add(item)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Parse topics if available
|
|
28
|
+
topics_path = find_topics_path(headers_path)
|
|
29
|
+
if topics_path && File.directory?(topics_path)
|
|
30
|
+
topic_parser = TopicParser.new
|
|
31
|
+
topic_parser.parse_directory(topics_path).each do |topic|
|
|
32
|
+
refine_topic_references(topic, index)
|
|
33
|
+
index.add(topic)
|
|
34
|
+
end
|
|
35
|
+
yield(:topics_indexed, topics_path, index.stats[:topics]) if block_given?
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
index
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def valid?
|
|
42
|
+
File.directory?(headers_path)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def resolve_headers_path(root:, download:)
|
|
48
|
+
return root if root
|
|
49
|
+
return ENV["CF_HEADERS_PATH"] if ENV["CF_HEADERS_PATH"]
|
|
50
|
+
|
|
51
|
+
if download
|
|
52
|
+
warn "Downloading Cute Framework headers from GitHub..."
|
|
53
|
+
downloader = Downloader.new
|
|
54
|
+
path = downloader.download_and_extract
|
|
55
|
+
warn "Downloaded headers to: #{path}"
|
|
56
|
+
return path
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
DEFAULT_HEADERS_PATH
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def find_topics_path(headers_path)
|
|
63
|
+
# If headers_path is .../cute_framework/include, topics is at .../cute_framework/docs/topics
|
|
64
|
+
base = File.dirname(headers_path)
|
|
65
|
+
topics_path = File.join(base, "docs", "topics")
|
|
66
|
+
return topics_path if File.directory?(topics_path)
|
|
67
|
+
|
|
68
|
+
# Alternative: topics directly under headers parent
|
|
69
|
+
topics_path = File.join(base, "topics")
|
|
70
|
+
return topics_path if File.directory?(topics_path)
|
|
71
|
+
|
|
72
|
+
nil
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def refine_topic_references(topic, index)
|
|
76
|
+
# Move items from struct_references to enum_references if they're actually enums
|
|
77
|
+
topic.struct_references.dup.each do |ref|
|
|
78
|
+
item = index.find(ref)
|
|
79
|
+
next unless item
|
|
80
|
+
|
|
81
|
+
if item.type == :enum
|
|
82
|
+
topic.struct_references.delete(ref)
|
|
83
|
+
topic.enum_references << ref unless topic.enum_references.include?(ref)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -128,6 +128,23 @@ module CF
|
|
|
128
128
|
end
|
|
129
129
|
|
|
130
130
|
def to_text(detailed: false, index: nil)
|
|
131
|
+
lines = []
|
|
132
|
+
lines.concat(build_header_lines)
|
|
133
|
+
lines.concat(build_description_lines)
|
|
134
|
+
|
|
135
|
+
if detailed
|
|
136
|
+
lines.concat(build_type_specific_lines)
|
|
137
|
+
lines.concat(build_remarks_lines)
|
|
138
|
+
lines.concat(build_example_lines)
|
|
139
|
+
lines.concat(build_related_lines(index))
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
lines.join("\n")
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
protected
|
|
146
|
+
|
|
147
|
+
def build_header_lines
|
|
131
148
|
lines = []
|
|
132
149
|
lines << "# #{name}"
|
|
133
150
|
lines << ""
|
|
@@ -140,36 +157,44 @@ module CF
|
|
|
140
157
|
lines << "- **Implementation:** #{urls[:impl_raw]}"
|
|
141
158
|
end
|
|
142
159
|
lines << ""
|
|
160
|
+
lines
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def build_description_lines
|
|
164
|
+
lines = []
|
|
143
165
|
lines << "## Description"
|
|
144
166
|
lines << brief if brief
|
|
145
167
|
lines << ""
|
|
168
|
+
lines
|
|
169
|
+
end
|
|
146
170
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
lines << remarks
|
|
151
|
-
lines << ""
|
|
152
|
-
end
|
|
171
|
+
def build_type_specific_lines
|
|
172
|
+
[] # Override in subclasses
|
|
173
|
+
end
|
|
153
174
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
lines << example
|
|
159
|
-
lines << "```"
|
|
160
|
-
lines << ""
|
|
161
|
-
end
|
|
175
|
+
def build_remarks_lines
|
|
176
|
+
return [] unless remarks && !remarks.empty?
|
|
177
|
+
["## Remarks", remarks, ""]
|
|
178
|
+
end
|
|
162
179
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
180
|
+
def build_example_lines
|
|
181
|
+
return [] unless example && !example.empty?
|
|
182
|
+
lines = ["## Example"]
|
|
183
|
+
lines << example_brief if example_brief
|
|
184
|
+
lines << "```c"
|
|
185
|
+
lines << example
|
|
186
|
+
lines << "```"
|
|
187
|
+
lines << ""
|
|
188
|
+
lines
|
|
189
|
+
end
|
|
169
190
|
|
|
170
|
-
|
|
191
|
+
def build_related_lines(index)
|
|
192
|
+
return [] unless related && !related.empty?
|
|
193
|
+
["## Related", format_related_items(index), ""]
|
|
171
194
|
end
|
|
172
195
|
|
|
196
|
+
public
|
|
197
|
+
|
|
173
198
|
def format_related_items(index)
|
|
174
199
|
return related.join(", ") unless index
|
|
175
200
|
|
|
@@ -24,58 +24,21 @@ module CF
|
|
|
24
24
|
).compact
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
protected
|
|
28
|
+
|
|
29
|
+
def build_type_specific_lines
|
|
30
|
+
return [] unless entries && !entries.empty?
|
|
31
|
+
|
|
28
32
|
lines = []
|
|
29
|
-
lines << "
|
|
33
|
+
lines << "## Values"
|
|
30
34
|
lines << ""
|
|
31
|
-
lines << "
|
|
32
|
-
lines << "
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
lines << "- **Source:** [include/#{source_file}](#{urls[:blob]})"
|
|
36
|
-
lines << "- **Raw:** #{urls[:raw]}"
|
|
37
|
-
lines << "- **Implementation:** #{urls[:impl_raw]}"
|
|
35
|
+
lines << "| Name | Value | Description |"
|
|
36
|
+
lines << "| --- | --- | --- |"
|
|
37
|
+
entries.each do |entry|
|
|
38
|
+
lines << "| `#{entry.name}` | #{entry.value} | #{entry.description} |"
|
|
38
39
|
end
|
|
39
40
|
lines << ""
|
|
40
|
-
lines
|
|
41
|
-
lines << brief if brief
|
|
42
|
-
lines << ""
|
|
43
|
-
|
|
44
|
-
if detailed
|
|
45
|
-
if entries && !entries.empty?
|
|
46
|
-
lines << "## Values"
|
|
47
|
-
lines << ""
|
|
48
|
-
lines << "| Name | Value | Description |"
|
|
49
|
-
lines << "| --- | --- | --- |"
|
|
50
|
-
entries.each do |entry|
|
|
51
|
-
lines << "| `#{entry.name}` | #{entry.value} | #{entry.description} |"
|
|
52
|
-
end
|
|
53
|
-
lines << ""
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
if remarks && !remarks.empty?
|
|
57
|
-
lines << "## Remarks"
|
|
58
|
-
lines << remarks
|
|
59
|
-
lines << ""
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
if example && !example.empty?
|
|
63
|
-
lines << "## Example"
|
|
64
|
-
lines << example_brief if example_brief
|
|
65
|
-
lines << "```c"
|
|
66
|
-
lines << example
|
|
67
|
-
lines << "```"
|
|
68
|
-
lines << ""
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
if related && !related.empty?
|
|
72
|
-
lines << "## Related"
|
|
73
|
-
lines << format_related_items(index)
|
|
74
|
-
lines << ""
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
lines.join("\n")
|
|
41
|
+
lines
|
|
79
42
|
end
|
|
80
43
|
end
|
|
81
44
|
end
|
|
@@ -38,71 +38,48 @@ module CF
|
|
|
38
38
|
|
|
39
39
|
def to_text(detailed: false, index: nil)
|
|
40
40
|
lines = []
|
|
41
|
-
lines
|
|
42
|
-
lines
|
|
43
|
-
lines
|
|
44
|
-
lines << "- **Category:** #{category}" if category
|
|
45
|
-
if source_file
|
|
46
|
-
urls = source_urls
|
|
47
|
-
lines << "- **Source:** [include/#{source_file}](#{urls[:blob]})"
|
|
48
|
-
lines << "- **Raw:** #{urls[:raw]}"
|
|
49
|
-
lines << "- **Implementation:** #{urls[:impl_raw]}"
|
|
50
|
-
end
|
|
51
|
-
lines << ""
|
|
41
|
+
lines.concat(build_header_lines)
|
|
42
|
+
lines.concat(build_signature_lines)
|
|
43
|
+
lines.concat(build_description_lines)
|
|
52
44
|
|
|
53
|
-
if
|
|
54
|
-
lines
|
|
55
|
-
lines
|
|
56
|
-
lines
|
|
57
|
-
lines
|
|
58
|
-
lines << ""
|
|
45
|
+
if detailed
|
|
46
|
+
lines.concat(build_type_specific_lines)
|
|
47
|
+
lines.concat(build_remarks_lines)
|
|
48
|
+
lines.concat(build_example_lines)
|
|
49
|
+
lines.concat(build_related_lines(index))
|
|
59
50
|
end
|
|
60
51
|
|
|
61
|
-
lines
|
|
62
|
-
|
|
63
|
-
lines << ""
|
|
52
|
+
lines.join("\n")
|
|
53
|
+
end
|
|
64
54
|
|
|
65
|
-
|
|
66
|
-
if parameters && !parameters.empty?
|
|
67
|
-
lines << "## Parameters"
|
|
68
|
-
lines << ""
|
|
69
|
-
lines << "| Parameter | Description |"
|
|
70
|
-
lines << "| --- | --- |"
|
|
71
|
-
parameters.each do |param|
|
|
72
|
-
lines << "| `#{param.name}` | #{param.description} |"
|
|
73
|
-
end
|
|
74
|
-
lines << ""
|
|
75
|
-
end
|
|
55
|
+
protected
|
|
76
56
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
end
|
|
57
|
+
def build_signature_lines
|
|
58
|
+
return [] unless signature
|
|
59
|
+
["## Signature", "```c", signature, "```", ""]
|
|
60
|
+
end
|
|
82
61
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
lines << remarks
|
|
86
|
-
lines << ""
|
|
87
|
-
end
|
|
62
|
+
def build_type_specific_lines
|
|
63
|
+
lines = []
|
|
88
64
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
lines << ""
|
|
65
|
+
if parameters && !parameters.empty?
|
|
66
|
+
lines << "## Parameters"
|
|
67
|
+
lines << ""
|
|
68
|
+
lines << "| Parameter | Description |"
|
|
69
|
+
lines << "| --- | --- |"
|
|
70
|
+
parameters.each do |param|
|
|
71
|
+
lines << "| `#{param.name}` | #{param.description} |"
|
|
96
72
|
end
|
|
73
|
+
lines << ""
|
|
74
|
+
end
|
|
97
75
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
end
|
|
76
|
+
if return_value && !return_value.empty?
|
|
77
|
+
lines << "## Return Value"
|
|
78
|
+
lines << return_value
|
|
79
|
+
lines << ""
|
|
103
80
|
end
|
|
104
81
|
|
|
105
|
-
lines
|
|
82
|
+
lines
|
|
106
83
|
end
|
|
107
84
|
end
|
|
108
85
|
end
|