Advertisement
diaaa

Untitled

Feb 23rd, 2022
1,602
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Latex 11.47 KB | None | 0 0
  1. \ExplSyntaxOn
  2. % Step 1: reading the file
  3. \tl_new:N \l__diaa_tmpa_tl
  4. \ior_new:N \l__diaa_csv_ior
  5. \bool_new:N \l__diaa_csv_str_bool
  6. \bool_new:N \l__diaa_empty_item_bool
  7. \seq_new:N \l__diaa_csv_tmp_seq
  8.  
  9. % str mode (bool/star), key column, label, value columns, file
  10. \NewDocumentCommand \ReadCSV { s O{1} m O{} m }
  11. {
  12.     \IfBooleanTF {#1}
  13.     { \bool_set_true:N \l__diaa_csv_str_bool }
  14.     { \bool_set_false:N \l__diaa_csv_str_bool }
  15.     \diaa_csv_read:nnnn {#3} {#2} {#4} {#5}
  16. }
  17.  
  18. % label, key column, value columns, file
  19. \cs_new_protected:Npn \diaa_csv_read:nnnn #1 #2 #3 #4
  20. {
  21.     \tl_if_blank:nTF {#3}       % Detect number of columns and use 2 to last
  22.     {
  23.         \ior_open:NnTF \l__diaa_csv_ior {#4}
  24.         {
  25.             \bool_if:NTF \l__diaa_csv_str_bool
  26.             { \ior_str_get:NN }
  27.             { \ior_get:NN }
  28.             \l__diaa_csv_ior \l__diaa_tmpa_tl
  29.            
  30.             \ior_close:N \l__diaa_csv_ior
  31.             \seq_set_split:NnV \l_tmpa_seq { , } \l__diaa_tmpa_tl
  32.             \seq_clear:N \l__diaa_csv_tmp_seq
  33.             \int_step_inline:nnn { 2 } { \seq_count:N \l_tmpa_seq }
  34.             { \seq_put_right:Nn \l__diaa_csv_tmp_seq {##1} }
  35.         }
  36.         { \msg_expandable_error:nnn { diaa } { file-not-found } {#4} }
  37.     }
  38.     { \seq_set_split:Nnn \l__diaa_csv_tmp_seq { , } {#3} } % explicit columns
  39.    
  40.     \ior_open:NnTF \l__diaa_csv_ior {#4}
  41.     {
  42.         \prop_new:c { g__diaa_csv_#1_prop }
  43.         \__diaa_csv_read:nn {#1} {#2}
  44.         \ior_close:N \l__diaa_csv_ior
  45.     }
  46.     { \msg_expandable_error:nnn { diaa } { file-not-found } {#4} }
  47. }
  48.  
  49. \msg_new:nnn { diaa } { file-not-found }
  50. { File~`#1'~not~found. }
  51.  
  52. \cs_generate_variant:Nn \prop_put:Nnn { cxV }
  53.  
  54. % label, key column
  55. \cs_new_protected:Npn \__diaa_csv_read:nn #1 #2
  56. {
  57.     \bool_if:NTF \l__diaa_csv_str_bool
  58.     { \ior_str_map_inline:Nn }
  59.     { \ior_map_inline:Nn }
  60.     \l__diaa_csv_ior
  61.     {
  62.         \seq_set_split:Nnn \l_tmpa_seq { , } {##1} % split one CSV row
  63.         \tl_clear:N \l__diaa_tmpa_tl
  64.         \seq_map_inline:Nn \l__diaa_csv_tmp_seq
  65.         {
  66.             \tl_put_right:Nx \l__diaa_tmpa_tl { { \seq_item:Nn \l_tmpa_seq {####1} } }
  67.         }
  68.         \prop_put:cxV { g__diaa_csv_#1_prop }
  69.         { \seq_item:Nn \l_tmpa_seq {#2} }
  70.         \l__diaa_tmpa_tl
  71.     }
  72. }
  73.  
  74. %%%%%%%%%%%%%%%%%%%%%%%%
  75.  
  76. % https://tex.stackexchange.com/a/634894/2288
  77.  
  78. \keys_define:nn { diaa / getPolyFromRow }
  79. {
  80.     global-assignment .bool_set:N = \l__diaa_gpfr_global_assignment_bool,
  81.     global-assignment .default:n = true,
  82.     global-assignment .initial:n = false,
  83.     variable .tl_set:N = \l__diaa_gpfr_variable_name_tl,
  84.     variable .value_required:n = true,
  85.     variable .initial:n = X,
  86.     typographical-variant .str_set:N = \l__diaa_gpfr_typographical_variant_str,
  87.     typographical-variant .value_required:n = true,
  88.     typographical-variant .initial:n = default,
  89. }
  90.  
  91. % \getPolyFromRow will temporarily store the result in this variable. This
  92. % allows us not to lose the result when the group started for \keys_set:nn
  93. % ends (if the user chose to perform a local assignment, this must be done
  94. % after closing that group).
  95. \tl_new:N \g__diaa_gpfr_result_tl
  96.  
  97. % Options, macro for result, key, datafile label
  98. \NewDocumentCommand \getPolyFromRow { O{} m m m }
  99. {
  100.     \group_begin:
  101.     \keys_set:nn { diaa / getPolyFromRow } {#1}
  102.    
  103.     % Globally define _gfunc function aliases that perform global or local
  104.     % assignments depending on \l__diaa_gpfr_global_assignment_bool. They
  105.     % will be used *after* we close the current group.
  106.     \bool_set_true:N \l__diaa_gpfr_dtfa_global_aliases_bool
  107.     \__diaa_gpfr_define_tl_func_aliases:
  108.    
  109.     % Store the result in \g__diaa_gpfr_result_tl for now.
  110.     \bool_set_true:N \l__diaa_gpfr_global_assignment_bool
  111.     \diaa_get_poly_from_row:Nnn \g__diaa_gpfr_result_tl {#3} {#4}
  112.     \group_end:
  113.    
  114.     % Use the globally-defined aliases to perform the user-chosen (local or
  115.     % global) kind of assignment.
  116.     \__diaa_clear_gfunc:N #2    % make sure the tl var #2 is defined
  117.     \__diaa_set_eq_gfunc:NN #2 \g__diaa_gpfr_result_tl % set it
  118. }
  119.  
  120. % True to globally define the aliases and give them _gfunc names rather than
  121. % _func
  122. \bool_new:N \l__diaa_gpfr_dtfa_global_aliases_bool
  123.  
  124. \cs_new_protected:Npn \__diaa_gpfr_define_tl_func_aliases:
  125. {
  126.     \bool_if:NTF \l__diaa_gpfr_global_assignment_bool
  127.     {
  128.         \__diaa_gpfr_define_alias:nnN { clear }     { N }  \tl_gclear_new:N
  129.         \__diaa_gpfr_define_alias:nnN { set_eq }    { NN } \tl_gset_eq:NN
  130.         \__diaa_gpfr_define_alias:nnN { put_right } { Nn } \tl_gput_right:Nn
  131.     }
  132.     {
  133.         \__diaa_gpfr_define_alias:nnN { clear }     { N }  \tl_clear_new:N
  134.         \__diaa_gpfr_define_alias:nnN { set_eq }    { NN } \tl_set_eq:NN
  135.         \__diaa_gpfr_define_alias:nnN { put_right } { Nn } \tl_put_right:Nn
  136.     }
  137. }
  138.  
  139. % Locally or globally define an alias for a function. The alias is defined
  140. % globally with a gfunc name if \l__diaa_gpfr_dtfa_global_aliases_bool is true.
  141. %
  142. % #1: stem such as “clear”, “put_right”, etc.
  143. % #2: signature of the alias (e.g., “Nn”)
  144. \cs_new_protected:Npn \__diaa_gpfr_define_alias:nnN #1#2
  145. {
  146.     \bool_if:NTF \l__diaa_gpfr_dtfa_global_aliases_bool
  147.     { \cs_gset_eq:cN }
  148.     { \cs_set_eq:cN }
  149.     {
  150.         __diaa_#1_
  151.         \bool_if:NT \l__diaa_gpfr_dtfa_global_aliases_bool { g }
  152.         func:#2
  153.     }
  154. }
  155.  
  156. \int_new:N \l__diaa_gpfr_degree_int
  157. \tl_new:N \l__dia_gpfr_row_values_tl
  158. \cs_generate_variant:Nn \__diaa_put_right_func:Nn { Nx }
  159. \cs_generate_variant:Nn \__diaa_get_poly_from_row_append_monomial:Nnn { NnV }
  160.  
  161. % Macro for result, key, datafile label
  162. \cs_new_protected:Npn \diaa_get_poly_from_row:Nnn #1#2#3
  163. {
  164.     % Locally define function aliases that perform global or local assignments
  165.     % depending on \l__diaa_gpfr_global_assignment_bool: \__diaa_clear_func:Nn,
  166.     % \__diaa_put_right_func:Nn, etc.
  167.     \bool_set_false:N \l__diaa_gpfr_dtfa_global_aliases_bool
  168.     \__diaa_gpfr_define_tl_func_aliases:
  169.    
  170.     % Retrieve the coefficients
  171.     \prop_get:cnN { g__diaa_csv_#3_prop } {#2} \l__dia_gpfr_row_values_tl
  172.    
  173.     % Let's put (1 + degree) for now in this int variable.
  174.     \int_zero:N \l__diaa_gpfr_degree_int
  175.     \tl_map_inline:Nn \l__dia_gpfr_row_values_tl
  176.     {
  177.         \tl_if_empty:nT {##1} { \tl_map_break: }
  178.         \int_incr:N \l__diaa_gpfr_degree_int
  179.     }
  180.    
  181.     \__diaa_clear_func:N #1        % initialize #1 as a tl var if necessary
  182.     \bool_set_false:N \l_tmpa_bool % true: add + operator if next coeff is > 0
  183.    
  184.     \tl_map_inline:Nn \l__dia_gpfr_row_values_tl % loop over the coefficients
  185.     {
  186.         % Degree of the monomial we're about to output
  187.         \int_decr:N \l__diaa_gpfr_degree_int
  188.         % Early termination condition if the row is not full of coefficients
  189.         \int_compare:nNnT { \l__diaa_gpfr_degree_int } < { 0 }
  190.         { \tl_map_break: }
  191.        
  192.         \fp_compare:nNnF {##1} = { 0 }
  193.         {
  194.             % Insert a + operator if necessary
  195.             \bool_if:NTF \l_tmpa_bool
  196.             {
  197.                 \fp_compare:nNnT {##1} > { 0 }
  198.                 { \__diaa_put_right_func:Nn #1 { + } }
  199.             }
  200.             { \bool_set_true:N \l_tmpa_bool }
  201.            
  202.             % Insert the monomial
  203.             \__diaa_get_poly_from_row_append_monomial:NnV #1 {##1}
  204.             \l__diaa_gpfr_variable_name_tl
  205.         }
  206.     }
  207. }
  208.  
  209. \msg_new:nnn { diaa } { gpfr-unknown-typo-variant }
  210. { Unknown~typographical~variant~for~\token_to_str:N \getPolyFromRow :~`#1'. }
  211.  
  212. \cs_generate_variant:Nn \str_case_e:nnF { V }
  213. \cs_generate_variant:Nn \msg_error:nnn { nnV }
  214.  
  215. % Macro, coefficient, variable name
  216. \cs_new_protected:Npn \__diaa_get_poly_from_row_append_monomial:Nnn #1#2#3
  217. {
  218.     \str_case_e:VnF \l__diaa_gpfr_typographical_variant_str
  219.     {
  220.         { default }     { \tl_set:Nn \l_tmpa_tl { #2 \times #3 ^ } }
  221.         { with-braces } { \tl_set:Nn \l_tmpa_tl { #2 \times {#3} ^ } }
  222.     }
  223.     {
  224.         \msg_error:nnV { diaa } { gpfr-unknown-typo-variant }
  225.         \l__diaa_gpfr_typographical_variant_str
  226.     }
  227.    
  228.     \__diaa_put_right_func:Nx #1
  229.     {
  230.         \int_case:nnF { \l__diaa_gpfr_degree_int } % depending on the degree...
  231.         {
  232.             { 0 } { \exp_not:n {#2} } % degree 0 → only the coefficient
  233.             { 1 } { \exp_not:n { #2 \times #3 } }
  234.         }
  235.         { % Other degrees
  236.             \exp_not:V \l_tmpa_tl % use the selected variant
  237.             % Use braces in case the exponent has several digits
  238.             { \int_use:N \l__diaa_gpfr_degree_int }
  239.         }
  240.     }
  241. }
  242.  
  243. %%%%%%%%%%%%%%%%%%%%%
  244.  
  245. % Step 2: getting the values
  246. % star → global assignment, macro or tl var, value column, key, label
  247. \NewDocumentCommand \getValue { s m O{1} m m }
  248. {
  249.     \IfBooleanTF {#1} { \tl_gset:Nx } { \tl_set:Nx }
  250.     #2 { \diaa_csv_item:nnn {#4} {#3} {#5} }
  251.     \tl_if_empty:NT #2
  252.     { \msg_warning:nnnnn { diaa } { item-empty } {#3} {#4} {#5} }
  253. }
  254.  
  255. % key, value column, label
  256. \NewExpandableDocumentCommand \CSVItem { m O{1} m }
  257. { \diaa_csv_item:nnn {#1} {#2} {#3} }
  258.  
  259. % Version with error if empty
  260. % \NewExpandableDocumentCommand \CSVItem { m O{1} m }
  261. %   {
  262.     %     \exp_args:Nf \__diaa_check_empty_item:nnnn
  263.     %       { \diaa_csv_item:nnn {#1} {#2} {#3} } {#2} {#1} {#3}
  264.     %   }
  265. % \cs_new:Npn \__diaa_check_empty_item:nnnn #1 #2 #3 #4
  266. %   {
  267.     %     \tl_if_empty:nTF {#1}
  268.     %       { \msg_expandable_error:nnnnn { diaa } { item-empty } {#2} {#3} {#4} }
  269.     %       {#1}
  270.     %   }
  271.  
  272. \cs_generate_variant:Nn \tl_item:nn { f }
  273.  
  274. % key, value column, label
  275. \cs_new:Npn \diaa_csv_item:nnn #1 #2 #3
  276. {
  277.     \prop_if_exist:cTF { g__diaa_csv_#3_prop }
  278.     {
  279.         \prop_if_in:cnTF { g__diaa_csv_#3_prop } {#1}
  280.         {
  281.             \exp_args:NNf \__diaa_check_column_range:Nnn \use_i:nn
  282.             { \prop_item:cn { g__diaa_csv_#3_prop } {#1} } {#2}
  283.         }
  284.         { \msg_expandable_error:nnnn { diaa } { key-undefined } {#1} {#3} }
  285.     }
  286.     { \msg_expandable_error:nnn { diaa } { csv-undefined } {#3} }
  287. }
  288.  
  289. \cs_new:Npn \__diaa_check_column_range:Nnn #1 #2 #3
  290. {
  291.     \bool_lazy_or:nnTF
  292.     { \int_compare_p:nNn {#3} = { 0 } }
  293.     { \int_compare_p:nNn { \tl_count:n {#2} } < { \int_abs:n {#3} } }
  294.     { \msg_expandable_error:nnn { diaa } { out-of-range } {#3} }
  295.     { \exp_args:Nf #1 { \tl_item:nn {#2} {#3} } {#3} }
  296. }
  297.  
  298. \msg_new:nnn { diaa } { csv-undefined } { CSV~database~''#1''~is~undefined! }
  299. \msg_new:nnn { diaa } { key-undefined } {Parameter~''#1''~is~not~found~in~CSV~''#2''! }
  300. \msg_new:nnn { diaa } { out-of-range } { Column~#1~is~out~of~range! }
  301. %\msg_new:nnn { diaa } { item-empty }
  302. %{ Column~#1~of~''#2''~in~CSV~''#3''~is~empty! }
  303. \msg_new:nnn { diaa } { item-empty }
  304. { Empty~column~#1~of~''#2''~in~CSV~''#3''! }%Item~#1~from~`#2'~in~CSV~`#3'~is~empty!
  305. \msg_new:nnn { diaa } { empty-row-item }
  306. { Empty~item~#1~\msg_line_context:! }
  307. \msg_new:nnn { diaa } { row-empty }
  308. { Empty~parameter~''#1''~in~CSV~''#2''! }
  309.  
  310.  
  311. \cs_new:Npn \__diaa_check_empty:nn #1 #2
  312. {
  313.     \tl_if_empty:nT {#1}
  314.     { \msg_warning:nnn { diaa } { empty-row-item } {#2} }
  315.     #1
  316. }
  317.  
  318. % star → global assignment, macro, key, label
  319. \NewDocumentCommand \getRow { s m m m }
  320. {
  321.     \prop_if_exist:cTF { g__diaa_csv_#4_prop }
  322.     {
  323.         \prop_get:cnNTF { g__diaa_csv_#4_prop } {#3} \l__diaa_tmpa_tl
  324.         {
  325.             \bool_set_true:N \l__diaa_empty_item_bool
  326.             \tl_map_inline:Nn \l__diaa_tmpa_tl
  327.             {
  328.                 \tl_if_empty:nF {##1}
  329.                 { \bool_set_false:N \l__diaa_empty_item_bool }
  330.             }
  331.             \bool_if:NT \l__diaa_empty_item_bool
  332.             { \msg_warning:nnnn { diaa } { row-empty } {#3} {#4} }
  333.             \IfBooleanTF {#1} { \cs_gset_nopar:Npx } { \cs_set_nopar:Npx } #2 [ ##1 ]
  334.             {
  335.                 \exp_not:N \str_if_eq:nnTF {##1} { non-empty }
  336.                 {
  337.                     \exp_not:N \__diaa_nb_nonempty_items_in_row:nw { 0 }
  338.                     \exp_not:V \l__diaa_tmpa_tl
  339.                     \exp_not:n { \q_recursion_tail \q_recursion_stop }
  340.                 }
  341.                 {
  342.                     \exp_not:N \__diaa_check_column_range:Nnn
  343.                     \exp_not:N \__diaa_check_empty:nn
  344.                     { \exp_not:V \l__diaa_tmpa_tl } {##1}
  345.                 }
  346.             }
  347.         }
  348.         { \msg_expandable_error:nnnn { diaa } { key-undefined } {#3} {#4} }
  349.     }
  350.     { \msg_expandable_error:nnn { diaa } { csv-undefined } {#4} }
  351. }
  352.  
  353.  
  354. \cs_new:Npn \__diaa_nb_nonempty_items_in_row:nw #1#2
  355. {
  356.     \quark_if_recursion_tail_stop_do:nn {#2} { \int_eval:n {#1} }
  357.     \tl_if_empty:nTF {#2}
  358.     { \__diaa_nb_nonempty_items_in_row:nw {#1} }
  359.     { \__diaa_nb_nonempty_items_in_row:nw { #1 + 1 } }
  360. }
  361. \ExplSyntaxOff
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement