In my VSCode extension I have a string filePath and need to know its associated language.
As the user can change the language associations in the configuration (files.associations) only checking for the known extensions does not work.
Is there a functionality in the VSCode API to do that? Or do I need to extract the information from the configuration using vscode.workspace.getConfiguration("files").get("associations")?
Try using workspace.openTextDocument and document.languageId:
import { workspace } from 'vscode';
workspace.openTextDocument(pathToMyFile).then(doc => {
console.log(doc.languageId)
})
This only opens the document from the disk, it will not show it in the editor.
Related
I'm writing a vscode extension where I'm hoping to squeeze more dynamic functionality out of markdown preview. Effectively the problem I'm trying to solve is:
In markdown preview, there's a checkbox
When user clicks the checkbox in markdown preview, send a message/event to the vscode extension runtime
Vscode extension can listen for this message/event and store the action in local storage
Checkbox state is saved - and subsequent renders of the markdown preview can use this action
Ideally, I'd like to do this while keeping the default markdown preview security (https://code.visualstudio.com/Docs/languages/markdown#_strict). After all, I don't need the extension to or markdown preview script to talk to a remote server - I just want them to be able to talk to one another.
Problem as code
To write the problem as sudo code, I want my markdown preview script to contain something like:
const button = ... // get button element
button.addEventListener('click', () => {
... /*
* Send a message to the vscode extension. Something like:
* `vscode.postMessage('vscode.my-extension.preview-action' + value)`
* (which I can't get to work, I'll discuss why)
*/
});
where then my extension can listen for messages like 'vscode.my-extension.preview-action'.
What I've Tried Already
I have tried acquireVsCodeApi() but because the markdown extension already does that, I can't do it again in the subsequent loaded script. I've also tried registering a uri handler but as far as I can try out the preview script still needs to fetch to that uri, which is still blocked by the default markdown security settings.
Perhaps markdown preview scripts are not the place to do this kind of thing, but I just wanted to leverage as much as possible that's already there with the vscode markdown extension. I want to supplement markdown but not replace it, the functionality I want to add is just icing on markdown documentation.
I've read https://code.visualstudio.com/api/extension-guides/markdown-extension#adding-advanced-functionality-with-scripts and it doesn't tell me much about markdown extension scripts capabilities and limitations.
Thanks to #LexLi I looked at some of the source code in the markdown extension and was able to come up with an ugly hack to make this work in preview scripts. Markdown allows normal clicks. And vscode extensions can handle normal clicks. I've paraphrased the code so there could be small syntax errors.
In the extension I did this:
vscode.window.registerUriHandler({
handleUri(uri: vscode.Uri): vscode.ProviderResult<void> {
console.log(`EXTENSION GOT URL: ${uri.toString()}`);
},
});
Then I made sure my extension/preview script put this in the document
<!-- in the preview script I place a button like this -->
<!-- it even works with hidden :) so I can do more app customization -->
<a
hidden
id="my-extension-messager"
href="vscode://publisher-id.my-extension"
>
cant see me but I'm there
</a>
Then my preview script I can even set href before faking a click:
const aMessager = document.querySelector("#my-extension-messager");
console.log('client is setting attribute and clicking...')
aMessager.setAttribute('href', 'vscode://publisher-id.my-extension?action=do-something');
aMessager.click();
console.log('client clicked');
Logs I saw (trimmed/tweaked from my particular extension to match the contrived example):
client is setting attribute and clicking...
client clicked
[Extension Host] EXTENSION GOT URL: vscode://publisher-id.my-extension?action%3Ddo-something
It's a hack but I can do a lot with this. Within the URL I can encode data back to the extension and kind of pass whatever I want (as long as data is relatively small).
I am using this code to check if the client runs from DMG /Volume, and show an alert and quit.
private void IsRunningFromDMG()
{
var currentPath = NSBundle.MainBundle.BundlePath;
if (currentPath.StartsWith("/Volumes", StringComparison.Ordinal))
{
using (var alert = new NSAlert
{
MessageText = "Warning",
InformativeText = "You cannot run this application from DMG, drag move to the " +
"\"/Applications\" folder"
})
{
alert.RunModal();
NSApplication.SharedApplication.Terminate(null);
}
}
}
This is fine if the system language is set to English. I doubt if the /Volumes reacts to localization in that case how to do it?
There should be a system defined constant that would take care of it?
If it is, please help me to know what is it.
Filesystem paths do not change based on localization, they are localized for "display" though (i.e. Pictures, Music, etc... would be localized in Finder for display to the user but the filesystem path is still /User/xxx/Pictures, etc...)
Localized names. The system provides localized names for many system directories, such as Applications, Library, Music, Movies. An app may similarly provide localized names for itself and for any directories it creates.
Display names do not affect the actual name of the file in the file system. Code that accesses a file or directory programmatically must specify the item’s actual name when opening or manipulating the item using the file system interfaces. The only time your app should ever use display names is when displaying the name of a file or directory to the user. You can get the display name for any file or directory using the displayNameAtPath: method of NSFileManager.
i.e.
var urls = NSFileManager.DefaultManager.GetUrls(NSSearchPathDirectory.ApplicationsDirectory, NSSearchPathDomain.System);
var applicationDisplayName = NSFileManager.DefaultManager.DisplayName(urls[0].AbsoluteString);
Note: You should use NSSearchPathDirectory.AllApplicationsDirectory within the NSSearchPathDomain.All domain to obtain a valid list of "Application" urls where your application might/should be located at, instead of hard coding it to the "System" application location.
what i want to do
i want to write a plugin which could open file(which code could not) use user configed cmd.
user config like
{
'mp3':'c:/mp3player/mp3.exe {file_path}'
}
when i use code to open a mp3 the plugin will run this cmd
what the problem
i could not fould a event triger me on each file open
what i have know/try
vscode has some event like
workspaceContains:${toplevelfilename}
onLanguage:${language}
but all of this are hardcode in package.json and could not triger on all file type
help me
it there some advise? maybe this is not a vscode plugin should do?
thanks
The normal approach for that is to listen to the didOpen workspace event:
workspace.onDidOpenTextDocument((doc: TextDocument) => {
if (doc.languageId == "mp3" && doc.uri.scheme === "file") {
// do something
}
});
But note: vscode will not allow to open big or binary files. It will hence not activate your extension for that.
You can create such an application by using VS Code's Custom Editor API.
It seems that there is already an extension to play audio files.
https://marketplace.visualstudio.com/items?itemName=sukumo28.wav-preview
I have an html template which I need to render as a .PDF and then save that pdf file on server. I'm using "rendering" plugin of grails. I'm able to render file as PDF but I don't understand how to save it on server location and not on user's system. Can anybody please help me ?
The pdfRenderingService provided by the plugin allows you to call render and get back an OutputStream. Using that output stream you can write that to a file on your server. The documentation explains the basics of using the service.
Your code may look something like this:
new File("report.pdf").withOutputStream { outputStream ->
outputStream << pdfRenderingService.render(template: '/report/report', model: [serial: 12345])
}
Well, actually I changed my plugin. Got Wkhtmltopdf plugin of grails more helpful. you can find it here --
https://github.com/quorak/grails-wkhtmltopdf
Also instructions regarding using this plugin you can find on the same link or here --
[https://github.com/quorak/grails-wkhtmltopdf]
Using this you can get "bytes" which you can write to file system.
The Adobe Photoshop CS3/4 SDK has a lot of examples for Filter, Import, Export, etc plugins but I haven't found anything that illustrates how to write a 8BX plugin.
The reason is, I need to write one is to add a new drop-down menu to the Photoshop root toolbar (where it displays File, Edit, Image ... Window. Help drop-down menus). I have seen a product like OneSoftware install an 8BX plugin into Adobe Photoshop CS3\Plug-Ins\Extensions directory that causes PS to add adrop down menu for OneSoft. That suggests this is a solvable problem :-)
I tried by changing an existing plugin in the SDK samples but no go. Specifically I modified the resource file:
resource 'PiPL' (ResourceID, plugInName " PiPL", purgeable)
{
{
Kind { **Extension** },
Name { plugInName "..." },
...
Despite using the Extension Kind, PS never loads the plugin. It doesn't generate any compile-time or load error either.
Does anyone have any ideas on how to go about doing this?