Skip to content

Commit

Permalink
Migrate to only custom formats
Browse files Browse the repository at this point in the history
  • Loading branch information
heaths committed Feb 10, 2024
1 parent 397a8df commit a0528a1
Show file tree
Hide file tree
Showing 10 changed files with 241 additions and 51 deletions.
1 change: 0 additions & 1 deletion .vscodeignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
**/*.zip
node_modules/**
out/**
out/test/**
package-lock.json
res/*.svg
src/**
Expand Down
21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,21 @@ You can set different configuration options to control the format of GUIDs that
* insertGuid.showUppercase: Show uppercase GUIDs (with and without braces) when presenting possible GUID formats to insert. The default is `false`.
* insertGuid.showCodeSnippets: Show code snippets for C++ when presenting possible GUID formats to insert. The default is `true`.
* insertGuid.pasteAutomatically: When not empty, paste the GUID in a specified format without showing selection menu. The default is "". The formatting options are:
* `{b}|{B}` inserts a braced string in lowercase `{b}` or uppercase `{B}` e.g., `{880c86bc-384c-4cce-9e9a-4f760ca755c4}`
* `{d}|{D}` inserts a hyphenated string in lowercase `{d}` or uppercase `{D}` e.g., `880c86bc-384c-4cce-9e9a-4f760ca755c4`
* `{n}|{N}` inserts an unformatted string in lowercase `{n}` or uppercase `{N}` e.g., `880c86bc384c4cce9e9a4f760ca755c4`
* `{x}|{X}` inserts a struct-formatted string in lowercase `{x}` or uppercase `{X}` e.g., `{0x880c86bc,0x384c,0x4cce,{0x9e,0x9a,0x4f,0x76,0x0c,0xa7,0x55,0xc4}}`
* `{x0}|{X0}` inserts the first four bytes as a hexadecimal string in lowercase `{x0}` or uppercase `{X0}` e.g., `0x880c86bc`
* `{x1}|{X1}` and `{x2}|{X2}` insert the second and third two bytes as a hexadecimal string in lowercase `{x1}` and `{x2}`, or uppercase `{X1}` and `{X2}` e.g., `0x384c` and `0x4cce`
* `{x3}|{X3}` through `{x10}|{X10}` insert the subsequent bytes individually as a hexadecimal string in lowercase `{x3}` or uppercase `{X3}` e.g., `0x9e` through `0xc4`.
* `{nl}` inserts a new line
* All other characters will be interpreted literally e.g., `new GUID("{D}")` inserts `new GUID("880C86BC-384C-4CCE-9E9A-4F760CA755C4")`
* `{b}` or `{B}` inserts a braced string in lowercase `{b}` or uppercase `{B}` e.g., `{880c86bc-384c-4cce-9e9a-4f760ca755c4}`
* `{d}` or `{D}` inserts a hyphenated string in lowercase `{d}` or uppercase `{D}` e.g., `880c86bc-384c-4cce-9e9a-4f760ca755c4`
* `{n}` or `{N}` inserts an unformatted string in lowercase `{n}` or uppercase `{N}` e.g., `880c86bc384c4cce9e9a4f760ca755c4`
* `{x}` or `{X}` inserts a struct-formatted string in lowercase `{x}` or uppercase `{X}` e.g., `{0x880c86bc,0x384c,0x4cce,{0x9e,0x9a,0x4f,0x76,0x0c,0xa7,0x55,0xc4}}`
* `{x0}` or `{X0}` inserts the first four bytes as a hexadecimal string in lowercase `{x0}` or uppercase `{X0}` e.g., `0x880c86bc`
* `{x1}` or `{X1}`, and `{x2}` or `{X2}` insert the second and third two bytes as a hexadecimal string in lowercase `{x1}` and `{x2}`, or uppercase `{X1}` and `{X2}` e.g., `0x384c` and `0x4cce`
* `{x3}` or `{X3}` through `{x10}` or `{X10}` insert the subsequent bytes individually as a hexadecimal string in lowercase `{x3}` or uppercase `{X3}` e.g., `0x9e` through `0xc4`.
* `\n` or `{nl}` inserts a new line

All other characters will be interpreted literally e.g., `new GUID("{D}")` inserts `new GUID("880C86BC-384C-4CCE-9E9A-4F760CA755C4")`

For example, to generate a `GUID` for the [windows](https://crates.io/crates/windows) crate, you could define:

```json
"const G: ::windows::core::GUID = ::windows::core::GUID {{nl} data1: 0x{x0},{nl} data2: 0x{x1},{nl} data3: 0x{x2},{nl} data4: [0x{x3}, 0x{x4}, 0x{x5}, 0x{x6}, 0x{x7}, 0x{x8}, 0x{x9}, 0x{x10}],{nl}};"
"const G: ::windows::core::GUID = ::windows::core::GUID {\n data1: 0x{x0},\n data2: 0x{x1},\n data3: 0x{x2},\n data4: [0x{x3}, 0x{x4}, 0x{x5}, 0x{x6}, 0x{x7}, 0x{x8}, 0x{x9}, 0x{x10}],\n};"
```

Which would insert a `GUID` like:
Expand Down
35 changes: 24 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,43 @@
"configuration": {
"title": "Insert GUID",
"properties": {
"insertGuid.formats": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"uniqueItems": true,
"default": null,
"order": 0,
"markdownDescription": "An array of string formats to display in a quick pick menu. Each line contains format specifiers from the list below:\n* `{b}` or `{B}` inserts a braced string in lowercase `{b}` or uppercase `{B}` e.g., `{880c86bc-384c-4cce-9e9a-4f760ca755c4}`\n* `{d}` or `{D}` inserts a hyphenated string in lowercase `{d}` or uppercase `{D}` e.g., `880c86bc-384c-4cce-9e9a-4f760ca755c4`\n* `{n}` or `{N}` inserts an unformatted string in lowercase `{n}` or uppercase `{N}` e.g., `880c86bc384c4cce9e9a4f760ca755c4`\n* `{x}` or `{X}` inserts a struct-formatted string in lowercase `{x}` or uppercase `{X}` e.g., `{0x880c86bc,0x384c,0x4cce,{0x9e,0x9a,0x4f,0x76,0x0c,0xa7,0x55\nxc4}}`\n* `{x0}` or `{X0}` inserts the first four bytes as a hexadecimal string in lowercase `{x0}` or uppercase `{X0}` e.g., `0x880c86bc`\n* `{x1}` or `{X1}`, and `{x2}` or `{X2}` insert the second and third two bytes as a hexadecimal string in lowercase `{x1}` and `{x2}`, or uppercase `{X1}` nd \n{X2}` e.g., `0x384c` and `0x4cce`\n* `{x3}` or `{X3}` through `{x10}` or `{X10}` insert the subsequent bytes individually as a hexadecimal string in lowercase `{x3}` or uppercase `{X3}` e.g.,\n0x9e` through `0xc4`.\n* `\\n` or `{nl}` inserts a new line\n\nAll other characters will be interpreted literally e.g., `new GUID(\"{D}\")` inserts `new GUID(\"880C86BC-384C-4CCE-9E9A-4F760CA755C4\")`"
},
"insertGuid.showLowercase": {
"type": "boolean",
"default": true,
"description": "Show lowercase GUIDs (with and without braces) when presenting possible GUID formats to insert."
"order": 1,
"description": "Show lowercase GUIDs (with and without braces) when presenting possible GUID formats to insert.",
"deprecationMessage": "Add desired lowercase formats to `#insertGuid.formats#`. This setting will be removed in a future version."
},
"insertGuid.showUppercase": {
"type": "boolean",
"default": false,
"description": "Show uppercase GUIDs (with and without braces) when presenting possible GUID formats to insert."
"order": 2,
"description": "Show uppercase GUIDs (with and without braces) when presenting possible GUID formats to insert.",
"deprecationMessage": "Add desired uppercase formats to `#insertGuid.formats#`. This setting will be removed in a future version."
},
"insertGuid.showCodeSnippets": {
"type": "boolean",
"default": true,
"description": "Show code snippets for C++ when presenting possible GUID formats to insert."
"order": 3,
"description": "Show code snippets for C++ when presenting possible GUID formats to insert.",
"deprecationMessage": "Add desired snippet formats to `#insertGuid.formats#`. This setting will be removed in a future version."
},
"insertGuid.pasteAutomatically": {
"type": "string",
"default": "",
"markdownDescription": "Paste GUID without prompting using the specified format:\n* `{b}|{B}` inserts a braced string in lowercase `{b}` or uppercase `{B}` e.g., `{880c86bc-384c-4cce-9e9a-4f760ca755c4}`\n* `{d}|{D}` inserts a hyphenated string in lowercase `{d}` or uppercase `{D}` e.g., `880c86bc-384c-4cce-9e9a-4f760ca755c4`\n* `{n}|{N}` inserts an unformatted string in lowercase `{n}` or uppercase `{N}` e.g., `880c86bc384c4cce9e9a4f760ca755c4`\n* `{x}|{X}` inserts a struct-formatted string in lowercase `{x}` or uppercase `{X}` e.g., `{0x880c86bc,0x384c,0x4cce,{0x9e,0x9a,0x4f,0x76,0x0c,0xa7,0x55,0xc4}}`\n* `{x0}|{X0}` inserts the first four bytes as a hexadecimal string in lowercase `{x0}` or uppercase `{X0}` e.g., `0x880c86bc`\n* `{x1}|{X1}` and `{x2}|{X2}` insert the second and third two bytes as a hexadecimal string in lowercase `{x1}` and `{x2}`, or uppercase `{X1}` and `{X2}` e.g., `0x384c` and `0x4cce`\n* `{x3}|{X3}` through `{x10}|{X10}` insert the subsequent bytes individually as a hexadecimal string in lowercase `{x3}` or uppercase `{X3}` e.g., `0x9e` through `0xc4`.\n* `{nl}` inserts a new line\n* All other characters will be interpreted literally e.g., `new GUID(\"{D}\")` inserts `new GUID(\"880C86BC-384C-4CCE-9E9A-4F760CA755C4\")`"
"order": 4,
"markdownDescription": "Paste GUID without prompting using format specifiers described on `#insertGuid.formats#`."
}
}
},
Expand All @@ -66,11 +84,6 @@
}
]
},
"activationEvents": [
"onCommand:guid.insert",
"onCommand:guid.insertMany",
"onCommand:guid.insertEmpty"
],
"icon": "res/logo.png",
"galleryBanner": {
"color": "#252526",
Expand All @@ -93,13 +106,13 @@
"watch": "webpack --watch",
"watch-test": "tsc -p . -w",
"pretest": "npm run compile-test",
"test": "node ./out/test/runTest.js",
"test": "node ./out/src/test/runTest.js",
"package": "webpack --mode production --devtool hidden-source-map",
"preversion": "npm test",
"vscode:prepublish": "npm run package"
},
"engines": {
"vscode": "^1.30.0"
"vscode": "^1.75.0"
},
"dependencies": {
"buffer": "^6.0.3",
Expand Down
50 changes: 36 additions & 14 deletions src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import * as vscode from 'vscode';
import * as util from 'util';
import { Guid } from './guid';
import getSettings, { Settings } from './settings';

enum FormatType {
LOWERCASE,
Expand Down Expand Up @@ -50,10 +51,17 @@ class GuidPickItem implements vscode.QuickPickItem {
private _guid: Guid;
private readonly _format: GuidPickFormat;

constructor(index: number, guid: Guid, format: GuidPickFormat) {
constructor(index: number, guid: Guid, format: GuidPickFormat | string) {
this._index = index;
this._guid = guid;
this._format = format;
if (typeof format === 'string') {
this._format = {
format: (g) => g.format(format),
type: FormatType.CUSTOM,
};
} else {
this._format = format;
}
}

get label(): string {
Expand Down Expand Up @@ -192,16 +200,27 @@ export function insertEmptyCommand(textEditor: vscode.TextEditor, edit: vscode.T

async function insertCommandImpl(textEditor: vscode.TextEditor, edit: vscode.TextEditorEdit, type: GuidGenerateType): Promise<void> {
const g = type === GuidGenerateType.EMPTY ? Guid.EMPTY : new Guid();
const settings = vscode.workspace.getConfiguration('insertGuid');
const showLowercase = settings.get<boolean>('showLowercase', true);
const showUppercase = settings.get<boolean>('showUppercase', false);
const showCodeSnippets = settings.get<boolean>('showCodeSnippets', true);
const pasteAutomatically = settings.get<string>('pasteAutomatically', '');
const settings = getSettings();
const formats = settings.formats;
const pasteAutomatically = settings.pasteAutomatically;

let item: GuidPickItem;
if (formats !== null) {
const items: GuidPickItem[] = [];
let nextIndex = 0;

const items = getQuickPickItems(g, showLowercase, showUppercase, showCodeSnippets);
let item = items[0];
for (const format of formats) {
items.push(new GuidPickItem(++nextIndex, g, format));
}

if (pasteAutomatically !== '') {
const selection = await vscode.window.showQuickPick<GuidPickItem>(items)
if (selection == null) {
// Selection canceled.
return
}

item = selection
} else if (pasteAutomatically !== null) {
// Format with the specified string and insert without user selection
const customFormatter = {
format: (g: Guid) => g.format(pasteAutomatically),
Expand All @@ -210,6 +229,7 @@ async function insertCommandImpl(textEditor: vscode.TextEditor, edit: vscode.Tex
item = new GuidPickItem(-1, g, customFormatter)
} else {
// Let user select format
const items = getQuickPickItems(g, settings);
const selection = await vscode.window.showQuickPick<GuidPickItem>(items)
if (selection == null) {
// Selection canceled.
Expand Down Expand Up @@ -239,6 +259,8 @@ async function insertCommandImpl(textEditor: vscode.TextEditor, edit: vscode.Tex
});
}

export type QuickPickSettings = Pick<Settings, 'showLowercase' | 'showUppercase' | 'showCodeSnippets'>;

/**
* Gets an array of items to display in the Quick Pick window.
* @param guid The GUID to render in each Quick Pick item.
Expand All @@ -247,14 +269,14 @@ async function insertCommandImpl(textEditor: vscode.TextEditor, edit: vscode.Tex
* @param showCodeSnippets Indicates whether code snippet options should be included in the array.
* @returns An array of items to display in the Quick Pick window.
*/
export function getQuickPickItems(guid: Guid, showLowercase: boolean, showUppercase: boolean, showCodeSnippets: boolean): GuidPickItem[] {
export function getQuickPickItems(guid: Guid, settings: QuickPickSettings): GuidPickItem[] {
const items: GuidPickItem[] = [];
let nextIndex = 0;

for (const format of FORMATS) {
if (((showLowercase || (!showUppercase && !showCodeSnippets)) && format.type === FormatType.LOWERCASE) ||
(showUppercase && format.type === FormatType.UPPERCASE) ||
(showCodeSnippets && format.type === FormatType.SNIPPET)) {
if (((settings.showLowercase || (!settings.showUppercase && !settings.showCodeSnippets)) && format.type === FormatType.LOWERCASE) ||
(settings.showUppercase && format.type === FormatType.UPPERCASE) ||
(settings.showCodeSnippets && format.type === FormatType.SNIPPET)) {
const item = new GuidPickItem(++nextIndex, guid, format);
items.push(item);
}
Expand Down
2 changes: 1 addition & 1 deletion src/guid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export class Guid {
const fn = replacements[replacement]
ret = ret.replace(replacement, fn(this));
}
return ret.replace(/\{nl\}/g, '\n');
return ret.replace(/\{nl\}|\\n/g, '\n');
}

/**
Expand Down
104 changes: 104 additions & 0 deletions src/settings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// The MIT License (MIT)
//
// Copyright (c) Heath Stewart
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import { WorkspaceConfiguration, workspace } from 'vscode';

export interface Settings {
showLowercase: boolean
showUppercase: boolean
showCodeSnippets: boolean
pasteAutomatically: string
formats: string[] | null
};

export const DEFAULTS: Settings = {
showLowercase: true,
showUppercase: false,
showCodeSnippets: true,
pasteAutomatically: '',
formats: null,
};

// Use placeholder token that completely selects with double click.
const NAME_PLACEHOLDER: string = '__NAME__';
const FORMATS: Array<{ format: string, type: 'LOWERCASE' | 'UPPERCASE' | 'SNIPPET' }> = [
{
format: '{d}',
type: 'LOWERCASE',
},
{
format: '{b}',
type: 'LOWERCASE',
},
{
format: `// {b}\nstatic const struct GUID ${NAME_PLACEHOLDER} = {x}\n`,
type: 'SNIPPET',
},
// TODO
];

class SettingsImpl implements Settings {
private readonly _settings: WorkspaceConfiguration;
constructor() {
this._settings = workspace.getConfiguration('insertGuid');
}

get showLowercase(): boolean {
return this._settings.get('showLowercase', DEFAULTS.showLowercase);
}

get showUppercase(): boolean {
return this._settings.get('showUppercase', DEFAULTS.showUppercase);
}

get showCodeSnippets(): boolean {
return this._settings.get('showCodeSnippets', DEFAULTS.showCodeSnippets);
}

get pasteAutomatically(): string {
return this._settings.get('pasteAutomatically', DEFAULTS.pasteAutomatically);
}

get formats(): string[] | null {
let formats = this._settings.get<string[]>('formats');
if (formats !== undefined && formats.length > 0) {
return formats;
}

formats = new Array<string>();
for (const format of FORMATS) {
if (format.type === 'LOWERCASE' && this.showLowercase) {
formats.push(format.format);
} else if (format.type === 'UPPERCASE' && this.showUppercase) {
formats.push(format.format);
} else if (format.type === 'SNIPPET' && this.showCodeSnippets) {
formats.push(format.format);
}
}

return formats;
}

// TODO: Write migration route during start up to populate `formats` using `WorkspaceConfiguration.update`.
};

export default (): Settings => new SettingsImpl();
Loading

0 comments on commit a0528a1

Please sign in to comment.