the-carlisle-group / Acre-Desktop

A simple Dyalog APL IDE plugin that introduces "projects" and allows you to keep your source code in Unicode text files.
MIT License
11 stars 1 forks source link

API functions and -options. #184

Closed PhilLast closed 4 years ago

PhilLast commented 5 years ago

I now have acreAPI functions that mirror all acre commands. Still a few hiccups here and there but working in the main.

Decision to make is what to do about options.

So far the only one to rear its head was -when that I set at zero for acreAPI.changes and one for acreAPI.projects. With acreAPI.createproject, acreAPI.erase and acreAPI.openproject it gets more complicated. So for now I've used the optional left argument to supply values:

For -when, changes arg defaults to no date but 1 changes arg adds the date-time and with a string date-time '2019-07-05 13:30' changes arg restricts to changes made since.

Also for -when projects '' defaults to no date while 1 projects'' adds the date-time.

For -casecode, -keephistory and -variables createproject arg defaults to having them all Off while for -track and -dependencies openproject arg defaults to both On.

How to supply an alternative? Simplest would be a positional boolean:

e.g. 1 0 1 createproject arg meaning -casecode=On -keephistory=Off -variables=On [say] but then the order would have to be prescribed.

We could reproduce the option spec; hyphens, equal-signs an' all; and run it through Dan's parser but I was hoping for a bit less verbosity.

Any ideas?

PhilLast commented 5 years ago

Have committed and pushed anyway. The protocol for functions mirroring the commands that take -options is as follows:

PaulMansour commented 5 years ago

It appears that Link uses a namespace as an optional left argument. I prefer this to positional booleans. Another alternative I guess is a left argument of name/value pairs, also optional.

Finally, is it possible to pass everything in on the right, so the API looks similar to the UserCommand?

For example: ]UserCommand Arg1 Arg2 -op1 -op2=y

APICall Arg1 Arg2 ('op1' '') ('op2' 'y')

I guess a problem would be an optional 2nd argument. But could it be inferred from the structure? In other words, is it possible for a user command to have an argument that is not a simple string?

If this works it seems the best. There is high degree of similarity between user command and API call, no positional stuff, and no need to create and populate a namespace.

PaulMansour commented 5 years ago

I have re-read the user command user guide.

By definition, every argument is a simple text string. Therefore if we insist that modifiers are two item vectors, it should be no problem to mimic the syntax of a user command. In fact, we could even go as far as letting the user put the modifiers before, after, or inbetween arguments as user commands allow, though I'm not suggesting that.

Any reason this worn work or is not a good idea?

One advantage is that this leaves the left argument available for something else, perhaps a namespace reference for explicit context. When executing a user command, often the current namespace is an implicit argument. When calling the API equivalent, we don't want to change the current space just to get the command to run, so passing in a ref to space as the left arg is quite useful.

PhilLast commented 5 years ago

Re. the last point the API framework already takes care of this. If you )CS into a project space then the item(s) of the argument to a project or item method will be prefixed with the current space if they don't start with "#". After )cs #.myproject both of

      ⎕se.acreAPI.itemmethod 'this' 'and.that'
      ]acre.itemmethod this and.that

will result in the itemmethod method receiving the argument '#.myproject.this' '#.myproject.and.that'.

The structure of the argument to API fns is rather flexible. By the time an acre method gets its argument via the user command framework and acre's shared/project/item process or via the API framework it's a vector of strings - words and quoted strings - and the options are variables in a locally accessible space. The argument to ⎕se.acreAPI.openproject is a folder path as a simple string or nested singleton; or a two item nested vector of folder path and target space.

But certainly there is currently no expectation that any item will be itself a nested string so your first option is feasible.

PhilLast commented 5 years ago

... and although I hate typing I must admit it's probably better than the positional thing I described even though it is rediculously verbose. I suppose we could still use abbreviation.

Currently we can do

      ]createproject folder space -var=on ⍝ vs -variables=on

so I suppose we could do

      ⎕se.acreAPI.createproject 'folder' 'space' ('var' 'on') ⍝ vs ('variables' 'on')

I'd prefer to use it even though I'd rather not have to code it.

PhilLast commented 5 years ago

If we passed a single option pair to a method without an argument it would have to be enclosed:

      ⎕se.acreAPI.method ⊂'option' 'value'
norberturkiewicz commented 5 years ago

I agree with space delimited name value pairs over ordered inputs.

It makes the whole thing much easier to extend and with how seldom I do it, I don’t have an issue typing full parameter names.

PaulMansour commented 5 years ago

If we passed a single option pair to a method without an argument it would have to be enclosed

True. Alternatively, would it be possible to insist on at least an empty argument ala a dfn? For example:

 ⎕se.acreAPI.method '' ('option' 'value')
PaulMansour commented 5 years ago

Or, every API call requires precisely two arguments - a list of argument and a list of option/value pairs:

⎕se.acreAPI.method (arg1 arg2)  (('op1' 'value') ('op2 'val2') etc )

Phil, I'm not trying to over think this (I think!), I'm trying to come up with something that will work for other apps as well as Acre - that's why I was concerned about leaving the left arg available.

PhilLast commented 5 years ago

One problem regarding my posting one hour ago is that the process to prefix items with the current space doesn't actually work!!

PhilLast commented 5 years ago

... (but it will do.)

PhilLast commented 5 years ago

Currently proceeding on the basis of a potentially mixed depth three list of arg strings and option pairs ⎕se.acreAPI.fn 'arg1' ( 'opt1' '' ) 'arg2' ( 'opt2 '' ). But can easily institute the two list ⎕se.acreAPI.fn ( 'argument' 'list' ) ( ( 'option' 1 ) ( 'list' 0 ) at a later stage if needed.

The API framework consists in a couple of small functions that have become a mess so it's easier to rethink and rewrite.

One thing that could be changed at this time is that the ⎕SE.acre.run function could disappear and the pointer functions in ⎕SE.acreAPI could be put into ⎕SE.acre itself.

but would require changes to make at your end if you've automated any calls.

PaulMansour commented 5 years ago

One thing that could be changed at this time is that the ⎕SE.acre.run function could disappear and the pointer functions in ⎕SE.acreAPI could be put into ⎕SE.acre itself.

Please do. I was just going to suggest this myself. I prefer one namespace in []SE.

PhilLast commented 5 years ago

One thing - would anyone object if I rename the primary code space from ⎕SE.acre._code to ⎕SE.acre.zcode or ⎕SE.acre.z_code.

Although ⎕NL puts '_' after the Latin capitals and the diacritical and "foreign" chars after the minuscules, autocomplete puts '_' first of all, the others interspersed after their unaccented counterparts, leaving 'zZ' to bring up the rear.

The renaming would put all the API functions before the namespace that can't easily be hidden.

norberturkiewicz commented 5 years ago

I actually like @PaulMansour convention of using "Core" as the primary namespace.

PaulMansour commented 5 years ago

I don't reach in there for anything, so I'm ok with any change. I've started using Main as the main space in new projects. It would be nice if top level namespace naming conventions were adhered to across projects. Same for resource folder names. I've been attempting this with AcreTools.

I would not rename the code space just so it shows up less prominently in autocomplete for those using the API.

PaulMansour commented 5 years ago

I'm not suggesting you call it Main (yet!) … I haven't really thought about how AcreTools wants this stuff to look like in detail. Would like to discuss with all at some point.

e9gille commented 5 years ago

I've been considering a clear separation of API vs core code simply by exporting a reference to a sub or sibling namespace. Consider the project space Acre

#.CarlisleGroup.Acre.API
#.CarlisleGroup.Acre.Core

The API space would hold public functions that simply call the private counterparts in either the parent or sibling space (eg. API.Open←{##.Core.Open ⍵}). I'm not pretending this is a new concept, but this combined with the idea that packages are installed in a dedicated space and references then created to the API space would make it a bit more clear what the API is.

Say you install Acre in the session space. If acre is configured to expose the API space, you would end up with something like this:

⎕SE._packages.CarlisleGroup.Acre
⎕SE.acre←⎕SE._packages.CarlisleGroup.Acre.API

Of course, this would only be a convention, nothing that could be enforced perhaps.

PaulMansour commented 5 years ago

Gil, very nice. Solves the problem of arbitrary depth of namespace structure for dev purposes, and easy access to API.

I just built something like :

⎕SE._packages.CarlisleGroup.Acre

to hold the AcreTools code (and any other apps that use the AcreTools) for user command, which is fine, no one is bothered by the depth when using a UCMD. But for the API, obviously a problem. ( I also used the name []SE.AcreTools as the root, which is no good I realize, as I want that name at the top for the AcreTools API).

I am also trying to formalize the relationship between UCMD and API, and this fits in very well.

PaulMansour commented 5 years ago

Phil, correct me if I am wrong, but if one is using the UCMD framework to instantiate the API, then unless you are doing some hackery in the List function, you can't make an API call until you have called an acre user command at least once.

I'm addressing this in AcreTools with my own start session framework.

aplteam commented 5 years ago

I call acre.projects in my startup.dyalog to get around this.

On Fri, 9 Aug 2019, 17:47 Paul Mansour, notifications@github.com wrote:

Phil, correct me if I am wrong, but if one is using the UCMD framework to instantiate the API, then unless you are doing some hackery in the List function, you can't make an API call until you have called an acre user command at least once.

I'm addressing this in AcreTools with my own start session framework.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/the-carlisle-group/Acre-Desktop/issues/184?email_source=notifications&email_token=AD5XJHPHTEHS57RMGJV5ZMTQDWNQZA5CNFSM4H6LVAN2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD37GB4I#issuecomment-519987441, or mute the thread https://github.com/notifications/unsubscribe-auth/AD5XJHPV7VBAVOQGQSGY2OLQDWNQZANCNFSM4H6LVANQ .

PaulMansour commented 5 years ago

Is it startup.dyalog or setup.dyalog?

Also do you know how this is called? Is it deep in the interpreter or a hack in []SE somewhere?

aplteam commented 5 years ago

Sorry, setup.dyalog. it's part of the salt boot process.

On Fri, 9 Aug 2019, 18:02 Paul Mansour, notifications@github.com wrote:

Is it startup.dyalog or setup.dyalog?

Also do you know how this is called? Is it deep in the interpreter or a hack in []SE somewhere?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/the-carlisle-group/Acre-Desktop/issues/184?email_source=notifications&email_token=AD5XJHN6CODMKKIX4MYWVZDQDWPKJA5CNFSM4H6LVAN2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD37HIWI#issuecomment-519992409, or mute the thread https://github.com/notifications/unsubscribe-auth/AD5XJHPQEJ2BTFBILCGCUSLQDWPKJANCNFSM4H6LVANQ .

PaulMansour commented 5 years ago

So that means is in OnWorkspaceLoaded callback somewhere. Ok, thanks.

PhilLast commented 5 years ago

Phil, correct me if I am wrong, but if one is using the UCMD framework to instantiate the API, then unless you are doing some hackery in the List function, you can't make an API call until you have called an acre user command at least once.

Bit late but yes indeed. Acre isn't there and is copied in by the first command that's called.

So that means is in OnWorkspaceLoaded callback somewhere. Ok, thanks.

In a new, unchanged session:

      ↑⎕se ⎕wg 'event'
 GestureZoom              ⎕SE.Fonts.ZoomSession 
 WorkspaceLoaded  ⎕SE.Dyalog.Callbacks.WSLoaded 
 SessionPrint                                 0 

Can't see any reference to "setup.dyalog" in ⎕SE.Dyalog.Callbacks.WSLoaded or anywhere else in ⎕SE. Not in 17.0 that is. But it's certain that WSLoaded does get called at the start of the session.

PaulMansour commented 5 years ago

Whatever you do, do not use setup.dyalog!

PaulMansour commented 5 years ago

WSLoaded probably loads a script, which in turn runs setup.dyalog, my guess.

e9gille commented 5 years ago

This is perhaps going off topic even further (and I know we've been invited to talk to Dyalog about all this post user meeting) but I think I would like to see the session configuration in a structured text file akin to the Acre Project config file.

Packages could then be installed in the session file and each package could contribute a number of user commands via its API.

Same thing with workspaces. They would be config files that optionally define projects and or packages to be loaded.

PaulMansour commented 5 years ago

(and I know we've been invited to talk to Dyalog about all this post user meeting)

Not me!

But to the question at hand, why not just a scripted namespace instead, like a user command file, only done right?

PaulMansour commented 5 years ago

Packages could then be installed in the session file and each package could contribute a number of user commands via its API.

Understood.

Same thing with workspaces. They would be config files that optionally define projects and or packages to be loaded.

Not understood… I vaguely remember a new name for the concept of workspace defined in a config file... but you had another name for it, no?

e9gille commented 5 years ago

(and I know we've been invited to talk to Dyalog about all this post user meeting)

Not me!

OK, me neither. That was an optimistic interpretation of the email Kai copied us in on. I think the wording was that Morten has every intention to invite us all in the design discussions :)

but you had another name for it, no?

No, I couldn't think of a better name for it, so I called it a workspace. It is a slight change of perspective. You have defined that a project can load other projects via its config file. My suggestion is that you could extend that by defining a workspace as a collection of projects that are all opened at the same time. The config file would simply list the projects and potentially other IDE settings but lack properties that are project specific (ProjectSpace, Name, Version etc.)

PhilLast commented 5 years ago

Reread Andy's mail that Kai forwarded to us. Is this what you're doing Kai? Using ]usetup?

      ]USetup -?? ⍝ for more info
───────────────────────────────────────────────────────────────────────────────

]UCMD.USetup

Initialise user's setup

This command is used to (re-)initialize a user's setup by running a specific function every
time the user command system is (re-)started, e.g. upon starting Dyalog APL (with SALT
enabled). The function can also be run at any time with ]USetup

To use this functionality, save a function named "Setup" (or namespace with such a function) in
a file called "setup.dyalog" in "C:\Users\Phil\Documents\MyUCMDs\" or in one of the current
SALT workdirs (C:\Users\Phil\Documents\Dyalog APL-64 17.0 Unicode Files\Code,
[DYALOG]\Library\Core, [DYALOG]\Library\Conga, [SALT]).

If the Setup function is monadic it will be called with ]USetup's argument or with 'init' when
Dyalog APL starts.

Examples:
  To always let F2 list variables and F3 list functions:
    Setup←{(')VARS',⊂'ER') (')FNS',⊂'ER') ⎕PFKEY¨2 3}
    ]Save Setup C:\Users\Phil\Documents\MyUCMDs\ -makedir

  To return the filename which will be used followed by a Boolean indicating if it exists or
  not:
    ]USetup -info
  To return a list of all current search paths with a Boolean for each indicating if that file
  exists:
    ]USetup -info=list
  The file that will be run is the topmost existing one (if any exists).

    ]USetup -info=list
 C:\Users\Phil\Documents\MyUCMDs\setup.dyalog                                0
 C:\Users\Phil\Documents\Dyalog APL-64 17.0 Unicode Files\Code\setup.dyalog  0
 [DYALOG]\Library\Core\setup.dyalog                                          0
 [DYALOG]\Library\Conga\setup.dyalog                                         0
 [SALT]\setup.dyalog                                                         0

Looks innocuous enough and given that there are no examples in any path in my machine it doesn't look as though I'd be likely to break anything by using it.

And even if Dyalog is thinking of replacing it, how many years are we looking at? I guess they would then be asking not just us few whose code they were about to break before abandonning it.

Even so I think I'd rather have things closer to home and initialise whatever I want when I want it. If I'm going to change anything I want to know what it was like beforehand. If my session is not default at the start I can't assume that what acre's doing is going to work the same anywhere else.

PhilLast commented 5 years ago

In any case, this doesn't bode well ...

      ]usetup -info
 C:\Users\Phil\Documents\MyUCMDs\setup.dyalog  0
      setup←{⎕←⍵}
      ]save setup C:\Users\Phil\Documents\MyUCMDs\ -makedir
C:\Users\Phil\Documents\MyUCMDs\setup.dyalog 
      ]usetup -info
 C:\Users\Phil\Documents\MyUCMDs\setup.dyalog  1
      ]usetup
* Command Execution Failed: VALUE ERROR
      ]usetup arthur
* Command Execution Failed: VALUE ERROR
aplteam commented 5 years ago

It's case sensitive. The function I mean.

When you name it "Setup" it works as described.

I am using this mechanism for a long time now. Back then there was no ]Usetup. Back then it had to be a namespace script.

On Sat, 10 Aug 2019 at 08:32, PhilLast notifications@github.com wrote:

In any case, this doesn't bode well ...

  ]usetup -info

C:\Users\Phil\Documents\MyUCMDs\setup.dyalog 0

  setup←{⎕←⍵}

  ]save setup C:\Users\Phil\Documents\MyUCMDs\ -makedir

C:\Users\Phil\Documents\MyUCMDs\setup.dyalog

  ]usetup -info

C:\Users\Phil\Documents\MyUCMDs\setup.dyalog 1

  ]usetup
  • Command Execution Failed: VALUE ERROR

    ]usetup arthur

  • Command Execution Failed: VALUE ERROR

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/the-carlisle-group/Acre-Desktop/issues/184?email_source=notifications&email_token=AD5XJHOBLCBYX47AKJ2ER5DQDZVHLA5CNFSM4H6LVAN2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD4AIB7Y#issuecomment-520126719, or mute the thread https://github.com/notifications/unsubscribe-auth/AD5XJHPCQZCAP4PDJ75F7PTQDZVHLANCNFSM4H6LVANQ .

PhilLast commented 5 years ago

On the topic of case sensibility, ]User.Commands are not but APL function names certainly are.

With API fns and commands to correspond one-to-one, I'm currently jumping through hoops to get them to run the same code as far as possible.

It would be much simpler if their names were actually identical. The reason they're not is because the API fns were initially just a few peeks into acre's internals that didn't seem to warrant being made into user commands and they were invoked by passing a case-agnostic "name" into the run function.

Many acre commands have borne the same PascalCaseName for ten years and are referred to as such thoughout the documentation. The API is barely a couple of years in its oldest manifestation.

Given the availability of autocompletion I propose to rename all the API fns to pascal case mirroring the commands.

aplteam commented 5 years ago

Sounds right to me.

PaulMansour commented 5 years ago

Please do.

PaulMansour commented 5 years ago

If one were going to generalize the concept of an API with an acre project, what name would give the parameter that specifies the API space: API or EntrySpace or something else?

e9gille commented 5 years ago

API is better. The API could in theory be a simple/single function.

PhilLast commented 4 years ago

This became a very wide ranging thread but the main issue was settled in Acre 6.0.0+258 2019-08-31 21:51.

Latest change Acre 6.0.2+270 2019-09-10 13.13 allowed the option names to be abbreviated and added then to the command log message.