Trying to add hovers to add hovers to my VS Code extension. I was able to syntax highlighting and commands to work, but stuck on adding this hover feature.
I think my blocker is how to properly implement the HoverProvider API. I'm doing a simple test below for a hover provider that activates when a series of tokens are recognized as the keyword HELLO. The hover I've implemented in my testing. I'm using vsce package to package and test my extension locally.
My command for the extension works, but when I hover over the word "HELLO", my hover does not appear.
./client/extension.js
const vscode = require('vscode');
function activate(context) {
console.log('Congratulations, your extension "star-rod" is now active!');
let disposable = vscode.commands.registerCommand('extension.mamar', () => {
vscode.window.showInformationMessage("The Star Rod... is powerful beyond belief. It can grant any wish. For as long as we can remember, Bowser has been making wishes like, for instance... 'I'd like to trounce Mario' or 'I want Princess Peach to like me.' Of course, Stars ignore such selfish wishes. As a result, his wishes were never granted.");
});
context.subscriptions.push(disposable);
vscode.languages.registerHoverProvider('javascript', {
provideHover(document, position, token) {
const range = document.getWordRangeAtPosition(position);
const word = document.getText(range);
if (word == "HELLO") {
return new vscode.Hover({
language: "Hello language",
value: "Hello Value"
});
}
}
});
}
function deactivate() { }
module.exports = {
activate,
deactivate
}
./package.json
{
"name": "star-rod-script",
"publisher": "sonicspiral",
"displayName": "Star Rod Script",
"description": "Syntax highlighting for Paper Mario 64 ROM patching tool",
"version": "1.0.1",
"repository": {
"type": "git",
"url": "https://github.com/gregdegruy/star-rod.git"
},
"categories": [
"Programming Languages"
],
"activationEvents": [
"onCommand:extension.mamar",
"onLanguage:star-rod-script"
],
"engines": {
"vscode": "^1.31.0"
},
"main": "./client/extension.js",
"contributes": {
"capabilities": {
"hoverProvider": "true"
},
"commands": [
{
"command": "extension.mamar",
"title": "Mamar"
}
],
"languages": [
{
"id": "star-rod-script",
"extensions": [
".bpat",
".bscr",
".mpat",
".mscr"
],
"aliases": [
"Star Rod Script",
"mscr"
],
"configuration": "./language-configuration.json"
}
],
"grammars": [
{
"language": "star-rod-script",
"scopeName": "source.mscr",
"path": "./syntaxes/mscr.tmLanguage.json"
}
]
},
"devDependencies": {
"js-yaml": "^3.12.1",
"vscode": "^1.1.29"
}
}
Your code allowed me to get Hovers working in my first extension. I think your mistake is having javascript as the selector: vscode.DocumentSelector. Is that there from code you copied? That should probably be set to star-rod-script for your extension.
I also don't have "capabilities": {"hoverProvider": "true"} in mine. I changed your code to:
disposable = vscode.languages.registerHoverProvider('star-rod-script', { // or 'star rod script'
//....
});
context.subscriptions.push(disposable);
I don't know the nuances of how you apply your extension to certain documents, but it doesn't look like you're trying to apply the hover to javascript docs. You need the selector to include the docs your extension works with. In my case that's covered by my extension name which is the language mode that shows up in the vscode status bar. More info on document-selectors.
Not sure if it's needed, but I also took the return and pushed it onto the subscriptions array. Works without that, but I think that's proper??
Your package.json looks a bit odd. I bet your extension is not activated. The "contributes/capabilites" value is something I haven't seen before. Remove that and instead change your activationEvents to:
"activationEvents": [
"onLanguage:star-rod-script"
],
Related
I am using Cucumber (Gherkin) Full Support by Alexander Krechik in Cypress.
I have a step definition like this:
Then('I expect {string}.{string} button is displayed', (pageName, element) => {
const page = utility.getPage(pageName)
cy.get(page[`${element}`]).should('be.visible')
})
I am getting the auto-suggestion like this while writing in the feature file:
screenshot
After selection it's coming like this:
Then I expect ("|')[^\1]*\1.("|')[^\1]*\1 button is displayed
But I want after selection it should come like this:
Then I expect ""."" button is displayed
I am using these settings in settings.json
{
"cucumberautocomplete.steps": [
"cypress/integration/cucumber-test/**/*.{js,ts}",
"cypress/support/step_definitions/**/*.js"
],
"cucumberautocomplete.syncfeatures": "cypress/integration/features/**/*feature",
"cucumberautocomplete.strictGherkinCompletion": true,
"cucumberautocomplete.pages": {
"checkout": "cypress/pages/legacy/checkout.js"
},
"cucumberautocomplete.formatConfOverride": {
"And": 3,
"But": "relative",
},
"cucumberautocomplete.onTypeFormat": true,
"editor.quickSuggestions": {
"comments": false,
"strings": true,
"other": true
}
}
What setting do I have to achieve it, please help
How can I access the container that appears when I write a url in the address bar? I have a search engine, I just need to show an icon plus a url in the panel
researching I could only get a basic javascript
function createMenuItem(engines) {
for (let engine of engines) {
browser.menus.create({
id: engine.name,
title: engine.name,
contexts: ["selection"]
});
}
}
browser.search.get().then(createMenuItem);
browser.menus.onClicked.addListener((info, tab) => {
browser.search.search({
query: info.selectionText,
engine: info.menuItemId
});
});
//php get variable code
if(isset($_GET["term"])) {
$term = $_GET["term"];
} else {
header('location: '.$url.'');
}
//json
"search_url": "https://127.0.0.1/search/search?term={term}"
result
I tried it with
${term}
$term
{term}
term
You'll notice that the browser.search namespace only has two functions: get() and search() but nothing to add or modify search engines.
Instead, you declare the search engine as a search_provider in your extension's manifest.json file.
Mozilla provides an example for how to add a search engine here. The manifest.json included in the example speaks for itself.
manifest.json
{
"manifest_version": 2,
"name": "Discogs search engine",
"description": "Adds a search engine that searches discogs.com",
"version": "1.0",
"applications": {
"gecko": {
"strict_min_version": "55"
}
},
"chrome_settings_overrides": {
"search_provider": {
"name": "Discogs",
"search_url": "https://www.discogs.com/search/?q={searchTerms}",
"keyword": "disc",
"favicon_url": "https://www.discogs.com/favicon.ico",
"is_default": false,
"encoding": "UTF-8"
}
}
}
I have the following code. This is what it does. When you highlight/select some text on a webpage by clicking and dragging, right click to see the context menu, and when the menu item is clicked, the highlighted text shows up in an alert box. I want to modify this code so that the user doesn't have to highlight any text by click and drag. All they have to do is right click on a word and choose the context menu item. The word/text they right clicked on should appear as alert.
let contextMenuItem = {
"id": "helloWorld",
"title": "Hello World",
"contexts": ["selection"]
};
chrome.contextMenus.removeAll(function() {
chrome.contextMenus.create(contextMenuItem);
});
chrome.contextMenus.onClicked.addListener(function(clickData) {
let inputString = clickData.selectionText;
alert(inputString);
})
First of all, extensions have a "strict" permission model. When you give permission for contextMenus, you are limited to the following contexts:
"all", "page", "frame", "selection", "link", "editable", "image", "video", "audio", "launcher", "browser_action", or "page_action"
Bad UX
If it had a "word" or even a "text" context, it creates a non consistent user experience. Users are not familiar with right click doing actions on text within a web browser.
If you wanted such action, you need to introduce a content-script to add a mouse event to "automatically" select that word using the JavaScript Selection APIs. If you wanted this, you need to expose more "permissions" to your extension to support this experience. Users might not like that.
Example
If this is the experience the extension needs, just create a content-script which automatically selects that word. Something like this will work, which will create a caret range from the mouse position and modify its selection to that word. Note, within the permissions, I just enabled google.com, this is where the content script will inject.
contentscript.js
document.addEventListener('mouseup', (e) => {
if (e.button !== 2) {
return
}
const selection = window.getSelection()
selection.removeAllRanges()
const range = document.caretRangeFromPoint(e.clientX, e.clientY)
range.expand('word')
selection.addRange(range)
});
background.js
const menu = chrome.contextMenus.create({
'id': 'helloWorld',
'title': 'Hello "%s"',
'contexts': ['selection']
})
chrome.contextMenus.onClicked.addListener((clickData) => {
const inputString = clickData.selectionText
console.log(inputString)
});
manifest.json
{
"name": "contextMenus",
"version": "1.0",
"minimum_chrome_version": "35.0",
"manifest_version": 2,
"permissions": [
"contextMenus"
],
"background": {
"scripts": [
"background.js"
]
},
"content_scripts": [
{
"matches": ["https://*.google.com/*"],
"js": ["contentscript.js"]
}
]
}
This is what I'd like to achieve (t is selected in editor):
Before snippet:
var t = 'Foobar';
After snippet:
var t = 'Foobar';
console.log('t', t);
How can I do that?
Here is what I tried to do:
"log_selection": {
"prefix": "cls",
"body": [
"console.log('$TM_SELECTED_TEXT', $TM_SELECTED_TEXT);"
],
"description": "Logs selected text"
}
But this just replace selected text with snippet. I think that I could use TM_CURRENT_LINE here but I have no idea what to do with remaining text in the line.
Do you have any idea for this? Maybe it's impossible with snippet? If so, how can I achieve desired effect?
Thank you.
Extension macros (executing multiple commands in 1 keybinding).
settings.json:
"macros": {
"snippetWithDescription": [
"editor.action.clipboardCopyAction",
"editor.action.insertLineAfter",
{
"command": "editor.action.insertSnippet",
"when": "editorTextFocus",
"args": {
"snippet": "console.log('$CLIPBOARD', $CLIPBOARD)$0"
}
}
]
}
keybindings.json:
{
"key": "ctrl+shift+;",
"command": "macros.snippetWithDescription"
}
P.S. you can even omit the selection part if you add another command at the beginning of snippetWithDescription: "editor.action.addSelectionToNextFindMatch",. Just place cursor beside the word and hit hotkey.
I came to this question looking for a solution other than installing a macro extension. Yours can be done with a snippet though as long as the cursor is at the end of your var declaration line. The snippet would use regex:
"log_selection": {
"prefix": "cls",
"body": [
"",
"console.log('${TM_CURRENT_LINE/var (.+?) =.*$/$1', $1/});"
],
"description": "Logs selected text"
}
The capturing group (.+?) holds your variable name and is placed in $1. I've tested it (and a good thing, because it took a lot of edits to get a working regex). You'd probably want to set up a key binding in your settings to trigger the snippet (but it also works typing the snippet prefix):
"key": "alt+c alt+l", // some key combo
"command": "editor.action.insertSnippet",
"when": "editorTextFocus && !editorHasSelection",
"args": {
"langId": "js", // ?? optional?
"name": "log_selection" // your snippet name
}
Unfortunately, in my case I'm trying to alter the current line so it seems I may need a macro to select the line so that it is replaced.
this worked for me:
"macros": {
"logCurrentVariable": [
"editor.action.addSelectionToNextFindMatch",
"problems.action.copy",
"editor.action.clipboardCopyAction",
{
"command": "editor.action.insertSnippet",
"when": "editorTextFocus",
"args": {
"snippet": "console.log('$CLIPBOARD', $CLIPBOARD)$0"
}
}
]
},
from https://medium.com/#copperfox777/how-to-console-log-variable-under-the-cursor-in-visual-studio-code-ba25feadb00a
I am learning Angular2 using JavaScript(No TypeScript) with the help of this video. The code worked fine, until I started using a service. It starts to give me the following error -
Uncaught ReferenceError: Class is not defined
I understand that Class is not defined in JavaScript, but I assume that it's a part of Angular2 library. Here's my complete app.js code -
(function() {
var Component = ng.core.Component;
var bootstrap = ng.platformBrowserDynamic.bootstrap;
var QuoteService = Class({
constructor:function () {
this.quotes = quotes;
},
getRandomQuote: function (params) {
var randomIndex = Math.floor(Math.random()*quotes.length);
return this.quotes[randomIndex];
}
});
var RandomQuoteComponent = Component({
selector:'random-quote',
template:'<em>{{quote.line}}</em> - {{quote.author}}'
})
.Class({
constructor:function () {
var quoteService = new QuoteService();
this.quote = quoteService.getRandomQuote();
}
});
var AppComponent = Component({
selector: 'my-app',
directives:[RandomQuoteComponent],
template:
'<h1>Random Quotes</h1>'+
'<p><random-quote></random-quote></p>'
})
.Class({
constructor: function () {
//empty
}
});
document.addEventListener('DOMContentLoaded',function () {
bootstrap(AppComponent);
})
var quotes = [
{
"line": "Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.",
"author": "Brian W. Kernighan"
},
{
"line": "Walking on water and developing software from a specification are easy if both are frozen.",
"author": "Edward V Berard"
},
{
"line": "It always takes longer than you expect, even when you take into account Hofstadter's Law.",
"author": "Hofstadter's Law"
},
{
"line": "Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.",
"author": "Rick Osborne"
},
{
"line": "In theory, there is no difference between theory and practice. But, in practice, there is.",
"author": "Jan L. A. van de Snepscheut"
},
{
"line": "Measuring programming progress by lines of code is like measuring aircraft building progress by weight.",
"author": "Bill Gates"
},
{
"line": "There are 2 hard problems in computer science: cache invalidation, naming things, and off-by-1 errors.",
"author": "Leon Bambrick"
},
{
"line": "Nine people can't make a baby in a month.",
"author": "Fred Brooks"
},
{
"line": "If debugging is the process of removing software bugs, then programming must be the process of putting them in.",
"author": "Edsger Dijkstra"
},
{
"line": "The first 90% of the code accounts for the first 90% of the development time. The remaining 10% of the code accounts for the other 90% of the development time.",
"author": "Tom Cargill"
}
];
})();
This line var QuoteService = Class({...}); is responsible for this error. Any idea what could be going wrong in this case?
I think you should write as follows:
var Class = ng.core.Class;
var QuoteService = Class({ ...
https://angular.io/api/core/Class