Multiple functions in one fish file - fish

If I put a file called myfunc.fish in a directory called functions, and it includes a single function called myfunc, then fish will locate it if I type myfunc as a command.
What about if I want to have a bunch of short functions in one file? How do I "include" them?

source is how you include files.
Say you have a collection of functions thing1, thing2, etc. in a single file ~/mystuff/things.fish that you want to make available. Two good approaches are:
You can use the autoloading machinery: make the files functions/thing1.fish, functions/thing2.fish, etc. each with the same contents:
source ~/mystuff/things.fish
But a simpler approach is to just put that source line into your ~/.config/fish/config.fish file. Then it will be executed for each session.

Related

How can I maintain a collection of fish functions in a single file?

I want to define a number of functions for use from the command line and in scripts. One way would be to create one file for every function, and store them in the autoloading folder (e.g. ~/config/fish/functions/one.fish, ~/config/fish/functions/two.fish, ...)
But I don't want to maintain each function in its own file. Is there any way to define a collection of functions in a single file (such that they can be referenced from the command line and from multiple scripts)?
(Alternatively, fish is guided by strong design principles. If there is a documented fish-was-designed-this-way rationale to store one file per user-defined function, I'd like to see it.)
You can just have multiple functions in a single file, but you can only use autoloading for one of them.
The issue is this: If you have a function "foo" and a function "bar" in a file, how is fish supposed to know that, without reading the file first?
For autoloading, the file is named after the function (e.g. "bar" would be stored in "bar.fish"), so fish can figure out where it is.
So, you can do one of two things:
If one of the functions is always called first, then you can use that as the file name and store it in a function file. After you've used that function, fish knows about the rest (since it sourced the file).
If that isn't the case (or you don't want to rely on it), you can either source the file manually whenever you need it (or just once at startup) or store it in a configuration snippet in ~/.config/fish/conf.d/SOMETHING.fish (which fish will source automatically right before reading config.fish).
The former means that e.g. helper functions can be stored along with the main one. The latter is a teensy bit slower when you're loading the file without using the function, but unless you're using this excessively you're unlikely to even notice.

Can I make a module from a bunch of single-function scripts?

We've accumulated a bunch of scripts, each looks and feels like CmdLets, i.e. it has a set of declared params and then it immediately calls a Main function which does the work, calling private sub-functions within.
An example is Remove-ContentLine.ps1 which just spits out the contents of a file or piped input except for lines matching some pattern.
So they're like little "function-scripts".
Is there any way I can aggregate these scripts into a module while also keeping them exactly as they are in files?
Edit
If your hunch is that its easier to just copy paste and refactor them into a psm1 then just say ;)
You ask:
Is there any way I can aggregate these scripts into a module while
also keeping them exactly as they are in files?
But I am certain that is not what you really want. If so, then all of your code will immediately execute when you load the module! Rather, I think what you want is that each of your scripts should be contained within a function; that group of functions is then loaded when you import the module; and you can then execute any of your functions on demand.
The process is very straightforward, and I have written an extensive article on just how to do that (Further Down the Rabbit Hole: PowerShell Modules and Encapsulation) but I will summarize here:
(1) Edit each file to wrap the entire contents into a function and conclude with exporting the function. I would suggest name the function based on the file name. Thus, Remove-ContentLine.ps1 should now look like this:
function Remove-ContentLine()
{
# original content of Remove-ContentLine.ps1 here
}
Export-ModuleMember Remove-ContentLine
(2) Decide on a name for your module and create a directory of that name. Let's call it MyModule. Within the MyModule directory, create a subdirectory to place all your .ps1 files; let's call that ScriptCmdlets.
(3) Create a module file MyModule.psm1 within MyModule whose contents will be exactly this:
Resolve-Path $PSScriptRoot\ScriptCmdlets\*.ps1 |
? { -not ($_.ProviderPath.Contains(".Tests.")) } |
% { . $_.ProviderPath }
Yes, every module (.psm1) file I write contains that identical code!
(4) Create a module manifest MyModule.psd1 within MyModule using the New-ModuleManifest cmdlet.
Then to use your module, just use Import-Module. But I urge you to review my article for more details to gain a better understanding of the process.
I doubt you can if the scripts already executing something ("main"). If they just expose a function like Remove-ContentLine for the Remove-ContentLine.ps1 you could dot source all the scripts in a single script to aggregate them or use the ScriptsToProcess = #() section when working with a module manifest.
I think it would be best to refactor the functions from within each .ps1 into a proper module. It should be essentially just copy/pasting the scripts into a single .psm1 file and creating a .psd1 for it. Be sure to check for and properly handle anything that is set in the script or global scopes, and there are no naming conflicts between functions.
If you have Sapien PowerShell Studio, there is a 'New Module from Functions' option in the File menu which would help automate the bulk of this for you.

clearing many MATLAB functions in one single file

I have many small functions in matlab, is it possible to put them all in one file so my work will look clearer?
i tried writing a small script and then adding the functions but is didn't work
any idea on how do do it?
It is not possible to have several functions in one file, because the function is accessed via the file name. That is why a function has to have the same name as the file name.
If you only access the "small" functions inside one other function, then you can put the small functions in the file of the other function, but then they are only accessible to this one function. This is called local functions in MATLAB. For example you have a file test.m with:
function x=test(y,z)
x = add(y,z)
end
function a=add(b,c)
a = b + c;
end
You can then only use add inside test, but you can use test just as usual.
What I usually do is put functions in subfolders. This helps you keep your path clean without any limitations. This also allows you to capsule your software better. The only thing you have to do is add the folder to your path with
addpath('subfolder');
If you have a function file, you can add other functions in that file.
If you have a script, you cannot add functions to it.
Note that if you put a function in a file, you cannot access the functions directly from outside your 'main' function scope.
In general I would recommend the use of folders, or proper file names to organize your functions, not stacking many of them in one file.
Extra
If your functions are really small and trivial, you could write a script with the declaration of anonymous functions for easy reuse. However this is probably not what you want.

Executing a file or calling a function whose file is placed in another folder with MATLAB?

Tried Googling, but couldn't find anything.
I have a few files and folders in my current MATLAB folder.
One of those folders is called 'Map' and it has a 'map1.m' file which I want to call from my code in the current MATLAB folder.
In my code, I can't call it like this:
/Map/map1;
but I can do so like this:
cd Map;
map1;
cd ..;
Somehow the above method seems incorrect. Is there a more elegant way to do it?
You can run the file without adding the folder to your path manually, using the run command, which is specifically for such cases. From the documentation:
run is a convenience function that runs scripts that are not currently on the path.
You call your function/script as
run /Map/map1
If you want to run the function/script by merely entering its name and not with the full (or relative) path, then you should add the folder to your path.
As noted by #mutzmatron, you cannot use run to call functions with input/output arguments. So, unless if it's a script/function without input/output arguments, using run will not work and you'll have to add the folder to your path.
EDIT
Just as a matter of good coding practice, and to work in cases where your function has inputs/outputs, adding/removing the folder from your path is the correct way to go. So for your case,
addpath /Map
...
map1;
...
rmpath /Map
The important thing is that your function call is sandwiched between the addpath and rmpath commands. If you have functions of the same name in both folders, then you should sandwich it tighter i.e., a line before and a line after, so as to avoid conflicts.
Just add all those directories to the Matlab path with addpath like gnovice suggests. Then you'll be able to call the functions normally, and they'll be visible to which(), help(), depfun(), and the other Matlab meta-programming commands. You can put the addpath() calls in your startup.m file to have them automatically appear each time you start Matlab.
Changing the path with addpath/map1()/rmpath each time has some drawbacks.
It's a performance hit because you're adding path manipulation to each call.
Functions in different directories won't be able to see each other.
It'll be harder to write and debug functions because the path context in which they execute will change dynamically, and won't be the same as what you see when you're in the editor and the base workspace.
You need additional error handling code to make sure the path is properly restored if the called function errors out.
This won't work with the Matlab Compiler, if you want to deploy this code at some point.
And using run() or cd() yourself is ugly, because relative paths are going to have problems.
If you really want to separate the functions in the subdirectories so they can't "see" each other, you can make those directories namespaces by putting a "+" in front of their names, and then qualify the function calls with the namespace, like Map.map1().
Just to contribute to the path-altering debate...
One way to make it a bit "safer" is to write
% start of my code: create function handles
% to the functions I need:
try
cd Map
map1_func = #map1;
catch mexception
end
cd ..
This tries to preserve the current directory, and you get a handle to the function in a different directory.
Only thing is, this method won't work if map1 relies upon other functions in the Map directory.

How do I emulate 'include' behaviour in MATLAB?

In MATLAB I can define multiple functions in one file, with only the first defined function being visible external to that file. Alternatively, I can put each function in its own file and make them all globally visible through the path. I'm writing a menu driven application, where each menu item runs a different function. Currently, these are all in one big file, which is getting increasingly difficult to navigate. What I'd like to do is put groups of related functions into separate files.
I think I can do something like this by putting all the child functions into a separate directory and then adding the directory to the path in my parent function, but this feels a bit messy and inelegant.
Can anyone make a better suggestion?
Note: I'm most familiar with MATLAB 2006, but I'm in the process of upgrading to MATLAB 2009.
One suggestion, which would avoid having to modify the MATLAB path, is to use a private function directory. For example:
Let's say you have a function called test.m in the directory \MATLAB\temp\ (which is already on the MATLAB path). If there are local functions in test.m that you want to place in their own m-files, and you only want test.m to have access to them, you would first create a subdirectory in \MATLAB\temp\ called private. Then, put the individual local function m-files from test.m in this private subdirectory.
The private subdirectory doesn't need to be added to the MATLAB path (in fact, it shouldn't be added to the path for things to work properly). Only the file test.m and other m-files in the directory immediately above the private subdirectory have access to the functions it contains. Using private functions, you can effectively emulate the behavior of local functions (i.e. limited scope, function overloading, etc.) without having to put all the functions in the same m-file (which can get very big for some applications).
Maybe something like this,
function foobar
addpath C:\Include\ModuleX
%% Script file residing in ModuleX
some_func();
end
Of course, ModuleX will remain in your search path after exiting foobar. If you want to set it to the default path without restarting, then add this line:
path(pathdef)
See ADDPATH for more details.
You can use sub-folders that begin with "+" to separate functions into namespaces.
For example:
Place a function "bar" in the folder "+foo"
function bar()
print('hello world');
This function can be used as:
foo.bar() % prints hello world
More information can be found here:
What is the closest thing MATLAB has to namespaces?