I'm trying to conditionally load files in vim/neovim with Vimscript, except where the filename is prefixed with an underscore. It's not working 100% yet, instead all the files are still loading:
for filename in split(globpath('~/.config/nvim/plugins', '*.vim'), '\n')
if filename !~ "^_"
exe 'source' filename
endif
endfor
Sort of works with file !~ "_", but that matches with the underscore anywhere in the string. I need ignore only filenames that start with _.
I made a trivial mistake here, I assumed the filename contains something like _filename.vim, but instead the string contains the path as well, /Users/someuser/blah/_filename.vim.
I fixed it by splitting the path, and checking only the last element in the array:
for filename in split(globpath('~/.config/nvim/plugins', '*.vim'), '\n')
if split(filename, "/")[-1] !~ "^_"
exe 'source' filename
endif
endfor
Related
I have a string that is like so:
"string content here
"
because it is too long to fit on the screen in one line
The string is the name of a file i would like to read, but i always get an error message that the file name wasn't found because it includes the new line character in the string when this obviously isn't in the file name. I cannot rename the file and I have tried the strip function to remove it, but this doesn't work. How can I remove the enter character from my string so I can load my file?
You can use the function strip to remove any trailing whitespace from a string.
>> text = "hello" + newline; %Create test string.
>> disp(text)
hello
>> text_stripped = strip(text);
>> disp(text_stripped)
hello
>>
In the above ">>" has been included to better present the removal of the whitespace in the string.
Consider replacing the newline character with nothing using strrep. Link
As an example:
s = sprintf('abc\ndef') % Create a string s with a newline character in the middle
s = strrep(s, newline, '') % Replace newline with nothing
Alternatively, you could use regular expressions if there are several characters causing you issues.
Alternatively, you could use strip if you know the newline always occurs at the beginning or end.
my $book = Spreadsheet::Read->new();
my $book = ReadData
('D:\Profiles\jmahroof\Desktop\Scheduled_Build_Overview.xls');
my $cell = "CD7";
my $n = "1";
my $send = $book->[$n]{$cell};
The above code gets data from a spreadsheet, then prints the content of a cell that I know has text in. It has text of exactly the following format: text(text)
I need to replace the open bracket with a empty space and I need to remove the close bracket. I have tried the below code to substitute the open bracket for an empty space however it does not seem to work.
$send =~ s/(/ /g;
print $send;
The bracket is seen as part of the code, just escape it.
$send =~ s/\(/ /;
print $send;
Since you only replace one char with another, you don't want a substitution, but a transliteration. That's the tr/// function in Perl. Since the pattern is just a list of chars, and not an actual regex, you don't need to escape the open parenthesis (. There is also no /g flag. It just substitutes all occurrences.
$send =~ tr/(/ /;
The main difference to a regular expression substitution is that the transliterations get compiled at compile time, not at run time. That makes the tr/// faster than a s///, especially in a loop.
See the full documentation in perlop.
I need to find all pairs of strings that have the same pattern.
For example:
another string, that is not interesting
la-di-da-di __pattern__ -di-la-di-la
la-di-da-da-di-la __pattern__ -la-da-li-la
and yet another usual string
So I want to delete strings with __pattern__ inside.
I don't know how to do it just with builtin commands and now I have the function, that doesn't work properly:
function! DelDup(pattern)
echom a:pattern
redir => l:count
execute "normal! :%s/a:pattern//n\<cr>"
redir END
echo l:count
endfunction
Here I try to run ":%s/a:pattern//n" to find the count of occurrences of pattern in the text.
And at the same time I try to put it into the variable "l:count".
Then I tried to echo the count I got, but nothing happens when I try to do it.
So the last my problem in function writing is that I can't write the command execution result to variable.
If you have another solution -- please describe it to me.
Update:
Excuse me for bad description. I want to delete only strings, that has pattern-twins in text.
I'm not sure if I understand your question correctly, but I'm assuming you want to remove all lines where there are at least 2 matches. If that's the case you can use the following command:
:g/\(__pattern__.*\)\{2,}/d
How this works is that it deletes all the lines where there is a match (:g/../d).
The pattern is made up of a group (\(..\)) which needs to be matched at least 2 times (\{2,}). And the pattern has a .* at the end so it matches everything between the matches of the pattern.
There are many ways to count occurrences of a pattern, and I'm quite sure there exist a Q/A on the subject. Let's do it yet another way and chain with the next step. (Yes this is completely obfuscated, but it permits to obtain programmatically the information without the need to parse the localized result of :substitute after redirection.)
" declare a list that contain all matches
let matches = []
" replace each occurrence of the "pattern" with:
" the result of the expression "\=" that can be
" interpreted as the last ([-1]) element of the
" list "matches" returned by the function (add)
" that adds the current match (submatch(0)) to the
" list
:%s/thepattern/\=add(matches, submatch(0))[-1]/gn
" The big caveat of this command is that it modifies
" the current buffer.
" We need something like the following to leave it unmodified:
:g/thepattern/call substitute(getline('.'), 'thepattern', '\=add(counter, submatch(0))[-1]', 'g')
" Note however that this flavour won't work with multi-lines patterns
" Now you can test the number of matches or do anything fancy with it
if len(matches) > 1
" replaces matches with nothing
:%s/thepattern//g
endif
Only if you want to define this as a function you'll need to play with:
exe 'normal :%s/'.escape(a:pattern, '/\').'/replacement..../flags....'
I've looked everywhere and I'm out of luck.
I am trying to count the files in my current directory and all sub directories so that when I run the shell script count_files.sh it will produce a similar output to:
$
2 sh
4 html
1 css
2 noexts
(EDIT the above output should have each count and extension on a newline)
$
where noexts are either files without any period as an extension (ex: fileName ) or files with a period but no extension (ex: fileName. ).
this pipeline:
find * | awf -F . '{print $NF}'
gives me a comprehensive list of all the files, and I've figured out how to remove files without any period (ex: fileName ) using sed '/\//d'
MY ISSUE is that I cannot remove the files from the output of the above pipeline that are separated by a period but have NULL after the period (ex: fileName. ), as it is separated by the delimiter '.'
How can I use sed like above to remove a null character from a pipe input?
I understand this could be a quick fix, but I've been googling like a madman with no luck. Thanks in advance.
Chip
To filter filenames that end with ., since filenames are the whole input line in find's output, you could use
sed '/\.$/d'
Where \. matches a literal dot and $ matches the end of the line.
However, I think I'd do the whole thing in awk. Since sorting does not appear to be necessary:
EDIT: Found a nicer way to do it with awk and find's -printf action.
find . -type f -printf '%f\n' | awk -F. '!/\./ || $NF == "" { ++count["noext"]; next } { ++count[$NF] } END { for(k in count) { print k " " count[k] } }'
Here we pass -printf '%f\n' to find to make it print only the file name without the preceding directory, which makes it much easier to work with for our purposes -- this way there's no need to worry about periods in directory names (such as /etc/somethingorother.d). The field separator is '.', the awk code is
!/\./ || $NF == "" { # if the line (the filename) does not contain
# a period or there's nothing after the last .
++count["noext"] # increment the "noext" counter
# note that this will be collated with files that
# have ".noext" as filename extension. see below.
next # go to the next line
}
{ # in all other lines
++count[$NF] # increment the counter for the file extension
}
END { # in the very end:
for(k in count) { # print the counters.
print count[k] " " k
}
}
Note that this way, if there is a file "foo.noext", it will be counted among the files without a filename extension. If this is a worry, use a special counter for files without an extension -- either apart from the array or with a key that cannot be a filename extension (such as one that includes a . or the empty string).
In vimscript, how can I iterate through all the matches of a regex in the current file and then run a shell command for each result?
I think this is a start but I cant figure out how to feed it the whole file and get each match.
while search(ENTIRE_FILE, ".*{{\zs.*\ze}}", 'nw') > 0
system(do something with THIS_MATCH)
endwhile
Assuming that we have a file with the content:
123 a shouldmatch
456 b shouldmatch
111 c notmatch
And we like to match
123 a shouldmatch
456 b shouldmatch
with the regex
.*shouldmatch
If you only have one match per line you can use readfile() and afterwards loop through the lines and check each line with matchstr(). [1]
function! Test001()
let file = readfile(expand("%:p")) " read current file
for line in file
let match = matchstr(line, '.*shouldmatch') " regex match
if(!empty(match))
echo match
" your command with match
endif
endfor
endfunction
You can put this function in your ~/.vimrc and call it with call Test001().
[1] http://vimdoc.sourceforge.net/htmldoc/eval.html#matchstr%28%29
You could use subtitute() instead. For instance...
call substitute(readfile(expand('%')), '.*{{\zs.*\ze}}',
\ '\=system("!dosomething ".submatch(1))', 'g')