Ace Editor manually adding snippets - javascript

TL;DR
I am trying to manually trigger ace editor snippets through a function call, rather than the conventional approach (keyboard keys).
Explanation
I need a function that takes in the editor and a snippet string as the parameters, and adds that snippet to the editor. function addSnippet(editor, snippet).
Ace editor supports TextMate-ish snippets.
if (${1:condition_name}) {
${2:body}
}
So when we call this function, it should add the snippet, highlight the snippet markers and select the first one. After filling the first one and hitting tab, the editor should move to the next snippet marker. Just like in the Kitchen Sink example (but I want to add/trigger snippets via a function call instead).
I tried hacking my way through and made this function. But it's messy and incomplete (doesn't support markers and tab presses). Is there any native method for this? I've seen a few examples using snippetManager, but they use keyboard triggers, not manual functions.
Any help regarding this issue would be appreciated.
Thanks.

After hours of hacks and research, I finally came across the insertSnippet function of snippetManager in ext-language_tools.js, it works this way:
var snippetManager = ace.require("ace/snippets").snippetManager;
snippetManager.insertSnippet(editor, snippet);
Pretty easy actually, couldn't find it earlier due to lack of documentation.

If you don't use RequireJS then the following syntax works as well:
ace.config.loadModule('ace/ext/language_tools', function () {
editor.insertSnippet(snippetText);
});

Use ace.define(...) for adding your snippet.
The snippets are written in tex-like language.
For Snippet defined at ./src/lib/json-snippet.js:
// eslint-disable-next-line
const snippet = '# AddNode\n\
snippet addn\n\
{\n\
"nodeName": "${1:node_name}",\n\
"algorithmName": "${2:algo_name}",\n\
"input": []\n\
}\n\
';
export default snippet;
// import your snippet
import snippet from "../lib/json-snippet";
// SUPER HACK FOR ADDING SNIPPETS
ace.define("ace/snippets/json", ["require", "exports", "module"], (e, t, n) => {
// eslint-disable-next-line
(t.snippetText = snippet), (t.scope = "json");
});
Use brace/mode/{filetype}, brace/snippets/{filetype} for defining file type and it snippets.
Find existing snippets at node_module/brace/snippets/ for overriding.
import "brace/mode/json";
import "brace/snippets/json";
import "brace/ext/language_tools";
For more information check out:
Demo
This repository

The other answers seem to be kind of old or rather hacky. This worked for me using actual Ace APIs on v1.4.12 (albeit this seems to be totally and frustratingly undocumented).
const snippetManager = ace.require('ace/snippets').snippetManager;
const snippetContent = `
# scope: html
snippet hello
<p>Hello, \${1:name}!</p>
`;
const snippets = snippetManager.parseSnippetFile(snippetContent);
snippetManager.register(snippets, 'html');
Exchange html for whatever scope you want.
In the editor type "hello" followed by TAB to trigger the snippet.

Related

How do you use multple files in a JavaScript project that will not be used as a web application? Need a single working example

I'm kind of going nuts here.
I need to start writing a stand alone non web application in JavaScript.
My problem is that I can run (using nodejs) the script just fine, but I can't split the code that I need to write among multiple files because then I don't know how to include them.
Rigth now all I want is the simplest working example of including a JS file inside another so I can use the functions defined there (or class if I so choose).
My test.js looks like this.
const { outputText } = require("./text_module.node.js");
outputText();
While my text_module.node.js looks like this:
function outputText(){
console.log("hello world");
}
My package.json looks like this:
{
"type": "text_module.node.js"
}
I have tried
Adding export before the function. It tells me export is unexpected
Using this notation: import { something } from "a_path". Anything that uses this notation will get me an "Unexpected token {" error.
The current configuration simply tells me that outputText() is not a function. So I'm out of ideas.
I don't know how else to search. I've been searching for hours on this topic and it seem that no matter where I look there is some HTML code that is needed to tie everything togeter or using another third party tool. Using jQuery loads stuff "asynchronically" which is not what I need. I want it to sequential.
Is JS just NOT suppossed to be used like other scripting languages? Otherwise I can't figure out why this is so complicated. I feel like I'm missing something big here.
If you want to use const { outputText } = require("./text_module.node.js");,
export it as module.exports = { outputText: outputText }.
In your question,
Adding export before the function. It tells me export is unexpected
Because it's an es6 thing and nodejs doesn't support all es6 features. You can refer to this answer for more details on that.

Unity js script not working

I have recently taken an interest into unity, and as I guide a chose a playlist from youtube. I have installed the
Unity 5.6.4
16 Oct, 2017
version as well.
Now, I encounter an error when I try to add a script to an object.
In the tutorial:
here
, this happens from 11:40 to 13:40.
Basically, as a summary, he is writing a script in js and then attaches it to an object. Now, I have followed the exact steps as him, but it does not work for me.
I write the same script as him, in JS:
then add the script to the object. But then, on the object, I should get a target option, like he does:
However, I don't get this option on my object:
The error I get in the console is this:
Assets/Scripts/PickUp.js(1,386): BCE0044: unexpected char: 0xFEFF.
And this is the actual script:
var target : Transform;
function Update () { }
function OnMouseDown ()
{
this.transform.position = target.position;
this.transform.parent = GameObject.Find("FPSController").transform;
this.transform.parent = GameObject.Find("FirstPersonCharacter").transform;
}
function OnMouseUp ()
{
this.transform.parent = GameObject.Find ("FPSController").transform;
this.transform.parent = null;
}
Now, I've heard that it is not the most efficient, but at this point, I don't really care about that, I just want it to work.
Try to save your script using UTF8 - no BOM (ByteOrderMark). If that does not help, save as Ansi and try that - or read up what unity wants :)
Unity3d Issue Tracker: textassets-encoding-prefab-with-utf8-bom-encryption-is-corrupted it might be related.
This UTF-8 as default in Unity3D new script? was not solved unfortunately.

SonarQube JavaScript disable a part of code

I would like to disable a block of code(say a function) in a file for analysis by SonarQube... Any suggestions on how to do that..
I found something for java here --> Turning Sonar off for certain code
As far as I know Sonar respects // NOSONAR tag for Java projects but it looks like that is also has been implemented for JS: https://jira.sonarsource.com/browse/SONARJS-294
SonarQube provides plenty of options for ignoring issues in specific files and/or code blocks, see Narrowing the Focus documentation (and to your specific case: look for Ignore Issues in Blocks).
To ignore blocks:
// BEGIN-NOSCAN
const YourFunction () => {
// Your code
}
// END-NOSCAN
To ignore single lines:
// NOSONAR
const YourCode = 'Example';
You can read more about it here in the SonarQube docs Narrowing the Focus. Thanks to Jan and Nicolas's answer above.

Markdown syntax highlighting in Javascript

I am trying to get the rainbow syntax highlighting library to work with the marked markdown rendering engine. The marked documentation states that a syntax highlighter is supported through the following configuration option:
marked.setOptions({
highlight: function(code, lang) {
return highlighter.javascript(code);
}
});
The rainbow source code indicates that passing in a string to highlight is supported via the following syntax:
Rainbow.color(code, lang, success);
I'm a bit at a loss as to how to put the two together. Specifically, success is a callback that will be called asynchronously, and I can't simply return the value from the Rainbow.color code inside the highlight callback. How would this be accomplished?
Author of marked here. I addressed this a while ago on the issue tracker: https://github.com/chjj/marked/issues/47
It's more than possible to use an asynchronous highlighter with marked. You'll just have to iterate over the tokens the lexer spits out.
Example here: https://github.com/chjj/marked/issues/47#issuecomment-5297067 (Keep in mind this is an example. You'll have to modify it a bit.)
I might just implement this natively in marked using the method in the link above. It will be a performance hit to the people using async highlighters, but if you need an async highlighter, that means the highlighter is doing some kind of IO and you're already taking a performance hit.
You could try using another highlighting library, such as highlight.js - It has synchronous highlighting methods (hljs.highlight(lang, code).value and hljs.highlightAuto(code).value) that you can use in the browser like this:
marked.setOptions({
highlight: function(code) {
return hljs.highlightAuto(code).value;
}
});
Here's a working JsFiddle example.
Unfortunately there's no way to solve the problem.
marked seems to require a synchronous syntax highlighter, and rainbow is an asynchronous syntax highlighter.
In Javascript there's no way to convert the latter to the former.
This is for example the reason why in node.js for many library functions there are both a synchronous and an asynchronous version. There's no way in Javascript to build a synchronous one given only the asynchronous one because you cannot create a "nested event loop" (in some cases the opposite conversion instead can be done using web workers).
May be it's not difficult to add the synchronous version to rainbow (e.g. by providing beforehand the external resources that it is probably loading asynchronously).
Not the perfect solution, but until the synchronous API has been merged into rainbow.js I solved it with the code below:
// ... after marked() has converted the markdown to html
// (the highlight option of marked should be unchanged!)
// find all <code> elements and go through each
$('body')
.find('code')
.each(function() {
var $code = $(this),
cls = $code.attr('class'),
language;
// no language information at all
if(typeof cls === 'undefined') {
return;
}
// actually we should also check if a valid "lang-" class
// (which is by default set through marked) is given
language = cls.split('-')[1];
// add the data-language to the <code> element
$code.data('language', language);
});
// let the rainbows shine
Rainbow.color();
This runs client side and uses jQuery.

Exclude debug JavaScript code during minification

I'm looking into different ways to minify my JavaScript code including the regular JSMin, Packer, and YUI solutions. I'm really interested in the new Google Closure Compiler, as it looks exceptionally powerful.
I noticed that Dean Edwards packer has a feature to exclude lines of code that start with three semicolons. This is handy to exclude debug code. For instance:
;;; console.log("Starting process");
I'm spending some time cleaning up my codebase and would like to add hints like this to easily exclude debug code. In preparation for this, I'd like to figure out if this is the best solution, or if there are other techniques.
Because I haven't chosen how to minify yet, I'd like to clean the code in a way that is compatible with whatever minifier I end up going with. So my questions are these:
Is using the semicolons a standard technique, or are there other ways to do it?
Is Packer the only solution that provides this feature?
Can the other solutions be adapted to work this way as well, or do they have alternative ways of accomplishing this?
I will probably start using Closure Compiler eventually. Is there anything I should do now that would prepare for it?
here's the (ultimate) answer for closure compiler :
/** #const */
var LOG = false;
...
LOG && log('hello world !'); // compiler will remove this line
...
this will even work with SIMPLE_OPTIMIZATIONS and no --define= is necessary !
Here's what I use with Closure Compiler. First, you need to define a DEBUG variable like this:
/** #define {boolean} */
var DEBUG = true;
It's using the JS annotation for closure, which you can read about in the documentation.
Now, whenever you want some debug-only code, just wrap it in an if statement, like so:
if (DEBUG) {
console.log("Running in DEBUG mode");
}
When compiling your code for release, add the following your compilation command: --define='DEBUG=false' -- any code within the debug statement will be completely left out of the compiled file.
A good solution in this case might be js-build-tools which supports 'conditional compilation'.
In short you can use comments such as
// #ifdef debug
var trace = debug.getTracer("easyXDM.Rpc");
trace("constructor");
// #endif
where you define a pragma such as debug.
Then when building it (it has an ant-task)
//this file will not have the debug code
<preprocess infile="work/easyXDM.combined.js" outfile="work/easyXDM.js"/>
//this file will
<preprocess infile="work/easyXDM.combined.js" outfile="work/easyXDM.debug.js" defines="debug"/>
Adding logic to every place in your code where you are logging to the console makes it harder to debug and maintain.
If you are already going to add a build step for your production code, you could always add another file at the top that turns your console methods into noop's.
Something like:
console.log = console.debug = console.info = function(){};
Ideally, you'd just strip out any console methods, but if you are keeping them in anyway but not using them, this is probably the easiest to work with.
If you use the Closure Compiler in Advanced mode, you can do something like:
if (DEBUG) console.log = function() {}
Then the compiler will remove all your console.log calls. Of course you need to --define the variable DEBUG in the command line.
However, this is only for Advanced mode. If you are using Simple mode, you'll need to run a preprocessor on your source file.
Why not consider the Dojo Toolkit? It has built-in comment-based pragma's to include/exclude sections of code based on a build. Plus, it is compatible with the Closure Compiler in Advanced mode (see link below)!
http://dojo-toolkit.33424.n3.nabble.com/file/n2636749/Using_the_Dojo_Toolkit_with_the_Closure_Compiler.pdf?by-user=t
Even though its an old question. I stumbled upon the same issue today and found that it can be achieved using CompilerOptions.
I followed this thread.
We run the compiler, from Java, on our server before sending the code to the client. This worked for us in Simple mode.
private String compressWithClosureCompiler(final String code) {
final Compiler compiler = new Compiler();
final CompilerOptions options = new CompilerOptions();
Logger.getLogger("com.google.javascript.jscomp").setLevel(Level.OFF);
if (compressRemovesLogging) {
options.stripNamePrefixes = ImmutableSet.of("logger");
options.stripNameSuffixes = ImmutableSet.of("debug", "dev", "info", "error",
"warn", "startClock", "stopClock", "dir");
}
CompilationLevel.SIMPLE_OPTIMIZATIONS.setOptionsForCompilationLevel(options);
final JSSourceFile extern = JSSourceFile.fromCode("externs.js", "");
final JSSourceFile input = JSSourceFile.fromCode("input.js", code);
compiler.compile(extern, input, options);
return compiler.toSource();
}
It will remove all the calls to logger.debug, logger.dev...etc.etc
If you're using UglifyJS2, you can use the drop_console argument to remove console.* functions.
I use this in my React apps:
if (process.env.REACT_APP_STAGE === 'PROD')
console.log = function no_console() {};
In other words, console.log will return nothing on prod enviroment.
I am with #marcel-korpel. Isn't perfect but works. Replace the debug instructions before minification. The regular expression works in many places. Watch out unenclosed lines.
/console\.[^;]*/gm
Works on:
;;; console.log("Starting process");
console.log("Starting process");
console.dir("Starting process");;;;;
console.log("Starting "+(1+2)+" processes"); iamok('good');
console.log('Message ' +
'with new line'
);
console.group("a");
console.groupEnd();
swtich(input){
case 1 : alert('ok'); break;
default: console.warn("Fatal error"); break;
}
Don't works:
console.log("instruction without semicolon")
console.log("semicolon in ; string");
I haven't looked into minification so far, but this behaviour could be accomplished using a simple regular expression:
s/;;;.*//g
This replaces everything in a line after (and including) three semicolons with nothing, so it's discarded before minifying. You can run sed (or a similar tool) before running your minification tool, like this:
sed 's/;;;.*//g' < infile.js > outfile.js
BTW, if you're wondering whether the packed version or the minified version will be 'better', read this comparison of JavaScript compression methods.
I've used following self-made stuf:
// Uncomment to enable debug messages
// var debug = true;
function ShowDebugMessage(message) {
if (debug) {
alert(message);
}
}
So when you've declared variable debug which is set to true - all ShowDebugMessage() calls would call alert() as well. So just use it in a code and forget about in place conditions like ifdef or manual commenting of the debug output lines.
I was searching for a built-in option to do this. I have not found that yet, but my favorite answer also does not require any changes to existing source code. Here's an example with basic usage.
Assume HTML file test.html with:
<html>
<script src="hallo.js"></script>
</html>
And hallo.js with:
sayhi();
function sayhi()
{
console.log("hallo, world!");
}
We'll use a separate file, say noconsole.js, having this from the linked answer:
console.log = console.debug = console.info = function(){};
Then we can compile it as follows, bearing in mind that order matters, noconsole.js must be placed first in the arguments:
google-closure-compiler --js noconsole.js hallo.js --js_output_file hallo.out.js
If you cat hallo.out.js you'd see:
console.log=console.debug=console.info=function(){};sayhi();function sayhi(){console.log("hallo, world!")};
And if I test with mv hallo.out.js hallo.js and reload the page, I can see that the console is now empty.
Hope this clarifies it. Note that I have not yet tested this in the ideal mode of compiling all the source code with ADVANCED optimizations, but I'd expect it to also work.

Categories