sublime-hooks plugin - multiple commands on event hook - sublimetext3

I use sublime-hooks plugin to run a sublime command on event hook. I usually use it to run only one command on event hook. I don't know how to run multiple commands on one event hook. I tried this, but it does not work.
CSS.sublime-settings
{
"on_pre_save_language": [
{
"command": [
"autoprefixer",
"css_comb"
]
}
]
}

According to the plugin docs given in the provided link:
Hooks are stored in the User, Project, or Language settings. Each of
these expects a list of dictionaries. Each of those dictionaries
satisfies the following:
command [...]
args [...]
scope [...]
views [...]
So don't make an array of commands but add an object (with command/args) to the array for every command:
{
"on_pre_save_language": [
{
"command": "autoprefixer"
},
{
"command": "css_comb"
}
]
}

Related

Sublime text 3 keymap only runs last command defined

I'm trying to create two shortcuts to add these codes on sublime when I hit these keys, but only the second one works, like it overrides the first one.
Does someone have any idea on how to get this working?
I tried this:
[{
"keys": ["ctrl+."],
"command": "insert_snippet",
"args": {
"contents": "<pre><?print_r()?></pre>"
},
"keys": ["ctrl+alt+."],
"command": "insert_snippet",
"args": {
"contents": "?><pre><?print_r()?></pre><?"
},
}]
And this:
[{
"keys": ["ctrl+.", "ctrl+alt+."],
"command": "insert_snippet",
"args": {
"contents": "<pre><?print_r()?></pre>",
"contents": "?><pre><?print_r()?></pre><?"
}
}]
Each individual key binding needs to be it's own distinct JSON object (i.e. inside of {} characters), with keys to specify what key triggers it, command to specify what to execute and args to specify the command arguments.
Assuming it's not a copy/paste error of some sort, the reason your examples don't work the way you want them to is because although they contain valid JSON, they don't contain valid key bindings. So the structure of the file is valid, but the way that Sublime interprets it is different than you intended.
To visualize this, here's your first example with the [] characters removed:
{
"keys": ["ctrl+."],
"command": "insert_snippet",
"args": {
"contents": "<pre><?print_r()?></pre>"
},
"keys": ["ctrl+alt+."],
"command": "insert_snippet",
"args": {
"contents": "?><pre><?print_r()?></pre><?"
},
}
Now we can see that the very first { character is opening the first key binding, but there is no matching } character after the args of that command; instead we see another set of key binding object keys and the } on the last line is the end of the key binding.
In any JSON object (this is not Sublime Text specific), object keys need to be unique; so this is actually a single JSON object with each key duplicated. Sublime's reaction to this is to ignore the first three keys in favor of the second three.
This ends you up with a single key binding instead of two of them, and it's the second one, so ctrl+alt+. works, but ctrl+. doesn't because it was ignored.
In your second example, the duplicate object key is in the args key of the key binding; that means that when the key binding triggers, the insert_snippet command will execute, but the argument that it gets will be the contents of that second key.
In this case this binding works, but what you (perhaps inadvertently) did was define a key binding that requires you to press two keys in sequence in order to trigger it. That is, you would need to press ctrl+. followed by ctrl+alt+. in order for the key binding to trigger.
I think based on your examples you intended to have two distinct key bindings that each insert something different, and the first example is closest to that; you just need to insert }, after the first args and a { before the second keys:
[
{
"keys": ["ctrl+."],
"command": "insert_snippet",
"args": {
"contents": "<pre><?print_r()?></pre>"
},
},
{
"keys": ["ctrl+alt+."],
"command": "insert_snippet",
"args": {
"contents": "?><pre><?print_r()?></pre><?"
},
},
]
Here I've reformatted your second example with the additional fix in place to help clarify that it's the {} that are defining the individual key bindings, the [] characters are for wrapping the list of bindings in the file.

Running several scripts with forever

I have several scripts in a directory, each of the scripts called bot and it's number, from 1 to the number of the scripts.
What I would like to do is somehow run all of the scripts by 1 command line through the terminal (Using Ubuntu), I've used forever command to run the script without stopping and etc.
Could you make it through the terminal or using a node js script?
Is there any other commands like forever that would do it for me?
You could use it through the command line with the command forever.
You'll need to create a JSON file with the files you need.
Example:
[
{
// App1
"uid": "app1", // ID of the script.
"append": true,
"watch": true,
"script": "bot1.js", // Name of the script
"sourceDir": "" // Where the script is located. If it's in the
// same location as the json file, leave it ""
},
{
// App2 = > Same as app1, just different script name.
"uid": "app2",
"append": true,
"watch": true,
"script": "bot2.js",
"sourceDir": ""
}
]
Then you need just to run the JSON file through the forever command.
Example:
forever start apps.json
You can see more information about forever here.
My answer is the same as the answer by #Nikita Ivanov but with pm2. I personally like pm2, which also uses a config file just like forever, but it can be a js, json or yaml file.
// JS File
module.exports = {
apps : [{
name: "bot1",
script: "./bot1.js",
watch: true, // some optional param just for example
env: {
"NODE_ENV": "development",
}, // some optional param just for example
env_production : {
"NODE_ENV": "production"
} // some optional param just for example
},{
name: "bot2",
script: "./bot2.js",
instances: 4, // some optional param just for example
exec_mode: "cluster" // some optional param just for example
}]
}
Now if you do not know the number of scripts there are, it ok. Since it is JS, you can write a script to get the list of all the files in the directory and create an array similar to the one above and use that config for pm2.
module.exports = (function () {
// logic to get all file names and create the 'apps' array
return {
apps: apps
}
})()
Furthermore, you can also use the pm2 npm module and use pm2 as a module in a js script and do this.
See PM2 DOCS for more info.

jfrog cli, how to return "creation date" during search

I am trying to retrieve additional fields from jfrog cli:
./jfrog rt s --spec serach_old_spec.json
Having spec:
{
"files": [
{
"aql": {
"items.find": {
"repo": "myrepo-deb-local",
"path": "pool",
"name": {"$match": "*.deb"}
},
},
"limit": 1
}
]
}
This request will actually work, returning files, but only path parameter. How can i return additionally creation date parameter?
I looked into https://www.jfrog.com/confluence/display/RTF/Artifactory+Query+Language#ArtifactoryQueryLanguage-Usage, where i could find
fields (Optional) There is a default set of fields for query output.
This parameter lets you specify a different set of fields that should
be included in the output
The problem, i can't understand how to use it inside specs, and there are no native parameter for jfrog cli https://www.jfrog.com/confluence/display/CLI/CLI+for+JFrog+Artifactory#CLIforJFrogArtifactory-SearchingFiles
Am i forced to implement it manually via REST calls ?

Create a custom setxkbmap option

Oddly, this seems like it should be something that's been done before: I want to swap the numbers and symbols on the 1–0 keys across the top of my keyboard so that:
When I hit the 6 key, an * is typed instead of a 6.
When I hit Shift+6 the number 6 will display instead of an *.
There were several other modifications that I wanted to make, but quickly found that others had already accomplished these layout modifications before using options for setxkbmap (like caps:swapescape, for example).
Given the above, this is a 3-part question:
Is there an option for swapping numbers and symbols on the top row of my keyboard?
Whether there is or not, is there any way to find out if such a thing exists without having to manually browse the *.lst and *.xml files in /usr/share/X11/xkb/rules/?
Finally, if I were to create an option for setxkbmap, what would be an ideal approach, and how would I see about contributing my option back to the community?
As for question 3:
I have attempted to create the option without success (setxkbmap silently fails and I'm not even confident in my approach).
I can't find where the project is hosted.
Aside from man setxkbmap and various blog posts that touch on the topic, I've been unable to find any documentation on any of this.
Question 2:
For a list of all options available, you can execute localectl list-x11-keymap-options. This seems to only provide you with the options themselves, not the descriptions, so a better approach may be to execute the following on the XKB *.lst files:
for f in /usr/share/X11/xkb/rules/*.lst; do sed -ne '/^\! option$/{s///; :a' -e 'n;p;ba' -e '}' $f; done | sort -u
(sed reference)*
If you're looking for something related to swapping numbers, you can append | grep -i num, revealing several options for working with the numpad/keypad. Unfortunately, I think that all of the layouts have the numbers laid out in the templates related to alphanumeric characters, meaning they're built in to the regional layouts themselves (or the variant, in the case of dvorak).
Question 1:
There are three approaches that you can take.
Override layouts using xmodmap
You can create a somewhat versatile approach by creating an .Xmodmap file in your home to override mappings, as described on the Arch Wiki here.
Here is an example configuration: https://github.com/karma0/layouts/blob/master/home/.Xmodmap
Steps:
Drop .Xmodmap in your home.
Add the line xmodmap $HOME/.Xmodmap to your .profile
A quick and dirty, but flexible approach:
Run xkbcomp -xkb $DISPLAY xkbmap to generate a file xkbmap with your current configuration in it.
Modify it to match the desired configuration. Here's an example:
Original:
key <AE01> { [ 1, exclam ] };
key <AE02> { [ 2, at ] };
key <AE03> { [ 3, numbersign ] };
key <AE04> { [ 4, dollar ] };
key <AE05> { [ 5, percent ] };
key <AE06> { [ 6, asciicircum ] };
key <AE07> { [ 7, ampersand ] };
key <AE08> { [ 8, asterisk ] };
key <AE09> { [ 9, parenleft ] };
key <AE10> { [ 0, parenright ] };
Modified:
key <AE01> { [ exclam, 1 ] };
key <AE02> { [ at, 2 ] };
key <AE03> { [ numbersign, 3 ] };
key <AE04> { [ dollar,i 4 ] };
key <AE05> { [ percent, 5 ] };
key <AE06> { [ asciicircum, 6 ] };
key <AE07> { [ ampersand, 7 ] };
key <AE08> { [ asterisk, 8 ] };
key <AE09> { [ parenleft, 9 ] };
key <AE10> { [ parenright, 0 ] };
Execute the command xkbcomp -w 0 xkbmap $DISPLAY to load the new configuration.
Get the command to run at startup using xinitrc or similar.
Modify your layout and add a new variant
Open up your favorite layout file (likely under /usr/share/X11/xkb/symbols). We'll use the us file for this example.
Find your favorite variant within the file; workman-intl if you're like me.
Assuming you want to replicate the workman-intl layout, you can duplicate that section, and modify it similar to how I did here (note that this is copy/pasted from the intl template and the first and second columns are simply swapped):
partial alphanumeric_keys
xkb_symbols "workman-programmer" {
include "us(workman-intl)"
name[Group1]= "English (Workman, intl., with dead keys and num/sym swapped)";
key <AE01> { [ exclam, 1, exclamdown, onesuperior ] };
key <AE02> { [ at, 2, twosuperior, dead_doubleacute ] };
key <AE03> { [ numbersign, 3, threesuperior, dead_macron ] };
key <AE04> { [ dollar, 4, currency, sterling ] };
key <AE05> { [ percent, 5, EuroSign, dead_cedilla ] };
key <AE06> { [ dead_circumflex,6, onequarter, asciicircum ] };
key <AE07> { [ ampersand, 7, onehalf, dead_horn ] };
key <AE08> { [ asterisk, 8, threequarters, dead_ogonek ] };
key <AE09> { [ parenleft, 9, leftsinglequotemark, dead_breve ] };
key <AE10> { [ parenright, 0, rightsinglequotemark, dead_abovering ] };
};
The xkb_symbols line defines the name of your variation; the include line borrows everything you need from the variation of your choice within the file (here, it's the workman-intl variation in the us layout). Then, the definitions you want are what follows.
4. Add your new definition to /usr/share/xkb/rules/base.xml to the end of the variantList tag. Here's the one I used:
<variant>
<configItem>
<name>workman-programmer</name>
<description>English (Workman, intl., with dead keys and num/sym swapped)</description>
</configItem>
</variant>
Add the new variant and description to the ! variant section of /usr/share/X11/xkb/rules/base.lst as:
workman-programmer us: English (Workman, intl., with dead keys and num/sys swapped)'
Restart your Xorg server.
Setup the setxkbmap command to run using the new variant. Here's the one for this demonstration: setxkbmap -layout us -variant workman-programmer -option
Question 3:
Try as you might, you're not going to find the documentation until you start looking for xkb documentation, which is situated within the xorg ecosystem.
The best write-up out there is probably this one:
https://www.charvolant.org/doug/xkb/html/index.html
QUOTE:
Before you read this, please understand that I never wanted to write this document, being grossly under-qualified, but I always wanted to read it, and this was the only way.
Additionally, here are a list of links as well to get started on learning all of the intricacies of the xkb system in xorg: https://www.x.org/wiki/XKB/
Note: most of the documentation references relative paths within xkb as it is installed on your system. This is typically under /usr/share/X11/xkb
If you wish to contribute, this project lives under the xorg, which provides developer documentation here: https://www.x.org/wiki/guide/, or better, here: https://www.x.org/wiki/Development/

AWS Cloudformation: How to reuse bash script placed in user-data parameter when creating EC2?

In Cloudformation I have two stacks (one nested).
Nested stack "ec2-setup":
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Parameters" : {
// (...) some parameters here
"userData" : {
"Description" : "user data to be passed to instance",
"Type" : "String",
"Default": ""
}
},
"Resources" : {
"EC2Instance" : {
"Type" : "AWS::EC2::Instance",
"Properties" : {
"UserData" : { "Ref" : "userData" },
// (...) some other properties here
}
}
},
// (...)
}
Now in my main template I want to refer to nested template presented above and pass a bash script using the userData parameter. Additionally I do not want to inline the content of user data script because I want to reuse it for few ec2 instances (so I do not want to duplicate the script each time I declare ec2 instance in my main template).
I tried to achieve this by setting the content of the script as a default value of a parameter:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Parameters" : {
"myUserData": {
"Type": "String",
"Default" : { "Fn::Base64" : { "Fn::Join" : ["", [
"#!/bin/bash \n",
"yum update -y \n",
"# Install the files and packages from the metadata\n",
"echo 'tralala' > /tmp/hahaha"
]]}}
}
},
(...)
"myEc2": {
"Type": "AWS::CloudFormation::Stack",
"Properties": {
"TemplateURL": "s3://path/to/ec2-setup.json",
"TimeoutInMinutes": "10",
"Parameters": {
// (...)
"userData" : { "Ref" : "myUserData" }
}
But I get following error while trying to launch stack:
"Template validation error: Template format error: Every Default
member must be a string."
The error seems to be caused by the fact that the declaration { Fn::Base64 (...) } is an object - not a string (although it results in returning base64 encoded string).
All works ok, if I paste my script directly into to the parameters section (as inline script) when calling my nested template (instead of reffering to string set as parameter):
"myEc2": {
"Type": "AWS::CloudFormation::Stack",
"Properties": {
"TemplateURL": "s3://path/to/ec2-setup.json",
"TimeoutInMinutes": "10",
"Parameters": {
// (...)
"userData" : { "Fn::Base64" : { "Fn::Join" : ["", [
"#!/bin/bash \n",
"yum update -y \n",
"# Install the files and packages from the metadata\n",
"echo 'tralala' > /tmp/hahaha"
]]}}
}
but I want to keep the content of userData script in a parameter/variable to be able to reuse it.
Any chance to reuse such a bash script without a need to copy/paste it each time?
Here are a few options on how to reuse a bash script in user-data for multiple EC2 instances defined through CloudFormation:
1. Set default parameter as string
Your original attempted solution should work, with a minor tweak: you must declare the default parameter as a string, as follows (using YAML instead of JSON makes it possible/easier to declare a multi-line string inline):
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
myUserData:
Type: String
Default: |
#!/bin/bash
yum update -y
# Install the files and packages from the metadata
echo 'tralala' > /tmp/hahaha
(...)
Resources:
myEc2:
Type: AWS::CloudFormation::Stack
Properties
TemplateURL: "s3://path/to/ec2-setup.yml"
TimeoutInMinutes: 10
Parameters:
# (...)
userData: !Ref myUserData
Then, in your nested stack, apply any required intrinsic functions (Fn::Base64, as well as Fn::Sub which is quite helpful if you need to apply any Ref or Fn::GetAtt functions within your user-data script) within the EC2 instance's resource properties:
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
# (...) some parameters here
userData:
Description: user data to be passed to instance
Type: String
Default: ""
Resources:
EC2Instance:
Type: AWS::EC2::Instance
Properties:
UserData:
"Fn::Base64":
"Fn::Sub": !Ref userData
# (...) some other properties here
# (...)
2. Upload script to S3
You can upload your single Bash script to an S3 bucket, then invoke the script by adding a minimal user-data script in each EC2 instance in your template:
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
# (...) some parameters here
ScriptBucket:
Description: S3 bucket containing user-data script
Type: String
ScriptKey:
Description: S3 object key containing user-data script
Type: String
Resources:
EC2Instance:
Type: AWS::EC2::Instance
Properties:
UserData:
"Fn::Base64":
"Fn::Sub": |
#!/bin/bash
aws s3 cp s3://${ScriptBucket}/${ScriptKey} - | bash -s
# (...) some other properties here
# (...)
3. Use preprocessor to inline script from single source
Finally, you can use a template-preprocessor tool like troposphere or your own to 'generate' verbose CloudFormation-executable templates from more compact/expressive source files. This approach will allow you to eliminate duplication in your source files - although the templates will contain 'duplicate' user-data scripts, this will only occur in the generated templates, so should not pose a problem.
You'll have to look outside the template to provide the same user data to multiple templates. A common approach here would be to abstract your template one step further, or "template the template". Use the same method to create both templates, and you'll keep them both DRY.
I'm a huge fan of cloudformation and use it to create most all my resources, especially for production-bound uses. But as powerful as it is, it isn't quite turn-key. In addition to creating the template, you'll also have to call the coudformation API to create the stack, and provide a stack name and parameters. Thus, automation around the use of cloudformation is a necessary part of a complete solution. This automation can be simplistic ( bash script, for example ) or sophisticated. I've taken to using ansible's cloudformation module to automate "around" the template, be it creating a template for the template with Jinja, or just providing different sets of parameters to the same reusable template, or doing discovery before the stack is created; whatever ancillary operations are necessary. Some folks really like troposphere for this purpose - if you're a pythonic thinker you might find it to be a good fit. Once you have automation of any kind handling the stack creation, you'll find it's easy to add steps to make the template itself more dynamic, or assemble multiple stacks from reusable components.
At work we use cloudformation quite a bit and are tending these days to prefer a compositional approach, where we define the shared components of the templates we use, and then compose the actual templates from components.
the other option would be to merge the two stacks, using conditionals to control the inclusion of the defined resources in any particular stack created from the template. This works OK in simple cases, but the combinatorial complexity of all those conditions tends to make this a difficult solution in the long run, unless the differences are really simple.
Actually I found one more solution than already mentioned. This solution on the one hand is a little "hackish", but on the other hand I found it to be really useful for "bash script" use case (and also for other parameters).
The idea is to create an extra stack - "parameters stack" - which will output the values. Since outputs of a stack are not limited to String (as it is for default values) we can define entire base64 encoded script as a single output from a stack.
The drawback is that every stack needs to define at least one resource, so our parameters stack also needs to define at least one resource. The solution for this issue is either to define the parameters in another template which already defines existing resource, or create a "fake resource" which will never be created becasue of a Condition which will never be satisified.
Here I present the solution with fake resource. First we create our new paramaters-stack.json as follows:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Outputs/returns parameter values",
"Conditions" : {
"alwaysFalseCondition" : {"Fn::Equals" : ["aaaaaaaaaa", "bbbbbbbbbb"]}
},
"Resources": {
"FakeResource" : {
"Type" : "AWS::EC2::EIPAssociation",
"Condition" : "alwaysFalseCondition",
"Properties" : {
"AllocationId" : { "Ref": "AWS::NoValue" },
"NetworkInterfaceId" : { "Ref": "AWS::NoValue" }
}
}
},
"Outputs": {
"ec2InitScript": {
"Value":
{ "Fn::Base64" : { "Fn::Join" : ["", [
"#!/bin/bash \n",
"yum update -y \n",
"# Install the files and packages from the metadata\n",
"echo 'tralala' > /tmp/hahaha"
]]}}
}
}
}
Now in the main template we first declare our paramters stack and later we refer to the output from that parameters stack:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"myParameters": {
"Type": "AWS::CloudFormation::Stack",
"Properties": {
"TemplateURL": "s3://path/to/paramaters-stack.json",
"TimeoutInMinutes": "10"
}
},
"myEc2": {
"Type": "AWS::CloudFormation::Stack",
"Properties": {
"TemplateURL": "s3://path/to/ec2-setup.json",
"TimeoutInMinutes": "10",
"Parameters": {
// (...)
"userData" : {"Fn::GetAtt": [ "myParameters", "Outputs.ec2InitScript" ]}
}
}
}
}
Please note that one can create up to 60 outputs in one stack file, so it is possible to define 60 variables/paramaters per single stack file using this technique.

Resources