bshell: re-organise build into three separate components
bshell: the front-end binary bshell.runtime: contains the parser, compiler, and classes needed to run bshell scripts bshell.core: contains the builtin commandlets and aliases
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
set(source_dirs aliases cmdlets)
|
||||
|
||||
file(GLOB sources
|
||||
*.c
|
||||
*.h)
|
||||
|
||||
foreach (d ${source_dirs})
|
||||
file(GLOB d_sources
|
||||
${d}/*.c
|
||||
${d}/*.h)
|
||||
set(sources ${sources} ${d_sources})
|
||||
endforeach (d)
|
||||
|
||||
message(STATUS ${sources})
|
||||
add_library(bshell.core SHARED ${sources})
|
||||
|
||||
target_link_libraries(bshell.core bshell.runtime FX::Runtime FX::Collections FX::Term)
|
||||
target_include_directories(bshell.core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
target_compile_definitions(bshell.core PUBLIC
|
||||
BSHELL_VERSION="${bshell_version}")
|
||||
@@ -0,0 +1,44 @@
|
||||
#include <bshell/command/alias.h>
|
||||
#include <bshell/command/command.h>
|
||||
#include <fx/reflection/function.h>
|
||||
#include <fx/string.h>
|
||||
#include <fx/vector.h>
|
||||
|
||||
#define BSHELL_TYPE_ECHO (bshell_echo_get_type())
|
||||
|
||||
fx_type_id bshell_echo_get_type(void);
|
||||
|
||||
FX_DECLARE_TYPE(bshell_echo);
|
||||
|
||||
FX_TYPE_CLASS_DECLARATION_BEGIN(bshell_echo)
|
||||
FX_TYPE_CLASS_DECLARATION_END(bshell_echo)
|
||||
|
||||
struct bshell_echo_p {
|
||||
};
|
||||
|
||||
static void init(fx_object *obj, void *priv)
|
||||
{
|
||||
}
|
||||
|
||||
FX_TYPE_CLASS_BEGIN(bshell_echo)
|
||||
FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
|
||||
FX_INTERFACE_ENTRY(to_string) = NULL;
|
||||
FX_TYPE_VTABLE_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
|
||||
|
||||
FX_TYPE_VTABLE_INTERFACE_BEGIN(bshell_alias, BSHELL_TYPE_ALIAS)
|
||||
FX_INTERFACE_ENTRY(a_callable_name) = "echo";
|
||||
FX_INTERFACE_ENTRY(a_target_name) = "Write-Output";
|
||||
FX_TYPE_VTABLE_INTERFACE_END(bshell_cmdlet, BSHELL_TYPE_CMDLET)
|
||||
|
||||
FX_TYPE_VTABLE_INTERFACE_BEGIN(bshell_command, BSHELL_TYPE_COMMAND)
|
||||
FX_TYPE_VTABLE_INTERFACE_END(bshell_command, BSHELL_TYPE_COMMAND)
|
||||
FX_TYPE_CLASS_END(bshell_echo)
|
||||
|
||||
FX_TYPE_DEFINITION_BEGIN(bshell_echo)
|
||||
FX_TYPE_ID(0xedd507bf, 0x2e32, 0x425b, 0x9c73, 0x2ba9539eace0);
|
||||
FX_TYPE_NAME("bshell.core.echo");
|
||||
FX_TYPE_EXTENDS(BSHELL_TYPE_ALIAS);
|
||||
FX_TYPE_CLASS(bshell_echo_class);
|
||||
FX_TYPE_INSTANCE_INIT(init);
|
||||
FX_TYPE_INSTANCE_PRIVATE(struct bshell_echo_p);
|
||||
FX_TYPE_DEFINITION_END(bshell_echo)
|
||||
@@ -0,0 +1,44 @@
|
||||
#include <bshell/command/alias.h>
|
||||
#include <bshell/command/command.h>
|
||||
#include <fx/reflection/function.h>
|
||||
#include <fx/string.h>
|
||||
#include <fx/vector.h>
|
||||
|
||||
#define BSHELL_TYPE_PERCENT (bshell_percent_get_type())
|
||||
|
||||
fx_type_id bshell_percent_get_type(void);
|
||||
|
||||
FX_DECLARE_TYPE(bshell_percent);
|
||||
|
||||
FX_TYPE_CLASS_DECLARATION_BEGIN(bshell_percent)
|
||||
FX_TYPE_CLASS_DECLARATION_END(bshell_percent)
|
||||
|
||||
struct bshell_percent_p {
|
||||
};
|
||||
|
||||
static void init(fx_object *obj, void *priv)
|
||||
{
|
||||
}
|
||||
|
||||
FX_TYPE_CLASS_BEGIN(bshell_percent)
|
||||
FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
|
||||
FX_INTERFACE_ENTRY(to_string) = NULL;
|
||||
FX_TYPE_VTABLE_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
|
||||
|
||||
FX_TYPE_VTABLE_INTERFACE_BEGIN(bshell_alias, BSHELL_TYPE_ALIAS)
|
||||
FX_INTERFACE_ENTRY(a_callable_name) = "%";
|
||||
FX_INTERFACE_ENTRY(a_target_name) = "ForEach-Object";
|
||||
FX_TYPE_VTABLE_INTERFACE_END(bshell_cmdlet, BSHELL_TYPE_CMDLET)
|
||||
|
||||
FX_TYPE_VTABLE_INTERFACE_BEGIN(bshell_command, BSHELL_TYPE_COMMAND)
|
||||
FX_TYPE_VTABLE_INTERFACE_END(bshell_command, BSHELL_TYPE_COMMAND)
|
||||
FX_TYPE_CLASS_END(bshell_percent)
|
||||
|
||||
FX_TYPE_DEFINITION_BEGIN(bshell_percent)
|
||||
FX_TYPE_ID(0x4255a9de, 0xd6f6, 0x4708, 0x829c, 0xffa4c6034edb);
|
||||
FX_TYPE_NAME("bshell.core.percent");
|
||||
FX_TYPE_EXTENDS(BSHELL_TYPE_ALIAS);
|
||||
FX_TYPE_CLASS(bshell_percent_class);
|
||||
FX_TYPE_INSTANCE_INIT(init);
|
||||
FX_TYPE_INSTANCE_PRIVATE(struct bshell_percent_p);
|
||||
FX_TYPE_DEFINITION_END(bshell_percent)
|
||||
@@ -0,0 +1,22 @@
|
||||
#include <fx/macros.h>
|
||||
#include <fx/reflection/assembly.h>
|
||||
|
||||
FX_ASSEMBLY_BEGIN(bshell_core)
|
||||
FX_ASSEMBLY_NAME("bshell.core");
|
||||
FX_ASSEMBLY_VERSION(0, 1, 0, 0);
|
||||
FX_ASSEMBLY_EXPORT_TYPE("bshell.core", "get_verb", bshell_get_verb);
|
||||
FX_ASSEMBLY_EXPORT_TYPE(
|
||||
"bshell.core",
|
||||
"write_output",
|
||||
bshell_write_output);
|
||||
FX_ASSEMBLY_EXPORT_TYPE(
|
||||
"bshell.core",
|
||||
"foreach_object",
|
||||
bshell_foreach_object);
|
||||
FX_ASSEMBLY_EXPORT_TYPE(
|
||||
"bshell.core",
|
||||
"get_command",
|
||||
bshell_get_command);
|
||||
FX_ASSEMBLY_EXPORT_TYPE("bshell.core", "percent", bshell_percent);
|
||||
FX_ASSEMBLY_EXPORT_TYPE("bshell.core", "echo", bshell_echo);
|
||||
FX_ASSEMBLY_END(bshell_core)
|
||||
@@ -0,0 +1,98 @@
|
||||
#include <bshell/command/cmdlet.h>
|
||||
#include <bshell/command/command.h>
|
||||
#include <bshell/runtime/pipeline.h>
|
||||
#include <bshell/runtime/runtime.h>
|
||||
#include <bshell/runtime/script-block.h>
|
||||
#include <bshell/status.h>
|
||||
#include <fx/reflection/function.h>
|
||||
#include <fx/string.h>
|
||||
#include <fx/vector.h>
|
||||
|
||||
#define BSHELL_TYPE_FOREACH_OBJECT (bshell_foreach_object_get_type())
|
||||
|
||||
fx_type_id bshell_foreach_object_get_type(void);
|
||||
|
||||
FX_DECLARE_TYPE(bshell_foreach_object);
|
||||
|
||||
FX_TYPE_CLASS_DECLARATION_BEGIN(bshell_foreach_object)
|
||||
FX_TYPE_CLASS_DECLARATION_END(bshell_foreach_object)
|
||||
|
||||
struct bshell_foreach_object_p {
|
||||
bshell_scriptblock *f_block;
|
||||
};
|
||||
|
||||
static enum bshell_status begin_processing(bshell_cmdlet *cmdlet)
|
||||
{
|
||||
struct bshell_foreach_object_p *p
|
||||
= fx_object_get_private(cmdlet, BSHELL_TYPE_FOREACH_OBJECT);
|
||||
|
||||
const fx_value *block_v = bshell_command_get_arg(cmdlet, 1);
|
||||
if (!block_v) {
|
||||
return BSHELL_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
fx_value_get_object(block_v, &p->f_block);
|
||||
return BSHELL_SUCCESS;
|
||||
}
|
||||
|
||||
static enum bshell_status process_record(
|
||||
bshell_cmdlet *cmdlet,
|
||||
bshell_pipeline *pipeline,
|
||||
struct bshell_runtime *rt)
|
||||
{
|
||||
struct bshell_foreach_object_p *p
|
||||
= fx_object_get_private(cmdlet, BSHELL_TYPE_FOREACH_OBJECT);
|
||||
|
||||
fx_value in = bshell_pipeline_read_value(pipeline);
|
||||
if (!fx_value_is_set(&in)) {
|
||||
return BSHELL_SUCCESS;
|
||||
}
|
||||
|
||||
bshell_runtime_push_scope(rt, p->f_block);
|
||||
bshell_variable *item = bshell_runtime_define_var(rt, "_");
|
||||
bshell_variable_set_value(item, &in);
|
||||
fx_value out = bshell_runtime_eval(rt);
|
||||
bshell_runtime_pop_scope(rt);
|
||||
fx_value_unset(&in);
|
||||
bshell_pipeline_write_value(pipeline, out, false);
|
||||
fx_value_unset(&out);
|
||||
|
||||
return BSHELL_SUCCESS;
|
||||
}
|
||||
|
||||
static enum bshell_status end_processing(bshell_cmdlet *cmdlet)
|
||||
{
|
||||
struct bshell_foreach_object_p *p
|
||||
= fx_object_get_private(cmdlet, BSHELL_TYPE_FOREACH_OBJECT);
|
||||
return BSHELL_SUCCESS;
|
||||
}
|
||||
|
||||
static void init(fx_object *obj, void *priv)
|
||||
{
|
||||
}
|
||||
|
||||
FX_TYPE_CLASS_BEGIN(bshell_foreach_object)
|
||||
FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
|
||||
FX_INTERFACE_ENTRY(to_string) = NULL;
|
||||
FX_TYPE_VTABLE_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
|
||||
|
||||
FX_TYPE_VTABLE_INTERFACE_BEGIN(bshell_cmdlet, BSHELL_TYPE_CMDLET)
|
||||
FX_INTERFACE_ENTRY(c_verb) = BSHELL_VERB_FOREACH;
|
||||
FX_INTERFACE_ENTRY(c_noun) = "Object";
|
||||
FX_TYPE_VTABLE_INTERFACE_END(bshell_cmdlet, BSHELL_TYPE_CMDLET)
|
||||
|
||||
FX_TYPE_VTABLE_INTERFACE_BEGIN(bshell_command, BSHELL_TYPE_COMMAND)
|
||||
FX_INTERFACE_ENTRY(c_begin_processing) = begin_processing;
|
||||
FX_INTERFACE_ENTRY(c_process_record) = process_record;
|
||||
FX_INTERFACE_ENTRY(c_end_processing) = end_processing;
|
||||
FX_TYPE_VTABLE_INTERFACE_END(bshell_command, BSHELL_TYPE_COMMAND)
|
||||
FX_TYPE_CLASS_END(bshell_foreach_object)
|
||||
|
||||
FX_TYPE_DEFINITION_BEGIN(bshell_foreach_object)
|
||||
FX_TYPE_ID(0x44ae3223, 0x14b3, 0x4c89, 0x9753, 0x6c7901ae00e9);
|
||||
FX_TYPE_NAME("bshell.core.foreach_object");
|
||||
FX_TYPE_EXTENDS(BSHELL_TYPE_CMDLET);
|
||||
FX_TYPE_CLASS(bshell_foreach_object_class);
|
||||
FX_TYPE_INSTANCE_INIT(init);
|
||||
FX_TYPE_INSTANCE_PRIVATE(struct bshell_foreach_object_p);
|
||||
FX_TYPE_DEFINITION_END(bshell_foreach_object)
|
||||
@@ -0,0 +1,8 @@
|
||||
#include <bshell/status.h>
|
||||
#include <fx/object.h>
|
||||
#include <fx/stream.h>
|
||||
|
||||
enum bshell_status do_format_table(fx_object *object, fx_stream *dest)
|
||||
{
|
||||
return BSHELL_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
#include <bshell/command/cmdlet.h>
|
||||
#include <bshell/command/command.h>
|
||||
#include <bshell/runtime/pipeline.h>
|
||||
#include <bshell/runtime/runtime.h>
|
||||
#include <bshell/runtime/scope.h>
|
||||
#include <bshell/status.h>
|
||||
#include <fx/reflection/assembly.h>
|
||||
#include <fx/reflection/function.h>
|
||||
#include <fx/string.h>
|
||||
#include <fx/vector.h>
|
||||
|
||||
#define BSHELL_TYPE_GET_COMMAND (bshell_get_command_get_type())
|
||||
|
||||
fx_type_id bshell_get_command_get_type(void);
|
||||
|
||||
FX_DECLARE_TYPE(bshell_get_command);
|
||||
|
||||
FX_TYPE_CLASS_DECLARATION_BEGIN(bshell_get_command)
|
||||
FX_TYPE_CLASS_DECLARATION_END(bshell_get_command)
|
||||
|
||||
struct bshell_get_command_p {
|
||||
bool c_eof;
|
||||
};
|
||||
|
||||
static enum bshell_status begin_processing(bshell_cmdlet *cmdlet)
|
||||
{
|
||||
struct bshell_get_command_p *p
|
||||
= fx_object_get_private(cmdlet, BSHELL_TYPE_GET_COMMAND);
|
||||
return BSHELL_SUCCESS;
|
||||
}
|
||||
|
||||
static enum bshell_status process_record(
|
||||
bshell_cmdlet *cmdlet,
|
||||
bshell_pipeline *pipeline,
|
||||
struct bshell_runtime *rt)
|
||||
{
|
||||
struct bshell_get_command_p *p
|
||||
= fx_object_get_private(cmdlet, BSHELL_TYPE_GET_COMMAND);
|
||||
if (p->c_eof) {
|
||||
return BSHELL_SUCCESS;
|
||||
}
|
||||
|
||||
fx_iterator *aliases = fx_iterator_begin(rt->rt_aliases);
|
||||
fx_foreach(item_v, aliases)
|
||||
{
|
||||
fx_hashtable_item *item;
|
||||
fx_value_get_object(&item_v, &item);
|
||||
fx_value alias_v = fx_hashtable_item_get_value(item);
|
||||
bshell_pipeline_write_value(pipeline, alias_v, false);
|
||||
}
|
||||
fx_iterator_unref(aliases);
|
||||
|
||||
struct bshell_runtime_scope *scope
|
||||
= bshell_runtime_get_current_scope(rt);
|
||||
while (scope) {
|
||||
fx_hashtable *function_map
|
||||
= bshell_runtime_scope_get_functions(scope);
|
||||
fx_iterator *functions = fx_iterator_begin(function_map);
|
||||
fx_foreach(item_v, functions)
|
||||
{
|
||||
fx_hashtable_item *item;
|
||||
fx_value_get_object(&item_v, &item);
|
||||
fx_value func_v = fx_hashtable_item_get_value(item);
|
||||
bshell_pipeline_write_value(pipeline, func_v, false);
|
||||
}
|
||||
fx_iterator_unref(functions);
|
||||
|
||||
scope = bshell_runtime_get_parent_scope(rt, scope);
|
||||
}
|
||||
|
||||
fx_iterator *assemblies = fx_assembly_get_all();
|
||||
fx_foreach(asm_v, assemblies)
|
||||
{
|
||||
fx_assembly *assembly = NULL;
|
||||
fx_value_get_object(&asm_v, &assembly);
|
||||
fx_iterator *types = fx_assembly_get_types(assembly);
|
||||
fx_foreach(v, types)
|
||||
{
|
||||
fx_type *ty = NULL;
|
||||
fx_value_get_object(&v, &ty);
|
||||
fx_type_flags ty_flags = fx_type_get_flags(ty);
|
||||
bool is_abstract = (ty_flags & FX_TYPE_F_ABSTRACT) != 0;
|
||||
if (is_abstract) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bshell_command_class *cmd = fx_type_get_interface(
|
||||
ty,
|
||||
BSHELL_TYPE_COMMAND);
|
||||
if (!cmd) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fx_value callable = FX_VALUE_OBJECT(
|
||||
fx_object_create(fx_type_get_id(ty)));
|
||||
bshell_pipeline_write_value(pipeline, callable, false);
|
||||
fx_value_unset(&callable);
|
||||
}
|
||||
|
||||
fx_iterator_unref(types);
|
||||
}
|
||||
|
||||
fx_iterator_unref(assemblies);
|
||||
p->c_eof = true;
|
||||
|
||||
return BSHELL_SUCCESS;
|
||||
}
|
||||
|
||||
static enum bshell_status end_processing(bshell_cmdlet *cmdlet)
|
||||
{
|
||||
struct bshell_get_command_p *p
|
||||
= fx_object_get_private(cmdlet, BSHELL_TYPE_GET_COMMAND);
|
||||
|
||||
return BSHELL_SUCCESS;
|
||||
}
|
||||
|
||||
static void init(fx_object *obj, void *priv)
|
||||
{
|
||||
}
|
||||
|
||||
FX_TYPE_CLASS_BEGIN(bshell_get_command)
|
||||
FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
|
||||
FX_INTERFACE_ENTRY(to_string) = NULL;
|
||||
FX_TYPE_VTABLE_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
|
||||
|
||||
FX_TYPE_VTABLE_INTERFACE_BEGIN(bshell_cmdlet, BSHELL_TYPE_CMDLET)
|
||||
FX_INTERFACE_ENTRY(c_verb) = BSHELL_VERB_GET;
|
||||
FX_INTERFACE_ENTRY(c_noun) = "Command";
|
||||
FX_TYPE_VTABLE_INTERFACE_END(bshell_cmdlet, BSHELL_TYPE_CMDLET)
|
||||
|
||||
FX_TYPE_VTABLE_INTERFACE_BEGIN(bshell_command, BSHELL_TYPE_COMMAND)
|
||||
FX_INTERFACE_ENTRY(c_begin_processing) = begin_processing;
|
||||
FX_INTERFACE_ENTRY(c_process_record) = process_record;
|
||||
FX_INTERFACE_ENTRY(c_end_processing) = end_processing;
|
||||
FX_TYPE_VTABLE_INTERFACE_END(bshell_cmdlet, BSHELL_TYPE_CMDLET)
|
||||
FX_TYPE_CLASS_END(bshell_get_command)
|
||||
|
||||
FX_TYPE_DEFINITION_BEGIN(bshell_get_command)
|
||||
FX_TYPE_ID(0x4f862cc3, 0xf3d3, 0x4f04, 0xb68e, 0x8764079f03c4);
|
||||
FX_TYPE_NAME("bshell.core.get_command");
|
||||
FX_TYPE_EXTENDS(BSHELL_TYPE_CMDLET);
|
||||
FX_TYPE_CLASS(bshell_get_command_class);
|
||||
FX_TYPE_INSTANCE_INIT(init);
|
||||
FX_TYPE_INSTANCE_PRIVATE(struct bshell_get_command_p);
|
||||
FX_TYPE_DEFINITION_END(bshell_get_command)
|
||||
@@ -0,0 +1,110 @@
|
||||
#include <bshell/command/cmdlet.h>
|
||||
#include <bshell/command/command.h>
|
||||
#include <bshell/runtime/pipeline.h>
|
||||
#include <bshell/status.h>
|
||||
#include <fx/reflection/function.h>
|
||||
#include <fx/string.h>
|
||||
#include <fx/vector.h>
|
||||
|
||||
#define BSHELL_TYPE_GET_VERB (bshell_get_verb_get_type())
|
||||
|
||||
fx_type_id bshell_get_verb_get_type(void);
|
||||
|
||||
FX_DECLARE_TYPE(bshell_get_verb);
|
||||
|
||||
FX_TYPE_CLASS_DECLARATION_BEGIN(bshell_get_verb)
|
||||
FX_TYPE_CLASS_DECLARATION_END(bshell_get_verb)
|
||||
|
||||
struct bshell_get_verb_p {
|
||||
fx_hashtable *c_verbs;
|
||||
fx_iterator *c_it;
|
||||
};
|
||||
|
||||
static enum bshell_status begin_processing(bshell_cmdlet *cmdlet)
|
||||
{
|
||||
struct bshell_get_verb_p *p
|
||||
= fx_object_get_private(cmdlet, BSHELL_TYPE_GET_VERB);
|
||||
p->c_verbs = bshell_get_all_verbs();
|
||||
p->c_it = fx_iterator_begin(p->c_verbs);
|
||||
return BSHELL_SUCCESS;
|
||||
}
|
||||
|
||||
static enum bshell_status process_record(
|
||||
bshell_cmdlet *cmdlet,
|
||||
bshell_pipeline *pipeline,
|
||||
struct bshell_runtime *rt)
|
||||
{
|
||||
struct bshell_get_verb_p *p
|
||||
= fx_object_get_private(cmdlet, BSHELL_TYPE_GET_VERB);
|
||||
|
||||
do {
|
||||
fx_value v = fx_iterator_get_value(p->c_it);
|
||||
if (!v.v_type) {
|
||||
return BSHELL_SUCCESS;
|
||||
}
|
||||
|
||||
fx_hashtable_item *item = NULL;
|
||||
fx_value_get_object(&v, &item);
|
||||
|
||||
v = fx_hashtable_item_get_value(item);
|
||||
|
||||
bshell_verb *verb = NULL;
|
||||
fx_value_get_object(&v, &verb);
|
||||
fx_iterator_move_next(p->c_it);
|
||||
|
||||
if (bshell_verb_is_reserved(verb)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bshell_verb_ref(verb);
|
||||
bshell_pipeline_write_value(
|
||||
pipeline,
|
||||
fx_value_copy_return(fx_hashtable_item_get_value(item)),
|
||||
false);
|
||||
break;
|
||||
} while (1);
|
||||
|
||||
return BSHELL_SUCCESS;
|
||||
}
|
||||
|
||||
static enum bshell_status end_processing(bshell_cmdlet *cmdlet)
|
||||
{
|
||||
struct bshell_get_verb_p *p
|
||||
= fx_object_get_private(cmdlet, BSHELL_TYPE_GET_VERB);
|
||||
if (p->c_it) {
|
||||
fx_iterator_unref(p->c_it);
|
||||
p->c_it = NULL;
|
||||
}
|
||||
|
||||
return BSHELL_SUCCESS;
|
||||
}
|
||||
|
||||
static void init(fx_object *obj, void *priv)
|
||||
{
|
||||
}
|
||||
|
||||
FX_TYPE_CLASS_BEGIN(bshell_get_verb)
|
||||
FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
|
||||
FX_INTERFACE_ENTRY(to_string) = NULL;
|
||||
FX_TYPE_VTABLE_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
|
||||
|
||||
FX_TYPE_VTABLE_INTERFACE_BEGIN(bshell_cmdlet, BSHELL_TYPE_CMDLET)
|
||||
FX_INTERFACE_ENTRY(c_verb) = BSHELL_VERB_GET;
|
||||
FX_INTERFACE_ENTRY(c_noun) = "Verb";
|
||||
FX_TYPE_VTABLE_INTERFACE_END(bshell_cmdlet, BSHELL_TYPE_CMDLET)
|
||||
|
||||
FX_TYPE_VTABLE_INTERFACE_BEGIN(bshell_command, BSHELL_TYPE_COMMAND)
|
||||
FX_INTERFACE_ENTRY(c_begin_processing) = begin_processing;
|
||||
FX_INTERFACE_ENTRY(c_process_record) = process_record;
|
||||
FX_INTERFACE_ENTRY(c_end_processing) = end_processing;
|
||||
FX_TYPE_VTABLE_INTERFACE_END(bshell_cmdlet, BSHELL_TYPE_CMDLET)
|
||||
FX_TYPE_CLASS_END(bshell_get_verb)
|
||||
|
||||
FX_TYPE_DEFINITION_BEGIN(bshell_get_verb)
|
||||
FX_TYPE_ID(0xa47976a6, 0xf7d8, 0x447f, 0x887b, 0x6c5d78b7bd2e);
|
||||
FX_TYPE_NAME("bshell.core.get_verb");
|
||||
FX_TYPE_EXTENDS(BSHELL_TYPE_CMDLET);
|
||||
FX_TYPE_CLASS(bshell_get_verb_class);
|
||||
FX_TYPE_INSTANCE_INIT(init);
|
||||
FX_TYPE_INSTANCE_PRIVATE(struct bshell_get_verb_p);
|
||||
FX_TYPE_DEFINITION_END(bshell_get_verb)
|
||||
@@ -0,0 +1,140 @@
|
||||
#include <bshell/command/cmdlet.h>
|
||||
#include <bshell/command/command.h>
|
||||
#include <bshell/format.h>
|
||||
#include <bshell/runtime/pipeline.h>
|
||||
#include <bshell/status.h>
|
||||
#include <fx/collections/array.h>
|
||||
#include <fx/reflection/function.h>
|
||||
#include <fx/string.h>
|
||||
#include <fx/value-type.h>
|
||||
#include <fx/vector.h>
|
||||
|
||||
#define BSHELL_TYPE_WRITE_OUTPUT (bshell_write_output_get_type())
|
||||
|
||||
fx_type_id bshell_write_output_get_type(void);
|
||||
|
||||
FX_DECLARE_TYPE(bshell_write_output);
|
||||
|
||||
FX_TYPE_CLASS_DECLARATION_BEGIN(bshell_write_output)
|
||||
FX_TYPE_CLASS_DECLARATION_END(bshell_write_output)
|
||||
|
||||
struct bshell_write_output_p {
|
||||
struct bshell_table_ctx w_table_ctx;
|
||||
bool w_table_initialised;
|
||||
};
|
||||
|
||||
static void initialise_table(
|
||||
struct bshell_write_output_p *cmd,
|
||||
const fx_value *first_record)
|
||||
{
|
||||
bshell_table_ctx_init(&cmd->w_table_ctx, fx_stdout);
|
||||
const fx_type *ty = fx_type_get_by_id(first_record->v_type);
|
||||
bshell_table_ctx_prepare_columns_from_format(
|
||||
&cmd->w_table_ctx,
|
||||
ty,
|
||||
NULL);
|
||||
bshell_table_ctx_print_headers(&cmd->w_table_ctx);
|
||||
cmd->w_table_initialised = true;
|
||||
}
|
||||
|
||||
static bool value_requires_table(const fx_value *value)
|
||||
{
|
||||
if (fx_type_is_value_type(value->v_type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fx_value_is_type(value, FX_TYPE_STRING)
|
||||
|| fx_value_is_type(value, FX_TYPE_ARRAY)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void write_value(
|
||||
struct bshell_write_output_p *cmd,
|
||||
const fx_value *value)
|
||||
{
|
||||
if (!value_requires_table(value)) {
|
||||
fx_value_to_string(value, fx_stdout, NULL);
|
||||
fx_stream_write_char(fx_stdout, '\n');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cmd->w_table_initialised) {
|
||||
initialise_table(cmd, value);
|
||||
}
|
||||
|
||||
bshell_table_ctx_print_record(&cmd->w_table_ctx, value);
|
||||
}
|
||||
|
||||
static enum bshell_status begin_processing(bshell_cmdlet *cmdlet)
|
||||
{
|
||||
struct bshell_write_output_p *p
|
||||
= fx_object_get_private(cmdlet, BSHELL_TYPE_WRITE_OUTPUT);
|
||||
for (size_t i = 1;; i++) {
|
||||
const fx_value *v = bshell_command_get_arg(cmdlet, i);
|
||||
if (!v) {
|
||||
break;
|
||||
}
|
||||
|
||||
write_value(p, v);
|
||||
}
|
||||
|
||||
return BSHELL_SUCCESS;
|
||||
}
|
||||
|
||||
static enum bshell_status process_record(
|
||||
bshell_cmdlet *cmdlet,
|
||||
bshell_pipeline *pipeline,
|
||||
struct bshell_runtime *rt)
|
||||
{
|
||||
struct bshell_write_output_p *p
|
||||
= fx_object_get_private(cmdlet, BSHELL_TYPE_WRITE_OUTPUT);
|
||||
|
||||
fx_value in = bshell_pipeline_read_value(pipeline);
|
||||
if (fx_value_is_set(&in)) {
|
||||
write_value(p, &in);
|
||||
fx_value_unset(&in);
|
||||
}
|
||||
|
||||
return BSHELL_SUCCESS;
|
||||
}
|
||||
|
||||
static enum bshell_status end_processing(bshell_cmdlet *cmdlet)
|
||||
{
|
||||
struct bshell_write_output_p *p
|
||||
= fx_object_get_private(cmdlet, BSHELL_TYPE_WRITE_OUTPUT);
|
||||
|
||||
return BSHELL_SUCCESS;
|
||||
}
|
||||
|
||||
static void init(fx_object *obj, void *priv)
|
||||
{
|
||||
}
|
||||
|
||||
FX_TYPE_CLASS_BEGIN(bshell_write_output)
|
||||
FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
|
||||
FX_INTERFACE_ENTRY(to_string) = NULL;
|
||||
FX_TYPE_VTABLE_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
|
||||
|
||||
FX_TYPE_VTABLE_INTERFACE_BEGIN(bshell_cmdlet, BSHELL_TYPE_CMDLET)
|
||||
FX_INTERFACE_ENTRY(c_verb) = BSHELL_VERB_WRITE;
|
||||
FX_INTERFACE_ENTRY(c_noun) = "Output";
|
||||
FX_TYPE_VTABLE_INTERFACE_END(bshell_cmdlet, BSHELL_TYPE_CMDLET)
|
||||
|
||||
FX_TYPE_VTABLE_INTERFACE_BEGIN(bshell_command, BSHELL_TYPE_COMMAND)
|
||||
FX_INTERFACE_ENTRY(c_begin_processing) = begin_processing;
|
||||
FX_INTERFACE_ENTRY(c_process_record) = process_record;
|
||||
FX_INTERFACE_ENTRY(c_end_processing) = end_processing;
|
||||
FX_TYPE_VTABLE_INTERFACE_END(bshell_cmdlet, BSHELL_TYPE_CMDLET)
|
||||
FX_TYPE_CLASS_END(bshell_write_output)
|
||||
|
||||
FX_TYPE_DEFINITION_BEGIN(bshell_write_output)
|
||||
FX_TYPE_ID(0xf7f9c42d, 0xc053, 0x4ffc, 0xa8ec, 0x78fef4844ac0);
|
||||
FX_TYPE_NAME("bshell.core.write_output");
|
||||
FX_TYPE_EXTENDS(BSHELL_TYPE_CMDLET);
|
||||
FX_TYPE_CLASS(bshell_write_output_class);
|
||||
FX_TYPE_INSTANCE_INIT(init);
|
||||
FX_TYPE_INSTANCE_PRIVATE(struct bshell_write_output_p);
|
||||
FX_TYPE_DEFINITION_END(bshell_write_output)
|
||||
Reference in New Issue
Block a user