Package nject is a general purpose dependency injection framework. It provides wrapping, pruning, and indirect variable passing. It is type safe and using it requires no type assertions. There are two main injection APIs: Run and Bind. Bind is designed to be used at program initialization and does as much work as possible then rather than during main execution. The API for nject is a list of providers (injectors) that are run in order. The final function in the list must be called. The other functions are called if their value is consumed by a later function that must be called. Here is a simple example: In this example, context.Background and log.Default are not invoked because their outputs are not used by the final function (http.ListenAndServe). The basic idea of nject is to assemble a Collection of providers and then use that collection to supply inputs for functions that may use some or all of the provided types. One big win from dependency injection with nject is the ability to reshape various different functions into a single signature. For example, having a bunch of functions with different APIs all bound as http.HandlerFunc is easy. Providers produce or consume data. The data is distinguished by its type. If you want to three different strings, then define three different types: Then you can have a function that does things with the three types: The above function would be a valid injector or final function in a provider Collection. For example: This creates a sequence and executes it. Run injects a myFirst value and the sequence of providers runs: genSecond() injects a mySecond and myStringFunc() combines the myFirst and mySecond to create a myThird. Then the function given in run saves that final value. The expected output is Providers are grouped as into linear sequences. When building an injection chain, the providers are grouped into several sets: LITERAL, STATIC, RUN. The LITERAL and STATIC sets run once per initialization. The RUN set runs once per invocation. Providers within a set are executed in the order that they were originally specified. Providers whose outputs are not consumed are omitted unless they are marked Required(). Collections are bound with Bind(&invocationFunction, &initializationFunction). The invocationFunction is expected to be used over and over, but the initializationFunction is expected to be used less frequently. The STATIC set is re-invoked each time the initialization function is run. The LITERAL set is just the literal values in the collection. The STATIC set is composed of the cacheable injectors. The RUN set if everything else. All injectors have the following type signature: None of the input or output parameters may be anonymously-typed functions. An anoymously-typed function is a function without a named type. Injectors whose output values are not used by a downstream handler are dropped from the handler chain. They are not invoked. Injectors that have no output values are a special case and they are always retained in the handler chain. In injector that is annotated as Cacheable() may promoted to the STATIC set. An injector that is annotated as MustCache() must be promoted to the STATIC set: if it cannot be promoted then the collection is deemed invalid. An injector may not be promoted to the STATIC set if it takes as input data that comes from a provider that is not in the STATIC or LITERAL sets. For example, arguments to the invocation function, if the invoke function takes an int as one of its inputs, then no injector that takes an int as an argument may be promoted to the STATIC set. Injectors in the STATIC set will be run exactly once per set of input values. If the inputs are consistent, then the output will be a singleton. This is true across injection chains. If the following provider is used in multiple chains, as long as the same integer is injected, all chains will share the same pointer. Injectors in the STATIC set are only run for initialization. For some things, like opening a database, that may still be too often. Injectors that are marked Memoized must be promoted to the static set. Memoized injectors are only run once per combination of inputs. Their outputs are remembered. If called enough times with different arguments, memory will be exhausted. Memoized injectors may not have more than 90 inputs. Memoized injectors may not have any inputs that are go maps, slices, or functions. Arrays, structs, and interfaces are okay. This requirement is recursive so a struct that that has a slice in it is not okay. Fallible injectors are special injectors that change the behavior of the injection chain if they return error. Fallible injectors in the RUN set, that return error will terminate execution of the injection chain. A non-wrapper function that returns nject.TerminalError is a fallible injector. The TerminalError does not have to be the last return value. The nject package converts TerminalError objects into error objects so only the fallible injector should use TerminalError. Anything that consumes the TerminalError should do so by consuming error instead. Fallible injectors can be in both the STATIC set and the RUN set. Their behavior is a bit different. If a non-nil value is returned as the TerminalError from a fallible injector in the RUN set, none of the downstream providers will be called. The provider chain returns from that point with the TerminalError as a return value. Since all return values must be consumed by a middleware provider or the bound invoke function, fallible injectors must come downstream from a middleware handler that takes error as a returned value if the invoke function (function that runs a bound injection chain) does not return error. If a fallible injector returns nil for the TerminalError, the other output values are made available for downstream handlers to consume. The other output values are not considered return values and are not available to be consumed by upstream middleware handlers. The error returned by a fallible injector is not available downstream. If a non-nil value is returned as the TerminalError from a fallible injector in the STATIC set, the rest of the STATIC set will be skipped. If there is an init function and it returns error, then the value returned by the fallible injector will be returned via init function. Unlike fallible injectors in the RUN set, the error output by a fallible injector in the STATIC set is available downstream (but only in the RUN set -- nothing else in the STATIC set will execute). Some examples: A wrap function interrupts the linear sequence of providers. It may or may invoke the remainder of the sequence that comes after it. The remainder of the sequence is provided to the wrap function as a function that it may call. The type signature of a wrap function is a function that receives an function as its first parameter. That function must be of an anonymous type: For example: When this wrappper function runs, it is responsible for invoking the rest of the provider chain. It does this by calling inner(). The parameters to inner are available as inputs to downstream providers. The value(s) returned by inner come from the return values of other wrapper functions and from the return value(s) of the final function. Wrap functions can call inner() zero or more times. The values returned by wrap functions must be consumed by another upstream wrap function or by the init function (if using Bind()). Wrap functions have a small amount of runtime overhead compared to other kinds of functions: one call to reflect.MakeFunc(). Wrap functions serve the same role as middleware, but are usually easier to write. Wrap functions that invoke inner() multiple times in parallel are are not well supported at this time and such invocations must have the wrap function decorated with Parallel(). Final functions are simply the last provider in the chain. They look like regular Go functions. Their input parameters come from other providers. Their return values (if any) must be consumed by an upstream wrapper function or by the init function (if using Bind()). Wrap functions that return error should take error as a returned value so that they do not mask a downstream error. Wrap functions should not return TerminalError because they internally control if the downstream chain is called. Literal values are values in the provider chain that are not functions. Provider chains can be invalid for many reasons: inputs of a type not provided earlier in the chain; annotations that cannot be honored (eg. MustCache & Memoize); return values that are not consumed; functions that take or return functions with an anymous type other than wrapper functions; A chain that does not terminate with a function; etc. Bind() and Run() will return error when presented with an invalid provider chain. Bind() and Run() will return error rather than panic. After Bind()ing an init and invoke function, calling them will not panic unless a provider panic()s A wrapper function can be used to catch panics and turn them into errors. When doing that, it is important to propagate any errors that are coming up the chain. If there is no guaranteed function that will return error, one can be added with Shun(). Bind() uses a complex and somewhat expensive O(n^2) set of rules to evaluate which providers should be included in a chain and which can be dropped. The goal is to keep the ones you want and remove the ones you don't want. Bind() tries to figure this out based on the dependencies and the annotations. MustConsume, not Desired: Only include if at least one output is transitively consumed by a Required or Desired chain element and all outputs are consumed by some other provider. Not MustConsume, not Desired: only include if at least one output is transitively consumed by a Required or Desired provider. Not MustConsume, Desired: Include if all inputs are available. MustConsume, Desired: Only include if all outputs are transitively consumed by a required or Desired chain element. When there are multiple providers of a type, Bind() tries to get it from the closest provider. Providers that have unmet dependencies will be eliminated from the chain unless they're Required. The remainder of this document consists of suggestions for how to use nject. Contributions to this section would be welcome. Also links to blogs or other discussions of using nject in practice. The best practice for using nject inside a large project is to have a few common chains that everyone imports. Most of the time, these common chains will be early in the sequence of providers. Customization of the import chains happens in many places. This is true for services, libraries, and tests. For tests, a wrapper that includes the standard chain makes it easier to write tests. See github.com/memsql/ntest for helper functions and more examples. If nject cannot bind or run a chain, it will return error. The returned error is generally very good, but it does not contain the full debugging output. The full debugging output can be obtained with the DetailedError function. If the detailed error shows that nject has a bug, note that part of the debug output includes a regression test that can be turned into an nject issue. Remove the comments to hide the original type names. The Reorder() decorator allows injection chains to be fully or partially reordered. Reorder is currently limited to a single pass and does not know which injectors are ultimately going to be included in the final chain. It is likely that if you mark your entire chain with Reorder, you'll have unexpected results. On the other hand, Reorder provides safe and easy way to solve some common problems. For example: providing optional options to an injected dependency. Because the default options are marked as Shun, they'll only be included if they have to be included. If a user of thingChain wants to override the options, they simply need to mark their override as Reorder. To make this extra friendly, a helper function to do the override can be provided and used. Recommended best practice is to have injectors shutdown the things they themselves start. They should do their own cleanup. Inside tests, an injector can use t.Cleanup() for this. For services, something like t.Cleanup can easily be built: Alternatively, any wrapper function can do it's own cleanup in a defer that it defines. Wrapper functions have a small runtime performance penalty, so if you have more than a couple of providers that need cleanup, it makes sense to include something like CleaningService. The normal direction of forced inclusion is that an upstream provider is required because a downstream provider uses a type produced by the upstream provider. There are times when the relationship needs to be reversed. For example, a type gets modified by a downstream injector. The simplest option is to combine the providers into one function. Another possibility is to mark the upstream provider with MustConsume and have it produce a type that is only consumed by the downstream provider. Lastly, the providers can be grouped with Cluster so that they'll be included or excluded as a group. Example shows what gets included and what does not for several injection chains. These examples are meant to show the subtlety of what gets included and why. This example explores injecting a database handle or transaction only when they're used.
Package gel is the official Go driver for Gel. Additionally, github.com/geldata/gel-go/cmd/edgeql-go is a code generator that generates go functions from edgeql files. See Client for an example of typical usage. We recommend using environment variables for connection parameters. See the client connection docs for more information. gel never returns underlying errors directly. If you are checking for things like context expiration use errors.Is or errors.As. Most errors returned by the gel package will satisfy the gelerr.Error interface which has methods for introspecting. The following list shows the marshal/unmarshal mapping between Gel types and go types. See also geltypes: Note that Gel's std::duration type is represented in int64 microseconds while go's time.Duration type is int64 nanoseconds. It is incorrect to cast one directly to the other. Shape fields that are not required must use optional types for receiving query results. geltypes.Optional can be embedded to make structs optional. Not all types listed above are valid query parameters. To pass a slice of scalar values use array in your query. Gel doesn't currently support using sets as parameters. Nested structures are also not directly allowed but you can use json instead. By default Gel will ignore embedded structs when marshaling/unmarshaling. To treat an embedded struct's fields as part of the parent struct's fields, tag the embedded struct with `gel:"$inline"`. Interfaces for user defined marshaler/unmarshalers are documented in the github.com/geldata/gel-go/internal/marshal package. Link properties are treated as fields in the linked to struct, and the @ is omitted from the field's tag.
Package testpackage tests Go online documentation capabilties. Here’s a link to parl Paragraph. List heading: More bragging here.
Package goutte provides a generic, thread-safe LRU (Least Recently Used) cache implementation in Go. The cache is implemented using a hash map for fast point queries and a doubly linked list (via the standard library’s container/list package) to track the usage order. When the cache reaches its capacity, the least recently used item is evicted automatically. The cache is generic, allowing you to specify the types for keys and values at creation time (using Go 1.18+ generics). Keys must be comparable and values can be of any type. All operations (Get, Set, Delete) are safe for concurrent use. ## Usage Example
Package list implements a doubly linked list. To iterate over a list (where l is a *List):
2fa is a two-factor authentication agent. Usage: “2fa -add name” adds a new key to the 2fa keychain with the given name. It prints a prompt to standard error and reads a two-factor key from standard input. Two-factor keys are short case-insensitive strings of letters A-Z and digits 2-7. By default the new key generates time-based (TOTP) authentication codes; the -hotp flag makes the new key generate counter-based (HOTP) codes instead. By default the new key generates 6-digit codes; the -7 and -8 flags select 7- and 8-digit codes instead. “2fa -list” lists the names of all the keys in the keychain. “2fa name” prints a two-factor authentication code from the key with the given name. If “-clip” is specified, 2fa also copies the code to the system clipboard. With no arguments, 2fa prints two-factor authentication codes from all known time-based keys. The default time-based authentication codes are derived from a hash of the key and the current time, so it is important that the system clock have at least one-minute accuracy. The keychain is stored unencrypted in the text file $HOME/.2fa. During GitHub 2FA setup, at the “Scan this barcode with your app” step, click the “enter this text code instead” link. A window pops up showing “your two-factor secret,” a short string of letters and digits. Add it to 2fa under the name github, typing the secret at the prompt: Then whenever GitHub prompts for a 2FA code, run 2fa to obtain one: Or to type less:
Continuation of byosh and SimpleSNIProxy projects. To ensure that Sniproxy works correctly, it's important to have ports 80, 443, and 53 open. However, on Ubuntu, it's possible that port 53 may be in use by systemd-resolved. To disable systemd-resolved and free up the port, follow these instructions. If you prefer to keep systemd-resolved and just disable the built-in resolver, you can use the following command: The simplest way to install the software is by utilizing the pre-built binaries available on the releases page. Alternatively, there are other ways to install, which include: Using "go install" command: Using Docker or Podman: Using the installer script: sniproxy can be configured using a configuration file or command line flags. The configuration file is a JSON file, and an example configuration file can be found under config.sample.json. Flags: In this tutorial, we will go over the steps to set up an SNI proxy using Vultr as a service provider. This will allow you to serve multiple SSL-enabled websites from a single IP address. - A Vultr account. If you don't have one, you can sign up for free using my Vultr referal link ## Step 1: Create a Vultr Server First, log in to your Vultr account and click on the "Instances" tab in the top menu. Then, click the "+" button to deploy a new server. On the "Deploy New Instance" page, select the following options: - Choose Server: Choose "Cloud Compute" - CPU & Storage Technology: Any of the choices should work perfectly fine - Server Location: Choose the location of the server. This will affect the latency of your website, so it's a good idea to choose a location that is close to your target audience. - Server Image: Any OS listed there is supported. If you're not sure what to choose, Ubuntu is a good option - Server Size: Choose a server size that is suitable for your needs. A small or medium-sized server should be sufficient for most SNI proxy setups. Pay attention to the monthly bandwidth usage as well - "Add Auto Backups": not strictly needed for sniproxy. - "SSH Keys": choose a SSH key to facilitate logging in later on. you can always use Vultr's builtin console as well. - Server Hostname: Choose a hostname for your server. This can be any name you like. After you have selected the appropriate options, click the "Deploy Now" button to create your server. ## Step 2: Install the SNI Proxy Once your server has been created, log in to the server using SSH or console. The root password is available under the "Overview" tab in instances list. Ensure the firewall (firewalld, ufw or iptables) is allowing connectivity to ports 80/TCP, 443/TCP and 53/UDP. For `ufw`, allow these ports with: once you have a shell in front of you, run the following (assuming you're on Ubuntu 22.04) above script is an interactive installer, it will ask you a few questions and then install sniproxy for you. it also installs sniproxy as a systemd servers, and enables it to start on boot. above wizard will set up execution arguments for sniproxy. you can edit them by running and then edit the execStart line to your liking. for example, if you want to use a different port for HTTP, you can edit the line to
Package tk9.0 is a CGo-free, cross platform GUI toolkit for Go. It is similar to Tkinter for Python. Also available in _examples/hello.go To execute the above program on any supported target issue something like The CGO_ENABLED=0 is optional and here it only demonstrates the program can be built without CGo. Do I need to install the Tcl/Tk libraries on my system to use this package or programs that import it? No. You still have to have a desktop environment installed on systems where that is not necessarily the case by default. That means some of the unix-like systems. Usually installing any desktop environment, like Gnome, Xfce etc. provides all the required library (.so) files. The minimum is the X Window System and this package was tested to work there, although with all the limitations one can expect in this case. Windows: How to build an executable that doesn't open a console window when run? From the documentation for cmd/link: On Windows, -H windowsgui writes a "GUI binary" instead of a "console binary.". To pass the flag to the Go build system use 'go build -ldflags -H=windowsgui somefile.go', for example. What does CGo-free really mean? cgo is a tool used by the Go build system when Go code uses the pseudo-import "C". For technical details please see the link. For us it is important that using CGo ends up invoking a C compiler during building of a Go program/package. The C compiler is used to determine exact, possibly locally dependent, values of C preprocessor constants and other defines, as well as the exact layout of C structs. This enables the Go compiler to correctly handle things like, schematically `C.someStruct.someField` appearing in Go code. At runtime a Go program using CGo must switch stacks when calling into C. Additionally the runtime scheduler is made aware of such calls into C. The former is necessary, the later is not, but it is good to have as it improves performance and provides better resource management. There is an evironment variable defined, `CGO_ENABLED`. When the Go build system compiles Go code, it checks for the value of this env var. If it is not set or its value is "1", then CGo is enabled and used when 'import "C"' is encountered. If the env var contains "0", CGo is disabled and programs using 'import "C"' will not compile. After this longish intro we can finally get to the short answer: CGo-free means this package can be compiled with CGO_ENABLED=0. In other words, there's no 'import "C"' clause anywhere. The consequences of being CGo-free follows from the above. The Go build system does not need to invoke a C compiler when compiling this package. Hence users don't have to have a C compiler installed in their machines. There are advantages when a C compiler is not invoked during compilation/build of Go code. Programs can be installed on all targets supported by this package the easy way: '$ go install example.com/foo@latest' and programs for all supported targets can be cross-compiled on all Go-supported targets just by setting the respective env vars, like performing '$ GOOS=darwin GOARCH=arm64 go build' on a Windows/AMD64 machine, for example. How does this package achieve being CGo-free? The answer depends on the particular target in question. Targets supported by purego call into the Tcl/Tk C libraries without using CGo. See the source code at the link for how it is done. On other targets CGo is avoided by transpiling all the C libraries and their transitive dependencies to Go. In both cases the advantages are the same: CGo-free programs are go-installable and CGo-free programs can be cross-compiled without having a C compiler or a cross-C compiler tool chain installed. Does being CGo-free remove the overhead of crossing the Go-C boundary? For the purego targets, no. Only the C compiler is not involved anymore. For other supported targets the boundary for calling Tcl/Tk C API from Go is gone. No free lunches though, the transpilled code has to care about additional things the C code does not need to - with the respective performance penalties, now just in different places. Consider this program in _examples/debugging.go: Execute the program using the tags as indicated, then close the window or click the Hello button. With the tk.dmesg tag the package initialization prints the debug messages path. So we can view it, for example, like this: 18876 was the process PID in this particular run. Using the tags allows to inspect the Tcl/Tk code executed during the lifetime of the process. These combinations of GOOS and GOARCH are currently supported Specific to FreeBSD: When building with cross-compiling or CGO_ENABLED=0, add the following argument to `go` so that these symbols are defined by making fakecgo the Cgo. Builder results available at modern-c.appspot.com. At the moment the package is a MVP allowing to build at least some simple, yet useful programs. The full Tk API is not yet usable. Please report needed, but non-exposed Tk features at the issue tracker, thanks. Providing feedback about the missing building blocks, bugs and your user experience is invaluable in helping this package to eventually reach version 1. See also RERO. The ErrorMode variable selects the behaviour on errors for certain functions that do not return error. When ErrorMode is PanicOnError, the default, errors will panic, providing a stack trace. When ErrorMode is CollectErrors, errors will be recorded using errors.Join in the Error variable. Even if a function does not return error, it is still possible to handle errors in the usual way when needed, except that Error is now a static variable. That's a problem in the general case, but less so in this package that must be used from a single goroutine only, as documented elsewhere. This is obviously a compromise enabling to have a way to check for errors and, at the same time, the ability to write concise code like: There are altogether four different places where the call to the Button function can produce errors as additionally to the call itself, every of its three arguments can independently fail as well. Checking each and one of them separately is not always necessary in GUI code. But the explicit option in the first example is still available when needed. There is a centralized theme register in Themes. Theme providers can opt in to call RegisterTheme at package initialization to make themes discoverable at run-time. Clients can use ActivateTheme to apply a theme by name. Example in _examples/azure.go. There is a VNC over wbesockets functionality available for X11 backed hosts. See the tk9.0/vnc package for details. Package initialization is done lazily. This saves noticeable additional startup time and avoids screen flicker in hybrid programs that use the GUI only on demand. (For a hybrid example see _examples/ring.go.) Early package initialization can be enforced by Initialize. Initialization will fail if a Unix process starts on a machine with no X server or the process is started in a way that it has no access to the X server. On the other hand, this package may work on Unix machines with no X server if the process is started remotely using '$ ssh -X foo@bar' and the X forwarding is enabled/supported. Darwin port uses the macOS GUI API and does not use X11. Zero or more options can be specified when creating a widget. For example or Tcl/Tk uses widget pathnames, image and font names explicitly set by user code. This package generates those names automatically and they are not directly needed in code that uses this package. There is, for a example, a Tcl/tk 'text' widget and a '-text' option. This package exports the widget as type 'TextWidget', its constructor as function 'Text' and the option as function 'Txt'. The complete list is: This package should be used from the same goroutine that initialized the package. Package initialization performs a runtime.LockOSThread, meaning func main() will start execuing locked on the same OS thread. The Command() and similar options expect an argument that must be one of: - An EventHandler or a function literal of the same signature. - A func(). This can be used when the handler does not need the associated Event instance. When passing an argument of type time.Durarion to a function accepting 'any', the duration is converted to an integer number of milliseconds. When passing an argument of type image.Image to a function accepting 'any', the image is converted to a encoding/base64 encoded string of the PNG representation of the image. When passing an argument of type []byte to a function accepting 'any', the byte slice is converted to a encoding/base64 encoded string. When passing an argument of type []FileType to a function accepting 'any', the slice is converted to the representation the Tcl/Tk -filetypes option expects. At least some minimal knowledge of reading Tcl/Tk code is probably required for using this package and/or using the related documentation. However you will not need to write any Tcl code and you do not need to care about the grammar of Tcl words/string literals and how it differs from Go. There are several Tcl/Tk tutorials available, for example at tutorialspoint. Merge requests for known issues are always welcome. Please send merge requests for new features/APIs after filling and discussing the additions/changes at the issue tracker first. Most of the documentation is generated directly from the Tcl/Tk documentation and may not be entirely correct for the Go package. Those parts hopefully still serve as a quick/offline Tcl/Tk reference. Parts of the documentation are copied and/or modified from the tcl.tk site, see the LICENSE-TCLTK file for details. Parts of the documentation are copied and/or modified from the tkinter.ttk site which is You can support the maintenance and further development of this package at jnml's LiberaPay (using PayPal). "Checkbutton.indicator" style element options: "Combobox.downarrow" style element options: "Menubutton.indicator" style element options: "Radiobutton.indicator" style element options: "Spinbox.downarrow" style element options: "Spinbox.uparrow" style element options: "Treeitem.indicator" style element options: "arrow" style element options: "border" style element options: "downarrow" style element options: "field" style element options: "leftarrow" style element options: "rightarrow" style element options: "slider" style element options: "thumb" style element options: "uparrow" style element options: "alt" theme style list Style map: -foreground {disabled #a3a3a3} -background {disabled #d9d9d9 active #ececec} -embossed {disabled 1} Layout: ComboboxPopdownFrame.border -sticky nswe Layout: Treeheading.cell -sticky nswe Treeheading.border -sticky nswe -children {Treeheading.padding -sticky nswe -children {Treeheading.image -side right -sticky {} Treeheading.text -sticky we}} Layout: Treeitem.padding -sticky nswe -children {Treeitem.indicator -side left -sticky {} Treeitem.image -side left -sticky {} Treeitem.text -sticky nswe} Layout: Treeitem.separator -sticky nswe Layout: Button.border -sticky nswe -border 1 -children {Button.focus -sticky nswe -children {Button.padding -sticky nswe -children {Button.label -sticky nswe}}} Style map: -highlightcolor {alternate black} -relief { {pressed !disabled} sunken {active !disabled} raised } Layout: Checkbutton.padding -sticky nswe -children {Checkbutton.indicator -side left -sticky {} Checkbutton.focus -side left -sticky w -children {Checkbutton.label -sticky nswe}} Style map: -indicatorcolor {pressed #d9d9d9 alternate #aaaaaa disabled #d9d9d9} Layout: Combobox.field -sticky nswe -children {Combobox.downarrow -side right -sticky ns Combobox.padding -sticky nswe -children {Combobox.textarea -sticky nswe}} Style map: -fieldbackground {readonly #d9d9d9 disabled #d9d9d9} -arrowcolor {disabled #a3a3a3} Layout: Entry.field -sticky nswe -border 1 -children {Entry.padding -sticky nswe -children {Entry.textarea -sticky nswe}} Style map: -fieldbackground {readonly #d9d9d9 disabled #d9d9d9} Layout: Labelframe.border -sticky nswe Layout: Menubutton.border -sticky nswe -children {Menubutton.focus -sticky nswe -children {Menubutton.indicator -side right -sticky {} Menubutton.padding -sticky we -children {Menubutton.label -side left -sticky {}}}} Layout: Notebook.client -sticky nswe Layout: Notebook.tab -sticky nswe -children {Notebook.padding -side top -sticky nswe -children {Notebook.focus -side top -sticky nswe -children {Notebook.label -side top -sticky {}}}} Style map: -expand {selected {1.5p 1.5p 0.75p 0}} -background {selected #d9d9d9} - Layout: Radiobutton.padding -sticky nswe -children {Radiobutton.indicator -side left -sticky {} Radiobutton.focus -side left -sticky {} -children {Radiobutton.label -sticky nswe}} Style map: -indicatorcolor {pressed #d9d9d9 alternate #aaaaaa disabled #d9d9d9} - - Layout: Spinbox.field -side top -sticky we -children {null -side right -sticky {} -children {Spinbox.uparrow -side top -sticky e Spinbox.downarrow -side bottom -sticky e} Spinbox.padding -sticky nswe -children {Spinbox.textarea -sticky nswe}} Style map: -fieldbackground {readonly #d9d9d9 disabled #d9d9d9} -arrowcolor {disabled #a3a3a3} Layout: Notebook.tab -sticky nswe -children {Notebook.padding -side top -sticky nswe -children {Notebook.focus -side top -sticky nswe -children {Notebook.label -side top -sticky {}}}} Layout: Toolbutton.border -sticky nswe -children {Toolbutton.focus -sticky nswe -children {Toolbutton.padding -sticky nswe -children {Toolbutton.label -sticky nswe}}} Style map: -relief {disabled flat selected sunken pressed sunken active raised} -background {pressed #c3c3c3 active #ececec} Layout: Treeview.field -sticky nswe -border 1 -children {Treeview.padding -sticky nswe -children {Treeview.treearea -sticky nswe}} Style map: -foreground {disabled #a3a3a3 selected #ffffff} -background {disabled #d9d9d9 selected #4a6984} Layout: Treeitem.separator -sticky nswe "Button.button" style element options: "Checkbutton.button" style element options: "Combobox.button" style element options: "DisclosureButton.button" style element options: "Entry.field" style element options: "GradientButton.button" style element options: "HelpButton.button" style element options: "Horizontal.Scrollbar.leftarrow" style element options: "Horizontal.Scrollbar.rightarrow" style element options: "Horizontal.Scrollbar.thumb" style element options: "Horizontal.Scrollbar.trough" style element options: "InlineButton.button" style element options: "Labelframe.border" style element options: "Menubutton.button" style element options: "Notebook.client" style element options: "Notebook.tab" style element options: "Progressbar.track" style element options: "Radiobutton.button" style element options: "RecessedButton.button" style element options: "RoundedRectButton.button" style element options: "Scale.slider" style element options: "Scale.trough" style element options: "Searchbox.field" style element options: "SidebarButton.button" style element options: "Spinbox.downarrow" style element options: "Spinbox.field" style element options: "Spinbox.uparrow" style element options: "Toolbar.background" style element options: "Toolbutton.border" style element options: "Treeheading.cell" style element options: "Treeitem.indicator" style element options: "Treeview.treearea" style element options: "Vertical.Scrollbar.downarrow" style element options: "Vertical.Scrollbar.thumb" style element options: "Vertical.Scrollbar.trough" style element options: "Vertical.Scrollbar.uparrow" style element options: "background" style element options: "field" style element options: "fill" style element options: "hseparator" style element options: "separator" style element options: "sizegrip" style element options: "vseparator" style element options: "aqua" theme style list Style map: -selectforeground { background systemSelectedTextColor !focus systemSelectedTextColor} -foreground { disabled systemDisabledControlTextColor background systemLabelColor} -selectbackground { background systemSelectedTextBackgroundColor !focus systemSelectedTextBackgroundColor} Layout: DisclosureButton.button -sticky nswe Layout: GradientButton.button -sticky nswe -children {Button.padding -sticky nswe -children {Button.label -sticky nswe}} Layout: Treeheading.cell -sticky nswe Treeheading.image -side right -sticky {} Treeheading.text -side top -sticky {} Layout: HelpButton.button -sticky nswe Layout: Horizontal.Scrollbar.trough -sticky we -children {Horizontal.Scrollbar.thumb -sticky nswe Horizontal.Scrollbar.rightarrow -side right -sticky {} Horizontal.Scrollbar.leftarrow -side right -sticky {}} Layout: Button.padding -sticky nswe -children {Button.label -sticky nswe} Style map: -foreground { pressed systemLabelColor !pressed systemSecondaryLabelColor } Layout: InlineButton.button -sticky nswe -children {Button.padding -sticky nswe -children {Button.label -sticky nswe}} Style map: -foreground { disabled systemWindowBackgroundColor } Layout: Treeitem.padding -sticky nswe -children {Treeitem.indicator -side left -sticky {} Treeitem.image -side left -sticky {} Treeitem.text -side left -sticky {}} Layout: Label.fill -sticky nswe -children {Label.text -sticky nswe} Layout: RecessedButton.button -sticky nswe -children {Button.padding -sticky nswe -children {Button.label -sticky nswe}} Style map: -font { selected RecessedFont active RecessedFont pressed RecessedFont } -foreground { {disabled selected} systemWindowBackgroundColor3 {disabled !selected} systemDisabledControlTextColor selected systemTextBackgroundColor active white pressed white } Layout: RoundedRectButton.button -sticky nswe -children {Button.padding -sticky nswe -children {Button.label -sticky nswe}} Layout: Searchbox.field -sticky nswe -border 1 -children {Entry.padding -sticky nswe -children {Entry.textarea -sticky nswe}} Layout: SidebarButton.button -sticky nswe -children {Button.padding -sticky nswe -children {Button.label -sticky nswe}} Style map: -foreground { {disabled selected} systemWindowBackgroundColor3 {disabled !selected} systemDisabledControlTextColor selected systemTextColor active systemTextColor pressed systemTextColor } Layout: Button.button -sticky nswe -children {Button.padding -sticky nswe -children {Button.label -sticky nswe}} Style map: -foreground { pressed white {alternate !pressed !background} white disabled systemDisabledControlTextColor} Layout: Checkbutton.button -sticky nswe -children {Checkbutton.padding -sticky nswe -children {Checkbutton.label -side left -sticky {}}} Layout: Combobox.button -sticky nswe -children {Combobox.padding -sticky nswe -children {Combobox.textarea -sticky nswe}} Style map: -foreground { disabled systemDisabledControlTextColor } -selectbackground { !focus systemUnemphasizedSelectedTextBackgroundColor } Layout: Entry.field -sticky nswe -border 1 -children {Entry.padding -sticky nswe -children {Entry.textarea -sticky nswe}} Style map: -foreground { disabled systemDisabledControlTextColor } -selectbackground { !focus systemUnemphasizedSelectedTextBackgroundColor } Layout: Labelframe.border -sticky nswe Layout: Label.fill -sticky nswe -children {Label.text -sticky nswe} Layout: Menubutton.button -sticky nswe -children {Menubutton.padding -sticky nswe -children {Menubutton.label -side left -sticky {}}} Layout: Notebook.client -sticky nswe Layout: Notebook.tab -sticky nswe -children {Notebook.padding -sticky nswe -children {Notebook.label -sticky nswe}} Style map: -foreground { {background !selected} systemControlTextColor {background selected} black {!background selected} systemSelectedTabTextColor disabled systemDisabledControlTextColor} Layout: Progressbar.track -sticky nswe Layout: Radiobutton.button -sticky nswe -children {Radiobutton.padding -sticky nswe -children {Radiobutton.label -side left -sticky {}}} - Layout: Spinbox.buttons -side right -sticky {} -children {Spinbox.uparrow -side top -sticky e Spinbox.downarrow -side bottom -sticky e} Spinbox.field -sticky we -children {Spinbox.textarea -sticky we} Style map: -foreground { disabled systemDisabledControlTextColor } -selectbackground { !focus systemUnemphasizedSelectedTextBackgroundColor } Layout: Notebook.tab -sticky nswe -children {Notebook.padding -sticky nswe -children {Notebook.label -sticky nswe}} Layout: Toolbar.background -sticky nswe Layout: Toolbutton.border -sticky nswe -children {Toolbutton.focus -sticky nswe -children {Toolbutton.padding -sticky nswe -children {Toolbutton.label -sticky nswe}}} Layout: Treeview.field -sticky nswe -children {Treeview.padding -sticky nswe -children {Treeview.treearea -sticky nswe}} Style map: -background { selected systemSelectedTextBackgroundColor } Layout: Vertical.Scrollbar.trough -sticky ns -children {Vertical.Scrollbar.thumb -sticky nswe Vertical.Scrollbar.downarrow -side bottom -sticky {} Vertical.Scrollbar.uparrow -side bottom -sticky {}} "Checkbutton.indicator" style element options: "Combobox.field" style element options: "Radiobutton.indicator" style element options: "Spinbox.downarrow" style element options: "Spinbox.uparrow" style element options: "arrow" style element options: "bar" style element options: "border" style element options: "client" style element options: "downarrow" style element options: "field" style element options: "hgrip" style element options: "leftarrow" style element options: "pbar" style element options: "rightarrow" style element options: "slider" style element options: "tab" style element options: "thumb" style element options: "trough" style element options: "uparrow" style element options: "vgrip" style element options: "clam" theme style list Style map: -selectforeground {!focus white} -foreground {disabled #999999} -selectbackground {!focus #9e9a91} -background {disabled #dcdad5 active #eeebe7} Layout: ComboboxPopdownFrame.border -sticky nswe Layout: Treeheading.cell -sticky nswe Treeheading.border -sticky nswe -children {Treeheading.padding -sticky nswe -children {Treeheading.image -side right -sticky {} Treeheading.text -sticky we}} Layout: Sash.hsash -sticky nswe -children {Sash.hgrip -sticky nswe} Layout: Treeitem.padding -sticky nswe -children {Treeitem.indicator -side left -sticky {} Treeitem.image -side left -sticky {} Treeitem.text -sticky nswe} - Layout: Treeitem.separator -sticky nswe Layout: Button.border -sticky nswe -border 1 -children {Button.focus -sticky nswe -children {Button.padding -sticky nswe -children {Button.label -sticky nswe}}} Style map: -lightcolor {pressed #bab5ab} -background {disabled #dcdad5 pressed #bab5ab active #eeebe7} -bordercolor {alternate #000000} -darkcolor {pressed #bab5ab} Layout: Checkbutton.padding -sticky nswe -children {Checkbutton.indicator -side left -sticky {} Checkbutton.focus -side left -sticky w -children {Checkbutton.label -sticky nswe}} Style map: -indicatorbackground {pressed #dcdad5 {!disabled alternate} #5895bc {disabled alternate} #a0a0a0 disabled #dcdad5} Layout: Combobox.downarrow -side right -sticky ns Combobox.field -sticky nswe -children {Combobox.padding -sticky nswe -children {Combobox.textarea -sticky nswe}} Style map: -foreground {{readonly focus} #ffffff} -fieldbackground {{readonly focus} #4a6984 readonly #dcdad5} -background {active #eeebe7 pressed #eeebe7} -bordercolor {focus #4a6984} -arrowcolor {disabled #999999} Layout: Entry.field -sticky nswe -border 1 -children {Entry.padding -sticky nswe -children {Entry.textarea -sticky nswe}} Style map: -lightcolor {focus #6f9dc6} -background {readonly #dcdad5} -bordercolor {focus #4a6984} Layout: Labelframe.border -sticky nswe Layout: Menubutton.border -sticky nswe -children {Menubutton.focus -sticky nswe -children {Menubutton.indicator -side right -sticky {} Menubutton.padding -sticky we -children {Menubutton.label -side left -sticky {}}}} Layout: Notebook.tab -sticky nswe -children {Notebook.padding -side top -sticky nswe -children {Notebook.focus -side top -sticky nswe -children {Notebook.label -side top -sticky {}}}} Style map: -lightcolor {selected #eeebe7 {} #cfcdc8} -padding {selected {4.5p 3p 4.5p 1.5p}} -background {selected #dcdad5 {} #bab5ab} - Layout: Radiobutton.padding -sticky nswe -children {Radiobutton.indicator -side left -sticky {} Radiobutton.focus -side left -sticky {} -children {Radiobutton.label -sticky nswe}} Style map: -indicatorbackground {pressed #dcdad5 {!disabled alternate} #5895bc {disabled alternate} #a0a0a0 disabled #dcdad5} - - Layout: Spinbox.field -side top -sticky we -children {null -side right -sticky {} -children {Spinbox.uparrow -side top -sticky e Spinbox.downarrow -side bottom -sticky e} Spinbox.padding -sticky nswe -children {Spinbox.textarea -sticky nswe}} Style map: -background {readonly #dcdad5} -bordercolor {focus #4a6984} -arrowcolor {disabled #999999} Layout: Notebook.tab -sticky nswe -children {Notebook.padding -side top -sticky nswe -children {Notebook.focus -side top -sticky nswe -children {Notebook.label -side top -sticky {}}}} Layout: Toolbutton.border -sticky nswe -children {Toolbutton.focus -sticky nswe -children {Toolbutton.padding -sticky nswe -children {Toolbutton.label -sticky nswe}}} Style map: -lightcolor {pressed #bab5ab} -relief {disabled flat selected sunken pressed sunken active raised} -background {disabled #dcdad5 pressed #bab5ab active #eeebe7} -darkcolor {pressed #bab5ab} Layout: Treeview.field -sticky nswe -border 1 -children {Treeview.padding -sticky nswe -children {Treeview.treearea -sticky nswe}} Style map: -foreground {disabled #999999 selected #ffffff} -background {disabled #dcdad5 selected #4a6984} -bordercolor {focus #4a6984} Layout: Treeitem.separator -sticky nswe Layout: Sash.vsash -sticky nswe -children {Sash.vgrip -sticky nswe} "Button.border" style element options: "Checkbutton.indicator" style element options: "Combobox.downarrow" style element options: "Menubutton.indicator" style element options: "Radiobutton.indicator" style element options: "Spinbox.downarrow" style element options: "Spinbox.uparrow" style element options: "arrow" style element options: "downarrow" style element options: "highlight" style element options: "hsash" style element options: "leftarrow" style element options: "rightarrow" style element options: "slider" style element options: "uparrow" style element options: "vsash" style element options: "classic" theme style list Style map: -highlightcolor {focus black} -foreground {disabled #a3a3a3} -background {disabled #d9d9d9 active #ececec} Layout: ComboboxPopdownFrame.border -sticky nswe Layout: Treeheading.cell -sticky nswe Treeheading.border -sticky nswe -children {Treeheading.padding -sticky nswe -children {Treeheading.image -side right -sticky {} Treeheading.text -sticky we}} Layout: Horizontal.Scale.highlight -sticky nswe -children {Horizontal.Scale.trough -sticky nswe -children {Horizontal.Scale.slider -side left -sticky {}}} Layout: Treeitem.padding -sticky nswe -children {Treeitem.indicator -side left -sticky {} Treeitem.image -side left -sticky {} Treeitem.text -sticky nswe} - Layout: Treeitem.separator -sticky nswe Layout: Button.highlight -sticky nswe -children {Button.border -sticky nswe -border 1 -children {Button.padding -sticky nswe -children {Button.label -sticky nswe}}} Style map: -relief {{!disabled pressed} sunken} Layout: Checkbutton.highlight -sticky nswe -children {Checkbutton.border -sticky nswe -children {Checkbutton.padding -sticky nswe -children {Checkbutton.indicator -side left -sticky {} Checkbutton.label -side left -sticky nswe}}} Style map: -indicatorrelief {alternate raised selected sunken pressed sunken} -indicatorcolor {pressed #d9d9d9 alternate #b05e5e selected #b03060} Layout: Combobox.highlight -sticky nswe -children {Combobox.field -sticky nswe -children {Combobox.downarrow -side right -sticky ns Combobox.padding -sticky nswe -children {Combobox.textarea -sticky nswe}}} Style map: -fieldbackground {readonly #d9d9d9 disabled #d9d9d9} Layout: Entry.highlight -sticky nswe -children {Entry.field -sticky nswe -border 1 -children {Entry.padding -sticky nswe -children {Entry.textarea -sticky nswe}}} Style map: -fieldbackground {readonly #d9d9d9 disabled #d9d9d9} Layout: Labelframe.border -sticky nswe Layout: Menubutton.highlight -sticky nswe -children {Menubutton.border -sticky nswe -children {Menubutton.indicator -side right -sticky {} Menubutton.padding -sticky we -children {Menubutton.label -sticky {}}}} Layout: Notebook.tab -sticky nswe -children {Notebook.padding -side top -sticky nswe -children {Notebook.focus -side top -sticky nswe -children {Notebook.label -side top -sticky {}}}} Style map: -background {selected #d9d9d9} - Layout: Radiobutton.highlight -sticky nswe -children {Radiobutton.border -sticky nswe -children {Radiobutton.padding -sticky nswe -children {Radiobutton.indicator -side left -sticky {} Radiobutton.label -side left -sticky nswe}}} Style map: -indicatorrelief {alternate raised selected sunken pressed sunken} -indicatorcolor {pressed #d9d9d9 alternate #b05e5e selected #b03060} Style map: -sliderrelief {{pressed !disabled} sunken} Style map: -relief {{pressed !disabled} sunken} Layout: Spinbox.highlight -sticky nswe -children {Spinbox.field -sticky nswe -children {null -side right -sticky {} -children {Spinbox.uparrow -side top -sticky e Spinbox.downarrow -side bottom -sticky e} Spinbox.padding -sticky nswe -children {Spinbox.textarea -sticky nswe}}} Style map: -fieldbackground {readonly #d9d9d9 disabled #d9d9d9} Layout: Notebook.tab -sticky nswe -children {Notebook.padding -side top -sticky nswe -children {Notebook.focus -side top -sticky nswe -children {Notebook.label -side top -sticky {}}}} Layout: Toolbutton.focus -sticky nswe -children {Toolbutton.border -sticky nswe -children {Toolbutton.padding -sticky nswe -children {Toolbutton.label -sticky nswe}}} Style map: -relief {disabled flat selected sunken pressed sunken active raised} -background {pressed #b3b3b3 active #ececec} Layout: Treeview.highlight -sticky nswe -children {Treeview.field -sticky nswe -border 1 -children {Treeview.padding -sticky nswe -children {Treeview.treearea -sticky nswe}}} Style map: -foreground {disabled #a3a3a3 selected #000000} -background {disabled #d9d9d9 selected #c3c3c3} Layout: Treeitem.separator -sticky nswe Layout: Vertical.Scale.highlight -sticky nswe -children {Vertical.Scale.trough -sticky nswe -children {Vertical.Scale.slider -side top -sticky {}}} "" style element options: "Checkbutton.indicator" style element options: "Combobox.downarrow" style element options: "Menubutton.indicator" style element options: "Radiobutton.indicator" style element options: "Spinbox.downarrow" style element options: "Spinbox.uparrow" style element options: "Treeheading.cell" style element options: "Treeitem.indicator" style element options: "Treeitem.row" style element options: "Treeitem.separator" style element options: "arrow" style element options: "background" style element options: "border" style element options: "client" style element options: "ctext" style element options: "downarrow" style element options: "field" style element options: "fill" style element options: "focus" style element options: "hsash" style element options: "hseparator" style element options: "image" style element options: "indicator" style element options: "label" style element options: "leftarrow" style element options: "padding" style element options: "pbar" style element options: "rightarrow" style element options: "separator" style element options: "sizegrip" style element options: "slider" style element options: "tab" style element options: "text" style element options: "textarea" style element options: "thumb" style element options: "treearea" style element options: "trough" style element options: "uparrow" style element options: "vsash" style element options: "vseparator" style element options: "default" theme style list Style map: -foreground {disabled #a3a3a3} -background {disabled #edeceb active #ececec} Layout: Treedata.padding -sticky nswe -children {Treeitem.image -side left -sticky {} Treeitem.text -sticky nswe} Layout: ComboboxPopdownFrame.border -sticky nswe Layout: Treeheading.cell -sticky nswe Treeheading.border -sticky nswe -children {Treeheading.padding -sticky nswe -children {Treeheading.image -side right -sticky {} Treeheading.text -sticky we}} Layout: Sash.hsash -sticky we Layout: Horizontal.Progressbar.trough -sticky nswe -children {Horizontal.Progressbar.pbar -side left -sticky ns Horizontal.Progressbar.ctext -side left -sticky {}} Layout: Horizontal.Scale.focus -sticky nswe -children {Horizontal.Scale.padding -sticky nswe -children {Horizontal.Scale.trough -sticky nswe -children {Horizontal.Scale.slider -side left -sticky {}}}} Layout: Horizontal.Scrollbar.trough -sticky we -children {Horizontal.Scrollbar.leftarrow -side left -sticky {} Horizontal.Scrollbar.rightarrow -side right -sticky {} Horizontal.Scrollbar.thumb -sticky nswe} Layout: Treeitem.padding -sticky nswe -children {Treeitem.indicator -side left -sticky {} Treeitem.image -side left -sticky {} Treeitem.text -sticky nswe} Layout: Label.fill -sticky nswe -children {Label.text -sticky nswe} Layout: Treeitem.row -sticky nswe - Layout: Treeitem.separator -sticky nswe Layout: Button.border -sticky nswe -border 1 -children {Button.focus -sticky nswe -children {Button.padding -sticky nswe -children {Button.label -sticky nswe}}} Style map: -relief {{!disabled pressed} sunken} Layout: Checkbutton.padding -sticky nswe -children {Checkbutton.indicator -side left -sticky {} Checkbutton.focus -side left -sticky w -children {Checkbutton.label -sticky nswe}} Style map: -indicatorbackground {{alternate disabled} #a3a3a3 {alternate pressed} #5895bc alternate #4a6984 {selected disabled} #a3a3a3 {selected pressed} #5895bc selected #4a6984 disabled #edeceb pressed #c3c3c3} Layout: Combobox.field -sticky nswe -children {Combobox.downarrow -side right -sticky ns Combobox.padding -sticky nswe -children {Combobox.textarea -sticky nswe}} Style map: -fieldbackground {readonly #edeceb disabled #edeceb} -arrowcolor {disabled #a3a3a3} Layout: Entry.field -sticky nswe -border 1 -children {Entry.padding -sticky nswe -children {Entry.textarea -sticky nswe}} Style map: -fieldbackground {readonly #edeceb disabled #edeceb} Layout: Frame.border -sticky nswe Layout: Label.border -sticky nswe -border 1 -children {Label.padding -sticky nswe -border 1 -children {Label.label -sticky nswe}} Layout: Labelframe.border -sticky nswe Layout: Menubutton.border -sticky nswe -children {Menubutton.focus -sticky nswe -children {Menubutton.indicator -side right -sticky {} Menubutton.padding -sticky we -children {Menubutton.label -side left -sticky {}}}} Style map: -arrowcolor {disabled #a3a3a3} Layout: Notebook.client -sticky nswe Layout: Notebook.tab -sticky nswe -children {Notebook.padding -side top -sticky nswe -children {Notebook.focus -side top -sticky nswe -children {Notebook.label -side top -sticky {}}}} Style map: -highlightcolor {selected #4a6984} -highlight {selected 1} -background {selected #edeceb} Layout: Panedwindow.background -sticky {} - Layout: Radiobutton.padding -sticky nswe -children {Radiobutton.indicator -side left -sticky {} Radiobutton.focus -side left -sticky {} -children {Radiobutton.label -sticky nswe}} Style map: -indicatorbackground {{alternate disabled} #a3a3a3 {alternate pressed} #5895bc alternate #4a6984 {selected disabled} #a3a3a3 {selected pressed} #5895bc selected #4a6984 disabled #edeceb pressed #c3c3c3} Style map: -outercolor {active #ececec} Style map: -arrowcolor {disabled #a3a3a3} Layout: Separator.separator -sticky nswe Layout: Sizegrip.sizegrip -side bottom -sticky se Layout: Spinbox.field -side top -sticky we -children {null -side right -sticky {} -children {Spinbox.uparrow -side top -sticky e Spinbox.downarrow -side bottom -sticky e} Spinbox.padding -sticky nswe -children {Spinbox.textarea -sticky nswe}} Style map: -fieldbackground {readonly #edeceb disabled #edeceb} -arrowcolor {disabled #a3a3a3} Layout: Notebook.tab -sticky nswe -children {Notebook.padding -side top -sticky nswe -children {Notebook.focus -side top -sticky nswe -children {Notebook.label -side top -sticky {}}}} Layout: Toolbutton.border -sticky nswe -children {Toolbutton.focus -sticky nswe -children {Toolbutton.padding -sticky nswe -children {Toolbutton.label -sticky nswe}}} Style map: -relief {disabled flat selected sunken pressed sunken active raised} -background {pressed #c3c3c3 active #ececec} Layout: Treeview.field -sticky nswe -border 1 -children {Treeview.padding -sticky nswe -children {Treeview.treearea -sticky nswe}} Style map: -foreground {disabled #a3a3a3 selected #ffffff} -background {disabled #edeceb selected #4a6984} Layout: Treeitem.separator -sticky nswe Layout: Sash.vsash -sticky ns Layout: Vertical.Progressbar.trough -sticky nswe -children {Vertical.Progressbar.pbar -side bottom -sticky we} Layout: Vertical.Scale.focus -sticky nswe -children {Vertical.Scale.padding -sticky nswe -children {Vertical.Scale.trough -sticky nswe -children {Vertical.Scale.slider -side top -sticky {}}}} Layout: Vertical.Scrollbar.trough -sticky ns -children {Vertical.Scrollbar.uparrow -side top -sticky {} Vertical.Scrollbar.downarrow -side bottom -sticky {} Vertical.Scrollbar.thumb -sticky nswe}PASS "Combobox.background" style element options: "Combobox.border" style element options: "Combobox.rightdownarrow" style element options: "ComboboxPopdownFrame.background" style element options: "Entry.background" style element options: "Entry.field" style element options: "Horizontal.Progressbar.pbar" style element options: "Horizontal.Scale.slider" style element options: "Horizontal.Scrollbar.grip" style element options: "Horizontal.Scrollbar.leftarrow" style element options: "Horizontal.Scrollbar.rightarrow" style element options: "Horizontal.Scrollbar.thumb" style element options: "Horizontal.Scrollbar.trough" style element options: "Menubutton.dropdown" style element options: "Spinbox.background" style element options: "Spinbox.downarrow" style element options: "Spinbox.field" style element options: "Spinbox.innerbg" style element options: "Spinbox.uparrow" style element options: "Vertical.Progressbar.pbar" style element options: "Vertical.Scale.slider" style element options: "Vertical.Scrollbar.downarrow" style element options: "Vertical.Scrollbar.grip" style element options: "Vertical.Scrollbar.thumb" style element options: "Vertical.Scrollbar.trough" style element options: "Vertical.Scrollbar.uparrow" style element options: "vista" theme style list Style map: -foreground {disabled SystemGrayText} Layout: ComboboxPopdownFrame.background -sticky nswe -border 1 -children {ComboboxPopdownFrame.padding -sticky nswe} Layout: Treeheading.cell -sticky nswe Treeheading.border -sticky nswe -children {Treeheading.padding -sticky nswe -children {Treeheading.image -side right -sticky {} Treeheading.text -sticky we}} Layout: Horizontal.Progressbar.trough -sticky nswe -children {Horizontal.Progressbar.pbar -side left -sticky ns Horizontal.Progressbar.ctext -sticky nswe} Layout: Scale.focus -sticky nswe -children {Horizontal.Scale.trough -sticky nswe -children {Horizontal.Scale.track -sticky we Horizontal.Scale.slider -side left -sticky {}}} Layout: Treeitem.padding -sticky nswe -children {Treeitem.indicator -side left -sticky {} Treeitem.image -side left -sticky {} Treeitem.text -sticky nswe} Layout: Label.fill -sticky nswe -children {Label.text -sticky nswe} Layout: Treeitem.separator -sticky nswe Layout: Button.button -sticky nswe -children {Button.focus -sticky nswe -children {Button.padding -sticky nswe -children {Button.label -sticky nswe}}} Layout: Checkbutton.padding -sticky nswe -children {Checkbutton.indicator -side left -sticky {} Checkbutton.focus -side left -sticky w -children {Checkbutton.label -sticky nswe}} Layout: Combobox.border -sticky nswe -children {Combobox.rightdownarrow -side right -sticky ns Combobox.padding -sticky nswe -children {Combobox.background -sticky nswe -children {Combobox.focus -sticky nswe -children {Combobox.textarea -sticky nswe}}}} Style map: -focusfill {{readonly focus} SystemHighlight} -foreground {disabled SystemGrayText {readonly focus} SystemHighlightText} -selectforeground {!focus SystemWindowText} -selectbackground {!focus SystemWindow} Layout: Entry.field -sticky nswe -children {Entry.background -sticky nswe -children {Entry.padding -sticky nswe -children {Entry.textarea -sticky nswe}}} Style map: -selectforeground {!focus SystemWindowText} -selectbackground {!focus SystemWindow} Layout: Label.fill -sticky nswe -children {Label.text -sticky nswe} Layout: Menubutton.dropdown -side right -sticky ns Menubutton.button -sticky nswe -children {Menubutton.padding -sticky we -children {Menubutton.label -sticky {}}} Layout: Notebook.client -sticky nswe Layout: Notebook.tab -sticky nswe -children {Notebook.padding -side top -sticky nswe -children {Notebook.focus -side top -sticky nswe -children {Notebook.label -side top -sticky {}}}} Style map: -expand {selected {2 2 2 2}} - Layout: Radiobutton.padding -sticky nswe -children {Radiobutton.indicator -side left -sticky {} Radiobutton.focus -side left -sticky {} -children {Radiobutton.label -sticky nswe}} - Layout: Spinbox.field -sticky nswe -children {Spinbox.background -sticky nswe -children {Spinbox.padding -sticky nswe -children {Spinbox.innerbg -sticky nswe -children {Spinbox.textarea -sticky nswe}} Spinbox.uparrow -side top -sticky nse Spinbox.downarrow -side bottom -sticky nse}} Style map: -selectforeground {!focus SystemWindowText} -selectbackground {!focus SystemWindow} Layout: Notebook.tab -sticky nswe -children {Notebook.padding -side top -sticky nswe -children {Notebook.focus -side top -sticky nswe -children {Notebook.label -side top -sticky {}}}} Layout: Toolbutton.border -sticky nswe -children {Toolbutton.focus -sticky nswe -children {Toolbutton.padding -sticky nswe -children {Toolbutton.label -sticky nswe}}} Layout: Treeview.field -sticky nswe -border 1 -children {Treeview.padding -sticky nswe -children {Treeview.treearea -sticky nswe}} Style map: -foreground {disabled SystemGrayText selected SystemHighlightText} -background {disabled SystemButtonFace selected SystemHighlight} Layout: Treeitem.separator -sticky nswe Layout: Vertical.Progressbar.trough -sticky nswe -children {Vertical.Progressbar.pbar -side bottom -sticky we} Layout: Scale.focus -sticky nswe -children {Vertical.Scale.trough -sticky nswe -children {Vertical.Scale.track -sticky ns Vertical.Scale.slider -side top -sticky {}}} "Button.border" style element options: "Checkbutton.indicator" style element options: "Combobox.focus" style element options: "ComboboxPopdownFrame.border" style element options: "Radiobutton.indicator" style element options: "Scrollbar.trough" style element options: "Spinbox.downarrow" style element options: "Spinbox.uparrow" style element options: "border" style element options: "client" style element options: "downarrow" style element options: "field" style element options: "focus" style element options: "leftarrow" style element options: "rightarrow" style element options: "sizegrip" style element options: "slider" style element options: "tab" style element options: "thumb" style element options: "uparrow" style element options: "winnative" theme style list Style map: -foreground {disabled SystemGrayText} -embossed {disabled 1} Layout: ComboboxPopdownFrame.border -sticky nswe Layout: Treeheading.cell -sticky nswe Treeheading.border -sticky nswe -children {Treeheading.padding -sticky nswe -children {Treeheading.image -side right -sticky {} Treeheading.text -sticky we}} Layout: Treeitem.padding -sticky nswe -children {Treeitem.indicator -side left -sticky {} Treeitem.image -side left -sticky {} Treeitem.text -sticky nswe} Layout: Label.fill -sticky nswe -children {Label.text -sticky nswe} Layout: Treeitem.separator -sticky nswe Layout: Button.border -sticky nswe -children {Button.padding -sticky nswe -children {Button.label -sticky nswe}} Style map: -relief {{!disabled pressed} sunken} Layout: Checkbutton.padding -sticky nswe -children {Checkbutton.indicator -side left -sticky {} Checkbutton.focus -side left -sticky w -children {Checkbutton.label -sticky nswe}} Layout: Combobox.field -sticky nswe -children {Combobox.downarrow -side right -sticky ns Combobox.padding -sticky nswe -children {Combobox.focus -sticky nswe -children {Combobox.textarea -sticky nswe}}} Style map: -focusfill {{readonly focus} SystemHighlight} -foreground {disabled SystemGrayText {readonly focus} SystemHighlightText} -selectforeground {!focus SystemWindowText} -fieldbackground {readonly SystemButtonFace disabled SystemButtonFace} -selectbackground {!focus SystemWindow} Layout: Entry.field -sticky nswe -border 1 -children {Entry.padding -sticky nswe -children {Entry.textarea -sticky nswe}} Style map: -selectforeground {!focus SystemWindowText} -selectbackground {!focus SystemWindow} -fieldbackground {readonly SystemButtonFace disabled SystemButtonFace} Layout: Labelframe.border -sticky nswe Layout: Label.fill -sticky nswe -children {Label.text -sticky nswe} Layout: Menubutton.border -sticky nswe -children {Menubutton.focus -sticky nswe -children {Menubutton.indicator -side right -sticky {} Menubutton.padding -sticky we -children {Menubutton.label -side left -sticky {}}}} Layout: Notebook.client -sticky nswe Layout: Notebook.tab -sticky nswe -children {Notebook.padding -side top -sticky nswe -children {Notebook.focus -side top -sticky nswe -children {Notebook.label -side top -sticky {}}}} Style map: -expand {selected {2 2 2 0}} - Layout: Radiobutton.padding -sticky nswe -children {Radiobutton.indicator -side left -sticky {} Radiobutton.focus -side left -sticky {} -children {Radiobutton.label -sticky nswe}} - Layout: Spinbox.field -side top -sticky we -children {null -side right -sticky {} -children {Spinbox.uparrow -side top -sticky e Spinbox.downarrow -side bottom -sticky e} Spinbox.padding -sticky nswe -children {Spinbox.textarea -sticky nswe}} Layout: Notebook.tab -sticky nswe -children {Notebook.padding -side top -sticky nswe -children {Notebook.focus -side top -sticky nswe -children {Notebook.label -side top -sticky {}}}} Layout: Toolbutton.border -sticky nswe -children {Toolbutton.focus -sticky nswe -children {Toolbutton.padding -sticky nswe -children {Toolbutton.label -sticky nswe}}} Style map: -relief {disabled flat selected sunken pressed sunken active raised} Layout: Treeview.field -sticky nswe -border 1 -children {Treeview.padding -sticky nswe -children {Treeview.treearea -sticky nswe}} Style map: -foreground {disabled SystemGrayText selected SystemHighlightText} -background {disabled SystemButtonFace selected SystemHighlight} Layout: Treeitem.separator -sticky nswe "Button.button" style element options: "Checkbutton.indicator" style element options: "Combobox.downarrow" style element options: "Combobox.field" style element options: "Entry.field" style element options: "Horizontal.Progressbar.pbar" style element options: "Horizontal.Progressbar.trough" style element options: "Horizontal.Scale.slider" style element options: "Horizontal.Scale.track" style element options: "Horizontal.Scrollbar.grip" style element options: "Horizontal.Scrollbar.thumb" style element options: "Horizontal.Scrollbar.trough" style element options: "Labelframe.border" style element options: "Menubutton.button" style element options: "Menubutton.dropdown" style element options: "NotebookPane.background" style element options: "Radiobutton.indicator" style element options: "Scale.trough" style element options: "Scrollbar.downarrow" style element options: "Scrollbar.leftarrow" style element options: "Scrollbar.rightarrow" style element options: "Scrollbar.uparrow" style element options: "Spinbox.downarrow" style element options: "Spinbox.field" style element options: "Spinbox.uparrow" style element options: "Toolbutton.border" style element options: "Treeheading.border" style element options: "Treeitem.indicator" style element options: "Treeview.field" style element options: "Vertical.Progressbar.pbar" style element options: "Vertical.Progressbar.trough" style element options: "Vertical.Scale.slider" style element options: "Vertical.Scale.track" style element options: "Vertical.Scrollbar.grip" style element options: "Vertical.Scrollbar.thumb" style element options: "Vertical.Scrollbar.trough" style element options: "client" style element options: "sizegrip" style element options: "tab" style element options: "xpnative" theme style list Style map: -foreground {disabled SystemGrayText} Layout: Treeheading.cell -sticky nswe Treeheading.border -sticky nswe -children {Treeheading.padding -sticky nswe -children {Treeheading.image -side right -sticky {} Treeheading.text -sticky we}} Layout: Scale.focus -sticky nswe -children {Horizontal.Scale.trough -sticky nswe -children {Horizontal.Scale.track -sticky we Horizontal.Scale.slider -side left -sticky {}}} Layout: Horizontal.Scrollbar.trough -sticky we -children {Horizontal.Scrollbar.leftarrow -side left -sticky {} Horizontal.Scrollbar.rightarrow -side right -sticky {} Horizontal.Scrollbar.thumb -sticky nswe -unit 1 -children {Horizontal.Scrollbar.grip -sticky {}}} Layout: Treeitem.padding -sticky nswe -children {Treeitem.indicator -side left -sticky {} Treeitem.image -side left -sticky {} Treeitem.text -sticky nswe} Layout: Label.fill -sticky nswe -children {Label.text -sticky nswe} Layout: Treeitem.separator -sticky nswe Layout: Button.button -sticky nswe -children {Button.focus -sticky nswe -children {Button.padding -sticky nswe -children {Button.label -sticky nswe}}} Layout: Checkbutton.padding -sticky nswe -children {Checkbutton.indicator -side left -sticky {} Checkbutton.focus -side left -sticky w -children {Checkbutton.label -sticky nswe}} Layout: Combobox.field -sticky nswe -children {Combobox.downarrow -side right -sticky ns Combobox.padding -sticky nswe -children {Combobox.focus -sticky nswe -children {Combobox.textarea -sticky nswe}}} Style map: -focusfill {{readonly focus} SystemHighlight} -foreground {disabled SystemGrayText {readonly focus} SystemHighlightText} -selectforeground {!focus SystemWindowText} -selectbackground {!focus SystemWindow} Layout: Entry.field -sticky nswe -border 1 -children {Entry.padding -sticky nswe -children {Entry.textarea -sticky nswe}} Style map: -selectforeground {!focus SystemWindowText} -selectbackground {!focus SystemWindow} Layout: Label.fill -sticky nswe -children {Label.text -sticky nswe} Layout: Menubutton.dropdown -side right -sticky ns Menubutton.button -sticky nswe -children {Menubutton.padding -sticky we -children {Menubutton.label -sticky {}}} Layout: Notebook.client -sticky nswe Layout: Notebook.tab -sticky nswe -children {Notebook.padding -side top -sticky nswe -children {Notebook.focus -side top -sticky nswe -children {Notebook.label -side top -sticky {}}}} Style map: -expand {selected {2 2 2 2}} - Layout: Radiobutton.padding -sticky nswe -children {Radiobutton.indicator -side left -sticky {} Radiobutton.focus -side left -sticky {} -children {Radiobutton.label -sticky nswe}} - - Layout: Spinbox.field -side top -sticky we -children {null -side right -sticky {} -children {Spinbox.uparrow -side top -sticky e Spinbox.downarrow -side bottom -sticky e} Spinbox.padding -sticky nswe -children {Spinbox.textarea -sticky nswe}} Style map: -selectforeground {!focus SystemWindowText} -selectbackground {!focus SystemWindow} Layout: Notebook.tab -sticky nswe -children {Notebook.padding -side top -sticky nswe -children {Notebook.focus -side top -sticky nswe -children {Notebook.label -side top -sticky {}}}} Layout: Toolbutton.border -sticky nswe -children {Toolbutton.focus -sticky nswe -children {Toolbutton.padding -sticky nswe -children {Toolbutton.label -sticky nswe}}} Layout: Treeview.field -sticky nswe -border 1 -children {Treeview.padding -sticky nswe -children {Treeview.treearea -sticky nswe}} Style map: -foreground {disabled SystemGrayText selected SystemHighlightText} -background {disabled SystemButtonFace selected SystemHighlight} Layout: Treeitem.separator -sticky nswe Layout: Scale.focus -sticky nswe -children {Vertical.Scale.trough -sticky nswe -children {Vertical.Scale.track -sticky ns Vertical.Scale.slider -side top -sticky {}}} Layout: Vertical.Scrollbar.trough -sticky ns -children {Vertical.Scrollbar.uparrow -side top -sticky {} Vertical.Scrollbar.downarrow -side bottom -sticky {} Vertical.Scrollbar.thumb -sticky nswe -unit 1 -children {Vertical.Scrollbar.grip -sticky {}}}PASS
Package list implements a doubly linked list. To iterate over a list (where l is a *List):
Package lq implements a spatial database which stores objects each of which is associated with a 2D point (a location in a 2D space). The points serve as the "search key" for the associated object. It is intended to efficiently answer "circle inclusion" queries, also known as "range queries": basically questions like: Which objects are within a radius R of the location L? In this context, "efficiently" means significantly faster than the naive, brute force O(n) testing of all known points. Additionally it is assumed that the objects move along unpredictable paths, so that extensive preprocessing (for example, constructing a Delaunay triangulation of the point set) may not be practical. The implementation is a "bin lattice": a 2D rectangular array of brick-shaped (rectangles) regions of space. Each region is represented by a pointer to a (possibly empty) doubly-linked list of objects. All of these sub-bricks are the same size. All bricks are aligned with the global coordinate axes. Terminology used here: the region of space associated with a bin is called a sub-brick. The collection of all sub-bricks is called the super-brick. The super-brick should be specified to surround the region of space in which (almost) all the key-points will exist. If key-points move outside the super-brick everything will continue to work, but without the speed advantage provided by the spatial subdivision. For more details about how to specify the super-brick's position, size and subdivisions see NewDB below. Overview of usage: an application using this facility to perform locality queries over objects of type myStruct would first create a database with: Then, call Attach for each objects to attach to the database. Attach returns a 'proxy' object, which is a link between the user object and its representation in the locality database. When a client object moves, the application calls Update with the new location. Update is a method of the lq.Proxy object, that's why the the proxy object is generally kept within the user object, though it can be managed separately: To perform a query, DB.ForEachWithinRadius is passed a user function which will be called for all client objects in the locality. See Func below for more detail. The DB.FindNearestInRadius function can be used to find a single nearest neighbor using the database. Note that "locality query" is also known as neighborhood query, neighborhood search, near neighbor search, and range query. Author: Aurélien Rainone Based on original work of: Craig Reynolds
Package unfurlist implements a service that unfurls URLs and provides more information about them. The current version supports Open Graph and oEmbed formats, Twitter card format is also planned. If the URL does not support common formats, unfurlist falls back to looking at common HTML tags such as <title> and <meta name="description">. The endpoint accepts GET and POST requests with `content` as the main argument. It then returns a JSON encoded list of URLs that were parsed. If an URL lacks an attribute (e.g. `image`) then this attribute will be omitted from the result. Example: Will return: If handler was configured with FetchImageSize=true in its config, each hash may have additional fields `image_width` and `image_height` specifying dimensions of image provided by `image` attribute. Additionally you can supply `callback` to wrap the result in a JavaScript callback (JSONP), the type of this response would be "application/x-javascript" If an optional `markdown` boolean argument is set (markdown=true), then provided content is parsed as markdown formatted text and links are extracted in context-aware mode — i.e. preformatted text blocks are skipped. Care should be taken when running this inside internal network since it may disclose internal endpoints. It is a good idea to run the service on a separate host in an isolated subnet. Alternatively access to internal resources may be limited with firewall rules, i.e. if service is running as 'unfurlist' user on linux box, the following iptables rules can reduce chances of it connecting to internal endpoints (note this example is for ipv4 only!):
Package pm is a process manager with an HTTP monitoring/control interface. To this package, processes or tasks are user-defined routines within a running program. This model is particularly suitable to server programs, with independent client-generated requests for action. The library would keep track of all such tasks and make the information available through HTTP, thus providing valuable insight into the running application. The client can also ask for a particular task to be canceled. Using pm starts by calling ListenAndServe() in a separate routine, like so: Note that pm's ListenAndServe() will not return by itself. Nevertheless, it will if the underlying net/http's ListenAndServe() does. So it's probably a good idea to wrap that call with some error checking and retrying for production code. Tasks to be tracked must be declared with Start(); that's when the identifier gets linked to them. An optional set of (arbitrary) attributes may be provided, that will get attached to the running task and be reported to the HTTP client tool as well. (Think of host, method and URI for a web server, for instance.) This could go like this: Note the deferred pm.Done() call. That's essential to mark the task as finished and release resources, and has to be called no matter if the task succeeded or not. That's why it's a good idea to use Go's defer mechanism. In fact, the protection from cancel-related panics (see StopCancelPanic below) does NOT work if Done() is called in-line (i.e., not deferred) due to properties of recover(). An HTTP client issuing a GET call to /procs/ would receive a JSON response with a snapshot of all currently running tasks. Each one will include the time when it was started (as per the server clock) as well as the complete set of attributes provided to Start(). Note that to avoid issues with clock skews among servers, the current time for the server is returned as well. The reply to the /procs/ GET also includes a status. When tasks start they are set to "init", but they may change their status using pm's Status() function. Each call will record the change and the HTTP client will receive the last status available, together with the time it was set. Furthermore, the client may GET /procs/<id>/history instead (where <id> is the task identifier) to have a complete history for the given task, including all status changes with their time information. However, note that task information is completely recycled as soon as a task is Done(). Hence, client applications should be prepared to receive a not found reply even if they've just seen the task in a /procs/ GET result. Given the lack of a statement in Go to kill a routine, cancellations are implemented as panics. A DELETE call to /procs/<id> will mark the task with the given identifier as cancel-pending. Nevertheless, the task will never notice until it reaches another Status() call, which is by definition a cancellation point. Calls to Status() either return having set the new status, or panic with an error of type CancelErr. Needless to say, the application should handle this gracefully or will otherwise crash. Programs serving multiple requests will probably be already protected, with a recover() call at the level where the routine was started. But if that's not the case, or if you simply want the panic to be handled transparently, you may use this: When the StopCancelPanic option is set (which is NOT the default) Done() will recover a panic due to a cancel operation. In such a case, the routine running that code will jump to the next statement after the invocation to the function that called Start(). (Read it again.) In other words, stack unfolding stops at the level where Done() was deferred. Notice, though, that this behavior is specifically tailored to panics raising from pending cancellation requests. Should any other panic arise for any reason, it will continue past Done() as usual. So will panics due to cancel requests if StopCancelPanic is not set. Options set with pm.SetOptions() work on a global scope for the process list. Alternatively, you may provide a specific set for some task by using the options argument in the Start() call. If none is given, pm will grab the current global values at the time Start() was invoked. Task-specific options may come handy when, for instance, some tasks should be resilient to cancellation. Setting the ForbidCancel option makes the task effectively immune to cancel requests. Attempts by clients to cancel one of such tasks will inevitably yield an error message with no other effects. Set that with the global SetOptions() function and none of your tasks will cancel, ever. HTTP clients can learn about pending cancellation requests. Furthermore, if a client request happens to be handled between the task is done/canceled and resource recycling (a VERY tiny time window), then the result would include one of these as the status: "killed", "aborted" or "ended", if it was respectively canceled, died out of another panic (not pm-related) or finished successfully. The "killed" status may optionally add a user-defined message, provided through the HTTP /procs/<id> DELETE method. For the cancellation feature to be useful, applications should collaborate. Go lacks a mechanism to cancel arbitrary routines (it even lacks identifiers for them), so programs willing to provide the feature must be willing to help. It's a good practice to add cancellation points every once in a while, particularly when lengthy operations are run. However, applications are not expected to change status that frequently. This package provides the function CheckCancel() for that. It works as a cancellation point by definition, without messing with the task status, nor leaving a trace in history. Finally, please note that cancellation requests yield panics in the same routine that called Start() with that given identifier. However, it's not unusual for servers to spawn additional Go routines to handle the same request. The application is responsible of cleaning up, if there are additional resources that should be recycled. The proper way to do this is by catching CancelErr type panics, cleaning-up and then re-panic, i.e.:
Package enjinql provides an abstracted system for indexing and querying a collection of content. Sources is an interface for managing and querying a collection of Source instances. Source is an interface for managing the correlation of contextual information with the collection of content. There are currently three forms of what a Source is, conceptually speaking. The first is the "primary source" that the Enjin Query Language is tasked with indexing. This is not the actual data being stored in a table per-se, just the necessary bits for providing a reference back to the actual content (like most other indexing systems). For example, in the use of the fantastic bleve search system, the site developer must provide a mapping of fields to index and then for each url of content, pass the url and its specific fields to bleve to index. bleve analyses the individual fields of content and using its internal primary source (likely a btree or some other wizardry), links this listing of URLs to the content fields provided. Once the site indexing process is complete, the developer can easily produce a search page which end-users can use the bleve search syntax to find content present in the site. For the Enjin Query Language, more than just the URL is important. There is still the URL of course but there is a greater context present as well. There is the page's shasum identifier, the page's type of content, language and so on to form a contextual index for finding content. This isn't to replace bleve within Go-Enjin; end-user search features are notoriously difficult to get right and bleve excels at getting this right. As a developer of a Go-Enjin based system, writing features often requires querying the enjin for a contextual case that may not involve the URL at all and to be forced to query for a URL in order to query for a page's specific context becomes a rather tedious repetition of code that isn't easily abstracted. Cases like that are examples of what could be called the farming of technical debt. Of course developers don't like farming technical debt and because one of the main purposes of the Go-Enjin project is to cater to the needs of the developer rather than just the employers and end-users, Go-Enjin necessitates a system for managing and querying a context of information. The second form of Source is the "data source". These are sources of data that relate to the primary source but do not actually have any direct correlation with the primary source context. For example, if the developer needs to build up a list of distinct words found within any given page of content, it is beneficial to have an index of all distinct words in general and to then use another form of source which joins the data source with the primary source. The final form of Source is the "link source" and as noted in the data source description, these sources typically have only unique identifiers which link two data sources together. This is the basis for how the Enjin Query Language can construct SQL queries with multiple JOIN statements without the developer having to spell out the table relationships in their use of the Enjin Query Language. One of the Go-Enjin website projects is an experiment in exploring human thought through the strange indexing of a large set of quotes from various sources. This website is called Quoted.FYI and in specific, it allows visitors to select from a list of "first words" from all quotes and then select from another list of "next words", and so on, building up to a narrow selection of quotes sharing the same series of opening words. To implement this feature, systems like bleve just aren't designed for it. Let's take a little walkthrough of the Quoted.FYI website project. ## Quotes ## Statistics ## EnjinQL Setup Quoted.FYI of course uses the default Go-Enjin primary source which consists of a number of specific columns of information related to any given page. These are the commonly used context keys when implementing Go-Enjin features, and so they're all a part of the primary enjinql source. For each of the authors, topics and words information, Quoted.FYI needs additional indexing to support these various things. They're relatively the same but let's take a look at the words indexing in more detail. The above data source, describes the list of distinct words used to consolidate the space required by the underlying database. So, now there are two sources defined, the primary one and the list of unique words. These two sources, being entirely unrelated to each other would result in a query error if used together. For example, to look up a list of page shasums for the "en" language: The above query would work and return the list of all page shasums that are of the "en" language. The above query again would work, this time returning a list of all words starting with the letter "a". While not the most efficient due to the use of the "starts with" (^=) operator, it does perform well. Given just the primary and word data sources, the following query would not work (yet): The above query is supposed to return a list of page shasums where the page uses the word "thing" at least once. To make this work, the needs to be a link source connecting the relationship of pages to words within each page. The above link source joins the primary source with the word data source and includes an extra count of how many times that specific word is used within the specific quote. Now, the query to get the list of pages with the word "thing": This demonstrates the simplicity of the Enjin Query Language in that the EQL statements don't need to do an SQL magic directly, such as sorting out the table joins. This is all done by the developer simply defining the various sources and then populating them with the content available. The below code demonstrates how to create the primary and word data sources depicted above: With the above constructed, the developer can now proceed with updating the sources instance with the content available. That process needs to be expanded up of course for the complete site, but for just the primary, data and link sources defined so far, the enjinql instance is now ready to build the actual SQL from parsing EQL statements: Code generated by Participle. DO NOT EDIT.
Package lfucache implements an O(1) LFU (Least Frequenty Used) cache. **DEPRECATION WARNING** This package is unmaintained and probably not what you're looking for. This structure is described in the paper "An O(1) algorithm for implementing the LFU cache eviction scheme" by K. Shah, A. Mitra and D. Matani. It is based on two levels of doubly linked lists and gives O(1) insert, access and delete operations. It is implemented here with a few practical optimizations and extra features. The cache supports sending evicted items to interested listeners via channels, and manually evicting cache items matching a certain criteria. This is useful for example when using the package as a write cache for a database, where items must be written to the backing store on eviction. The cache structure is not thread safe. Example: --- Copyright (c) 2013 Jakob Borg. Licensed under the MIT license.