8
8
package = "obsws"
9
9
10
10
type_map = {
11
+ "bool" : "bool" ,
11
12
"boolean" : "bool" ,
12
13
"int" : "int" ,
14
+ "float" : "float64" ,
13
15
"double" : "float64" ,
14
16
"string" : "string" ,
15
17
"array" : "[]string" ,
@@ -36,36 +38,37 @@ def optional_type(s: str) -> Tuple[str, bool]:
36
38
37
39
38
40
def process_json (d : Dict ):
39
- process_events (d ["events" ])
40
- process_requests (d ["requests" ])
41
+ gen_events (d ["events" ])
42
+ gen_requests (d ["requests" ])
41
43
42
44
43
- def process_events (events : Dict ):
45
+ def gen_events (events : Dict ):
46
+ """Generate all events."""
44
47
for category , data in events .items ():
45
- process_events_category (category , data )
48
+ gen_events_category (category , data )
46
49
47
50
48
- def process_events_category (category : str , data : Dict ):
49
- events = "\n \n " .join (generate_event (event ) for event in data )
51
+ def gen_events_category (category : str , data : Dict ):
52
+ """Generate all events in one category."""
53
+ events = "\n \n " .join (gen_event (event ) for event in data )
50
54
with open (go_filename ("events" , category ), "w" ) as f :
51
55
f .write (f"""\
52
56
package { package }
53
57
54
- // This code is automatically generated.
55
- // See: https://github.com/christopher-dG/go-obs-websocket/blob/master/codegen/protocol.py
56
-
57
- // https://github.com/Palakis/obs-websocket/blob/master/docs/generated/protocol.md#{ category }
58
+ // This file is automatically generated.
59
+ // https://github.com/christopher-dG/go-obs-websocket/blob/master/codegen/protocol.py
58
60
59
61
{ events }
60
62
""" )
61
63
62
64
63
- def generate_event (data : Dict ) -> str :
64
- """Generate Go code with type definitions and interface functions."""
65
- if "returns" in data :
65
+ def gen_event (data : Dict ) -> str :
66
+ """Write Go code with a type definition and interface functions."""
67
+ reserved = ["Type" , "StreamTC" , "RecTC" ]
68
+ if data .get ("returns" ):
66
69
struct = f"""\
67
70
type { data ['name' ]} Event struct {{
68
- { go_variables (data ['returns' ])}
71
+ { go_variables (data ['returns' ], reserved )}
69
72
_event
70
73
}}\
71
74
"""
@@ -74,8 +77,10 @@ def generate_event(data: Dict) -> str:
74
77
75
78
description = data ["description" ].replace ("\n " , " " )
76
79
description = f"{ data ['name' ]} Event : { description } "
77
- if "since" in data :
78
- description += f" Since: { data ['since' ].capitalize ()} "
80
+ if description and not description .endswith ("." ):
81
+ description += "."
82
+ if data .get ("since" ):
83
+ description += f" Since: { data ['since' ].capitalize ()} ."
79
84
80
85
return f"""\
81
86
// { description }
@@ -93,44 +98,135 @@ def generate_event(data: Dict) -> str:
93
98
"""
94
99
95
100
96
- def process_requests (requests : Dict ):
97
- pass
101
+ def gen_requests (requests : Dict ):
102
+ """Generate all requests and responses."""
103
+ for category , data in requests .items ():
104
+ gen_requests_category (category , data )
105
+
106
+
107
+ def gen_requests_category (category : str , data : Dict ):
108
+ requests = "\n \n " .join (gen_request (request ) for request in data )
109
+ with open (go_filename ("requests" , category ), "w" ) as f :
110
+ f .write (f"""\
111
+ package { package }
98
112
113
+ // This file is automatically generated.
114
+ // https://github.com/christopher-dG/go-obs-websocket/blob/master/codegen/protocol.py
99
115
100
- def go_variables (vars : List ) -> str :
116
+ { requests }
117
+ """ )
118
+
119
+
120
+ def gen_request (data : Dict ) -> str :
121
+ """Write Go code with type definitions and interface functions."""
122
+ reserved = ["ID" , "Type" ]
123
+ if data .get ("params" ):
124
+ struct = f"""\
125
+ type { data ['name' ]} Request struct {{
126
+ { go_variables (data ['params' ], reserved )}
127
+ _request
128
+ }}
129
+ """
130
+ else :
131
+ struct = f"type { data ['name' ]} Request _request"
132
+
133
+ description = data ["description" ].replace ("\n " , " " )
134
+ description = f"{ data ['name' ]} Request : { description } "
135
+ if description and not description .endswith ("." ):
136
+ description += "."
137
+ if data .get ("since" ):
138
+ description += f" Since: { data ['since' ].capitalize ()} ."
139
+
140
+ request = f"""\
141
+ // { description }
142
+ // https://github.com/Palakis/obs-websocket/blob/master/docs/generated/protocol.md#{ data ['heading' ]['text' ].lower ()}
143
+ { struct }
144
+
145
+ // ID returns the request's message ID.
146
+ func (r { data ['name' ]} Request) ID() string {{ return r.MessageID }}
147
+
148
+ // Type returns the request's message type.
149
+ func (r { data ['name' ]} Request) Type() string {{ return r.RequestType }}
101
150
"""
102
- Convert a list of variable definition into Go code to be put
151
+
152
+ if data .get ("returns" ):
153
+ reserved = ["ID" , "Stat" , "Err" ]
154
+ struct = f"""\
155
+ type { data ['name' ]} Response struct {{
156
+ { go_variables (data ['returns' ], reserved )}
157
+ _response
158
+ }}
159
+ """
160
+ else :
161
+ struct = f"type { data ['name' ]} Response _response"
162
+
163
+ description = f"{ data ['name' ]} Response : Response for { data ['name' ]} Request."
164
+ if data .get ("since" ):
165
+ description += f" Since: { data ['since' ].capitalize ()} ."
166
+
167
+ response = f"""\
168
+ // { description }
169
+ // https://github.com/Palakis/obs-websocket/blob/master/docs/generated/protocol.md#{ data ['heading' ]['text' ].lower ()}
170
+ { struct }
171
+
172
+ // ID returns the response's message ID.
173
+ func (r { data ['name' ]} Response) ID() string {{ return r.MessageID }}
174
+
175
+ // Stat returns the response's status.
176
+ func (r { data ['name' ]} Response) Stat() string {{ return r.Status }}
177
+
178
+ // Err returns the response's error.
179
+ func (r { data ['name' ]} Response) Err() string {{ return r.Error }}
180
+ """
181
+
182
+ return f"{ request } \n \n { response } "
183
+
184
+
185
+ def go_variables (names : List , reserved : List ) -> str :
186
+ """
187
+ Convert a list of variable names into Go code to be put
103
188
inside a struct definition.
104
189
"""
105
- lines = []
106
- for v in vars :
107
- line = go_name (v ["name" ])
190
+ lines , varnames = [], []
191
+ for v in names :
108
192
typename , optional = optional_type (v ["type" ])
109
- line += f" { type_map [typename .lower ()]} // { v ['description' ]} "
193
+ varname = go_var (v ["name" ])
194
+ description = v ["description" ].replace ("\n " , " " )
195
+ if description and not description .endswith ("." ):
196
+ description += "."
197
+ tag = '`json:"%s"`' % v ['name' ]
198
+ line = f"{ go_var (v ['name' ])} { type_map [typename .lower ()]} { tag } // { description } "
110
199
if optional :
111
- line += " Optional."
200
+ line += " Optional." if description else "Optional."
201
+ if varname in reserved :
202
+ line += " TODO: Reserved name."
203
+ if varname in varnames :
204
+ line += " TODO: Duplicate name."
205
+ else :
206
+ varnames .append (varname )
112
207
if typename .lower () in unknown_types :
113
- line += f" TODO: Unknown type ({ typename } )."
208
+ line += f" TODO: Unknown type ({ v [ 'type' ] } )."
114
209
lines .append (line )
115
210
return "\n " .join (lines )
116
211
117
212
118
- def go_name (s : str ) -> str :
119
- """
120
- Convert a variable name in the input file to a Go variable name.
121
- Note: This makes lots of assumptions about the input,
122
- i.e. nothing ends with a separator.
123
- """
124
- s = s .capitalize ()
213
+ def go_var (s : str ) -> str :
214
+ """Convert a variable name in the input file to a Go variable name."""
215
+ s = f"{ s [0 ].upper ()} { s [1 :]} "
125
216
for sep in ["-" , "_" , ".*." , "[]." , "." ]:
126
217
while sep in s :
127
- i = s .find (sep )
128
218
_len = len (sep )
219
+ if s .endswith (sep ):
220
+ s = s [:- _len ]
221
+ continue
222
+ i = s .find (sep )
129
223
s = f"{ s [:i ]} { s [i + _len ].upper ()} { s [i + _len + 1 :]} "
130
- return s
224
+
225
+ return s .replace ("Id" , "ID" ) # Yuck.
131
226
132
227
133
228
def go_filename (category , section ):
229
+ """Generate a Go filename from a category and section."""
134
230
return f"{ category } _{ section .replace (' ' , '_' )} .go"
135
231
136
232
0 commit comments