Author Topic: Title Case  (Read 16447 times)

Ulfhednar

  • Contributor
  • Elite Member
  • *****
  • Posts: 439
    • View Profile
Title Case
« on: July 05, 2018, 20:24:16 »
I saw this the other day
Code: [Select]
using System;
using System.Collections.Generic;

public static class ClipboardFusionHelper
{
    public static string ProcessText(string text)
    {
        //Words that will not be capitalized; add words to this list as required
        string[] exceptionsArray = { "a", "an", "and", "any", "at", "from", "into", "of", "on", "or", "the", "to", };
     
        List<string> exceptions = new List<string>(exceptionsArray);
     
        //Break the input text into a list of capitalized (not upper case) words
        text = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(text.ToLower());
        List<string> words = new List<string>(text.Split(new char[] { ' ' }));

        //Always leave the first word capitalized, regardless of what it is
        text = words[0];
        words.RemoveAt(0);
       
        //Check each remaining word against the list, and append it to the new text
        foreach (string s in words)
        {
            if (exceptions.Contains(s.ToLower()))
               text += " " + s.ToLower();   
            else
               text += " " + s;
        }

        return text;
    }
}

I thought I'd like to translate it to MS & add it to a button.

I can grab & split a filename, I can see how I could use the str selection to alter the words I want in lower case to lower case ... but I'm wondering if I need something like a regex version of
Code: [Select]
<str> StrReplace(<str> input, <str> find, <str> with );
Maybe I just haven't figured out the ordering of commands to modify the arrays yet but I'd really like something that would give me a [a-z] -> [A-Z] function :P

Any advice Mathias?

AlanJB

  • Power Member
  • ****
  • Posts: 287
  • VERY old Programmer
    • View Profile
Re: Title Case
« Reply #1 on: July 06, 2018, 00:27:19 »
Hi Ulf.

Can you not use combinations of StrToUpper() and StrSub()?

Mathias (Author)

  • Administrator
  • Elite Member
  • *****
  • Posts: 3459
    • View Profile
    • Multi Commander
Re: Title Case
« Reply #2 on: July 06, 2018, 07:56:30 »
I think it should be possible

Would be very similar I think..
Except I do not know what ToTitleCase(..) does ?  You have to recreate that in script I think.
But should not be to hard. String manipulation is supported.. 
And as Alan say.. StrToUpper and StrSub would be something to use..

If you try to write something, then leave a post if you get stuck I might be able to help out


Ulfhednar

  • Contributor
  • Elite Member
  • *****
  • Posts: 439
    • View Profile
Re: Title Case
« Reply #3 on: July 06, 2018, 13:34:17 »
Thanks for the replies.  :)

I am using StrToUpper and StrSub .  The trouble probably is my finding the right approach.

This was a way I'd looked at word capitalization, but a regex gives me all the instances quicker.
Code: [Select]
...
@var $arrN = StrSplit( $NameA, " ");
@var $Words = $arrN[1];
@var $Char1 = StrSub($Words, 0, 1);
@var $arrN1 = StrToUpper($Char1);
...

Via regex I can have the number of instances output, hence my search for a regex replace function.
Using StrRegExpFind & a simple \s[a-z] gives me all the lower case words, I should in theory be able to take each instance ($1 $2 etc) & handle it with the StrToUpper - but that doesn't seem to be possible (tho it may be just me not getting the <str> &/or <arr> code right!) so I wondered if there might be a StrRegExpReplace function... 
Can I pass the instances found by StrRegExpFind to the StrToUpper  function?  :-\ 

The exception list should be straight forward enough - I can just run them one by one, would be nice if I could pass the exception array as in the C# above tho!   The C# seems to require a lot less steps to achieve the result.

My plan was
  • acquire the selected file name(s)
  • select the words ignoring 1st word
  • all words to lower case
  • capitalize all words
  • find words in the exception list & make them lower case
  • write the new title case string to the filename.

I don't know if I'm misunderstanding you Mathias ref  - ToTitleCase - could just be how the author has labelled the process the code invokes & displays on the GUI as opposed to a specific C# function....?

The idea was to take a title eg
ANT-MAN AND THE WASP  | ant-man and the wasp | Ant-Man And The Wasp
& convert it to Title Case = Ant-Man and the Wasp
(Altho I think in this case it may need to be Ant-Man and The Wasp...  ::) :P)

This process obviously applies to many titles where simply using Camel-Case doesn't look pretty/over-emphasizes secondary prepositions etc.
I liked the idea so thought it might be fun (!) to try to recall how to script with MS   ::)  ;D


Mathias (Author)

  • Administrator
  • Elite Member
  • *****
  • Posts: 3459
    • View Profile
    • Multi Commander
Re: Title Case
« Reply #4 on: July 06, 2018, 14:47:54 »
Here is a function in MultiScript that does TitleCase. kind of..
Code: [Select]
@var $exceptionsArray[] = { "a", "an", "and", "any", "at", "from", "into", "of", "on", "or", "the", "to", };

function TitleCase($name)
{
   return  _TitleCase($name, " ");
}

function _TitleCase($name , $splitchar)
{

  @var $result = "";
  @var $parts = StrSplit($name , $splitchar); // space and - will split string
 
  @var $cnt = arrayCount( $parts );
  for( $n = 0; $n < $cnt ; $n++ )
  {
    @var $textPart = $parts[ $n ];
    // To Lower
    $textPart = StrToLower( $textPart );
 
    if( StrFind( $textPart , "-", 0 ) > 0)
    {
      // Becuse of recursive bug, $n is is overwriten
      $oldN = $n;
      $textPart = _TitleCase($textPart , "-");
      $n = $oldN;
    }

    if( arrayFind( $exceptionsArray, $textPart ) == -1)
    {
    // Uppser case on first
    $textPart[0] = StrToUpper( $textPart[0] );
    }

    if( StrLen( $result ) > 0 )
$result += $splitchar;

    $result += $textPart;
  }
  return $result;
}
@var $newText = TitleCase("ANT-MAN AND THE WASP");

Hmm Found a bug with calling recusrive ( same function calling it self.)  variables are overwwitten.. so there is a workaround in the code for that..




Ulfhednar

  • Contributor
  • Elite Member
  • *****
  • Posts: 439
    • View Profile
Re: Title Case
« Reply #5 on: July 06, 2018, 18:31:42 »
Thanks very much Mathias.  ;D  8)
I didn't realize I could use this array form in MS -
Code: [Select]
@var $exceptionsArray[] = { "a", "an", "and", "any", "at", "from", "into", "of", "on", "or", "the", "to", };
The function you have provided is very helpful in making me see the break-down of events & how MS can be used to run different tasks.  I will have to study/learn your style. 

Also I think I may have under-estimated MS & that that combined with my inexperience with ('modern') programming, causes trouble.
I have been looking at Java & C++ so I recognize these structures of code - just not well enough...! 
Better go & read those books I bought I guess ;)

OT Is it possible to create a StrRegExpReplace function for MS?  Or better to combine functions that are already there? 
I liked the idea of using StrRegExpFind to enumerate $<instance> & StrRegExpReplace to step through & replace each $<instance>.  Maybe that couldn't work in practice tho?

Mathias (Author)

  • Administrator
  • Elite Member
  • *****
  • Posts: 3459
    • View Profile
    • Multi Commander
Re: Title Case
« Reply #6 on: July 06, 2018, 21:27:33 »

OT Is it possible to create a StrRegExpReplace function for MS?  Or better to combine functions that are already there? 
I liked the idea of using StrRegExpFind to enumerate $<instance> & StrRegExpReplace to step through & replace each $<instance>.  Maybe that couldn't work in practice tho?

It depends on what the bulit in regex engine support. RegEx is very got at complicating things to much too.  Maybe

Ulfhednar

  • Contributor
  • Elite Member
  • *****
  • Posts: 439
    • View Profile
Re: Title Case
« Reply #7 on: July 07, 2018, 16:08:20 »
Thanks for the advice & info Mathias.
This is how I employed your function & it works well. I can see that it will be straightforward to expand on this for a number of other operations so I might actually learn how to use MS properly one day  :P ;)  It has (again) impressed on me that it is quite different from my school experience of Basic, this system feels like it contains a lot of macros in comparison.

Code: [Select]
@var $exceptionsArray[] = { "a", "an", "and", "any", "at", "for", "from", "into", "of", "on", "or", "the", "to", };

function TitleCase($name)
{
   return  _TitleCase($name, " ");
}

function _TitleCase($name , $splitchar)
{

  @var $result = "";
  @var $parts = StrSplit($name , $splitchar); // space and - will split string
 
  @var $cnt = arrayCount( $parts );
  for( $n = 0; $n < $cnt ; $n++ )
  {
    @var $textPart = $parts[ $n ];
    // To Lower
    $textPart = StrToLower( $textPart );
 
    if( StrFind( $textPart , "-", 0 ) > 0)
    {
      // Becuse of recursive bug, $n is is overwriten
      $oldN = $n;
      $textPart = _TitleCase($textPart , "-");
      $n = $oldN;
    }

    if( arrayFind( $exceptionsArray, $textPart ) == -1)
    {
    // Uppser case on first
    $textPart[0] = StrToUpper( $textPart[0] );
    }

    if( StrLen( $result ) > 0 )
$result += $splitchar;

    $result += $textPart;
  }
  return $result;
}

 
@var $arr = GetSourceSelectedPaths();
@var $items = arrayCount($arr);
@var $NameA = PathGetNamePart( $arr );
@var $newText = TitleCase($NameA);
@var $i = 0;


for( $i = 0; $i < $items; $i++ )


{
RenameFile( $arr, $newText, "RENAME_RO" );
}


EDIT
If I select multiple files it only runs on the first file... is this the recurse bug or is my recurse instruction bad... thought I had that one OK  :-\ ???
« Last Edit: July 07, 2018, 17:46:17 by Ulfhednar »

Mathias (Author)

  • Administrator
  • Elite Member
  • *****
  • Posts: 3459
    • View Profile
    • Multi Commander
Re: Title Case
« Reply #8 on: July 07, 2018, 17:21:50 »
Code: [Select]

@var $arr = GetSourceSelectedPaths();
@var $NameA = PathGetNamePart( $arr );
@var $newText = TitleCase($NameA);
@var $i = 0;

 for ( $i = 0; $i < arrayCount( $arr ); $i++ )

{
RenameFile( $arr, $newText, "RENAME_RO" );
}

Ehh what are you doing ?? that can't work
$arr is a list of files.  and a single file..
and then you take all the items in the array and rename everything to the same name  ?
Hm No not every item, you send RenameFile the complete array if path. not a specific item in the list

« Last Edit: July 07, 2018, 17:23:30 by Mathias (Author) »

Ulfhednar

  • Contributor
  • Elite Member
  • *****
  • Posts: 439
    • View Profile
Re: Title Case
« Reply #9 on: July 07, 2018, 17:51:57 »
OK I'm incorrectly thinking that because
Code: [Select]
for( $n = 0; $n < $items; $n++ )works for multiple files - it will call the same thing ($arr) in 2 different ways --- which it won't  :o

I need to differentiate...  Thank you Mathias, I will try again & stop destroying your weekend now !   :D

Mathias (Author)

  • Administrator
  • Elite Member
  • *****
  • Posts: 3459
    • View Profile
    • Multi Commander
Re: Title Case
« Reply #10 on: July 07, 2018, 18:19:07 »
OK I'm incorrectly thinking that because
Code: [Select]
for( $n = 0; $n < $items; $n++ )works for multiple files - it will call the same thing ($arr) in 2 different ways --- which it won't  :o

I need to differentiate...  Thank you Mathias, I will try again & stop destroying your weekend now !   :D

Yhaa.  But then $n is used someway..  What is $n ?  and what is  $arr
Sorry,. I don't understand your reasoning how that should work, it make no logical sense :)

$arr is an array (list) of text strings.  there are many text strings in that list.. and when you convert one of the text in the list you need to grab the item you want from the list.
For example "@var $NameA = PathGetNamePart( $arr )"  you send a list of many text string (that are paths) to a function that return a new text. not a list of text.. a single text.
So, there is no logic in sending an entire list of items to that function.. you need to send the specific item you want from the list into the function




Ulfhednar

  • Contributor
  • Elite Member
  • *****
  • Posts: 439
    • View Profile
Re: Title Case
« Reply #11 on: July 08, 2018, 14:59:16 »

Sorry,. I don't understand your reasoning how that should work, it make no logical sense :)
I know!  :D

Thanks to your input, I realized I hadn't assigned iterations & needed more references for the arrays & got it to work - I am still finding it hard to balance how smart code can appear with how dumb the machine really is  :P

Code: [Select]
@var $exceptionsArray[] = { "a", "as", "an", "and", "any", "at", "for", "from", "into", "is", "of", "on", "or", "the", "to", };
@var $n;
@var $oldN;

function TitleCase($name)
{
   return  _TitleCase($name, " ");
}

function _TitleCase($name , $splitchar)
{

  @var $result = "";
  @var $parts = StrSplit($name , $splitchar); // space and - will split string
 
  @var $cnt = arrayCount( $parts );
  for( $n = 0; $n < $cnt ; $n++ )
  {
    @var $textPart = $parts[ $n ];
    // To Lower
    $textPart = StrToLower( $textPart );
 
    if( StrFind( $textPart , "-", 0 ) > 0)
    {
      // Becuse of recursive bug, $n is is overwriten
      $oldN = $n;
      $textPart = _TitleCase($textPart , "-");
      $n = $oldN;
    }

    if( arrayFind( $exceptionsArray, $textPart ) == -1)
    {
    // Uppser case on first
    $textPart[0] = StrToUpper( $textPart[0] );
    }

    if( StrLen( $result ) > 0 )
$result += $splitchar;

    $result += $textPart;
  }
  return $result;
}
 

@var $arr1 = GetSourceSelectedPaths();
@var $items = arrayCount($arr1);
@var $CurrentNameFullPath;
@var $OrgName;
@var $NewName;
@var $n1;


for( $n1 = 0; $n1 < $items; $n1++ )
{
 
@var $arr = GetSourceSelectedPaths();
@var $NameA = PathGetNamePart( $arr[$n1] );
@var $newText = TitleCase($NameA);



  $CurrentNameFullPath = $arr1[ $n1 ];
  $OrgName = PathGetNamePart( $CurrentNameFullPath );
  $NewName = StrReplace( $OrgName, $NameA, $newText );
 
RenameFile( $CurrentNameFullPath, $NewName, "RENAME_RO" );
}

I obviously haven't made it as clean as it might be, but it is a start. 
Think I have abused the { } .  ::)

I am now wondering about capitalizing the first word where the first word is in the exceptions list e.g.
For MultiScript coding disasters this is the place
becomes
for Multiscript Coding Disasters This is the Place

I may need to plagiarize some of that function you created...  ;)

UPDATE
Added this
Code: [Select]
@var $char1 = StrSub($NewName, 0, 1);
@var $char2 = StrToUpper( $char1 );
@var $NameB = StrReplace( $NewName, $char1, $char2 );
 
RenameFile( $CurrentNameFullPath, $NameB, "RENAME_RO" );

so now the emergency is over, I can go to sleep :D :P



........I also wondered about the recursive bug $n/$oldN is that something that only manifests in this type of function?
« Last Edit: July 08, 2018, 15:50:00 by Ulfhednar »

Mathias (Author)

  • Administrator
  • Elite Member
  • *****
  • Posts: 3459
    • View Profile
    • Multi Commander
Re: Title Case
« Reply #12 on: July 08, 2018, 21:27:37 »
If you look at my code.. it will make everything lowercase first.. then when it handled everyword it uppcase the first letter with

Code: [Select]
$textPart[0] = StrToUpper( $textPart[0] );This will take the first character if textPart and insert it into the first postion in textPart

You can access individual characters using the [.], think of the string and an array (list) of characters

$textPart[0] = $textPart[1]; 
This will take the seconds characters and overwrite the first character with that. so the first two characters are now the same

........I also wondered about the recursive bug $n/$oldN is that something that only manifests in this type of function?

It is when you have a functions that is calling it self. The problem is that all the local variables are not unique then. so it overwrite when it should not.
That trick $n to the old state it had before the function was called because when it called it self it changed the value of that variable.


Ulfhednar

  • Contributor
  • Elite Member
  • *****
  • Posts: 439
    • View Profile
Re: Title Case
« Reply #13 on: July 08, 2018, 22:30:57 »
Thanks Mathias.  I appreciate the help. :)

My solution was more verbose.  My primary focus was to get a working version.  Now I can use this as a reference whilst I am playing about trying to tweak & tidy my code.
I had looked at the
Code: [Select]
$textPart[0] = StrToUpper( $textPart[0] );entry & was going to try it, but decided that I would probably create a conflict/problem.    ::)
So I went with what I knew would work with this task as a logical progression/last check on the first word case status. :P
I'd also wondered about adding a line equating to something like "ignore exceptions array if word starts with/at character 0" within your function.

I intend to come back to your function code as I need to understand how you have used scope & therefore how to use that $textPart[0] to check first word capitalization as the last operation before generating $NewText..

I think I understand about $n, that is interesting & raises more questions for me. I'm glad you have shown me that this can happen or I am sure I would have been driven crazy had I accidentally discovered it alone :)   

Ulfhednar

  • Contributor
  • Elite Member
  • *****
  • Posts: 439
    • View Profile
Re: Title Case
« Reply #14 on: July 09, 2018, 22:07:04 »
I managed to plagiarize that piece  of code Mathias, I hadn't been sure how/where to insert it but I figured it out :P

Code: [Select]
@var $arr = GetSourceSelectedPaths();
@var $NameA = PathGetNamePart( $arr );
@var $newText = TitleCase($NameA);
@var $NameB = $newText[0] = StrToUpper( $newText[0] );

{
RenameFile( $arr, $newText, "RENAME_RO" );
}

Thanks again. ;)

BTW do you use any specific syntax coloring to help when when coding with MS?  I find it helps me if I can use colors when I'm trying something.  ATM I am using notepad++.  Any recommendations for coloring?   (It's probably a big job but maybe you can add syntax coloring to the MS Debugger some time....?)
« Last Edit: July 09, 2018, 22:13:56 by Ulfhednar »