Selected lines with pattern: Vim Visual Mode - vim

I would like to select (in Vim) the lines that start with the same pattern. For example, if I have this:
if (...) {
print "Accepted\n"
o.attr_out = "Accepted";
}
else if (...) {
print "Partially accepted\n"
o.attr_out = "Partially Accepted";
}
else if (...) {
print " NOT Accepted\n"
o.attr_out = "Not Accepted";
}
Skip to this in a quick way in Vim.
if (...) {
if (debug == true) print "Accepted\n"
o.attr_out = "Accepted";
}
else if (...) {
if (debug == true) print "Partially accepted\n"
o.attr_out = "Partially Accepted";
}
else if (...) {
if (debug == true) print " NOT Accepted\n"
o.attr_out = "Not Accepted";
}

You can use the vim command:
:%s/print "/if ( debug == true ) &/g
here's a quick breakdown of the command:
% - include all lines in the search
s - substiture the 1st pattern with the 2nd.
/print "/ - the pattern you're searching for.
if ( debug == true ) &/ - the text you want to replace the pattern with (note & will put back the print " text that it found in the search).
g - replace all occurrences on the same line. (Technically you don't need that here - since there's only one occurrence of print " on each line).
Refer to the :help :s command for more information.

Related

How to check whether the given word exists in a sentence(string) without using the contains function in golang

I need an alternative method instead of strings.contains() to to check whether the given word exists in a sentence(string).
As an example I need to check the word "can" is inside the sentence "I can run fast" . If I use strings strings.Contains("can", "I can run fast") this gives true . But strings.Contains("can", "I cannot run fast") also gives true as it contains can . How can I check exactly the word can gives true and cannot gives false in the above mentioned scenario ?
Just as a first attempt, you can try using a regular expression:
import "regexp"
var containsCanRegex = regexp.MustCompile(`\b[Cc]an\b`)
func containsCan(s string) bool {
return containsCanRegex.MatchString(s)
}
Note that this matches title-case, so it matches "Can I go?".
The \b in a regular expression matches a "word boundary". It just means there is a word character on one side, and a non-word character, beginning of text, or end of text on the other side.
Note that this will match "can't" because \b treats ' as a word boundary (since it's a non-word character). It sounds like this is not what you want. In order to come up with a more general solution, you may want to know just how general you want the solution to be. A very basic approach would be to split the words first, and then check if any of those words match "can". You could split the words with a regular expression or by using a text segmentation library.
I don't know how to write a regular expression that would accept "can" but reject "can't" in a sentence--the "regexp" package does not support negative lookahead.
I need an alternative method instead of strings.contains() to to check
whether the given word exists in a sentence(string).
I'm trying to implement a filter for given set of words.
Here's a solution which uses simple algorithms for a word. The algorithms can distinguish between "can", "cannot", and "can't".
package main
import (
"fmt"
"strings"
"unicode"
)
func newFilter(words []string) map[string]struct{} {
filter := make(map[string]struct{}, len(words))
for _, word := range words {
word = strings.TrimSpace(word)
word = strings.ToLower(word)
if len(word) > 0 {
filter[word] = struct{}{}
}
}
return filter
}
func applyFilter(text string, filter map[string]struct{}) bool {
const (
rApostrophe = '\u0027'
sApostrophe = string(rApostrophe)
sApostropheS = string(rApostrophe) + "s"
rSoftHyphen = '\u00AD'
sSoftHyphen = string(rSoftHyphen)
sHyphenLF = "-\n"
sHyphenCRLF = "-\r\n"
)
split := func(r rune) bool {
return !unicode.IsLetter(r) && r != rApostrophe
}
text = strings.ToLower(text)
if strings.Contains(text, sSoftHyphen) {
text = strings.ReplaceAll(text, sSoftHyphen, "")
}
if strings.Contains(text, sHyphenLF) {
text = strings.ReplaceAll(text, sHyphenLF, "")
} else if strings.Contains(text, sHyphenCRLF) {
text = strings.ReplaceAll(text, sHyphenCRLF, "")
}
words := strings.FieldsFunc(text, split)
for _, word := range words {
if strings.HasSuffix(word, sApostrophe) {
word = word[:len(word)-len(sApostrophe)]
} else if strings.HasSuffix(word, sApostropheS) {
word = word[:len(word)-len(sApostropheS)]
}
if _, ok := filter[word]; ok {
return true
}
}
return false
}
func main() {
filter := newFilter([]string{"can"})
text := "I can run fast"
fmt.Println(applyFilter(text, filter))
text = "I cannot run fast"
fmt.Println(applyFilter(text, filter))
text = "I can-\nnot run fast"
fmt.Println(applyFilter(text, filter))
text = "I can't run fast"
fmt.Println(applyFilter(text, filter))
filter = newFilter([]string{"cannot", "can't"})
text = "I can run fast"
fmt.Println(applyFilter(text, filter))
text = "I cannot run fast"
fmt.Println(applyFilter(text, filter))
text = "I can-\nnot run fast"
fmt.Println(applyFilter(text, filter))
text = "I can't run fast"
fmt.Println(applyFilter(text, filter))
}
https://go.dev/play/p/sQpTt5JY8Qt

How to sort the characters of a word using awk?

I can't seem to find any way of sorting a word based on its characters in awk.
For example if the word is "hello" then its sorted equivalent is "ehllo". how to achieve this in awk ?
With GNU awk for PROCINFO[], "sorted_in" (see https://www.gnu.org/software/gawk/manual/gawk.html#Controlling-Scanning) and splitting with a null separator resulting in an array of chars:
$ echo 'hello' |
awk '
BEGIN { PROCINFO["sorted_in"]="#val_str_asc" }
{
split($1,chars,"")
word = ""
for (i in chars) {
word = word chars[i]
}
print word
}
'
ehllo
$ echo 'hello' | awk -v ordr='#val_str_asc' 'BEGIN{PROCINFO["sorted_in"]=ordr} {split($1,chars,""); word=""; for (i in chars) word=word chars[i]; print word}'
ehllo
$ echo 'hello' | awk -v ordr='#val_str_desc' 'BEGIN{PROCINFO["sorted_in"]=ordr} {split($1,chars,""); word=""; for (i in chars) word=word chars[i]; print word}'
ollhe
Another option is a Decorate-Sort-Undecorate with sed. Essentially, you use sed to break "hello" into one character per-line (decorating each character with a newline '\n') and pipe the result to sort. You then use sed to do the reverse (undecorate each line by removing the '\n') to join the lines back together.
printf "hello" | sed 's/\(.\)/\1\n/g' | sort | sed '{:a N;s/\n//;ta}'
ehllo
There are several approaches you can use, but this one is shell friendly, but the behavior requires GNU sed.
This would be more doable with gawk, which includes the asort function to sort an array:
awk 'BEGIN{FS=OFS=ORS=""}{split($0,a);asort(a);for(i in a)print a[i]}'<<<hello
This outputs:
ehllo
Demo: https://ideone.com/ylWQLJ
You need to write a function to sort letters in a word (see : https://www.gnu.org/software/gawk/manual/html_node/Join-Function.html):
function siw(word, result, arr, arrlen, arridx) {
split(word, arr, "")
arrlen = asort(arr)
for (arridx = 1; arridx <= arrlen; arridx++) {
result = result arr[arridx]
}
return result
}
And define a sort sub-function to compare two words (see : https://www.gnu.org/software/gawk/manual/html_node/Array-Sorting-Functions.html):
function compare_by_letters(i1, v1, i2, v2, left, right) {
left = siw(v1)
right = siw(v2)
if (left < right)
return -1
else if (left == right)
return 0
else
return 1
}
And use this function with awk sort function:
asort(array_test, array_test_result, "compare_by_letters")
Then, the sample program is:
function siw(word, result, arr, arrlen, arridx) {
result = hash_word[word]
if (result != "") {
return result
}
split(word, arr, "")
arrlen = asort(arr)
for (arridx = 1; arridx <= arrlen; arridx++) {
result = result arr[arridx]
}
hash_word[word] = result
return result
}
function compare_by_letters(i1, v1, i2, v2, left, right) {
left = siw(v1)
right = siw(v2)
if (left < right)
return -1
else if (left == right)
return 0
else
return 1
}
{
array_test[i++] = $0
}
END {
alen = asort(array_test, array_test_result, "compare_by_letters")
for (aind = 1; aind <= alen; aind++) {
print array_test_result[aind]
}
}
Executed like this:
echo -e "fail\nhello\nborn" | awk -f sort_letter.awk
Output:
fail
born
hello
Of course, if you have a big input, you could adapt siw function to memorize result for fastest compute:
function siw(word, result, arr, arrlen, arridx) {
result = hash_word[word]
if (result != "") {
return result
}
split(word, arr, "")
arrlen = asort(arr)
for (arridx = 1; arridx <= arrlen; arridx++) {
result = result arr[arridx]
}
hash_word[word] = result
return result
}
here's a very unorthodox method for a quick-n-dirty approach, if you really want to sort "hello" into "ehllo" :
mawk/mawk2/gawk 'BEGIN { FS="^$"
# to make it AaBbCc… etc; chr(65) = ascii "A"
for (x = 65; x < 91; x++) {
ref = sprintf("%s%c%c",ref, x, x+32)
} } /^[[:alpha:]]$/ { print } /[[:alpha:]][[:alpha:]]+/ {
# for gawk/nawk, feel free to change
# that to /[[:alpha:]]{2,}/
# the >= 2+ condition is to prevent wasting time
# sorting single letter words "A" and "I"
s=""; x=1; len=length(inp=$0);
while ( len && (x<53) ) {
if (inp~(ch = substr(ref,x++,1))) {
while ( sub(ch,"",inp) ) {
s = s ch;
len -= 1 ;
} } }
print s }'
I'm aware it's an extremely inefficient way of doing selection sort. The potential time-savings stem from instant loop ending the moment all letters are completed, instead of iterating all 52 letters everytime. The downside is that it doesn't pre-profile the input
(e.g. if u detect that this row is only lower-case, then u can speed it up with a lowercase only loop instead)
The upside is that it eliminates the need for custom-functions, eliminate any gawk dependencies, and also eliminate the need to split every row into an array (or every character into its own field)
i mean yes technically one can set FS to null string thus automatically becomes having NF as the string length. But at times it could be slow if input is a bit large. If you need unicode support, then a match()-based approach is more desirable.
added (x<53) condition to prevent run-away infinite loops in case input isn't pure ASCII letters

Indent statement after case only without braces in vim cindent

My cinoptions is the folowing :
:set cinoptions={1s,t0,f0s,g0,i0,(0,=0
it works well with brace contained case statement, but not unbraced one :
switch(foo)
{
case(0):
{
...
break;
}
case(1):
... <-- should be indented
break;
}
i need the {1s for all my code need to be formated like that, if i drop the =0 i get this.
switch(foo)
{
case(0):
{
... <-- should not be idented so much
break;
}
case(1):
...
break;
}
Is there any way to specify vim not to indent case in any special way ?
Finaly done it myself, using a in house indent method :
function Indent(line)
" Store current pos
let l:indent = cindent(a:line)
let l:lineprec = a:line - 1
let l:linefirst = split(getline(a:line), " ")[0]
if l:linefirst ==# "{"
let l:case = split(getline(l:lineprec), " ")[0]
if l:case ==# "case"
let l:indent = indent(l:lineprec) + &shiftwidth
endif
endif
return l:indent
endfunction
add in .vimrc :
:set indentexpr=Indent(line(\".\"))
it's kinda specific to my coding style ( case must be followed by a space )

UltiSnips - Create argument list with placeholders

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}) {
//....
}

How to remove whitespaces in strings in Swift?

This works
let replaced = String(map(aString.generate()) {
$0 == " " ? "-" : $0 })
and this doesn't
let replaced = String(map(aString.generate()) {
$0 == " " ? "" : $0 })
Why?
For Swift 5:
" spaces here ".replacingOccurrences(of: " ", with: "")
returns:
"spaceshere"
Enumerating a string gives a sequence of characters, so $0 inside
the closure has the type Character. This compiles
{ $0 == " " ? "-" : $0 }
because "-" in this context is interpreted as a character literal
and therefore of the same type as $0. But
{ $0 == " " ? "" : $0 }
does not compile because "" is not a character literal (and in the conditional expression a ? b : c the operands b and c
must have the same type).
You can fix that by converting $0 to a string:
{ $0 == " " ? "" : String($0) }
but now the mapping returns an array of strings instead
of an array of characters. So instead
of the String() constructor you have to join the results:
let replaced = "".join(map(aString) { $0 == " " ? "" : String($0) })
// Swift 2 / Xcode 7:
let replaced = "".join(aString.characters.map({ $0 == " " ? "" : String($0) }))
(Note that calling generate() explicitly is not needed.)
Of course the same result would also be achieved with
// Before Swift 3.0
let replaced = aString.stringByReplacingOccurrencesOfString(" ", withString: "")
// After Swift 3.0
let replaced = aString.replacingOccurrences(of: " ", with: "")
If you want to remove white space from string then just pass string with stringByReplacingOccurrencesOfString function like below,
let replacedString = string.replacingOccurrences(of: " ", with: "")
For Text Fields, you can apply directly object of UITextField,
let replacedString = textField.text!.replacingOccurrences(of: " ", with: "")
This should work as of Swift 2.2:
let replaced = String(aString.characters.filter {$0 != " "})
If you want to delete whitespaces before and after a string, which is very useful in user input forms, you can use:
let replaced = aString.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
You can apply it directly on a textfield as well.
If you want to remove all whitespaces anywhere in the String I did come up with this solution for Swift 3.0:
let number = "+000 000 000"
let nonWhiteCharacters = number.unicodeScalars.filter {
false == NSCharacterSet.whitespacesAndNewlines.contains($0)
}.map(Character.init)
let whitespacelessNumber = String(nonWhiteCharacters)
or even better (you will need generic extension on Sequence):
extension Sequence {
public func reduce<Result>(_ result: (Self) throws -> Result) rethrows -> Result {
return try result(self)
}
}
and then you can write:
let whitespacelessNumber = number.unicodeScalars.filter {
false == NSCharacterSet.whitespacesAndNewlines.contains($0)
}.map(Character.init).reduce { String($0) }
where you can also replace NSCharacterSet.whitespacesAndNewlines for any of other character sets:
NSCharacterSet.controlCharacters
NSCharacterSet.whitespaces
NSCharacterSet.whitespacesAndNewlines
NSCharacterSet.decimalDigits
NSCharacterSet.letters
NSCharacterSet.lowercaseLetters
NSCharacterSet.uppercaseLetters
NSCharacterSet.nonBaseCharacters
NSCharacterSet.alphanumerics
NSCharacterSet.decomposables
NSCharacterSet.illegalCharacters
NSCharacterSet.punctuationCharacters
NSCharacterSet.capitalizedLetters
NSCharacterSet.symbols
NSCharacterSet.newline
You are mapping thus the number of elements should be preserved. In the second case you remove elements. Your example will fail even in case you replace " " with --.
You might prefer using filter:
let replaced = String(filter(aString.generate()) { $0 != " "})
None of the previous answers where Swifty enough for me, so I ended up with this using Swift 5:
let nonWhitespaceString = String(whitespaceString.compactMap({ $0.isWhitespace ? nil : $0 })
try this one:
let strArray0 = strArray1.map { $0.stringByTrimmingCharactersInSet(.whitespaceAndNewlineCharacterSet()) }
Hope this helps
In Swift 3.0 DO as
func RemoveWhiteSpace(aString:String) -> String
{
let replaced = aString.trimmingCharacters(in: NSCharacterSet.whitespaces)
return replaced
}
And use like this
let nonWhiteSpaceStr = self.RemoveWhiteSpace(aString: "I have white Space ")
NOTE: juhan_h's answer on this question is a more succinct version if whitespace is really all you're interested in stripping out.
https://stackoverflow.com/a/57425783/5946596
Swift 5.5
All the answers are great for removing spaces but sometimes I want to remove any whitespaces and newLines throwing in _ and - ... who knows.
The following extension on string lets me do that.
extension String {
func removingCharacters(_ characters:CharacterSet) -> Self {
Self(self.unicodeScalars.filter {
!characters.contains($0)
})
}
func removingCharacters(in string:String) -> Self {
Self(self.unicodeScalars.filter {
!CharacterSet(charactersIn:string).contains($0)
})
}
func replacingCharacters(_ characters:CharacterSet, with newChar:Character) -> Self {
String(self.compactMap( {
CharacterSet(charactersIn: "\($0)").isSubset(of: characters)
? newChar : $0
}))
}
func replacingCharacters(in string:String, with newChar:Character) -> Self {
String(self.compactMap( {
CharacterSet(charactersIn: "\($0)").isSubset(of: CharacterSet(charactersIn:string))
? newChar : $0
}))
}
}
usage:
print("hello \n my name\t is Joe".removingCharacters(.whitespacesAndNewlines))
print("hello \n my name\t is Joe".removingCharacters(in: " \t\n"))
print("ban annan anann ana".replacingCharacters(.whitespacesAndNewlines, with: "_"))
print("ban-annan anann ana".replacingCharacters(in: " -", with: "_"))
Obviously for just spaces the .replacingOccurrences(of: " ", with: "") is better.
I have not done a performance comparison to the
let toArray = aString.components(separatedBy: characterSet)
let backToString = toArray.joined(separator: "+")
style done in Ramis's extension on this question:
https://stackoverflow.com/a/33120336/5946596
I'd be interested if someone does.
See also replacing emojis: https://stackoverflow.com/a/63416058/5946596

Resources