feat: add hover provider for virtual sensors to display entity details

This commit is contained in:
2026-05-20 23:21:13 +02:00
parent 13e37816f8
commit 91a48a4604
2 changed files with 45 additions and 1 deletions

View File

@@ -244,7 +244,7 @@ class ADVirtualSensorDefinitionProvider implements vscode.DefinitionProvider {
invalidate() { this.cache = undefined; }
private async getSensors(): Promise<VirtualSensorEntry[]> {
async getSensors(): Promise<VirtualSensorEntry[]> {
const now = Date.now();
if (this.cache && now < this.cacheExpiry) { return this.cache; }
this.cache = await findAllVirtualSensors();
@@ -282,6 +282,46 @@ class ADVirtualSensorDefinitionProvider implements vscode.DefinitionProvider {
}
}
class ADVirtualSensorHoverProvider implements vscode.HoverProvider {
constructor(
private haClient: HAClient,
private defProvider: ADVirtualSensorDefinitionProvider
) {}
async provideHover(
document: vscode.TextDocument,
position: vscode.Position
): Promise<vscode.Hover | undefined> {
// Find a virtual sensor whose definition is on this exact line
const sensors = await this.defProvider.getSensors();
const match = sensors.find(
s => s.uri.fsPath === document.uri.fsPath && s.line === position.line
);
if (!match) { return undefined; }
const entity = this.haClient.getEntity(match.sensorId);
if (!entity) { return undefined; }
const md = new vscode.MarkdownString();
md.isTrusted = true;
const friendly = entity.attributes?.friendly_name as string | undefined;
md.appendMarkdown(`### ${friendly || entity.entity_id}\n\n`);
md.appendMarkdown(`| | |\n|---|---|\n`);
md.appendMarkdown(`| **Entity** | \`${entity.entity_id}\` |\n`);
md.appendMarkdown(`| **State** | **\`${entity.state}\`** |\n`);
if (entity.attributes) {
const skip = new Set(['friendly_name', 'icon', 'entity_picture', 'supported_features', 'supported_color_modes']);
for (const [key, value] of Object.entries(entity.attributes).filter(([k]) => !skip.has(k)).slice(0, 12)) {
const display = typeof value === 'object' ? JSON.stringify(value) : String(value);
const truncated = display.length > 60 ? display.substring(0, 57) + '...' : display;
md.appendMarkdown(`| ${key.replace(/\|/g, '\\|')} | \`${truncated.replace(/\|/g, '\\|')}\` |\n`);
}
}
md.appendMarkdown(`\n*Last changed: ${entity.last_changed}*`);
return new vscode.Hover(md);
}
}
// ─────────────────────────────────────────────────────────────────────────────
function updateContextualButton(editor: vscode.TextEditor | undefined) {
@@ -367,6 +407,10 @@ export async function activate(context: vscode.ExtensionContext) {
vscode.languages.registerDefinitionProvider(
{ scheme: 'file', language: 'yaml' },
virtualSensorDefProvider
),
vscode.languages.registerHoverProvider(
{ scheme: 'file', language: 'yaml' },
new ADVirtualSensorHoverProvider(haClient, virtualSensorDefProvider)
)
);