Current section
Files
Jump to
Current section
Files
src/otpcl_core.erl
% @doc Core OTPCL commands. These commands are technically optional, but
% leaving them out (i.e. in a custom interpreter state) can create some rather
% peculiar results, in particular since this is where basic commands like
% `return' and `|' live (yes, the OTPCL standard pipe is internally an ordinary
% command, so you can call it on its own; you can also define your own
% pipe-commands, as detailed below).
-module(otpcl_core).
-include("otpcl.hrl").
-export([return/2, '|'/2]).
-otpcl_cmds([return, '|']).
-spec return(any(), state()) -> {any(), state()}.
% @doc Sets `$RETVAL' in the given state. `$RETVAL' will be set to one of `ok'
% (if passed an empty list), the list element (if passed a single-element list)
% or the given return value as-is (if passed literally anything else). Because
% `$RETVAL' is an ordinary OTPCL variable, it's possible to write
% functions/commands that read it, allowing for, say, chained operations on an
% item (this is, notably, how OTPCL's pipe functionality works; more on that in
% the documentation for ``'|'/2'').
return([], State) ->
{ok, State};
return([RetVal], State) ->
{RetVal, State};
return(Args, State) ->
{Args, State}.
-spec '|'([any()|[any()]], state()) -> {any(), state()}.
% @doc Inline command chaining operator. Takes the result of the preceding
% command (stored in `$RETVAL') and passes it as the first argument to the named
% command (the rest of the arguments passed being passed through as additional
% arguments to the named command).
%
% OTPCL's parser treats any "free" instance of a pipe character (i.e. unescaped
% and not already part of some other word) as a command terminator, so OTPCL
% will interpret a line like `foo | bar | baz' as equivalent to separately
% calling `foo', `| bar', and `| baz' (which would in turn be equivalent to `baz
% [bar [foo]]'). This means that it's possible to define custom commands with
% pipe-like behavior, and rather simply, too; for example, to define a `|!'
% command that sends the result of a command to a process:
%
% ```
% '|!'([Pid], State) ->
% {RetVal, State} = otpcl_meta:get(['RETVAL', State),
% Pid ! RetVal,
% {ok, State}.
% '''
%
% Assuming the above function is tied to a command name somehow, one could then
% call `foo bar baz |! $pid' to send the result of the command `foo bar baz' as
% a message to the process identified via `$pid'.
'|'([Cmd|Args], State) ->
{RetVal, State} = otpcl_meta:get(['RETVAL'], State),
otpcl_meta:apply([Cmd, [RetVal|Args]], State).