Macros listing fields with spaces in their names

Continuing the discussion from Display selected fields in a Tiddler but only those with values:

Here is my working version:

\define field-list(names:"Home Occupation Residence")
<table>    
<$list filter="[enlist<__names__>]" variable=name>
  <$list filter="[all[current]get<name>]" variable=value>
    <tr><td><<name>></td><td><<value>></td></tr>
  </$list>
</$list>
</table>
\end

Ideally, I want to use some fields with spaces in the field name, so in place of Residence in the list I want to use Place of residence.

It works fine in the tiddler itself, but is it possible to modify the statement to something like:

\define field-list(names:“Home Occupation [Place of residence]”)

So that it actually works. I can’t find the correct syntax, if there is one.

(I realise that spaces in field names might cause me other issues, like backwards compatability with older plugins, but I’ll see if that impacts me later.)

Thanks.

If you need a field list you need to use

\define field-list() Home Occupation [[Place of residence]]

Which you then can use with

<$list filter="[<field-list>enlist-input[]]">
<<currentTiddler>><br>
</$list>

Just a remark. I personally would never use field names with spaces. I am pretty sure it will cause all sorts of weird (extremely hard to find) problems in the future.

Just my personal thought.

Thank you.

I realised that it might be somewhere experienced folk would not go. As an alternative, if I have a field, say, place_of_residence, is there some way I could use it via pseudonym? Perhaps with some lookup table/macro:

Field Alternative name
place of residence Place of residence

This is good advice if there is no specific requirement that contradicts it, I do recall however when the extended naming of fieldnames was floated, then implemented, a possibility we investigated was to create fieldnames using a “tiddler name” and thus spaces were very likely. As far as I recall there is nothing prohibiting this, just that a little additional handling may be needed.

  • In this senario one could use a fieldnamed after a tiddler to act as reference to another tiddler, and the value of the field as an indicator of the relationship eg “partnership”, “joint venture” or “colaboration”
  • however we now have better support for list fields, that can contain a list of titles so we can choose a shorter and simpler field name such as the relationship eg; partners and its value is a list of tiddler titles.

Could you expand? Does this give me a way of have alternative names for fields? So that place-residence can also be called Place of residence?

I am not sure how to answer your question;

  • You can already used a field name of "Place of residence"
  • If you used place-residence you could lookup a type of caption for that fieldname such as Place of residence
    • place-residence: Place of residence in a data tiddler to “lookup the sentence form” while keeping the fieldname space free.
    • Similarly name the field “place-of-residence” then replace - with space and format as sentence case to get “Place of residence”.
  • You could have a field of any name with a value of [[Place of residence]] and store more than one item in that field. Using enlist to extract the titles from the value.

We often need to use delimiters to set a value in a fieldname eg fieldname="Place of residence" or methods to add the title to a field (eg listops operator) resulting in [[Place of residence]].

But consider the need to do this on the left hand side of the = eg '“Place of residence”=“cote d’Azur”. However the way parameters and attributes/value pairs work there are different ways to handle this. I have not looked at this in detail for some time so would need to work through it to provide robust advice.

Recomendation:
Unless you have a very good reason, avoid fieldnames that need special handling to include spaces and other special characters and definatly adhear to the title rules;

Warning: avoid using any of the characters | [ ] { } in tiddler title

And fieldnames

@TW_Tones your reply seems to allude to what I am trying to do, but how and where do I set up this lookup?

place_of_residence maps to “Place of residence”
where place_of_residence is the real field name and “Place of residence” is the version we could display in another tiddler?

Let’s suppose you have a tiddler named test1 that has a field named place_of_residence containing a value like “123 Main Street”.

You could then create a tiddler (e.g., “MyGetField”) tagged with $:/tags/Global containing:

\function get.field(tid,fieldname)
[<fieldname>lowercase[]search-replace:g[ ],[_]] :map[<tid>get<currentTiddler>]
\end

To use this function in another tiddler, you could write something like this:

{{{ [get.field[test1],[Place of Residence]] }}}

Notes:

  • The function name, get.field, MUST contain a “.” so that it can be recognized as a function reference (as opposed to a fieldname reference. This allows it to be invoked from within the filter syntax.
  • The function first converts the fieldname to all lower case, and then replaces each space with an underscore.
  • Then, it uses a :map[...] filter run prefix to fetch the field value from the specified tiddler using the converted fieldname.
  • Note that the example uses “filtered transclusion” (the tripled curly brackets) to show the output which, when rendered, create a tiddler link. To show the result as plain text, you would write:
    <$text text={{{ [get.field[test1],[Place of Residence]] }}}/>
  • The output is equivalent to a direct reference like this:
    <$text text={{{ [[test1]get[place_of_residence]] }}}/>
  • In this example, the [test1] and [Place of residence] parameters are literal values, but you could just as easily use variables, like this:
    <$let tid="test1" field="Place of residence"><$text text={{{ [get.field<tid>,<field>] }}}/>

enjoy,
-e

Thanks. Once I upgraded to 5.3.7 that all worked nicely.

I may come back for ideas how to modify the {{{ [get.field[test1],[Place of Residence]] }}} For example, to get the place of residence for a set of tiddlers.

In case it’s helpful, I set up a demo for working in this way with fieldnames that actually have underscores, but where user interaction works with natural-looking labels (with spaces).

It includes a model of a list widget to survey all tiddlers that have [fieldname as if with space] — while actually listing tiddlers that have fieldname_with_underscore.

I have long wanted to implement “field tiddlers” similar to “tag tiddlers” against which one could set a caption field, and other details.

Now with the cascade functions I think this may be easier than ever. However just as with tags I like to use plain language names.

  • If, as in this topic, I created a tiddler field named “fieldname_with_underscore” or with spaces, it would of course some up in searches, and is some rare situations may clash with a tag or regular tiddler of the same name.

As has being addressed in this Topic the simpler solution is to simply process a fieldname into a caption or label using a deterministic pattern, for example change underscore or hyphens to spaces, sentence case the resulting words and add a colon space : at the end.

Although I would love to take this a lot further and may start a relevant topic.

1 Like

Is it possible to modify that list widget so that it Sentence cases all fields, not just those with an underscore?

If I simply remove search[_] I get every ‘field’ including title, txt and date etc.

How do I apply it to just my user fields?

Trying to get “just my user fields” sounds simple, but we may need to know more. If you get all fields from all non-system tiddlers, and then you later import a tiddler for some random utility purpose, or a plugin, etc…, you may suddenly complicate your list of fields.

I would suggest having a filter that gets all fields from tiddlers under a certain tag (or all tiddlers meeting some other filter condition that captures typical tiddlers for the workflow you have in mind here)…, and then subtracting out the ones that are unwanted.

Then you’d have an expression like [tag[people]fields[]] -title -creator -modifier -modified -created -text -type -tags

Another approach is to have, in some utility tiddler, a list of the actual fields that are relevant to the purposes you have here. If you use tags in your workflow, the tiddler for that tag is a nice place to store something like a list of fields that will be needed for some tag-relevant workflow. Make an actual tiddler at that tag node, and make a custom field there to manually list key-fields.

[{people]get[key-fields]]

Of course, then this list would not be automatically updated if you further expand your solution to add a field for each person’s website, or their position title, or whatever. But there would be one clear place to update that list — or to trim it, if you realize some field is no longer relevant.

I’ve updated the demo, so that all fields in tiddlers with a certain tag — minus typical ones — are shown, AND each fieldname_with_underscore is shown as the more readable version with spaces.

1 Like

I’m a bit puzzled what is going on here. I inserted your code into one of my tiddlers.

<table>
<$list filter="[<currentTiddler>fields[]] -title -tags -created -modified -creator -modifier -text -notes -intro -selection -draft.title -draft.of -type -revision -bag">
<tr>
<th><$text text={{{ [<currentTiddler>search-replace:g[_],[ ]sentencecase[]] }}}/></th><td><$text text={{{ [get.field<storyTiddler>,<currentTiddler>] :else[<storyTiddler>get<currentTiddler>] }}}/></td></tr>
</$list>

</table>

You will see I had to exclude three more fields.

The result I get processes the field names (underscore to space and sentence case) but some of the fields are not displaying their actual data. i.e. the table is empt in some places.

I see that your wiki has the fields “bags” and “revision” etc (which mine doesn’t have).

But I’m not sure what else may be happening. Do you have the get.field function installed, as suggested in Eric’s reply above? My solution builds on that function, to answer the questions you asked in following up to that one.

It wouldn’t be hard to develop a solution that doesn’t use such a function. But probably the most efficient solution — if you’re going to work a lot with multi-word field names that swap something like underscores in — would actually have multiple custom functions.

I have Eric’s function.

It is the fields that don’t have spaces in their names that appear in the output table but with a blank entry next to them.

I don’t know what explains the difference (am not in a position to troubleshoot much right now). But you could examine my demo of this basic idea, where single-word fields’ contents (so long as they’re lower-case as well as not having spaces) are displaying right, and see how/where it differs from yours?

So what I have found it is the fields that begin with an upper case character that are not being processed correctly.

When it is a single word, i.e. no spaces and the first character is upper case it does not show the field value.

Address
Map
Modern
Place of residence Rome
Mep [[Rome map]]

The other issue I have is that values that are wrapped in [[…]] are being interpreted literally and no longer work as links.

  • For the first problem:
    The get.field custom function assumes that ALL fields are stored using fieldnames with lower case and “_” instead of spaces. A field named “Map” (with initial upper case) does not fit this assumption. Thus, get.field fails to retrieve a field value.

  • For the second problem:
    You are using a $text widget to show the field value. This treats ALL field values as literal text, which prevents any embedded wikitext syntax, such as [[...]], from being rendered. Instead of using a $text widget, I suggest using a $transclude widget, which allows any wikitext in the field content to be rendered as intended.

Try this:

<table>
<$list filter="[<currentTiddler>fields[]] -title -tags -created -modified -creator -modifier -text -notes -intro -selection -draft.title -draft.of -type -revision -bag" variable=f>
   <tr>
   <th>
      <$text text={{{ [<f>search-replace:g[_],[ ]sentencecase[]] }}}/>
   </th>
   <td>
      <$transclude $field={{{ [<f>lowercase[]search-replace:g[ ],[_]] }}}>
         <$transclude $field=<<f>>/>
      </$transclude>
   </td>
   </tr>
</$list>
</table>

Notes:

  • The $list widget uses variable=f so that the currentTiddler value is unchanged
  • The outer $transclude widget tries to render a field whose name is converted to lower case with underscores in place of spaces.
  • For fieldnames that don’t follow the “lower case and underscores” convention (e.g., “Map”), the outer $transclude will fail, and the inner $transclude will be used as a fallback.
  • The inner $transclude then just renders the field without converting the name.

Let me know how it goes…

enjoy,
-e