Logtalk for VSCodeA VSCode extension that provides language support for Logtalk. Forked from the original plugin by Arthur Wang. Requires Logtalk 3.96.0 or later and a supported Prolog backend. As this extension uses supporting code that's part of the Logtalk distribution, use of the latest Logtalk version is strongly recommended. 🙏 Sponsored by Permion and GitHub Sponsors. Installation | Features | Configuration | Known issues | Development | Acknowledgements | Licence InstallationThis extension can be installed directly from VSCode, from its Marketplace, or by downloading its This extension must be configured before it can be used. Notably, the following settings are required:
For details, see Configuration. This extension includes a walkthrough that can be accessed from the VSCode "Welcome" page after installing the extension. It can also be accessed from the command palette using the command "Welcome: Open Walkthrough...". The walkthrough guides you in configuring the extension and checking that basic functionality is working. FeaturesThis extension provides a comprehensive set of features for Logtalk development:
Most of the features rely on a Logtalk session running in the integrated terminal with VSCode support loaded. This session is automatically created when the extension is activated (by opening a Logtalk source file). This Logtalk session is functionally equivalent to a portable Language Server Protocol (LSP) server. You can also use this section for your own Logtalk queries. Alternatively, you can create a new terminal running a shell and call the backend integration script that you want to use. Syntax highlighting
Automatic indentation
Completions
SnippetsThe snippets for entity opening directives and predicate scope directives are all triggered by natural prefix, i.e. Refer to the table below for other snippets:
Selection rangesThe "Expand Selection" command can be used to expand the selection to the next level using the hierarchy: word, line, comment or directive or clause or grammar rule, predicate or non-terminal definition, entity, file. The "Shrink Selection" command can be used to shrink the selection to the previous level. Formatting supportExperimental support for the "Format Document" and "Format Selection" commands is provided. The formatting rules follow the Logtalk coding style guidelines. Currently, the following formatting rules are supported:
You can verify the changes before saving them using the "File: Compare Active File with Saved" command, which also allows selectively undoing formatting changes. Linter
Quick fixes are provided for some errors and warnings. When applying quick fixes, notably those that delete and insert code, the positions of the warnings and errors later in the file may not be updated, thus preventing further quick fixes to be applied or applied correctly. In this case, save your changes and re-run the linter by using the "Make - Reload" command (note that this command can be called automatically when saving a file using the CommandsMost commands, notably those that run the developer tools, require the code to be loaded, typically by opening the project loader file and selecting the "Load File" menu or context menu item. In the command palette and context menus, all commands have a "Logtalk:" prefix. Project commandsProject (workspace) commands can be triggered from the command palette by typing 'Logtalk' in the input box to pop up the list of all commands of this extension. In this case, the commands resort to the first workspace root folder in the case of multi-root workspaces. Alternatively, these commands can be triggered from the explorer/context menu via right-click (Ctrl+click on Windows and Linux, Cmd+click on macOS) in a Logtalk source file in the Explorer.
The "Create Project" command is usually called from the command palette. It asks for the folder where to copy the renamed sample files. The "Load Project" command looks for a The "Scan Project Dead Code", "Compute Project Metrics", "Generate Project Documentation", and "Generate Project Diagrams" commands require that the project code is already loaded. Quick fixes are provided for some of the documentation and dead code linter warnings. The output of the "Run Project Testers" and "Run Project Doclets" commands is displayed in the "OUTPUT" pane "Logtalk Testers & Doclets" channel. The output of the "Generate Project Documentation" and "Generate Project Diagrams" commands assume that the documentation and the diagrams will be browsed locally in VSCode (with the entry point being the main diagram, which can be opened using the "Open SVG in Viewer" command). The default output directories are The "Open Logtalk" command starts a Logtalk session in the integrated terminal and loads the VSCode support. This command is meant to be used when the Logtalk session created when the extension is activated (by opening a Logtalk source file) is accidentally closed (e.g., by a crash of the backend Prolog process). If you need a separate Logtalk session, create a new terminal running a shell and call the backend integration script that you want to use. Directory and source file commandsThese commands can be triggered from the editor/context menu via right-click in the editor area. These commands can also be triggered from the command palette assuming there's an active editor window.
The "Load Directory" command looks for a The "Run Tests" and "Run Tests with Coverage" commands add failed tests to the "PROBLEMS" pane. Quick fixes are provided for some test definition warnings. The "Generate Documentation" and "Scan Dead Code" commands add linter warnings to the "PROBLEMS" pane. Quick fixes are provided for some of the warnings. The output of the "Generate Documentation" and "Generate Diagrams" commands assume that the documentation and the diagrams will be browsed locally in VSCode (with the entry point being the main diagram, which can be opened using the "Logtalk: Open SVG in Viewer" command). The default output directories are Jupyter commandsThese commands are available from the "Jupyter" sub-menu and allow opening Logtalk source files and Markdown files as Jupyter notebooks, plus pairing and syncing notebook representations. They can be triggered from the explorer and editor context menus via right-click in the editor area or from the command palette.
These commands are only available when Jupytext 1.16.7 or a later version is installed. See also the "logtalk.jupytext.path" setting below. When selecting a Markdown file, the extension must be activated first by opening a Logtalk source file. Paired notebooks allow synchronizing changes between the notebook and its text representation. The text representation is version control and code review friendly. The notebook representation is best for interactive development and testing. See the Jupytext documentation for more details. Make commandsThese commands are available from the "Make" sub-menu. They can be triggered from the explorer and editor context menus via right-click in the editor area or from the command palette.
Profiling commandsThese commands are available from the "Profiling" sub-menu. They can be triggered from the explorer and editor context menus via right-click in the editor area or from the command palette.
The profiling webview allows navigating to the source file location of entities, predicates, and clauses. Note that collecting profiling data depends solely on the project loader file, which must allow recompilation of the source code in debug mode. Diagram commands
Right-click on a Logtalk diagram SVG file in the Explorer pane and select the "Open SVG in Viewer" context menu item to open the selected file in a webview. This webview provides navigation and link handling with zoom and reload controls. Links to other SVG files and HTML documentation files open in the same viewer. This assumes that the commands that generate the diagrams and documentation were used with their default output directories (respectively, Chat participant commandsThese commands are only available from the command palette. They testing and refreshing the documentation cache used by the chat participant.
Extension logging commandsThese commands are only available from the command palette. They are meant for helping with debugging and troubleshooting the extension.
Code NavigationCode navigation features require the code to be loaded, typically by using the "Load Project" command or by opening the project loader file and using the "Load File" command from the editor/context menu. Additionally, code must be compiled with the Go to DeclarationRight-click on a predicate (or non-terminal) name and select the "Go to Declaration" context menu item to go to the predicate (or non-terminal) scope directive. Go to DefinitionRight-click on a predicate (or non-terminal) name in a goal or predicate directive and select the "Go to Definition" context menu item to go to the first clause defining the predicate. Note that some definitions may only be resolved at runtime (e.g., in a message to self goal or when dynamic predicates are used). When a definition is not found, try in alternative to go to the declaration and then to the implementations. Go to Type DefinitionEntities (objects, protocols, and categories) are interpreted as types. Right-click on an entity name and select the "Go to Type Definition" context menu item to go to the entity opening directive. Go to ReferencesRight-click on a predicate (or non-terminal) name in a scope directive, Right-click on an entity name in an entity opening directive to find references to it in other entity opening directives (i.e., entities in an implementing, importing, complementing, extending, instantiating, or specializing relation with the selected entity), Go to ImplementationsRight-click on a predicate (or non-terminal) name in a scope directive and select the "Go to Implementations" or "Find All Implementations" context menu items. Note that you can go to a predicate scope directive by right-clicking in the predicate name in a goal and selecting the "Go to Declaration" context menu item. Right-click on a protocol name in its entity opening directive to find implementations of the protocol. Note that you can go to an entity opening directive by right-clicking in an entity name and selecting the "Go to Type Definition" context menu item. Go to Symbol in Editor...Symbols include entity identifiers in entity opening directives, predicate (and non-terminal) indicators in predicate scope directives, first predicate clause, and first non-terminal rule. Note that VSCode doesn't support customization of symbol kind names and icons, thus forcing adapting the pre-defined names and icons. This feature doesn't require the code to be loaded. Go to Symbol in Workspace...Symbols include entity identifiers in entity opening directives, predicate (and non-terminal) indicators in predicate scope directives, first predicate clause, and first non-terminal rule. Note that VSCode doesn't support customization of symbol kind names and icons, thus forcing adapting the pre-defined names and icons. This feature doesn't require the code to be loaded. Show Call HierarchyRight-click on a predicate (or non-terminal) name in a goal or in a clause head and select the "Show Call Hierarchy" context menu item to browse callers and callees of the selected predicate (or non-terminal). Note that callers and callees that can only be resolved at runtime (e.g., in a message to self goal or when dynamic predicates are used) may not be returned. Show Type HierarchyRight-click on an entity name and select the "Show Type Hierarchy" context menu item to browse ancestors and descendants of the selected entity. Here, ancestor is interpreted as any entity from which the selected entity inherits, and descendant is interpreted as any entity that inherits from the selected entity. Refactoring supportSeveral refactoring operations are supported. Users should commit their work before using this feature and preview the changes (when available) before applying them (see also the When a refactoring results in changes to multiple files, use the "Save All" command to save all modified files so that a single "Make - Reload" command can be used to reload the modified code. Note that this command can be called automatically when saving files using the Increment and decrement numbered variablesThe "Increment numbered variables" and "Decrement numbered variables" refactoring operations are available when the user right-clicks on a variable ending with a number in a predicate rule or in a grammar rule and uses the "Refactor" context menu items or the "Refactor" command palette items. These refactorings increment or decrement all variables with the same prefix and a number equal or greater than the selected variable number in the rule. The selected variable can be anywhere in the rule (e.g., in the head, in the body, or in a comment). Variable inlining and variable introductionAn "Inline variable" refactoring operation is available when the user selects a unification goal in a rule body and uses the "Refactor" context menu item or the "Refactor" command palette item. The refactoring replaces all occurrences of the variable in the rule with its unified term. The unification goal should be the only goal in the line. A "Unify with new variable" refactoring operation is available when the user selects a complete term in a predicate rule or in a grammar rule (e.g., a head argument) and uses the "Refactor" context menu item or the "Refactor" command palette item. The refactoring asks the user for the name of the new variable, replaces the selected term with the new variable, and adds a unification goal to the rule body (after the rule head when the term is a head argument, before the line of the selected term otherwise). Code extractionA "Replace magic number with predicate call" refactoring operation is available when the user selects a number in a rule body and uses the "Refactor" context menu item or the "Refactor" command palette item. The user is asked to enter the name of the predicate to be created and its scope. The predicate is created with the number as its single argument and added to the entity. The selected number is replaced with a variable derived from the predicate name and the rule body is updated with a call to the new predicate inserted after the clause head (note that when compiling the code in optimal mode, the call to the new predicate is inlined). An "Extract predicate/non-terminal" refactoring operation is available when the user selects one ot more lines of code with complete goals in a predicate rule or in a grammar rule and uses the "Refactor" context menu item or the "Refactor" command palette item. The refactoring asks the user for the name of the new predicate (or non-terminal) and adds it after all clauses of the current predicate (or non-terminal). The selected code is replaced with a call to the new predicate (or non-terminal). An "Extract protocol" refactoring operation is available when the user right-clicks on an object or category name in their opening entity directive and uses the "Refactor" context menu item or the "Refactor" command palette item. This refactoring is only available when the entity contains at least one predicate scope directive. The name of the protocol is derived from the name of the selected entity. The user is asked to confirm the file name and file location. The extracted code includes all predicate declarations for the selected entity. The extracted code is always copied verbatim, with no changes to the indentation or whitespace. Four other code extraction refactoring operations are supported when the user selects one or more complete terms (or comments) and uses the "Refactor" context menu item or the "Refactor" command palette item:
Resolving and introducing include/1 directivesWhen the user selects a region of code that contains an The "Replace with include/1 directive" refactoring operation is available when the user selects a region of code and uses the "Refactor" context menu item or the "Refactor" command palette item. The user is asked to select the new file name and file location. The selected code is extracted to the new file and the selection is replaced with an Symbol renamingEntity, predicate, non-terminal, and variable rename support is available:
Entity parameters refactoringTo add a new parameter to an object (or category), right-click on the object (or category) name in its opening directive and select the "Add parameter to object/category" context menu item. To reorder the parameters of an object (or category), right-click on the object (or category) name in its opening directive and select the "Reorder object/category parameters" context menu item. To remove a parameter from an object (or category), right-click on the object (or category) name in its opening directive and select the "Remove parameter from object/category" context menu item. New parameters must use parameter variable syntax (i.e., Predicate and non-terminal argument refactoringTo add a new argument to a predicate (or non-terminal), right-click on the predicate name in a directive, goal, or clause head and select the "Add argument to predicate/non-terminal" context menu item and enter the new argument name and position. To reorder the arguments of a predicate (or non-terminal), right-click on the predicate name in a directive, goal, or clause head and select the "Reorder predicate/non-terminal arguments" context menu item and enter the new argument order. To remove an argument from a predicate (or non-terminal), right-click on the predicate name in a directive, goal, or clause head and select the "Remove argument from predicate/non-terminal" context menu item and enter the argument position. Add predicate/non-terminal declarationTo add a declaration for a local predicate (or non-terminal), right-click on the predicate name in a clause head and select the "Add predicate/non-terminal declaration" context menu item. The declaration, consisting of scope, Directive refactoringThe "Split in individual directives" refactoring operation is available when the user right-clicks on the directive name in a predicate directive with a list argument. The directive is split into individual directives, one for each element in the list. The "Sort predicates/non-terminals" refactoring operation is available when the user right-clicks on the directive name in a predicate directive with a list argument. The list is sorted alphabetically. Single line directives are kept as single line. Multi-line directives are formatted after sorting using the same code as the "Format Selection" command. For directives defining aliases (using the Converting between object, protocol, and category entity typesRight-click on an entity name in its opening directive and select the "Convert ... to object", "Convert ... to protocol", or "Convert ... to category" context menu items. The applicability of these operations depends on the entity type and its opening directive arguments. Note that the entity name is not changed and further edits may be required to the entity code after the conversion to make it valid (for example, removing predicate definitions that are not allowed in a protocol). Converting a Prolog module to an objectRight-click on a module name in its opening directive and select the "Convert module to object" context menu item. The module is converted to an object by replacing the module directive with an object opening directive. Any predicates exported from the module directive are declared as public predicates. Any existing Note that this conversion is always partial as several decisions are required by the user that cannot be automated. Wrapping file contents as an objectRight-click anywhere in a file that has no entity or module opening directives and select the "Wrap file contents as an object" context menu item. The file contents are wrapped with object opening and closing directives. The object name is derived from the file name. This refactoring is useful when converting plain Prolog files to Logtalk. Inferring public predicatesRight-click on an object or category name in its opening directive and select the "Infer public predicates" context menu item. The file must be loaded. The public predicates are inferred from the entity's implementation and a Sorting files by dependenciesRight-click on the predicate name in a Known refactoring issues
Debugging supportWhen debugging in the integrated terminal using the This extension provides a button with a Logtalk icon at the top-right corner to toggle debugging (equivalent to the Breakpoints and log points can be added and removed using the "Run" menu breakpoint items. Clicking at the left of a line number in an editor window, in the same line as a clause head, creates a clause breakpoint represented by a red dot. Control-clicking in this red dot allows the breakpoint to be removed, edited, or disabled. But, although VSCode supports it, a Logtalk breakpoint cannot be a combination of log point and different types of breakpoints. If you edit a breakpoint, you must keep its singular type. Function breakpoints are interpreted as predicate (or non-terminal) spy points by entering a predicate indicator (or a non-terminal indicator) or as context spy points by entering a Changes to spy points via user-typed queries in the integrated terminal are not reflected in the VSCode display of current breakpoints. A particular case is when, at a leashed port, you enter the VSCode usability issues that affect debugging support:
Testing support
Support for the VSCode Testing API is provided. This allows browsing and running tests from the "Testing" pane. After running the "Logtalk: Run Tests" or "Logtalk: Run Tests with Coverage" commands at least once, the "Testing" pane shows all the test results. Alternatively, you can also click in the "Run Tests" or "Run Tests with Coverage" buttons at the top of the "Testing" pane. You can then run individual tests or groups of tests from the "Testing" pane by clicking on the play button next to a test, a test object, or a test file. You can also navigate to a test by clicking its name. In the "Testing" and "Tests Results" panes, you can also use the "Rerun Last Run" button to re-run the last test run. When available, code coverage information is also shown in the covered source files. Note that coverage data is per predicate and per predicate clause (or per non-terminal and per non-terminal rule), not per goal. Clauses used by the tests will be marked using a green color overlay in the editor gutter while clauses not used by the tests will be marked using a red color overlay. Use the editor window "Toggle Inline Coverage" button to toggle the coverage overlay. In the "Testing" pane, the "Test Coverage" sub-pane shows both statement (clauses) and function (predicates) coverage numbers and percentages (note that VSCode doesn't support renaming these terms). In the "Explorer" pane, the colored bar to the right of a file name indicates the combined percentage of covered clauses and predicates. Hovering over the bar shows the separate coverage details. In the "Testing" pane, a warning triangle emoji (⚠️) is shown after the test name when the test is declared as flaky. You can navigate to the test by clicking its name or using the "Go to Test" context menu item. For directory, file, and object items, the "Go to Test" context menu item allows you to navigate to, respectively, the tests driver file, the tests file, and the object in the tests file. Note that collecting code coverage data depends solely on the tests driver file. The option between running tests with or without coverage is only used to decide if any collected coverage data should be displayed. Profiling support
Support for profiling is provided. This allows browsing and analyzing profiling data from the "Logtalk: Profiling" sub-menu in the explorer and editor context menus. After running the "Logtalk: Toggle Profiling" command, loaded code is recompiled in debug mode and profiling is enabled. The "Logtalk: Show Profiling Data" command can be used to show the profiling data in a webview. The webview allows navigating to the source file location of entities, predicates, and clauses. It also allows saving the profiling data as a CSV file. Collected profiling data can be reset using the "Logtalk: Reset Profiling Data" command. The profiling commands are also available from the command palette. See the documentation of the Hover contentsHover contents is provided for built-in directives, built-in predicates, and built-in methods. Chat ParticipantExperimental. The Requirements:
Usage: Type
The The The For the Examples:
Features:
The chat participant automatically detects your Logtalk version from File renaming and deletion propagationRenaming and deletion of Logtalk source files is propagated to Note that if the user selects "Cancel" in the preview dialog, the file will still be renamed or deleted but the propagation changes will not be applied. This is due to a limitation in the VS Code API. But the uer can always focus on the "Explorer" pane and undo the rename or deletion operation. Virtual workspaces supportVirtual workspaces support is limited as the extension is fundamentally designed for local development with a local Logtalk installation. Only basic language features such as syntax highlighting, symbol navigation, and document formatting work in virtual workspaces. Assuming a local Logtalk installation is available, you can start a Logtalk process by running the "Open Logtalk" command. But this process will not be able to load files from the virtual workspace. ConfigurationThe user can configure settings via the VSCode menu Settings are divided between required and optional settings. If you're migrating from an old version of this extension, you may need to delete the old settings (from the Required settingsLogtalk home and user paths
No defaults (VSCode doesn't support using environment variables to define settings). Must be set to the Prolog backend
No default. Possible values are Optional settingsIn most cases, the required settings are enough for full extension functionality. But they assume default installations for Logtalk and the Prolog backends. On Windows, they also assume the default installation of PowerShell 7. When that's not the case, the optional settings listed below allow overriding the defaults that are derived from the required settings. On Windows, use forward slashes in settings that require paths. Use the On a POSIX system (e.g., macOS or Linux), use the For settings that specify scripts, see their man pages for their available options. Logtalk executable
Absolute path to the Logtalk executable or integration script and its arguments. The
On POSIX systems (e.g., macOS or Linux), the Example using the legacy array format (assuming a POSIX system, using SWI-Prolog as the backend, with the integration scripts installed at
Example using the dictionary format for multiple backends (assuming a POSIX system with integration scripts installed at
On Windows systems, use the absolute path to the PowerShell 7 executable and set the arguments to load the Logtalk integration script. For example (assuming the default Logtalk installation) and using SWI-Prolog as the backend:
Example using the dictionary format on Windows for multiple backends:
Logtalk project testers
Absolute path to the
On Windows systems, these settings must be set differently. For example (assuming the default Logtalk installation) and using SWI-Prolog as the backend:
The "logtalk.tester.arguments" setting is only used when the "logtalk.tester.script" setting is not the empty string. By default, the path to the Logtalk project doclets
Absolute path to the
On Windows systems, these settings must be set differently. For example (assuming the default Logtalk installation) and using SWI-Prolog as the backend:
The "logtalk.doclet.arguments" setting is only used when the "logtalk.doclet.script" setting is not the empty string. By default, the path to the Logtalk project documentation
Absolute path to the documentation script and its arguments for converting the XML files generated by the Logtalk
On Windows systems, these settings must be set differently. For example (assuming the default Logtalk installation):
The "logtalk.documentation.arguments" setting is only used when the "logtalk.documentation.script" setting is not the empty string. By default, the path to the Logtalk project diagrams
Absolute path to the script for converting the
On Windows systems, these settings must be set differently. For example (assuming the default Logtalk installation):
Diagrams script for converting the The "logtalk.diagrams.arguments" setting is only used when the "logtalk.diagrams.script" setting is not the empty string. By default, the path to the Load project on activation
Load project on extension activation. Although the default value is Run Logtalk make on save
Automatically call the "Logtalk: Make - Reload" command when saving a Logtalk source file. Although the default value is Code metrics and test results code lens
Enables displaying inline test results (including code coverage when collected) using code lens in both the test object and the tested entity source files opened in the editor. It also enables displaying inline entity cyclomatic complexity after computing code metrics. The tests and metrics data is persistent and can be updated by re-running tests and re-computing metrics (e.g., by simply clicking in the inline data). This setting can be toggled using the "Toggle Code Lens" command. Diagrams file format
Format for the diagram files generated using the "Generate Diagrams" and "Generate Project Diagrams" commands. Note that support for Mermaid is experimental due to limitations in the Mermaid library that currently doesn't provide all the required features for parity with Graphviz and D2. Jupytext path
Absolute path to the Timeout for waiting to run conversion scripts
The number of milliseconds to wait before running the scripts that convert Logtalk extension logging level
Controls the verbosity of logging output for the Logtalk extension. Available levels (from least to most verbose): Known issuesCode issues detected when running the "Make - Check" or "Make - Circular" commands are displayed in the integrated terminal but not added to the "PROBLEMS" pane. But when an issue is reported in a source file, you can right-click (Ctrl+click on Windows and Linux, Cmd+click on macOS) in the file path to navigate to the issue location. On Windows systems, some Prolog backends such as ECLiPSe and XSB are not usable due to file path representation issues. Precise code navigation and quick fixes require a Prolog backend that supports accessing read term starting line but only some backends (B-Prolog, GNU Prolog, JIProlog, SICStus Prolog, SWI-Prolog, Trealla Prolog, XVM, and YAP) provide accurate line numbers. This issue is fixed for ECLiPSe in version 7.2#5 when using Logtalk 3.96.0 or later. When using the "Make - Reload" command, spurious warnings may be reported when there are multiple modified files due to out-of-order compilation. Although the Logtalk If you're migrating from the old "VSC-Logtalk" extension, you may see duplicated context menu items even after uninstalling it. If that happens, delete any extension leftovers in the VSCode triggers the "Go to Definition" computations if the cursor happens to be in the middle of some text when pressing the command (macOS) or control (Windows, Linux) keys to type any keyboard command shortcut without waiting for or requiring cursor movement. It also doesn't allow disabling this "feature". This extension implements mitigation measures to avoid most accidental "Go to Definition" computations. In rare cases, the Logtalk terminal may be restored when reloading the VSCode window or restarting VSCode, despite being marked as transient, due to VSCode limitations. But the restored terminal will not load the required Logtalk VSCode support files. The solution is to manually close the restored terminal. If this is recurrent issue, you can disable terminal persistence in VSCode by setting DevelopmentDeveloped and tested with Logtalk 3.96.0 and VSCode 1.106.2 on macOS 14.8 and Windows 10 with Node 25.1.0. After running See the CHANGELOG.md file for the most recent changes. Contributions and bug reports are most welcome. Publishing
AcknowledgementsThis extension started as a fork of the VSC-Logtalk extension by Arthur Wang. Due to Arthur's current unavailability and since-deprecated modules, this extension has been adopted by new maintainers. Renaming the fork was necessary to allow publishing to the VSCode Marketplace and avoid conflicts with the original extension. Arthur Wang (Original Author)"The original author of this extension thanks Professor Paulo Moura, who is the author of Logtalk, for his patient help and support. Syntax highlighting, some snippets, and some commands are integrated from his distro of Logtalk." LicenseThis extension is published under the MIT license. |



