Skip to content

Add language icon, New File entry, and .sql file support - #502

Open
juliasilge wants to merge 7 commits into
mainfrom
feat/some-extension-improvements
Open

Add language icon, New File entry, and .sql file support#502
juliasilge wants to merge 7 commits into
mainfrom
feat/some-extension-improvements

Conversation

@juliasilge

Copy link
Copy Markdown
Member

This PR provides three extension improvements, all of which are focused on improving discoverability. Two of the three issues above describe the current situation slightly inaccurately, so this PR does not implement them literally.

This PR also fixes a pre-existing bug where plain VS Code offered run actions that had no handler. That is the last section down there at the bottom.

posit-dev/positron#14953: language icon missing

It turns out that contributes.languages[].icon pointed at ./icon.png, which does not exist and never has; the only images shipped are logo.png and resources/ggsql-icon.svg.

Nothing validates that path, so languageService handed back a URI to a missing file and the icon theme emitted a rule with content: '\2001' (an em quad, used so image icons do not collapse to zero height) plus a background-image that 404s. The result is correctly sized blank space. The broken contribution was worse than no contribution at all. Without it, the item would have fallen through to Seti's generic file glyph, but the language-icon rule is more specific and won.

This PR adds a new resources/ggsql-lang-icon.svg that is a single flat #0A9396 fill with transparent seams, following the file-icon-theme idiom where the background shows through the cuts rather than a second colour being painted. One geometry therefore serves light and dark themes, and icon.light and icon.dark point at the same file. #0A9396 is 3.73:1 on white and 4.42:1 on #1f1f1f, so it clears the 3:1 floor for non-text graphics on both; the dark and light teals from the logo each fail on one background, which is why a single file works and a colour pair would not.

The geometry is derived from the logo rather than redrawn: a boolean union of its own path data, preserving the 29 degree tilt, with three seams subtracted on the logo's own band boundaries. Ink spans 87.5% of a square viewBox, landing at 14px in the 16px slot to match the positron-r reference icon's weight. The viewBox is centred on the shape's area centroid rather than its bounding box, because the thick body sits up-right while the point trails down-left, which made the icon read as shifted left.

This problem was actually broader than the issue reports. Both surfaces named in the issue, the interpreter selector and the console pane, resolve icons through getSessionIconClasses and so are both fixed. The same broken rule was also suppressing the icon for .gsql files in the Explorer, editor tabs and breadcrumbs, which the issue does not mention. resources/ggsql-icon.svg is untouched, since manager.ts still reads it for base64EncodedIconSvg.

Here are some screenshots of how this looks now, in various parts of the IDE:

Screenshot 2026-07-29 at 7 33 44 PM Screenshot 2026-07-29 at 7 34 36 PM Screenshot 2026-07-29 at 7 34 45 PM

It does not change the parts of the IDE where we use the "real" logo:

Screenshot 2026-07-29 at 6 50 41 PM

posit-dev/positron#14955: ggsql file type in New File

Adds a ggsql.createNewFile command contributed to the file/newFile menu, so New File... offers "ggsql File". It opens an untitled document with the ggsql language, matching how positron-r and positron-python and many other extensions implement the same contribution.

FYI the issue and ggsql's own docs use .gsql as the main extension, and that needed a manifest change to actually work. contributes.languages[].extensions listed .ggsql first, and textFileService.suggestFilename uses extensions.at(0), so saving an untitled ggsql document suggested Untitled-1.ggsql. The array is reordered to put .gsql first, which also matches the docs, which use .gsql everywhere a real file extension appears, and never .ggsql. All three extensions stay registered, so existing files keep working.

Unlike positron-r and positron-python, which use group: "file", this uses its own ggsql group so the entry appears under its own heading like Quarto rather than mixed in with the built-in file types, reflecting that ggsql is not built into Positron:

Screenshot 2026-07-29 at 8 35 59 PM

posit-dev/positron#14971: using .sql files with ggsql

FYI the issue's premise conflates two separate things, and the more useful fix is not the one it proposes. It states that running code in a .sql file with a ggsql kernel requires setting files.associations. Execution never actually required that. executeCode('ggsql', ...) names the runtime explicitly, so the document's language id is irrelevant to running the code; the setting was only needed because the extension gated its own run affordances on resourceLangId == ggsql.

So rather than making the association easier to reach, this removes the need for it. The "Source Current File" button, the code cells and the CodeLens now attach to sql documents as well as ggsql ones. Running SQL in a ggsql console works out of the box, with no settings change at all.

That leaves files.associations doing only what it really should, opting in to ggsql syntax highlighting for .sql files.

I don't think the extension should write that setting, so ideas 2 and 3 in the issue are deliberately not implemented as described. Mapping *.sql rewrites how every .sql file in every workspace is treated. It replaces the built-in source.sql grammar, which might arguably be the better grammar for plain SQL, and it breaks language-scoped features from other SQL tooling such as mssql, SQLTools, dbt, etc. I did try a version of this that actually changes the setting on a button press, and that turned out to require a reset command, an offer to un-write, and care about which config level to base the update on. I no longer think we should do this.

Instead, opening a .sql file shows a notice pointing at the setting, with a Show Setting button that opens it directly and a Don't show again button. The notice fires on each open rather than once, because an Info notification in an extension with buttons is not sticky and auto-hides after 10 seconds with no way for an extension to opt out, so a show-once notice is pretty easy to miss. A guard prevents a pile-up when many .sql files open at once, and only "Don't show again" is persisted, so letting the toast age out unseen is not treated as an answer:

Screenshot 2026-07-29 at 9 18 38 PM

I did consider just claiming .sql in contributes.languages but I decided that's a bad idea. Extension-contributed associations resolve last-registered-wins, which is not a contract and is fragile against other SQL extensions, whereas user-configured associations sit in the highest precedence tier and win deterministically.

New ggsql.enableSqlFiles setting (default true) can turn the .sql behaviour off for anyone who uses .sql files with other database tooling.

Also fixed: dead run actions in plain VS Code

I noticed I was making this problem worse, although it predates my work here. On main the editor/title/run buttons were already contributed with when: resourceLangId == ggsql && !isInDiffEditor, with no Positron gate. Every command that executes code is registered after activate() returns early when the Positron API is absent, so plain VS Code has always shown a run button on .gsql files with no handler behind it.

Everything execution-related now gates on Positron's built-in isPositron context key, per the extension development docs: the two editor/title/run buttons, the three keybindings, and the five run commands, which are hidden from the Command Palette through a new commandPalette menu entry. ggsql.createNewFile and ggsql.resetSqlAssociationPrompt are deliberately left ungated, since they work without Positron.

ggsql-vscode/CLAUDE.md claimed "Outside Positron, the same commands fall back to writing query output to the active terminal." No such fallback exists anywhere in src/, which is plausibly why this went unnoticed. That line is replaced with a description of the actual behaviour and of which side of the early return new commands belong on.

A few details

  • All seven inline languageId === 'ggsql' checks now route through isGgsqlDocument() in the new src/languages.ts, rather than each growing its own || 'sql' branch.
  • The CodeLens provider registers for both language ids and gates at request time, firing onDidChangeCodeLenses when the setting changes, so toggling it takes effect without re-registering.
  • ggsql-vscode/CLAUDE.md listed a non-existent icon.png in its layout tree, which is presumably how the broken manifest path arose. Corrected.
  • Docs gain a "Using ggsql with .sql files" section, with an explicit {#sql-files} anchor and then the setting description links to it.

Verification

tsc --noEmit, eslint, and a production esbuild run are clean. The icon was rendered through headless Chromium at true slot geometry (16px background-size in a 16x22 box) on #ffffff, #1f1f1f and #252526, alongside the real Seti python, R and SQL glyphs and the positron-r reference icon, to confirm legibility and matching weight.

@juliasilge
juliasilge requested a review from thomasp85 July 30, 2026 03:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make it more discoverable how to use .sql files with ggsql Add ggsql file as a file type in New ggsql icon missing in the interpreter selector

1 participant