Saving arguments of commands to be used later
up vote
6
down vote
favorite
I'd like to create a command to print some contacts inserted with same 3 commands: name{},work{},email{}
.
Every time we use those 3 commands, a new contact is collected and then all of them is printed as below.
I suspect that I need some kind of array of list, to save the contacts, but I have no idea how to search for this.
MWE
documentclass{article}
makeatletter
deflistcontacts{%
noindenttextbf{@name}par
noindenttextit{@work}par
noindenttexttt{@email}par
vskip 1in % to start a new block of contact
}
newcommand{name}[1]{def@name{#1}}
newcommand{work}[1]{def@work{#1}}
newcommand{email}[1]{def@email{#1}}
newcommand{information}[3]{%
name{#1}
work{#2}
email{#3}
}
makeatother
information{Faa Foo}{Univ. Blah}{goo@goo.com}
%% I'd like to insert a new one with same commands
%name{Faa Foo}
%work{Univ. Blah}
%email{goo@goo.com}
% and repeat the process with different number of blocks,
%that is, could be any finite number of contacts.
begin{document}
listcontacts
end{document}
macros
add a comment |
up vote
6
down vote
favorite
I'd like to create a command to print some contacts inserted with same 3 commands: name{},work{},email{}
.
Every time we use those 3 commands, a new contact is collected and then all of them is printed as below.
I suspect that I need some kind of array of list, to save the contacts, but I have no idea how to search for this.
MWE
documentclass{article}
makeatletter
deflistcontacts{%
noindenttextbf{@name}par
noindenttextit{@work}par
noindenttexttt{@email}par
vskip 1in % to start a new block of contact
}
newcommand{name}[1]{def@name{#1}}
newcommand{work}[1]{def@work{#1}}
newcommand{email}[1]{def@email{#1}}
newcommand{information}[3]{%
name{#1}
work{#2}
email{#3}
}
makeatother
information{Faa Foo}{Univ. Blah}{goo@goo.com}
%% I'd like to insert a new one with same commands
%name{Faa Foo}
%work{Univ. Blah}
%email{goo@goo.com}
% and repeat the process with different number of blocks,
%that is, could be any finite number of contacts.
begin{document}
listcontacts
end{document}
macros
add a comment |
up vote
6
down vote
favorite
up vote
6
down vote
favorite
I'd like to create a command to print some contacts inserted with same 3 commands: name{},work{},email{}
.
Every time we use those 3 commands, a new contact is collected and then all of them is printed as below.
I suspect that I need some kind of array of list, to save the contacts, but I have no idea how to search for this.
MWE
documentclass{article}
makeatletter
deflistcontacts{%
noindenttextbf{@name}par
noindenttextit{@work}par
noindenttexttt{@email}par
vskip 1in % to start a new block of contact
}
newcommand{name}[1]{def@name{#1}}
newcommand{work}[1]{def@work{#1}}
newcommand{email}[1]{def@email{#1}}
newcommand{information}[3]{%
name{#1}
work{#2}
email{#3}
}
makeatother
information{Faa Foo}{Univ. Blah}{goo@goo.com}
%% I'd like to insert a new one with same commands
%name{Faa Foo}
%work{Univ. Blah}
%email{goo@goo.com}
% and repeat the process with different number of blocks,
%that is, could be any finite number of contacts.
begin{document}
listcontacts
end{document}
macros
I'd like to create a command to print some contacts inserted with same 3 commands: name{},work{},email{}
.
Every time we use those 3 commands, a new contact is collected and then all of them is printed as below.
I suspect that I need some kind of array of list, to save the contacts, but I have no idea how to search for this.
MWE
documentclass{article}
makeatletter
deflistcontacts{%
noindenttextbf{@name}par
noindenttextit{@work}par
noindenttexttt{@email}par
vskip 1in % to start a new block of contact
}
newcommand{name}[1]{def@name{#1}}
newcommand{work}[1]{def@work{#1}}
newcommand{email}[1]{def@email{#1}}
newcommand{information}[3]{%
name{#1}
work{#2}
email{#3}
}
makeatother
information{Faa Foo}{Univ. Blah}{goo@goo.com}
%% I'd like to insert a new one with same commands
%name{Faa Foo}
%work{Univ. Blah}
%email{goo@goo.com}
% and repeat the process with different number of blocks,
%that is, could be any finite number of contacts.
begin{document}
listcontacts
end{document}
macros
macros
asked Nov 15 at 18:00
Sigur
23.3k353135
23.3k353135
add a comment |
add a comment |
4 Answers
4
active
oldest
votes
up vote
3
down vote
accepted
This is similar to Steven Seglets solution with slightly different packaging. You can show a single contact with ShowContact{}
or list all the contact with listcontacts
Notes:
- The values are stored based on
#1
which is used as the key to access the contacts. An attempt to reuse the same key is now flagged as an error. - This has now been updated to add a
medskip
between entries when the entire list is printed. Themedskip
is not added before the first entry, nor after the last as shown in the figure.
Code:
documentclass{article}
usepackage{etoolbox}
makeatletter
newtoggle{@IsFirstEntryInList}
newcommand*{@ShowContact}[1]{%
iftoggle{@IsFirstEntryInList}{%
globaltogglefalse{@IsFirstEntryInList}%
}{%
medskip% <-- separator between entries
}%
ShowContact{#1}%
}
newcommand*{ShowContact}[1]{%
parnoindenttextbf{csuse{name #1}}%
parnoindenttextit{csuse{work #1}}%
parnoindenttexttt{csuse{email #1}}%
}%
%% https://tex.stackexchange.com/a/14394/4301
newcommand*{listcontacts}{% Initialize
globaltoggletrue{@IsFirstEntryInList}%
}
newcommand{AddToListOfContacts}[1]{%
g@addto@macrolistcontacts{{#1}}%
}
newcommand{information}[3]{%
ifcsdef{name #1}{%
PackageError{jobname}{Multiple uses of the key: '#1'}{}%
}{%
csdef{name #1}{#1}%
csdef{work #1}{#2}%
csdef{email #1}{#3}%
AddToListOfContacts{unexpanded{@ShowContact{#1}}}%
}%
}
makeatother
information{Faa Foo}{Univ. Blah}{goo@goo.com}
information{Harvard}{Harvard University}{me@harvard.com}
%information{Harvard}{xxx University}{me@harvard.com}% <-- Triggers an error
begin{document}
noindent
To show one contact:
ShowContact{Harvard}
medskipnoindent
To show all contacts:
listcontacts
parnoindent
Text following to check that there is no extra space at end...
end{document}
Interesting. In this case, the contacts are accessed via argument value, not via a number, right?
– Sigur
Nov 15 at 18:28
@Sigur: Yes, the first parameter is used as the key to access the information. This is really helpful if you have a large number of contacts.
– Peter Grill
Nov 15 at 18:30
Since I'm going to share this file, do you know ifetoolbox
comes with a basic installation? Because I know thattikz
does not.
– Sigur
Nov 15 at 18:30
Yes,etoolbox
is in the standard distribution. But, so istikz
so not sure why you think otherwise. Also, have added error checking in the updated version.
– Peter Grill
Nov 15 at 18:34
1
@Sigur: As requested, I have updated it inserts amedskip
only between entries. You can replace themedskip
with the symbol you desire.
– Peter Grill
Nov 16 at 6:39
|
show 8 more comments
up vote
4
down vote
I have made it so that @name[<index>]
@work[<index>]
, and @email[<index>]
are arrays, where the index is stepped with every call to information{}{}{}
.
listcontact{<index>}
will provide the contact info for the one specified index. In the MWE, I loop through all indices.
documentclass{article}
usepackage{pgffor}
makeatletter
newcounter{infocnt}
newcommand{name}[1]{%
expandafterdefcsname @name[theinfocnt]endcsname{#1}}
newcommand{work}[1]{%
expandafterdefcsname @work[theinfocnt]endcsname{#1}}
newcommand{email}[1]{%
expandafterdefcsname @email[theinfocnt]endcsname{#1}}
newcommand{information}[3]{%
stepcounter{infocnt}%
name{#1}%
work{#2}%
email{#3}%
}
newcommandlistcontact[1]{noindent%
NAME: textbf{csname @name[#1]endcsname}\
WORK: textbf{csname @work[#1]endcsname}\
EMAIL: textbf{csname @email[#1]endcsname}par
vskip 1in
}
makeatother
information{Faa Foo}{Univ. Blah}{goo@goo.com}
information{XXX}{YYY}{ZZZ@goo.com}
begin{document}
foreachx in {1,2,...,theinfocnt}{listcontact{x}}
end{document}
If I had my 'druthers, though, I would input the list all at once, quite simply, with the same output. The listofitems
package immediately stores the list as an accessible array:
documentclass{article}
usepackage{listofitems}
newcommandlistcontact[1]{noindent%
NAME: textbf{contacts[#1,1]}\
WORK: textbf{contacts[#1,2]}\
EMAIL: textbf{contacts[#1,3]}par
vskip 1in
}
setsepchar{\/&}
begin{document}
readlist*contacts{
Faa Foo & Univ. Blah & goo@goo.com\
XXX & YYY & ZZZ@goo.com}
foreachitemxincontacts{listcontact{xcnt}}
Here is the email of contact 2: contacts[2,3].
end{document}
With a small supplement from the readarray
package, the list of contacts could even be stored in an external file.
Very nice, specially sincetikz
is needed only for the loop.
– Sigur
Nov 15 at 18:18
@Sigur Oops. I redefined it (didn't see it defined earlier).
– Steven B. Segletes
Nov 15 at 18:20
No problem, I observed that. Thanks a lot
– Sigur
Nov 15 at 18:21
Do you know another way to print all without usingtikz
? Maybe using the value of the counter only? I'm going to share the file andtikz
could be not available.
– Sigur
Nov 15 at 18:31
1
@Sigur I changed it topgffor
. However, I also added technique #2, which is far simpler, if you can add all names at once.
– Steven B. Segletes
Nov 15 at 18:33
add a comment |
up vote
3
down vote
This is “property lists” playground. Here I define newcontact
for defining a contact with a key-value interface.
With newcontactscheme
one defines different ways to print the data; default
is used by listcontact
if no optional argument is supplied. In the definition, use getcontact{<key>}{#1}
to print the value corresponding to <key>
for the current contact, represented by #1
.
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{newcontact}{mm}
{% #1 = contact label, #2 = data
prop_new:c { g_sigur_contact_#1_prop }
prop_gset_from_keyval:cn { g_sigur_contact_#1_prop } { #2 }
}
NewDocumentCommand{listcontact}{O{default}m}
{
cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
__sigur_contact_list:n { #2 }
}
NewDocumentCommand{getcontact}{mm}
{
sigur_contact_print:nn { #1 } { #2 }
}
NewDocumentCommand{newcontactscheme}{m+m}
{% #1 = scheme name, #2 = definition
cs_new_protected:cn { sigur_contact_list_#1:n } { #2 }
}
cs_new_protected:Nn sigur_contact_print:nn
{
prop_item:cn { g_sigur_contact_#2_prop } { #1 }
}
ExplSyntaxOff
newcontactscheme{default}{%
parnoindent
getcontact{name}{#1}\
getcontact{work}{#1}\
getcontact{email}{#1}par
}
newcontactscheme{short}{%
getcontact{name}{#1}, getcontact{email}{#1}%
}
newcontactscheme{alternate}{%
begin{tabular}[t]{@{}l@{ }l@{}}
Name: & getcontact{name}{#1} \
Work: & getcontact{work}{#1} \
Email: & texttt{getcontact{email}{#1}}
end{tabular}%
}
newcontact{foo}{
name=Faa Foo,
work=Univ. Blah,
email=goo@goo.com
}
newcontact{xxx}{
name=XXX,
work=YYY,
email=ZZZ@goo.com
}
begin{document}
listcontact{foo}
medskip
listcontact{xxx}
medskip
Short: listcontact[short]{xxx}
medskip
Alternate: listcontact[alternate]{foo}
end{document}
A version that also defines listallcontacts
(the optional argument is one of the defined schemes).
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{newcontact}{mm}
{% #1 = contact label, #2 = data
prop_new:c { g_sigur_contact_#1_prop }
prop_gset_from_keyval:cn { g_sigur_contact_#1_prop } { #2 }
seq_gput_right:Nn g_sigur_contact_seq { #1 }
}
NewDocumentCommand{listcontact}{O{default}m}
{
cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
__sigur_contact_list:n { #2 }
}
NewDocumentCommand{listallcontacts}{O{default}}
{
cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
seq_map_inline:Nn g_sigur_contact_seq
{
__sigur_contact_list:n { ##1 } par
}
}
NewDocumentCommand{getcontact}{mm}
{
sigur_contact_print:nn { #1 } { #2 }
}
NewDocumentCommand{newcontactscheme}{m+m}
{% #1 = scheme name, #2 = definition
cs_new_protected:cn { sigur_contact_list_#1:n } { #2 }
}
seq_new:N g_sigur_contact_seq
cs_new_protected:Nn sigur_contact_print:nn
{
prop_item:cn { g_sigur_contact_#2_prop } { #1 }
}
ExplSyntaxOff
newcontactscheme{default}{%
parnoindent
getcontact{name}{#1}\
getcontact{work}{#1}\
getcontact{email}{#1}par
}
newcontactscheme{short}{%
getcontact{name}{#1}, getcontact{email}{#1}%
}
newcontactscheme{alternate}{%
begin{tabular}[t]{@{}l@{ }l@{}}
Name: & getcontact{name}{#1} \
Work: & getcontact{work}{#1} \
Email: & texttt{getcontact{email}{#1}}
end{tabular}%
}
newcontact{foo}{
name=Faa Foo,
work=Univ. Blah,
email=goo@goo.com
}
newcontact{xxx}{
name=XXX,
work=YYY,
email=ZZZ@goo.com
}
begin{document}
listcontact{foo}
medskip
listcontact{xxx}
medskip
Short: listcontact[short]{xxx}
medskip
Alternate: listcontact[alternate]{foo}
medskip
listallcontacts
medskip
listallcontacts[short]
end{document}
I never studied or tried to learnxparse
. The result is amazing. Nice!
– Sigur
Nov 15 at 21:04
add a comment |
up vote
0
down vote
This "answer" does not answer your question.
A few remarks about the pitfalls of database-management in LaTeX
A few remarks about database-management in general:
Usually data is organized in so-called data-bases.
A data-base could, e.g., be a list of contact-details.
Each person or organization that you wish to contact might within the data-base be connected to a data-record which holds all the contact-details related to that person/organization.
Therefore a data-record itself could be organized by means of data-fields whereby each field serves for storing/providing information that belongs to a specific category.
Thus the logical structure of a data-base could be something like:
Data-base: contact-details
==========================
Data-record 001:
----------------
Value of data-field "Name":=John Doe
Value of data-field "Work":=whistle blower
Value of data-field "E-Mail":=Whistle@fake.email.address
Data-record 002:
----------------
Value of data-field "Name":=Jane Smith
Value of data-field "Work":=employée at department of alternative facts
Value of data-field "E-Mail":=AltFacts@fake.email.address
...
You need means
- both for identifying each record that belongs to a data-base
- and for keeping the single records that belong to a data-base distinguishable from each other.
The data-fields "Name" or "Work" or "E-Mail" are not suitable for this purpose.
E.g., some day there might be records about two different people in the data-base that have the same name.
Thus in data-base-management, it is common practise to indroduce in the structure of data-records a data-field which for each data-record holds a piece of information which does not occur within the corresponding data-field of any other data-record.
Usually this data-field is called a "primary key".
Often this primary-key is just some item of continuous numeration which is obtained by continuously numerating data-records.
When introducing a primary-key, the data-base "contact details" could look like this:
Data-base: contact-details
==========================
Data-record 001:
----------------
Value of data-field "Primary Key":=001
Value of data-field "Name":=John Doe
Value of data-field "Work":=whistle blower
Value of data-field "E-Mail":=Whistle@fake.email.address
Data-record 002:
----------------
Value of data-field "Primary Key":=002
Value of data-field "Name":=Jane Smith
Value of data-field "Work":=employée at department of alternative facts
Value of data-field "E-Mail":=AltFacts@fake.email.address
When doing this, you can - besides the single data-records - also maintain
- a list of primary-keys belonging to the data-base an
- a counter denoting the amount of records belonging to the data-base:
Data-base: contact-details
==========================
Amount of data-records: 2
List of primary-keys: {001}, {002}
Data-record 001:
----------------
Value of data-field "Primary Key":=001
Value of data-field "Name":=John Doe
Value of data-field "Work":=whistle blower
Value of data-field "E-Mail":=Whistle@fake.email.address
Data-record 002:
----------------
Value of data-field "Primary Key":=002
Value of data-field "Name":=Jane Smith
Value of data-field "Work":=employée at department of alternative facts
Value of data-field "E-Mail":=AltFacts@fake.email.address
The list of primary-keys would be of special interest for sorting out specific data-records:
Assume you wish to retrieve the e-mail-address of Jane Smith:
In terms of pseudo-code, you would do this via a directive like:
Iterate on that list of primary-keys that belongs to
the data-base "contact-details" as follows:
In each iteration "look" at the value of the data-field "Name"
of that data-record whose data-field "Primary Key" equals the
current list element.
If that value equals "Jane Smith", print out the value of the
data-field "E-Mail" of that data-record.
Pitfalls related to (La)TeX:
When implementing such things in terms of (La)TeX, you will encounter a few problems which have to do with the fact that (La)TeX is a macro-language which does some pre-processing of input in terms of reading and tokenizing input:
For example, curly braces ({
and }
) have a specific meaning in LaTeX and usually each opening-brace must habe a matching closing-brace and vice versa.
For example, the percent-character (%
) has a specific meaning in LaTeX.
But according to RFC 2822 e-mail-adresses may contain unbalanced curly braces and percent-characters.
Therefore maintaining such entries via a data-base that is provided in terms of (La)TeX-input might be related to circumstances which the not-so experienced user might see as problems.
E.g., Alt}Fa%c#1ts@fake.email.address
would be a nice e-mail-address.
But how to get the value Alt}Fa%c#1ts@fake.email.address
into a data-record's data-field "E-Mail" in case the data-base in question is maintained in (La)TeX?
At first glimpse you could do it by means of macros that deliver the desired symbols in question:
Something like:
Value of data-field "E-Mail":=Altleftbrace Fatextpercent chash1ts@fake.email.address
Also the names of people/organizations might contain characters/symbols which the input-encoding in which the (La)TeX-file is written does not contain.
Assume one of the persons whose contact-details are to be maintained has the name Alaïa Maëlys Gambolpütty while the data-base is written in a (La)TeX-input-file that is encoded in ASCII.
In such a case you must do it in terms of control-sequence-tokens whose names are formed by characters within the range of the input-encoding.
But such control-sequences make sorting out specific data-records difficult.
Therefore it might be a good idea to maintain each piece of data twice:
Once written only by means of characters of the input-encoding in question.
Once written in a way where also LaTeX-control-sequences that deliver the desired characters/symbols may occur:
Data-base: contact-details
==========================
Amount of data-records: 3
List of primary-keys: {001}, {002}, {003}
Data-record 001:
----------------
Value of data-field "Primary Key":=001
Value of data-field "Name" in input-encoding-representation:=John Doe
Value of data-field "Name" in LaTeX-representation:=John Doe
Value of data-field "Work" in input-encoding-representation:=whistle blower
Value of data-field "Work" in LaTeX-representation:=whistle blower
Value of data-field "E-Mail" in input-encoding-representation:=Whistle@fake.email.address
Value of data-field "E-Mail" in LaTeX-representation:=Whistle@fake.email.address
Data-record 002:
----------------
Value of data-field "Primary Key":=002
Value of data-field "Name" in input-encoding-representation:=Jane Smith
Value of data-field "Name" in LaTeX-representation:=Jane Smith
Value of data-field "Work" in input-encoding-representation:=employee at department of alternative facts
Value of data-field "Work" in LaTeX-representation:=employ'ee at department of alternative facts
Value of data-field "E-Mail" in input-encoding-representation:=AltFacts@fake.email.address
Value of data-field "E-Mail" in LaTeX-representation:=AltFacts@fake.email.address
Data-record 003:
----------------
Value of data-field "Primary Key":=003
Value of data-field "Name" in input-encoding-representation:=Alaia Maelys Gambolpuetty
Value of data-field "Name" in LaTeX-representation:=Ala"{i}a Ma"{e}lys Gambolp"{u}tty
Value of data-field "Work" in input-encoding-representation:=employee at department of alternative facts
Value of data-field "Work" in LaTeX-representation:=employée at department of alternative facts
Value of data-field "E-Mail" in input-encoding-representation:=Alt}Fa%c#1ts@fake.email.address
Value of data-field "E-Mail" in LaTeX-representation:=Altleftbrace Fatextpercent chash1ts@fake.email.address
...
With such an approach you could implement an interface where searching and sorting out takes place in terms of input-encoding-representation and delivers data in terms of LaTeX-representation.
With such an interface, one stage would always include reading and tokenizing the input-encoding-representations under verbatim-catcode-régime.
This is feasible but makes using the macros that form the interface
- within pure-expansion-contexts impossible.
- within the definition-texts of other macros cumbersome.
With such an interface, it would also be a good idea to have everything that denotes names of databases or names of data-fields or values in input-encoding-representation evaluate to characters of the input-encoding.
Therefore for proper error-checking a routine would be useful which does fully evaluate/expand arguments and then does check whether the expansion-result does hold character-tokens obeying the verbatim-catcode-régime only.
Full evaluation/expansion of an argument that might hold arbitrary tokens is already a nice problem.
An easy approach would be using edef
.
For one thing this also would break expandability of the interface.
For another thing edef
is not totally safe with arbitrary tokens.
E.g., look at
edeftest{%
Where does the definition text
stop?iffalse{fi Here?} Or Here?{iffalse}fi
}
I think a minimalist interface for some sort of database-management is feasible in LaTeX – with things like:
NewInitializedDataRecord{<Primary Key>}%
{<Name>}%
{<Work>}%
{<EMail>}%
NewEmptyDataRecord{<Primary Key>}
AddNewDataFieldToDataRecord{<Primary Key>}{<Name of data-field>}{<Value>}%
VerbatimizedAddNewDataFieldToDataRecord{<Primary Key>}{<Name of data-field>}|<Value>|% <- verbatim-arg
(extraction of verbatimized values of data-fields via scantokens...)
PrintFieldValueFromDataRecord{<Primary Key>}{<Name of data-field>}
PrintDataRecord{<Primary Key>}
PrintAllDataRecords
PrintAllDataRecordsWithSpecificDatFieldValue{<Name of data-field>}{<Specific Value>}
But before going into details, specification about the tokens that might form values of data-fields and about their treatment when comparing values of data-fields is needed.
I am not sure if I understood your comments. Anyway, thanks for attention. Let me inform that the contacts come from authors of a paper, so I think that two exactly equal names could happen rarely.
– Sigur
Nov 16 at 18:13
Your question actually is about some sort of whatsoever minimalist database-management. :-) I extended my answer in the hope of pointing out some of the pitfalls related to whatsoever minimalist database-management in terms of a macro language. :-)
– Ulrich Diez
Nov 16 at 21:29
Well, thanks for your work. But I confess that I have no idea how to understand it... lol
– Sigur
Nov 16 at 21:33
I think you want to say “From relational algebra we know that it is not a good idea to assign to each data-record its own unique primary-key as a data-field of its own of that data-record.”.
– egreg
Nov 16 at 21:48
@UlrichDiez The formulation is way better now. For the same reason I assigned a label to each contact.
– egreg
Nov 16 at 22:31
add a comment |
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
3
down vote
accepted
This is similar to Steven Seglets solution with slightly different packaging. You can show a single contact with ShowContact{}
or list all the contact with listcontacts
Notes:
- The values are stored based on
#1
which is used as the key to access the contacts. An attempt to reuse the same key is now flagged as an error. - This has now been updated to add a
medskip
between entries when the entire list is printed. Themedskip
is not added before the first entry, nor after the last as shown in the figure.
Code:
documentclass{article}
usepackage{etoolbox}
makeatletter
newtoggle{@IsFirstEntryInList}
newcommand*{@ShowContact}[1]{%
iftoggle{@IsFirstEntryInList}{%
globaltogglefalse{@IsFirstEntryInList}%
}{%
medskip% <-- separator between entries
}%
ShowContact{#1}%
}
newcommand*{ShowContact}[1]{%
parnoindenttextbf{csuse{name #1}}%
parnoindenttextit{csuse{work #1}}%
parnoindenttexttt{csuse{email #1}}%
}%
%% https://tex.stackexchange.com/a/14394/4301
newcommand*{listcontacts}{% Initialize
globaltoggletrue{@IsFirstEntryInList}%
}
newcommand{AddToListOfContacts}[1]{%
g@addto@macrolistcontacts{{#1}}%
}
newcommand{information}[3]{%
ifcsdef{name #1}{%
PackageError{jobname}{Multiple uses of the key: '#1'}{}%
}{%
csdef{name #1}{#1}%
csdef{work #1}{#2}%
csdef{email #1}{#3}%
AddToListOfContacts{unexpanded{@ShowContact{#1}}}%
}%
}
makeatother
information{Faa Foo}{Univ. Blah}{goo@goo.com}
information{Harvard}{Harvard University}{me@harvard.com}
%information{Harvard}{xxx University}{me@harvard.com}% <-- Triggers an error
begin{document}
noindent
To show one contact:
ShowContact{Harvard}
medskipnoindent
To show all contacts:
listcontacts
parnoindent
Text following to check that there is no extra space at end...
end{document}
Interesting. In this case, the contacts are accessed via argument value, not via a number, right?
– Sigur
Nov 15 at 18:28
@Sigur: Yes, the first parameter is used as the key to access the information. This is really helpful if you have a large number of contacts.
– Peter Grill
Nov 15 at 18:30
Since I'm going to share this file, do you know ifetoolbox
comes with a basic installation? Because I know thattikz
does not.
– Sigur
Nov 15 at 18:30
Yes,etoolbox
is in the standard distribution. But, so istikz
so not sure why you think otherwise. Also, have added error checking in the updated version.
– Peter Grill
Nov 15 at 18:34
1
@Sigur: As requested, I have updated it inserts amedskip
only between entries. You can replace themedskip
with the symbol you desire.
– Peter Grill
Nov 16 at 6:39
|
show 8 more comments
up vote
3
down vote
accepted
This is similar to Steven Seglets solution with slightly different packaging. You can show a single contact with ShowContact{}
or list all the contact with listcontacts
Notes:
- The values are stored based on
#1
which is used as the key to access the contacts. An attempt to reuse the same key is now flagged as an error. - This has now been updated to add a
medskip
between entries when the entire list is printed. Themedskip
is not added before the first entry, nor after the last as shown in the figure.
Code:
documentclass{article}
usepackage{etoolbox}
makeatletter
newtoggle{@IsFirstEntryInList}
newcommand*{@ShowContact}[1]{%
iftoggle{@IsFirstEntryInList}{%
globaltogglefalse{@IsFirstEntryInList}%
}{%
medskip% <-- separator between entries
}%
ShowContact{#1}%
}
newcommand*{ShowContact}[1]{%
parnoindenttextbf{csuse{name #1}}%
parnoindenttextit{csuse{work #1}}%
parnoindenttexttt{csuse{email #1}}%
}%
%% https://tex.stackexchange.com/a/14394/4301
newcommand*{listcontacts}{% Initialize
globaltoggletrue{@IsFirstEntryInList}%
}
newcommand{AddToListOfContacts}[1]{%
g@addto@macrolistcontacts{{#1}}%
}
newcommand{information}[3]{%
ifcsdef{name #1}{%
PackageError{jobname}{Multiple uses of the key: '#1'}{}%
}{%
csdef{name #1}{#1}%
csdef{work #1}{#2}%
csdef{email #1}{#3}%
AddToListOfContacts{unexpanded{@ShowContact{#1}}}%
}%
}
makeatother
information{Faa Foo}{Univ. Blah}{goo@goo.com}
information{Harvard}{Harvard University}{me@harvard.com}
%information{Harvard}{xxx University}{me@harvard.com}% <-- Triggers an error
begin{document}
noindent
To show one contact:
ShowContact{Harvard}
medskipnoindent
To show all contacts:
listcontacts
parnoindent
Text following to check that there is no extra space at end...
end{document}
Interesting. In this case, the contacts are accessed via argument value, not via a number, right?
– Sigur
Nov 15 at 18:28
@Sigur: Yes, the first parameter is used as the key to access the information. This is really helpful if you have a large number of contacts.
– Peter Grill
Nov 15 at 18:30
Since I'm going to share this file, do you know ifetoolbox
comes with a basic installation? Because I know thattikz
does not.
– Sigur
Nov 15 at 18:30
Yes,etoolbox
is in the standard distribution. But, so istikz
so not sure why you think otherwise. Also, have added error checking in the updated version.
– Peter Grill
Nov 15 at 18:34
1
@Sigur: As requested, I have updated it inserts amedskip
only between entries. You can replace themedskip
with the symbol you desire.
– Peter Grill
Nov 16 at 6:39
|
show 8 more comments
up vote
3
down vote
accepted
up vote
3
down vote
accepted
This is similar to Steven Seglets solution with slightly different packaging. You can show a single contact with ShowContact{}
or list all the contact with listcontacts
Notes:
- The values are stored based on
#1
which is used as the key to access the contacts. An attempt to reuse the same key is now flagged as an error. - This has now been updated to add a
medskip
between entries when the entire list is printed. Themedskip
is not added before the first entry, nor after the last as shown in the figure.
Code:
documentclass{article}
usepackage{etoolbox}
makeatletter
newtoggle{@IsFirstEntryInList}
newcommand*{@ShowContact}[1]{%
iftoggle{@IsFirstEntryInList}{%
globaltogglefalse{@IsFirstEntryInList}%
}{%
medskip% <-- separator between entries
}%
ShowContact{#1}%
}
newcommand*{ShowContact}[1]{%
parnoindenttextbf{csuse{name #1}}%
parnoindenttextit{csuse{work #1}}%
parnoindenttexttt{csuse{email #1}}%
}%
%% https://tex.stackexchange.com/a/14394/4301
newcommand*{listcontacts}{% Initialize
globaltoggletrue{@IsFirstEntryInList}%
}
newcommand{AddToListOfContacts}[1]{%
g@addto@macrolistcontacts{{#1}}%
}
newcommand{information}[3]{%
ifcsdef{name #1}{%
PackageError{jobname}{Multiple uses of the key: '#1'}{}%
}{%
csdef{name #1}{#1}%
csdef{work #1}{#2}%
csdef{email #1}{#3}%
AddToListOfContacts{unexpanded{@ShowContact{#1}}}%
}%
}
makeatother
information{Faa Foo}{Univ. Blah}{goo@goo.com}
information{Harvard}{Harvard University}{me@harvard.com}
%information{Harvard}{xxx University}{me@harvard.com}% <-- Triggers an error
begin{document}
noindent
To show one contact:
ShowContact{Harvard}
medskipnoindent
To show all contacts:
listcontacts
parnoindent
Text following to check that there is no extra space at end...
end{document}
This is similar to Steven Seglets solution with slightly different packaging. You can show a single contact with ShowContact{}
or list all the contact with listcontacts
Notes:
- The values are stored based on
#1
which is used as the key to access the contacts. An attempt to reuse the same key is now flagged as an error. - This has now been updated to add a
medskip
between entries when the entire list is printed. Themedskip
is not added before the first entry, nor after the last as shown in the figure.
Code:
documentclass{article}
usepackage{etoolbox}
makeatletter
newtoggle{@IsFirstEntryInList}
newcommand*{@ShowContact}[1]{%
iftoggle{@IsFirstEntryInList}{%
globaltogglefalse{@IsFirstEntryInList}%
}{%
medskip% <-- separator between entries
}%
ShowContact{#1}%
}
newcommand*{ShowContact}[1]{%
parnoindenttextbf{csuse{name #1}}%
parnoindenttextit{csuse{work #1}}%
parnoindenttexttt{csuse{email #1}}%
}%
%% https://tex.stackexchange.com/a/14394/4301
newcommand*{listcontacts}{% Initialize
globaltoggletrue{@IsFirstEntryInList}%
}
newcommand{AddToListOfContacts}[1]{%
g@addto@macrolistcontacts{{#1}}%
}
newcommand{information}[3]{%
ifcsdef{name #1}{%
PackageError{jobname}{Multiple uses of the key: '#1'}{}%
}{%
csdef{name #1}{#1}%
csdef{work #1}{#2}%
csdef{email #1}{#3}%
AddToListOfContacts{unexpanded{@ShowContact{#1}}}%
}%
}
makeatother
information{Faa Foo}{Univ. Blah}{goo@goo.com}
information{Harvard}{Harvard University}{me@harvard.com}
%information{Harvard}{xxx University}{me@harvard.com}% <-- Triggers an error
begin{document}
noindent
To show one contact:
ShowContact{Harvard}
medskipnoindent
To show all contacts:
listcontacts
parnoindent
Text following to check that there is no extra space at end...
end{document}
edited Nov 16 at 6:37
answered Nov 15 at 18:25
Peter Grill
163k24432740
163k24432740
Interesting. In this case, the contacts are accessed via argument value, not via a number, right?
– Sigur
Nov 15 at 18:28
@Sigur: Yes, the first parameter is used as the key to access the information. This is really helpful if you have a large number of contacts.
– Peter Grill
Nov 15 at 18:30
Since I'm going to share this file, do you know ifetoolbox
comes with a basic installation? Because I know thattikz
does not.
– Sigur
Nov 15 at 18:30
Yes,etoolbox
is in the standard distribution. But, so istikz
so not sure why you think otherwise. Also, have added error checking in the updated version.
– Peter Grill
Nov 15 at 18:34
1
@Sigur: As requested, I have updated it inserts amedskip
only between entries. You can replace themedskip
with the symbol you desire.
– Peter Grill
Nov 16 at 6:39
|
show 8 more comments
Interesting. In this case, the contacts are accessed via argument value, not via a number, right?
– Sigur
Nov 15 at 18:28
@Sigur: Yes, the first parameter is used as the key to access the information. This is really helpful if you have a large number of contacts.
– Peter Grill
Nov 15 at 18:30
Since I'm going to share this file, do you know ifetoolbox
comes with a basic installation? Because I know thattikz
does not.
– Sigur
Nov 15 at 18:30
Yes,etoolbox
is in the standard distribution. But, so istikz
so not sure why you think otherwise. Also, have added error checking in the updated version.
– Peter Grill
Nov 15 at 18:34
1
@Sigur: As requested, I have updated it inserts amedskip
only between entries. You can replace themedskip
with the symbol you desire.
– Peter Grill
Nov 16 at 6:39
Interesting. In this case, the contacts are accessed via argument value, not via a number, right?
– Sigur
Nov 15 at 18:28
Interesting. In this case, the contacts are accessed via argument value, not via a number, right?
– Sigur
Nov 15 at 18:28
@Sigur: Yes, the first parameter is used as the key to access the information. This is really helpful if you have a large number of contacts.
– Peter Grill
Nov 15 at 18:30
@Sigur: Yes, the first parameter is used as the key to access the information. This is really helpful if you have a large number of contacts.
– Peter Grill
Nov 15 at 18:30
Since I'm going to share this file, do you know if
etoolbox
comes with a basic installation? Because I know that tikz
does not.– Sigur
Nov 15 at 18:30
Since I'm going to share this file, do you know if
etoolbox
comes with a basic installation? Because I know that tikz
does not.– Sigur
Nov 15 at 18:30
Yes,
etoolbox
is in the standard distribution. But, so is tikz
so not sure why you think otherwise. Also, have added error checking in the updated version.– Peter Grill
Nov 15 at 18:34
Yes,
etoolbox
is in the standard distribution. But, so is tikz
so not sure why you think otherwise. Also, have added error checking in the updated version.– Peter Grill
Nov 15 at 18:34
1
1
@Sigur: As requested, I have updated it inserts a
medskip
only between entries. You can replace the medskip
with the symbol you desire.– Peter Grill
Nov 16 at 6:39
@Sigur: As requested, I have updated it inserts a
medskip
only between entries. You can replace the medskip
with the symbol you desire.– Peter Grill
Nov 16 at 6:39
|
show 8 more comments
up vote
4
down vote
I have made it so that @name[<index>]
@work[<index>]
, and @email[<index>]
are arrays, where the index is stepped with every call to information{}{}{}
.
listcontact{<index>}
will provide the contact info for the one specified index. In the MWE, I loop through all indices.
documentclass{article}
usepackage{pgffor}
makeatletter
newcounter{infocnt}
newcommand{name}[1]{%
expandafterdefcsname @name[theinfocnt]endcsname{#1}}
newcommand{work}[1]{%
expandafterdefcsname @work[theinfocnt]endcsname{#1}}
newcommand{email}[1]{%
expandafterdefcsname @email[theinfocnt]endcsname{#1}}
newcommand{information}[3]{%
stepcounter{infocnt}%
name{#1}%
work{#2}%
email{#3}%
}
newcommandlistcontact[1]{noindent%
NAME: textbf{csname @name[#1]endcsname}\
WORK: textbf{csname @work[#1]endcsname}\
EMAIL: textbf{csname @email[#1]endcsname}par
vskip 1in
}
makeatother
information{Faa Foo}{Univ. Blah}{goo@goo.com}
information{XXX}{YYY}{ZZZ@goo.com}
begin{document}
foreachx in {1,2,...,theinfocnt}{listcontact{x}}
end{document}
If I had my 'druthers, though, I would input the list all at once, quite simply, with the same output. The listofitems
package immediately stores the list as an accessible array:
documentclass{article}
usepackage{listofitems}
newcommandlistcontact[1]{noindent%
NAME: textbf{contacts[#1,1]}\
WORK: textbf{contacts[#1,2]}\
EMAIL: textbf{contacts[#1,3]}par
vskip 1in
}
setsepchar{\/&}
begin{document}
readlist*contacts{
Faa Foo & Univ. Blah & goo@goo.com\
XXX & YYY & ZZZ@goo.com}
foreachitemxincontacts{listcontact{xcnt}}
Here is the email of contact 2: contacts[2,3].
end{document}
With a small supplement from the readarray
package, the list of contacts could even be stored in an external file.
Very nice, specially sincetikz
is needed only for the loop.
– Sigur
Nov 15 at 18:18
@Sigur Oops. I redefined it (didn't see it defined earlier).
– Steven B. Segletes
Nov 15 at 18:20
No problem, I observed that. Thanks a lot
– Sigur
Nov 15 at 18:21
Do you know another way to print all without usingtikz
? Maybe using the value of the counter only? I'm going to share the file andtikz
could be not available.
– Sigur
Nov 15 at 18:31
1
@Sigur I changed it topgffor
. However, I also added technique #2, which is far simpler, if you can add all names at once.
– Steven B. Segletes
Nov 15 at 18:33
add a comment |
up vote
4
down vote
I have made it so that @name[<index>]
@work[<index>]
, and @email[<index>]
are arrays, where the index is stepped with every call to information{}{}{}
.
listcontact{<index>}
will provide the contact info for the one specified index. In the MWE, I loop through all indices.
documentclass{article}
usepackage{pgffor}
makeatletter
newcounter{infocnt}
newcommand{name}[1]{%
expandafterdefcsname @name[theinfocnt]endcsname{#1}}
newcommand{work}[1]{%
expandafterdefcsname @work[theinfocnt]endcsname{#1}}
newcommand{email}[1]{%
expandafterdefcsname @email[theinfocnt]endcsname{#1}}
newcommand{information}[3]{%
stepcounter{infocnt}%
name{#1}%
work{#2}%
email{#3}%
}
newcommandlistcontact[1]{noindent%
NAME: textbf{csname @name[#1]endcsname}\
WORK: textbf{csname @work[#1]endcsname}\
EMAIL: textbf{csname @email[#1]endcsname}par
vskip 1in
}
makeatother
information{Faa Foo}{Univ. Blah}{goo@goo.com}
information{XXX}{YYY}{ZZZ@goo.com}
begin{document}
foreachx in {1,2,...,theinfocnt}{listcontact{x}}
end{document}
If I had my 'druthers, though, I would input the list all at once, quite simply, with the same output. The listofitems
package immediately stores the list as an accessible array:
documentclass{article}
usepackage{listofitems}
newcommandlistcontact[1]{noindent%
NAME: textbf{contacts[#1,1]}\
WORK: textbf{contacts[#1,2]}\
EMAIL: textbf{contacts[#1,3]}par
vskip 1in
}
setsepchar{\/&}
begin{document}
readlist*contacts{
Faa Foo & Univ. Blah & goo@goo.com\
XXX & YYY & ZZZ@goo.com}
foreachitemxincontacts{listcontact{xcnt}}
Here is the email of contact 2: contacts[2,3].
end{document}
With a small supplement from the readarray
package, the list of contacts could even be stored in an external file.
Very nice, specially sincetikz
is needed only for the loop.
– Sigur
Nov 15 at 18:18
@Sigur Oops. I redefined it (didn't see it defined earlier).
– Steven B. Segletes
Nov 15 at 18:20
No problem, I observed that. Thanks a lot
– Sigur
Nov 15 at 18:21
Do you know another way to print all without usingtikz
? Maybe using the value of the counter only? I'm going to share the file andtikz
could be not available.
– Sigur
Nov 15 at 18:31
1
@Sigur I changed it topgffor
. However, I also added technique #2, which is far simpler, if you can add all names at once.
– Steven B. Segletes
Nov 15 at 18:33
add a comment |
up vote
4
down vote
up vote
4
down vote
I have made it so that @name[<index>]
@work[<index>]
, and @email[<index>]
are arrays, where the index is stepped with every call to information{}{}{}
.
listcontact{<index>}
will provide the contact info for the one specified index. In the MWE, I loop through all indices.
documentclass{article}
usepackage{pgffor}
makeatletter
newcounter{infocnt}
newcommand{name}[1]{%
expandafterdefcsname @name[theinfocnt]endcsname{#1}}
newcommand{work}[1]{%
expandafterdefcsname @work[theinfocnt]endcsname{#1}}
newcommand{email}[1]{%
expandafterdefcsname @email[theinfocnt]endcsname{#1}}
newcommand{information}[3]{%
stepcounter{infocnt}%
name{#1}%
work{#2}%
email{#3}%
}
newcommandlistcontact[1]{noindent%
NAME: textbf{csname @name[#1]endcsname}\
WORK: textbf{csname @work[#1]endcsname}\
EMAIL: textbf{csname @email[#1]endcsname}par
vskip 1in
}
makeatother
information{Faa Foo}{Univ. Blah}{goo@goo.com}
information{XXX}{YYY}{ZZZ@goo.com}
begin{document}
foreachx in {1,2,...,theinfocnt}{listcontact{x}}
end{document}
If I had my 'druthers, though, I would input the list all at once, quite simply, with the same output. The listofitems
package immediately stores the list as an accessible array:
documentclass{article}
usepackage{listofitems}
newcommandlistcontact[1]{noindent%
NAME: textbf{contacts[#1,1]}\
WORK: textbf{contacts[#1,2]}\
EMAIL: textbf{contacts[#1,3]}par
vskip 1in
}
setsepchar{\/&}
begin{document}
readlist*contacts{
Faa Foo & Univ. Blah & goo@goo.com\
XXX & YYY & ZZZ@goo.com}
foreachitemxincontacts{listcontact{xcnt}}
Here is the email of contact 2: contacts[2,3].
end{document}
With a small supplement from the readarray
package, the list of contacts could even be stored in an external file.
I have made it so that @name[<index>]
@work[<index>]
, and @email[<index>]
are arrays, where the index is stepped with every call to information{}{}{}
.
listcontact{<index>}
will provide the contact info for the one specified index. In the MWE, I loop through all indices.
documentclass{article}
usepackage{pgffor}
makeatletter
newcounter{infocnt}
newcommand{name}[1]{%
expandafterdefcsname @name[theinfocnt]endcsname{#1}}
newcommand{work}[1]{%
expandafterdefcsname @work[theinfocnt]endcsname{#1}}
newcommand{email}[1]{%
expandafterdefcsname @email[theinfocnt]endcsname{#1}}
newcommand{information}[3]{%
stepcounter{infocnt}%
name{#1}%
work{#2}%
email{#3}%
}
newcommandlistcontact[1]{noindent%
NAME: textbf{csname @name[#1]endcsname}\
WORK: textbf{csname @work[#1]endcsname}\
EMAIL: textbf{csname @email[#1]endcsname}par
vskip 1in
}
makeatother
information{Faa Foo}{Univ. Blah}{goo@goo.com}
information{XXX}{YYY}{ZZZ@goo.com}
begin{document}
foreachx in {1,2,...,theinfocnt}{listcontact{x}}
end{document}
If I had my 'druthers, though, I would input the list all at once, quite simply, with the same output. The listofitems
package immediately stores the list as an accessible array:
documentclass{article}
usepackage{listofitems}
newcommandlistcontact[1]{noindent%
NAME: textbf{contacts[#1,1]}\
WORK: textbf{contacts[#1,2]}\
EMAIL: textbf{contacts[#1,3]}par
vskip 1in
}
setsepchar{\/&}
begin{document}
readlist*contacts{
Faa Foo & Univ. Blah & goo@goo.com\
XXX & YYY & ZZZ@goo.com}
foreachitemxincontacts{listcontact{xcnt}}
Here is the email of contact 2: contacts[2,3].
end{document}
With a small supplement from the readarray
package, the list of contacts could even be stored in an external file.
edited Nov 15 at 18:42
answered Nov 15 at 18:12
Steven B. Segletes
151k9189397
151k9189397
Very nice, specially sincetikz
is needed only for the loop.
– Sigur
Nov 15 at 18:18
@Sigur Oops. I redefined it (didn't see it defined earlier).
– Steven B. Segletes
Nov 15 at 18:20
No problem, I observed that. Thanks a lot
– Sigur
Nov 15 at 18:21
Do you know another way to print all without usingtikz
? Maybe using the value of the counter only? I'm going to share the file andtikz
could be not available.
– Sigur
Nov 15 at 18:31
1
@Sigur I changed it topgffor
. However, I also added technique #2, which is far simpler, if you can add all names at once.
– Steven B. Segletes
Nov 15 at 18:33
add a comment |
Very nice, specially sincetikz
is needed only for the loop.
– Sigur
Nov 15 at 18:18
@Sigur Oops. I redefined it (didn't see it defined earlier).
– Steven B. Segletes
Nov 15 at 18:20
No problem, I observed that. Thanks a lot
– Sigur
Nov 15 at 18:21
Do you know another way to print all without usingtikz
? Maybe using the value of the counter only? I'm going to share the file andtikz
could be not available.
– Sigur
Nov 15 at 18:31
1
@Sigur I changed it topgffor
. However, I also added technique #2, which is far simpler, if you can add all names at once.
– Steven B. Segletes
Nov 15 at 18:33
Very nice, specially since
tikz
is needed only for the loop.– Sigur
Nov 15 at 18:18
Very nice, specially since
tikz
is needed only for the loop.– Sigur
Nov 15 at 18:18
@Sigur Oops. I redefined it (didn't see it defined earlier).
– Steven B. Segletes
Nov 15 at 18:20
@Sigur Oops. I redefined it (didn't see it defined earlier).
– Steven B. Segletes
Nov 15 at 18:20
No problem, I observed that. Thanks a lot
– Sigur
Nov 15 at 18:21
No problem, I observed that. Thanks a lot
– Sigur
Nov 15 at 18:21
Do you know another way to print all without using
tikz
? Maybe using the value of the counter only? I'm going to share the file and tikz
could be not available.– Sigur
Nov 15 at 18:31
Do you know another way to print all without using
tikz
? Maybe using the value of the counter only? I'm going to share the file and tikz
could be not available.– Sigur
Nov 15 at 18:31
1
1
@Sigur I changed it to
pgffor
. However, I also added technique #2, which is far simpler, if you can add all names at once.– Steven B. Segletes
Nov 15 at 18:33
@Sigur I changed it to
pgffor
. However, I also added technique #2, which is far simpler, if you can add all names at once.– Steven B. Segletes
Nov 15 at 18:33
add a comment |
up vote
3
down vote
This is “property lists” playground. Here I define newcontact
for defining a contact with a key-value interface.
With newcontactscheme
one defines different ways to print the data; default
is used by listcontact
if no optional argument is supplied. In the definition, use getcontact{<key>}{#1}
to print the value corresponding to <key>
for the current contact, represented by #1
.
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{newcontact}{mm}
{% #1 = contact label, #2 = data
prop_new:c { g_sigur_contact_#1_prop }
prop_gset_from_keyval:cn { g_sigur_contact_#1_prop } { #2 }
}
NewDocumentCommand{listcontact}{O{default}m}
{
cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
__sigur_contact_list:n { #2 }
}
NewDocumentCommand{getcontact}{mm}
{
sigur_contact_print:nn { #1 } { #2 }
}
NewDocumentCommand{newcontactscheme}{m+m}
{% #1 = scheme name, #2 = definition
cs_new_protected:cn { sigur_contact_list_#1:n } { #2 }
}
cs_new_protected:Nn sigur_contact_print:nn
{
prop_item:cn { g_sigur_contact_#2_prop } { #1 }
}
ExplSyntaxOff
newcontactscheme{default}{%
parnoindent
getcontact{name}{#1}\
getcontact{work}{#1}\
getcontact{email}{#1}par
}
newcontactscheme{short}{%
getcontact{name}{#1}, getcontact{email}{#1}%
}
newcontactscheme{alternate}{%
begin{tabular}[t]{@{}l@{ }l@{}}
Name: & getcontact{name}{#1} \
Work: & getcontact{work}{#1} \
Email: & texttt{getcontact{email}{#1}}
end{tabular}%
}
newcontact{foo}{
name=Faa Foo,
work=Univ. Blah,
email=goo@goo.com
}
newcontact{xxx}{
name=XXX,
work=YYY,
email=ZZZ@goo.com
}
begin{document}
listcontact{foo}
medskip
listcontact{xxx}
medskip
Short: listcontact[short]{xxx}
medskip
Alternate: listcontact[alternate]{foo}
end{document}
A version that also defines listallcontacts
(the optional argument is one of the defined schemes).
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{newcontact}{mm}
{% #1 = contact label, #2 = data
prop_new:c { g_sigur_contact_#1_prop }
prop_gset_from_keyval:cn { g_sigur_contact_#1_prop } { #2 }
seq_gput_right:Nn g_sigur_contact_seq { #1 }
}
NewDocumentCommand{listcontact}{O{default}m}
{
cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
__sigur_contact_list:n { #2 }
}
NewDocumentCommand{listallcontacts}{O{default}}
{
cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
seq_map_inline:Nn g_sigur_contact_seq
{
__sigur_contact_list:n { ##1 } par
}
}
NewDocumentCommand{getcontact}{mm}
{
sigur_contact_print:nn { #1 } { #2 }
}
NewDocumentCommand{newcontactscheme}{m+m}
{% #1 = scheme name, #2 = definition
cs_new_protected:cn { sigur_contact_list_#1:n } { #2 }
}
seq_new:N g_sigur_contact_seq
cs_new_protected:Nn sigur_contact_print:nn
{
prop_item:cn { g_sigur_contact_#2_prop } { #1 }
}
ExplSyntaxOff
newcontactscheme{default}{%
parnoindent
getcontact{name}{#1}\
getcontact{work}{#1}\
getcontact{email}{#1}par
}
newcontactscheme{short}{%
getcontact{name}{#1}, getcontact{email}{#1}%
}
newcontactscheme{alternate}{%
begin{tabular}[t]{@{}l@{ }l@{}}
Name: & getcontact{name}{#1} \
Work: & getcontact{work}{#1} \
Email: & texttt{getcontact{email}{#1}}
end{tabular}%
}
newcontact{foo}{
name=Faa Foo,
work=Univ. Blah,
email=goo@goo.com
}
newcontact{xxx}{
name=XXX,
work=YYY,
email=ZZZ@goo.com
}
begin{document}
listcontact{foo}
medskip
listcontact{xxx}
medskip
Short: listcontact[short]{xxx}
medskip
Alternate: listcontact[alternate]{foo}
medskip
listallcontacts
medskip
listallcontacts[short]
end{document}
I never studied or tried to learnxparse
. The result is amazing. Nice!
– Sigur
Nov 15 at 21:04
add a comment |
up vote
3
down vote
This is “property lists” playground. Here I define newcontact
for defining a contact with a key-value interface.
With newcontactscheme
one defines different ways to print the data; default
is used by listcontact
if no optional argument is supplied. In the definition, use getcontact{<key>}{#1}
to print the value corresponding to <key>
for the current contact, represented by #1
.
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{newcontact}{mm}
{% #1 = contact label, #2 = data
prop_new:c { g_sigur_contact_#1_prop }
prop_gset_from_keyval:cn { g_sigur_contact_#1_prop } { #2 }
}
NewDocumentCommand{listcontact}{O{default}m}
{
cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
__sigur_contact_list:n { #2 }
}
NewDocumentCommand{getcontact}{mm}
{
sigur_contact_print:nn { #1 } { #2 }
}
NewDocumentCommand{newcontactscheme}{m+m}
{% #1 = scheme name, #2 = definition
cs_new_protected:cn { sigur_contact_list_#1:n } { #2 }
}
cs_new_protected:Nn sigur_contact_print:nn
{
prop_item:cn { g_sigur_contact_#2_prop } { #1 }
}
ExplSyntaxOff
newcontactscheme{default}{%
parnoindent
getcontact{name}{#1}\
getcontact{work}{#1}\
getcontact{email}{#1}par
}
newcontactscheme{short}{%
getcontact{name}{#1}, getcontact{email}{#1}%
}
newcontactscheme{alternate}{%
begin{tabular}[t]{@{}l@{ }l@{}}
Name: & getcontact{name}{#1} \
Work: & getcontact{work}{#1} \
Email: & texttt{getcontact{email}{#1}}
end{tabular}%
}
newcontact{foo}{
name=Faa Foo,
work=Univ. Blah,
email=goo@goo.com
}
newcontact{xxx}{
name=XXX,
work=YYY,
email=ZZZ@goo.com
}
begin{document}
listcontact{foo}
medskip
listcontact{xxx}
medskip
Short: listcontact[short]{xxx}
medskip
Alternate: listcontact[alternate]{foo}
end{document}
A version that also defines listallcontacts
(the optional argument is one of the defined schemes).
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{newcontact}{mm}
{% #1 = contact label, #2 = data
prop_new:c { g_sigur_contact_#1_prop }
prop_gset_from_keyval:cn { g_sigur_contact_#1_prop } { #2 }
seq_gput_right:Nn g_sigur_contact_seq { #1 }
}
NewDocumentCommand{listcontact}{O{default}m}
{
cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
__sigur_contact_list:n { #2 }
}
NewDocumentCommand{listallcontacts}{O{default}}
{
cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
seq_map_inline:Nn g_sigur_contact_seq
{
__sigur_contact_list:n { ##1 } par
}
}
NewDocumentCommand{getcontact}{mm}
{
sigur_contact_print:nn { #1 } { #2 }
}
NewDocumentCommand{newcontactscheme}{m+m}
{% #1 = scheme name, #2 = definition
cs_new_protected:cn { sigur_contact_list_#1:n } { #2 }
}
seq_new:N g_sigur_contact_seq
cs_new_protected:Nn sigur_contact_print:nn
{
prop_item:cn { g_sigur_contact_#2_prop } { #1 }
}
ExplSyntaxOff
newcontactscheme{default}{%
parnoindent
getcontact{name}{#1}\
getcontact{work}{#1}\
getcontact{email}{#1}par
}
newcontactscheme{short}{%
getcontact{name}{#1}, getcontact{email}{#1}%
}
newcontactscheme{alternate}{%
begin{tabular}[t]{@{}l@{ }l@{}}
Name: & getcontact{name}{#1} \
Work: & getcontact{work}{#1} \
Email: & texttt{getcontact{email}{#1}}
end{tabular}%
}
newcontact{foo}{
name=Faa Foo,
work=Univ. Blah,
email=goo@goo.com
}
newcontact{xxx}{
name=XXX,
work=YYY,
email=ZZZ@goo.com
}
begin{document}
listcontact{foo}
medskip
listcontact{xxx}
medskip
Short: listcontact[short]{xxx}
medskip
Alternate: listcontact[alternate]{foo}
medskip
listallcontacts
medskip
listallcontacts[short]
end{document}
I never studied or tried to learnxparse
. The result is amazing. Nice!
– Sigur
Nov 15 at 21:04
add a comment |
up vote
3
down vote
up vote
3
down vote
This is “property lists” playground. Here I define newcontact
for defining a contact with a key-value interface.
With newcontactscheme
one defines different ways to print the data; default
is used by listcontact
if no optional argument is supplied. In the definition, use getcontact{<key>}{#1}
to print the value corresponding to <key>
for the current contact, represented by #1
.
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{newcontact}{mm}
{% #1 = contact label, #2 = data
prop_new:c { g_sigur_contact_#1_prop }
prop_gset_from_keyval:cn { g_sigur_contact_#1_prop } { #2 }
}
NewDocumentCommand{listcontact}{O{default}m}
{
cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
__sigur_contact_list:n { #2 }
}
NewDocumentCommand{getcontact}{mm}
{
sigur_contact_print:nn { #1 } { #2 }
}
NewDocumentCommand{newcontactscheme}{m+m}
{% #1 = scheme name, #2 = definition
cs_new_protected:cn { sigur_contact_list_#1:n } { #2 }
}
cs_new_protected:Nn sigur_contact_print:nn
{
prop_item:cn { g_sigur_contact_#2_prop } { #1 }
}
ExplSyntaxOff
newcontactscheme{default}{%
parnoindent
getcontact{name}{#1}\
getcontact{work}{#1}\
getcontact{email}{#1}par
}
newcontactscheme{short}{%
getcontact{name}{#1}, getcontact{email}{#1}%
}
newcontactscheme{alternate}{%
begin{tabular}[t]{@{}l@{ }l@{}}
Name: & getcontact{name}{#1} \
Work: & getcontact{work}{#1} \
Email: & texttt{getcontact{email}{#1}}
end{tabular}%
}
newcontact{foo}{
name=Faa Foo,
work=Univ. Blah,
email=goo@goo.com
}
newcontact{xxx}{
name=XXX,
work=YYY,
email=ZZZ@goo.com
}
begin{document}
listcontact{foo}
medskip
listcontact{xxx}
medskip
Short: listcontact[short]{xxx}
medskip
Alternate: listcontact[alternate]{foo}
end{document}
A version that also defines listallcontacts
(the optional argument is one of the defined schemes).
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{newcontact}{mm}
{% #1 = contact label, #2 = data
prop_new:c { g_sigur_contact_#1_prop }
prop_gset_from_keyval:cn { g_sigur_contact_#1_prop } { #2 }
seq_gput_right:Nn g_sigur_contact_seq { #1 }
}
NewDocumentCommand{listcontact}{O{default}m}
{
cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
__sigur_contact_list:n { #2 }
}
NewDocumentCommand{listallcontacts}{O{default}}
{
cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
seq_map_inline:Nn g_sigur_contact_seq
{
__sigur_contact_list:n { ##1 } par
}
}
NewDocumentCommand{getcontact}{mm}
{
sigur_contact_print:nn { #1 } { #2 }
}
NewDocumentCommand{newcontactscheme}{m+m}
{% #1 = scheme name, #2 = definition
cs_new_protected:cn { sigur_contact_list_#1:n } { #2 }
}
seq_new:N g_sigur_contact_seq
cs_new_protected:Nn sigur_contact_print:nn
{
prop_item:cn { g_sigur_contact_#2_prop } { #1 }
}
ExplSyntaxOff
newcontactscheme{default}{%
parnoindent
getcontact{name}{#1}\
getcontact{work}{#1}\
getcontact{email}{#1}par
}
newcontactscheme{short}{%
getcontact{name}{#1}, getcontact{email}{#1}%
}
newcontactscheme{alternate}{%
begin{tabular}[t]{@{}l@{ }l@{}}
Name: & getcontact{name}{#1} \
Work: & getcontact{work}{#1} \
Email: & texttt{getcontact{email}{#1}}
end{tabular}%
}
newcontact{foo}{
name=Faa Foo,
work=Univ. Blah,
email=goo@goo.com
}
newcontact{xxx}{
name=XXX,
work=YYY,
email=ZZZ@goo.com
}
begin{document}
listcontact{foo}
medskip
listcontact{xxx}
medskip
Short: listcontact[short]{xxx}
medskip
Alternate: listcontact[alternate]{foo}
medskip
listallcontacts
medskip
listallcontacts[short]
end{document}
This is “property lists” playground. Here I define newcontact
for defining a contact with a key-value interface.
With newcontactscheme
one defines different ways to print the data; default
is used by listcontact
if no optional argument is supplied. In the definition, use getcontact{<key>}{#1}
to print the value corresponding to <key>
for the current contact, represented by #1
.
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{newcontact}{mm}
{% #1 = contact label, #2 = data
prop_new:c { g_sigur_contact_#1_prop }
prop_gset_from_keyval:cn { g_sigur_contact_#1_prop } { #2 }
}
NewDocumentCommand{listcontact}{O{default}m}
{
cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
__sigur_contact_list:n { #2 }
}
NewDocumentCommand{getcontact}{mm}
{
sigur_contact_print:nn { #1 } { #2 }
}
NewDocumentCommand{newcontactscheme}{m+m}
{% #1 = scheme name, #2 = definition
cs_new_protected:cn { sigur_contact_list_#1:n } { #2 }
}
cs_new_protected:Nn sigur_contact_print:nn
{
prop_item:cn { g_sigur_contact_#2_prop } { #1 }
}
ExplSyntaxOff
newcontactscheme{default}{%
parnoindent
getcontact{name}{#1}\
getcontact{work}{#1}\
getcontact{email}{#1}par
}
newcontactscheme{short}{%
getcontact{name}{#1}, getcontact{email}{#1}%
}
newcontactscheme{alternate}{%
begin{tabular}[t]{@{}l@{ }l@{}}
Name: & getcontact{name}{#1} \
Work: & getcontact{work}{#1} \
Email: & texttt{getcontact{email}{#1}}
end{tabular}%
}
newcontact{foo}{
name=Faa Foo,
work=Univ. Blah,
email=goo@goo.com
}
newcontact{xxx}{
name=XXX,
work=YYY,
email=ZZZ@goo.com
}
begin{document}
listcontact{foo}
medskip
listcontact{xxx}
medskip
Short: listcontact[short]{xxx}
medskip
Alternate: listcontact[alternate]{foo}
end{document}
A version that also defines listallcontacts
(the optional argument is one of the defined schemes).
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{newcontact}{mm}
{% #1 = contact label, #2 = data
prop_new:c { g_sigur_contact_#1_prop }
prop_gset_from_keyval:cn { g_sigur_contact_#1_prop } { #2 }
seq_gput_right:Nn g_sigur_contact_seq { #1 }
}
NewDocumentCommand{listcontact}{O{default}m}
{
cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
__sigur_contact_list:n { #2 }
}
NewDocumentCommand{listallcontacts}{O{default}}
{
cs_set_eq:Nc __sigur_contact_list:n { sigur_contact_list_#1:n }
seq_map_inline:Nn g_sigur_contact_seq
{
__sigur_contact_list:n { ##1 } par
}
}
NewDocumentCommand{getcontact}{mm}
{
sigur_contact_print:nn { #1 } { #2 }
}
NewDocumentCommand{newcontactscheme}{m+m}
{% #1 = scheme name, #2 = definition
cs_new_protected:cn { sigur_contact_list_#1:n } { #2 }
}
seq_new:N g_sigur_contact_seq
cs_new_protected:Nn sigur_contact_print:nn
{
prop_item:cn { g_sigur_contact_#2_prop } { #1 }
}
ExplSyntaxOff
newcontactscheme{default}{%
parnoindent
getcontact{name}{#1}\
getcontact{work}{#1}\
getcontact{email}{#1}par
}
newcontactscheme{short}{%
getcontact{name}{#1}, getcontact{email}{#1}%
}
newcontactscheme{alternate}{%
begin{tabular}[t]{@{}l@{ }l@{}}
Name: & getcontact{name}{#1} \
Work: & getcontact{work}{#1} \
Email: & texttt{getcontact{email}{#1}}
end{tabular}%
}
newcontact{foo}{
name=Faa Foo,
work=Univ. Blah,
email=goo@goo.com
}
newcontact{xxx}{
name=XXX,
work=YYY,
email=ZZZ@goo.com
}
begin{document}
listcontact{foo}
medskip
listcontact{xxx}
medskip
Short: listcontact[short]{xxx}
medskip
Alternate: listcontact[alternate]{foo}
medskip
listallcontacts
medskip
listallcontacts[short]
end{document}
edited Nov 15 at 21:43
answered Nov 15 at 21:01
egreg
698k8518573126
698k8518573126
I never studied or tried to learnxparse
. The result is amazing. Nice!
– Sigur
Nov 15 at 21:04
add a comment |
I never studied or tried to learnxparse
. The result is amazing. Nice!
– Sigur
Nov 15 at 21:04
I never studied or tried to learn
xparse
. The result is amazing. Nice!– Sigur
Nov 15 at 21:04
I never studied or tried to learn
xparse
. The result is amazing. Nice!– Sigur
Nov 15 at 21:04
add a comment |
up vote
0
down vote
This "answer" does not answer your question.
A few remarks about the pitfalls of database-management in LaTeX
A few remarks about database-management in general:
Usually data is organized in so-called data-bases.
A data-base could, e.g., be a list of contact-details.
Each person or organization that you wish to contact might within the data-base be connected to a data-record which holds all the contact-details related to that person/organization.
Therefore a data-record itself could be organized by means of data-fields whereby each field serves for storing/providing information that belongs to a specific category.
Thus the logical structure of a data-base could be something like:
Data-base: contact-details
==========================
Data-record 001:
----------------
Value of data-field "Name":=John Doe
Value of data-field "Work":=whistle blower
Value of data-field "E-Mail":=Whistle@fake.email.address
Data-record 002:
----------------
Value of data-field "Name":=Jane Smith
Value of data-field "Work":=employée at department of alternative facts
Value of data-field "E-Mail":=AltFacts@fake.email.address
...
You need means
- both for identifying each record that belongs to a data-base
- and for keeping the single records that belong to a data-base distinguishable from each other.
The data-fields "Name" or "Work" or "E-Mail" are not suitable for this purpose.
E.g., some day there might be records about two different people in the data-base that have the same name.
Thus in data-base-management, it is common practise to indroduce in the structure of data-records a data-field which for each data-record holds a piece of information which does not occur within the corresponding data-field of any other data-record.
Usually this data-field is called a "primary key".
Often this primary-key is just some item of continuous numeration which is obtained by continuously numerating data-records.
When introducing a primary-key, the data-base "contact details" could look like this:
Data-base: contact-details
==========================
Data-record 001:
----------------
Value of data-field "Primary Key":=001
Value of data-field "Name":=John Doe
Value of data-field "Work":=whistle blower
Value of data-field "E-Mail":=Whistle@fake.email.address
Data-record 002:
----------------
Value of data-field "Primary Key":=002
Value of data-field "Name":=Jane Smith
Value of data-field "Work":=employée at department of alternative facts
Value of data-field "E-Mail":=AltFacts@fake.email.address
When doing this, you can - besides the single data-records - also maintain
- a list of primary-keys belonging to the data-base an
- a counter denoting the amount of records belonging to the data-base:
Data-base: contact-details
==========================
Amount of data-records: 2
List of primary-keys: {001}, {002}
Data-record 001:
----------------
Value of data-field "Primary Key":=001
Value of data-field "Name":=John Doe
Value of data-field "Work":=whistle blower
Value of data-field "E-Mail":=Whistle@fake.email.address
Data-record 002:
----------------
Value of data-field "Primary Key":=002
Value of data-field "Name":=Jane Smith
Value of data-field "Work":=employée at department of alternative facts
Value of data-field "E-Mail":=AltFacts@fake.email.address
The list of primary-keys would be of special interest for sorting out specific data-records:
Assume you wish to retrieve the e-mail-address of Jane Smith:
In terms of pseudo-code, you would do this via a directive like:
Iterate on that list of primary-keys that belongs to
the data-base "contact-details" as follows:
In each iteration "look" at the value of the data-field "Name"
of that data-record whose data-field "Primary Key" equals the
current list element.
If that value equals "Jane Smith", print out the value of the
data-field "E-Mail" of that data-record.
Pitfalls related to (La)TeX:
When implementing such things in terms of (La)TeX, you will encounter a few problems which have to do with the fact that (La)TeX is a macro-language which does some pre-processing of input in terms of reading and tokenizing input:
For example, curly braces ({
and }
) have a specific meaning in LaTeX and usually each opening-brace must habe a matching closing-brace and vice versa.
For example, the percent-character (%
) has a specific meaning in LaTeX.
But according to RFC 2822 e-mail-adresses may contain unbalanced curly braces and percent-characters.
Therefore maintaining such entries via a data-base that is provided in terms of (La)TeX-input might be related to circumstances which the not-so experienced user might see as problems.
E.g., Alt}Fa%c#1ts@fake.email.address
would be a nice e-mail-address.
But how to get the value Alt}Fa%c#1ts@fake.email.address
into a data-record's data-field "E-Mail" in case the data-base in question is maintained in (La)TeX?
At first glimpse you could do it by means of macros that deliver the desired symbols in question:
Something like:
Value of data-field "E-Mail":=Altleftbrace Fatextpercent chash1ts@fake.email.address
Also the names of people/organizations might contain characters/symbols which the input-encoding in which the (La)TeX-file is written does not contain.
Assume one of the persons whose contact-details are to be maintained has the name Alaïa Maëlys Gambolpütty while the data-base is written in a (La)TeX-input-file that is encoded in ASCII.
In such a case you must do it in terms of control-sequence-tokens whose names are formed by characters within the range of the input-encoding.
But such control-sequences make sorting out specific data-records difficult.
Therefore it might be a good idea to maintain each piece of data twice:
Once written only by means of characters of the input-encoding in question.
Once written in a way where also LaTeX-control-sequences that deliver the desired characters/symbols may occur:
Data-base: contact-details
==========================
Amount of data-records: 3
List of primary-keys: {001}, {002}, {003}
Data-record 001:
----------------
Value of data-field "Primary Key":=001
Value of data-field "Name" in input-encoding-representation:=John Doe
Value of data-field "Name" in LaTeX-representation:=John Doe
Value of data-field "Work" in input-encoding-representation:=whistle blower
Value of data-field "Work" in LaTeX-representation:=whistle blower
Value of data-field "E-Mail" in input-encoding-representation:=Whistle@fake.email.address
Value of data-field "E-Mail" in LaTeX-representation:=Whistle@fake.email.address
Data-record 002:
----------------
Value of data-field "Primary Key":=002
Value of data-field "Name" in input-encoding-representation:=Jane Smith
Value of data-field "Name" in LaTeX-representation:=Jane Smith
Value of data-field "Work" in input-encoding-representation:=employee at department of alternative facts
Value of data-field "Work" in LaTeX-representation:=employ'ee at department of alternative facts
Value of data-field "E-Mail" in input-encoding-representation:=AltFacts@fake.email.address
Value of data-field "E-Mail" in LaTeX-representation:=AltFacts@fake.email.address
Data-record 003:
----------------
Value of data-field "Primary Key":=003
Value of data-field "Name" in input-encoding-representation:=Alaia Maelys Gambolpuetty
Value of data-field "Name" in LaTeX-representation:=Ala"{i}a Ma"{e}lys Gambolp"{u}tty
Value of data-field "Work" in input-encoding-representation:=employee at department of alternative facts
Value of data-field "Work" in LaTeX-representation:=employée at department of alternative facts
Value of data-field "E-Mail" in input-encoding-representation:=Alt}Fa%c#1ts@fake.email.address
Value of data-field "E-Mail" in LaTeX-representation:=Altleftbrace Fatextpercent chash1ts@fake.email.address
...
With such an approach you could implement an interface where searching and sorting out takes place in terms of input-encoding-representation and delivers data in terms of LaTeX-representation.
With such an interface, one stage would always include reading and tokenizing the input-encoding-representations under verbatim-catcode-régime.
This is feasible but makes using the macros that form the interface
- within pure-expansion-contexts impossible.
- within the definition-texts of other macros cumbersome.
With such an interface, it would also be a good idea to have everything that denotes names of databases or names of data-fields or values in input-encoding-representation evaluate to characters of the input-encoding.
Therefore for proper error-checking a routine would be useful which does fully evaluate/expand arguments and then does check whether the expansion-result does hold character-tokens obeying the verbatim-catcode-régime only.
Full evaluation/expansion of an argument that might hold arbitrary tokens is already a nice problem.
An easy approach would be using edef
.
For one thing this also would break expandability of the interface.
For another thing edef
is not totally safe with arbitrary tokens.
E.g., look at
edeftest{%
Where does the definition text
stop?iffalse{fi Here?} Or Here?{iffalse}fi
}
I think a minimalist interface for some sort of database-management is feasible in LaTeX – with things like:
NewInitializedDataRecord{<Primary Key>}%
{<Name>}%
{<Work>}%
{<EMail>}%
NewEmptyDataRecord{<Primary Key>}
AddNewDataFieldToDataRecord{<Primary Key>}{<Name of data-field>}{<Value>}%
VerbatimizedAddNewDataFieldToDataRecord{<Primary Key>}{<Name of data-field>}|<Value>|% <- verbatim-arg
(extraction of verbatimized values of data-fields via scantokens...)
PrintFieldValueFromDataRecord{<Primary Key>}{<Name of data-field>}
PrintDataRecord{<Primary Key>}
PrintAllDataRecords
PrintAllDataRecordsWithSpecificDatFieldValue{<Name of data-field>}{<Specific Value>}
But before going into details, specification about the tokens that might form values of data-fields and about their treatment when comparing values of data-fields is needed.
I am not sure if I understood your comments. Anyway, thanks for attention. Let me inform that the contacts come from authors of a paper, so I think that two exactly equal names could happen rarely.
– Sigur
Nov 16 at 18:13
Your question actually is about some sort of whatsoever minimalist database-management. :-) I extended my answer in the hope of pointing out some of the pitfalls related to whatsoever minimalist database-management in terms of a macro language. :-)
– Ulrich Diez
Nov 16 at 21:29
Well, thanks for your work. But I confess that I have no idea how to understand it... lol
– Sigur
Nov 16 at 21:33
I think you want to say “From relational algebra we know that it is not a good idea to assign to each data-record its own unique primary-key as a data-field of its own of that data-record.”.
– egreg
Nov 16 at 21:48
@UlrichDiez The formulation is way better now. For the same reason I assigned a label to each contact.
– egreg
Nov 16 at 22:31
add a comment |
up vote
0
down vote
This "answer" does not answer your question.
A few remarks about the pitfalls of database-management in LaTeX
A few remarks about database-management in general:
Usually data is organized in so-called data-bases.
A data-base could, e.g., be a list of contact-details.
Each person or organization that you wish to contact might within the data-base be connected to a data-record which holds all the contact-details related to that person/organization.
Therefore a data-record itself could be organized by means of data-fields whereby each field serves for storing/providing information that belongs to a specific category.
Thus the logical structure of a data-base could be something like:
Data-base: contact-details
==========================
Data-record 001:
----------------
Value of data-field "Name":=John Doe
Value of data-field "Work":=whistle blower
Value of data-field "E-Mail":=Whistle@fake.email.address
Data-record 002:
----------------
Value of data-field "Name":=Jane Smith
Value of data-field "Work":=employée at department of alternative facts
Value of data-field "E-Mail":=AltFacts@fake.email.address
...
You need means
- both for identifying each record that belongs to a data-base
- and for keeping the single records that belong to a data-base distinguishable from each other.
The data-fields "Name" or "Work" or "E-Mail" are not suitable for this purpose.
E.g., some day there might be records about two different people in the data-base that have the same name.
Thus in data-base-management, it is common practise to indroduce in the structure of data-records a data-field which for each data-record holds a piece of information which does not occur within the corresponding data-field of any other data-record.
Usually this data-field is called a "primary key".
Often this primary-key is just some item of continuous numeration which is obtained by continuously numerating data-records.
When introducing a primary-key, the data-base "contact details" could look like this:
Data-base: contact-details
==========================
Data-record 001:
----------------
Value of data-field "Primary Key":=001
Value of data-field "Name":=John Doe
Value of data-field "Work":=whistle blower
Value of data-field "E-Mail":=Whistle@fake.email.address
Data-record 002:
----------------
Value of data-field "Primary Key":=002
Value of data-field "Name":=Jane Smith
Value of data-field "Work":=employée at department of alternative facts
Value of data-field "E-Mail":=AltFacts@fake.email.address
When doing this, you can - besides the single data-records - also maintain
- a list of primary-keys belonging to the data-base an
- a counter denoting the amount of records belonging to the data-base:
Data-base: contact-details
==========================
Amount of data-records: 2
List of primary-keys: {001}, {002}
Data-record 001:
----------------
Value of data-field "Primary Key":=001
Value of data-field "Name":=John Doe
Value of data-field "Work":=whistle blower
Value of data-field "E-Mail":=Whistle@fake.email.address
Data-record 002:
----------------
Value of data-field "Primary Key":=002
Value of data-field "Name":=Jane Smith
Value of data-field "Work":=employée at department of alternative facts
Value of data-field "E-Mail":=AltFacts@fake.email.address
The list of primary-keys would be of special interest for sorting out specific data-records:
Assume you wish to retrieve the e-mail-address of Jane Smith:
In terms of pseudo-code, you would do this via a directive like:
Iterate on that list of primary-keys that belongs to
the data-base "contact-details" as follows:
In each iteration "look" at the value of the data-field "Name"
of that data-record whose data-field "Primary Key" equals the
current list element.
If that value equals "Jane Smith", print out the value of the
data-field "E-Mail" of that data-record.
Pitfalls related to (La)TeX:
When implementing such things in terms of (La)TeX, you will encounter a few problems which have to do with the fact that (La)TeX is a macro-language which does some pre-processing of input in terms of reading and tokenizing input:
For example, curly braces ({
and }
) have a specific meaning in LaTeX and usually each opening-brace must habe a matching closing-brace and vice versa.
For example, the percent-character (%
) has a specific meaning in LaTeX.
But according to RFC 2822 e-mail-adresses may contain unbalanced curly braces and percent-characters.
Therefore maintaining such entries via a data-base that is provided in terms of (La)TeX-input might be related to circumstances which the not-so experienced user might see as problems.
E.g., Alt}Fa%c#1ts@fake.email.address
would be a nice e-mail-address.
But how to get the value Alt}Fa%c#1ts@fake.email.address
into a data-record's data-field "E-Mail" in case the data-base in question is maintained in (La)TeX?
At first glimpse you could do it by means of macros that deliver the desired symbols in question:
Something like:
Value of data-field "E-Mail":=Altleftbrace Fatextpercent chash1ts@fake.email.address
Also the names of people/organizations might contain characters/symbols which the input-encoding in which the (La)TeX-file is written does not contain.
Assume one of the persons whose contact-details are to be maintained has the name Alaïa Maëlys Gambolpütty while the data-base is written in a (La)TeX-input-file that is encoded in ASCII.
In such a case you must do it in terms of control-sequence-tokens whose names are formed by characters within the range of the input-encoding.
But such control-sequences make sorting out specific data-records difficult.
Therefore it might be a good idea to maintain each piece of data twice:
Once written only by means of characters of the input-encoding in question.
Once written in a way where also LaTeX-control-sequences that deliver the desired characters/symbols may occur:
Data-base: contact-details
==========================
Amount of data-records: 3
List of primary-keys: {001}, {002}, {003}
Data-record 001:
----------------
Value of data-field "Primary Key":=001
Value of data-field "Name" in input-encoding-representation:=John Doe
Value of data-field "Name" in LaTeX-representation:=John Doe
Value of data-field "Work" in input-encoding-representation:=whistle blower
Value of data-field "Work" in LaTeX-representation:=whistle blower
Value of data-field "E-Mail" in input-encoding-representation:=Whistle@fake.email.address
Value of data-field "E-Mail" in LaTeX-representation:=Whistle@fake.email.address
Data-record 002:
----------------
Value of data-field "Primary Key":=002
Value of data-field "Name" in input-encoding-representation:=Jane Smith
Value of data-field "Name" in LaTeX-representation:=Jane Smith
Value of data-field "Work" in input-encoding-representation:=employee at department of alternative facts
Value of data-field "Work" in LaTeX-representation:=employ'ee at department of alternative facts
Value of data-field "E-Mail" in input-encoding-representation:=AltFacts@fake.email.address
Value of data-field "E-Mail" in LaTeX-representation:=AltFacts@fake.email.address
Data-record 003:
----------------
Value of data-field "Primary Key":=003
Value of data-field "Name" in input-encoding-representation:=Alaia Maelys Gambolpuetty
Value of data-field "Name" in LaTeX-representation:=Ala"{i}a Ma"{e}lys Gambolp"{u}tty
Value of data-field "Work" in input-encoding-representation:=employee at department of alternative facts
Value of data-field "Work" in LaTeX-representation:=employée at department of alternative facts
Value of data-field "E-Mail" in input-encoding-representation:=Alt}Fa%c#1ts@fake.email.address
Value of data-field "E-Mail" in LaTeX-representation:=Altleftbrace Fatextpercent chash1ts@fake.email.address
...
With such an approach you could implement an interface where searching and sorting out takes place in terms of input-encoding-representation and delivers data in terms of LaTeX-representation.
With such an interface, one stage would always include reading and tokenizing the input-encoding-representations under verbatim-catcode-régime.
This is feasible but makes using the macros that form the interface
- within pure-expansion-contexts impossible.
- within the definition-texts of other macros cumbersome.
With such an interface, it would also be a good idea to have everything that denotes names of databases or names of data-fields or values in input-encoding-representation evaluate to characters of the input-encoding.
Therefore for proper error-checking a routine would be useful which does fully evaluate/expand arguments and then does check whether the expansion-result does hold character-tokens obeying the verbatim-catcode-régime only.
Full evaluation/expansion of an argument that might hold arbitrary tokens is already a nice problem.
An easy approach would be using edef
.
For one thing this also would break expandability of the interface.
For another thing edef
is not totally safe with arbitrary tokens.
E.g., look at
edeftest{%
Where does the definition text
stop?iffalse{fi Here?} Or Here?{iffalse}fi
}
I think a minimalist interface for some sort of database-management is feasible in LaTeX – with things like:
NewInitializedDataRecord{<Primary Key>}%
{<Name>}%
{<Work>}%
{<EMail>}%
NewEmptyDataRecord{<Primary Key>}
AddNewDataFieldToDataRecord{<Primary Key>}{<Name of data-field>}{<Value>}%
VerbatimizedAddNewDataFieldToDataRecord{<Primary Key>}{<Name of data-field>}|<Value>|% <- verbatim-arg
(extraction of verbatimized values of data-fields via scantokens...)
PrintFieldValueFromDataRecord{<Primary Key>}{<Name of data-field>}
PrintDataRecord{<Primary Key>}
PrintAllDataRecords
PrintAllDataRecordsWithSpecificDatFieldValue{<Name of data-field>}{<Specific Value>}
But before going into details, specification about the tokens that might form values of data-fields and about their treatment when comparing values of data-fields is needed.
I am not sure if I understood your comments. Anyway, thanks for attention. Let me inform that the contacts come from authors of a paper, so I think that two exactly equal names could happen rarely.
– Sigur
Nov 16 at 18:13
Your question actually is about some sort of whatsoever minimalist database-management. :-) I extended my answer in the hope of pointing out some of the pitfalls related to whatsoever minimalist database-management in terms of a macro language. :-)
– Ulrich Diez
Nov 16 at 21:29
Well, thanks for your work. But I confess that I have no idea how to understand it... lol
– Sigur
Nov 16 at 21:33
I think you want to say “From relational algebra we know that it is not a good idea to assign to each data-record its own unique primary-key as a data-field of its own of that data-record.”.
– egreg
Nov 16 at 21:48
@UlrichDiez The formulation is way better now. For the same reason I assigned a label to each contact.
– egreg
Nov 16 at 22:31
add a comment |
up vote
0
down vote
up vote
0
down vote
This "answer" does not answer your question.
A few remarks about the pitfalls of database-management in LaTeX
A few remarks about database-management in general:
Usually data is organized in so-called data-bases.
A data-base could, e.g., be a list of contact-details.
Each person or organization that you wish to contact might within the data-base be connected to a data-record which holds all the contact-details related to that person/organization.
Therefore a data-record itself could be organized by means of data-fields whereby each field serves for storing/providing information that belongs to a specific category.
Thus the logical structure of a data-base could be something like:
Data-base: contact-details
==========================
Data-record 001:
----------------
Value of data-field "Name":=John Doe
Value of data-field "Work":=whistle blower
Value of data-field "E-Mail":=Whistle@fake.email.address
Data-record 002:
----------------
Value of data-field "Name":=Jane Smith
Value of data-field "Work":=employée at department of alternative facts
Value of data-field "E-Mail":=AltFacts@fake.email.address
...
You need means
- both for identifying each record that belongs to a data-base
- and for keeping the single records that belong to a data-base distinguishable from each other.
The data-fields "Name" or "Work" or "E-Mail" are not suitable for this purpose.
E.g., some day there might be records about two different people in the data-base that have the same name.
Thus in data-base-management, it is common practise to indroduce in the structure of data-records a data-field which for each data-record holds a piece of information which does not occur within the corresponding data-field of any other data-record.
Usually this data-field is called a "primary key".
Often this primary-key is just some item of continuous numeration which is obtained by continuously numerating data-records.
When introducing a primary-key, the data-base "contact details" could look like this:
Data-base: contact-details
==========================
Data-record 001:
----------------
Value of data-field "Primary Key":=001
Value of data-field "Name":=John Doe
Value of data-field "Work":=whistle blower
Value of data-field "E-Mail":=Whistle@fake.email.address
Data-record 002:
----------------
Value of data-field "Primary Key":=002
Value of data-field "Name":=Jane Smith
Value of data-field "Work":=employée at department of alternative facts
Value of data-field "E-Mail":=AltFacts@fake.email.address
When doing this, you can - besides the single data-records - also maintain
- a list of primary-keys belonging to the data-base an
- a counter denoting the amount of records belonging to the data-base:
Data-base: contact-details
==========================
Amount of data-records: 2
List of primary-keys: {001}, {002}
Data-record 001:
----------------
Value of data-field "Primary Key":=001
Value of data-field "Name":=John Doe
Value of data-field "Work":=whistle blower
Value of data-field "E-Mail":=Whistle@fake.email.address
Data-record 002:
----------------
Value of data-field "Primary Key":=002
Value of data-field "Name":=Jane Smith
Value of data-field "Work":=employée at department of alternative facts
Value of data-field "E-Mail":=AltFacts@fake.email.address
The list of primary-keys would be of special interest for sorting out specific data-records:
Assume you wish to retrieve the e-mail-address of Jane Smith:
In terms of pseudo-code, you would do this via a directive like:
Iterate on that list of primary-keys that belongs to
the data-base "contact-details" as follows:
In each iteration "look" at the value of the data-field "Name"
of that data-record whose data-field "Primary Key" equals the
current list element.
If that value equals "Jane Smith", print out the value of the
data-field "E-Mail" of that data-record.
Pitfalls related to (La)TeX:
When implementing such things in terms of (La)TeX, you will encounter a few problems which have to do with the fact that (La)TeX is a macro-language which does some pre-processing of input in terms of reading and tokenizing input:
For example, curly braces ({
and }
) have a specific meaning in LaTeX and usually each opening-brace must habe a matching closing-brace and vice versa.
For example, the percent-character (%
) has a specific meaning in LaTeX.
But according to RFC 2822 e-mail-adresses may contain unbalanced curly braces and percent-characters.
Therefore maintaining such entries via a data-base that is provided in terms of (La)TeX-input might be related to circumstances which the not-so experienced user might see as problems.
E.g., Alt}Fa%c#1ts@fake.email.address
would be a nice e-mail-address.
But how to get the value Alt}Fa%c#1ts@fake.email.address
into a data-record's data-field "E-Mail" in case the data-base in question is maintained in (La)TeX?
At first glimpse you could do it by means of macros that deliver the desired symbols in question:
Something like:
Value of data-field "E-Mail":=Altleftbrace Fatextpercent chash1ts@fake.email.address
Also the names of people/organizations might contain characters/symbols which the input-encoding in which the (La)TeX-file is written does not contain.
Assume one of the persons whose contact-details are to be maintained has the name Alaïa Maëlys Gambolpütty while the data-base is written in a (La)TeX-input-file that is encoded in ASCII.
In such a case you must do it in terms of control-sequence-tokens whose names are formed by characters within the range of the input-encoding.
But such control-sequences make sorting out specific data-records difficult.
Therefore it might be a good idea to maintain each piece of data twice:
Once written only by means of characters of the input-encoding in question.
Once written in a way where also LaTeX-control-sequences that deliver the desired characters/symbols may occur:
Data-base: contact-details
==========================
Amount of data-records: 3
List of primary-keys: {001}, {002}, {003}
Data-record 001:
----------------
Value of data-field "Primary Key":=001
Value of data-field "Name" in input-encoding-representation:=John Doe
Value of data-field "Name" in LaTeX-representation:=John Doe
Value of data-field "Work" in input-encoding-representation:=whistle blower
Value of data-field "Work" in LaTeX-representation:=whistle blower
Value of data-field "E-Mail" in input-encoding-representation:=Whistle@fake.email.address
Value of data-field "E-Mail" in LaTeX-representation:=Whistle@fake.email.address
Data-record 002:
----------------
Value of data-field "Primary Key":=002
Value of data-field "Name" in input-encoding-representation:=Jane Smith
Value of data-field "Name" in LaTeX-representation:=Jane Smith
Value of data-field "Work" in input-encoding-representation:=employee at department of alternative facts
Value of data-field "Work" in LaTeX-representation:=employ'ee at department of alternative facts
Value of data-field "E-Mail" in input-encoding-representation:=AltFacts@fake.email.address
Value of data-field "E-Mail" in LaTeX-representation:=AltFacts@fake.email.address
Data-record 003:
----------------
Value of data-field "Primary Key":=003
Value of data-field "Name" in input-encoding-representation:=Alaia Maelys Gambolpuetty
Value of data-field "Name" in LaTeX-representation:=Ala"{i}a Ma"{e}lys Gambolp"{u}tty
Value of data-field "Work" in input-encoding-representation:=employee at department of alternative facts
Value of data-field "Work" in LaTeX-representation:=employée at department of alternative facts
Value of data-field "E-Mail" in input-encoding-representation:=Alt}Fa%c#1ts@fake.email.address
Value of data-field "E-Mail" in LaTeX-representation:=Altleftbrace Fatextpercent chash1ts@fake.email.address
...
With such an approach you could implement an interface where searching and sorting out takes place in terms of input-encoding-representation and delivers data in terms of LaTeX-representation.
With such an interface, one stage would always include reading and tokenizing the input-encoding-representations under verbatim-catcode-régime.
This is feasible but makes using the macros that form the interface
- within pure-expansion-contexts impossible.
- within the definition-texts of other macros cumbersome.
With such an interface, it would also be a good idea to have everything that denotes names of databases or names of data-fields or values in input-encoding-representation evaluate to characters of the input-encoding.
Therefore for proper error-checking a routine would be useful which does fully evaluate/expand arguments and then does check whether the expansion-result does hold character-tokens obeying the verbatim-catcode-régime only.
Full evaluation/expansion of an argument that might hold arbitrary tokens is already a nice problem.
An easy approach would be using edef
.
For one thing this also would break expandability of the interface.
For another thing edef
is not totally safe with arbitrary tokens.
E.g., look at
edeftest{%
Where does the definition text
stop?iffalse{fi Here?} Or Here?{iffalse}fi
}
I think a minimalist interface for some sort of database-management is feasible in LaTeX – with things like:
NewInitializedDataRecord{<Primary Key>}%
{<Name>}%
{<Work>}%
{<EMail>}%
NewEmptyDataRecord{<Primary Key>}
AddNewDataFieldToDataRecord{<Primary Key>}{<Name of data-field>}{<Value>}%
VerbatimizedAddNewDataFieldToDataRecord{<Primary Key>}{<Name of data-field>}|<Value>|% <- verbatim-arg
(extraction of verbatimized values of data-fields via scantokens...)
PrintFieldValueFromDataRecord{<Primary Key>}{<Name of data-field>}
PrintDataRecord{<Primary Key>}
PrintAllDataRecords
PrintAllDataRecordsWithSpecificDatFieldValue{<Name of data-field>}{<Specific Value>}
But before going into details, specification about the tokens that might form values of data-fields and about their treatment when comparing values of data-fields is needed.
This "answer" does not answer your question.
A few remarks about the pitfalls of database-management in LaTeX
A few remarks about database-management in general:
Usually data is organized in so-called data-bases.
A data-base could, e.g., be a list of contact-details.
Each person or organization that you wish to contact might within the data-base be connected to a data-record which holds all the contact-details related to that person/organization.
Therefore a data-record itself could be organized by means of data-fields whereby each field serves for storing/providing information that belongs to a specific category.
Thus the logical structure of a data-base could be something like:
Data-base: contact-details
==========================
Data-record 001:
----------------
Value of data-field "Name":=John Doe
Value of data-field "Work":=whistle blower
Value of data-field "E-Mail":=Whistle@fake.email.address
Data-record 002:
----------------
Value of data-field "Name":=Jane Smith
Value of data-field "Work":=employée at department of alternative facts
Value of data-field "E-Mail":=AltFacts@fake.email.address
...
You need means
- both for identifying each record that belongs to a data-base
- and for keeping the single records that belong to a data-base distinguishable from each other.
The data-fields "Name" or "Work" or "E-Mail" are not suitable for this purpose.
E.g., some day there might be records about two different people in the data-base that have the same name.
Thus in data-base-management, it is common practise to indroduce in the structure of data-records a data-field which for each data-record holds a piece of information which does not occur within the corresponding data-field of any other data-record.
Usually this data-field is called a "primary key".
Often this primary-key is just some item of continuous numeration which is obtained by continuously numerating data-records.
When introducing a primary-key, the data-base "contact details" could look like this:
Data-base: contact-details
==========================
Data-record 001:
----------------
Value of data-field "Primary Key":=001
Value of data-field "Name":=John Doe
Value of data-field "Work":=whistle blower
Value of data-field "E-Mail":=Whistle@fake.email.address
Data-record 002:
----------------
Value of data-field "Primary Key":=002
Value of data-field "Name":=Jane Smith
Value of data-field "Work":=employée at department of alternative facts
Value of data-field "E-Mail":=AltFacts@fake.email.address
When doing this, you can - besides the single data-records - also maintain
- a list of primary-keys belonging to the data-base an
- a counter denoting the amount of records belonging to the data-base:
Data-base: contact-details
==========================
Amount of data-records: 2
List of primary-keys: {001}, {002}
Data-record 001:
----------------
Value of data-field "Primary Key":=001
Value of data-field "Name":=John Doe
Value of data-field "Work":=whistle blower
Value of data-field "E-Mail":=Whistle@fake.email.address
Data-record 002:
----------------
Value of data-field "Primary Key":=002
Value of data-field "Name":=Jane Smith
Value of data-field "Work":=employée at department of alternative facts
Value of data-field "E-Mail":=AltFacts@fake.email.address
The list of primary-keys would be of special interest for sorting out specific data-records:
Assume you wish to retrieve the e-mail-address of Jane Smith:
In terms of pseudo-code, you would do this via a directive like:
Iterate on that list of primary-keys that belongs to
the data-base "contact-details" as follows:
In each iteration "look" at the value of the data-field "Name"
of that data-record whose data-field "Primary Key" equals the
current list element.
If that value equals "Jane Smith", print out the value of the
data-field "E-Mail" of that data-record.
Pitfalls related to (La)TeX:
When implementing such things in terms of (La)TeX, you will encounter a few problems which have to do with the fact that (La)TeX is a macro-language which does some pre-processing of input in terms of reading and tokenizing input:
For example, curly braces ({
and }
) have a specific meaning in LaTeX and usually each opening-brace must habe a matching closing-brace and vice versa.
For example, the percent-character (%
) has a specific meaning in LaTeX.
But according to RFC 2822 e-mail-adresses may contain unbalanced curly braces and percent-characters.
Therefore maintaining such entries via a data-base that is provided in terms of (La)TeX-input might be related to circumstances which the not-so experienced user might see as problems.
E.g., Alt}Fa%c#1ts@fake.email.address
would be a nice e-mail-address.
But how to get the value Alt}Fa%c#1ts@fake.email.address
into a data-record's data-field "E-Mail" in case the data-base in question is maintained in (La)TeX?
At first glimpse you could do it by means of macros that deliver the desired symbols in question:
Something like:
Value of data-field "E-Mail":=Altleftbrace Fatextpercent chash1ts@fake.email.address
Also the names of people/organizations might contain characters/symbols which the input-encoding in which the (La)TeX-file is written does not contain.
Assume one of the persons whose contact-details are to be maintained has the name Alaïa Maëlys Gambolpütty while the data-base is written in a (La)TeX-input-file that is encoded in ASCII.
In such a case you must do it in terms of control-sequence-tokens whose names are formed by characters within the range of the input-encoding.
But such control-sequences make sorting out specific data-records difficult.
Therefore it might be a good idea to maintain each piece of data twice:
Once written only by means of characters of the input-encoding in question.
Once written in a way where also LaTeX-control-sequences that deliver the desired characters/symbols may occur:
Data-base: contact-details
==========================
Amount of data-records: 3
List of primary-keys: {001}, {002}, {003}
Data-record 001:
----------------
Value of data-field "Primary Key":=001
Value of data-field "Name" in input-encoding-representation:=John Doe
Value of data-field "Name" in LaTeX-representation:=John Doe
Value of data-field "Work" in input-encoding-representation:=whistle blower
Value of data-field "Work" in LaTeX-representation:=whistle blower
Value of data-field "E-Mail" in input-encoding-representation:=Whistle@fake.email.address
Value of data-field "E-Mail" in LaTeX-representation:=Whistle@fake.email.address
Data-record 002:
----------------
Value of data-field "Primary Key":=002
Value of data-field "Name" in input-encoding-representation:=Jane Smith
Value of data-field "Name" in LaTeX-representation:=Jane Smith
Value of data-field "Work" in input-encoding-representation:=employee at department of alternative facts
Value of data-field "Work" in LaTeX-representation:=employ'ee at department of alternative facts
Value of data-field "E-Mail" in input-encoding-representation:=AltFacts@fake.email.address
Value of data-field "E-Mail" in LaTeX-representation:=AltFacts@fake.email.address
Data-record 003:
----------------
Value of data-field "Primary Key":=003
Value of data-field "Name" in input-encoding-representation:=Alaia Maelys Gambolpuetty
Value of data-field "Name" in LaTeX-representation:=Ala"{i}a Ma"{e}lys Gambolp"{u}tty
Value of data-field "Work" in input-encoding-representation:=employee at department of alternative facts
Value of data-field "Work" in LaTeX-representation:=employée at department of alternative facts
Value of data-field "E-Mail" in input-encoding-representation:=Alt}Fa%c#1ts@fake.email.address
Value of data-field "E-Mail" in LaTeX-representation:=Altleftbrace Fatextpercent chash1ts@fake.email.address
...
With such an approach you could implement an interface where searching and sorting out takes place in terms of input-encoding-representation and delivers data in terms of LaTeX-representation.
With such an interface, one stage would always include reading and tokenizing the input-encoding-representations under verbatim-catcode-régime.
This is feasible but makes using the macros that form the interface
- within pure-expansion-contexts impossible.
- within the definition-texts of other macros cumbersome.
With such an interface, it would also be a good idea to have everything that denotes names of databases or names of data-fields or values in input-encoding-representation evaluate to characters of the input-encoding.
Therefore for proper error-checking a routine would be useful which does fully evaluate/expand arguments and then does check whether the expansion-result does hold character-tokens obeying the verbatim-catcode-régime only.
Full evaluation/expansion of an argument that might hold arbitrary tokens is already a nice problem.
An easy approach would be using edef
.
For one thing this also would break expandability of the interface.
For another thing edef
is not totally safe with arbitrary tokens.
E.g., look at
edeftest{%
Where does the definition text
stop?iffalse{fi Here?} Or Here?{iffalse}fi
}
I think a minimalist interface for some sort of database-management is feasible in LaTeX – with things like:
NewInitializedDataRecord{<Primary Key>}%
{<Name>}%
{<Work>}%
{<EMail>}%
NewEmptyDataRecord{<Primary Key>}
AddNewDataFieldToDataRecord{<Primary Key>}{<Name of data-field>}{<Value>}%
VerbatimizedAddNewDataFieldToDataRecord{<Primary Key>}{<Name of data-field>}|<Value>|% <- verbatim-arg
(extraction of verbatimized values of data-fields via scantokens...)
PrintFieldValueFromDataRecord{<Primary Key>}{<Name of data-field>}
PrintDataRecord{<Primary Key>}
PrintAllDataRecords
PrintAllDataRecordsWithSpecificDatFieldValue{<Name of data-field>}{<Specific Value>}
But before going into details, specification about the tokens that might form values of data-fields and about their treatment when comparing values of data-fields is needed.
edited Nov 18 at 17:34
answered Nov 16 at 17:55
Ulrich Diez
3,745515
3,745515
I am not sure if I understood your comments. Anyway, thanks for attention. Let me inform that the contacts come from authors of a paper, so I think that two exactly equal names could happen rarely.
– Sigur
Nov 16 at 18:13
Your question actually is about some sort of whatsoever minimalist database-management. :-) I extended my answer in the hope of pointing out some of the pitfalls related to whatsoever minimalist database-management in terms of a macro language. :-)
– Ulrich Diez
Nov 16 at 21:29
Well, thanks for your work. But I confess that I have no idea how to understand it... lol
– Sigur
Nov 16 at 21:33
I think you want to say “From relational algebra we know that it is not a good idea to assign to each data-record its own unique primary-key as a data-field of its own of that data-record.”.
– egreg
Nov 16 at 21:48
@UlrichDiez The formulation is way better now. For the same reason I assigned a label to each contact.
– egreg
Nov 16 at 22:31
add a comment |
I am not sure if I understood your comments. Anyway, thanks for attention. Let me inform that the contacts come from authors of a paper, so I think that two exactly equal names could happen rarely.
– Sigur
Nov 16 at 18:13
Your question actually is about some sort of whatsoever minimalist database-management. :-) I extended my answer in the hope of pointing out some of the pitfalls related to whatsoever minimalist database-management in terms of a macro language. :-)
– Ulrich Diez
Nov 16 at 21:29
Well, thanks for your work. But I confess that I have no idea how to understand it... lol
– Sigur
Nov 16 at 21:33
I think you want to say “From relational algebra we know that it is not a good idea to assign to each data-record its own unique primary-key as a data-field of its own of that data-record.”.
– egreg
Nov 16 at 21:48
@UlrichDiez The formulation is way better now. For the same reason I assigned a label to each contact.
– egreg
Nov 16 at 22:31
I am not sure if I understood your comments. Anyway, thanks for attention. Let me inform that the contacts come from authors of a paper, so I think that two exactly equal names could happen rarely.
– Sigur
Nov 16 at 18:13
I am not sure if I understood your comments. Anyway, thanks for attention. Let me inform that the contacts come from authors of a paper, so I think that two exactly equal names could happen rarely.
– Sigur
Nov 16 at 18:13
Your question actually is about some sort of whatsoever minimalist database-management. :-) I extended my answer in the hope of pointing out some of the pitfalls related to whatsoever minimalist database-management in terms of a macro language. :-)
– Ulrich Diez
Nov 16 at 21:29
Your question actually is about some sort of whatsoever minimalist database-management. :-) I extended my answer in the hope of pointing out some of the pitfalls related to whatsoever minimalist database-management in terms of a macro language. :-)
– Ulrich Diez
Nov 16 at 21:29
Well, thanks for your work. But I confess that I have no idea how to understand it... lol
– Sigur
Nov 16 at 21:33
Well, thanks for your work. But I confess that I have no idea how to understand it... lol
– Sigur
Nov 16 at 21:33
I think you want to say “From relational algebra we know that it is not a good idea to assign to each data-record its own unique primary-key as a data-field of its own of that data-record.”.
– egreg
Nov 16 at 21:48
I think you want to say “From relational algebra we know that it is not a good idea to assign to each data-record its own unique primary-key as a data-field of its own of that data-record.”.
– egreg
Nov 16 at 21:48
@UlrichDiez The formulation is way better now. For the same reason I assigned a label to each contact.
– egreg
Nov 16 at 22:31
@UlrichDiez The formulation is way better now. For the same reason I assigned a label to each contact.
– egreg
Nov 16 at 22:31
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f460175%2fsaving-arguments-of-commands-to-be-used-later%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown