This commit is contained in:
2025-05-12 19:58:45 +08:00
parent 3377641ee3
commit 0411d8c19b
20 changed files with 3574 additions and 28 deletions

View File

@@ -0,0 +1,26 @@
set(TOOL_NAME dsviewer)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
find_package(PkgConfig)
pkg_search_module(EDITLINE REQUIRED libeditline)
include_directories(${EDITLINE_INCLUDE_DIRS})
link_directories(${EDITLINE_LIBRARY_DIRS})
aux_source_directory(. TOOL_SRC)
add_executable(${TOOL_NAME} ${TOOL_SRC})
set_target_properties(${TOOL_NAME} PROPERTIES INSTALL_RPATH /usr/local/lib)
set_target_properties(${TOOL_NAME} PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON)
target_link_libraries(${TOOL_NAME} PRIVATE gctl)
target_link_libraries(${TOOL_NAME} PRIVATE ${EDITLINE_LIBRARIES})
install(TARGETS ${TOOL_NAME} RUNTIME DESTINATION sbin)
file(GLOB HELP_DOC *.md)
install(FILES ${HELP_DOC} DESTINATION sbin/share)

614
dsviewer/dsviewer.cpp Normal file
View File

@@ -0,0 +1,614 @@
/********************************************************
* ██████╗ ██████╗████████╗██╗
* ██╔════╝ ██╔════╝╚══██╔══╝██║
* ██║ ███╗██║ ██║ ██║
* ██║ ██║██║ ██║ ██║
* ╚██████╔╝╚██████╗ ██║ ███████╗
* ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝
* Geophysical Computational Tools & Library (GCTL)
*
* Copyright (c) 2023 Yi Zhang (yizhang-geo@zju.edu.cn)
*
* GCTL is distributed under a dual licensing scheme. You can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 2
* of the License, or (at your option) any later version. You should have
* received a copy of the GNU Lesser General Public License along with this
* program. If not, see <http://www.gnu.org/licenses/>.
*
* If the terms and conditions of the LGPL v.2. would prevent you from using
* the GCTL, please consider the option to obtain a commercial license for a
* fee. These licenses are offered by the GCTL's original author. As a rule,
* licenses are provided "as-is", unlimited in time for a one time fee. Please
* send corresponding requests to: yizhang-geo@zju.edu.cn. Please do not forget
* to include some description of your company and the realm of its activities.
* Also add information on how to contact you by electronic and paper mail.
******************************************************/
#include "dsviewer.h"
// We use the editline library to handle all inputs
#include "editline.h"
// install configuration
#include "../gctl_toolkits_config.h"
cmd_pair curr_cmd; // Executing command
gctl::dsv_io tc; // Grid object
extern "C" {
/*
* Strip whitespace from the start and end of STRING. Return a pointer
* into STRING.
*/
char *stripwhite(char *string)
{
char *s, *t;
for (s = string; isspace(*s); s++) ;
if (*s == 0)
return s;
t = s + strlen(s) - 1;
while (t > s && isspace(*t))
t--;
*++t = '\0';
return s;
}
/* Generator function for command completion. STATE lets us
know whether to start from scratch; without any state
(i.e. STATE == 0), then we start at the top of the list. */
char *command_generator(const char *text, int state)
{
static int list_index, len;
/* If this is a new word to complete, initialize now. This
includes saving the length of TEXT for efficiency, and
initializing the index variable to 0. */
if (!state)
{
list_index = 0;
len = strlen(text);
}
/* Return the next name which partially matches from the command list. */
while (list_index < CMD_NUM)
{
if (std::string(text) == commands[list_index].name.substr(0, len))
{
//const char* name = commands[list_index].name.data();
return strdup(commands[list_index].name.data());
}
else list_index++;
}
/* If no names matched, then return NULL. */
return nullptr;
}
/*
* Attempt to complete on the contents of TEXT. START and END
* bound the region of rl_line_buffer that contains the word to
* complete. TEXT is the word to complete. We can use the entire
* contents of rl_line_buffer in case we want to do some simple
* parsing. Return the array of matches, or NULL if there aren't any.
*/
char **dsviewer_completion(const char *text, int start, int end)
{
char **matches = nullptr;
/* If this word is at the start of the line, then it is a command
to complete. Otherwise it is the name of a file in the current
directory. */
if (start == 0) matches = rl_completion_matches(text, command_generator);
return matches;
}
void initialize_readline(void)
{
/* Allow conditional parsing of the ~/.inputrc file. */
rl_readline_name = "dsviewer";
/* Tell the completer that we want a crack first. */
rl_attempted_completion_function = dsviewer_completion;
}
} // End C section
void display_cmds()
{
std::clog << "Command:\n";
for (size_t i = 0; i < CMD_NUM - 1; i++)
{
std::clog << std::setw(12) << commands[i].name << ":\t" << commands[i].brief << "\n";
}
std::clog << "\nEnter \"<command>?\" to see detailed instructions.\n";
std::clog << "\nCmdFile:\n";
std::clog << "Each line of the input file(s) will be parsed as a command.\nEmpty lines and lines start with '#' will be skipped.\n";
std::clog << "\nHereDoc:\n";
std::clog << "You can use HereDoc to input commands. A simple example is:\n";
std::clog << "dsviewer << EOF\n";
std::clog << "open file1.csv\n";
std::clog << "info\n";
std::clog << "EOF\n";
return;
}
void display_help(std::string input_cmd)
{
std::string install_dir = GCTL_TOOLKITS_INSTALL_PREFIX;
std::ifstream helpin;
open_infile(helpin, install_dir + "/sbin/share/dsviewer", ".md");
std::string tmp_l, tmp_help;
std::vector<std::string> cmds;
std::vector<std::string> helps;
while (getline(helpin, tmp_l))
{
if (tmp_l.substr(0, 4) == "####")
{
cmds.push_back(tmp_l.substr(5));
tmp_help = "";
while (getline(helpin, tmp_l))
{
if (tmp_l == "") break;
else tmp_help += tmp_l + "\n";
}
helps.push_back(tmp_help);
}
}
helpin.close();
std::string cmd_str;
for (size_t j = 0; j < cmds.size(); j++)
{
parse_string_to_value(cmds[j], ' ', true, cmd_str);
if (input_cmd == cmd_str)
{
replace_all(tmp_l, cmds[j], "\\", "");
std::cout << GCTL_BOLDGREEN << tmp_l << GCTL_RESET << "\n";
std::cout << helps[j] << "\n";
break;
}
}
return;
}
void exec_cmd(std::string cmd)
{
std::string cmd_name;
parse_string_to_value(cmd, ' ', true, cmd_name);
// show instruction if there is a question mark at end of the command
if (cmd_name.back() == '?')
{
cmd_name = cmd_name.substr(0, cmd_name.length() - 1);
display_help(cmd_name);
return;
}
// set default command to null
curr_cmd = commands[CMD_NUM - 1];
for (size_t i = 0; i < CMD_NUM - 1; i++)
{
if (cmd_name == commands[i].name)
{
curr_cmd = commands[i]; break;
}
}
if (curr_cmd.func_p == nullptr) throw gctl::runtime_error("Invalid command: " + cmd_name);
std::vector<std::string> cmd_units;
parse_string_with_quotes(cmd, cmd_units);
return curr_cmd.func_p(cmd_units);
}
// This function is defined to avoid potential breakdown while running in script mode.
void quit(const std::vector<std::string> &cmd_units)
{
return;
}
void info(const std::vector<std::string> &cmd_units)
{
std::smatch ret;
std::regex pata("att"), patt("tag"), patc("col"), patr("row"), path("hdr");
// info [att|tag|hdr|col|row]
int info_code = 0;
if (cmd_units.size() > 1)
{
if (regex_search(cmd_units[1], ret, pata)) info_code = AttInfo;
if (regex_search(cmd_units[1], ret, patt)) info_code = info_code|TagInfo;
if (regex_search(cmd_units[1], ret, patc)) info_code = info_code|ColInfo;
if (regex_search(cmd_units[1], ret, patr)) info_code = info_code|RowInfo;
if (regex_search(cmd_units[1], ret, path)) info_code = info_code|HeadInfo;
tc.info(info_code);
}
else tc.info(ColInfo);
return;
}
void head(const std::vector<std::string> &cmd_units)
{
// head [number]
int h = 10;
if (cmd_units.size() > 1) h = atoi(cmd_units[1].c_str());
if (h <= 0) throw std::runtime_error("head: invalid number.");
_1s_vector cnames = tc.column_names();
display_vector(cnames, std::cout, tc.delimeter());
_1s_array line;
for (size_t i = 1; i <= h; i++)
{
tc.get_row(line, i);
line.show(std::cout, tc.delimeter());
}
return;
}
void tail(const std::vector<std::string> &cmd_units)
{
// tail [number]
int h = 10;
if (cmd_units.size() > 1) h = atoi(cmd_units[1].c_str());
if (h <= 0) throw std::runtime_error("tail: invalid number.");
_1s_vector cnames = tc.column_names();
display_vector(cnames, std::cout, tc.delimeter());
_1s_array line;
for (size_t i = tc.row_number() - h + 1; i <= tc.row_number(); i++)
{
tc.get_row(line, i);
line.show(std::cout, tc.delimeter());
}
return;
}
void set_enable(const std::vector<std::string> &cmd_units)
{
// enable table|column|row [<name1>,<name2>...]
if (cmd_units.size() < 2) throw std::runtime_error("enable: insufficient parameters.");
if (cmd_units[1] == "table") tc.table_output(Enable);
else if (cmd_units[1] == "column")
{
for (size_t i = 2; i < cmd_units.size(); i++)
{
tc.column_output(cmd_units[i], Enable);
}
}
else if (cmd_units[1] == "row")
{
for (size_t i = 2; i < cmd_units.size(); i++)
{
tc.row_output(cmd_units[i], Enable);
}
}
else throw std::runtime_error("enable: invalid parameters.");
return;
}
void set_disable(const std::vector<std::string> &cmd_units)
{
// disable table|column|row [<name1>,<name2>...]
if (cmd_units.size() < 2) throw std::runtime_error("disable: insufficient parameters.");
if (cmd_units[1] == "table") tc.table_output(Disable);
else if (cmd_units[1] == "column")
{
for (size_t i = 2; i < cmd_units.size(); i++)
{
tc.column_output(cmd_units[i], Disable);
}
}
else if (cmd_units[1] == "row")
{
for (size_t i = 2; i < cmd_units.size(); i++)
{
tc.row_output(cmd_units[i], Disable);
}
}
else throw std::runtime_error("disable: invalid parameters.");
return;
}
void load_file(const std::vector<std::string> &cmd_units)
{
// load <file> [nohead|column|row|both] [head_num] [<delimeter>] [att_sym] [tag_sym]
if (cmd_units.size() < 2) throw std::runtime_error("open: insufficient parameters.");
gctl::array<std::string> copy_str(5, "null");
for (size_t i = 0; i < GCTL_MIN(cmd_units.size() - 2, 5); i++)
{
copy_str[i] = cmd_units[i + 2];
}
int ht = NoHead;
if (copy_str[0] == "nohead") ht = NoHead;
else if (copy_str[0] == "column") ht = ColHead;
else if (copy_str[0] == "row") ht = RowHead;
else if (copy_str[0] == "both") ht = RowHead|ColHead;
int hnum = 0;
if (copy_str[1] != "null") hnum = atoi(copy_str[1].c_str());
if (hnum != 0) tc.head_number(hnum);
if (copy_str[2] != "null") tc.delimeter(copy_str[2][0]);
if (copy_str[3] != "null") tc.annotation_symbol(copy_str[3][0]);
if (copy_str[4] != "null") tc.tag_symbol(copy_str[4][0]);
std::string naked_name, exten_name;
parse_filename(cmd_units[1], naked_name, exten_name);
if (exten_name == ".csv") tc.load_csv(naked_name);
else tc.load_text(naked_name, exten_name, ht);
return;
}
void save_file(const std::vector<std::string> &cmd_units)
{
// save <file> [<delimeter>] [att_sym] [tag_sym]
if (cmd_units.size() < 2) throw std::runtime_error("save: insufficient parameters.");
gctl::array<std::string> copy_str(3, "null");
for (size_t i = 0; i < GCTL_MIN(cmd_units.size() - 2, 3); i++)
{
copy_str[i] = cmd_units[i + 2];
}
if (copy_str[0] != "null") tc.delimeter(copy_str[0][0]);
if (copy_str[1] != "null") tc.annotation_symbol(copy_str[1][0]);
if (copy_str[2] != "null") tc.tag_symbol(copy_str[2][0]);
std::string naked_name, exten_name;
parse_filename(cmd_units[1], naked_name, exten_name);
if (exten_name == ".csv") tc.save_csv(naked_name);
else tc.save_text(naked_name, exten_name);
return;
}
void statistic(const std::vector<std::string> &cmd_units)
{
// stats <column> <column>...
if (cmd_units.size() < 2) throw std::runtime_error("stats: insufficient parameters.");
_1d_array data;
for (size_t i = 1; i < cmd_units.size(); i++)
{
tc.get_column(data, cmd_units[i]);
std::clog << "column: " << cmd_units[i]
<< " | " << data.min() << "/" << data.mean() << "/" << data.max()
<< " | STD: " << data.std() << "\n";
}
return;
}
void set_type(const std::vector<std::string> &cmd_units)
{
// type row|col int|float|string <name>
if (cmd_units.size() < 4) throw std::runtime_error("type: insufficient parameters.");
if (cmd_units[1] == "row")
{
if (cmd_units[2] == "int") tc.row_type(Int, cmd_units[3]);
else if (cmd_units[2] == "float") tc.row_type(Float, cmd_units[3]);
else if (cmd_units[2] == "string") tc.row_type(String, cmd_units[3]);
else throw std::runtime_error("type: invalid parameters.");
}
else if (cmd_units[1] == "col")
{
if (cmd_units[2] == "int") tc.column_type(Int, cmd_units[3]);
else if (cmd_units[2] == "float") tc.column_type(Float, cmd_units[3]);
else if (cmd_units[2] == "string") tc.column_type(String, cmd_units[3]);
else throw std::runtime_error("type: invalid parameters.");
}
else throw std::runtime_error("type: invalid parameters.");
return;
}
void set_titles(const std::vector<std::string> &cmd_units)
{
// title <row|col> <t1>,<t2>,<t3>,... [<id1>,<id2>,<id3>,...]
if (cmd_units.size() < 3) throw std::runtime_error("title: insufficient parameters.");
if (cmd_units[1] == "row")
{
std::vector<std::string> row_titles;
std::vector<int> row_ids;
parse_string_to_vector(cmd_units[2], ',', row_titles);
if (cmd_units.size() >= 4)
{
parse_string_to_vector(cmd_units[3], ',', row_ids);
if (row_titles.size() != row_ids.size()) throw std::runtime_error("title: invalid parameters.");
tc.row_names(row_titles, row_ids);
}
else tc.row_names(row_titles);
}
else if (cmd_units[1] == "col")
{
std::vector<std::string> col_titles;
std::vector<int> col_ids;
parse_string_to_vector(cmd_units[2], ',', col_titles);
if (cmd_units.size() >= 4)
{
parse_string_to_vector(cmd_units[3], ',', col_ids);
if (col_titles.size()!= col_ids.size()) throw std::runtime_error("title: invalid parameters.");
tc.column_names(col_titles, col_ids);
}
else tc.column_names(col_titles);
}
else throw std::runtime_error("title: invalid parameters.");
return;
}
void math_func(const std::vector<std::string> &cmd_units)
{
// math <func> <col1>,<col2>,<col3>...
if (cmd_units.size() < 3) throw std::runtime_error("math: insufficient parameters.");
std::vector<std::string> col_names;
parse_string_to_vector(cmd_units[2], ',', col_names);
tc.cal_column(cmd_units[1], col_names, 12);
return;
}
void rand_data(const std::vector<std::string> &cmd_units)
{
// random normal|uniform <p1> <p2> [<colname>]
if (cmd_units.size() < 4) throw std::runtime_error("random: insufficient parameters.");
random_type_e rd_type = RdNormal;
if (cmd_units[1] == "normal") rd_type = RdNormal;
else if (cmd_units[1] == "uniform") rd_type = RdUniform;
else throw std::runtime_error("random: invalid parameters.");
double p1 = atof(cmd_units[2].c_str());
double p2 = atof(cmd_units[3].c_str());
array<double> rd_data(tc.row_number());
rd_data.random_float(p1, p2, rd_type);
if (cmd_units.size() >= 5) tc.fill_column(rd_data, cmd_units[4], 12);
else
{
std::string col_name = "RdData";
tc.add_column(col_name);
tc.fill_column(rd_data, col_name, 12);
}
return;
}
void filt_data(const std::vector<std::string> &cmd_units)
{
// filter row|col regex|math <expression> <name1>,<name2>,<name3>...
if (cmd_units.size() < 5) throw std::runtime_error("filter: insufficient parameters.");
std::vector<std::string> tar_names;
parse_string_to_vector(cmd_units[4], ',', tar_names);
table_headtype_e thead;
if (cmd_units[1] == "row") thead = RowHead;
else if (cmd_units[1] == "col") thead = ColHead;
else throw std::runtime_error("filter: invalid parameters.");
if (cmd_units[2] == "regex") tc.filter(cmd_units[3], tar_names[0], thead);
else if (cmd_units[2] == "math") tc.filter(cmd_units[3], tar_names, thead);
else throw std::runtime_error("filter: invalid parameters.");
return;
}
void insert_data(const std::vector<std::string> &cmd_units)
{
// insert row|col [<new-name>] [<insert-name>]
if (cmd_units.size() < 2) throw std::runtime_error("insert: insufficient parameters.");
if (cmd_units[1] == "row")
{
if (cmd_units.size() == 2) tc.add_row();
else if (cmd_units.size() == 3) tc.add_row(cmd_units[2]);
else if (cmd_units.size() == 4) tc.add_row(cmd_units[2], cmd_units[3]);
}
else if (cmd_units[1] == "col")
{
if (cmd_units.size() == 2) tc.add_column();
else if (cmd_units.size() == 3) tc.add_column(cmd_units[2]);
else if (cmd_units.size() == 4) tc.add_column(cmd_units[2], cmd_units[3]);
}
else throw std::runtime_error("insert: invalid parameters.");
return;
}
void set_data(const std::vector<std::string> &cmd_units)
{
// set row|col \<name\> \<value\>
if (cmd_units.size() < 4) throw std::runtime_error("set: insufficient parameters.");
if (cmd_units[1] == "row")
{
_1s_array row_data(tc.row_number(), cmd_units[3]);
tc.fill_row(row_data, cmd_units[2]);
}
else if (cmd_units[1] == "col")
{
_1s_array col_data(tc.col_number(), cmd_units[3]);
tc.fill_column(col_data, cmd_units[2]);
}
else throw std::runtime_error("set: invalid parameters.");
return;
}
void display_table(const std::vector<std::string> &cmd_units)
{
// view
tc.display();
return;
}
int main(int argc, char *argv[])
{
if (argc >= 2)
{
std::string tmp_l;
std::ifstream cmdin;
// Run commands from files. Each line is a command.
// You can give more than one file
for (size_t i = 1; i < argc; i++) try
{
open_infile(cmdin, argv[i]);
while (getline(cmdin, tmp_l) && tmp_l != "" && tmp_l[0] != '#')
{
exec_cmd(tmp_l);
}
cmdin.close();
}
catch(std::exception& e)
{
GCTL_ShowWhatError(e.what(), GCTL_ERROR_ERROR, 0, "run dsviewer in the interactive mode for instructions.", 0);
}
}
else
{
setlocale(LC_CTYPE, "");
initialize_readline(); /* Bind our completer. */
display_logo();
std::clog << "dsviewer - read, manipulate and write dsv/csv files.\n";
std::clog << "Usage: dsviewer [<cmdfile1> <cmdfile2>...]\n";
std::clog << "Enter '?' to see all available commands.\n";
std::string cmd_str;
char *c_line = (char *)NULL;
char *c_line_s = (char *)NULL;
bool quit = false;
while (!quit) try
{
c_line = readline(">> ");
if (!c_line) break;
c_line_s = stripwhite(c_line);
cmd_str = c_line_s;
if (cmd_str == "quit") quit = true;
else if (cmd_str == "?") display_cmds();
else exec_cmd(cmd_str);
free(c_line);
}
catch(std::exception& e)
{
GCTL_ShowWhatError(e.what(), GCTL_ERROR_ERROR, 0, "Enter 'help' for instructions.", 0);
}
}
return 0;
}

86
dsviewer/dsviewer.h Normal file
View File

@@ -0,0 +1,86 @@
/********************************************************
* ██████╗ ██████╗████████╗██╗
* ██╔════╝ ██╔════╝╚══██╔══╝██║
* ██║ ███╗██║ ██║ ██║
* ██║ ██║██║ ██║ ██║
* ╚██████╔╝╚██████╗ ██║ ███████╗
* ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝
* Geophysical Computational Tools & Library (GCTL)
*
* Copyright (c) 2023 Yi Zhang (yizhang-geo@zju.edu.cn)
*
* GCTL is distributed under a dual licensing scheme. You can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 2
* of the License, or (at your option) any later version. You should have
* received a copy of the GNU Lesser General Public License along with this
* program. If not, see <http://www.gnu.org/licenses/>.
*
* If the terms and conditions of the LGPL v.2. would prevent you from using
* the GCTL, please consider the option to obtain a commercial license for a
* fee. These licenses are offered by the GCTL's original author. As a rule,
* licenses are provided "as-is", unlimited in time for a one time fee. Please
* send corresponding requests to: yizhang-geo@zju.edu.cn. Please do not forget
* to include some description of your company and the realm of its activities.
* Also add information on how to contact you by electronic and paper mail.
******************************************************/
#ifndef GCTL_DSVIEWER_H
#define GCTL_DSVIEWER_H
#include <regex>
#include "gctl/io.h"
using namespace gctl;
// Function pointer for commands
typedef void (*cmd_func_ptr)(const std::vector<std::string> &cmd_units);
struct cmd_pair
{
std::string name;
cmd_func_ptr func_p;
std::string brief;
};
void quit(const std::vector<std::string> &cmd_units);
void info(const std::vector<std::string> &cmd_units);
void head(const std::vector<std::string> &cmd_units);
void tail(const std::vector<std::string> &cmd_units);
void load_file(const std::vector<std::string> &cmd_units);
void save_file(const std::vector<std::string> &cmd_units);
void statistic(const std::vector<std::string> &cmd_units);
void set_enable(const std::vector<std::string> &cmd_units);
void set_disable(const std::vector<std::string> &cmd_units);
void set_type(const std::vector<std::string> &cmd_units);
void set_titles(const std::vector<std::string> &cmd_units);
void math_func(const std::vector<std::string> &cmd_units);
void rand_data(const std::vector<std::string> &cmd_units);
void filt_data(const std::vector<std::string> &cmd_units);
void insert_data(const std::vector<std::string> &cmd_units);
void set_data(const std::vector<std::string> &cmd_units);
void display_table(const std::vector<std::string> &cmd_units);
#define CMD_NUM 18
const cmd_pair commands[CMD_NUM] = {
{"quit", quit, "Quit the program."},
{"view", display_table, "Display valid cells."},
{"info", info, "Show the table information."},
{"head", head, "Show head line(s) of the table."},
{"tail", tail, "Show tail line(s) of the table."},
{"open", load_file, "Open a dsv/csv file."},
{"save", save_file, "Save the table to a file."},
{"stats", statistic, "Calculate statistics of the selected columns."},
{"enable", set_enable, "Enable column/row outputs by name or index."},
{"disable", set_disable, "Disable column/row outputs by name or index."},
{"insert", insert_data, "Insert a new column/row data."},
{"set", set_data, "Set a column/row data."},
{"type", set_type, "Set column/row data types."},
{"title", set_titles, "Set row and column titles."},
{"math", math_func, "Preform mathematic operations of column data."},
{"random", rand_data, "Generate random column data."},
{"filter", filt_data, "Filter row and column data using regex and mathematic expressions."},
{"null", nullptr, "null"}
};
#endif // GCTL_DSVIEWER_H

47
dsviewer/dsviewer.md Normal file
View File

@@ -0,0 +1,47 @@
#### quit
Does what it says.
#### info [att|tag|hdr|col|row]
Show the table information. 'att' shows the annotations, 'tag' shows the tag lines, 'hdr' shows the head lines, 'col' shows the columns' summary, and 'row' shows the rows' summary. Use '|' to separate multiple options.
#### head
Show the first `n` (the default is 10) rows of the table.
#### tail
Show the last `n` (the default is 10) rows of the table.
#### open \<file\> [nohead|column|row|both] [\<head_num\>] [\<deli-sym\>] [\<att-sym\>] [\<tag-sym\>]
Open a dsv/csv file. The default setups are 'nohead', space for delimeter, '#' for annotations, and '!' for tags. If the file name ends with '.csv', the default delimeter is ','.
#### save \<file\> [\<delimeter\>] [\<att-sym\>] [\<tag-sym\>]
Save table to a dsv/csv file. The default setups are space for delimeter, '#' for annotations, and '!' for tags. If the file name ends with '.csv', the default delimeter is ','.
#### stats \<colname1\> \<colname2\> ...
Show statistics of a data column or columns. If the input file has no column names, use inbuilt names `C<id>` to select the columns.
#### enable table|column|row [\<name1\> \<name2\> ...]
Enable table outputs. If the input file has no row or column names, use inbuilt names `R<id>` and `C<id>` to select the rows and columns.
#### disable table|column|row [\<name1\> \<name2\> ...]
Disable table outputs. If the input file has no row or column names, use inbuilt names `R<id>` and `C<id>` to select the rows and columns.
#### insert row|col [\<new-name\>] [\<insert-name\>]
Insert a new row or column. The new row or column will be attached to the end of the table by default. A `new-name` can be provided if the user wants to rename the new row or column. Provide the `insert-name` to insert the new row or column at the specified row or column. The remaining columns or rows will be moved one step right or down accordingly. If the input file has no row or column names, use inbuilt names `R<id>` and `C<id>` to select the rows and columns.
#### set row|col \<name\> \<value\>
Set a row or column's value to the given one. If the input file has no row or column names, use inbuilt names `R<id>` and `C<id>` to select the rows and columns.
#### type row|col int|float|string \<name\>
Set the data type of a row or column. If the input file has no row or column names, use inbuilt names `R<id>` and `C<id>` to select the rows and columns.
#### title row|col \<t1\>,\<t2\>,\<t3\>,... [\<id1\>,\<id2\>,\<id3\>,...]
Set row and column titles. The titles will be assigned sequentially if no index is specified.
#### math \<func\> \<col1\>,\<col2\>,\<col3\>...
Preform mathematic operations of column data. The user needs to write a mathematical expression using the column names as variables. Then provide the column names as the arguments, in which the resultant column's name must be placed at the beginning. For example, to calculate the sum of column `C1` and `C2`, and store the result in column `C3`, the command is: `math C3=C1+C2 C3,C1,C2`.
#### random normal|uniform \<p1\> \<p2\> [\<colname\>]
Generate random data using normal or uniform distribution. The first parameter is the mean or the lower bound, and the second parameter is the standard deviation or the upper bound. If no column name is provided, a new column will be created (titled "RdData").
#### filter row|col regex|math \<expression\> \<name1\>,\<name2\>,\<name3\>...
Filter row and column data using regex and mathematic expressions. The first parameter is the expression, and the following parameters are the column names. For example, to filter rows whose column `C1` is greater than 0, the command is: `filter col math C1>0 C1`. Regex expression can be used to filter rows whose column `C1` contains the string "abc", the command is: `filter col regex abc C1`.

11
dsviewer/example.csv Normal file
View File

@@ -0,0 +1,11 @@
Name,Age,Gender,Occupation,City,Phone Number,Email,Annual Income,Company,Position
John Doe,28,Male,Engineer,New York,123-456-7890,john.doe@example.com,$75000,ABC Tech,Senior Software Engineer
Jane Smith,34,Female,Teacher,Los Angeles,234-567-8901,jane.smith@example.com,$55000,XYZ School,Math Teacher
Michael Brown,22,Male,Student,Toronto,345-678-9012,michael.brown@example.com,$18000,University of Toronto,Undergraduate Student
Emily Davis,45,Female,Doctor,Chicago,456-789-0123,emily.davis@example.com,$180000,Chicago Medical Center,Cardiologist
David Wilson,30,Male,Designer,San Francisco,567-890-1234,david.wilson@example.com,$90000,DesignWorks,Senior Graphic Designer
Sarah Johnson,29,Female,Marketing Specialist,Seattle,678-901-2345,sarah.johnson@example.com,$85000,MarketingPro,Marketing Manager
Robert Lee,36,Male,Software Developer,Boston,789-012-3456,robert.lee@example.com,$120000,SoftDev Solutions,Lead Developer
Laura Miller,25,Female,Graphic Designer,Denver,890-123-4567,laura.miller@example.com,$60000,Creative Arts,Junior Designer
William Clark,40,Male,Consultant,Atlanta,901-234-5678,william.clark@example.com,$110000,ConsultPro,Business Consultant
Olivia Turner,33,Female,Researcher,Phoenix,012-345-6789,olivia.turner@example.com,$70000,ResearchInnovate,Research Scientist
1 Name Age Gender Occupation City Phone Number Email Annual Income Company Position
2 John Doe 28 Male Engineer New York 123-456-7890 john.doe@example.com $75000 ABC Tech Senior Software Engineer
3 Jane Smith 34 Female Teacher Los Angeles 234-567-8901 jane.smith@example.com $55000 XYZ School Math Teacher
4 Michael Brown 22 Male Student Toronto 345-678-9012 michael.brown@example.com $18000 University of Toronto Undergraduate Student
5 Emily Davis 45 Female Doctor Chicago 456-789-0123 emily.davis@example.com $180000 Chicago Medical Center Cardiologist
6 David Wilson 30 Male Designer San Francisco 567-890-1234 david.wilson@example.com $90000 DesignWorks Senior Graphic Designer
7 Sarah Johnson 29 Female Marketing Specialist Seattle 678-901-2345 sarah.johnson@example.com $85000 MarketingPro Marketing Manager
8 Robert Lee 36 Male Software Developer Boston 789-012-3456 robert.lee@example.com $120000 SoftDev Solutions Lead Developer
9 Laura Miller 25 Female Graphic Designer Denver 890-123-4567 laura.miller@example.com $60000 Creative Arts Junior Designer
10 William Clark 40 Male Consultant Atlanta 901-234-5678 william.clark@example.com $110000 ConsultPro Business Consultant
11 Olivia Turner 33 Female Researcher Phoenix 012-345-6789 olivia.turner@example.com $70000 ResearchInnovate Research Scientist