Skip to content

Commit c58b5d6

Browse files
authored
Merge pull request #710 from jpogran/gh-709-puppetfile-autocomplete
(GH-709) Puppetfile autocomplete
2 parents 4fefe49 + 74948b3 commit c58b5d6

File tree

4 files changed

+93
-1
lines changed

4 files changed

+93
-1
lines changed

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/extension.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { IFeature } from './feature';
99
import { DebuggingFeature } from './feature/DebuggingFeature';
1010
import { FormatDocumentFeature } from './feature/FormatDocumentFeature';
1111
import { PDKFeature } from './feature/PDKFeature';
12+
import { PuppetfileCompletionFeature } from './feature/PuppetfileCompletionFeature';
1213
import { PuppetfileHoverFeature } from './feature/PuppetfileHoverFeature';
1314
import { PuppetModuleHoverFeature } from './feature/PuppetModuleHoverFeature';
1415
import { PuppetNodeGraphFeature } from './feature/PuppetNodeGraphFeature';
@@ -85,6 +86,7 @@ export function activate(context: vscode.ExtensionContext) {
8586
new UpdateConfigurationFeature(logger, extContext),
8687
statusBar,
8788
new PuppetfileHoverFeature(extContext, logger),
89+
new PuppetfileCompletionFeature(extContext, logger),
8890
];
8991

9092
if (configSettings.workspace.editorService.enable === false) {
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import * as vscode from 'vscode';
2+
import { IFeature } from '../feature';
3+
import { getPuppetModuleCompletion } from '../forge';
4+
import { ILogger } from '../logging';
5+
6+
export class PuppetfileCompletionProvider implements vscode.CompletionItemProvider {
7+
constructor(public logger: ILogger) {}
8+
async provideCompletionItems(
9+
document: vscode.TextDocument,
10+
position: vscode.Position,
11+
token: vscode.CancellationToken,
12+
context: vscode.CompletionContext,
13+
): Promise<vscode.CompletionItem[] | vscode.CompletionList> {
14+
// get all text until the `position` and check if it reads `mod.`
15+
const linePrefix = document.lineAt(position).text.substr(0, position.character);
16+
if (!linePrefix.startsWith('mod')) {
17+
return undefined;
18+
}
19+
20+
const completionText = document.getText(document.getWordRangeAtPosition(position));
21+
22+
const data = await getPuppetModuleCompletion(completionText, this.logger);
23+
24+
const l: vscode.CompletionList = new vscode.CompletionList();
25+
data.modules.forEach((element) => {
26+
l.items.push(new vscode.CompletionItem(element, vscode.CompletionItemKind.Module));
27+
});
28+
29+
return l;
30+
}
31+
32+
resolveCompletionItem?(
33+
item: vscode.CompletionItem,
34+
token: vscode.CancellationToken,
35+
): vscode.ProviderResult<vscode.CompletionItem> {
36+
throw new Error('Method not implemented.');
37+
}
38+
}
39+
40+
export class PuppetfileCompletionFeature implements IFeature {
41+
constructor(public context: vscode.ExtensionContext, public logger: ILogger) {
42+
const selector = [{ scheme: 'file', language: 'puppetfile' }];
43+
context.subscriptions.push(
44+
vscode.languages.registerCompletionItemProvider(selector, new PuppetfileCompletionProvider(logger)),
45+
);
46+
}
47+
48+
// eslint-disable-next-line @typescript-eslint/no-empty-function
49+
dispose() {}
50+
}

src/forge.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ import axios from 'axios';
22
import { extensions, MarkdownString } from 'vscode';
33
import { ILogger } from './logging';
44

5+
export interface PuppetForgeCompletionInfo {
6+
total: number;
7+
modules: string[];
8+
}
9+
510
export interface PuppetForgeModuleInfo {
611
uri: string;
712
slug: string;
@@ -108,3 +113,38 @@ export function getModuleInfo(title: string, logger: ILogger): Promise<PuppetFor
108113
});
109114
});
110115
}
116+
117+
export function getPuppetModuleCompletion(text: string, logger: ILogger): Promise<PuppetForgeCompletionInfo> {
118+
return new Promise((resolve) => {
119+
return axios
120+
.get(`https://forgeapi.puppet.com/private/modules?starts_with=${text}`, {
121+
params: {
122+
// eslint-disable-next-line @typescript-eslint/camelcase
123+
exclude_fields: 'readme changelog license reference',
124+
},
125+
headers: {
126+
'Content-Type': 'application/json;charset=UTF-8',
127+
'User-Agent': `puppet-vscode/${getVersion()}`,
128+
},
129+
})
130+
.then((response) => {
131+
if (response.status !== 200) {
132+
logger.error(`Error getting Puppet forge data. Status: ${response.status}:${response.statusText}`);
133+
resolve();
134+
}
135+
136+
const info = response.data;
137+
const results: string[] = info.results as string[];
138+
const data = {
139+
total: parseInt(info.total),
140+
modules: results,
141+
};
142+
143+
resolve(data);
144+
})
145+
.catch((error) => {
146+
logger.error(`Error getting Puppet forge data: ${error}`);
147+
resolve();
148+
});
149+
});
150+
}

0 commit comments

Comments
 (0)