Mass Un-camel-case Every Tiddler Title

Hello all,

After months of using tw daily, I’ve come to the conclusion that everything would be better if I hadn’t started with the convention of camel-casing my titles. I now have over 2000 tiddlers that I want to batch un-camel-case the titles of. (e.g. the simplest way to hit a button or run some code and magically make all 2000 tiddlers go from “LanguageIsForCommunication” to “language is for communication” and for single-word titles from “Hypothesis” to “hypothesis”). Can anyone think of some creative way to do this? Any help is much appreciated!

-Noa

Give this a try… but be sure to backup your file first!

<$vars caps="([A-Z]+)">
<$button> un-camel-case
<$list filter="[all[tiddlers]!is[system]]">
   <$action-setfield title={{{ [<currentTiddler>search-replace:g:regexp<caps>,[ $1]lowercase[]trim[]] }}} />
   <$action-deletetiddler $tiddler=<<currentTiddler>> />
</$list>
</$button>
</$vars>

Notes:

  1. <$vars caps="([A-Z]+)"> defines a regular expression pattern to match a sequence of one or more capital letters. The parentheses in the regular expression creates a “capture group” for the matched capital letters, so that they can be inserted into the replacement text by using $1.
  2. The <$list> filter matches all tiddlers, except for system tiddlers (starting with $:/).
  3. <$action-setfield> actually creates a copy of the matched tiddler with a new title.
  4. The new title is constructed using a filtered transclusion that takes the existing title, matches all sequences of capital letters, adds a leading space before each sequence, converts it all to lowercase, and removes any leading/trailing whitespace.
  5. <$action-deletetiddler> deletes the old mixed-case tiddler.

I strongly suggest that, in addition to backing up your file, you should also do a “dry run” by first omitting the <$action-deletetiddler> widget so you can verify that the new tiddler titles are acceptable before removing the old tiddler titles. When you are satisfied with the results, then add the <$action-deletetiddler> and re-run the code again.

Let me know how it goes…

enjoy,
-e

4 Likes

Thank you so much for this quick and brilliant reply!
I tried this out on a separate copy of my tw and it almost works perfectly. The one problem is that I’d like there to be some way to use relink to change all links to now link to the newly-named tiddlers. Is that possible, do you think?

Thanks!
Noa

@noa I think avoiding Camel case in titles is simple, and Eric is helping you remove them, but from experience this should not be an issue, as you can see it is not an issue in the various default core lists that tiddlywiki uses such as recent, open etc…

Can you illustrate where this is causing a problem?

More often that not it can be addressed by converting a title to text, or wrapping [[the whole title as a tiddler title]].

<$text text={{!!title}}/>

So I am arguing the “Null Case”, don’t change them, deal with them. I/we are happy to help you resolve this and cope with camelCase in titles as well as helping improve your coding practice.

That is really awesome Eric. Thanks!

I can’t stand CamelCase, so I am keeping the gem you’ve provided handy.)

Noa: thanks for starting this thread !

Use this modified @EricShulman solution

<$vars caps="([A-Z]+)">
<$button> un-camel-case
<$list filter="[all[tiddlers]!is[system]!regexp[\s]!sort[modified]limit[50]]">
 <$vars newTitle={{{ [<currentTiddler>search-replace:g:regexp<caps>,[ $1]lowercase[]trim[]] }}} >
   <$action-sendmessage $message=tm-rename-tiddler from=<<currentTiddler>> to=<<newTitle>>/>
</$vars>	
</$list>
</$button>
</$vars>

I also modified the search in title to look for title have one camelCase expression, so the code changes HiEric to hi eric but not Hi Eric to hi eric.

The limit[50] helps to prevent unresponsive Tiddlywiki. This is important if you have several hundreds tiddlers with many links.

  • NOTE: Make sure to have the latest relink plugin installed in your Tiddlywiki.
2 Likes

Thank you so much, Mohammad and Eric! I have now officially clicked the button 40 times and now my TW looks exactly how I dreamed it would look. :slight_smile:

(It is really amazing to be part of this community that helps each other like this within hours!)

3 Likes

@Flibbles
If you use the above code without limit[50] in $list widget, with relink installed on https://tiddlywiki.com, TW freezes! Is there any any solution for this?
May be @jeremyruston also can give some advices here. If user can see a message like: operation in progress… wait

What do you expect? If you change a single tiddler title, the relink plugin has to go through every single tiddler and apply it’s magic. Not only the title. It has to check the whole text, all fields, every macro definition and possibly some other stuff …

So eg: 2000 tiddlers to check times 50 tiddlers to rename. You have to go 10000 times through the whole wiki. Or 4 000 000 times, if you want to do it all in 1 run. … What do you expect?

I expect a notification to tell the user, wait,… a lengthy operation is in progress and takes several minutes…

But now I get a frozen page and I have to reload the page and loose my unsaved changes…

1 Like

TW doesn’t freeze for me. It just take a minute. It’s having to sift through every tiddler many times, and as much as it tries to cache, each relink causes every touched tiddler to be re-evaluated. You’re performing an expensive operation there.

OK … That’s fair.

The problem is, that TW doesn’t know that upfront. Neither does the browser. … Most browsers will show a message after some seconds, that there is something going on with javascript and if you want to stop it.

Clicking the “Continue” button several times may be resolve the issue. …

Clicking “Stop” will definitely cause an undefined state and a reload has to be done.

I would put the onus on the one making bulk operators about creating a “Working… please wait” indication. The best way to do that would be to make a javascript macro which pushes each of these renames to the event stack, one-after-another so that it has time to clear between each tiddler. That would keep it from freezing while it’s working.

1 Like

Thank you both @pmario and @Flibbles
I documented this in TW-Scripts and will push it to GitHub soon!

You are right, this is a very expensive operation! So, while you gave useful hints, I think it is fair to use ALSO the first solution e.g. use limit[50] and click the button several times.

This kind of problem who’s execution results in many iterations and thus time, is similar to Dynamic Programing where the programer can estimate the time and space required for a given algorithm process and finding ways to optimise it.

Perhaps a “poormans” version would be in such cases to put some analytics on a sample of cases eg 10 or 100, then given a count of cases estimate the time to do all “remaining” cases. A method to click to do next 10, next 100, All etc… and let the user make a decision according to the “time to complete”.

The real solution is to create a custom javascript macro:

// This tiddler can be transcluded into whatever tiddler has
// the "un-camel-case button", and it will show a growing
// percentage number of progress.
var stateTiddler = "$:/state/progress";

exports.run = function(stringListOfTiddlers) {
   var i = 0,
       list = $tw.utils.parseStringArray(stringListOfTiddlers);
   function next() {
      // Set the progress percentage
      $tw.wiki.addTiddler({title: stateTiddler, text: i / list.length });
      // Do the actual renaming of the next tiddler
      $tw.wiki.renameTiddler(listOfTiddlers[i], /* New tiddler name */);
      i++;
      if (i < list.length) {
         // More tiddlers to go. Push the next rename to the event queue.
         $tw.utils.nextTick(next);
      } else {
         // No more tiddlers to rename. Delete progress tiddler
         $tw.wiki.deleteTiddler(stateTiddler);
      }
   }
   next();
};

This is completely untested, but if this operation is to be part of a plugin (say TW-Commander), then this is the way you’d keep TiddlyWiki from freezing up while it’s working, and it gives a nice progress percent indicator.

(This is completely untested. I didn’t even make sure I got the right function names.)

EDIT: Yeah, now that I think about it, you want this to be a custom action-widget, not a macro, but same idea.

2 Likes

@noa Sorry to revive this thread, but I’m interested in why you decided to move away from CamelCase titles? I’m asking because I have been considering the opposite move (spaces to CamelCase), and I’m wondering what the reasoning was behind abandoning CamelCase?

I’ll chime in with my own reasons.

I rely on the shape of words to recognize them. The words are easier to see and parse out when there are spaces betweeen those words.

Maybe most folk recognize CamelCase, the grouping of words, as an abstract thing that means something in the same way an icon means something.

But CamelCase-style word groupings, just like icons, totally throw me off: it takes me longer, more effort, to process what I’m looking at.

It is much easier for me to understand what I’m seeing when they are words vs images, and much easier to understand words that are neatly separated.

The first thing I do with any new TiddlyWiki instance I create: turn off CamelCase.

1 Like

I’m curious about OP (noa’s) reasoning as well, but for anyone writing TiddlyWiki projects for eventual publication to a beyond-TW-insider public audience, all the CamelCase stuff is a terrible distracting departure from natural language.

(Also, if you work with names like McIntyre, having to remember to type such names with the tilde prefix — to avoid having them appear as links/missing links — is a drag.)

I never know what tiddlers I may want to copy over to a public-facing wiki, so it makes sense to set the CamelCaseToLink norm aside from the beginning.

1 Like

I think my reasons are very similar to Springer’s. When I send pages from my wiki to friends, I want it to read naturally. Although even with just a private-facing wiki, I feel the same way. I like the aesthetic of a “normal”- looking page with links that don’t break up the natural flow of the language.

Now I’m curious to know for Sii and others who are switching to/sticking with CamelCase, what elements convinced you to do that?

1 Like