Commands defined as primitive
receive additional input via the cog_env
key on the Command.Request. cog_env
is populated with the execution scope of the command. Specifically it's the values
key from the scope in the current state of the executor. It is necessary because certain primitive commands, filter
or sort
for example, need access to the entire map returned by a previous command. We don't want that information available to non primitive commands because it makes permissions difficult to lock down. Since primitives have no permissions, it doesn't matter.
For example
Given the command @cog stackoverflow vim | echo $title
The stackoverflow command produces output similar to the following:
For simplicity we'll assume stackoverflow only returns one result.
[{ "title": "Vim an editor",
"link": "http://stackoverflow.com/vim-an-editor",
"likes": 40,
"some_other_key": "some other value"
}]
The executor then uses the results of stackoverflow to create a scope for the execution of echo. In this case $title
is replace with "Vim an editor". And so the user receives "Vim an editor" as the result of the operation. This is basically how all commands work, but primitives also receive an addition key on the request, cog_env
.
Which in this case would be populated with:
{ "title": "Vim an editor",
"link": "http://stackoverflow.com/vim-an-editor",
"likes": 40,
"some_other_key": "some other value"
}
Now in the case of echo this is irrelevant, but for commands like filter
it becomes more important.
Given the command @cog stackoverflow vim | filter --matches="^Vim" --key="title" --returns="title,link"
Stackoverflow might return input similar to the following:
[{ "title": "Vim an editor",
"link": "http://stackoverflow.com/vim-an-editor",
"likes": 40,
"some_other_key": "some other value"
},
{ "title": "Emacs vs Vim",
"link": "http://stackoverflow.com/emacs-vs-vim",
"likes": 23,
"some_other_key": "a new some other value"
},
{ "title": "VimGolf, what's up with that?",
"link": "http://stackoverflow.com/vimgolf",
"likes": 86,
"some_other_key": "another new some other value"
}]
Assuming filter uses the multi
execution type, I'll explain single
in a bit, it would be executed once per entry in the results list using each result as the execution scope for the command. In this case there is no variable replacement like in echo, instead filter pulls the data it needs directly from the map. It can then check the title
field to see if it matches with "^Vim". If it does it returns a new map consisting of title and link. If it doesn't it just returns an empty response.
The user would then receive a response like this:
[{ "title": "Vim an editor",
"link": "http://stackoverflow.com/vim-an-editor"
},
{ "title": "VimGolf, what's up with that?",
"link": "http://stackoverflow.com/vimgolf"
}]
Now if we throw a single
execution command into the mix.
Given the command @cog stackoverflow vim | filter --matches="^Vim" --field="title" | sort --field="likes" --desc
| filter --return="title,link"
We can assume stackoverflow returns the same output as the previous example.
filter
would then output something like this:
[{ "title": "Vim an editor",
"link": "http://stackoverflow.com/vim-an-editor",
"likes": 40,
"some_other_key": "some other value"
},
{ "title": "VimGolf, what's up with that?",
"link": "http://stackoverflow.com/vimgolf",
"likes": 86,
"some_other_key": "another new some other value"
}]
The execution of sort
is where we can see the difference between multi
and single
. sort
is of the single
execution type. This means that the command is only executed one time no matter how many items are in the input list. It get's the entire list. Since sort
is a primitive, cog_env
would match the output of filter.
[{ "title": "Vim an editor",
"link": "http://stackoverflow.com/vim-an-editor",
"likes": 40,
"some_other_key": "some other value"
},
{ "title": "VimGolf, what's up with that?",
"link": "http://stackoverflow.com/vimgolf",
"likes": 86,
"some_other_key": "another new some other value"
}]
Sort is responsible for iterating over the list an processing accordingly.
[{ "title": "VimGolf, what's up with that?",
"link": "http://stackoverflow.com/vimgolf",
"likes": 86,
"some_other_key": "another new some other value"
},
{ "title": "Vim an editor",
"link": "http://stackoverflow.com/vim-an-editor",
"likes": 40,
"some_other_key": "some other value"
}]
Then filter runs again and the final output looks like this:
[{ "title": "VimGolf, what's up with that?",
"link": "http://stackoverflow.com/vimgolf"
},
{ "title": "Vim an editor",
"link": "http://stackoverflow.com/vim-an-editor"
}]