Programmatically return a list of all functions - matlab

I want to programmatically get a list of available functions in the current MATLAB namespace, as well the available functions in a package. How can this be done?

We can use package metadata for this:
pkgs = meta.package.getAllPackages();
% Or if the specific package name is known:
mp = meta.package.fromName('matlab')
The cell array returned in the 1st case, pkgs, contains objects such as this:
package with properties:
Name: 'Sldv'
Description: ''
DetailedDescription: ''
ClassList: [29×1 meta.class]
FunctionList: [8×1 meta.method]
PackageList: [9×1 meta.package]
ContainingPackage: [0×0 meta.package]
So all that's left to do is iterate through the packages and sub-packages tand collect their FunctionList entries.
I'm not sure how to get the functions that belong to the "default" namespace, other than by parsing the function list doc page, for example using the Python API and BeautifulSoup:
fl = arrayfun(#(x)string(x{1}.string.char), py.bs4.BeautifulSoup( ...
fileread(fullfile(docroot,'matlab','functionlist-alpha.html')), ...
'html.parser').find_all("code")).';

Further to Dev-iL's answer, parsing the function list documentation web page is pretty easy because of the useful "function" class that the web devs have (currently) used to tag each function name with! Each function looks like this within the HTML:
<code class="function">accumarray</code>
So we can use urlread to grab the source, and regular expressions to strip out the inner text of each "function" class item:
str = urlread('https://mathworks.com/help/matlab/functionlist-alpha.html');
funcs = regexp( str, '(?<="function">)[0-9A-Za-z.]+', 'match' );
Note: "alpha" in the URL is for "alphabetical" rather than to denote early testing!
funcs is a cell array with all the function names on that page.
The page used above is for the most recent MATLAB version. For a specific version, use the historic documentation pages structured like so:
https://mathworks.com/help/releases/R2017b/matlab/functionlist.html

Related

VSCode Extension: Get outline of function for custom outliner

I'm trying to create a custom outliner for VSCode (currently only for python), but I don't find measures to get the information I needed.
I like to get information in this manner this:
Array:
[0]
label: "foo"
type: "Function"
parameters: [...]
Range: [...]
innerDefinitions: [0]
[1]
label: "myclass"
type: "Class"
base_class: ""
Range: [...]
innerDefinitions:
[0]:
[...]
[1]:
[...]
Currently I try to get outline information via vscode.commands.executeCommand( 'vscode.XXX'
What I've tried:
Here is what commands I've tried and what result I received.
vscode.executeImplementationProvider
half usable: range of functionname. Other information is missing
vscode.executeHoverProvider
half usable: string of function head (including def keyword)
vscode.executeDefinitionProvider
half usable: range of complete function. Individual information must be "parsed out"
vscode.executeTypeDefinitionProvider
Never provided any result
vscode.executeDeclarationProvider
Never provided any result
vscode.executeDocumentSymbolProvider
Goes in a good direction. However
(1) Does only work on the whole document (not single function)
(2) Does only return first-level entities (i.e. class methods are not included in result)
Is there any API call I've overseen?
I wonder how the built-in outliner works, as it contains all-level information.
You need to use vscode.commands.executeCommand<vscode.Location[]>("vscode.executeDocumentSymbolProvider", uri, position)
This will give you the full outline of one file. There is no way to receive a partial outline.
Note: innerDefinitions are called children here.
Regarding the detail of the outline:
How detailed (and correct) an outline is going to be, depends on the implementation of the provider. Also, provider's information is no necessarily consistent among languages. This is very important to keep in mind!
At the moment (2021/03), the standard SymbolProvider for...
... Python will have a child for each parameter and local variable of a function. They will not be distinguishable
... C++ will contain no children for parameters. But it will have the parameter types in its name. (e.g. name of void foo(string p) will be foo(string): void.
As you can see, both act differently with their own quirks.
You could create and register a DocumentSymbolProvider yourself, that would return a level of detail you need (see VSCode Providers)
Also see: https://stackoverflow.com/a/66486297/6702598

Inspect unprocessed collection objects in Eclipse

Eclipse has a feature that represents some types of Java collections (most notably ArrayList and ArrayDeque) in a simplified way in the inspect tool (also in the Variables and Expression views):
d = ArrayDeque<E> (id=33)
[0] = "somevalue" (id=57)
[1] = "someothervalue (id=59)
In most other classes, instead of the [0] and [1] entries, the inspect tool will show fields of the object, including their names. I'm interested in looking at the internals of a live ArrayDeque.
Is there a way to make the inspect tool show the real fields of the ArrayDeque, so that the output looks more like this?:
"d" = ArrayDeque<E> (id=33)
elements = Object[] (id=34)
head = 2
tail = 4
I'm using Eclipse 2018-12 (4.10.0).
EDIT: I have already tried using a subclass of ArrayDeque, but it doesn't help.
I have found a way:
In Preferences > Java > Debug > Logical Structures, there is a definiton that performs toArray() on any java.util.Collection before the inspect tool shows the result.
While it is not possible to remove that default entry, you can add an entry for a more specific type:
Qualified type name: java.util.ArrayDeque
Description: Shows ArrayDeque internals
Code: this

Exporting the output of MATLAB's methodsview

MATLAB's methodsview tool is handy when exploring the API provided by external classes (Java, COM, etc.). Below is an example of how this function works:
myApp = actxserver('Excel.Application');
methodsview(myApp)
I want to keep the information in this window for future reference, by exporting it to a table, a cell array of strings, a .csv or another similar format, preferably without using external tools.
Some things I tried:
This window allows selecting one line at a time and doing "Ctrl+c Ctrl+v" on it, which results in a tab-separated text that looks like this:
Variant GetCustomListContents (handle, int32)
Such a strategy can work when there are only several methods, but not viable for (the usually-encountered) long lists.
I could not find a way to access the table data via the figure handle (w/o using external tools like findjobj or uiinspect), as findall(0,'Type','Figure') "do not see" the methodsview window/figure at all.
My MATLAB version is R2015a.
Fortunately, methodsview.m file is accessible and allows to get some insight on how the function works. Inside is the following comment:
%// Internal use only: option is optional and if present and equal to
%// 'noUI' this function returns methods information without displaying
%// the table. `
After some trial and error, I saw that the following works:
[titles,data] = methodsview(myApp,'noui');
... and returns two arrays of type java.lang.String[][].
From there I found a couple of ways to present the data in a meaningful way:
Table:
dataTable = cell2table(cell(data));
dataTable.Properties.VariableNames = matlab.lang.makeValidName(cell(titles));
Cell array:
dataCell = [cell(titles).'; cell(data)];
Important note: In the table case, the "Return Type" column title gets renamed to ReturnType, since table titles have to be valid MATLAB identifiers, as mentioned in the docs.

get/edit code of function with Ipython

when you enter function??, besides the info you get the source code of the function if there is available.
Is there a way of?:
1) get the code as str object
2) edit in place similar to %load
Assuming that you have the module and function names as "module" and "function" string variables, then
from inspect import getmembers, isfunction, getsource
internal_module = __import__(module)
internal_functions = dict(getmembers(internal_module, isfunction))
source_code = getsource(internal_functions[function])
will give you a dictionary (internal_functions) containing all functions in the module and a string (source_code) containing the source of that specific function.
You would then have to manipulate the string in order to edit the function, I think.

How do I dynamically build a search block in sunspot?

I am converting a Rails app from using acts_as_solr to sunspot.
The app uses the field search capability in solr that was exposed in acts_as_solr. You could give it a query string like this:
title:"The thing to search"
and it would search for that string in the title field.
In converting to sunspot I am parsing out field specific portions of the query string and I need to dynamically generate the search block. Something like this:
Sunspot.search(table_clazz) do
keywords(first_string, :fields => :title)
keywords(second_string, :fields => :description)
...
paginate(:page => page, :per_page => per_page)
end
This is complicated by also needing to do duration (seconds, integer) ranges and negation if the query requires it.
On the current system users can search for something in the title, excluding records with something else in another field and scoping by duration.
In a nutshell, how do I generate these blocks dynamically?
I recently did this kind of thing using instance_eval to evaluate procs (created elsewhere) in the context of the Sunspot search block.
The advantage is that these procs can be created anywhere in your application yet you can write them with the same syntax as if you were inside a sunspot search block.
Here's a quick example to get you started for your particular case:
def build_sunspot_query(conditions)
condition_procs = conditions.map{|c| build_condition c}
Sunspot.search(table_clazz) do
condition_procs.each{|c| instance_eval &c}
paginate(:page => page, :per_page => per_page)
end
end
def build_condition(condition)
Proc.new do
# write this code as if it was inside the sunspot search block
keywords condition['words'], :fields => condition[:field].to_sym
end
end
conditions = [{words: "tasty pizza", field: "title"},
{words: "cheap", field: "description"}]
build_sunspot_query conditions
By the way, if you need to, you can even instance_eval a proc inside of another proc (in my case I composed arbitrarily-nested 'and'/'or' conditions).
Sunspot provides a method called Sunspot.new_search which lets you build the search conditions incrementally and execute it on demand.
An example provided by the Sunspot's source code:
search = Sunspot.new_search do
with(:blog_id, 1)
end
search.build do
keywords('some keywords')
end
search.build do
order_by(:published_at, :desc)
end
search.execute
# This is equivalent to:
Sunspot.search do
with(:blog_id, 1)
keywords('some keywords')
order_by(:published_at, :desc)
end
With this flexibility, you should be able to build your query dynamically. Also, you can extract common conditions to a method, like so:
def blog_facets
lambda { |s|
s.facet(:published_year)
s.facet(:author)
}
end
search = Sunspot.new_search(Blog)
search.build(&blog_facets)
search.execute
I have solved this myself. The solution I used was to compiled the required scopes as strings, concatenate them, and then eval them inside the search block.
This required a separate query builder library that interrogates the solr indexes to ensure that a scope is not created for a non existent index field.
The code is very specific to my project, and too long to post in full, but this is what I do:
1. Split the search terms
this gives me an array of the terms or terms plus fields:
['field:term', 'non field terms']
2. This is passed to the query builder.
The builder converts the array to scopes, based on what indexes are available. This method is an example that takes the model class, field and value and returns the scope if the field is indexed.
def convert_text_query_to_search_scope(model_clazz, field, value)
if field_is_indexed?(model_clazz, field)
escaped_value = value.gsub(/'/, "\\\\'")
"keywords('#{escaped_value}', :fields => [:#{field}])"
else
""
end
end
3. Join all the scopes
The generated scopes are joined join("\n") and that is evaled.
This approach allows the user to selected the models they want to search, and optionally to do field specific searching. The system will then only search the models with any specified fields (or common fields), ignoring the rest.
The method to check if the field is indexed is:
# based on http://blog.locomotivellc.com/post/6321969631/sunspot-introspection
def field_is_indexed?(model_clazz, field)
# first part returns an array of all indexed fields - text and other types - plus ':class'
Sunspot::Setup.for(model_clazz).all_field_factories.map(&:name).include?(field.to_sym)
end
And if anyone needs it, a check for sortability:
def field_is_sortable?(classes_to_check, field)
if field.present?
classes_to_check.each do |table_clazz|
return false if ! Sunspot::Setup.for(table_clazz).field_factories.map(&:name).include?(field.to_sym)
end
return true
end
false
end