I want a Ultisnips snippet capable of dealing with the following scenario:
const [value1, value2, value3, ...valueN] = await Promise.all([
promise1,
promise2,
promise3,
...,
promiseN,
]);
Based on what I type inside the first square brackets, I want to generate the same amount of new tabstops for each line inside the Promise.all block.
Currently I have this approach, which almost works:
global !p
def insert_lines(txt, start = 2, generate_value = lambda i: f'val{i}'):
count = len(txt.split(','))
lines = ["${" + str(i) + ":" + generate_value(i+1-start) + "}," for i in range(start, count + 2)]
snip.expand_anon("\n".join(lines))
endglobal
post_jump "if snip.tabstop == 0: insert_lines(snip.tabstops[1].current_text, start=2)"
snippet pall "await Promise.all" b
const [${1:...items}] = await Promise.all([
$0
]);
endsnippet
The issue I'm having is that $0 there requires me to jump one time more than I would want to. For example, if I have:
const [foo, bar, baz|] = await Promise.all([
val1,
val2,
val3,
]);
Jumping to the next tabstop, I get:
const [foo, bar, baz|] = await Promise.all([
|val1,
val2,
val3,
]);
Then:
const [foo, bar, baz|] = await Promise.all([
val1,
|val2,
val3,
]);
Then:
const [foo, bar, baz|] = await Promise.all([
val1,
val2,
|val3,
]);
At this point, if I jumped to the next tabstop, I'd expect to reach the end of the snippet, however, what happens is this:
const [foo, bar, baz|] = await Promise.all([
val1,
val2,
val3,|
]);
It kind of makes sense because that's the original position of $0.
Is there any other way to achieve what I want?
I am trying to answer this because I have been involved with Ultisnips for a while and I am not reputed enough to comment.
Why don't you try to place the $0 at like ]);$0(the last line of the code you posted)?
I suppose it should resolve the issue. Let me know.
Edit: Use the stack specifically made for vim and vi related questions for such questions. You can find the site here.
Related
I'm trying to use inertContentsOf to loop through and find all "\" characters and insert another "\" character in front of it. The problem is I won't always know the index if the character I need to insert.
For example, I know I want to insert "\" at index 3:
myString.insertContentsOf("\\".characters, at: myString.startIndex.advancedBy(3))
How would I do this without knowing the index?
I've tried the following for loops but haven't had any luck.
for words in inputArray {
for char in words {
if char == "\\" {
words.insertContentsOf("\\".characters, at: char)
}
}
}
at: char yells at me for trying to convert a character to an index, which I get but don't know how to fix it.
Edit: For some reason when I try and put it in a function inputArray.map doesn't get called.
func GenerateString(inputArray:[String])->String {
inputArray.map {
$0.stringByReplacingOccurrencesOfString("\\", withString: "\\\\")
}
let joiner = "|"
let joinerString = inputArray.joinWithSeparator(joiner)
return ("Result: \(joinerString)")
}
let example = ["hello", "world", "c:\Program File\Example"]
GenerateString(example)
Result:
"Hello|world|c:\Program File\Example"
Use stringByReplacingOccurrencesOfString instead:
words.stringByReplacingOccurrencesOfString("\\", withString: "\\\\")
Try stringByReplacingOccurrencesOfString:
var words: String = "c\\Program Files\\Example"
words = words.stringByReplacingOccurrencesOfString("\\", withString: "\\\\")
print("Result: \(words)")
// "Result: c\\Program Files\\Example"
or if you want to do this in a array:
let inputArray: [String] = ["hello", "world", "c\\Program Files\\Example"]
inputArray.map {
$0.stringByReplacingOccurrencesOfString("\\", withString: "\\\\")
}
print("Result: \(inputArray)")
// "Result: ["hello", "world", "c\\Program Files\\Example"]"
stringByReplacingOccurrencesOfString("\\", withString: "\\\\") line means replace \\ with \\\\ and it's exactly what you want to do. :)
Related Questions: Any way to replace characters on Swift String?
You can call enumerate() on any sequence that is a SequenceType to get the index along with the current item so you can do something like:
for (index, char) in words.enumerate()
Although you should also avoid modifying an array while looping it. Think maybe about having another array where you add normal characters to it, and in the case of \, you add \\
You can do map on your array and use stringByReplacingOccurrencesOfString
let new Array = inputArray.map {
$0.stringByReplacingOccurrencesOfString("\\", withString: "\\\\")
}
I am trying to create a way in UltiSnip to take a list of variable names and transform them into a line delimited list of strings (like
you would see in AngularJS). So you type each arg, jump to next placeholder, and above the function is filled in with what you want.
Start with this:
function(FirstArg, SecondArg, ThirdArg)
Hit the CTRL-J (next placeholder)
And Final Result:
[
'FirstArg',
'SecondArg',
'ThridArg',
function(FirstArg, SecondArg, ThirdArg) {
// ... cursor here after hitting CTRL-J
// this would be $0
}
]
Any hints would be great!
Simpler then I thought. This is the function
global !p
def varDeps(args):
result = ""
argList = args.split(",")
for arg in argList:
dep = " " + "'" + arg.strip() + "',\n"
result = result + dep
return result.rstrip()
endglobal
Then use something like this (where this is the third placeholder)
`!p snip.rv = varDeps(t[3])`
function($scope, ${3:deps}) {
//....
}
I have seen many methods for removing the last character from a string. Is there however a way to remove any old character based on its index?
Here is a safe Swift 4 implementation.
var s = "Hello, I must be going"
var n = 5
if let index = s.index(s.startIndex, offsetBy: n, limitedBy: s.endIndex) {
s.remove(at: index)
print(s) // prints "Hello I must be going"
} else {
print("\(n) is out of range")
}
While string indices aren't random-access and aren't numbers, you can advance them by a number in order to access the nth character:
var s = "Hello, I must be going"
s.removeAtIndex(advance(s.startIndex, 5))
println(s) // prints "Hello I must be going"
Of course, you should always check the string is at least 5 in length before doing this!
edit: as #MartinR points out, you can use the with-end-index version of advance to avoid the risk of running past the end:
let index = advance(s.startIndex, 5, s.endIndex)
if index != s.endIndex { s.removeAtIndex(index) }
As ever, optionals are your friend:
// find returns index of first match,
// as an optional with nil for no match
if let idx = s.characters.index(of:",") {
// this will only be executed if non-nil,
// idx will be the unwrapped result of find
s.removeAtIndex(idx)
}
Swift 3.2
let str = "hello"
let position = 2
let subStr = str.prefix(upTo: str.index(str.startIndex, offsetBy: position)) + str.suffix(from: str.index(str.startIndex, offsetBy: (position + 1)))
print(subStr)
"helo"
var hello = "hello world!"
Let's say we want to remove the "w". (It's at the 6th index position.)
First: Create an Index for that position. (I'm making the return type Index explicit; it's not required).
let index:Index = hello.startIndex.advancedBy(6)
Second: Call removeAtIndex() and pass it our just-made index. (Notice it returns the character in question)
let choppedChar:Character = hello.removeAtIndex(index)
print(hello) // prints hello orld!
print(choppedChar) // prints w
On the webpage
http://services.runescape.com/m=itemdb_rs/Armadyl_chaps/viewitem.ws?obj=19463
It lists prices for a particular item in a game, I wanted to grab the "Current guide price:" of said item, and store it as a variable so I could output it in a google spreadsheet. I only want the number, currently it is "643.8k", but I am not sure how to grab specific text like that.
Since the number is in "k" form, that means I can't graph it, It would have to be something like 643,800 to make it graphable. I have a formula for it, and my second question would be to know if it's possible to use a formula on the number pulled, then store that as the final output?
-EDIT-
This is what I have so far and it's not working not sure why.
function pullRuneScape() {
var page = UrlFetchApp.fetch("http://services.runescape.com/m=itemdb_rs/Armadyl_chaps/viewitem.ws?obj=19463").getContentText();
var number = page.match(/Current guide price:<\/th>\n(\d*)/)[1];
SpreadsheetApp.getActive().getSheetByName('RuneScape').appendRow([new Date(), number]);
}
Your regex is wrong. I tested this one successfully:
var number = page.match(/Current guide price:<\/th>\s*<td>([^<]*)<\/td>/m)[1];
What it does:
Current guide price:<\/th> find Current guide price: and closing td tag
\s*<td> allow whitespace between tags, find opening td tag
([^<]*) build a group and match everything except this char <
<\/td> match the closing td tag
/m match multiline
Use UrlFetch to get the page [1]. That'll return an HTTPResponse that you can read with GetBlob [2]. Once you have the text you can use regular expressions. In this case just search for 'Current guide price:' and then read the next row. As to remove the 'k' you can just replace with reg ex like this:
'123k'.replace(/k/g,'')
Will return just '123'.
https://developers.google.com/apps-script/reference/url-fetch/
https://developers.google.com/apps-script/reference/url-fetch/http-response
Obviously, you are not getting anything because the regexp is wrong. I'm no regexp expert but I was able to extract the number using basic string manipulation
var page = UrlFetchApp.fetch("http://services.runescape.com/m=itemdb_rs/Armadyl_chaps/viewitem.ws?obj=19463").getContentText();
var TD = "<td>";
var start = page.indexOf('Current guide price');
start = page.indexOf(TD, start);
var end = page.indexOf('</td>',start);
var number = page.substring (start + TD.length , end);
Logger.log(number);
Then, I wrote a function to convert k,m etc. to the corresponding multiplying factors.
function getMultiplyingFactor(symbol){
switch(symbol){
case 'k':
case 'K':
return 1000;
case 'm':
case 'M':
return 1000 * 1000;
case 'g':
case 'G':
return 1000 * 1000 * 1000;
default:
return 1;
}
}
Finally, tie the two together
function pullRuneScape() {
var page = UrlFetchApp.fetch("http://services.runescape.com/m=itemdb_rs/Armadyl_chaps/viewitem.ws?obj=19463").getContentText();
var TD = "<td>";
var start = page.indexOf('Current guide price');
start = page.indexOf(TD, start);
var end = page.indexOf('</td>',start);
var number = page.substring (start + TD.length , end);
Logger.log(number);
var numericPart = number.substring(0, number.length -1);
var multiplierSymbol = number.substring(number.length -1 , number.length);
var multiplier = getMultiplyingFactor(multiplierSymbol);
var fullNumber = multiplier == 1 ? number : numericPart * multiplier;
Logger.log(fullNumber);
}
Certainly, not the optimal way of doing things but it works.
Basically I parse the html page as you did (with corrected regex) and split the string into number part and multiplicator (k = 1000). Finally I return the extracted number. This function can be used in Google Docs.
function pullRuneScape() {
var pageContent = UrlFetchApp.fetch("http://services.runescape.com/m=itemdb_rs/Armadyl_chaps/viewitem.ws?obj=19463").getContentText();
var matched = pageContent.match(/Current guide price:<.th>\n<td>(\d+\.*\d*)([k]{0,1})/);
var numberAsString = matched[1];
var multiplier = "";
if (matched.length == 3) {
multiplier = matched[2];
}
number = convertNumber(numberAsString, multiplier);
return number;
}
function convertNumber(numberAsString, multiplier) {
var number = Number(numberAsString);
if (multiplier == 'k') {
number *= 1000;
}
return number;
}
I am trying to insert a character into a string using Processing. After some reading around I tried out the following (I think Java) code:
1: String st = new String("abcde");
2: st = StringBuffer(st).insert(2, "C");
and got the following response:
the function StringBuffer(String) does not exist
Is there a different/simpler way of doing this? Do I need to use StringBuffer? I'm a fairly novice programmer so any help greatly appreciated.
Ok, so I've been looking at the processing 'Extended Language API' and there doesn't seem to be some function like that out of the box.
If you look at the String class's substring() function, you'll see an example where there is a String that is cut into two pieces at position 2. And then printed out with other characters between them. Will that help you any further?
String str1 = "CCCP";
String str2 = "Rabbit";
String ss1 = str1.substring(2); // Returns "CP"
String ss2 = str2.substring(3); // Returns "bit"
String ss3 = str1.substring(0, 2); // Returns "CC"
println(ss1 + ":" + ss2 + ":" + ss3); // Prints 'CP:bit:CC'
If we take your example, this would insert the 'C' at the right position:
String st = new String("abcde");
String p1 = st.substring(0,2); // "ab"
String p2 = st.substring(2); // "cde"
st = p1 + "C" + p2; // which will result in "abCcde"
Or create a function for it. Mind you, not super-robust (no checks for empty strings, overflow etc), but does the job:
String insert(original, toInsert, position){
String p1 = original.substring(0,position);
String p2 = original.substring(position);
return p1 + toInsert + p2;
}
...
String st = new String("abcde");
st = insert(st, "C", 2); // "abCcde"
st = insert(st, "D", 4); // "abCcDde"
tested at http://sketch.processing.org
You can insert multiple items with this functions by calling it once for each insert. To make it easier, insert them from right to left as otherwise the position to insert will change as you so inserts to the left.
Example:
String original="The quick fox jumped over lazy dog";
// lets insert "brown" at position 10, "the" at 21, and "'s back" at 34 to make
// "The quick brown fox jumped over the lazy dog's back"
println( original );
original= insertInString( original, "'s back", 34 );
original= insertInString( original, "the ", 26 );
original= insertInString( original, "brown ", 10 );
println( original );
This generated the following output:
The quick fox jumped over lazy dog
The quick brown fox jumped over the lazy dog's back
If you insert from left to right, the positions have to be adjusted after each insert.