How to search for a string inside a class in Squeak smalltalk ? How about inside a package? - smalltalk

I searched, and searched.
I went to IRC
Hope the question is not silly. If it was, the right string to search at google would still be much appreciated

Answering such questions with the refactoring engine is quite easy. The following code finds all occurrences of / in the system:
allCodeWithSlash := RBBrowserEnvironment new matches: '/'
From there you can further scope the search, e.g. to inside a class:
allCodeWithSlashInClass := allCodeWithSlash forClasses: (Array with: DosFileDirectory)
Or inside a package:
allCodeWithSlashInPackage := allCodeWithSlash forPackageNames: (Array with: 'Files')
If you have an UI loaded, you can open a browser on any of these search results:
allCodeWithSlashInPackage open
If you use OmniBrowser, you can also build and navigate these scopes without typing any code through the Refactoring scope menu.

Here's an example that shows you all methods in DosFileDirectory containing the string '\'.
aString := '\\'.
class := DosFileDirectory.
methodsContainingString := class methodDictionary values select: [:method |
method hasLiteralSuchThat: [:lit |
(lit isString and: [lit isSymbol not]) and:
[lit = aString]]].
messageList := methodsContainingString collect: [ :e | MethodReference new setStandardClass: class methodSymbol: e selector ].
SystemNavigation new
browseMessageList: messageList
name: 'methods containing string'.
To search a whole package, wrap the search part in:
package := PackageOrganizer default packageNamed: packageName ifAbsent: [ self error: 'package doesn't exist' ].
package classesAndMetaClasses do: [ :class | ... ]

Related

Go template merging dictionary with a possibly empty source dictionary

In a go template I'm merging labels from project level and application level with
{{ range $k, $v := (merge $project.labels $app.labels) }}
# Do something with $k and $v.
{{end}}
Both $project.labels and $app.labels are dictionaries generated from a yaml file.
Now I want to make app.labels as an optional field, this can be done with some extra with statement but I wonder if there is an elegant way to do this.
Currently if $app.label is not defined in the yaml file I'll get:
wrong type for value; expected map[string]interface {}; got interface {}
Figured it out by adding empty dict as a default:
{{ range $k, $v := (merge $project.labels ($app.labels | default dict)) }}

Why is a DOORS Module sometimes null when trying to edit the Module via DXL?

I'm new to DXL programming language in IBM DOORS. However, I think I have managed to do many interesting things: create Modules, create Objects, create Links, delete Objects etc.
However, I have a very specific problem regarding "null" Modules. I've just written null between "" because the modules exist and they are referenced with a correct name.
When doing this:
Module m1 = edit("1. MY_MODULE", false)
save(m1)
close(m1)
An error like this appears:
enter image description here
You could not understand what does that mean as it is spanish. Basically states this: "Module null parameter in the first position of the argument." That means that the "m1" is null, as the parameter for save() method is null.
The point is that it is an error which appears only sometimes. It seems that the Module is null as it has been previously opened and DOORS does not close properly.
Is there any way, any method...whatever to avoid this error?
I assume that the script cannot find the module when another folder is active.
Try
Module m1 = edit ("/myproject/myfolder/mysubfolder/1. MY_MODULE", false)
There might be many reasons that the module can't be opened in edit mode. For example: User do not have write access OR Module is being used by other user, etc.
However, you can get around the error with the below code snippet:
Module m = edit('My_module', false)
if(!null m) {
//execute program
...
}
else {
//do something
}
I hope this helps.
How does your script work? do you open the same module again and again and sometimes get the error or do you open lots of modules and for some of them it works and for others it doesn't? In the latter case, perhaps you misspelled the path. You could add some sanity checks like
string fullPathToMod = "/myproject/myfolder.."
Item i = item fullPathToMod;
if null i then error "there is no item called " fullPathToMod
if "Module" != type i then error "there is an item, but it's not a module, it's a " type i
This is how the Code is structured:
void checkModule(string folderPath, string mName, Skip list, int listSize, int listLastIndex, string headers[], string heading[], string headerKey, bool uniqueKey, string combinedKey[]){
if (module mName){
Folder f = folder(folderPath)
current = f
Module m = edit(folderPath""mName, false)
current = m
Object o = first(m) // error sometimes: Se ha pasado un parametro Module null en una posición de argumento 1
if (o == null){
loadModule(m, list, listSize, listLastIndex, headers, heading)
} else {
updateModule(m, mName, list, listSize, listLastIndex, heading, headerKey, headers, uniqueKey, combinedKey)
save(m)
close(m)
}
if (lastError() != ""){
print "Error: " lastError() "\n"
}
} else {
print "No module " mName ".\n"
}
}
Exactly it breaks in line:
current = m
But as said, only sometimes, not always.
BTW, I'm executing this script via Batch, via Java code. One curious thing is that if I close DOORS, and execute the script it does execute correctly. It is as if it needs to be closed in order to edit modules correctly.
I pressume current can be used more than once with different types of Items. I guess it should not be wrong, but it breaks saying (more or less):
Null value passed to DXL commmand (current Module).
Obviously, it means that m is null, but I cannot see any reason for that.

How to test the passing of arguments in Golang?

package main
import (
"flag"
"fmt"
)
func main() {
passArguments()
}
func passArguments() string {
username := flag.String("user", "root", "Username for this server")
flag.Parse()
fmt.Printf("Your username is %q.", *username)
usernameToString := *username
return usernameToString
}
Passing an argument to the compiled code:
./args -user=bla
results in:
Your username is "bla"
the username that has been passed is displayed.
Aim: in order to prevent that the code needs to be build and run manually every time to test the code the aim is to write a test that is able to test the passing of arguments.
Attempt
Running the following test:
package main
import (
"os"
"testing"
)
func TestArgs(t *testing.T) {
expected := "bla"
os.Args = []string{"-user=bla"}
actual := passArguments()
if actual != expected {
t.Errorf("Test failed, expected: '%s', got: '%s'", expected, actual)
}
}
results in:
Your username is "root".Your username is "root".--- FAIL: TestArgs (0.00s)
args_test.go:15: Test failed, expected: 'bla', got: 'root'
FAIL
coverage: 87.5% of statements
FAIL tool 0.008s
Problem
It looks like that the os.Args = []string{"-user=bla is not able to pass this argument to the function as the outcome is root instead of bla
Per my comment, the very first value in os.Args is a (path to) executable itself, so os.Args = []string{"cmd", "-user=bla"} should fix your issue. You can take a look at flag test from the standard package where they're doing something similar.
Also, as os.Args is a "global variable", it might be a good idea to keep the state from before the test and restore it after. Similarly to the linked test:
oldArgs := os.Args
defer func() { os.Args = oldArgs }()
This might be useful where other tests are, for example, examining the real arguments passed when evoking go test.
This is old enough but still searched out, while it seems out dated.
Because Go 1.13 changed sth.
I find this change helpful, putting flag.*() in init() and flag.Parse() in Test*()
-args cannot take -<test-args>=<val> after it, but only <test-args>, otherwise the test-args will be taken as go test's command line parameter, instead of your Test*'s

How to create Fields

I am trying to create a script to add Fields on MarkLogic Database with Admin API. I have created following functions to perform this task:
declare function local:createField($config as element(configuration), $server-config as element(http-server))
{
let $dbid := xdmp:database(fn:data($server-config/database))
let $addField :=
let $fieldspec := admin:database-field("VideoTitle1", fn:false())
return admin:save-configuration(admin:database-add-field($config, $dbid, $fieldspec))
return "SUCCESS"
};
declare function local:createFieldPath($config as element(configuration), $server-config as element(http-server))
{
let $dbid := xdmp:database(fn:data($server-config/database))
let $addPath :=
let $fieldpath := admin:database-field-path("/Video/BasicInfo/Title", 1.0)
return admin:save-configuration(admin:database-add-field-paths($config, $dbid, "VideoTitle1", $fieldpath))
return "SUCCESS"
};
declare function local:createFieldRangeIndex($config as element(configuration), $server-config as element(http-server))
{
let $dbid := xdmp:database(fn:data($server-config/database))
let $addRange :=
let $rangespec := admin:database-range-field-index("string","VideoTitle1", "http://marklogic.com/collation/",fn:false() )
return admin:save-configuration(admin:database-add-range-field-index($config, $dbid, $rangespec))
return "SUCCESS"
};
But I am getting error:
[1.0-ml] ADMIN-BADPATHFIELDTYPE: (err:FOER0000) Incorrect field:
the field VideoTitle1 already has include-root.
In /MarkLogic/admin.xqy on line 5255
In database-check-path-field(<configuration/>, xs:unsignedLong("12095791717198876597"), "VideoTitle1")
$config := <configuration/>
$database-id := xs:unsignedLong("12095791717198876597")
$field-name := "VideoTitle1"
$field := <field xmlns="http://marklogic.com/xdmp/database" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><field-name>VideoTitle1</field-name><include-root>false</include...</field>
$field-path := ()
I am running complete script through QC and my MarkLogic version is "7.0-1". I have created Element Range Index, Attribute Range Index successfully by the script. But for this I am getting error.
Error description says that field has include-root. But, I am keeping it false()
admin:database-field("VideoTitle1", fn:false())
Is I am using wrong function or missed something?
Please help.
If you're trying to set up an entire database you're usually better off using the packaging API and services: https://developer.marklogic.com/learn/packaging-tutorial gives a tour of the configuration manager web UI, and then there is a guide, an XQuery API, and a REST API.
That said let's try to debug. It's difficult to debug your error message because the variable names and line numbers in the error message don't match up with your sample code. For example the stack trace has $database-id but your code has $dbid. A test case needs to be reproducible.
However I notice that you aren't calling the right function to construct your field configuration. If you want to use paths, say so up front using https://docs.marklogic.com/admin:database-path-field — not admin:database-path. The error message could use some work: it should be something more like "Incorrect field: the field VideoTitle1 is not a path field".
If you really want to stick with the admin API for this, I recommend changing your code so that you only call admin:save-configuration once. That's more efficient, and more robust in the face of any need to restart. One way to arrange this would be for each of your function calls to take a $config as element(configuration) param and return a new element(configuration) with the changes. Another method is to have a module variable $CONFIG as element(configuration) and mutate it with xdmp:set. Take a look at https://stackoverflow.com/a/12252515/908390 for examples of both techniques.
Here's a working version of your code:
import module namespace admin="http://marklogic.com/xdmp/admin"
at "/MarkLogic/admin.xqy";
declare function local:createField(
$config as element(configuration),
$server-config as element(http-server))
as element(configuration)
{
let $dbid := xdmp:database(fn:data($server-config/database))
let $fieldspec :=
admin:database-path-field(
"VideoTitle1",
admin:database-field-path("/Video/BasicInfo/Title", 1.0))
return admin:database-add-field($config, $dbid, $fieldspec)
};
declare function local:createFieldRangeIndex(
$config as element(configuration),
$server-config as element(http-server))
as element(configuration)
{
let $dbid := xdmp:database(fn:data($server-config/database))
let $rangespec :=
admin:database-range-field-index(
"string",
"VideoTitle1",
"http://marklogic.com/collation/",
fn:false())
return
admin:database-add-range-field-index(
$config, $dbid, $rangespec)
};
let $cfg := admin:get-configuration()
let $fubar := <http-server><database>test</database></http-server>
let $_ := xdmp:set($cfg, local:createField($cfg, $fubar))
let $_ := xdmp:set($cfg, local:createFieldRangeIndex($cfg, $fubar))
return admin:save-configuration($cfg)
Not a direct answer, but why reinvent a wheel that other have already invented. There are several solutions that can help deploy database settings and more. One of them is Roxy:
https://github.com/marklogic/roxy
Roxy provides a full framework for managing a MarkLogic project. You can find docs and tutorials on the wiki of the github project.
Another, less intrusive solution could be to configure your databases once, and then use the built-in Configuration Manager (http://host:8002/nav/) to export your database settings, and use the export to import the settings elsewhere.
HTH!

How to redefine FrontEndEventActions?

Good day,
This question comes from the question on aborting evaluation of the full sequence of inputs.
I think it is probably possible to achieve the desired behavior by redefining FrontEndEventActions for two events: "EvaluateCells" (or pressing Shift+Enter) and for pressing Alt+.. It should be something like:
SetOptions[$FrontEndSession,
FrontEndEventActions -> {"EvaluateCells" :> Last$PreRead,
{{"Alt", "."} :> AbortAllNextInputs}}]
or
SetOptions[$FrontEndSession,
FrontEndEventActions -> {{{"ShiftKey", "ReturnKeyDown"} :> Last$PreRead}
{{"Alt", "."} :> AbortAllNextInputs}}]
Where AbortAllNextInputs and Last$PreRead are defined as follows:
AbortAllNextInputs := AbortProtect[
$new$PreRead = True;
last$PreRead = ToString[Definition[$PreRead], InputForm];
ClearAll[$PreRead];
$PreRead := # &] /; ! TrueQ[$new$PreRead]
Last$PreRead :=
$PreRead := AbortProtect[
$new$PreRead = False;
ClearAll[$PreRead];
If[last$PreRead === "Null", #,
ToExpression[last$PreRead]; $PreRead##]
] &
But I can not get FrontEndEventActions working. Can anyone help me?
I believe you need to modify KeyEventTranslations.tr as referenced here and here.