Say I have two Octave function files in the same load path: file1.m and file2.m.
file1:
function [variable] = file1()
variable = 1;
endfunction
file2:
function file2()
variable2 = variable*2;
endfunction
How can I make it so that I can use variable in file2?
I have tried many things, such as:
1.
function [variable] = file1()
global variable = 1;
endfunction
function file2()
global variable;
variable2 = variable*2;
endfunction
2.
Calling file1() before or within file2() in file2.m
file1();
function file2()
global variable;
variable2 = variable*2;
endfunction
3.
Using variable as a parameter when calling file2()
function file2(variable)
variable2 = variable*2;
endfunction
with no success. Any help would be greatly appreciated!
The easiest solution would be to call file1 in file2:
function file2()
variable = file1();
variable2 = variable*2; % do you want to return variable2 as the output of file2?
endfunction
EDIT
If your function returns more than one variable, the process is exactly the same, i.e.:
function [x,y,z] = file1()
x = 1;
y = 2;
z = 3;
endfunction
function file2()
[x,y,z] = file1();
variable2 = 2*(x+y+z); % do you want to return variable2 as the output of file2?
endfunction
Related
I'm interested to know if there is any way to mock Vimscript functions for testing. I know there are frameworks like vader.vim, but nothing is said about mocking.
You can redefine any existing user function with :function!. So, for example,
function! Mock(name, Hook) abort
" save a reference to original function
let l:Orig = funcref(a:name)
" overwrite function
let l:text =<< trim EOF
function! %s(...) abort closure
let l:oldresult = call(l:Orig, a:000)
let l:newresult = call(a:Hook, [l:Orig, l:oldresult] + a:000)
return l:newresult isnot v:null ? l:newresult : l:oldresult
endfunction
EOF
execute printf(join(l:text, "\n"), a:name)
endfunction
" silly test
function! Test(p1, p2) abort
return a:p1 * a:p2
endfunction
function! MyHook(Orig, result, ...) abort
echo 'Calling' get(a:Orig, 'name') 'with params' a:000 'produced' a:result
" remember: default return value is zero, not v:null
return a:result * 2
endfunction
call Mock('Test', funcref('MyHook'))
echo Test(6, 7)
" Calling Test with params [6, 7] produced 42
" 84
filelist.txt contains a list of files:
/path/file1.json
/path/file2.json
/path/fileN.json
Is there a (simple) MATLAB command that will accept filelist.txt and read each file as a string and store each string into a cell array?
Just use readtable, asking it to read each line in full.
>> tbl = readtable('filelist.txt','ReadVariableNames',false,'Delimiter','\n');
>> tbl.Properties.VariableNames = {'filenames'}
tbl =
3×1 table
filenames
__________________
'/path/file1.json'
'/path/file2.json'
'/path/fileN.json'
Then access the elements in a loop
for idx = 1:height(tbl)
this_filename = tbl.filenames{idx};
end
This problem is a bit to specific for a standard function. However, it is easily doable with the combination of two functions:
First, you have to open the file:
fid = fopen('filelist.txt');
Next you can read line by line with:
line_ex = fgetl(fid)
This function includes a counter. If you call the function the next time, it will read the second line and so on. You find more information here.
The whole code might look like this:
% Open file
fid = fopen('testabc');
numberOfLines = 3;
% Preallocate cell array
line = cell(numberOfLines, 1);
% Read one line after the other and save it in a cell array
for i = 1:numberOfLines
line{i} = fgetl(fid);
end
% Close file
fclose(fid);
For this replace the for loop with a while loop:
i=0;
while ~feof(fid)
i=i+1
line{1} = fgetl(fid)
end
Alternative to while loop: Retrieve the number of lines and use in Caduceus' for-loop:
% Open file
fid = fopen('testabc');
numberOfLines = numlinestextfile('testable'); % function defined below
% Preallocate cell array
line = cell(numberOfLines, 1);
% Read one line after the other and save it in a cell array
for i = 1:numberOfLines
line{i} = fgetl(fid);
end
% Close file
fclose(fid);
Custom function:
function [lineCount] = numlinestextfile(filename)
%numlinestextfile: returns line-count of filename
% Detailed explanation goes here
if (~ispc) % Tested on OSX
evalstring = ['wc -l ', filename];
% [status, cmdout]= system('wc -l filenameOfInterest.txt');
[status, cmdout]= system(evalstring);
if(status~=1)
scanCell = textscan(cmdout,'%u %s');
lineCount = scanCell{1};
else
fprintf(1,'Failed to find line count of %s\n',filenameOfInterest.txt);
lineCount = -1;
end
else
if (~ispc) % For Windows-based systems
[status, cmdout] = system(['find /c /v "" ', filename]);
if(status~=1)
scanCell = textscan(cmdout,'%s %s %u');
lineCount = scanCell{3};
disp(['Found ', num2str(lineCount), ' lines in the file']);
else
disp('Unable to determine number of lines in the file');
end
end
end
I have a debug file which looks like this:
==>func1:
.....
..
==>func2:
......
...
<==func2
..
<==func1
==>func3:
......
...
<==func3
Basically, I would like to be able to fold each one of the functions to eventually see something like this:
+-- x lines: ==> func1:
+-- x lines: ==> func3:
but still be able to expand func1 and see func2 folded:
==>func1:
.....
..
+-- x lines: ==> func2:
..
<==func1
is there any way to do so? thanks.
The unmatched markers need extra handle, here's an expr solution( see :h fold-expr):
setlocal foldmethod=expr
setlocal foldexpr=GetFoldlevel(v:lnum)
function GetFoldlevel(lnum)
let line = getline(a:lnum)
let ret = '='
if line[0:2] == '==>'
let name = matchstr(line, '^==>\zs\w*')
let has_match = HasMarkerMatch(a:lnum, name)
if has_match
let ret = 'a1'
endif
elseif line[0:2] == '<=='
let ret ='s1'
endif
return ret
endfunction
function HasMarkerMatch(lnum, name)
let endline = line('$')
let current = a:lnum + 1
let has_match = 0
while current <= endline
let line = getline(current)
if line =~ '^<=='.a:name
let has_match = 1
break
endif
let current += 1
endwhile
return has_match
endfunction
I have a list of symbols, and want to use the Vim8 timers API to loop over the symbols list every 80ms and return that symbol. I worked out something like this:
let s:frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
let s:numTestimonials = len(s:frames)
let s:start = 0
function! PrintValues()
return s:frames[s:start]
let s:start = (s:start) + 1 % s:numTestimonials
endfunction
let timer = timer_start(80, 'PrintValues', {'repeat': -1})
But as soon as it reaches the last symbol in the list, it will throw an error, E684: list index out of range: 10. Any ideas how to accomplish what I want?
You need to have the 1 inside parentheses before the mod
let s:start = (s:start + 1) % s:numTestimonials
1 % s:numTestimonials is always 1 and is evaluated before adding s:start
Some little changes made to your code (Tested on vim 7.4):
let timer = timer_start(500, 'PrintValues', {'repeat': -1})
let s:frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
let s:numTestimonials = len(s:frames)
let s:start = 0
function! PrintValues(timer)
execute "normal! i".s:frames[s:start]
let s:start = (s:start + 1) % s:numTestimonials
endfunction
I am using an adaptation of the VIM folding settings published here and here. Now, notice the program below:
When folded on my VIM, it produces the following result:
I don't really like that look, I'd prefer the following:
Which I got by rewriting the code:
But leaving the code like that is horrible. Is it possible to update the VimScript so I get the folding I want, without having to leave the JavaScript code like that?
Here is my exact setting:
setlocal foldmethod=expr
setlocal foldexpr=GetPotionFold(v:lnum)
setlocal foldminlines=0
function! s:NextNonBlankLine(lnum)
let numlines = line('$')
let current = a:lnum + 1
while current <= numlines
if getline(current) =~? '\v\S'
return current
endif
let current += 1
endwhile
return -2
endfunction
function! s:IndentLevel(lnum)
return indent(a:lnum) / &shiftwidth
endfunction
function! GetPotionFold(lnum)
if getline(a:lnum) =~? '\v^\s*$'
return '-1'
endif
let this_indent = <SID>IndentLevel(a:lnum)
let next_indent = <SID>IndentLevel(<SID>NextNonBlankLine(a:lnum))
if next_indent == this_indent
return this_indent
elseif next_indent < this_indent
return this_indent
elseif next_indent > this_indent
return '>' . next_indent
endif
endfunction
function! NeatFoldText()
let line = getline(v:foldstart)
let lines_count = v:foldend - v:foldstart + 1
let lines_count_text = '| ' . printf("%10s", lines_count . ' lines') . ' |'
let foldchar = ' '
let foldtextstart = strpart(line, 0, (winwidth(0)*2)/3)
let foldtextend = lines_count_text . repeat(foldchar, 6)
let foldtextlength = strlen(substitute(foldtextstart . foldtextend, '.', 'x', 'g')) + &foldcolumn
return foldtextstart . repeat(foldchar, winwidth(0)-foldtextlength) . foldtextend
endfunction
set foldtext=NeatFoldText()
hi Folded ctermbg=255 ctermfg=21
hi FoldColumn ctermbg=white ctermfg=darkred
And here is the sample code:
function foo(x){
var y = x*x;
var z = y+y;
return z;
};
function bar(x){
var y = x*x;
var z = y+y;
return z;
};
function foobar(x){
var y = x*x;
var z = y+y;
return z;
};
function barfoo(x){
var y = x*x;
var z = y+y;
return z;
};
set foldmethod=marker
set foldmarker={,}
Should give you what you want.
You are using a fold expression that is (as far as I can see from a glance) designed for indent folding (used for HAML, Python, Haskell and other indent-syntax languages).
For C, you should just be using :set foldmethod=syntax.