Hi, The point I have about user commands not cleared is rather a feature than a bug: I would like to have a set of my user commands irrespectively of loaded workspace. In other words, if I define ]pwd in setup.apl, I want to be able use it in regardless of )load, )clear or )continue and do not copy this workspace every time.
Juergen Sauermann <juergen.sauerm...@t-online.de> writes: > Hi Alexey, > > the fact that commands are not saved with a workspace is a bug and > I will fix it. Also )CLEAR or )LOAD should remove existing user defined > commands. > > My point with the CONTINUE workspace was that this is exactly the > functionality > that you are proposing. It is executed before anything else if you start APL. > The only problem > is that the )CONTINUE command overrides the CONTINUE workspace. But we could > have > a workspace with a different name, like SETUP.apl that behaves like CONTINUE > but can not be > overridden by a command like )CONTINUE. > > Running SETUP even if COUNTINUE is present would, in my opinion, be wrong > because the > expectation of )CONTINUE is that you continue at the same point, which can > not be guaranteed > because SETUP might do weird things that damage the CONTINUE workspace. > > So the logic would be: > > - start apl, > if CONTINUE exists - load it, > otherwise if SETUP exists - load it. > > I can take care of this because there are other aspects to consider, see > main.cc lines 417. > > /// Jürgen > > On 02/24/2017 08:24 PM, Alexey Veretennikov wrote: > > Hi, > > The solution with )continue is not helping me: I want to have the my > commands available in all workspaces. > Right now if I )load workspace, all functions from previous workspace > got lost. > But user commands stays! meaning they will refer to unexisting > functions. > With the introduction of lambdas as user commands one could overcome > this limitation by encoding necessary functionality as lambdas. > > In Dyalog APL I can create a file MyUCMDs/setup.dyalog with the > contents: > Setup←{_←⎕SE.UCMD'cd /Users/alexeyv/Sources/apl/dyalog-workspaces '} > > and every time I start the interpreter my current directory is changed > to the specified. > > I want to have something like this in GNU APL, so every time I run > interpreter I can: > - change the directory > - set my user commands > regardless of existence of CONTINUE workspace. > > This could be solved by introducing the ~/.gnu-apl/setup.apl file with > APL source code, which if exists executes before any other workspaces. > > How does it sound? If it is ok I'll implement it. > > Juergen Sauermann <juergen.sauerm...@t-online.de> writes: > > Hi Alexey, > > I believe it would be more useful to have a facility that loads an arbitrary > apl script at startup > instead of a specific one for user defined commands. > > Actually you can do that already with the )CONTINUE workspace, which is > loaded automatically > if it exists. You could replicate the )CONTINUE logic (or simply call your > workspace CONTINUE.apl). > > I would also suggest that we try to exploit existing functionalities before > we invent new ones. > Most non-standard functions of GNU APL are fairly useless because nobody > knows them. > > /// Jürgen > > On 02/23/2017 07:11 PM, Alexey Veretennikov wrote: > > Hi, > > Actually I'm thinking about a patch which will load these usercmds from > the config file at the startup. In this case every user will be > able to create own commands (like ]pwd and ]cd below) to interact with > interpreter and store them independent of the workspaces. > > It will definitely helpful for me, what about others? > > Christian Robert <christian.rob...@polymtl.ca> writes: > > It would be fun if those ]USERCMD could be saved in workspace and )loaded > back. > > Not sure if it's possible ... > > Xtian. > > > On 2017-02-23 12:04, Juergen Sauermann wrote: > > Hi Alexey, Blake, > > I have applied the patch, *SVN 892*. > > I don't think that it hurts too much even though its not APL. > Nor are lambdas, so the ⍎ of )COMMANDs and {...} should fit nicely. > > /// Jürgen > > > On 02/23/2017 08:47 AM, Alexey Veretennikov wrote: > > Hi, > > I'm updating the ]USERCMD functionality which is already non-standard > extension in GNU > APL. Similar extension exists in Dyalog APL for quite many years as > well. These commands targeted use in the interpreter and have nothing to do > with a new syntax. > What I did is just fixed its limitation where I always had to > create a named function to add a user command. > > P.S. Example with ]pwd was bogus, the proper one is > > ]usercmd ]pwd {⎕FIO 30 ⍵} > User-defined command ]pwd installed. > ]pwd > /Users/alexeyv > > > Blake McBride <blake1...@gmail.com> writes: > > Not sure I like this. Doesn't seem like APL. You are mangling > program-ability with system commands. APL > has no history of that. It may be an okay idea, but it's not APL. > > Adding program-ability to system commands is essentially adding a whole new > syntax to APL. > > Just one opinion. > > Blake > > On Wed, Feb 22, 2017 at 4:18 PM, Alexey Veretennikov > <alexey.veretenni...@gmail.com> wrote: > > Hi, > > The proposed patch allows usage of dfns as a ]USERCMD. > The mode (monadic or dyadic) is not needed since it is derived from the > lambda function itself. > > Possibility to use lambdas as a user commands allows to have commands > without polluting the global namespace with the function names. > > Usage example: > > ]usercmd ]pwd {⎕FIO 30 ⍵ ← ⍺} > User-defined command ]pwd installed. > > ]pwd > /Users/alexeyv/Sources/apl-svn/src > > ]usercmd ]cd {⎕FIO[54] (⎕IO+1) ⊃ ⍵ ← ⍺} > User-defined command ]cd installed. > > ]cd /Users/alexeyv > 0 > > ]pwd > /Users/alexeyv > > -- > Br, > /Alexey > > Index: src/Command.cc > =================================================================== > --- src/Command.cc (revision 891) > +++ src/Command.cc (working copy) > @@ -1277,6 +1277,7 @@ > // ]USERCMD REMOVE ]existing-command > // ]USERCMD ]new-command APL-fun > // ]USERCMD ]new-command APL-fun mode > + // ]USERCMD ]new-command LAMBDA-fun > // > if (args.size() == 0) > { > @@ -1321,14 +1322,54 @@ > return; > } > > - if (args.size() > 3) > + // check if the user command is not followed by the string > + if (args.size() == 1) > + { > + out << "BAD COMMAND+" << endl; > + MORE_ERROR() << "user command syntax in ]USERCMD: ]new-command APL-fun > [mode]"; > + return; > + } > + UCS_string command_name = args[0]; > + UCS_string apl_fun = args[1]; > + int mode = 0; > + > + // check if lambda > + bool is_lambda = false; > + if (apl_fun[0] == '{') > { > + // looks like the user command is a lambda function. > + UCS_string result; > + // lambdas could contain spaces, collect all arguments in one string > + for (int i = 1; i < args.size(); ++ i) > + { > + result << args[i]; > + } > + // check if lamda-function closed properly > + if (result.last() == '}') > + { > + is_lambda = true; > + apl_fun = result; > + // determine the mode: if both alpha and omega present, assume dyadic, > + // otherwise - monadic usage > + mode = (apl_fun.contains(UNI_OMEGA) && apl_fun.contains(UNI_ALPHA)) ? 1 : > 0; > + } > + else > + { > + out << "BAD COMMAND+" << endl; > + MORE_ERROR() << "not found closing } in lambda function"; > + return; > + } > + } > + > + if (args.size() > 3 && !is_lambda) > + { > out << "BAD COMMAND+" << endl; > MORE_ERROR() << "too many parameters in command ]USERCMD"; > return; > } > > -const int mode = (args.size() == 3) ? args[2].atoi() : 0; > + // check mode > + if (!is_lambda && args.size() == 3) mode = args[2].atoi(); > if (mode < 0 || mode > 1) > { > out << "BAD COMMAND+" << endl; > @@ -1339,11 +1380,11 @@ > > // check command name > // > - loop(c, args[0].size()) > + loop(c, command_name.size()) > { > bool error = false; > - if (c == 0) error = error || args[0][c] != ']'; > - else error = error || !Avec::is_symbol_char(args[0][c]); > + if (c == 0) error = error || command_name[c] != ']'; > + else error = error || !Avec::is_symbol_char(command_name[c]); > if (error) > { > out << "BAD COMMAND+" << endl; > @@ -1355,28 +1396,31 @@ > // check conflicts with existing commands > // > #define cmd_def(cmd_str, _cod, _arg, _hint) \ > - if (check_name_conflict(out, cmd_str, args[0])) return; > + if (check_name_conflict(out, cmd_str, command_name)) return; > #include "Command.def" > - if (check_redefinition(out, args[0], args[1], mode)) > + if (check_redefinition(out, command_name, apl_fun, mode)) > { > out << " User-defined command " > - << args[0] << " installed." << endl; > + << command_name << " installed." << endl; > return; > } > > // check APL function name > - // > - loop(c, args[1].size()) > + // Only needed when not a lambda function > + if (!is_lambda) > { > - if (!Avec::is_symbol_char(args[1][c])) > - { > - out << "BAD COMMAND+" << endl; > - MORE_ERROR() << "bad APL function name in command ]USERCMD"; > - return; > - } > + loop(c, apl_fun.size()) > + { > + if (!Avec::is_symbol_char(apl_fun[c])) > + { > + out << "BAD COMMAND+" << endl; > + MORE_ERROR() << "bad APL function name in command ]USERCMD"; > + return; > + } > + } > } > > -user_command new_user_command = { args[0], args[1], mode }; > +user_command new_user_command = { command_name, apl_fun, mode }; > user_commands.append(new_user_command); > > out << " User-defined command " > > > > > > > > -- Br, /Alexey