spendenquittungen/csvsimple/csvsimple-l3.sty
2024-03-19 12:46:28 +01:00

1606 lines
45 KiB
TeX

%% The LaTeX package csvsimple - version 2.5.0 (2023/10/16)
%% csvsimple-l3.sty: Simple LaTeX CSV file processing (LaTeX3)
%%
%% -------------------------------------------------------------------------------------------
%% Copyright (c) 2008-2023 by Prof. Dr. Dr. Thomas F. Sturm <thomas dot sturm at unibw dot de>
%% -------------------------------------------------------------------------------------------
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either version 1.3
%% of this license or (at your option) any later version.
%% The latest version of this license is in
%% http://www.latex-project.org/lppl.txt
%% and version 1.3 or later is part of all distributions of LaTeX
%% version 2005/12/01 or later.
%%
%% This work has the LPPL maintenance status `author-maintained'.
%%
%% This work consists of all files listed in README.md
%%
\ProvidesExplPackage{csvsimple-l3}{2023/10/16}{2.5.0}
{LaTeX3 CSV file processing}
%---- check package
\cs_if_exist:NT \c__csvsim_package_expl_bool
{
\msg_new:nnn { csvsimple }{ l3 / package-loaded }
{ Package~'csvsimple-legacy'~seems~already~be~loaded!~
'csvsimple-l3'~cannot~be~loaded~simultaneously.~
Therefore,~loading~of~'csvsimple-l3'~stops~now.}
\msg_warning:nn { csvsimple }{ l3 / package-loaded }
\tex_endinput:D
}
\bool_const:Nn \c__csvsim_package_expl_bool { \c_true_bool }
%---- declarations and expl3 variants
\bool_new:N \g__csvsim_check_column_count_bool
\bool_new:N \g__csvsim_collect_data_bool
\bool_new:N \g__csvsim_colnames_detection_bool
\bool_new:N \g__csvsim_head_bool
\bool_new:N \g__csvsim_head_to_colnames_bool
\bool_new:N \g__csvsim_line_accepted_bool
\bool_new:N \g__csvsim_line_firstline_bool
\bool_new:N \l__csvsim_respect_and_bool
\bool_new:N \l__csvsim_respect_backslash_bool
\bool_new:N \l__csvsim_respect_circumflex_bool
\bool_new:N \l__csvsim_respect_dollar_bool
\bool_new:N \l__csvsim_respect_leftbrace_bool
\bool_new:N \l__csvsim_respect_percent_bool
\bool_new:N \l__csvsim_respect_rightbrace_bool
\bool_new:N \l__csvsim_respect_sharp_bool
\bool_new:N \l__csvsim_respect_tab_bool
\bool_new:N \l__csvsim_respect_tilde_bool
\bool_new:N \l__csvsim_respect_underscore_bool
\int_new:N \g__csvsim_col_int
\int_new:N \g__csvsim_colmax_int
\int_new:N \g_csvsim_inputline_int
\int_new:N \g_csvsim_row_int
\int_new:N \g_csvsim_columncount_int
\seq_new:N \g__csvsim_colname_seq
\seq_new:N \g__csvsim_line_seq
\seq_new:N \g__csvsim_range_seq
\str_new:N \g__csvsim_curfilename_str
\str_new:N \g__csvsim_filename_str
\str_new:N \l__csvsim_csvsorter_command_str
\str_new:N \l__csvsim_csvsorter_configpath_str
\str_new:N \l__csvsim_csvsorter_log_str
\str_new:N \l__csvsim_csvsorter_token_str
\str_new:N \l__csvsim_ppfilename_str
\str_new:N \l__csvsim_temp_filename_str
\tl_const:Nn \c__csvsim_par_tl { \par }
\tl_new:N \g__csvsim_after_table_tl
\tl_new:N \g__csvsim_before_table_tl
\tl_new:N \g__csvsim_begin_table_center_tl
\tl_new:N \g__csvsim_body_tl
\tl_new:N \g__csvsim_catcode_tl
\tl_new:N \g__csvsim_collect_tl
\tl_new:N \g__csvsim_columnnames_tl
\tl_new:N \g__csvsim_data_collection_tl
\tl_new:N \g__csvsim_end_table_center_tl
\tl_new:N \g__csvsim_filter_tl
\tl_new:N \g__csvsim_generic_table_options_tl
\tl_new:N \g__csvsim_headname_prefix_tl
\tl_new:N \g__csvsim_hook_after_filter_tl
\tl_new:N \g__csvsim_hook_after_first_line_tl
\tl_new:N \g__csvsim_hook_after_head_tl
\tl_new:N \g__csvsim_hook_after_line_tl
\tl_new:N \g__csvsim_hook_after_reading_tl
\tl_new:N \g__csvsim_hook_before_filter_tl
\tl_new:N \g__csvsim_hook_before_first_line_tl
\tl_new:N \g__csvsim_hook_before_line_tl
\tl_new:N \g__csvsim_hook_before_reading_tl
\tl_new:N \g__csvsim_hook_columncounterror_tl
\tl_new:N \g__csvsim_hook_late_after_first_line_tl
\tl_new:N \g__csvsim_hook_late_after_head_tl
\tl_new:N \g__csvsim_hook_late_after_last_line_tl
\tl_new:N \g__csvsim_hook_late_after_line_tl
\tl_new:N \g__csvsim_hook_late_after_line_application_tl
\tl_new:N \g__csvsim_hook_table_begin_tl
\tl_new:N \g__csvsim_hook_table_end_tl
\tl_new:N \g__csvsim_preprocessor_tl
\tl_new:N \g__csvsim_separator_tl
\tl_new:N \g__csvsim_table_foot_tl
\tl_new:N \g__csvsim_table_head_tl
\tl_new:N \l__csvsim_filter_condition_tl
\group_begin:
\char_set_catcode_other:n { 9 }
\str_const:Nn \c__csvsim_tab_str { ^^I }
\group_end:
\regex_const:Nn \c__csvsim_integer_regex {\A\d+\Z}
\cs_generate_variant:Nn \bool_gset:Nn { NV }
\cs_generate_variant:Nn \seq_gset_split:Nnn { NVV }
%---- messages
\msg_new:nnnn { csvsimple }{ column-name }
{ Unknown~column~key~'#1'. }
{ The~key~'#1'~you~used~in~'column~names'~is~unknown.\\
Therefore,~the~macro~#2 is~not~defined.
}
\msg_new:nnn { csvsimple }{ empty-head }
{ File~'#1'~starts~with~an~empty~line~(empty~head)!.}
\msg_new:nnn { csvsimple }{ file-error }
{ File~'#1'~not~existent,~not~readable,~or~empty!}
\msg_new:nnn { csvsimple }{ column-wrong-count }
{ #1~instead~of~#2~columns~for~input~line~#3~of~file~'#4'}
\msg_new:nnn { csvsimple }{ sort-info }
{ Sort~'#1'~by~'#2' }
\msg_new:nnn { csvsimple }{ sort-shell-escape }
{ You~need~to~use~'-shell-escape'~to~run~CSV-Sorter }
\msg_new:nnnn { csvsimple }{ sort-error }
{ Call~of~CSV-Sorter~failed! }
{ See~log~file~'\l__csvsim_csvsorter_log_str'. }
%---- core loop processing
\NewHook{csvsimple/csvline}
\cs_new_protected_nopar:Npn \__csvsim_read_line:
{
\group_begin:
\g__csvsim_catcode_tl
\ior_get:NNTF \g__csvsim_ior \l_tmpa_tl
{
\tl_gset_eq:NN \csvline \l_tmpa_tl
\int_gincr:N \g_csvsim_inputline_int
}
{
\msg_error:nnx { csvsimple }{ file-error }{ \g__csvsim_curfilename_str }
}
\group_end:
\UseHook{csvsimple/csvline}
}
\cs_new_protected_nopar:Npn \__csvsim_scan_line:
{
\int_gzero:N \g__csvsim_col_int
\seq_gset_split:NVV \g__csvsim_line_seq \g__csvsim_separator_tl \csvline
\seq_map_inline:Nn \g__csvsim_line_seq
{
\int_gincr:N \g__csvsim_col_int
\tl_gset:cn {csvcol \int_to_roman:n \g__csvsim_col_int}{##1}
}
\int_compare:nNnT \g__csvsim_colmax_int < \g__csvsim_col_int
{
\int_gset_eq:NN \g__csvsim_colmax_int \g__csvsim_col_int
}
\int_compare:nNnT \g_csvsim_columncount_int < \c_one_int
{
\int_gset_eq:NN \g_csvsim_columncount_int \g__csvsim_col_int
}
}
\cs_new_protected_nopar:Npn \__csvsim_process_head_name:n #1
{
\tl_set:No \l_tmpa_tl {\cs:w csvcol\int_to_roman:n{#1} \cs_end:}
\exp_args:NnV \cs_set_nopar:cpn {__csvsim__/\l_tmpa_tl} \l_tmpa_tl
\bool_if:NT \g__csvsim_head_to_colnames_bool
{
\tl_set:No \l_tmpb_tl {\cs:w \g__csvsim_headname_prefix_tl \l_tmpa_tl \cs_end:}
\tl_put_right:NV \l_tmpb_tl \l_tmpa_tl
\exp_args:NNV \seq_gput_right:Nn \g__csvsim_colname_seq \l_tmpb_tl
}
}
\cs_new_protected_nopar:Npn \__csvsim_read_head:
{
\__csvsim_read_line:
\tl_if_eq:NNTF \csvline \c__csvsim_par_tl
{
\msg_error:nnx { csvsimple }{ empty-head }{ \g__csvsim_filename_str }
}
{
\int_gzero:N \g_csvsim_columncount_int
\__csvsim_scan_line:
\bool_if:NT \g__csvsim_colnames_detection_bool
{
\int_step_function:nN \g_csvsim_columncount_int \__csvsim_process_head_name:n
}
}
}
\cs_new_protected_nopar:Npn \__csvsim_process_colname:nn #1#2
{
\cs_if_exist:cTF {__csvsim__/#1}
{
\tl_set:Nv \l_tmpa_tl {__csvsim__/#1}
\tl_put_left:Nn \l_tmpa_tl {#2}
\exp_args:NNV \seq_gput_right:Nn \g__csvsim_colname_seq \l_tmpa_tl
}
{
\regex_match:NnTF \c__csvsim_integer_regex {#1}
{
\tl_set:No \l_tmpa_tl {\cs:w csvcol\int_to_roman:n{#1} \cs_end:}
\tl_put_left:Nn \l_tmpa_tl {#2}
\exp_args:NNV \seq_gput_right:Nn \g__csvsim_colname_seq \l_tmpa_tl
}
{
\str_set:Nn \l_tmpb_str {#2}
\msg_error:nnxx { csvsimple }{ column-name }{ #1 }{ \l_tmpb_str }
}
}
}
\cs_new_protected_nopar:Npn \__csvsim_set_colnames:
{
\seq_map_inline:Nn \g__csvsim_colname_seq
{
\tl_gset_eq:NN ##1
}
}
\cs_new_protected_nopar:Npn \__csvsim_loop:
{
% preprocess
\tl_if_empty:NTF \l__csvsim_preprocessor_tl
{
\str_gset_eq:NN \g__csvsim_curfilename_str \g__csvsim_filename_str
}
{
\l__csvsim_preprocessor_tl \g__csvsim_filename_str \l__csvsim_ppfilename_str
\str_gset_eq:NN \g__csvsim_curfilename_str \l__csvsim_ppfilename_str
}
% initialize
\cs_if_exist:NF \g__csvsim_ior
{
\ior_new:N \g__csvsim_ior
}
\__csvsim_setup_catcode_list:
\seq_gclear:N \g__csvsim_colname_seq
\int_gzero:N \g_csvsim_inputline_int
\int_gzero:N \g_csvsim_row_int
\int_gset_eq:NN \g__csvsim_colmax_int \c_one_int
\bool_if:NT \g__csvsim_collect_data_bool
{
\__csvsim_collect_data:
}
% open file
\g__csvsim_hook_before_reading_tl
\g__csvsim_hook_table_begin_tl
\ior_open:Nn \g__csvsim_ior { \g__csvsim_curfilename_str }
% read head line
\bool_if:NT \g__csvsim_head_bool
{
\__csvsim_read_head:
}
\exp_args:NNNV \keyval_parse:NNn \use_none:n
\__csvsim_process_colname:nn \g__csvsim_columnnames_tl
\bool_if:NT \g__csvsim_head_bool
{
\g__csvsim_hook_after_head_tl
}
% read body lines
\tl_gset:Nn \g__csvsim_hook_late_after_line_application_tl
{
\g__csvsim_hook_late_after_first_line_tl
\tl_gset_eq:NN \g__csvsim_hook_late_after_line_application_tl \g__csvsim_hook_late_after_line_tl
}
\bool_gset_true:N \g__csvsim_line_firstline_bool
\bool_until_do:nn {\ior_if_eof_p:N \g__csvsim_ior}
{
\__csvsim_read_line:
\tl_if_eq:NNF \csvline \c__csvsim_par_tl
{
\bool_gset_true:N \g__csvsim_line_accepted_bool
\__csvsim_scan_line:
\__csvsim_set_colnames:
\bool_if:NT \g__csvsim_check_column_count_bool
{
\int_compare:nNnF \g__csvsim_col_int = \g_csvsim_columncount_int
{
\bool_gset_false:N \g__csvsim_line_accepted_bool
\g__csvsim_hook_columncounterror_tl
}
}
\bool_if:NT \g__csvsim_line_accepted_bool
{
\g__csvsim_hook_before_filter_tl
\g__csvsim_filter_tl
\bool_if:NT \g__csvsim_line_accepted_bool
{
\int_gincr:N \g_csvsim_row_int
\__csvsim_check_range:
\bool_if:NT \g__csvsim_line_accepted_bool
{
\bool_if:NTF \g__csvsim_line_firstline_bool
{
\bool_if:NT \g__csvsim_head_bool
{
\g__csvsim_hook_late_after_head_tl
}
\g__csvsim_hook_after_filter_tl
\g__csvsim_hook_before_first_line_tl
\g__csvsim_body_tl
\g__csvsim_hook_after_first_line_tl
\bool_gset_false:N \g__csvsim_line_firstline_bool
}
{
\g__csvsim_hook_late_after_line_application_tl
\g__csvsim_hook_after_filter_tl
\g__csvsim_hook_before_line_tl
\g__csvsim_body_tl
\g__csvsim_hook_after_line_tl
}
}
}
}
}
}
% close file
\ior_close:N \g__csvsim_ior
% clear macros
\int_step_inline:nn \g__csvsim_colmax_int
{
\tl_set:No \l_tmpa_tl {\cs:w csvcol\int_to_roman:n{##1} \cs_end:}
\use:x
{
\exp_not:N\tl_gclear:N \exp_not:V\l_tmpa_tl
}
}
\__csvsim_set_colnames:
\seq_gclear:N \g__csvsim_colname_seq
\bool_if:NF \g__csvsim_line_firstline_bool
{
\g__csvsim_hook_late_after_last_line_tl
}
\g__csvsim_hook_table_end_tl
\g__csvsim_hook_after_reading_tl
\bool_if:NT \g__csvsim_collect_data_bool
{
\exp_args:NV \tl_gset_eq:NN \g__csvsim_data_collection_tl \g__csvsim_collect_tl
\tl_gclear:N \g__csvsim_collect_tl
}
}
\NewDocumentCommand \csvloop { +m }
{
\keys_set:nn { csvsim } { default, every~csv, #1}
\__csvsim_loop:
}
\NewDocumentCommand \csvreader { +O{} m m +m }
{
\keys_set:nn { csvsim } { default, every~csv, #1, file={#2}, column~names={#3} }
\tl_gset:Nn \g__csvsim_body_tl {#4}
\__csvsim_loop:
}
%---- auxiliary user macros
% \NewDocumentCommand \csvlinetotablerow { }
% {
% \tl_clear:N \l_tmpa_tl
% \bool_set_false:N \l_tmpa_bool
% \seq_map_inline:Nn \g__csvsim_line_seq
% {
% \bool_if:NTF \l_tmpa_bool
% {
% \tl_put_right:Nn \l_tmpa_tl { & ##1 }
% }
% {
% \tl_put_right:Nn \l_tmpa_tl { ##1 }
% \bool_set_true:N \l_tmpa_bool
% }
% }
% \l_tmpa_tl
% }
\NewExpandableDocumentCommand \csvlinetotablerow { }
{
\seq_use:Nn \g__csvsim_line_seq { & }
}
\NewExpandableDocumentCommand \thecsvrow { }
{
\int_use:N \g_csvsim_row_int
}
\NewExpandableDocumentCommand \thecsvcolumncount { }
{
\int_use:N \g_csvsim_columncount_int
}
\NewExpandableDocumentCommand \thecsvinputline { }
{
\int_use:N \g_csvsim_inputline_int
}
\NewExpandableDocumentCommand \ifcsvfirstrow { }
{
\bool_if:NTF \g__csvsim_line_firstline_bool
}
% deprecated
\NewExpandableDocumentCommand \csviffirstrow { }
{
\bool_if:NTF \g__csvsim_line_firstline_bool
}
\NewExpandableDocumentCommand \ifcsvoddrow { }
{
\int_if_odd:nTF {\g_csvsim_row_int}
}
% deprecated
\NewExpandableDocumentCommand \csvifoddrow { }
{
\int_if_odd:nTF {\g_csvsim_row_int}
}
\NewExpandableDocumentCommand \ifcsvstrcmp { m m }
{
\str_compare:eNeTF {#1} = {#2}
}
\NewExpandableDocumentCommand \ifcsvnotstrcmp { m m +m +m }
{
\ifcsvstrcmp{#1}{#2}{#4}{#3}
}
\NewDocumentCommand \ifcsvstrequal { m m }
{
\tl_set:Nx \l_tmpa_tl {#1}
\tl_set:Nx \l_tmpb_tl {#2}
\tl_if_eq:NNTF \l_tmpa_tl \l_tmpb_tl
}
\NewDocumentCommand \ifcsvprostrequal { m m }
{
\protected@edef \l_tmpa_tl {#1}
\protected@edef \l_tmpb_tl {#2}
\tl_if_eq:NNTF \l_tmpa_tl \l_tmpb_tl
}
\NewExpandableDocumentCommand \ifcsvfpcmp { m }
{
\fp_compare:nTF {#1}
}
\NewExpandableDocumentCommand \ifcsvintcmp { m }
{
\int_compare:nTF {#1}
}
%---- filename functions
\cs_new_protected_nopar:Npn \__csvsim_set_temp_filename:nnn #1#2#3
{
\str_set:Nn \l__csvsim_temp_filename_str {#2#3}
\str_if_empty:NTF \l__csvsim_temp_filename_str
{
\str_set:Nn \l__csvsim_temp_filename_str {#1}
}
{
\str_set:Nn \l_tmpa_str {#1}
\str_if_empty:NF \l_tmpa_str
{
\str_compare:eNeF { \str_item:Nn \l_tmpa_str {-1} } = { / }
{
\str_put_right:Nn \l_tmpa_str {/}
}
\str_concat:NNN \l__csvsim_temp_filename_str
\l_tmpa_str \l__csvsim_temp_filename_str
}
}
}
\cs_new_protected_nopar:Npn \__csvsim_set_temp_filename:n #1
{
\file_parse_full_name_apply:nN { #1 } \__csvsim_set_temp_filename:nnn
}
\cs_new_protected_nopar:Npn \__csvsim_set_filename:Nn #1#2
{
\__csvsim_set_temp_filename:n { #2 }
\str_set_eq:NN #1 \l__csvsim_temp_filename_str
}
\cs_new_protected_nopar:Npn \__csvsim_gset_filename:Nn #1#2
{
\__csvsim_set_temp_filename:n { #2 }
\str_gset_eq:NN #1 \l__csvsim_temp_filename_str
}
%---- keys
\NewDocumentCommand \csvset { +m }
{
\keys_set:nn { csvsim } { #1 }
}
\NewDocumentCommand \csvstyle { m +m }
{
\keys_define:nn { csvsim }
{
#1 .meta:n = { #2 }
}
}
\NewDocumentCommand \csvnames { m m }
{
\keys_define:nn { csvsim }
{
#1 .meta:n = { column~names={#2} }
}
}
\keys_define:nn { csvsim }
{
file .code:n = \__csvsim_gset_filename:Nn \g__csvsim_filename_str {#1},
column~names~reset .code:n = \tl_gclear:N \g__csvsim_columnnames_tl,
column~names .code:n =
{
\tl_if_empty:NTF \g__csvsim_columnnames_tl
{
\tl_gset:Nn \g__csvsim_columnnames_tl {#1}
}
{
\tl_gput_right:Nn \g__csvsim_columnnames_tl {,#1}
}
},
command .tl_gset:N = \g__csvsim_body_tl,
check~column~count .bool_gset:N = \g__csvsim_check_column_count_bool,
on~column~count~error .tl_gset:N = \g__csvsim_hook_columncounterror_tl,
head .bool_gset:N = \g__csvsim_head_bool,
head~to~column~names~prefix .tl_gset:N = \g__csvsim_headname_prefix_tl,
head~to~column~names .bool_gset:N = \g__csvsim_head_to_colnames_bool,
column~names~detection .bool_gset:N = \g__csvsim_colnames_detection_bool,
column~count .int_gset:N = \g_csvsim_columncount_int,
separator .choice:,
separator/comma .code:n =
{
\tl_gset:Nn \g__csvsim_separator_tl {,}
},
separator/semicolon .code:n =
{
\tl_gset:Nn \g__csvsim_separator_tl {;}
},
separator/pipe .code:n =
{
\tl_gset:Nn \g__csvsim_separator_tl {|}
},
separator/tab .code:n =
{
\tl_gset:NV \g__csvsim_separator_tl \c__csvsim_tab_str
\csvset{respect~tab}
},
separator/space .code:n =
{
\tl_gset:Nn \g__csvsim_separator_tl {~}
},
every~csv .meta:n = {},
no~head .meta:n = { head=false },
no~check~column~count .meta:n = { check~column~count=false },
warn~on~column~count~error .meta:n = { on~column~count~error=
{
\msg_warning:nnxxxx { csvsimple }{ column-wrong-count }
{ \int_use:N\g__csvsim_col_int }
{ \int_use:N\g_csvsim_columncount_int }
{ \int_use:N\g_csvsim_inputline_int }
{ \g__csvsim_filename_str }
}},
}
%---- hooks
\keys_define:nn { csvsim }
{
before~reading .tl_gset:N = \g__csvsim_hook_before_reading_tl,
after~head .tl_gset:N = \g__csvsim_hook_after_head_tl,
before~filter .tl_gset:N = \g__csvsim_hook_before_filter_tl,
after~filter .tl_gset:N = \g__csvsim_hook_after_filter_tl,
late~after~head .tl_gset:N = \g__csvsim_hook_late_after_head_tl,
late~after~first~line .tl_gset:N = \g__csvsim_hook_late_after_first_line_tl,
late~after~last~line .tl_gset:N = \g__csvsim_hook_late_after_last_line_tl,
before~first~line .tl_gset:N = \g__csvsim_hook_before_first_line_tl,
after~first~line .tl_gset:N = \g__csvsim_hook_after_first_line_tl,
after~reading .tl_gset:N = \g__csvsim_hook_after_reading_tl,
late~after~line .code:n =
{
\tl_gset:Nn \g__csvsim_hook_late_after_line_tl {#1}
\tl_gset_eq:NN \g__csvsim_hook_late_after_first_line_tl \g__csvsim_hook_late_after_line_tl
\tl_gset_eq:NN \g__csvsim_hook_late_after_last_line_tl \g__csvsim_hook_late_after_line_tl
},
before~line .code:n =
{
\tl_gset:Nn \g__csvsim_hook_before_line_tl {#1}
\tl_gset_eq:NN \g__csvsim_hook_before_first_line_tl \g__csvsim_hook_before_line_tl
},
after~line .code:n =
{
\tl_gset:Nn \g__csvsim_hook_after_line_tl {#1}
\tl_gset_eq:NN \g__csvsim_hook_after_first_line_tl \g__csvsim_hook_after_line_tl
},
}
%---- filter
\cs_new_protected_nopar:Npn \__csvsim_set_filter:n #1
{
\tl_gset:Nn \g__csvsim_filter_tl
{
#1
}
}
\cs_new_protected_nopar:Npn \__csvsim_set_filter_bool:n #1
{
\tl_set:Nn \l__csvsim_filter_condition_tl { #1 }
\tl_gset:Nn \g__csvsim_filter_tl
{
\bool_gset:NV \g__csvsim_line_accepted_bool \l__csvsim_filter_condition_tl
}
}
\NewDocumentCommand \csvfilteraccept { }
{
\__csvsim_set_filter:n
{
\bool_gset_true:N \g__csvsim_line_accepted_bool
}
}
\NewDocumentCommand \csvfilterreject { }
{
\__csvsim_set_filter:n
{
\bool_gset_false:N \g__csvsim_line_accepted_bool
}
}
\keys_define:nn { csvsim }
{
no~filter .code:n =
{
\csvfilteraccept
},
filter~reject~all .code:n =
{
\csvfilterreject
},
filter~accept~all .code:n =
{
\csvfilteraccept
},
full~filter. tl_gset:N = \g__csvsim_hook_before_filter_tl,
filter~test .code:n =
{
\__csvsim_set_filter:n
{
#1
{ \bool_gset_true:N \g__csvsim_line_accepted_bool }
{ \bool_gset_false:N \g__csvsim_line_accepted_bool }
}
},
filter~bool .code:n =
{
\__csvsim_set_filter_bool:n { #1 }
},
filter~fp .code:n =
{
\__csvsim_set_filter_bool:n { \fp_compare_p:n {#1} }
},
filter~strcmp .code:n =
{
\__csvsim_set_filter_bool:n { \str_if_eq_p:ee #1 }
},
filter~not~strcmp .code:n =
{
\__csvsim_set_filter_bool:n { !\str_if_eq_p:ee #1 }
},
and~filter~bool .code:n =
{
\tl_put_right:Nn \l__csvsim_filter_condition_tl { && #1 }
},
and~filter~fp .code:n =
{
\tl_put_right:Nn \l__csvsim_filter_condition_tl { && \fp_compare_p:n {#1} }
},
and~filter~strcmp .code:n =
{
\tl_put_right:Nn \l__csvsim_filter_condition_tl { && \str_if_eq_p:ee #1 }
},
and~filter~not~strcmp .code:n =
{
\tl_put_right:Nn \l__csvsim_filter_condition_tl { && !\str_if_eq_p:ee #1 }
},
or~filter~bool .code:n =
{
\tl_put_right:Nn \l__csvsim_filter_condition_tl { || #1 }
},
or~filter~fp .code:n =
{
\tl_put_right:Nn \l__csvsim_filter_condition_tl { || \fp_compare_p:n {#1} }
},
or~filter~strcmp .code:n =
{
\tl_put_right:Nn \l__csvsim_filter_condition_tl { || \str_if_eq_p:ee #1 }
},
or~filter~not~strcmp .code:n =
{
\tl_put_right:Nn \l__csvsim_filter_condition_tl { || !\str_if_eq_p:ee #1 }
},
}
\NewDocumentCommand \csvfilterbool { m m }
{
\keys_define:nn { csvsim }
{
#1 .meta:n = { filter~bool={#2} }
}
}
% ifthen
\keys_define:nn { csvsim }
{
filter~ifthen .code:n =
{
\__csvsim_set_filter:n
{
\ifthenelse{#1}
{ \bool_gset_true:N \g__csvsim_line_accepted_bool }
{ \bool_gset_false:N \g__csvsim_line_accepted_bool }
}
},
filter~equal .meta:n = { filter~ifthen=\equal #1 },
filter~not~equal .meta:n = { filter~ifthen=\not\equal #1 },
}
% etoolbox
\keys_define:nn { csvsim }
{
filter~expr .code:n =
{
\__csvsim_set_filter:n
{
\ifboolexpr{#1}
{ \bool_gset_true:N \g__csvsim_line_accepted_bool }
{ \bool_gset_false:N \g__csvsim_line_accepted_bool }
}
},
}
%---- range
\cs_new_protected_nopar:Npn \__csvsim_add_range:n #1
{
\tl_if_in:nnTF {#1}{-}
{
\seq_set_split:Nnn \l_tmpa_seq {-} {#1}
\seq_pop_left:NN \l_tmpa_seq \l_tmpa_tl
\seq_pop_left:NN \l_tmpa_seq \l_tmpb_tl
\tl_if_empty:NTF \l_tmpa_tl
{
\int_set_eq:NN \l_tmpa_int \c_one_int
}
{
\int_set:Nn \l_tmpa_int { \l_tmpa_tl }
}
\tl_if_empty:NTF \l_tmpb_tl
{
\int_set_eq:NN \l_tmpb_int \c_max_int
}
{
\int_set:Nn \l_tmpb_int { \l_tmpb_tl }
}
}
{
\tl_if_in:nnTF {#1}{+}
{
\seq_set_split:Nnn \l_tmpa_seq {+} {#1}
\seq_pop_left:NN \l_tmpa_seq \l_tmpa_tl
\seq_pop_left:NN \l_tmpa_seq \l_tmpb_tl
\tl_if_empty:NTF \l_tmpa_tl
{
\int_set:Nn \l_tmpa_int { 1 }
}
{
\int_set:Nn \l_tmpa_int { \l_tmpa_tl }
}
\tl_if_empty:NTF \l_tmpb_tl
{
\int_set_eq:NN \l_tmpb_int \l_tmpa_int
}
{
\int_set:Nn \l_tmpb_int { \l_tmpa_int + \l_tmpb_tl - 1 }
}
}
{
\int_set:Nn \l_tmpa_int {#1}
\int_set_eq:NN \l_tmpb_int \l_tmpa_int
}
}
\seq_gput_right:Nx \g__csvsim_range_seq {{\int_use:N \l_tmpa_int}{\int_use:N \l_tmpb_int}}
}
\cs_new_protected_nopar:Npn \__csvsim_set_range:n #1
{
\seq_gclear:N \g__csvsim_range_seq
\keyval_parse:NNn
\__csvsim_add_range:n
\use_none:nn
{ #1 }
}
\cs_generate_variant:Nn \__csvsim_set_range:n { e }
\keys_define:nn { csvsim }
{
range .code:n =
{
\__csvsim_set_range:e {#1}
},
}
\prg_new_conditional:Npnn \__csvsim_if_in_range:nn #1#2 { p , T }
{
\if_int_compare:w #1 > \g_csvsim_row_int
\prg_return_false:
\else:
\if_int_compare:w #2 < \g_csvsim_row_int
\prg_return_false:
\else:
\prg_return_true:
\fi:
\fi:
}
\cs_new_protected_nopar:Npn \__csvsim_check_range:
{
\seq_if_empty:NF \g__csvsim_range_seq
{
\bool_gset_false:N \g__csvsim_line_accepted_bool
\seq_map_inline:Nn \g__csvsim_range_seq
{
\__csvsim_if_in_range:nnT ##1
{
\bool_gset_true:N \g__csvsim_line_accepted_bool
\seq_map_break:
}
}
}
}
%---- data collection
\cs_new_protected_nopar:Npn \__csvsim_gset_tl_to_collect:N #1
{
\tl_gset:Nx #1
{
\exp_not:N \tl_gput_right:Nn
\exp_not:N \g__csvsim_collect_tl
{\exp_not:V #1}
}
}
\cs_new_protected_nopar:Npn \__csvsim_gset_tl_to_collect_expanded:N #1
{
\tl_gset:Nx #1
{
\exp_not:N \tl_gput_right:Nx
\exp_not:N \g__csvsim_collect_tl
{\exp_not:V #1}
}
}
\cs_new_protected_nopar:Npn \__csvsim_collect_data:
{
\__csvsim_gset_tl_to_collect:N \g__csvsim_hook_after_head_tl
\__csvsim_gset_tl_to_collect:N \g__csvsim_hook_after_first_line_tl
\__csvsim_gset_tl_to_collect:N \g__csvsim_hook_after_line_tl
\__csvsim_gset_tl_to_collect:N \g__csvsim_hook_before_first_line_tl
\__csvsim_gset_tl_to_collect:N \g__csvsim_hook_before_line_tl
\__csvsim_gset_tl_to_collect:N \g__csvsim_hook_late_after_first_line_tl
\__csvsim_gset_tl_to_collect:N \g__csvsim_hook_late_after_head_tl
\__csvsim_gset_tl_to_collect:N \g__csvsim_hook_late_after_last_line_tl
\__csvsim_gset_tl_to_collect:N \g__csvsim_hook_late_after_line_tl
\__csvsim_gset_tl_to_collect_expanded:N \g__csvsim_body_tl
\tl_gclear:N \g__csvsim_collect_tl
}
\cs_set_eq:NN \csvexpval \exp_not:V
\cs_set_eq:NN \csvexpnot \exp_not:N
\NewDocumentCommand{ \csvcollectn }{ +m }
{
\tl_gput_right:Nn \g__csvsim_collect_tl {#1}
}
\NewDocumentCommand{ \csvcollectx }{ +m }
{
\tl_gput_right:Nx \g__csvsim_collect_tl {#1}
}
\NewDocumentCommand{ \csvcollectV }{ m }
{
\tl_gput_right:NV \g__csvsim_collect_tl #1
}
\keys_define:nn { csvsim }
{
collect~data .bool_gset:N = \g__csvsim_collect_data_bool,
data~collection .tl_gset:N = \g__csvsim_data_collection_tl,
}
\keys_set:nn { csvsim }
{
data~collection = \csvdatacollection,
}
%---- catcodes
\cs_new_protected_nopar:Npn \__csvsim_setup_catcode_list:
{
\tl_gclear:N \g__csvsim_catcode_tl
\bool_if:NT \l__csvsim_respect_tab_bool
{
\tl_gput_right:Nn \g__csvsim_catcode_tl { \char_set_catcode_other:n { 9 } }
}
\bool_if:NT \l__csvsim_respect_percent_bool
{
\tl_gput_right:Nn \g__csvsim_catcode_tl { \char_set_catcode_other:n { 37 } }
}
\bool_if:NT \l__csvsim_respect_sharp_bool
{
\tl_gput_right:Nn \g__csvsim_catcode_tl { \char_set_catcode_other:n { 35 } }
}
\bool_if:NT \l__csvsim_respect_dollar_bool
{
\tl_gput_right:Nn \g__csvsim_catcode_tl { \char_set_catcode_other:n { 36 } }
}
\bool_if:NT \l__csvsim_respect_and_bool
{
\tl_gput_right:Nn \g__csvsim_catcode_tl { \char_set_catcode_other:n { 38 } }
}
\bool_if:NT \l__csvsim_respect_backslash_bool
{
\tl_gput_right:Nn \g__csvsim_catcode_tl { \char_set_catcode_other:n { 92 } }
}
\bool_if:NT \l__csvsim_respect_underscore_bool
{
\tl_gput_right:Nn \g__csvsim_catcode_tl { \char_set_catcode_other:n { 95 } }
}
\bool_if:NT \l__csvsim_respect_tilde_bool
{
\tl_gput_right:Nn \g__csvsim_catcode_tl { \char_set_catcode_other:n { 126 } }
}
\bool_if:NT \l__csvsim_respect_circumflex_bool
{
\tl_gput_right:Nn \g__csvsim_catcode_tl { \char_set_catcode_other:n { 94 } }
}
\bool_if:NT \l__csvsim_respect_leftbrace_bool
{
\tl_gput_right:Nn \g__csvsim_catcode_tl { \char_set_catcode_other:n { 123 } }
}
\bool_if:NT \l__csvsim_respect_rightbrace_bool
{
\tl_gput_right:Nn \g__csvsim_catcode_tl { \char_set_catcode_other:n { 125 } }
}
}
\keys_define:nn { csvsim }
{
respect~tab .bool_set:N = \l__csvsim_respect_tab_bool,
respect~percent .bool_set:N = \l__csvsim_respect_percent_bool,
respect~sharp .bool_set:N = \l__csvsim_respect_sharp_bool,
respect~dollar .bool_set:N = \l__csvsim_respect_dollar_bool,
respect~and .bool_set:N = \l__csvsim_respect_and_bool,
respect~backslash .bool_set:N = \l__csvsim_respect_backslash_bool,
respect~underscore .bool_set:N = \l__csvsim_respect_underscore_bool,
respect~tilde .bool_set:N = \l__csvsim_respect_tilde_bool,
respect~circumflex .bool_set:N = \l__csvsim_respect_circumflex_bool,
respect~leftbrace .bool_set:N = \l__csvsim_respect_leftbrace_bool,
respect~rightbrace .bool_set:N = \l__csvsim_respect_rightbrace_bool,
respect~all .meta:n =
{
respect~tab, respect~percent, respect~sharp, respect~dollar,
respect~and, respect~backslash, respect~underscore, respect~tilde,
respect~circumflex, respect~leftbrace, respect~rightbrace
},
respect~none .meta:n =
{
respect~tab=false, respect~percent=false, respect~sharp=false,
respect~dollar=false, respect~and=false, respect~backslash=false,
respect~underscore=false, respect~tilde=false, respect~circumflex=false,
respect~leftbrace=false, respect~rightbrace=false
},
}
%---- tables
\cs_new_protected_nopar:Npn \__csvsim_key_table:nn #1#2
{
\tl_gset:Nn \g__csvsim_hook_table_begin_tl {#1}
\tl_gset:Nn \g__csvsim_hook_table_end_tl {#2}
}
\keys_define:nn { csvsim }
{
before~table .tl_gset:N = \g__csvsim_before_table_tl,
after~table .tl_gset:N = \g__csvsim_after_table_tl,
table~head .tl_gset:N = \g__csvsim_table_head_tl,
table~foot .tl_gset:N = \g__csvsim_table_foot_tl,
generic~table~options .tl_gset:N = \g__csvsim_generic_table_options_tl,
table~centered .choice:,
table~centered .default:n = true,
table~centered/true .code:n =
{
\tl_gset:Nn \g__csvsim_begin_table_center_tl {\begin{center}}
\tl_gset:Nn \g__csvsim_end_table_center_tl {\end{center}}
},
table~centered/false .code:n =
{
\tl_gclear:N \g__csvsim_begin_table_center_tl
\tl_gclear:N \g__csvsim_end_table_center_tl
},
_table_ .code:n = \__csvsim_key_table:nn #1,
no~table .meta:n =
{
_table_ = {}{},
generic~table~options = ,
table~centered = false,
},
generic~table .meta:n =
{
_table_ =
{
\g__csvsim_begin_table_center_tl
\g__csvsim_before_table_tl
\tl_gset:Nn \g_tmpa_tl {\begin{#1}}
\tl_gput_right:NV \g_tmpa_tl \g__csvsim_generic_table_options_tl
\g_tmpa_tl
\g__csvsim_table_head_tl
}
{
\g__csvsim_table_foot_tl
\end{#1}
\g__csvsim_after_table_tl
\g__csvsim_end_table_center_tl
},
late~after~line = \\
},
generic~collected~table .meta:n =
{
collect~data,
_table_ =
{
\tl_gput_right:NV \g__csvsim_collect_tl \g__csvsim_begin_table_center_tl
\tl_gput_right:NV \g__csvsim_collect_tl \g__csvsim_before_table_tl
\tl_gput_right:Nn \g__csvsim_collect_tl { \begin{#1} }
\tl_gput_right:NV \g__csvsim_collect_tl \g__csvsim_generic_table_options_tl
\tl_gput_right:NV \g__csvsim_collect_tl \g__csvsim_table_head_tl
}
{
\tl_gput_right:NV \g__csvsim_collect_tl \g__csvsim_table_foot_tl
\tl_gput_right:Nn \g__csvsim_collect_tl { \end{#1} }
\tl_gput_right:NV \g__csvsim_collect_tl \g__csvsim_after_table_tl
\tl_gput_right:NV \g__csvsim_collect_tl \g__csvsim_end_table_center_tl
},
late~after~line = \\,
after~reading =
{
\tl_use:N \g__csvsim_collect_tl
},
},
}
\keys_define:nn { csvsim }
{
tabular .meta:n =
{
generic~table = tabular,
generic~table~options = {{#1}},
},
centered~tabular .meta:n =
{
tabular = {#1}, table~centered
},
longtable .meta:n =
{
generic~table = longtable,
generic~table~options = {{#1}},
},
tabbing .meta:n =
{
generic~table = tabbing,
generic~table~options =,
late~after~last~line =
},
centered tabbing .meta:n =
{
tabbing, table~centered
},
tabularray .meta:n =
{
generic~collected~table = tblr,
generic~table~options = {{#1}},
},
centered~tabularray .meta:n =
{
tabularray = {#1}, table~centered
},
long~tabularray .meta:n =
{
generic~collected~table = longtblr,
generic~table~options = {{#1}},
},
}
\keys_define:nn { csvsim }
{
_autotab_ .meta:n =
{
file = #1,
late~after~line = \\,
command = \csvlinetotablerow
},
_autotabular_ .meta:n =
{
_autotab_ = #1,
late~after~last~line = \g__csvsim_table_foot_tl
\end{tabular}
\g__csvsim_after_table_tl,
},
autotabular .meta:n =
{
_autotabular_ = #1,
head,
column~names~detection = false,
after~head = \g__csvsim_before_table_tl
\begin{tabular}{|*{\int_use:N\g_csvsim_columncount_int}{l|}}
\g__csvsim_table_head_tl,
table~head = \hline\csvlinetotablerow\\\hline,
table~foot = \\\hline,
},
autotabular* .meta:n =
{
_autotabular_ = #1,
no~head,
before~first~line = \g__csvsim_before_table_tl
\begin{tabular}{|*{\int_use:N\g_csvsim_columncount_int}{l|}}
\g__csvsim_table_head_tl,
table~head = \hline,
table~foot = \\\hline,
},
autobooktabular .meta:n =
{
_autotabular_ = #1,
head,
column~names~detection = false,
after~head = \g__csvsim_before_table_tl
\begin{tabular}{*{\int_use:N\g_csvsim_columncount_int}{l}}
\g__csvsim_table_head_tl,
table~head = \toprule\csvlinetotablerow\\\midrule,
table~foot = \\\bottomrule,
},
autobooktabular* .meta:n =
{
_autotabular_ = #1,
no~head,
before~first~line = \g__csvsim_before_table_tl
\begin{tabular}{*{\int_use:N\g_csvsim_columncount_int}{l}}
\g__csvsim_table_head_tl,
table~head = \toprule,
table~foot = \\\bottomrule,
},
_autolongtable_ .meta:n =
{
_autotab_ = #1,
late~after~last~line = \end{longtable}
\g__csvsim_after_table_tl,
},
autolongtable .meta:n =
{
_autolongtable_ = #1,
head,
column~names~detection = false,
after~head = \g__csvsim_before_table_tl
\begin{longtable}{|*{\int_use:N\g_csvsim_columncount_int}{l|}}
\g__csvsim_table_head_tl,
table~head = \hline\csvlinetotablerow\\\hline\endhead
\hline\endfoot,
},
autolongtable* .meta:n =
{
_autolongtable_ = #1,
no~head,
before~first~line = \g__csvsim_before_table_tl
\begin{longtable}{|*{\int_use:N\g_csvsim_columncount_int}{l|}}
\g__csvsim_table_head_tl,
table~head = \hline\endhead
\hline\endfoot,
},
autobooklongtable .meta:n =
{
_autolongtable_ = #1,
head,
column~names~detection = false,
after~head = \g__csvsim_before_table_tl
\begin{longtable}{*{\int_use:N\g_csvsim_columncount_int}{l}}
\g__csvsim_table_head_tl,
table~head = \toprule\csvlinetotablerow\\\midrule\endhead
\bottomrule\endfoot,
},
autobooklongtable* .meta:n =
{
_autolongtable_ = #1,
no~head,
before~first~line = \g__csvsim_before_table_tl
\begin{longtable}{*{\int_use:N\g_csvsim_columncount_int}{l}}
\g__csvsim_table_head_tl,
table~head = \toprule\endhead
\bottomrule\endfoot,
},
_autotabularray_ .meta:n =
{
file = {#1},
command = \csvlinetotablerow,
no~head,
generic~collected~table = tblr,
},
autotabularray .meta:n =
{
_autotabularray_ = {#1},
generic~table~options =
{ {
row{1} = {font=\bfseries},
hline{1,Z} = {0.8pt},
hline{2} = {0.4pt},
} }
},
autotabularray* .meta:n =
{
_autotabularray_ = {#1},
generic~table~options =
{ {
hline{1,Z} = {0.8pt},
} }
},
_autolongtabularray_ .meta:n =
{
file = {#1},
command = \csvlinetotablerow,
no~head,
generic~collected~table = longtblr,
},
autolongtabularray .meta:n =
{
_autolongtabularray_ = {#1},
generic~table~options =
{ {
row{1} = {font=\bfseries},
hline{1,Z} = {0.8pt},
hline{2} = {0.4pt},
} }
},
autolongtabularray* .meta:n =
{
_autolongtabularray_ = {#1},
generic~table~options =
{ {
hline{1,Z} = {0.8pt},
} }
},
}
\NewDocumentCommand \csvautotabular { s +O{} m }
{
\IfBooleanTF {#1}
{
\keys_set:nn { csvsim } { default, every~csv, autotabular*={#3}, #2}
}
{
\keys_set:nn { csvsim } { default, every~csv, autotabular={#3}, #2}
}
\__csvsim_loop:
}
\NewDocumentCommand \csvautolongtable { s +O{} m }
{
\IfBooleanTF {#1}
{
\keys_set:nn { csvsim } { default, every~csv, autolongtable*={#3}, #2}
}
{
\keys_set:nn { csvsim } { default, every~csv, autolongtable={#3}, #2}
}
\__csvsim_loop:
}
\NewDocumentCommand \csvautobooktabular { s +O{} m }
{
\IfBooleanTF {#1}
{
\keys_set:nn { csvsim } { default, every~csv, autobooktabular*={#3}, #2}
}
{
\keys_set:nn { csvsim } { default, every~csv, autobooktabular={#3}, #2}
}
\__csvsim_loop:
}
\NewDocumentCommand \csvautobooklongtable { s +O{} m }
{
\IfBooleanTF {#1}
{
\keys_set:nn { csvsim } { default, every~csv, autobooklongtable*={#3}, #2}
}
{
\keys_set:nn { csvsim } { default, every~csv, autobooklongtable={#3}, #2}
}
\__csvsim_loop:
}
\NewDocumentCommand \csvautotabularray { s +O{} m +o +o }
{
\keys_set:nn { csvsim } { default, every~csv }
\IfBooleanTF {#1}
{
\keys_set:nn { csvsim } { autotabularray*={#3}, #2}
}
{
\keys_set:nn { csvsim } { autotabularray={#3}, #2}
}
\IfNoValueF {#4}
{
\IfNoValueTF {#5}
{
\keys_set:nn { csvsim } { generic~table~options = { { #4 } } }
}
{
\keys_set:nn { csvsim } { generic~table~options = { [ #4 ]{ #5 } } }
}
}
\__csvsim_loop:
}
\NewDocumentCommand \csvautolongtabularray { s +O{} m +o +o }
{
\keys_set:nn { csvsim } { default, every~csv }
\IfBooleanTF {#1}
{
\keys_set:nn { csvsim } { autolongtabularray*={#3}, #2}
}
{
\keys_set:nn { csvsim } { autolongtabularray={#3}, #2}
}
\IfNoValueF {#4}
{
\IfNoValueTF {#5}
{
\keys_set:nn { csvsim } { generic~table~options = { { #4 } } }
}
{
\keys_set:nn { csvsim } { generic~table~options = { [ #4 ]{ #5 } } }
}
}
\__csvsim_loop:
}
%---- sorting
\cs_new_protected_nopar:Npn \__csvsim_key_new_sorting_rule:nn #1#2
{
\keys_define:nn { csvsim }
{
sort~by~#1 .meta:n = { sort~by={#2} },
}
}
\NewDocumentCommand \csvsortingrule { }
{
\__csvsim_key_new_sorting_rule:nn
}
\keys_define:nn { csvsim }
{
preprocessor .tl_set:N = \l__csvsim_preprocessor_tl,
preprocessed~file .code:n = \__csvsim_set_filename:Nn \l__csvsim_ppfilename_str {#1},
csvsorter~command .code:n = \__csvsim_set_filename:Nn \l__csvsim_csvsorter_command_str {#1},
csvsorter~configpath .code:n = \__csvsim_set_filename:Nn\l__csvsim_csvsorter_configpath_str {#1},
csvsorter~log .code:n = \__csvsim_set_filename:Nn \l__csvsim_csvsorter_log_str {#1},
csvsorter~token .code:n = \__csvsim_set_filename:Nn \l__csvsim_csvsorter_token_str {#1},
no~preprocessing .meta:n = { preprocessor= },
sort~by .meta:n =
{
preprocessor=
{
\__csvsim_processor_csvsorter:nnn {#1}
}
},
new~sorting~rule .code:n = \__csvsim_key_new_sorting_rule:nn #1,
new~sorting~rule .value_required:n = true ,
}
\keys_set:nn { csvsim }
{
preprocessed~file = \c_sys_jobname_str _sorted._csv,
csvsorter~command = csvsorter,
csvsorter~configpath = .,
csvsorter~log = csvsorter.log,
csvsorter~token = \c_sys_jobname_str.csvtoken,
}
\cs_new_protected_nopar:Npn \__csvsim_processor_csvsorter:nnn #1#2#3
{
\sys_if_shell_unrestricted:TF
{
\__csvsim_set_temp_filename:n { #1 }
\msg_note:nnxx { csvsimple }{ sort-info }{ #2 }{ \l__csvsim_temp_filename_str }
\cs_if_exist:NF \g__csvsim_iow
{
\iow_new:N \g__csvsim_iow
}
\iow_open:Nn \g__csvsim_iow { \l__csvsim_csvsorter_token_str }
\iow_now:Nn \g__csvsim_iow { \ExplSyntaxOn \msg_error:nn { csvsimple }{ sort-error } \ExplSyntaxOff }
\iow_close:N \g__csvsim_iow
\sys_shell_now:x
{
"\l__csvsim_csvsorter_command_str" \c_space_tl
-c~ "\l__csvsim_csvsorter_configpath_str/\l__csvsim_temp_filename_str" \c_space_tl
-l~ "\l__csvsim_csvsorter_log_str" \c_space_tl
-t~ "\l__csvsim_csvsorter_token_str" \c_space_tl
-i~ "#2" \c_space_tl
-o~ "#3" \c_space_tl
-q~1
}
\file_input:n { \l__csvsim_csvsorter_token_str }
}
{
\msg_error:nn { csvsimple }{ sort-shell-escape }
}
}
%---- default
\keys_define:nn { csvsim }
{
% default for reset
default .meta:n =
{
file = unknown.csv,
no~preprocessing,
command = \csvline,
column~names~reset,
head,
column~names~detection,
check~column~count,
head~to~column~names~prefix = ,
head~to~column~names = false,
collect~data = false,
column~count = 0,
on~column~count~error =,
range =,
no~filter,
before~filter =,
after~filter =,
before~line =,
after~line =,
late~after~line =,
after~head =,
late~after~head =,
before~reading =,
after~reading =,
before~table =,
after~table =,
table~head =,
table~foot =,
no~table,
separator = comma,
respect~none,
},
}
\keys_set:nn { csvsim }
{
default
}