v0.2.1 c0399be

template.go RawHistoryFolder

1package types
2
3import (
4	"fmt"
5	"strings"
6
7	"github.com/bnema/puregotk/internal/gir/util"
8)
9
10type argsTemplate struct {
11	// Names are the variables but just the names
12	Names []string
13
14	// Types are the variables but just the types
15	Types []string
16
17	// Call are the variables as given in a function call
18	Call []string
19
20	// CallWithRefs is like Call but with callback parameters using {name}Ref
21	// for use in contexts that generate closure wrappers
22	CallWithRefs []string
23
24	Full []string
25}
26
27// CallbackParam holds metadata for callback parameters to enable proper closure generation
28type CallbackParam struct {
29	// Name is the parameter name (e.g., "CallbackVar")
30	Name string
31	// TypeName is the callback type name (e.g., "TickCallback")
32	TypeName string
33	// PureTypes are the pure argument types for the closure
34	PureTypes []string
35	// CallArgs are expressions used when invoking cbFn from closure args
36	CallArgs []string
37	// RetRaw is the return type for the closure (e.g., "bool")
38	RetRaw string
39	// Nullable indicates if the callback can be nil
40	Nullable bool
41}
42
43// NullableStringParam holds metadata for nullable string parameters that need
44// temporary C-owned string allocation with g_strdup/g_free.
45type NullableStringParam struct {
46	// Name is the parameter name (e.g., "DataDirectoryVar")
47	Name string
48}
49
50// GErrorParam tracks a signal/callback parameter that is a GLib.Error record.
51// The Pure type stays uintptr (purego ABI), but the API type is *glib.Error
52// and the signal closure converts via unsafe.Pointer.
53type GErrorParam struct {
54	// Index is the position in the Pure args slice.
55	Index int
56	// GoType is the qualified Go type for the cast (e.g., "glib.Error" or "Error").
57	GoType string
58}
59
60type funcArgsTemplate struct {
61	// Pure are the arguments as passed directly to PureGo
62	// The pure Call is a special case that contains the arguments for a callback call
63	Pure argsTemplate
64
65	// API are the arguments as suitable for a Go API
66	API argsTemplate
67
68	// Callbacks tracks callback parameters for proper closure generation
69	Callbacks []CallbackParam
70
71	// NullableStrings tracks nullable string parameters that need temporary C strings
72	NullableStrings []NullableStringParam
73
74	// GErrors tracks GError record parameters in signal/callback contexts
75	// so PuregoSignalCall can emit unsafe.Pointer casts.
76	GErrors []GErrorParam
77
78	// UsesNullableHelper indicates nullable string handling that needs core import.
79	UsesNullableHelper bool
80
81	// UsesGStrdup indicates transfer-full string handling that needs core import.
82	UsesGStrdup bool
83}
84
85// ArgContext indicates where the arguments are flowing so we can handle
86// direction-sensitive cases (e.g. nullable strings) differently.
87type ArgContext int
88
89const (
90	// ArgsFromGoToC covers regular functions/methods where Go calls into C.
91	ArgsFromGoToC ArgContext = iota
92	// ArgsFromCToGo covers callbacks/signals where C calls into Go.
93	ArgsFromCToGo
94)
95
96func isStringType(t string) bool {
97	if strings.HasPrefix(t, "[]") {
98		return false
99	}
100	return strings.TrimLeft(t, "*") == "string"
101}
102
103// isGErrorType reports whether a GIR type name refers to GLib.Error.
104// Within the GLib namespace the name is just "Error"; elsewhere it is "GLib.Error".
105func isGErrorType(girName string) bool {
106	return girName == "GLib.Error" || girName == "Error"
107}
108
109// NeedsCore reports whether this argument set requires core helpers.
110func (f funcArgsTemplate) NeedsCore() bool {
111	return f.UsesNullableHelper || f.UsesGStrdup
112}
113
114// HasPureStrings reports whether any Pure parameter is a string type.
115// Signal closures with string parameters need core.GoString() conversion.
116func (f funcArgsTemplate) HasPureStrings() bool {
117	for _, t := range f.Pure.Types {
118		if t == "string" {
119			return true
120		}
121	}
122	return false
123}
124
125// PuregoSignalFull returns Pure.Full with string types replaced by uintptr.
126// Used for signal fcb closures passed to purego.NewCallback, which cannot
127// handle Go string parameters (C passes const char* as a pointer).
128func (f funcArgsTemplate) PuregoSignalFull() []string {
129	out := make([]string, len(f.Pure.Full))
130	copy(out, f.Pure.Full)
131	for i, t := range f.Pure.Types {
132		if t == "string" {
133			out[i] = f.Pure.Names[i] + " uintptr"
134		}
135	}
136	return out
137}
138
139// PuregoSignalCall returns Pure.Call with string variables wrapped in
140// core.GoString() for C char* → Go string conversion in signal closures,
141// and GError parameters wrapped in (*glib.Error)(unsafe.Pointer(...)).
142func (f funcArgsTemplate) PuregoSignalCall() []string {
143	out := make([]string, len(f.Pure.Call))
144	copy(out, f.Pure.Call)
145	for i, t := range f.Pure.Types {
146		if t == "string" {
147			out[i] = "core.GoString(" + f.Pure.Names[i] + ")"
148		}
149	}
150	for _, ge := range f.GErrors {
151		out[ge.Index] = "(*" + ge.GoType + ")(unsafe.Pointer(" + f.Pure.Names[ge.Index] + "))"
152	}
153	return out
154}
155
156// HasGErrors reports whether any parameter is a GError that needs
157// an unsafe.Pointer cast in the signal closure.
158func (f funcArgsTemplate) HasGErrors() bool {
159	return len(f.GErrors) > 0
160}
161
162func qualifyCallbackType(t string, callbackNS string, currentNS string) string {
163	if t == "" || callbackNS == "" || strings.EqualFold(callbackNS, currentNS) {
164		return t
165	}
166
167	if strings.Contains(t, ".") {
168		return t
169	}
170
171	ptrPrefix := ""
172	base := t
173	for strings.HasPrefix(base, "*") {
174		ptrPrefix += "*"
175		base = strings.TrimPrefix(base, "*")
176	}
177
178	slicePrefix := ""
179	for strings.HasPrefix(base, "[]") {
180		slicePrefix += "[]"
181		base = strings.TrimPrefix(base, "[]")
182	}
183
184	arrayPrefix := ""
185	for strings.HasPrefix(base, "[") {
186		end := strings.Index(base, "]")
187		if end == -1 {
188			break
189		}
190		arrayPrefix += base[:end+1]
191		base = base[end+1:]
192	}
193
194	switch base {
195	case "bool", "byte", "complex64", "complex128", "error", "float32", "float64", "int", "int8", "int16", "int32", "int64", "rune", "string", "uint", "uint8", "uint16", "uint32", "uint64", "uintptr":
196		return t
197	}
198
199	if base == "" {
200		return t
201	}
202
203	qualifiedBase := callbackNS + "." + base
204	return ptrPrefix + slicePrefix + arrayPrefix + qualifiedBase
205}
206
207func qualifyCallbackTypes(types []string, callbackNS string, currentNS string) []string {
208	qualified := make([]string, len(types))
209	for i, t := range types {
210		qualified[i] = qualifyCallbackType(t, callbackNS, currentNS)
211	}
212	return qualified
213}
214
215func (f *funcArgsTemplate) AddAPI(t string, n string, k Kind, ns string, nullable bool, isOut bool, ctx ArgContext, transferFull bool) {
216	c := n
217	cRef := n // For CallWithRefs, defaults to same as Call
218	stars := strings.Count(t, "*")
219	gobjectNs := "gobject."
220	glibNs := "glib."
221	if strings.ToLower(ns) == "gobject" {
222		gobjectNs = ""
223	}
224	if strings.ToLower(ns) == "glib" {
225		glibNs = ""
226	}
227
228	if isOut {
229		if stars == 0 {
230			// For out parameters, the C type already has a pointer, and so do non-primitive Go types.
231			// For primitive Go types we need to manually add the *
232			t = "*" + t
233		}
234		c = n
235		cRef = n
236	} else {
237		// For transfer-full strings, use g_strdup so GTK can safely g_free() the copy.
238		// This must be checked before nullable handling to avoid conflicting conversions.
239		if ctx == ArgsFromGoToC && transferFull && isStringType(t) {
240			f.UsesGStrdup = true
241			if nullable {
242				// Nullable transfer-full: API type is *string, call uses GStrdupNullable
243				t = "*string"
244				c = fmt.Sprintf("core.GStrdupNullable(%s)", n)
245				cRef = c
246			} else {
247				c = fmt.Sprintf("core.GStrdup(%s)", n)
248				cRef = c
249			}
250		} else if ctx == ArgsFromGoToC && nullable && isStringType(t) {
251			// Nullable strings differ based on direction. For Go->C we need a *string API type
252			// and pass a nullable C pointer to C. For C->Go we keep the string as-is.
253			// We track these parameters so templates can allocate/free a temporary
254			// C-owned copy via g_strdup/g_free around each call.
255			f.UsesNullableHelper = true
256			t = "*string"
257			c = fmt.Sprintf("%sPtr", n)
258			cRef = c
259			// Track this parameter for temp C allocation/free generation
260			f.NullableStrings = append(f.NullableStrings, NullableStringParam{Name: n})
261		}
262
263		switch k {
264		case CallbackType:
265			// Call uses glib.NewCallback for contexts like callback accessor getters
266			if nullable {
267				c = fmt.Sprintf("%sNewCallbackNullable(%s)", glibNs, n)
268			} else {
269				c = fmt.Sprintf("%sNewCallback(%s)", glibNs, n)
270			}
271			// For CallWithRefs, start with the same value as Call
272			// It will be updated to {name}Ref in Add() if the callback lookup succeeds
273			cRef = c
274			t = "*" + t
275		case ClassesType:
276			if stars == 0 {
277				c = n
278				t = "uintptr"
279			} else if stars > 1 {
280				c = fmt.Sprintf("%sConvertPtr(%s)", gobjectNs, n)
281			} else if stars == 1 {
282				c = n + ".GoPointer()"
283			}
284			cRef = c
285		case InterfacesType:
286			t = strings.TrimPrefix(t, "*")
287			if stars == 0 {
288				c = n
289				t = "uintptr"
290			} else if stars > 1 {
291				c = fmt.Sprintf("%sConvertPtr(%s)", gobjectNs, n)
292			} else if stars == 1 {
293				c = n + ".GoPointer()"
294			}
295			cRef = c
296		default:
297			cRef = c
298		}
299
300		// special case for varargs
301		if n == "varArgs" {
302			c = n + "..."
303			cRef = c
304		}
305	}
306
307	f.API.Names = append(f.API.Names, n)
308	f.API.Types = append(f.API.Types, t)
309	f.API.Call = append(f.API.Call, c)
310	f.API.CallWithRefs = append(f.API.CallWithRefs, cRef)
311	f.API.Full = append(f.API.Full, n+" "+t)
312}
313
314func (f *funcArgsTemplate) AddPure(t string, n string, k Kind, isOut bool, nullable bool, ctx ArgContext, transferFull bool) {
315	n += "p"
316	c := n
317	stars := strings.Count(t, "*")
318
319	if isOut {
320		// Out parameters are always pointers in C
321		if stars == 0 {
322			// For primitive Go types we need to manually add the *
323			t = "*" + t
324		}
325		c = n
326	} else {
327		// For transfer-full strings, the pure type must be uintptr to accept
328		// the g_strdup'd pointer from the API call
329		if ctx == ArgsFromGoToC && transferFull && isStringType(t) {
330			t = "uintptr"
331		} else if ctx == ArgsFromGoToC && nullable && isStringType(t) {
332			f.UsesNullableHelper = true
333			t = "uintptr"
334			// Use the pointer variable that will be set up by the template
335			c = fmt.Sprintf("%sPtr", strings.TrimSuffix(n, "p"))
336		}
337
338		switch k {
339		case RecordsType:
340			if stars == 0 {
341				t = "uintptr"
342			}
343		case CallbackType:
344			c = fmt.Sprintf("(*%s)(unsafe.Pointer(%s))", strings.TrimPrefix(t, "*"), n)
345			t = "uintptr"
346		case ClassesType:
347			if stars == 0 {
348				c = n
349				t = "uintptr"
350			} else {
351				// Remove all dereference operators to get the base class name
352				baseName := strings.TrimPrefix(t, strings.Repeat("*", stars))
353				if stars > 1 {
354					// For double pointers like **ParamSpec, we need to pass the double pointer directly
355					c = fmt.Sprintf("(**%s)(unsafe.Pointer(%s))", baseName, n)
356				} else {
357					c = fmt.Sprintf("%sNewFromInternalPtr(%s)", baseName, n)
358				}
359				t = "uintptr"
360			}
361		case InterfacesType:
362			if stars == 0 {
363				c = n
364				t = "uintptr"
365			} else {
366				c = fmt.Sprintf("%s{Ptr: %s}", t+"Base", n)
367				t = strings.Repeat("*", stars-1) + "uintptr"
368			}
369		}
370	}
371	f.Pure.Names = append(f.Pure.Names, n)
372	f.Pure.Types = append(f.Pure.Types, t)
373	f.Pure.Call = append(f.Pure.Call, c)
374	f.Pure.Full = append(f.Pure.Full, n+" "+t)
375}
376
377func (f *funcArgsTemplate) Add(p Parameter, ins string, ns string, kinds KindMap, ctx ArgContext) {
378	// get the lookup namespace
379	// as if the interface namespace is non-empty
380	// means we can also lookup in the namespace of the interface
381	lns := ns
382	if ins != "" {
383		lns = ins
384	}
385	goType := p.Translate(lns, kinds)
386	kind := kinds.Kind(lns, goType)
387
388	// Save the original type name before normalization for callback lookup
389	originalType := goType
390
391	stars := strings.Count(goType, "*")
392	goType = util.NormalizeNamespace(ns, goType, true)
393
394	if kind != OtherType && kind != UnknownType {
395		goType = util.AddNamespace(goType, ins)
396	}
397	if stars > 0 {
398		goType = util.StarsInFront(strings.ReplaceAll(goType, "*", ""), stars)
399	}
400
401	// Get a suitable variable name
402	varName := p.VarName()
403
404	isOut := p.Direction == "out"
405
406	transferFull := p.TransferOwnership.TransferOwnership == "full"
407	f.AddAPI(goType, varName, kind, ns, p.Nullable, isOut, ctx, transferFull)
408	f.AddPure(goType, varName, kind, isOut, p.Nullable, ctx, transferFull)
409
410	// For GError record parameters in signal/callback contexts (C→Go), the type
411	// is collapsed to uintptr by Type.Template(). Override the API type to
412	// *glib.Error so consumers get a proper Go error, and track the Pure index
413	// so PuregoSignalCall() can emit the unsafe.Pointer cast.
414	if ctx == ArgsFromCToGo && !isOut && goType == "uintptr" && p.Type != nil && isGErrorType(p.Type.Name) {
415		gerrorGoType := "glib.Error"
416		if strings.ToLower(ns) == "glib" {
417			gerrorGoType = "Error"
418		}
419		// Override API type from uintptr to *glib.Error
420		apiIdx := len(f.API.Types) - 1
421		f.API.Types[apiIdx] = "*" + gerrorGoType
422		f.API.Full[apiIdx] = varName + " *" + gerrorGoType
423		// Pure stays uintptr; record the index for signal call casting
424		pureIdx := len(f.Pure.Types) - 1
425		f.GErrors = append(f.GErrors, GErrorParam{
426			Index:  pureIdx,
427			GoType: gerrorGoType,
428		})
429	}
430
431	// Upstream purego does not support direct array parameters (reflect.Array kind).
432	// Fixed-size C arrays like "int fds[2]" are pointer params at the ABI level.
433	// For non-out fixed-size array params, change the pure signature to *[N]T and
434	// pass &param from the API wrapper so purego sees a pointer.
435	if p.Array != nil && p.Array.FixedSize > 0 && !isOut {
436		idx := len(f.Pure.Types) - 1
437		f.Pure.Types[idx] = "*" + f.Pure.Types[idx]
438		f.Pure.Full[idx] = f.Pure.Names[idx] + " " + f.Pure.Types[idx]
439		apiIdx := len(f.API.Call) - 1
440		f.API.Call[apiIdx] = "&" + f.API.Call[apiIdx]
441		f.API.CallWithRefs[apiIdx] = "&" + f.API.CallWithRefs[apiIdx]
442	}
443
444	// For callback parameters (not out parameters), populate callback metadata
445	// This enables the template to generate proper closure wrapping
446	if kind == CallbackType && !isOut {
447		if cb, ok := kinds.GetCallback(lns, originalType); ok {
448			// Determine the callback's namespace from the original type name
449			// e.g., "gio.AsyncReadyCallback" -> "gio", "AsyncReadyCallback" -> lns
450			cbNs := lns
451			if parts := strings.Split(originalType, "."); len(parts) > 1 {
452				cbNs = parts[0]
453			}
454
455			// Get the callback's pure argument types and return type
456			// Use cbNs (callback's namespace) for proper type lookups
457			cbArgs := cb.Parameters.Template(cbNs, "", kinds, cb.Throws, ArgsFromCToGo)
458			var retRaw string
459			if cb.ReturnValue != nil {
460				cbRet := cb.ReturnValue.Template(cbNs, "", kinds, cb.Throws)
461				retRaw = cbRet.Raw
462			}
463
464			qualifiedPureTypes := qualifyCallbackTypes(cbArgs.Pure.Types, cbNs, ns)
465			callArgs := make([]string, len(qualifiedPureTypes))
466			for i := range qualifiedPureTypes {
467				callArgs[i] = fmt.Sprintf("arg%d", i)
468				if qualifiedPureTypes[i] == "string" {
469					// C callback string parameters are char* pointers in ABI.
470					qualifiedPureTypes[i] = "uintptr"
471					callArgs[i] = fmt.Sprintf("core.GoString(arg%d)", i)
472				}
473			}
474			qualifiedRetRaw := qualifyCallbackType(retRaw, cbNs, ns)
475
476			f.Callbacks = append(f.Callbacks, CallbackParam{
477				Name:      varName,
478				TypeName:  strings.TrimPrefix(goType, "*"),
479				PureTypes: qualifiedPureTypes,
480				CallArgs:  callArgs,
481				RetRaw:    qualifiedRetRaw,
482				Nullable:  p.Nullable,
483			})
484
485			// Update CallWithRefs to use {name}Ref since we have the callback info
486			// for generating the closure wrapper
487			lastIdx := len(f.API.CallWithRefs) - 1
488			f.API.CallWithRefs[lastIdx] = varName + "Ref"
489		}
490	}
491}
492
493func (f *funcArgsTemplate) AddThrows(ns string) {
494	f.API.Call = append(f.API.Call, "&cerr")
495	f.API.CallWithRefs = append(f.API.CallWithRefs, "&cerr")
496	if strings.ToLower(ns) != "glib" {
497		f.Pure.Types = append(f.Pure.Types, "**glib.Error")
498	} else {
499		f.Pure.Types = append(f.Pure.Types, "**Error")
500	}
501}
502
503type CallbackTemplate struct {
504	Doc  string
505	Name string
506	Args funcArgsTemplate
507	Ret  funcRetTemplate
508}
509
510type AliasTemplate struct {
511	// Name is the name of the alias given to the Go type declaration
512	Name string
513
514	// Doc is the documentation of the alias
515	Doc string
516
517	// Value is the value for the alias as a Go type
518	Value string
519
520	// TypeGetter is the function to get the GLib type
521	TypeGetter string
522}
523
524type RecordField struct {
525	// Name is the Go name of the field
526	Name string
527
528	// Type is the Go type of the field
529	Type string
530}
531
532type CallbackAccessor struct {
533	// Name is the Go name of the callback field (without x prefix)
534	Name string
535
536	// CName is the raw c name
537	CName string
538
539	// Doc is the documentation for the callback
540	Doc string
541
542	// CallbackType is the name of the callback function type
543	CallbackType string
544
545	// Args are the callback function arguments template
546	Args funcArgsTemplate
547
548	// Ret is the callback function return template
549	Ret funcRetTemplate
550}
551
552type RecordTemplate struct {
553	// Name is the name of the record given to the Go type declaration
554	Name string
555
556	// Doc is the documentation of the alias
557	Doc string
558
559	// Constructors is the slice of functions that create the class struct
560	Constructors []FuncTemplate
561
562	// Receivers is the slice of functions that have value receivers to the struct
563	Receivers []FuncTemplate
564
565	// Fields is the list of record fields
566	Fields []RecordField
567
568	// CallbackAccessors are the setter/getter methods for callback fields
569	CallbackAccessors []CallbackAccessor
570
571	// TypeGetter is the function to get the GLib type
572	TypeGetter string
573}
574
575type enumValues struct {
576	// Doc is the documentation for the value
577	Doc string
578	// Name is the name of the enumeration value
579	Name string
580	// Value is the actual underlying value
581	Value int
582}
583
584type EnumTemplate struct {
585	// Name is the name of the enumeration declared as the Go type for the int
586	Name string
587	// Doc is the documentation for the enumeration
588	Doc string
589	// Values are the list of values for the enumeration
590	Values []enumValues
591	// TypeGetter is the function to get the GLib type
592	TypeGetter string
593}
594
595type ConstantTemplate struct {
596	// Name is the name of the constant
597	Name string
598	// Doc is the documentation for the constant
599	Doc string
600	// Type is the Go type for the constant
601	Type string
602	// Values are the list of values for the constant
603	Value string
604}
605
606type funcRetTemplate struct {
607	// Raw is the raw value for the underlying purego function
608	Raw string
609	// Value is the underlying return value as a Go type
610	Value string
611	// Class indicates whether or not the return value is a class
612	Class bool
613	// RefSink indicates whether or not we should increase the reference count using obj.RefSink()
614	RefSink bool
615	// Throws indicates whether or not this function throws
616	Throws bool
617}
618
619func (fr *funcRetTemplate) Instance() string {
620	val := fr.Value + "{}"
621	if strings.HasPrefix(fr.Value, "*") {
622		return "&" + val[1:]
623	}
624	return val
625}
626
627func (fr *funcRetTemplate) Return() string {
628	if fr.Throws {
629		if fr.Value == "" {
630			return "error"
631		}
632		return fmt.Sprintf("(%s, error)", fr.Value)
633	}
634	return fr.Value
635}
636
637func (fr *funcRetTemplate) HasReturn() bool {
638	return fr.Value != "" || fr.Throws
639}
640
641func (fr *funcRetTemplate) Preamble(nglib bool) string {
642	preamb := strings.Builder{}
643	if fr.Class {
644		preamb.WriteString("var cls ")
645		preamb.WriteString(fr.Value)
646		preamb.WriteString("\n")
647	}
648	if fr.Throws {
649		preamb.WriteString("var cerr *")
650		if nglib {
651			preamb.WriteString("glib.")
652		}
653		preamb.WriteString("Error\n")
654	}
655	return preamb.String()
656}
657
658func (fr *funcRetTemplate) Fmt(ngo bool) string {
659	if !fr.HasReturn() {
660		return ""
661	}
662	after := strings.Builder{}
663	val := "cret"
664	if fr.Class {
665		if fr.Throws {
666			after.WriteString(`
667    if cret == 0 {
668        return nil, cerr
669    }
670`)
671		} else {
672			after.WriteString(`
673    if cret == 0 {
674        return nil
675    }
676`)
677		}
678		if fr.RefSink {
679			if ngo {
680				after.WriteString("gobject.")
681			}
682			after.WriteString("IncreaseRef(cret)\n")
683		}
684		after.WriteString("cls = ")
685		after.WriteString(fr.Instance())
686		after.WriteString("\n")
687		after.WriteString("cls.Ptr = cret\n")
688		val = "cls"
689	}
690	if fr.Throws {
691		after.WriteString("if cerr == nil {\n")
692		after.WriteString("return ")
693		if fr.Value != "" {
694			after.WriteString(val)
695			after.WriteString(",")
696		}
697		after.WriteString("nil\n")
698		after.WriteString("}\n")
699		after.WriteString("return ")
700		if fr.Value != "" {
701			after.WriteString(val)
702			after.WriteString(",")
703		}
704		after.WriteString("cerr\n")
705		return after.String()
706	}
707	after.WriteString("return ")
708	after.WriteString(val)
709	return after.String()
710}
711
712type FuncTemplate struct {
713	// Name is the name of the function declared as the Go function variable and public exposed API
714	Name string
715	// CName is the raw c name to be passed to purego register
716	CName string
717	// Doc is the documentation for the function
718	Doc string
719	// Args are the arguments
720	Args funcArgsTemplate
721	// Ret is the return argument
722	Ret funcRetTemplate
723}
724
725type InterfaceFuncTemplate struct {
726	Namespace string
727	FullName  string
728	FuncTemplate
729}
730
731type SignalsTemplate struct {
732	Doc      string
733	Name     string
734	CName    string
735	Args     funcArgsTemplate
736	Ret      funcRetTemplate
737	Detailed bool
738}
739
740type PropertyTemplate struct {
741	// Doc is the documentation for the property
742	Doc string
743	// Name is the Go name for the property
744	Name string
745	// CName is the raw c name
746	CName string
747	// GoType is the Go type for the property
748	GoType string
749	// GValueType is the GObject Type constant (e.g. "TypeBooleanVal")
750	GValueType string
751	// SetMethod is the Value setter method name (e.g. "SetBoolean")
752	SetMethod string
753	// GetMethod is the Value getter method name (e.g. "GetBoolean")
754	GetMethod string
755	// Readable indicates if this property can be read
756	Readable bool
757	// Writable indicates if this property can be written
758	Writable bool
759}
760
761type ClassTemplate struct {
762	// Doc is the documentation for the class
763	Doc string
764	// Name is the name of the class that is given to the Go struct
765	Name string
766	// Parent is a non-empty string of the embedded parent struct
767	Parent string
768	// Constructors is the slice of functions that create the class struct
769	Constructors []FuncTemplate
770	// Receivers is the slice of functions that have value receivers to the struct
771	Receivers []FuncTemplate
772	// Interfaces are receiver methods that are implemented because it needs to satisfy a certain interface
773	Interfaces []InterfaceTemplate
774	// Functions are the Go function declarations
775	Functions []FuncTemplate
776	// Properties are the property getters and setters
777	Properties []PropertyTemplate
778	// Signals are helpers for ConnectX receivers
779	Signals []SignalsTemplate
780	// TypeGetter is the function to get the GLib type
781	TypeGetter string
782}
783
784type InterfaceTemplate struct {
785	Doc  string
786	Name string
787	// Methods is the methods that this interface defines
788	Methods []InterfaceFuncTemplate
789	// Properties are the property getters and setters
790	Properties []PropertyTemplate
791	// TypeGetter is the function to get the GLib type
792	TypeGetter string
793}
794
795type TemplateArg struct {
796	// PkgName is the name of the package, declared at the top-level
797	PkgName string
798	// PkgEnv is the name of the package in the load environment variable
799	PkgEnv string
800	// PkgConfigName is the pkg-config package name from the GIR file
801	PkgConfigName string
802	// SharedLibraries is the list of shared library names from the GIR file
803	SharedLibraries []string
804	// NeedsInit declares whether or not this file needs an init code to register functions with purego
805	NeedsInit bool
806	// NeedsCore indicates if core helpers are required even without init.
807	NeedsCore bool
808	// HasReceiverCallbacks indicates if any receiver method has callback parameters
809	// This is used to conditionally import unsafe and purego
810	HasReceiverCallbacks bool
811	// HasFunctionCallbacks indicates if any standalone function has callback parameters
812	HasFunctionCallbacks bool
813	// HasSignalStrings indicates if any signal has string parameters that need
814	// core.GoString() conversion in the purego callback closure.
815	HasSignalStrings bool
816	// HasTypeGetters indicates if any record, class, interface, alias, or enum
817	// in this file has a GLib type getter that uses types.GType.
818	HasTypeGetters bool
819	// NeedsGLib indicates if the generated file uses glib.* symbols.
820	NeedsGLib bool
821	// NeedsGObject indicates if the generated file uses gobject.* symbols.
822	NeedsGObject bool
823	// CrossPkgImports are fully qualified import paths for cross-package
824	// references detected in the generated code (e.g. gio.*, cairo.*, pango.*).
825	CrossPkgImports []string
826	// Imports defines the package imports that we need
827	// This does not include purego
828	// As the template already includes that if `NeedsInit` is set to true
829	Imports []string
830	// Aliases are type aliases declared as type ... = ...
831	Aliases []AliasTemplate
832	// Aliases are structs that are not classes
833	Records []RecordTemplate
834	// Callbacks are functions that will be converted with purego to uintptr
835	Callbacks []CallbackTemplate
836	// Enums are enumerations declared as const ... .... = ....
837	Enums []EnumTemplate
838	// Constants are declared as const ... .... = ....
839	Constants []ConstantTemplate
840	// Functions are the Go function declarations
841	Functions []FuncTemplate
842	// Interfaces is the list of interfaces that this package implements
843	Interfaces []InterfaceTemplate
844	// Classes are the Go struct with receiver declarations
845	Classes []ClassTemplate
846}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 102

↑↓ moveenter openesc close