Jump to content

Camel case and snake case

From Rosetta Code
Task
Camel case and snake case
You are encouraged to solve this task according to the task description, using any language you may know.

Two common conventions for naming of computer program variables are Snake Case and Camel Case.

Snake case variables are generally all lower case, with an underscore between words in the variable, as in snake_case_variable'. Camel case variables are generally lower case first (except in some Pascal conventions or with class names in many other languages), with captalization of the initial letter of the words within the variable, as in 'camelCaseVariable'.

Leading underscores are not used in such variables except as part of a different naming convention, usually for special internal or system variables. White space is not permitted as part of camel case or snake case variable names.

Task
  • Write two functions, one to change snake case to camel case and one to change camel case to snake case. If possible, generalize the function enough to apply to strings containing spaces between words or a `-` dash between words, assuming that in those cases a space or hyphen is a also a separator character, like `_`, for the purpose of creating a new variable name. Leading or trailing whitespace may be ignored.
  • Show the results on changing to both snake case and camel case for each of the following strings:
"snakeCase", "snake_case", "variable_10_case", "variable10Case", "ɛrgo rE tHis",
"hurry-up-joe!", "c://my-docs/happy_Flag-Day/12.doc", "  spaces  "
Related tasks
Translation of: Python
F snakeToCamelCase(nam, sep = ‘[_]+’, lcmiddle = 0B)
   ‘ convert snake '_' separator case to camel case ’
   I nam == ‘’
      R nam
   V words = nam.trim(‘ ’).split(re:(sep))
   I lcmiddle
      words = words.map(w -> w.lowercase())
   words = [words[0]] [+] words[1..].filter(w -> w.len > 0).map(w -> w[0].uppercase()‘’w[1..])
   R words.join(‘’)

[(String, (String -> String))] funcs
funcs [+]= (‘snakeToCamelCase’, nam -> snakeToCamelCase(nam))
funcs [+]= (‘spaceToCamelCase’, nam -> snakeToCamelCase(nam, sep' ‘\s+’))
funcs [+]= (‘kebabToCamelCase’, nam -> snakeToCamelCase(nam, sep' ‘[\-]+’))
funcs [+]= (‘periodToCamelCase’, nam -> snakeToCamelCase(nam, sep' ‘[\.]+’))
funcs [+]= (‘allsepToCamelCase’, nam -> snakeToCamelCase(nam, sep' ‘[ \-_\.]+’))
funcs [+]= (‘lowermiddle_allsepToCamelCase’, nam -> snakeToCamelCase(nam, sep' ‘[ \-_\.]+’, lcmiddle' 1B))

F camel_to_snake_case(=nam, allsep = ‘[_]+’, sep = ‘_’, lcmiddle = 1B)
   ‘ convert camel case to snake case (separate with '_') ’
   nam = nam.trim((‘ ’, "\t", "\r", "\n")).replace(re:‘([A-Z]+)’, sep‘$1’)
   V sep1 = I sep == ‘.’ {‘\’sep} E sep
   I lcmiddle
      nam = (nam.split(sep1).filter(w -> w.len > 0).map(w -> w.lowercase())).join(sep)
   E
      nam = (nam.split(sep1).filter(w -> w.len > 0).map(w -> w[0].lowercase()‘’w[1..])).join(sep)
   R nam.replace(re:(allsep), sep)

funcs [+]= (‘camel_to_snake_case’, nam -> camel_to_snake_case(nam))
funcs [+]= (‘preserve_midcaps_camel_to_snake_case’, nam -> camel_to_snake_case(nam, lcmiddle' 0B))
funcs [+]= (‘allsep_to_snake_case’, nam -> camel_to_snake_case(nam, allsep' ‘[ \-\._]+’))
funcs [+]= (‘allsep_to_kebab_case’, nam -> camel_to_snake_case(nam, allsep' ‘[ \-\._]+’, sep' ‘-’))
funcs [+]= (‘allsep_to_space_case’, nam -> camel_to_snake_case(nam, allsep' ‘[ \-\._]+’, sep' ‘ ’))
funcs [+]= (‘allsep_to_period_case’, nam -> camel_to_snake_case(nam, allsep' ‘[ \-\._]+’, sep' ‘.’))
funcs [+]= (‘allsep_to_slash_case’, nam -> camel_to_snake_case(nam, allsep' ‘[ \-\._]+’, sep' ‘/’))

L(f_name, f) funcs
   print(‘Testing function ’f_name‘:’)
   L(teststring) [
      ‘snakeCase’,
      ‘snake_case’,
      ‘snake-case’,
      ‘snake case’,
      ‘snake CASE’,
      ‘snake.case’,
      ‘variable_10_case’,
      ‘variable10Case’,
      ‘ergo rE tHis’,
      ‘hurry-up-joe!’,
      ‘c://my-docs/happy_Flag-Day/12.doc’,
      ‘ spaces ’]
      print(teststring.rjust(36)‘  =>  ’f(teststring))
   print()
Output:
Testing function snakeToCamelCase:
                           snakeCase  =>  snakeCase
                          snake_case  =>  snakeCase
                          snake-case  =>  snake-case
                          snake case  =>  snake case
                          snake CASE  =>  snake CASE
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable10Case
                      variable10Case  =>  variable10Case
                        ergo rE tHis  =>  ergo rE tHis
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happyFlag-Day/12.doc
                             spaces   =>  spaces

Testing function spaceToCamelCase:
                           snakeCase  =>  snakeCase
                          snake_case  =>  snake_case
                          snake-case  =>  snake-case
                          snake case  =>  snakeCase
                          snake CASE  =>  snakeCASE
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10Case
                        ergo rE tHis  =>  ergoRETHis
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy_Flag-Day/12.doc
                             spaces   =>  spaces

Testing function kebabToCamelCase:
                           snakeCase  =>  snakeCase
                          snake_case  =>  snake_case
                          snake-case  =>  snakeCase
                          snake case  =>  snake case
                          snake CASE  =>  snake CASE
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10Case
                        ergo rE tHis  =>  ergo rE tHis
                       hurry-up-joe!  =>  hurryUpJoe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://myDocs/happy_FlagDay/12.doc
                             spaces   =>  spaces

Testing function periodToCamelCase:
                           snakeCase  =>  snakeCase
                          snake_case  =>  snake_case
                          snake-case  =>  snake-case
                          snake case  =>  snake case
                          snake CASE  =>  snake CASE
                          snake.case  =>  snakeCase
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10Case
                        ergo rE tHis  =>  ergo rE tHis
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy_Flag-Day/12Doc
                             spaces   =>  spaces

Testing function allsepToCamelCase:
                           snakeCase  =>  snakeCase
                          snake_case  =>  snakeCase
                          snake-case  =>  snakeCase
                          snake case  =>  snakeCase
                          snake CASE  =>  snakeCASE
                          snake.case  =>  snakeCase
                    variable_10_case  =>  variable10Case
                      variable10Case  =>  variable10Case
                        ergo rE tHis  =>  ergoRETHis
                       hurry-up-joe!  =>  hurryUpJoe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://myDocs/happyFlagDay/12Doc
                             spaces   =>  spaces

Testing function lowermiddle_allsepToCamelCase:
                           snakeCase  =>  snakecase
                          snake_case  =>  snakeCase
                          snake-case  =>  snakeCase
                          snake case  =>  snakeCase
                          snake CASE  =>  snakeCase
                          snake.case  =>  snakeCase
                    variable_10_case  =>  variable10Case
                      variable10Case  =>  variable10case
                        ergo rE tHis  =>  ergoReThis
                       hurry-up-joe!  =>  hurryUpJoe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://myDocs/happyFlagDay/12Doc
                             spaces   =>  spaces

Testing function camel_to_snake_case:
                           snakeCase  =>  snake_case
                          snake_case  =>  snake_case
                          snake-case  =>  snake-case
                          snake case  =>  snake case
                          snake CASE  =>  snake _case
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10_case
                        ergo rE tHis  =>  ergo r_e t_his
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy_flag-_day/12.doc
                             spaces   =>  spaces

Testing function preserve_midcaps_camel_to_snake_case:
                           snakeCase  =>  snake_case
                          snake_case  =>  snake_case
                          snake-case  =>  snake-case
                          snake case  =>  snake case
                          snake CASE  =>  snake _cASE
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10_case
                        ergo rE tHis  =>  ergo r_e t_his
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy_flag-_day/12.doc
                             spaces   =>  spaces

Testing function allsep_to_snake_case:
                           snakeCase  =>  snake_case
                          snake_case  =>  snake_case
                          snake-case  =>  snake_case
                          snake case  =>  snake_case
                          snake CASE  =>  snake_case
                          snake.case  =>  snake_case
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10_case
                        ergo rE tHis  =>  ergo_r_e_t_his
                       hurry-up-joe!  =>  hurry_up_joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my_docs/happy_flag_day/12_doc
                             spaces   =>  spaces

Testing function allsep_to_kebab_case:
                           snakeCase  =>  snake-case
                          snake_case  =>  snake-case
                          snake-case  =>  snake-case
                          snake case  =>  snake-case
                          snake CASE  =>  snake-case
                          snake.case  =>  snake-case
                    variable_10_case  =>  variable-10-case
                      variable10Case  =>  variable10-case
                        ergo rE tHis  =>  ergo-r-e-t-his
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy-flag-day/12-doc
                             spaces   =>  spaces

Testing function allsep_to_space_case:
                           snakeCase  =>  snake case
                          snake_case  =>  snake case
                          snake-case  =>  snake case
                          snake case  =>  snake case
                          snake CASE  =>  snake case
                          snake.case  =>  snake case
                    variable_10_case  =>  variable 10 case
                      variable10Case  =>  variable10 case
                        ergo rE tHis  =>  ergo r e t his
                       hurry-up-joe!  =>  hurry up joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my docs/happy flag day/12 doc
                             spaces   =>  spaces

Testing function allsep_to_period_case:
                           snakeCase  =>  snake.case
                          snake_case  =>  snake.case
                          snake-case  =>  snake.case
                          snake case  =>  snake.case
                          snake CASE  =>  snake.case
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable.10.case
                      variable10Case  =>  variable10.case
                        ergo rE tHis  =>  ergo.r.e.t.his
                       hurry-up-joe!  =>  hurry.up.joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my.docs/happy.flag.day/12.doc
                             spaces   =>  spaces

Testing function allsep_to_slash_case:
                           snakeCase  =>  snake/case
                          snake_case  =>  snake/case
                          snake-case  =>  snake/case
                          snake case  =>  snake/case
                          snake CASE  =>  snake//case
                          snake.case  =>  snake/case
                    variable_10_case  =>  variable/10/case
                      variable10Case  =>  variable10/case
                        ergo rE tHis  =>  ergo/r/e/t/his
                       hurry-up-joe!  =>  hurry/up/joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c:/my/docs/happy//flag//day/12/doc
                             spaces   =>  spaces

with Ada.Characters.Handling,
     Ada.Strings,
     Ada.Strings.Fixed,
     Ada.Strings.Maps,
     Ada.Strings.Maps.Constants,
     Ada.Text_IO;

use Ada.Characters.Handling,
    Ada.Strings,
    Ada.Strings.Fixed,
    Ada.Strings.Maps,
    Ada.Strings.Maps.Constants;

procedure Camel_Snake_Case is
   type Sample_Array is array (Positive range <>) of access constant String;
   --  Work around for array elements needing to be the same size.
   --  Could also use Ada.Strings.Bounded_Strings instead.
   S1 : aliased constant String := "snakeCase";
   S2 : aliased constant String := "snake_case";
   S3 : aliased constant String := "variable_10_case";
   S4 : aliased constant String := "variable10Case";
   S5 : aliased constant String := "ɛrgo rE tHis";
   S6 : aliased constant String := "hurry-up-joe!";
   S7 : aliased constant String := "c://my-docs/happy_Flag-Day/12.doc";
   S8 : aliased constant String := "  spaces  ";

   Samples : constant Sample_Array :=
     (
       S1'Access,
       S2'Access,
       S3'Access,
       S4'Access,
       S5'Access,
       S6'Access,
       S7'Access,
       S8'Access
     );

   function Should_Insert (This, Last : Character) return Boolean is
     (
      (Is_In (Last, Lower_Set) and then
       Is_In (This, Upper_Set or Decimal_Digit_Set))
      or else
      (Is_In (Last, Upper_Set) and then
       Is_In (This, Decimal_Digit_Set))
      or else
      (Is_In (Last, Decimal_Digit_Set) and then
       Is_In (This, Upper_Set))
     );

   function To_Snake_Case (S : String) return String is
      Trimmed : constant String := Trim (S, Both);
      Separator_Map : constant Character_Mapping := To_Mapping (" -", "__");
      Translated : constant String := Translate (Trimmed, Separator_Map);
      New_Word_Set : constant Character_Set := Upper_Set or Decimal_Digit_Set;
      New_Word_Chars : constant Natural := Count (Translated, New_Word_Set);
      Snake : String (1 .. Translated'Length + New_Word_Chars);
      J : Positive := 2;
      L : Character;
   begin
      Snake (1 .. Translated'Length) := Translated;

      for I in 2 .. Translated'Last loop
         if Should_Insert (Translated (I), Translated (I - 1)) then
            Snake (J) := '_';
            J := J + 1;
         end if;

         L := Translated (I);

         if Is_In (Translated (I), Upper_Set) then
            L := To_Lower (L);
         end if;

         Snake (J) := L;
         J := J + 1;
      end loop;

      return Snake (1 .. J - 1);
   end To_Snake_Case;

   function To_Camel_Case (S : String) return String is
      Trimmed : constant String := Trim (S, Both);
      Separators : constant Character_Set := To_Set (" -_");
      Snake : String (Trimmed'Range) := Trimmed;
      J : Positive := 2;
   begin
      for I in 2 .. Trimmed'Length loop
         if not Is_In (Trimmed (I), Separators) then
            if Is_In (Trimmed (I - 1), Separators) and then
               Is_In (Trimmed (I), Lower_Set) then
               Snake (J) := To_Upper (Trimmed (I));
            else
               Snake (J) := Trimmed (I);
            end if;

            J := J + 1;
         end if;
      end loop;

      return Snake (1 .. J - 1);
   end To_Camel_Case;

begin
   Ada.Text_IO.Put_Line ("=Snake Case=");
   for I of Samples loop
      Ada.Text_IO.Put_Line (I.all & " => " & To_Snake_Case (I.all));
   end loop;

   Ada.Text_IO.Put_Line ("=Camel Case=");
   for I of Samples loop
      Ada.Text_IO.Put_Line (I.all & " => " & To_Camel_Case (I.all));
   end loop;
end Camel_Snake_Case;
Output:
=Snake Case=
snakeCase => snake_case
snake_case => snake_case
variable_10_case => variable_10_case
variable10Case => variable_10_case
ɛrgo rE tHis => ɛrgo_r_e_t_his
hurry-up-joe! => hurry_up_joe!
c://my-docs/happy_Flag-Day/12.doc => c://my_docs/happy_flag_day/12.doc
  spaces   => spaces
=Camel Case=
snakeCase => snakeCase
snake_case => snakeCase
variable_10_case => variable10Case
variable10Case => variable10Case
ɛrgo rE tHis => ɛrgoRETHis
hurry-up-joe! => hurryUpJoe!
c://my-docs/happy_Flag-Day/12.doc => c://myDocs/happyFlagDay/12.doc
  spaces   => spaces

Treating space, - and _ as equivalent "break" characters (as in most of the other samples) and adding kebab case (as in the Raku sample) and resisting the urge to add "space case" for languages like Algol 68 where (insignificant) spaces can appear in identifiers...

BEGIN # convert camel case to and from snake case #
    # returns c converted to uppercase if it is lowercase, c otherwise #
    OP   TOUPPER = ( CHAR c )STRING:
         IF c >= "a" AND c <= "z" THEN REPR( ( ABS c - ABS "a" ) + ABS "A" ) ELSE c FI;
    # returns c converted to lowercase if it is uppercase, c otherwise #
    OP   TOLOWER = ( CHAR c )STRING:
         IF c >= "A" AND c <= "Z" THEN REPR( ( ABS c - ABS "A" ) + ABS "a" ) ELSE c FI;
    # returns the camel case identifier c in snake case #
    OP   CAMELTOSNAKE = ( STRING c )STRING: c CAMELTOBREAK "_";
    # returns the camel case identifier c in kebab case #
    OP   CAMELTOKEBAB = ( STRING c )STRING: c CAMELTOBREAK "-";
    # returns TRUE if c is a "break" character ( " ", "-" or "_" ), FALSE otherwise #
    OP   ISBREAK = ( CHAR c )BOOL: c = " " OR c = "-" OR c = "_";
    # returns the indentifier id (which is assumed to be in Camel case) #
    #         converted to snake or kebab case depending on break char #
    PRIO CAMELTOBREAK = 9; # CAMELTOBREAK is dyadic so need a priority #
    OP   CAMELTOBREAK = ( STRING id, CHAR break char )STRING:
         BEGIN
            STRING result := "";
            STRING orig    = TRIM id; # remove leading and trailing spaces #
            BOOL   first  := TRUE;
            INT    c pos  := LWB orig;
            WHILE c pos <= UPB orig DO
                CHAR c = orig[ c pos ];
                IF c >= "A" AND c <= "Z" THEN
                    # have an uppercase letter #
                    IF NOT first THEN result +:= break char FI;
                    result +:= TOLOWER c
                ELIF ISBREAK c THEN
                    # replace one or more spaces and break characters by a single break #
                    BOOL have break := TRUE;
                    WHILE c pos <= UPB orig AND have break DO
                        IF have break := ISBREAK orig[ c pos ] THEN c pos +:= 1 FI
                    OD;
                    IF c pos <= UPB orig THEN
                        # the identifier didn't end wih a break #
                        result +:= break char + TOLOWER orig[ c pos ]
                    FI
                ELSE
                    # lowercase or punctuation #
                    result +:= c
                FI;
                first  := FALSE;
                c pos +:= 1
            OD;
            result
         END # CAMELTOBREAK # ;
    # returns the identifier id ( which is assumed to be in snake/kebab/space case ) #
    #         converted to Camel case #
    OP   TOCAMEL = ( STRING id )STRING:
         BEGIN
            STRING result := "";
            STRING orig    = TRIM id; # remove leading and trailing spaces #
            INT    c pos  := LWB orig;
            WHILE  c pos <= UPB orig DO
                CHAR c = orig[ c pos ];
                IF c >= "A" AND c <= "Z" THEN
                    # uppercase letter - leave as is #
                    result +:= c
                ELIF NOT ISBREAK c THEN
                    # not a break - convert to lower case if necessary and move to the next #
                    result +:= TOLOWER c
                ELSE
                    # have a separator - skip all subsequent separators and upcase the follower #
                    BOOL have break := TRUE;
                    WHILE c pos <= UPB orig AND have break DO
                        IF have break := ISBREAK orig[ c pos ] THEN c pos +:= 1 FI
                    OD;
                    IF c pos <= UPB orig THEN
                        # the identifier didn't end with a break character #
                        result +:= TOUPPER orig[ c pos ]
                    FI
                FI;
                c pos +:= 1
            OD;
            result
         END # TOCAMEL # ;
    # returns s left-padded to len characters or s if s is already that long #
    PRIO PAD = 9;
    OP   PAD = ( INT len, STRING s )STRING:
         IF    INT s len = ( UPB s - LWB s ) + 1;
               s len >= len
         THEN s
         ELSE
             STRING result := s;
             FROM s len + 1 TO len DO " " +=: result OD;
             result
         FI # PAD # ;
    # returns s with leading and trailing spaces removed #
    OP   TRIM = ( STRING s )STRING:
         BEGIN
             INT left  := LWB s;
             INT right := UPB s;
             WHILE IF left  > right THEN FALSE ELSE s[ left  ] = " " FI DO left  +:= 1 OD;
             WHILE IF right < left  THEN FALSE ELSE s[ right ] = " " FI DO right -:= 1 OD;
             s[ left : right ]
         END # TRIM # ;
    # task test cases #
    []STRING identifier = ( "snakeCase", "snake_case", "variable_10_case", "variable10Case", "ɛrgo rE tHis"
                          , "hurry-up-joe!", "c://my-docs/happy_Flag-Day/12.doc", "  spaces  "
                          );
    print( ( "to snake case:", newline ) );
    FOR i FROM LWB identifier TO UPB identifier DO
        print( ( 40 PAD identifier[ i ], " -> ", CAMELTOSNAKE identifier[ i ], newline ) )
    OD;
    print( ( "to Camel case:", newline ) );
    FOR i FROM LWB identifier TO UPB identifier DO
        print( ( 40 PAD identifier[ i ], " -> ",      TOCAMEL identifier[ i ], newline ) )
    OD;
    print( ( "to kebab case:", newline ) );
    FOR i FROM LWB identifier TO UPB identifier DO
        print( ( 40 PAD identifier[ i ], " -> ", CAMELTOKEBAB identifier[ i ], newline ) )
    OD
END
Output:
to snake case:
                               snakeCase -> snake_case
                              snake_case -> snake_case
                        variable_10_case -> variable_10_case
                          variable10Case -> variable10_case
                           ╔ørgo rE tHis -> ╔ørgo_r_e_t_his
                           hurry-up-joe! -> hurry_up_joe!
       c://my-docs/happy_Flag-Day/12.doc -> c://my_docs/happy_flag_day/12.doc
                                spaces   -> spaces
to Camel case:
                               snakeCase -> snakeCase
                              snake_case -> snakeCase
                        variable_10_case -> variable10Case
                          variable10Case -> variable10Case
                           ╔ørgo rE tHis -> ╔ørgoRETHis
                           hurry-up-joe! -> hurryUpJoe!
       c://my-docs/happy_Flag-Day/12.doc -> c://myDocs/happyFlagDay/12.doc
                                spaces   -> spaces
to kebab case:
                               snakeCase -> snake-case
                              snake_case -> snake-case
                        variable_10_case -> variable-10-case
                          variable10Case -> variable10-case
                           ╔ørgo rE tHis -> ╔ørgo-r-e-t-his
                           hurry-up-joe! -> hurry-up-joe!
       c://my-docs/happy_Flag-Day/12.doc -> c://my-docs/happy-flag-day/12.doc
                                spaces   -> spaces
camelToSnake: function [str][
    i: 0
    result: ""
    while [i < size str][
        ch: str\[i]
        switch upper? ch [
            'result ++ '_' ++ lower str\[i]
        ][
            'result ++ str\[i]
        ]

        inc 'i
    ]
    return result
]

snakeToCamel: function [str][
    i: 0
    result: ""
    while [i < size str][
        ch: str\[i]
        switch and? [ch='_'][(i+1) < size str] [
            'result ++ upper str\[i+1]
            inc 'i
        ][
            'result ++ str\[i]
        ]

        inc 'i
    ]
    return result
]

tests: ["snakeCase", "snake_case", "variable_10_case", "variable10Case", "ɛrgo rE tHis",
"hurry-up-joe!", "c://my-docs/happy_Flag-Day/12.doc", "  spaces  "]

loop tests 'test [
    print [pad test 35 "=> camel:" snakeToCamel test "snake:" camelToSnake test]
]
Output:
                          snakeCase => camel: snakeCase snake: snake_case 
                         snake_case => camel: snakeCase snake: snake_case 
                   variable_10_case => camel: variable10Case snake: variable_10_case 
                     variable10Case => camel: variable10Case snake: variable10_case 
                       ɛrgo rE tHis => camel: ɛrgo rE tHis snake: ɛrgo r_e t_his 
                      hurry-up-joe! => camel: hurry-up-joe! snake: hurry-up-joe! 
  c://my-docs/happy_Flag-Day/12.doc => camel: c://my-docs/happyFlag-Day/12.doc snake: c://my-docs/happy__flag-_day/12.doc 
                           spaces   => camel:   spaces   snake:   spaces


Works with: C# version .NET 9
Translation of: Java
using System;
using System.Collections.Generic;
using System.Text;

public static class CamelCaseAndSnakeCase
{
    public static void Main(string[] args)
    {
        List<string> variableNames = new List<string> 
        { 
            "snakeCase", "snake_case", "variable_10_case", "variable10Case",
            "ergo rE tHis", "hurry-up-joe!", "c://my-docs/happy_Flag-Day/12.doc", "  spaces  "
        };
        
        Console.WriteLine($"{"=== To snake_case ===",48}");
        foreach (string text in variableNames)
        {
            Console.WriteLine($"{text,34} --> {ToSnakeCase(text)}");
        }

        Console.WriteLine();
        Console.WriteLine($"{"=== To camelCase ===",48}");
        foreach (string text in variableNames)
        {
            Console.WriteLine($"{text,34} --> {ToCamelCase(text)}");
        }
    }

    private static string ToSnakeCase(string aCamel)
    {
        aCamel = aCamel.Trim().Replace(SPACE, UNDERSCORE).Replace(HYPHEN, UNDERSCORE);
        StringBuilder snake = new StringBuilder();
        bool first = true;
        foreach (char ch in aCamel)
        {
            if (first)
            {
                snake.Append(ch);
                first = false;
            }
            else if (!first && char.IsUpper(ch))
            {
                if (snake.ToString().EndsWith(UNDERSCORE))
                {
                    snake.Append(char.ToLower(ch));
                }
                else
                {
                    snake.Append(UNDERSCORE + char.ToLower(ch));
                }
            }
            else
            {
                snake.Append(ch);
            }
        }
        return snake.ToString();
    }

    private static string ToCamelCase(string aSnake)
    {
        aSnake = aSnake.Trim().Replace(SPACE, UNDERSCORE).Replace(HYPHEN, UNDERSCORE);
        StringBuilder camel = new StringBuilder();
        bool underscore = false;
        foreach (char ch in aSnake)
        {
            if (ch.ToString().Equals(UNDERSCORE))
            {
                underscore = true;
            }
            else if (underscore)
            {
                camel.Append(char.ToUpper(ch));
                underscore = false;
            }
            else
            {
                camel.Append(ch);
            }
        }
        return camel.ToString();
    }

    private static readonly string SPACE = " ";
    private static readonly string UNDERSCORE = "_";
    private static readonly string HYPHEN = "-";
}
Output:
                           === To snake_case ===
                         snakeCase --> snake_case
                        snake_case --> snake_case
                  variable_10_case --> variable_10_case
                    variable10Case --> variable10_case
                      ergo rE tHis --> ergo_r_e_t_his
                     hurry-up-joe! --> hurry_up_joe!
 c://my-docs/happy_Flag-Day/12.doc --> c://my_docs/happy_flag_day/12.doc
                          spaces   --> spaces

                            === To camelCase ===
                         snakeCase --> snakeCase
                        snake_case --> snakeCase
                  variable_10_case --> variable10Case
                    variable10Case --> variable10Case
                      ergo rE tHis --> ergoRETHis
                     hurry-up-joe! --> hurryUpJoe!
 c://my-docs/happy_Flag-Day/12.doc --> c://myDocs/happyFlagDay/12.doc
                          spaces   --> spaces


The output of this example reflects the author's interpretation of the task.

#include <algorithm>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>

const char HYPHEN = '-';
const char SPACE = ' ';
const char UNDERSCORE = '_';
const std::string WHITESPACE = " \n\r\t\f\v";

std::string left_trim(const std::string& text) {
    size_t start = text.find_first_not_of(WHITESPACE);
    return ( start == std::string::npos ) ? "" : text.substr(start);
}

std::string right_trim(const std::string& text) {
    size_t end = text.find_last_not_of(WHITESPACE);
    return ( end == std::string::npos ) ? "" : text.substr(0, end + 1);
}

std::string trim(const std::string& text) {
    return left_trim(right_trim(text));
}

void prepare_for_conversion(std::string& text) {
	text = trim(text);
	std::replace(text.begin(), text.end(), SPACE, UNDERSCORE);
	std::replace(text.begin(), text.end(), HYPHEN, UNDERSCORE);
}

std::string to_snake_case(std::string& camel) {
	prepare_for_conversion(camel);
	std::string snake = "";
	bool first = true;
	for ( const char& ch : camel ) {
		if ( first ) {
			snake += ch;
			first = false;
		} else if ( ! first && ch >= 'A' && ch <= 'Z' ) {
			if ( snake[snake.length() - 1] == UNDERSCORE ) {
				snake += tolower(ch);
			} else {
				snake += UNDERSCORE;
				snake += tolower(ch);
			}
		} else {
			snake += ch;
		}
	}
	return snake;
}

std::string to_camel_case(std::string& snake) {
	prepare_for_conversion(snake);
	std::string camel = "";
	bool underscore = false;
	for ( const char& ch : snake ) {
		if ( ch == UNDERSCORE ) {
			underscore = true;
		} else if ( underscore ) {
			camel += toupper(ch);
			underscore = false;
		} else {
			camel += ch;
		}
	}
	return camel;
}

int main() {
	const std::vector<std::string> variable_names = { "snakeCase", "snake_case", "variable_10_case",
        "variable10Case", "ergo rE tHis", "hurry-up-joe!", "c://my-docs/happy_Flag-Day/12.doc", "  spaces  " };

	std::cout << std::setw(48) << "=== To snake_case ===" << std::endl;
	for ( std::string text : variable_names ) {
		std::cout << std::setw(34) << text << " --> " << to_snake_case(text) << std::endl;
	}

	std::cout << std::endl;
	std::cout << std::setw(48) << "=== To camelCase ===" << std::endl;
	for ( std::string text : variable_names ) {
		std::cout << std::setw(34) <<  text << " --> " << to_camel_case(text) << std::endl;
	}
}
Output:
                          === To snake_case ===
                         snakeCase --> snake_case
                        snake_case --> snake_case
                  variable_10_case --> variable_10_case
                    variable10Case --> variable10_case
                      ergo rE tHis --> ergo_r_e_t_his
                     hurry-up-joe! --> hurry_up_joe!
 c://my-docs/happy_Flag-Day/12.doc --> c://my_docs/happy_flag_day/12.doc
                          spaces   --> spaces

                            === To camelCase ===
                         snakeCase --> snakeCase
                        snake_case --> snakeCase
                  variable_10_case --> variable10Case
                    variable10Case --> variable10Case
                      ergo rE tHis --> ergoRETHis
                     hurry-up-joe! --> hurryUpJoe!
 c://my-docs/happy_Flag-Day/12.doc --> c://myDocs/happyFlagDay/12.doc
                          spaces   --> spaces

Crystal has this built-in, as methods of String. The only separator they consider is underscore, tho, so first we have to convert spaces and dashes to it.

["snakeCase", "snake_case", "variable_10_case", "variable10Case", "ɛrgo rE tHis",
 "hurry-up-joe!", "c://my-docs/happy_Flag-Day/12.doc", "  spaces  "].each do |ident|
  print ident, " => "
  print ident.strip.gsub(/[ -]/, "_").camelcase, ", "
  puts  ident.strip.gsub(/[ -]/, "_").underscore
end
Output:
snakeCase => SnakeCase, snake_case
snake_case => SnakeCase, snake_case
variable_10_case => Variable10Case, variable_10_case
variable10Case => Variable10Case, variable10_case
ɛrgo rE tHis => ƐrgoRETHis, ɛrgo_r_e_t_his
hurry-up-joe! => HurryUpJoe!, hurry_up_joe!
c://my-docs/happy_Flag-Day/12.doc => C://myDocs/happyFlagDay/12.doc, c://my_docs/happy_flag_day/12.doc
  spaces   => Spaces, spaces
Works with: Delphi version 6.0

Makes use of Delphi "sets" to help parse strings.


const TestStrings: array [0..7] of string = (
 'snakeCase', 'snake_case', 'variable_10_case', 'variable10Case',
 '\u025brgo rE tHis', 'hurry-up-joe!', 'c://my-docs/happy_Flag-Day/12.doc',
 '  spaces  ');


function MakeCamelCase(S: string): string;
{Convert string to camel-case}
var I: integer;
var Toggle: boolean;
begin
S:=Trim(S);
Result:='';
for I:=1 to Length(S) do
 if Toggle then
	begin
	Result:=Result+UpperCase(S[I]);
	Toggle:=False;
	end
 else if S[I] in [' ','_','-'] then Toggle:=True
 else Result:=Result+S[I];
end;


function MakeSnakeCase(S: string): string;
{Convert string to snake-case}
var I: integer;
var Toggle: boolean;
begin
S:=Trim(S);
Result:='';
for I:=1 to Length(S) do
 if S[I] in [' ','-'] then Result:=Result+'_'
 else if S[I] in ['A'..'Z'] then
	begin
	Result:=Result+'_';
	Result:=Result+LowerCase(S[I]);
	end
 else Result:=Result+S[I];
end;

procedure ConvertCamelSnake(SA: array of string; Memo: TMemo);
var I: integer;
var S: string;

	function FormatStrs(S1,S2: string): string;
	begin
	Result:=Format('%35s',[S1])+' '+Format('%-35s',[S2]);
	end;

begin
Memo.Lines.Add('Snake Case: ');
for I:=0 to High(SA) do
	begin
	S:=FormatStrs(SA[I],MakeSnakeCase(SA[I]));
	Memo.Lines.Add(S);
	end;
Memo.Lines.Add('Camel Case: ');
for I:=0 to High(SA) do
	begin
	S:=FormatStrs(SA[I],MakeCamelCase(SA[I]));
	Memo.Lines.Add(S);
	end;
end;

procedure CamelSnakeTest(Memo: TMemo);
{Test camel/snake conversion routines}
begin
ConvertCamelSnake(TestStrings,Memo);
end;
Output:
Snake Case: 
                          snakeCase snake_case                         
                         snake_case snake_case                         
                   variable_10_case variable_10_case                   
                     variable10Case variable10_case                    
                  \u025brgo rE tHis \u025brgo_r_e_t_his                
                      hurry-up-joe! hurry_up_joe!                      
  c://my-docs/happy_Flag-Day/12.doc c://my_docs/happy__flag__day/12.doc
                           spaces   spaces                             
Camel Case: 
                          snakeCase snakeCase                          
                         snake_case snakeCase                          
                   variable_10_case variable10Case                     
                     variable10Case variable10Case                     
                  \u025brgo rE tHis \u025brgoRETHis                    
                      hurry-up-joe! hurryUpJoe!                        
  c://my-docs/happy_Flag-Day/12.doc c://myDocs/happyFlagDay/12.doc     
                           spaces   spaces                             
Translation of: Nim
func$ strip s$ .
   a = 1
   while substr s$ a 1 = " "
      a += 1
   .
   b = len s$
   while substr s$ b 1 = " "
      b -= 1
   .
   return substr s$ a (b - a + 1)
.
func$ toupper c$ .
   c = strcode c$
   if c >= 97 and c <= 122
      c$ = strchar (c - 32)
   .
   return c$
.
func$ tolower c$ .
   c = strcode c$
   if c >= 65 and c <= 90
      c$ = strchar (c + 32)
   .
   return c$
.
func isupper c$ .
   c = strcode c$
   if c >= 65 and c <= 90
      return 1
   .
.
delim$ = "_- "
func$ snakecase s$ .
   s$ = strip s$
   for c$ in strchars s$
      if isupper c$ = 1 and prev$ <> ""
         if strpos delim$ prev$ = 0
            r$ &= "_"
         .
         r$ &= tolower c$
      else
         r$ &= c$
      .
      prev$ = c$
   .
   return r$
.
func$ camelcase s$ .
   s$ = strip s$
   prev$ = "x"
   for c$ in strchars s$
      if strpos delim$ prev$ <> 0
         r$ &= toupper c$
      elif strpos delim$ c$ = 0
         r$ &= c$
      .
      prev$ = c$
   .
   return r$
.
test$[] = [ "snakeCase" "snake_case" "variable_10_case" "variable10Case" "ɛrgo rE tHis" "hurry-up-joe!" "c://my-docs/happy_Flag-Day/12.doc" "  spaces  " ]
print "=== To snake_case ==="
for s$ in test$[]
   print s$ & " -> " & snakecase s$
.
print "\n=== To camelCase ==="
for s$ in test$[]
   print s$ & " -> " & camelcase s$
.
Output:
=== To snake_case ===
snakeCase -> snake_case
snake_case -> snake_case
variable_10_case -> variable_10_case
variable10Case -> variable10_case
ɛrgo rE tHis -> ɛrgo r_e t_his
hurry-up-joe! -> hurry-up-joe!
c://my-docs/happy_Flag-Day/12.doc -> c://my-docs/happy_flag-day/12.doc
  spaces   -> spaces

=== To camelCase ===
snakeCase -> snakeCase
snake_case -> snakeCase
variable_10_case -> variable10Case
variable10Case -> variable10Case
ɛrgo rE tHis -> ɛrgoRETHis
hurry-up-joe! -> hurryUpJoe!
c://my-docs/happy_Flag-Day/12.doc -> c://myDocs/happyFlagDay/12.doc
  spaces   -> spaces

This is the best attempt at snake case program (camel case one is not possible for the reasons below.) It doesn't convert kebab-case identifiers and doesn't change the case of camel case capitals. sed \l and other case-changing directives could work here, but they are absent from ed. So camel case is impossible.

# by Artyom Bologov
H
g/.*/s/\([A-Z]\)/_&/g
g/^\<_*/s///
g/^_*\>/s///
,p
Q
Output:
$ ed -s snake-case.input < snake-case.ed 
Newline appended
snake_Case
snake_case
variable_10_case
variable10_Case
ɛrgo r_E t_His
hurry-up-joe!
c://my-docs/happy__Flag-_Day/12.doc
   spaces  

In my interpretation of the task, leading/trailing whitespace should be ignored, not trimmed. And non-leading/trailing whitespace should be dealt with the same way as underscores and hyphens. Although the task says nothing about numbers, I chose to treat letter->number and number->letter transitions the same way as lower->upper for the sake of converting to snake case.

Works with: Factor version 0.99 2021-06-02
USING: formatting kernel math regexp sequences splitting
splitting.extras unicode ;

! ignore leading/trailing whitespace
: preserve ( str quot -- newstr )
    [ [ blank? ] split-head [ blank? ] split-tail swap ] dip
    call glue ; inline

: >snake ( str -- newstr )
    [
        R/ (\p{lower}\p{upper}|\d\p{alpha}|\p{alpha}\d)/
        [ 1 short cut >lower "_" glue ] re-replace-with
        R/ [\s-]/ "_" re-replace
    ] preserve ;

: capitalize ( str -- newstr ) 1 short cut swap >upper prepend ;

: >camel ( str -- newstr )
    [
        "\s_-" split harvest 1 short cut
        [ capitalize ] map append "" join
    ] preserve ;

: test ( str -- )
    dup >snake over dup >camel
    "%u >snake %u\n%u >camel %u\n" printf ;

{
    "snakeCase" "snake_case" "variable_10_case" "variable10Case"
    "ɛrgo rE tHis" "hurry-up-joe!"
    "c://my-docs/happy_Flag-Day/12.doc" "  spaces  "
    "   internal space   "
} [ test ] each
Output:
"snakeCase" >snake "snake_case"
"snakeCase" >camel "snakeCase"
"snake_case" >snake "snake_case"
"snake_case" >camel "snakeCase"
"variable_10_case" >snake "variable_10_case"
"variable_10_case" >camel "variable10Case"
"variable10Case" >snake "variable_10_case"
"variable10Case" >camel "variable10Case"
"ɛrgo rE tHis" >snake "ɛrgo_r_e_t_his"
"ɛrgo rE tHis" >camel "ɛrgoRETHis"
"hurry-up-joe!" >snake "hurry_up_joe!"
"hurry-up-joe!" >camel "hurryUpJoe!"
"c://my-docs/happy_Flag-Day/12.doc" >snake "c://my_docs/happy_Flag_Day/12.doc"
"c://my-docs/happy_Flag-Day/12.doc" >camel "c://myDocs/happyFlagDay/12.doc"
"  spaces  " >snake "  spaces  "
"  spaces  " >camel "  spaces  "
"   internal space   " >snake "   internal_space   "
"   internal space   " >camel "   internalSpace   "

The conversion to camel case or snake case is straightforward: First find the positions inside the text where one word ends and the next word begins. Then change the text around these points accordingly.

One complication comes with the greek letter epsilon "ɛ" in one of the examples. The problem here is that this is a single letter on the screen but it occupies two bytes of storage. the intrinsic function len() returns the number of bytes but not the displayed number of character cells. function ulen() returns the number of displayed character cells. This is used to construct a variable format string to display the text containing the Epsilon correctly.

Functions ulen() and ulen_single were found (MIT License) on https://fortran-lang.discourse.group/t/using-unicode-characters-in-fortran/2764/8


! Camel case and snake case
!
! tested with Intel ifx (IFX) 2025.2.1 20250806             on Kubuntu 25.04
!             GNU Fortran (Ubuntu 14.2.0-19ubuntu2) 14.2.0  on Kubuntu 25.04
!
!
! U.B., August 2025
!
program CaseConverter

implicit none

! sep is a marker to separate words within given strings. 
! Selected "§" because this is never part of a legit text.
!
character, parameter  ::  sep='§'   

character (len=:), allocatable :: testWord    


print *, ' ***** Converting test strings to Snake Case *****'

testWord = 'snakeCase'
call printResult (testWord, toSnakeCase (testWord))

testWord = 'snake_case'
call printResult (testWord, toSnakeCase (testWord))

testWord = 'variable_10_case'
call printResult (testWord, toSnakeCase (testWord))

testWord = 'variable10Case'
call printResult (testWord, toSnakeCase (testWord))

testWord = 'ɛrgo rE tHis'
call printResult (testWord, toSnakeCase (testWord))

testWord = 'hurry-up-joe!'
call printResult (testWord, toSnakeCase (testWord))

testWord = 'c://my-docs/happy_Flag-Day/12.doc'
call printResult (testWord, toSnakeCase (testWord))

testWord = '  spaces  '
call printResult (testWord, toSnakeCase (testWord))

print *
print *, ' ***** Converting test strings to Camel Case *****'

testWord = 'snakeCase'
call printResult ( testWord, toCamelCase (testWord) )

testWord = 'snake_case'
call printResult ( testWord, toCamelCase (testWord) )

testWord = 'variable_10_case'
call printResult ( testWord, toCamelCase (testWord) )

testWord = 'variable10Case'
call printResult ( testWord, toCamelCase (testWord) )

testWord = 'ɛrgo rE tHis'
call printResult (testWord, toCamelCase(testWord))

testWord = 'hurry-up-joe!'
call printResult ( testWord, toCamelCase (testWord) )

testWord = 'c://my-docs/happy_Flag-Day/12.doc'
call printResult ( testWord, toCamelCase (testWord) )

testWord = '  spaces  '
call printResult ( testWord, toCamelCase (testWord) )




contains


! ----------------------------------------------------------
! print with variable format to display the greek "ɛ" 
! and the following text positioned correctly.
! Letter "ɛ"  uses 2 bytes so len("ɛ") = 2 but ulen("ɛ") = 1
! ----------------------------------------------------------

subroutine printResult (a,b)
character*(*), intent(in)  :: a,b
character (len=100) ::fmt
write (fmt, *) '(A', 34+ (len(a)-ulen(a)) ,', " => ",A)'  
print fmt, a, b

end subroutine printResult


!---------------------------------------
! change ASCII a...z to upper case a...z
!---------------------------------------
function toupper (c) result(retc)

character ::c
character :: retc

if (c >='a' .and. c <= 'z') then
  retc = achar (iachar('A') + (iachar(c)-iachar('a')))
else
  retc = c
end if

end function toupper

!---------------------------------------
! change ASCII A...Z to lower case a...z
!---------------------------------------
function tolower (c) result(retc)

character ::c
character :: retc

if (c >='A' .and. c <= 'Z') then              !  is upper case
  retc = achar (iachar('a') + (iachar(c)-iachar('A')))
else
  retc = c
end if

end function tolower

!---------------------------------------------------------------------------------
! Scan input text, mark all positions between distinct words within the text
! so that later in the actual conversion these points can be rewritten accordingly.
!---------------------------------------------------------------------------------
function  prepare (txt)  result (newtext)

character (len=*), intent (in) :: txt
character (len=:), allocatable  :: text, newtext
integer :: ip1, ip2, ip3, l
character :: beginword


newtext='';

! First remove leading and trailing spaces
text = trim (txt)
text = adjustl (text)
text = trim (text)
l = len_trim(text)

ip1 = 1
ip2 = 2
ip3 = 1
do while (ip2 <= l)
  if (text(ip2:ip2) >= 'A' .and. text(ip2:ip2) <='Z' ) then               ! upcase letter indicates beginning of a word
    newtext = newtext(:len_trim(newtext)) // text(ip1:ip2-1) // sep       
    ip1 = ip2
    ip2 = ip1+1
  else if (text(ip2:ip2) .eq. '_'  & 
      .or. text(ip2:ip2) .eq. '-'  & 
      .or. text(ip2:ip2) .eq. ' ' ) then    ! Separator is behind current word, new word following.
    if (ip2 .lt. l) then ! ip2+1 still inside text
      beginword = tolower (text(ip2+1:ip2+1))
      newtext = newtext(:len_trim(newtext)) // text (ip1:ip2-1) // sep  // beginword  
    else
      ! separator at ip2 is last character of text. Just drop it.
      newtext = newtext(:len_trim(newtext)) // text (ip1:ip2-1) 
    endif
    ip1 = ip2+2                                                            ! skip separator and begin of next word
    ip2 = ip1
  else
    ip2 = ip2 + 1
  end if 
end do

newtext = newtext(:len_trim(newtext))  // text(ip1:)

end function prepare 

!-----------------------------------
! Convert prepared text to CamelCase
!-----------------------------------
function toCamelCase (txt) result(newtext)
!
! 1st char is lowercase, all spaces removed and word beginnings upperCase
!
character (len=*), intent (in) :: txt
character (:), allocatable  :: text, newtext
integer :: ip, l
character :: beginword

newtext = ''
text = prepare (txt)

l = len_trim(text)
newtext = newtext(:len_trim(newtext)) // tolower (text(1:1))

ip = 2

do while (ip <= l)
  if (text(ip:ip) .eq. sep) then
    ip = ip + 1             ! skip the separator
    if (ip <l) then
      beginword = toUpper (text(ip:ip))
      newtext = newtext(:len_trim(newtext)) // beginword
      ip = ip + 1           ! skip the beginWord
    end if
  else
    newtext = newtext(:len_trim(newtext)) // text(ip:ip)
    ip = ip + 1
  end if
end do
end function toCamelCase

!------------------------------------
! Convert prepared text to snake_case
!------------------------------------
function toSnakeCase (txt) result (newtext)
!
character (len=*), intent (in)  :: txt
character (:), allocatable ::  text, newtext
integer :: ip, l
character :: beginword

newtext = ''

text = prepare (txt)
l = len_trim (text)
newtext = newtext(:len_trim(newtext)) // tolower (text(1:1))
ip = 2

do while (ip <= l)
  if (text(ip:ip) .eq. sep) then
    newtext = newtext(:len_trim(newtext))  // '_'    ! Replace sep by '_'
    ip = ip + 1
    if (ip <l) then
      beginword = toLower (text(ip:ip))       ! New word always starts in lowercase
      newtext = newtext(:len_trim(newtext))  // beginword
      ip = ip + 1           ! skip the beginWord
    end if
  else
    newtext = newtext(:len_trim(newtext))  // text(ip:ip)
    ip = ip + 1
  end if
end do
end function toSnakeCase

!----------------------------------------------------------------------------------
! get number of displayed characters of a string, which might differ from len(text)
!----------------------------------------------------------------------------------
integer function ulen(chars)
implicit none

  character(len=*), intent(in) :: chars
  integer :: i, j, bytes

  ulen = 0
  bytes= len(chars)
  if ( bytes == 0 ) then
    ulen = 0
    return
  end if
  i = 1
  do while ( i <= bytes )
    j = ulen_single(chars(i:i))
    i = i + j
    ulen = ulen + 1
  end do
end function
!------------------------------------------------------------
! look at single character and see how many bytes it occupies
!------------------------------------------------------------
function ulen_single(ch) result(retlen)
  implicit none
  character, intent(in) ::ch
  integer :: retlen, ich

  retlen=0
  ich = ichar(ch)

  if ( ich < int(Z'80') ) THEN
    retlen=1
  else if ( (ich > ( int(Z'C0') + 1)) .and. ( ich < int(Z'E0') )) THEN
    retlen=2
  else if ( ich < int(Z'F0') ) THEN
    retlen=3
  else if ( ich <= int(Z'F4') ) THEN
    retlen=4
  else
    retlen=1   !assume we process larger seqences, 1 by 1 bytes
  end if
end function


end program
Output:
 ***** Converting test strings to Snake Case *****
                         snakeCase => snake_case
                        snake_case => snake_case
                  variable_10_case => variable_10_case
                    variable10Case => variable10_case
                      ɛrgo rE tHis => ɛrgo_r_e_t_his
                     hurry-up-joe! => hurry_up_joe!
 c://my-docs/happy_Flag-Day/12.doc => c://my_docs/happy_flag_day/12_doc
                          spaces   => spaces
 
  ***** Converting test strings to Camel Case *****
                         snakeCase => snakeCase
                        snake_case => snakeCase
                  variable_10_case => variable10Case
                    variable10Case => variable10Case
                      ɛrgo rE tHis => ɛrgoRETHis
                     hurry-up-joe! => hurryUpJoe!
 c://my-docs/happy_Flag-Day/12.doc => c://myDocs/happyFlagDay/12Doc
                          spaces   => spaces

Function isDigit(ch As String) As Boolean
    Return ch >= "0" And ch <= "9"
End Function

Function to_snake_case(s As String) As String
    Dim As Integer l = Len(s)
    Dim As String snake = Trim(s), tmp = snake
    
    For i As Integer = 1 To Len(snake)
        If isDigit(Mid(snake, i, 1)) Then
            Continue For
        Elseif Instr(Mid(snake, i, 1), " ") Then
            Mid(snake, i) = "_"
            Continue For
        Elseif Instr(Mid(snake, i, 1), Any "\:/-_!.") Then
            Continue For
        Elseif Mid(snake, i, 1) = Ucase(Mid(snake, i, 1))  Then
            tmp = Lcase(Mid(snake, i,1))
            Mid(snake, i) = "_"
            snake = Left(snake, i) & tmp & Mid(snake, i+1)
        End If
    Next i
    Return snake
End Function

Function toCamelCase(s As String) As String
    Dim As Integer l = Len(s)
    Dim As String camel = Trim(s), tmp = camel
    
    For i As Integer = 1 To Len(camel)
        If Instr(Mid(camel, i, 1), Any ":/!.") Then
            Continue For
        Elseif Instr(Mid(camel, i, 1), Any " _-") Then
            camel = Left(camel, i-1) & Ucase(Mid(camel, i+1,1)) & Mid(camel, i+2)
        End If
    Next i
    Return camel
End Function

Dim Shared tests(1 To ...) As String*33 => {_
"snakeCase", "snake_case", "variable_10_case", "variable10Case", _
"\u025brgo rE tHis", "ergo rE tHis", "hurry-up-joe!", _
"c://my-docs/happy_Flag-Day/12.doc", "  spaces  "}

Sub test0(title As String, fn As String)
    Print title
    For i As Integer = 1 To Ubound(tests)
        Dim As String texto = tests(i) & " ===> " & to_snake_case(tests(i))
        Locate i+1, 41 - Len(texto) / 2 : Print texto
    Next i
End Sub

Sub test1(title As String, fn As String)
    Print title
    For i As Integer = 1 To Ubound(tests)
        Dim As String texto = tests(i) & " ===> " & toCamelCase(tests(i))
        Locate i+12, 41 - Len(texto) / 2 : Print texto
    Next i
End Sub

test0 "to_snake_case:", "to_snake_case"
Print
test1 "toCamelCase:", "toCamelCase"

Sleep
include "NSLog.incl"
local fn snake_toCamel( s as CFStringRef ) as CFStringRef
  long r,f
  s = fn StringByTrimmingCharactersInSet( s, fn CFCharacterSetGetPredefined(_kCFCharacterSetWhitespace ))
  for r = 1 to len(s)-2
    f = instr(0, @"_- ", mid(s, r, 1))
    if f <> NSNotFound
      s = fn stringwithformat(@"%@%@%@", left( s, r ), ucase(mid(s,r+1,1)), mid(s,r+2))
    end if
  next
end fn = s

local fn CamelTo_snake( s as CFStringRef ) as CFStringRef
  long r,f
  s = fn StringByTrimmingCharactersInSet( s, fn CFCharacterSetGetPredefined(_kCFCharacterSetWhitespace ))
  s = fn StringByReplacingOccurrencesOfString( s, @" ", @"_")
  s = fn StringByReplacingOccurrencesOfString( s, @"-", @"_")
  for r = 1 to len(s)-2
    f = instr(0, @"ABCDEFGHIJKLMNOPQRSTUVWXYZ", mid(s, r, 1))
    if f <> NSNotFound
      if fn StringIsEqual(@"_", mid(s, r-1, 1)) then continue
      s = fn stringwithformat(@"%@%@%@", left( s, r ), @"_", mid(s,r))
    end if
  next
  s = fn stringwithformat(@"%@%@",left( s, 1), lcase(mid(s, 1)))
end fn = s

local fn show( s1 as CFStringRef )
  CFStringRef  s = @"                                    "
  CFStringRef s2 = fn snake_toCamel( s1 )
  CFStringRef s3 = fn CamelTo_snake( s1 )
  nslog(@"  \"%@\"%@\"%@\"%@\"%@\"", s1, mid(s, len(s1)), s2, mid(s, len(s2)), s3)
end fn

nslog( @"%@",@"String                                ¬
fn snake_toCamel                      ¬
fn CamelTo_snake")
fn show(@"snakeCase")
fn show(@"snake_case")
fn show(@"variable_10_case")
fn show(@"variable10Case")
fn show(@"ɛrgo rE tHis")
fn show(@"hurry-up-joe!")
fn show(@"c://my-docs/happy_Flag-Day/12.doc")
fn show(@"  spaces  ")

handleevents
Output:
String                      fn snake_toCamel            fn CamelTo_snake
  "snakeCase"                 "snakeCase"                 "snake_case"
  "snake_case"                "snakeCase"                 "snake_case"
  "variable_10_case"          "variable10Case"            "variable_10_case"
  "variable10Case"            "variable10Case"            "variable10_case"
  "ɛrgo rE tHis"              "ɛrgoRETHis"                "ɛrgo_r_e_t_his"
  "hurry-up-joe!"             "hurryUpJoe!"               "hurry_up_joe!"
  "  spaces  "                "spaces"                    "spaces"
  "c://my-docs/happy_Flag-Day/12.doc" "c://myDocs/happyFlagDay/12.doc" "c://my_docs/happy_flag_day/12.doc"
package main

import (
	"fmt"
	"strings"
	"unicode"
)

func snakeCaseToCamelCase(word string, sep rune) string {
	var sb strings.Builder

	wordRunes := []rune(strings.TrimSpace(word))
	wordLen := len(wordRunes)

	for i := 0; i < wordLen; i++ {
		c := wordRunes[i]

		if c == sep {
			if i+1 < wordLen && wordRunes[i+1] != sep {
				sb.WriteRune(unicode.ToUpper(wordRunes[i+1]))
				i++
			}
		} else {
			if i == 0 {
				c = unicode.ToLower(c)
			}
			sb.WriteRune(c)
		}
	}

	return sb.String()
}

func camelCaseToSnakeCase(word string, sep rune) string {
	word = strings.TrimSpace(word)
	var sb strings.Builder
	var lastRune rune

	for i, c := range word {
		if i != 0 && unicode.IsUpper(c) {
			if lastRune != sep {
				sb.WriteRune(sep)
			}
		}
		sb.WriteRune(unicode.ToLower(c))
		lastRune = c
	}

	return sb.String()
}

func main() {
	words := []string{
		"snakeCase",
		"snake_case",
		"variable_10_case",
		"variable10Case",
		"ɛrgo rE tHis",
		"hurry-up-joe!",
		"c://my-docs/happy_Flag-Day/12.doc",
		"  spaces  ",
	}

	fmt.Print("snake_case to camelCase:\n\n")

	for _, word := range words {
		fmt.Println(word, "=>", snakeCaseToCamelCase(word, '_'))
	}

	fmt.Println()
	fmt.Print("kebab-case to camelCase:\n\n")

	for _, word := range words {
		fmt.Println(word, "=>", snakeCaseToCamelCase(word, '-'))
	}

	fmt.Println()
	fmt.Print("space case to camelCase:\n\n")

	for _, word := range words {
		fmt.Println(word, "=>", snakeCaseToCamelCase(word, ' '))
	}

	fmt.Println()
	fmt.Print("camelCase to snake_case:\n\n")

	for _, word := range words {
		fmt.Println(word, "=>", camelCaseToSnakeCase(word, '_'))
	}

	fmt.Println()
	fmt.Print("camelCase to kebab-case:\n\n")

	for _, word := range words {
		fmt.Println(word, "=>", camelCaseToSnakeCase(word, '-'))
	}

	fmt.Println()
	fmt.Print("camelCase to space case:\n\n")

	for _, word := range words {
		fmt.Println(word, "=>", camelCaseToSnakeCase(word, ' '))
	}
}
Output:
snake_case to camelCase:

snakeCase => snakeCase
snake_case => snakeCase
variable_10_case => variable10Case
variable10Case => variable10Case
ɛrgo rE tHis => ɛrgo rE tHis
hurry-up-joe! => hurry-up-joe!
c://my-docs/happy_Flag-Day/12.doc => c://my-docs/happyFlag-Day/12.doc
  spaces   => spaces

kebab-case to camelCase:

snakeCase => snakeCase
snake_case => snake_case
variable_10_case => variable_10_case
variable10Case => variable10Case
ɛrgo rE tHis => ɛrgo rE tHis
hurry-up-joe! => hurryUpJoe!
c://my-docs/happy_Flag-Day/12.doc => c://myDocs/happy_FlagDay/12.doc
  spaces   => spaces

space case to camelCase:

snakeCase => snakeCase
snake_case => snake_case
variable_10_case => variable_10_case
variable10Case => variable10Case
ɛrgo rE tHis => ɛrgoRETHis
hurry-up-joe! => hurry-up-joe!
c://my-docs/happy_Flag-Day/12.doc => c://my-docs/happy_Flag-Day/12.doc
  spaces   => spaces

camelCase to snake_case:

snakeCase => snake_case
snake_case => snake_case
variable_10_case => variable_10_case
variable10Case => variable10_case
ɛrgo rE tHis => ɛrgo r_e t_his
hurry-up-joe! => hurry-up-joe!
c://my-docs/happy_Flag-Day/12.doc => c://my-docs/happy_flag-_day/12.doc
  spaces   => spaces

camelCase to kebab-case:

snakeCase => snake-case
snake_case => snake_case
variable_10_case => variable_10_case
variable10Case => variable10-case
ɛrgo rE tHis => ɛrgo r-e t-his
hurry-up-joe! => hurry-up-joe!
c://my-docs/happy_Flag-Day/12.doc => c://my-docs/happy_-flag-day/12.doc
  spaces   => spaces

camelCase to space case:

snakeCase => snake case
snake_case => snake_case
variable_10_case => variable_10_case
variable10Case => variable10 case
ɛrgo rE tHis => ɛrgo r e t his
hurry-up-joe! => hurry-up-joe!
c://my-docs/happy_Flag-Day/12.doc => c://my-docs/happy_ flag- day/12.doc
  spaces   => spaces

The output of this example reflects the authors interpretation of the task.

import java.util.List;

public final class CamelCaseAndSnakeCase {

	public static void main(String[] aArgs) {
		List<String> variableNames = List.of( "snakeCase", "snake_case", "variable_10_case", "variable10Case",
			"ergo rE tHis", "hurry-up-joe!", "c://my-docs/happy_Flag-Day/12.doc", "  spaces  ");
		
		System.out.println(String.format("%48s", "=== To snake_case ==="));
		for ( String text : variableNames ) {
			System.out.println(String.format("%34s%s%s", text, " --> ", toSnakeCase(text)));
		}

		System.out.println();
		System.out.println(String.format("%48s", "=== To camelCase ==="));
		for ( String text : variableNames ) {
			System.out.println(String.format("%34s%s%s", text, " --> ", toCamelCase(text)));
		}
	}	
	
	private static String toSnakeCase(String aCamel) {
		aCamel = aCamel.trim().replace(SPACE, UNDERSCORE).replace(HYPHEN, UNDERSCORE);
	    StringBuilder snake = new StringBuilder();
	    boolean first = true;
	    for ( char ch : aCamel.toCharArray() ) {
	        if ( first ) {
	            snake.append(ch);
	            first = false;
	        } else if ( ! first && Character.isUpperCase(ch) ) {
	            if ( snake.toString().endsWith(UNDERSCORE) ) {
	                snake.append(Character.toLowerCase(ch));
	            } else {
	                snake.append(UNDERSCORE + Character.toLowerCase(ch));
	            }
	        } else {
	            snake.append(ch);
	        }
	    }
	    return snake.toString();
		
	}
	
	private static String toCamelCase(String aSnake) {
		aSnake = aSnake.trim().replace(SPACE, UNDERSCORE).replace(HYPHEN, UNDERSCORE);
	    StringBuilder camel = new StringBuilder();
	    boolean underscore = false;
	    for ( char ch : aSnake.toCharArray() ) {
	        if ( Character.toString(ch).equals(UNDERSCORE) ) {
	            underscore = true;
	        } else if ( underscore ) {
	            camel.append(Character.toUpperCase(ch));
	            underscore = false;
	        } else {
	            camel.append(ch);
	        }
	    }
	    return camel.toString();		
	}
	
	private static final String SPACE = " ";
	private static final String UNDERSCORE = "_";
	private static final String HYPHEN = "-";
	
}
Output:
                           === To snake_case ===
                         snakeCase --> snake_case
                        snake_case --> snake_case
                  variable_10_case --> variable_10_case
                    variable10Case --> variable10_case
                      ergo rE tHis --> ergo_r_e_t_his
                     hurry-up-joe! --> hurry_up_joe!
 c://my-docs/happy_Flag-Day/12.doc --> c://my_docs/happy_flag_day/12.doc
                          spaces   --> spaces

                           === To camelCase ===
                         snakeCase --> snakeCase
                        snake_case --> snakeCase
                  variable_10_case --> variable10Case
                    variable10Case --> variable10Case
                      ergo rE tHis --> ergoRETHis
                     hurry-up-joe! --> hurryUpJoe!
 c://my-docs/happy_Flag-Day/12.doc --> c://myDocs/happyFlagDay/12.doc
                          spaces   --> spaces 


Translation of: C++
const HYPHEN = '-';
const SPACE = ' ';
const UNDERSCORE = '_';
const WHITESPACE = " \n\r\t\f\v";

function leftTrim(text) {
  const start = text.search(/\S/); // Find the index of the first non-whitespace character
  return start === -1 ? "" : text.substring(start);
}

function rightTrim(text) {
  const end = text.search(/\S(?![\s\S]*\S)/); // Find the index of the last non-whitespace character
  return end === -1 ? "" : text.substring(0, end + 1);
}

function trim(text) {
  return leftTrim(rightTrim(text));
}

function prepareForConversion(text) {
  text = trim(text);
  text = text.replace(new RegExp(SPACE, 'g'), UNDERSCORE);
  text = text.replace(new RegExp(HYPHEN, 'g'), UNDERSCORE);
  return text; // Return the modified text
}

function toSnakeCase(camel) {
  camel = prepareForConversion(camel);
  let snake = "";
  let first = true;
  for (const ch of camel) {
    if (first) {
      snake += ch;
      first = false;
    } else if (!first && ch >= 'A' && ch <= 'Z') {
      if (snake.slice(-1) === UNDERSCORE) {
        snake += ch.toLowerCase();
      } else {
        snake += UNDERSCORE;
        snake += ch.toLowerCase();
      }
    } else {
      snake += ch;
    }
  }
  return snake;
}

function toCamelCase(snake) {
  snake = prepareForConversion(snake);
  let camel = "";
  let underscore = false;
  for (const ch of snake) {
    if (ch === UNDERSCORE) {
      underscore = true;
    } else if (underscore) {
      camel += ch.toUpperCase();
      underscore = false;
    } else {
      camel += ch;
    }
  }
  return camel;
}

function main() {
  const variableNames = ["snakeCase", "snake_case", "variable_10_case",
    "variable10Case", "ergo rE tHis", "hurry-up-joe!", "c://my-docs/happy_Flag-Day/12.doc", "  spaces  "];

  console.log("".padEnd(48, " ") + "=== To snake_case ===");
  for (const text of variableNames) {
    console.log("".padEnd(34, " ") + text + " --> " + toSnakeCase(text));
  }

  console.log("\n");
  console.log("".padEnd(48, " ") + "=== To camelCase ===");
  for (const text of variableNames) {
    console.log("".padEnd(34, " ") + text + " --> " + toCamelCase(text));
  }
}

main();
Output:
                                                === To snake_case ===
                                  snakeCase --> snake_case
                                  snake_case --> snake_case
                                  variable_10_case --> variable_10_case
                                  variable10Case --> variable10_case
                                  ergo rE tHis --> ergo_r_e_t_his
                                  hurry-up-joe! --> hurry_up_joe!
                                  c://my-docs/happy_Flag-Day/12.doc --> c://my_docs/happy_flag_day/12.doc
                                    spaces   --> spaces


                                                === To camelCase ===
                                  snakeCase --> snakeCase
                                  snake_case --> snakeCase
                                  variable_10_case --> variable10Case
                                  variable10Case --> variable10Case
                                  ergo rE tHis --> ergoRETHis
                                  hurry-up-joe! --> hurryUpJoe!
                                  c://my-docs/happy_Flag-Day/12.doc --> c://myDocs/happyFlagDay/12.doc
                                    spaces   --> spaces


Adapted from Wren

Works with: jq

Works with gojq, the Go implementation of jq

Preliminaries

def isUpper: explode[0] | 65 <= . and . <= 90;

def lpad($len): tostring | ($len - length) as $l | (" " * $l)[:$l] + .;

# "White space is not permitted as part of camel case or snake case variable names."
def trim: sub("^\\s+";"") | sub("\\s+$";"");

Camel and Snake

def toCamel:
  trim as $snake
  | { camel: "", underscore : false}
  | reduce ($snake|explode[]|[.]|implode) as $c (.;
      if ["_", "-", " "]|index($c)
      then .underscore = true
      elif .underscore
      then .camel += ($c|ascii_upcase)
      | .underscore = false
      else .camel += $c
      end)
  | .camel;

def toSnake:
  (trim | gsub("\\s"; "_")) as $camel
  | reduce ($camel|explode[1:][]|[.]|implode) as $c (
      $camel[0:1];
      if $c|isUpper
      then ($c|ascii_downcase) as $lc
      | if (.[-1:] | (. == "_" or . == "-"))
           then . + $lc
           else . +  "_" + $lc
           end
      else . + $c
      end );

def tests: [
    "snakeCase", "snake_case", "variable_10_case", "variable10Case", "ɛrgo rE tHis",
    "hurry-up-joe!", "c://my-docs/happy_Flag-Day/12.doc", "  spaces  "
];

"                          === to_snake_case ===",
(tests[] | "\(lpad(33)) -> \(toSnake)"),
"",
"                          === toCamelCase ===",
(tests[] | "\(lpad(33)) -> \(toCamel)")
Output:
                          === to_snake_case ===
                        snakeCase -> snake_case
                       snake_case -> snake_case
                 variable_10_case -> variable_10_case
                   variable10Case -> variable10_case
                     ɛrgo rE tHis -> ɛrgo_r_e_t_his
                    hurry-up-joe! -> hurry-up-joe!
c://my-docs/happy_Flag-Day/12.doc -> c://my-docs/happy_flag-day/12.doc
                         spaces   -> spaces

                          === toCamelCase ===
                        snakeCase -> snakeCase
                       snake_case -> snakeCase
                 variable_10_case -> variable10Case
                   variable10Case -> variable10Case
                     ɛrgo rE tHis -> ɛrgoRETHis
                    hurry-up-joe! -> hurryUpJoe!
c://my-docs/happy_Flag-Day/12.doc -> c://myDocs/happyFlagDay/12.doc
                         spaces   -> spaces
#=
Regex based variable name convention change string functions.
    `sep` is the separator targeted for change from (to camel case) or to (to snake case)
    `allsep` is the separators other than `sep` that may be changed to `sep`
    `lcmiddle` is a boolean to set whether caps within camel case words are made lowercase
=#

function snakeToCamelCase(s; sep=r"[_]+", lcmiddle=false)
    isempty(s) && return s
    words = split(strip(s), sep)
    return lowercasefirst(join(uppercasefirst.(lcmiddle ? lowercase.(words) : words)))
end

spaceToCamelCase(s) = snakeToCamelCase(s; sep=r"\s+")
kebabToCamelCase(s) = snakeToCamelCase(s; sep=r"[\-]+")
periodToCamelCase(s) = snakeToCamelCase(s; sep=r"[\.]+")
allsepToCamelCase(s) = snakeToCamelCase(s; sep=r"[ \-_\.]+")
lowermiddle_allsepToCamelCase(s) = snakeToCamelCase(s; sep=r"[ \-_\.]+", lcmiddle=true)

function camel_to_snake_case(s; sep="_", insep=sep, allsep=r"_+", lcmiddle=true)
    s = isempty(s) ? (return s) : lowercasefirst(strip(s))
    s = replace(s, r"[A-Z]+" => x -> sep * (lcmiddle ? lowercase(x) : lowercasefirst(x)))
    return replace(s, allsep => sep)
end

preserve_midcaps_camel_to_snake_case(s) = camel_to_snake_case(s; lcmiddle=false)
allsep_to_snake_case(s) = camel_to_snake_case(s; allsep=r"[ \-\._]+")
allsep_to_kebab_case(s) = camel_to_snake_case(s; allsep=r"[ \-\._]+", sep="-")
allsep_to_space_case(s) = camel_to_snake_case(s; allsep=r"[ \-\._]+", sep=" ")
allsep_to_period_case(s) = camel_to_snake_case(s; allsep=r"[ \-\._]+", sep=".")
allsep_to_slash_case(s) = camel_to_snake_case(s; allsep=r"[ \-\._]+", sep="/")

for f in [
    snakeToCamelCase,
    spaceToCamelCase,
    kebabToCamelCase,
    periodToCamelCase,
    allsepToCamelCase,
    lowermiddle_allsepToCamelCase,
    camel_to_snake_case,
    preserve_midcaps_camel_to_snake_case,
    allsep_to_snake_case,
    allsep_to_kebab_case,
    allsep_to_space_case,
    allsep_to_period_case,
    allsep_to_slash_case,
]
    println("Testing function $f:")

    for teststring in [
        "snakeCase",
        "snake_case",
        "snake-case",
        "snake case",
        "snake CASE",
        "snake.case",
        "variable_10_case",
        "variable10Case",
        "ɛrgo rE tHis",
        "hurry-up-joe!",
        "c://my-docs/happy_Flag-Day/12.doc",
        " spaces ",
    ]
        println(lpad(teststring, 36), "  =>  ", f(teststring))
    end
    println()
end
Output:
Testing function snakeToCamelCase:
                           snakeCase  =>  snakeCase     
                          snake_case  =>  snakeCase     
                          snake-case  =>  snake-case    
                          snake case  =>  snake case    
                          snake CASE  =>  snake CASE    
                          snake.case  =>  snake.case    
                    variable_10_case  =>  variable10Case
                      variable10Case  =>  variable10Case
                        ɛrgo rE tHis  =>  ɛrgo rE tHis
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happyFlag-Day/12.doc
                             spaces   =>  spaces

Testing function spaceToCamelCase:
                           snakeCase  =>  snakeCase
                          snake_case  =>  snake_case
                          snake-case  =>  snake-case
                          snake case  =>  snakeCase
                          snake CASE  =>  snakeCASE
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10Case
                        ɛrgo rE tHis  =>  ɛrgoRETHis
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy_Flag-Day/12.doc
                             spaces   =>  spaces

Testing function kebabToCamelCase:
                           snakeCase  =>  snakeCase
                          snake_case  =>  snake_case
                          snake-case  =>  snakeCase
                          snake case  =>  snake case
                          snake CASE  =>  snake CASE
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10Case
                        ɛrgo rE tHis  =>  ɛrgo rE tHis
                       hurry-up-joe!  =>  hurryUpJoe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://myDocs/happy_FlagDay/12.doc
                             spaces   =>  spaces

Testing function periodToCamelCase:
                           snakeCase  =>  snakeCase
                          snake_case  =>  snake_case
                          snake-case  =>  snake-case
                          snake case  =>  snake case
                          snake CASE  =>  snake CASE
                          snake.case  =>  snakeCase
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10Case
                        ɛrgo rE tHis  =>  ɛrgo rE tHis
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy_Flag-Day/12Doc
                             spaces   =>  spaces

Testing function allsepToCamelCase:
                           snakeCase  =>  snakeCase
                          snake_case  =>  snakeCase
                          snake-case  =>  snakeCase
                          snake case  =>  snakeCase
                          snake CASE  =>  snakeCASE
                          snake.case  =>  snakeCase
                    variable_10_case  =>  variable10Case
                      variable10Case  =>  variable10Case
                        ɛrgo rE tHis  =>  ɛrgoRETHis
                       hurry-up-joe!  =>  hurryUpJoe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://myDocs/happyFlagDay/12Doc
                             spaces   =>  spaces

Testing function lowermiddle_allsepToCamelCase:
                           snakeCase  =>  snakecase
                          snake_case  =>  snakeCase
                          snake-case  =>  snakeCase
                          snake case  =>  snakeCase
                          snake CASE  =>  snakeCase
                          snake.case  =>  snakeCase
                    variable_10_case  =>  variable10Case
                      variable10Case  =>  variable10case
                        ɛrgo rE tHis  =>  ɛrgoReThis
                       hurry-up-joe!  =>  hurryUpJoe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://myDocs/happyFlagDay/12Doc
                             spaces   =>  spaces

Testing function camel_to_snake_case:
                           snakeCase  =>  snake_case
                          snake_case  =>  snake_case
                          snake-case  =>  snake-case
                          snake case  =>  snake case
                          snake CASE  =>  snake _case
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10_case
                        ɛrgo rE tHis  =>  ɛrgo r_e t_his
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy_flag-_day/12.doc
                             spaces   =>  spaces

Testing function preserve_midcaps_camel_to_snake_case:
                           snakeCase  =>  snake_case
                          snake_case  =>  snake_case
                          snake-case  =>  snake-case
                          snake case  =>  snake case
                          snake CASE  =>  snake _cASE
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10_case
                        ɛrgo rE tHis  =>  ɛrgo r_e t_his
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy_flag-_day/12.doc
                             spaces   =>  spaces

Testing function allsep_to_snake_case:
                           snakeCase  =>  snake_case
                          snake_case  =>  snake_case
                          snake-case  =>  snake_case
                          snake case  =>  snake_case
                          snake CASE  =>  snake_case
                          snake.case  =>  snake_case
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10_case
                        ɛrgo rE tHis  =>  ɛrgo_r_e_t_his
                       hurry-up-joe!  =>  hurry_up_joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my_docs/happy_flag_day/12_doc
                             spaces   =>  spaces

Testing function allsep_to_kebab_case:
                           snakeCase  =>  snake-case
                          snake_case  =>  snake-case
                          snake-case  =>  snake-case
                          snake case  =>  snake-case
                          snake CASE  =>  snake-case
                          snake.case  =>  snake-case
                    variable_10_case  =>  variable-10-case
                      variable10Case  =>  variable10-case
                        ɛrgo rE tHis  =>  ɛrgo-r-e-t-his
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy-flag-day/12-doc
                             spaces   =>  spaces

Testing function allsep_to_space_case:
                           snakeCase  =>  snake case
                          snake_case  =>  snake case
                          snake-case  =>  snake case
                          snake case  =>  snake case
                          snake CASE  =>  snake case
                          snake.case  =>  snake case
                    variable_10_case  =>  variable 10 case
                      variable10Case  =>  variable10 case
                        ɛrgo rE tHis  =>  ɛrgo r e t his
                       hurry-up-joe!  =>  hurry up joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my docs/happy flag day/12 doc
                             spaces   =>  spaces

Testing function allsep_to_period_case:
                           snakeCase  =>  snake.case
                          snake_case  =>  snake.case
                          snake-case  =>  snake.case
                          snake case  =>  snake.case
                          snake CASE  =>  snake.case
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable.10.case
                      variable10Case  =>  variable10.case
                        ɛrgo rE tHis  =>  ɛrgo.r.e.t.his
                       hurry-up-joe!  =>  hurry.up.joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my.docs/happy.flag.day/12.doc
                             spaces   =>  spaces

Testing function allsep_to_slash_case:
                           snakeCase  =>  snake/case
                          snake_case  =>  snake/case
                          snake-case  =>  snake/case
                          snake case  =>  snake/case
                          snake CASE  =>  snake//case
                          snake.case  =>  snake/case
                    variable_10_case  =>  variable/10/case
                      variable10Case  =>  variable10/case
                        ɛrgo rE tHis  =>  ɛrgo/r/e/t/his
                       hurry-up-joe!  =>  hurry/up/joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my/docs/happy//flag//day/12/doc
                             spaces   =>  spaces
Translation of: Scala
fun main() {
    val variableNames = listOf("snakeCase", "snake_case", "variable_10_case", "variable10Case",
        "ergo rE tHis", "hurry-up-joe!", "c://my-docs/happy_Flag-Day/12.doc", "  spaces  ")

    println(" ".repeat(26) + "=== To snake_case ===")
    variableNames.forEach { text ->
        println("${text.padStart(34)} --> ${toSnakeCase(text)}")
    }

    println("\n" + " ".repeat(26) + "=== To camelCase ===")
    variableNames.forEach { text ->
        println("${text.padStart(34)} --> ${toCamelCase(text)}")
    }
}

fun toSnakeCase(camel: String): String {
    val snake = StringBuilder()
    camel.trim().replace(" ", "_").replace("-", "_").forEach { ch ->
        if (snake.isEmpty() || snake.last() != '_' || ch != '_') {
            if (ch.isUpperCase() && snake.isNotEmpty() && snake.last() != '_') snake.append('_')
            snake.append(ch.toLowerCase())
        }
    }
    return snake.toString()
}

fun toCamelCase(snake: String): String {
    val camel = StringBuilder()
    var underscore = false
    snake.trim().replace(" ", "_").replace("-", "_").forEach { ch ->
        if (ch == '_') {
            underscore = true
        } else if (underscore) {
            camel.append(ch.toUpperCase())
            underscore = false
        } else {
            camel.append(ch)
        }
    }
    return camel.toString()
}
Output:
                          === To snake_case ===
                         snakeCase --> snake_case
                        snake_case --> snake_case
                  variable_10_case --> variable_10_case
                    variable10Case --> variable10_case
                      ergo rE tHis --> ergo_r_e_t_his
                     hurry-up-joe! --> hurry_up_joe!
 c://my-docs/happy_Flag-Day/12.doc --> c://my_docs/happy_flag_day/12.doc
                          spaces   --> spaces

                          === To camelCase ===
                         snakeCase --> snakeCase
                        snake_case --> snakeCase
                  variable_10_case --> variable10Case
                    variable10Case --> variable10Case
                      ergo rE tHis --> ergoRETHis
                     hurry-up-joe! --> hurryUpJoe!
 c://my-docs/happy_Flag-Day/12.doc --> c://myDocs/happyFlagDay/12.doc
                          spaces   --> spaces


{def snake2camel
 {lambda {:w}
  {S.replace (?:_|-)(\w)
          by {span {@ style="text-transform:uppercase;"}$1}
          in :w}}}
-> snake2camel

{def camel2snake
 {lambda {:w}
   {S.replace ([A-Z])
           by _{span {@ style="text-transform:lowercase;"}$1} 
           in :w}}}
-> camel2snake

{S.map snake2camel 
snake_case 
snake-case 
my_brave_new_world 
my_brave-new_world 
... and_so_on
} 
-> snakeCase snakeCase myBraveNewWorld myBraveNewWorld ... andSoOn

{S.map camel2snake 
snakeCase 
myBraveNewWorld 
... andSoOn
}
-> snake_case my_brave_new_world ... and_so_on
Works with: Lua version 5.1 and later

Since the task is a bit vague this solution also has its own interpretation of several details.

We have the two functions toCamelCase() and fromCamelCase() that perform the conversion back and forth between camel case and non-camel case, including snake case. The test strings are assumed to potentially contain multiple names. Any character that isn't part of the matched names (including leading and trailing whitespace) is ignored/left alone. Numbers aren't mentioned in the task but the "variable_10_case"/"variable10Case" strings imply that numbers should be treated as their own words.

local function escapeForPattern(str)
	return (str:gsub("[-+*^?$.%%()[%]]", "%%%0"))
end

local function toCamelCase(str, separator)
	local escapedSeparator = escapeForPattern(separator)
	local namePattern      = "%l%w*"..escapedSeparator.."[%w"..escapedSeparator.."]*%w" -- Starting with a lower case character and containing the separator character.
	local separatorPattern = escapedSeparator.."(%w)" -- Discard the separator and capture the alphanumeric character.

	return (str:gsub(namePattern, function(name)
		return (name:gsub(separatorPattern, string.upper)) -- The captured character will be the one argument for string.upper().
	end))
end

local function fromCamelCase(str, separator)
	local namePattern       = "%l+[%u%d]%w*" -- Starting with a lower case character and containing an upper case character or digit.
	local separatorPattern1 = "(%l)([%u%d])" -- Lower case character followed by upper case character or digit.
	local separatorPattern2 = "(%d)(%a)"     -- Digit followed by alphanumeric character.

	return (str:gsub(namePattern, function(name)
		return (name
			:gsub(separatorPattern1, function(char1,char2)  return char1..separator..char2:lower()  end)
			:gsub(separatorPattern2, function(char1,char2)  return char1..separator..char2:lower()  end)
		)
	end))
end

Tests:

local function utf8Length(str)
	local len = 0
	for char in str:gmatch"[\1-\127\194-\244][\128-\191]*" do
		len = len + 1
	end
	return len
end

local tests = {
	"snakeCase", "snake_case",
	"variable_10_case", "variable10Case",
	"ɛrgo rE tHis",
	"hurry-up-joe!",
	"c://my-docs/happy_Flag-Day/12.doc",
	"  spaces  ",
	"  internal space  ",
}

local function convert(label, converter)
	print(label..":")
	for _, str in ipairs(tests) do
		print((" "):rep(35-utf8Length(str)) .. str .. "  =>  " .. converter(str))
	end
	print()
end

convert("snake_case to camelCase", function(str)  return toCamelCase  (str, "_")  end)
convert("space case to camelCase", function(str)  return toCamelCase  (str, " ")  end)
convert("kebab-case to camelCase", function(str)  return toCamelCase  (str, "-")  end)
convert("camelCase to snake_case", function(str)  return fromCamelCase(str, "_")  end)
Output:
snake_case to camelCase:
                          snakeCase  =>  snakeCase
                         snake_case  =>  snakeCase
                   variable_10_case  =>  variable10Case
                     variable10Case  =>  variable10Case
                       ɛrgo rE tHis  =>  ɛrgo rE tHis
                      hurry-up-joe!  =>  hurry-up-joe!
  c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happyFlag-Day/12.doc
                           spaces    =>    spaces
                   internal space    =>    internal space

space case to camelCase:
                          snakeCase  =>  snakeCase
                         snake_case  =>  snake_case
                   variable_10_case  =>  variable_10_case
                     variable10Case  =>  variable10Case
                       ɛrgo rE tHis  =>  ɛrgoRETHis
                      hurry-up-joe!  =>  hurry-up-joe!
  c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy_Flag-Day/12.doc
                           spaces    =>    spaces
                   internal space    =>    internalSpace

kebab-case to camelCase:
                          snakeCase  =>  snakeCase
                         snake_case  =>  snake_case
                   variable_10_case  =>  variable_10_case
                     variable10Case  =>  variable10Case
                       ɛrgo rE tHis  =>  ɛrgo rE tHis
                      hurry-up-joe!  =>  hurryUpJoe!
  c://my-docs/happy_Flag-Day/12.doc  =>  c://myDocs/happy_FlagDay/12.doc
                           spaces    =>    spaces
                   internal space    =>    internal space

camelCase to snake_case:
                          snakeCase  =>  snake_case
                         snake_case  =>  snake_case
                   variable_10_case  =>  variable_10_case
                     variable10Case  =>  variable_10_case
                       ɛrgo rE tHis  =>  ɛrgo r_e t_his
                      hurry-up-joe!  =>  hurry-up-joe!
  c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy_Flag-Day/12.doc
                           spaces    =>    spaces
                   internal space    =>    internal space

Notes:

  • We don't check if names have preceding alphanumeric characters (e.g. "10kN" will have the name "kN").
  • We don't handle consecutive upper case characters (e.g. "newUIBox").
  • We don't handle non-ASCII characters because of Lua's limited support for them ("ɛ" just happen to work here).


Translation of: Python
(* String case conversion functions in Mathematica *)

snakeToCamelCase[nam_String, sep_String : "[_]+", lcmiddle_ : False] := Module[{words},
  If[nam == "", Return[nam]];
  words = StringSplit[StringTrim[nam], RegularExpression[sep]];
  If[lcmiddle, words = ToLowerCase /@ words];
  words[[2 ;;]] = StringJoin[ToUpperCase[StringTake[#, 1]], StringDrop[#, 1]] & /@ Select[words[[2 ;;]], StringLength[#] > 0 &];
  StringJoin[words]
]

spaceToCamelCase[nam_String] := snakeToCamelCase[nam, "\\s+"]

kebabToCamelCase[nam_String] := snakeToCamelCase[nam, "[\\-]+"]

periodToCamelCase[nam_String] := snakeToCamelCase[nam, "[\\.]+"]

allsepToCamelCase[nam_String] := snakeToCamelCase[nam, "[ \\-_\\.]+"]

lowermiddleAllsepToCamelCase[nam_String] := snakeToCamelCase[nam, "[ \\-_\\.]+", True]

camelToSnakeCase[nam_String, sep_String : "_", allsep_String : "[_]+", lcmiddle_ : True] := Module[{result, sep1, words},
  result = StringReplace[StringTrim[nam], RegularExpression["([A-Z]+)"] -> sep <> "$1"];
  sep1 = If[sep == ".", "\\.", sep];
  If[lcmiddle,
    words = Select[StringSplit[result, sep1], StringLength[#] > 0 &];
    result = StringRiffle[ToLowerCase /@ words, sep],
    words = Select[StringSplit[result, sep1], StringLength[#] > 0 &];
    result = StringRiffle[StringJoin[ToLowerCase[StringTake[#, 1]], StringDrop[#, 1]] & /@ words, sep]
  ];
  StringReplace[result, RegularExpression[allsep] -> sep]
]

preserveMidcapsCamelToSnakeCase[nam_String] := camelToSnakeCase[nam, "_", "[_]+", False]

allsepToSnakeCase[nam_String] := camelToSnakeCase[nam, "_", "[ \\-\\._]+"]

allsepToKebabCase[nam_String] := camelToSnakeCase[nam, "-", "[ \\-\\._]+"]

allsepToSpaceCase[nam_String] := camelToSnakeCase[nam, " ", "[ \\-\\._]+"]

allsepToPeriodCase[nam_String] := camelToSnakeCase[nam, ".", "[ \\-\\._]+"]

allsepToSlashCase[nam_String] := camelToSnakeCase[nam, "/", "[ \\-\\._]+"]

(* Test the functions *)
testFunctions = {
  snakeToCamelCase,
  spaceToCamelCase,
  kebabToCamelCase,
  periodToCamelCase,
  allsepToCamelCase,
  lowermiddleAllsepToCamelCase,
  camelToSnakeCase,
  preserveMidcapsCamelToSnakeCase,
  allsepToSnakeCase,
  allsepToKebabCase,
  allsepToSpaceCase,
  allsepToPeriodCase,
  allsepToSlashCase
};

testStrings = {
  "snakeCase",
  "snake_case",
  "snake-case",
  "snake case",
  "snake CASE",
  "snake.case",
  "variable_10_case",
  "variable10Case",
  "ɛrgo rE tHis",
  "hurry-up-joe!",
  "c://my-docs/happy_Flag-Day/12.doc",
  " spaces "
};

Do[
  Print["Testing function ", f, ":"];
  Do[
    Print[StringPadLeft[testString, 36], " => ", f[testString]],
    {testString, testStrings}
  ];
  Print[""],
  {f, testFunctions}
]
Output:
Testing function snakeToCamelCase:
                           snakeCase => snakeCase
                          snake_case => snakeCase
                          snake-case => snake-case
                          snake case => snake case
                          snake CASE => snake CASE
                          snake.case => snake.case
                    variable_10_case => variable10Case
                      variable10Case => variable10Case
                        \:025brgo rE tHis => \:025brgo rE tHis
                       hurry-up-joe! => hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc => c://my-docs/happyFlag-Day/12.doc
                             spaces  => spaces

Testing function spaceToCamelCase:
                           snakeCase => snakeCase
                          snake_case => snake_case
                          snake-case => snake-case
                          snake case => snakeCase
                          snake CASE => snakeCASE
                          snake.case => snake.case
                    variable_10_case => variable_10_case
                      variable10Case => variable10Case
                        \:025brgo rE tHis => \:025brgoRETHis
                       hurry-up-joe! => hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc => c://my-docs/happy_Flag-Day/12.doc
                             spaces  => spaces

Testing function kebabToCamelCase:
                           snakeCase => snakeCase
                          snake_case => snake_case
                          snake-case => snakeCase
                          snake case => snake case
                          snake CASE => snake CASE
                          snake.case => snake.case
                    variable_10_case => variable_10_case
                      variable10Case => variable10Case
                        \:025brgo rE tHis => \:025brgo rE tHis
                       hurry-up-joe! => hurryUpJoe!
   c://my-docs/happy_Flag-Day/12.doc => c://myDocs/happy_FlagDay/12.doc
                             spaces  => spaces

Testing function periodToCamelCase:
                           snakeCase => snakeCase
                          snake_case => snake_case
                          snake-case => snake-case
                          snake case => snake case
                          snake CASE => snake CASE
                          snake.case => snakeCase
                    variable_10_case => variable_10_case
                      variable10Case => variable10Case
                        \:025brgo rE tHis => \:025brgo rE tHis
                       hurry-up-joe! => hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc => c://my-docs/happy_Flag-Day/12Doc
                             spaces  => spaces

Testing function allsepToCamelCase:
                           snakeCase => snakeCase
                          snake_case => snakeCase
                          snake-case => snakeCase
                          snake case => snakeCase
                          snake CASE => snakeCASE
                          snake.case => snakeCase
                    variable_10_case => variable10Case
                      variable10Case => variable10Case
                        \:025brgo rE tHis => \:025brgoRETHis
                       hurry-up-joe! => hurryUpJoe!
   c://my-docs/happy_Flag-Day/12.doc => c://myDocs/happyFlagDay/12Doc
                             spaces  => spaces

Testing function lowermiddleAllsepToCamelCase:
                           snakeCase => snakecase
                          snake_case => snakeCase
                          snake-case => snakeCase
                          snake case => snakeCase
                          snake CASE => snakeCase
                          snake.case => snakeCase
                    variable_10_case => variable10Case
                      variable10Case => variable10case
                        \:025brgo rE tHis => \:025brgoReThis
                       hurry-up-joe! => hurryUpJoe!
   c://my-docs/happy_Flag-Day/12.doc => c://myDocs/happyFlagDay/12Doc
                             spaces  => spaces

Testing function camelToSnakeCase:
                           snakeCase => snake_case
                          snake_case => snake_case
                          snake-case => snake-case
                          snake case => snake case
                          snake CASE => snake _case
                          snake.case => snake.case
                    variable_10_case => variable_10_case
                      variable10Case => variable10_case
                        \:025brgo rE tHis => \:025brgo r_e t_his
                       hurry-up-joe! => hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc => c://my-docs/happy_flag-_day/12.doc
                             spaces  => spaces

Testing function preserveMidcapsCamelToSnakeCase:
                           snakeCase => snake_case
                          snake_case => snake_case
                          snake-case => snake-case
                          snake case => snake case
                          snake CASE => snake _cASE
                          snake.case => snake.case
                    variable_10_case => variable_10_case
                      variable10Case => variable10_case
                        \:025brgo rE tHis => \:025brgo r_e t_his
                       hurry-up-joe! => hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc => c://my-docs/happy_flag-_day/12.doc
                             spaces  => spaces

Testing function allsepToSnakeCase:
                           snakeCase => snake_case
                          snake_case => snake_case
                          snake-case => snake_case
                          snake case => snake_case
                          snake CASE => snake_case
                          snake.case => snake_case
                    variable_10_case => variable_10_case
                      variable10Case => variable10_case
                        \:025brgo rE tHis => \:025brgo_r_e_t_his
                       hurry-up-joe! => hurry_up_joe!
   c://my-docs/happy_Flag-Day/12.doc => c://my_docs/happy_flag_day/12_doc
                             spaces  => spaces

Testing function allsepToKebabCase:
                           snakeCase => snake-case
                          snake_case => snake-case
                          snake-case => snake-case
                          snake case => snake-case
                          snake CASE => snake-case
                          snake.case => snake-case
                    variable_10_case => variable-10-case
                      variable10Case => variable10-case
                        \:025brgo rE tHis => \:025brgo-r-e-t-his
                       hurry-up-joe! => hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc => c://my-docs/happy-flag-day/12-doc
                             spaces  => spaces

Testing function allsepToSpaceCase:
                           snakeCase => snake case
                          snake_case => snake case
                          snake-case => snake case
                          snake case => snake case
                          snake CASE => snake case
                          snake.case => snake case
                    variable_10_case => variable 10 case
                      variable10Case => variable10 case
                        \:025brgo rE tHis => \:025brgo r e t his
                       hurry-up-joe! => hurry up joe!
   c://my-docs/happy_Flag-Day/12.doc => c://my docs/happy flag day/12 doc
                             spaces  => spaces

Testing function allsepToPeriodCase:
                           snakeCase => snake.case
                          snake_case => snake.case
                          snake-case => snake.case
                          snake case => snake.case
                          snake CASE => snake.case
                          snake.case => snake.case
                    variable_10_case => variable.10.case
                      variable10Case => variable10.case
                        \:025brgo rE tHis => \:025brgo.r.e.t.his
                       hurry-up-joe! => hurry.up.joe!
   c://my-docs/happy_Flag-Day/12.doc => c://my.docs/happy.flag.day/12.doc
                             spaces  => spaces

Testing function allsepToSlashCase:
                           snakeCase => snake/case
                          snake_case => snake/case
                          snake-case => snake/case
                          snake case => snake/case
                          snake CASE => snake//case
                          snake.case => snake/case
                    variable_10_case => variable/10/case
                      variable10Case => variable10/case
                        \:025brgo rE tHis => \:025brgo/r/e/t/his
                       hurry-up-joe! => hurry/up/joe!
   c://my-docs/happy_Flag-Day/12.doc => c:/my/docs/happy//flag//day/12/doc
                             spaces  => spaces


We use the same rules as those used by Wren's solution.

import std/[strformat, strutils, unicode]

const Delimiters = [Rune('_'), Rune('-'), Rune(' ')]

func toCamelCase(s: string): string =
  let s = s.strip(chars = Whitespace)
  var prev = Rune(0)
  for rune in s.runes:
    if prev in Delimiters:
      result.add rune.toUpper
    elif rune notin Delimiters:
      result.add rune
    prev = rune

func toSnakeCase(s: string): string =
  var s= s.strip(chars = Whitespace).replace(' ', '_')
  var idx = 0
  var prev =  Rune(0)
  for rune in s.runes:
    if rune.isUpper and idx > 0:
      if prev notin Delimiters:
        result.add '_'
      result.add rune.toLower
    else:
      result.add rune
    prev = rune
    inc idx

const Strings = ["snakeCase", "snake_case", "variable_10_case",
                 "variable10Case", "ɛrgo rE tHis", "hurry-up-joe!",
                 "c://my-docs/happy_Flag-Day/12.doc", "  spaces  "]

echo center("### To snake case ###", 69)
for s in Strings:
  echo &"{s:>33} → {s.toSnakeCase}"

echo()
echo center("### To camel case ###", 69)
for s in Strings:
  echo &"{s:>33} → {s.toCamelCase}"
Output:
                        ### To snake case ###                        
                        snakeCase → snake_case
                       snake_case → snake_case
                 variable_10_case → variable_10_case
                   variable10Case → variable10_case
                     ɛrgo rE tHis → ɛrgo_r_e_t_his
                    hurry-up-joe! → hurry-up-joe!
c://my-docs/happy_Flag-Day/12.doc → c://my-docs/happy_flag-day/12.doc
                         spaces   → spaces

                        ### To camel case ###                        
                        snakeCase → snakeCase
                       snake_case → snakeCase
                 variable_10_case → variable10Case
                   variable10Case → variable10Case
                     ɛrgo rE tHis → ɛrgoRETHis
                    hurry-up-joe! → hurryUpJoe!
c://my-docs/happy_Flag-Day/12.doc → c://myDocs/happyFlagDay/12.doc
                         spaces   → spaces
define stream function to_snake_case (value stream txt) as
  local stream ls
  open ls as buffer
  repeat scan txt
    match white-space* value-end
      ; "trailing whitespace may be ignored"
    match value-start white-space*
      ; "leading ... whitespace may be ignored"
    match (lc | digit) => char1 uc => char2
      put ls '%x(char1)_%lx(char2)'
    match ('_' | space | "-" | '.')
      ; normalise to underscore and lowercase letter
      put ls '_'
    match any => char
      ; all other characters are lowercase
      put ls '%lx(char)'
  again
  close ls
  return ls

define stream function toCamelCase (value stream txt) as
  local stream ls
  open ls as buffer
  repeat scan txt
    match white-space* value-end
      ; "trailing whitespace may be ignored"
    match value-start white-space* letter+ => word1
      ; "leading ... whitespace may be ignored"
      put ls word1
    match ('_' | space | "-" | '.') any => makeUpper
      ; consume dividing underscore, space, hyphen or full stop
      put ls '%ux(makeUpper)'
    match ([digit] letter) => chars
      ; a letter preceded by a numeral should be uppercase
      put ls '%ux(chars)'
    match any => char
      ; all other characters are lowercase
      put ls '%lx(char)'
  again
  close ls
  return ls

process
  local stream ls variable initial {"snakeCase", "snake_case",
  "variable_10_case", "variable10Case",
  "ɛrgo rE tHis", "hurry-up-joe!", "c://my-docs/happy_Flag-Day/12.doc",
  "  spaces  "}
  output 'to_snake_case%n'
  output '=============%n'
  repeat over ls
    output ls || ' => ' || to_snake_case(ls) || '%n'
  again
  output '%n'
  output 'toCamelCase%n'
  output '===========%n'
  repeat over ls
    output ls || ' => ' || toCamelCase(ls) || '%n'
  again
Output:
to_snake_case
=============
snakeCase => snake_case
snake_case => snake_case
variable_10_case => variable_10_case
variable10Case => variable10_case
ɛrgo rE tHis => ɛrgo_r_e_t_his
hurry-up-joe! => hurry_up_joe!
c://my-docs/happy_Flag-Day/12.doc => c://my_docs/happy_flag_day/12_doc
  spaces   => spaces

toCamelCase
===========
snakeCase => snakeCase
snake_case => snakeCase
variable_10_case => variable10Case
variable10Case => variable10Case
ɛrgo rE tHis => ɛrgoReThis
hurry-up-joe! => hurryUpJoe!
c://my-docs/happy_Flag-Day/12.doc => c://myDocs/happyFlagDay/12Doc
  spaces   => spaces
#!/usr/bin/perl

use strict; # https://rosettacode.org/wiki/Camel_case_and_snake_case
use warnings;

my @words = (  
  "snakeCase", "snake_case", "variable_10_case", "variable10Case", "#rgo rE tHis",
  "hurry-up-joe!", "c://my-docs/happy_Flag-Day/12.doc", "  spaces  "
   );

sub tosnake
  {
  shift =~ s/^ +| +$//gr =~ s/[A-Z]/_\l$&/gr =~ tr/ -/_/r =~ s/__+/_/gr;
  }

sub tocamel
  {
  shift =~ s/^ +| +$//gr =~ s/[ _-]([a-z0-9])/\u$1/gir;
  }

print "to snake case\n\n";
for my $word ( @words )
  {
  printf "%35s -> %s\n", $word, tosnake($word);
  }

print "\nto camel case\n\n";
for my $word ( @words )
  {
  printf "%35s -> %s\n", $word, tocamel($word);
  }
Output:
to snake case

                          snakeCase -> snake_case
                         snake_case -> snake_case
                   variable_10_case -> variable_10_case
                     variable10Case -> variable10_case
                       #rgo rE tHis -> #rgo_r_e_t_his
                      hurry-up-joe! -> hurry_up_joe!
  c://my-docs/happy_Flag-Day/12.doc -> c://my_docs/happy_flag_day/12.doc
                           spaces   -> spaces

to camel case

                          snakeCase -> snakeCase
                         snake_case -> snakeCase
                   variable_10_case -> variable10Case
                     variable10Case -> variable10Case
                       #rgo rE tHis -> #rgoRETHis
                      hurry-up-joe! -> hurryUpJoe!
  c://my-docs/happy_Flag-Day/12.doc -> c://myDocs/happyFlagDay/12.doc
                           spaces   -> spaces
with javascript_semantics
function to_snake_case(string s)
    string snake = substitute(trim(s)," ","_")
    for i=length(snake) to 1 by -1 do
        if isupper(snake[i]) then
            snake[i..i] = '_'&lower(snake[i])
        end if
    end for
    return snake
end function

function toCamelCase(string s)
    string camel = substitute_all(trim(s),"- ","__")
    for i=length(camel)-1 to 1 by -1 do
        if camel[i]='_' then
            camel[i..i+1] = upper(camel[i+1..i+1])
        end if
    end for
    return camel
end function
 
constant tests = {"snakeCase", "snake_case", "variable_10_case", "variable10Case", "ergo rE tHis",
                  "hurry-up-joe!", "c://my-docs/happy_Flag-Day/12.doc", "  spaces  "}
procedure test(string title, integer fn)
    printf(1,title)
    for i=1 to length(tests) do
        printf(1,"%33s ===> %s\n", {tests[i], fn(tests[i])})
    end for
end procedure
test("                          === to_snake_case ===\n",to_snake_case)
test("\n                          === toCamelCase ===\n",toCamelCase)
Output:
                          === to_snake_case ===
                        snakeCase ===> snake_case
                       snake_case ===> snake_case
                 variable_10_case ===> variable_10_case
                   variable10Case ===> variable10_case
                     ergo rE tHis ===> ergo_r_e_t_his
                    hurry-up-joe! ===> hurry-up-joe!
c://my-docs/happy_Flag-Day/12.doc ===> c://my-docs/happy__flag-_day/12.doc
                         spaces   ===> spaces

                          === toCamelCase ===
                        snakeCase ===> snakeCase
                       snake_case ===> snakeCase
                 variable_10_case ===> variable10Case
                   variable10Case ===> variable10Case
                     ergo rE tHis ===> ergoRETHis
                    hurry-up-joe! ===> hurryUpJoe!
c://my-docs/happy_Flag-Day/12.doc ===> c://myDocs/happyFlagDay/12.doc
                         spaces   ===> spaces
Translation of: Wren
Library: Pluto-fmt
local fmt = require "fmt"

local function to_camel(snake)
    snake = snake:strip()
    local camel = ""
    local underscore = false
    for i = 1, #snake do
        local c = snake[i]
        if c in "_- " then
            underscore = true
        elseif underscore then
            camel ..= c:upper()
            underscore = false
        else
            camel ..= c
        end
    end
    return camel
end

local function to_snake(camel)
    camel = camel:strip():replace(" ", "_")  -- we don't want any spaces in the result
    local snake = ""
    local first = true
    for i = 1, #camel do
        local c = camel[i]
        if first then
            snake ..= c
            first = false
        elseif !first and "A" <= c <= "Z" then
            if snake[-1] == "_" or snake[-1] == "-" then
                snake ..= c:lower()
            else
                snake ..= "_" .. c:lower()
            end
        else
            snake ..= c
        end
    end
    return snake
end

local tests = {
    "snakeCase", "snake_case", "variable_10_case", "variable10Case", "ɛrgo rE tHis",
    "hurry-up-joe!", "c://my-docs/happy_Flag-Day/12.doc", "  spaces  "
}

print("                          === to_snake_case ===")
for tests as camel do
    fmt.print("%s -> %s", fmt.lpad(camel, 33), to_snake(camel))
end

print("\n                         === toCamelCase ===")
for tests as snake do
    fmt.print("%s -> %s", fmt.lpad(snake, 33), to_camel(snake))
end
Output:
                          === to_snake_case ===
                        snakeCase -> snake_case
                       snake_case -> snake_case
                 variable_10_case -> variable_10_case
                   variable10Case -> variable10_case
                     ɛrgo rE tHis -> ɛrgo_r_e_t_his
                    hurry-up-joe! -> hurry-up-joe!
c://my-docs/happy_Flag-Day/12.doc -> c://my-docs/happy_flag-day/12.doc
                         spaces   -> spaces

                         === toCamelCase ===
                        snakeCase -> snakeCase
                       snake_case -> snakeCase
                 variable_10_case -> variable10Case
                   variable10Case -> variable10Case
                     ɛrgo rE tHis -> ɛrgoRETHis
                    hurry-up-joe! -> hurryUpJoe!
c://my-docs/happy_Flag-Day/12.doc -> c://myDocs/happyFlagDay/12.doc
                         spaces   -> spaces
""" https://rosettacode.org/wiki/Camel_case_and_snake_case """

import re

def snakeToCamelCase(nam, sep='[_]+', lcmiddle=False):
    """ convert snake '_' separator case to camel case """
    if nam == '':
        return nam
    words = re.split(sep, nam.strip())
    if lcmiddle:
        words = [w.lower() for w in words]
    words[1:] = [w[0].upper() + w[1:] for w in words[1:] if len(w) > 0]
    return ''.join(words)


def spaceToCamelCase(nam):
    """ convert space case to camel case """
    return snakeToCamelCase(nam, sep='\s+')

def kebabToCamelCase(nam):
    """ convert kebab '-' case to camel case """
    return snakeToCamelCase(nam, sep='[\-]+')

def periodToCamelCase(nam):
    """ convert period '.' case to camel case """
    return snakeToCamelCase(nam, sep='[\.]+')

def allsepToCamelCase(nam):
    """ convert all separators in allsep to camel case """
    return snakeToCamelCase(nam, sep='[ \-_\.]+')

def lowermiddle_allsepToCamelCase(nam):
    """ convert all separators to camel case, and all but word starts to lowercase """
    return snakeToCamelCase(nam, sep='[ \-_\.]+', lcmiddle=True)

def camel_to_snake_case(nam, sep='_', allsep='[_]+', lcmiddle=True):
    """ convert camel case to snake case (separate with '_') """
    nam = re.sub('([A-Z]+)', sep + r"\1", nam.strip())
    sep1 = '\\' + sep if sep == '.' else sep
    if lcmiddle:
        nam = sep.join([w.lower() for w in nam.split(sep1) if len(w) > 0])
    else:
        nam = sep.join([w[0].lower() + w[1:] for w in nam.split(sep1) if len(w) > 0])
    return re.sub(allsep, sep, nam)

def preserve_midcaps_camel_to_snake_case(nam):
    return camel_to_snake_case(nam, lcmiddle=False)

def allsep_to_snake_case(nam):
    return camel_to_snake_case(nam, allsep='[ \-\._]+')

def allsep_to_kebab_case(nam):
    return camel_to_snake_case(nam, allsep='[ \-\._]+', sep='-')

def allsep_to_space_case(nam):
    return camel_to_snake_case(nam, allsep='[ \-\._]+', sep=' ')

def allsep_to_period_case(nam):
    return camel_to_snake_case(nam, allsep='[ \-\._]+', sep='.')

def allsep_to_slash_case(nam):
    return camel_to_snake_case(nam, allsep='[ \-\._]+', sep='/')

for f in [
    snakeToCamelCase,
    spaceToCamelCase,
    kebabToCamelCase,
    periodToCamelCase,
    allsepToCamelCase,
    lowermiddle_allsepToCamelCase,
    camel_to_snake_case,
    preserve_midcaps_camel_to_snake_case,
    allsep_to_snake_case,
    allsep_to_kebab_case,
    allsep_to_space_case,
    allsep_to_period_case,
    allsep_to_slash_case]:
    print(f"Testing function {f}:")
    for teststring in [
        "snakeCase",
        "snake_case",
        "snake-case",
        "snake case",
        "snake CASE",
        "snake.case",
        "variable_10_case",
        "variable10Case",
        "ɛrgo rE tHis",
        "hurry-up-joe!",
        "c://my-docs/happy_Flag-Day/12.doc",
        " spaces "]:
        print(teststring.rjust(36), " => ", f(teststring))
    print()
Output:
Testing function <function snakeToCamelCase at 0x000001F17C25AC10>:
                           snakeCase  =>  snakeCase
                          snake_case  =>  snakeCase
                          snake-case  =>  snake-case
                          snake case  =>  snake case
                          snake CASE  =>  snake CASE
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable10Case
                      variable10Case  =>  variable10Case
                        ɛrgo rE tHis  =>  ɛrgo rE tHis
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happyFlag-Day/12.doc
                             spaces   =>  spaces

Testing function <function spaceToCamelCase at 0x000001F17C25AA60>:
                           snakeCase  =>  snakeCase
                          snake_case  =>  snake_case
                          snake-case  =>  snake-case
                          snake case  =>  snakeCase
                          snake CASE  =>  snakeCASE
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10Case
                        ɛrgo rE tHis  =>  ɛrgoRETHis
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy_Flag-Day/12.doc
                             spaces   =>  spaces

Testing function <function kebabToCamelCase at 0x000001F17C25ADC0>:
                           snakeCase  =>  snakeCase
                          snake_case  =>  snake_case
                          snake-case  =>  snakeCase
                          snake case  =>  snake case
                          snake CASE  =>  snake CASE
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10Case
                        ɛrgo rE tHis  =>  ɛrgo rE tHis
                       hurry-up-joe!  =>  hurryUpJoe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://myDocs/happy_FlagDay/12.doc
                             spaces   =>  spaces

Testing function <function periodToCamelCase at 0x000001F17C25AE50>:
                           snakeCase  =>  snakeCase
                          snake_case  =>  snake_case
                          snake-case  =>  snake-case
                          snake case  =>  snake case
                          snake CASE  =>  snake CASE
                          snake.case  =>  snakeCase
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10Case
                        ɛrgo rE tHis  =>  ɛrgo rE tHis
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy_Flag-Day/12Doc
                             spaces   =>  spaces

Testing function <function allsepToCamelCase at 0x000001F17C25AEE0>:
                           snakeCase  =>  snakeCase
                          snake_case  =>  snakeCase
                          snake-case  =>  snakeCase
                          snake case  =>  snakeCase
                          snake CASE  =>  snakeCASE
                          snake.case  =>  snakeCase
                    variable_10_case  =>  variable10Case
                      variable10Case  =>  variable10Case
                        ɛrgo rE tHis  =>  ɛrgoRETHis
                       hurry-up-joe!  =>  hurryUpJoe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://myDocs/happyFlagDay/12Doc
                             spaces   =>  spaces

Testing function <function lowermiddle_allsepToCamelCase at 0x000001F17C25AF70>:
                           snakeCase  =>  snakecase
                          snake_case  =>  snakeCase
                          snake-case  =>  snakeCase
                          snake case  =>  snakeCase
                          snake CASE  =>  snakeCase
                          snake.case  =>  snakeCase
                    variable_10_case  =>  variable10Case
                      variable10Case  =>  variable10case
                        ɛrgo rE tHis  =>  ɛrgoReThis
                       hurry-up-joe!  =>  hurryUpJoe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://myDocs/happyFlagDay/12Doc
                             spaces   =>  spaces

Testing function <function camel_to_snake_case at 0x000001F17C262040>:
                           snakeCase  =>  snake_case
                          snake_case  =>  snake_case
                          snake-case  =>  snake-case
                          snake case  =>  snake case
                          snake CASE  =>  snake _case
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10_case
                        ɛrgo rE tHis  =>  ɛrgo r_e t_his
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy_flag-_day/12.doc
                             spaces   =>  spaces

Testing function <function preserve_midcaps_camel_to_snake_case at 0x000001F17C2620D0>:
                           snakeCase  =>  snake_case
                          snake_case  =>  snake_case
                          snake-case  =>  snake-case
                          snake case  =>  snake case
                          snake CASE  =>  snake _cASE
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10_case
                        ɛrgo rE tHis  =>  ɛrgo r_e t_his
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy_flag-_day/12.doc
                             spaces   =>  spaces

Testing function <function allsep_to_snake_case at 0x000001F17C262160>:
                           snakeCase  =>  snake_case
                          snake_case  =>  snake_case
                          snake-case  =>  snake_case
                          snake case  =>  snake_case
                          snake CASE  =>  snake_case
                          snake.case  =>  snake_case
                    variable_10_case  =>  variable_10_case
                      variable10Case  =>  variable10_case
                        ɛrgo rE tHis  =>  ɛrgo_r_e_t_his
                       hurry-up-joe!  =>  hurry_up_joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my_docs/happy_flag_day/12_doc
                             spaces   =>  spaces

Testing function <function allsep_to_kebab_case at 0x000001F17C2621F0>:
                           snakeCase  =>  snake-case
                          snake_case  =>  snake-case
                          snake-case  =>  snake-case
                          snake case  =>  snake-case
                          snake CASE  =>  snake-case
                          snake.case  =>  snake-case
                    variable_10_case  =>  variable-10-case
                      variable10Case  =>  variable10-case
                        ɛrgo rE tHis  =>  ɛrgo-r-e-t-his
                       hurry-up-joe!  =>  hurry-up-joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my-docs/happy-flag-day/12-doc
                             spaces   =>  spaces

Testing function <function allsep_to_space_case at 0x000001F17C262280>:
                           snakeCase  =>  snake case
                          snake_case  =>  snake case
                          snake-case  =>  snake case
                          snake case  =>  snake case
                          snake CASE  =>  snake case
                          snake.case  =>  snake case
                    variable_10_case  =>  variable 10 case
                      variable10Case  =>  variable10 case
                        ɛrgo rE tHis  =>  ɛrgo r e t his
                       hurry-up-joe!  =>  hurry up joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my docs/happy flag day/12 doc
                             spaces   =>  spaces

Testing function <function allsep_to_period_case at 0x000001F17C262310>:
                           snakeCase  =>  snake.case
                          snake_case  =>  snake.case
                          snake-case  =>  snake.case
                          snake case  =>  snake.case
                          snake CASE  =>  snake.case
                          snake.case  =>  snake.case
                    variable_10_case  =>  variable.10.case
                      variable10Case  =>  variable10.case
                        ɛrgo rE tHis  =>  ɛrgo.r.e.t.his
                       hurry-up-joe!  =>  hurry.up.joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c://my.docs/happy.flag.day/12.doc
                             spaces   =>  spaces

Testing function <function allsep_to_slash_case at 0x000001F17C2623A0>:
                           snakeCase  =>  snake/case
                          snake_case  =>  snake/case
                          snake-case  =>  snake/case
                          snake case  =>  snake/case
                          snake CASE  =>  snake//case
                          snake.case  =>  snake/case
                    variable_10_case  =>  variable/10/case
                      variable10Case  =>  variable10/case
                        ɛrgo rE tHis  =>  ɛrgo/r/e/t/his
                       hurry-up-joe!  =>  hurry/up/joe!
   c://my-docs/happy_Flag-Day/12.doc  =>  c:/my/docs/happy//flag//day/12/doc
                             spaces   =>  spaces
  [ $ "_ -" find 3 < ]        is separator ( c --> b )

  [ dup lower != ]            is capital   ( c --> b )

  [ 2 times [ reverse trim ]
    $ "" false rot
    witheach
      [ dup separator iff
          [ 2drop true ]
        else
          [ over if upper
            swap dip join
            drop false ] ]
    drop ]                    is camelise  ( $ --> $ )

  [ camelise
    $ "" swap
    witheach
      [ dup capital if
          [ dip
            [ char _ join ] ]
        lower join ] ]        is snakify   ( $ --> $ )
Output:

Testing in the shell.

/O> ' [ $ "snakeCase"
...     $ "snake_case"
...     $ "variable_10_case"
...     $ "variable10Case"
...     $ "ergo rE tHis"
...     $ "hurry-up-joe!"
...     $ "c://my-docs/happy_Flag-Day/12.doc"
...     $ "  spaces  " ]
... dup
... say "To camelCase:" cr
... witheach [ do camelise say "   " echo$ cr ]
... cr
... say "To snake_case:" cr
... witheach [ do snakify say "   " echo$ cr ]
... 
To camelCase:
   snakeCase
   snakeCase
   variable10Case
   variable10Case
   ergoRETHis
   hurryUpJoe!
   c://myDocs/happyFlagDay/12.doc
   spaces

To snake_case:
   snake_case
   snake_case
   variable10_case
   variable10_case
   ergo_r_e_t_his
   hurry_up_joe!
   c://my_docs/happy_flag_day/12.doc
   spaces

Stack empty.

R

test_strings <- c(
  "snakeCase", "snake_case", "variable_10_case", 
  "variable10Case", "ɛrgo rE tHis", "hurry-up-joe!",
  "c://my-docs/happy_Flag-Day/12.doc", "  spaces  "
)

titles <- c(
  "Snake to camel case:", "Camel to snake case:",
  "Any separator to camel case:", "Any separator to snake case:"
)

#Simple functions
snake2camel <- function(s) {
  boundaries <- gregexpr("_+[^_]", s) |>
    regmatches(s, m = _) |>
    unlist() |>
    gsub("_", "", x = _)
  for (b in boundaries) {
    s <- gsub(paste0("_+", b), toupper(b), s)
  }
  return(s)
}

camel2snake <- function(s) {
  boundaries <- gregexpr("[A-Z]", s) |>
    regmatches(s, m = _) |>
    unlist()
  for (b in boundaries) {
    s <- gsub(b, paste0("_", tolower(b)), s)
  }
  return(s)
}

#More general functions
any2camel <- function(s) {
  #strip leading and trailing whitespace
  s <- trimws(s)
  #Deal with specified separators
  boundaries <- gregexpr("[ _-]+[^ _-]", s) |>
    regmatches(s, m = _) |>
    unlist() |>
    gsub("[ _-]", "", x = _)
  for (b in boundaries) {
    s <- gsub(paste0("[ _-]+", b), toupper(b), s)
  }
  return(s)
}

any2snake <- function(s) {
  s <- trimws(s)
  boundaries <- function(regexp) {
    gregexpr(regexp, s) |>
    regmatches(s, m = _) |>
    unlist()
  }
  for (b in boundaries("[A-Z]")) {
    s <- gsub(b, paste0("_", tolower(b)), s)
  }
  for (b in boundaries("[ -]+")) {
    s <- gsub(b, "_", s)
  }
  return(s)
}

funs <- c(snake2camel, camel2snake, any2camel, any2snake)
for (i in 1:4) {
  writeLines(c(titles[i], funs[[i]](test_strings), ""))
}
Output:
Snake to camel case:
snakeCase
snakeCase
variable10Case
variable10Case
ɛrgo rE tHis
hurry-up-joe!
c://my-docs/happyFlag-Day/12.doc
  spaces

Camel to snake case:
snake_case
snake_case
variable_10_case
variable10_case
ɛrgo r_e t_his
hurry-up-joe!
c://my-docs/happy__flag-_day/12.doc
  spaces

Any separator to camel case:
snakeCase
snakeCase
variable10Case
variable10Case
ɛrgoRETHis
hurryUpJoe!
c://myDocs/happyFlagDay/12.doc
spaces 

Any separator to snake case:
snake_case
snake_case
variable_10_case
variable10_case
ɛrgo_r_e_t_his
hurry_up_joe!
c://my_docs/happy__flag__day/12.doc
spaces  
#lang racket

(define input '("snakeCase" "snake_case" "variable_10_case" "variable10Case" "ɛrgo rE tHis" "hurry-up-joe!" "c://my-docs/happy_Flag-Day/12.doc" "  spaces  "))

;; make '-' the canonical separator by replacing '_' and ' ' with '-'
(define (dashify s)
  (regexp-replace* #px"[_ ]" s "-"))

;; replace -X with -x for any upper-case X
(define (dash-upper->dash-lower s)
  (regexp-replace* #px"-[[:upper:]]" s string-downcase))

;; replace X with -x for any upper-case X
(define (upper->dash-lower s)
  (regexp-replace* #px"[[:upper:]]"
                   s
                   (λ (s) (string-append "-" (string-downcase s)))))

(define (string-kebabcase s)
  (upper->dash-lower (dash-upper->dash-lower (dashify s))))

(define (string-snakecase s)
  ;; once we have kebabcase, snakecase is easy, just change '-' to '_'
  (regexp-replace* #px"-" (string-kebabcase s) "_"))

(define (string-camelcase s)
  ;; camel is pretty easy, too - replace dash-anything with uppercase-anything
  ;; note: this will change non-letters as well, so -10 becomes just 10
  (regexp-replace* #px"-." (string-kebabcase s) (λ (s) (string-upcase (substring s 1 2)))))

(define (convert-case to-case case-name namelist)
  (printf "Conversions to ~a:~n" case-name)
  (for ([name namelist])
    (printf "'~a' --> '~a'~n" name (to-case (string-trim name))))
  (printf "~n"))

(convert-case string-kebabcase "kebab-case" input)
(convert-case string-snakecase "snake_case" input)
(convert-case string-camelcase "camelCase" input)
Output:
Conversions to kebab-case:
'snakeCase' --> 'snake-case'
'snake_case' --> 'snake-case'
'variable_10_case' --> 'variable-10-case'
'variable10Case' --> 'variable10-case'
'ɛrgo rE tHis' --> 'ɛrgo-r-e-t-his'
'hurry-up-joe!' --> 'hurry-up-joe!'
'c://my-docs/happy_Flag-Day/12.doc' --> 'c://my-docs/happy-flag-day/12.doc'
'  spaces  ' --> 'spaces'

Conversions to snake_case:
'snakeCase' --> 'snake_case'
'snake_case' --> 'snake_case'
'variable_10_case' --> 'variable_10_case'
'variable10Case' --> 'variable10_case'
'ɛrgo rE tHis' --> 'ɛrgo_r_e_t_his'
'hurry-up-joe!' --> 'hurry_up_joe!'
'c://my-docs/happy_Flag-Day/12.doc' --> 'c://my_docs/happy_flag_day/12.doc'
'  spaces  ' --> 'spaces'

Conversions to camelCase:
'snakeCase' --> 'snakeCase'
'snake_case' --> 'snakeCase'
'variable_10_case' --> 'variable10Case'
'variable10Case' --> 'variable10Case'
'ɛrgo rE tHis' --> 'ɛrgoRETHis'
'hurry-up-joe!' --> 'hurryUpJoe!'
'c://my-docs/happy_Flag-Day/12.doc' --> 'c://myDocs/happyFlagDay/12.doc'
'  spaces  ' --> 'spaces'

The specs are a little vague, but taking a wild stab at it... (May be completely wrong but without any examples of expected output it is hard to judge. This is what I would expect at least...)

my @tests = qww<
  snakeCase  snake_case  variable_10_case  variable10Case  "ɛrgo rE tHis"
  hurry-up-joe!  c://my-docs/happy_Flag-Day/12.doc  "  spaces  "
>;


sub to_snake_case (Str $snake_case_string is copy) {
    $snake_case_string.=trim;
    return $snake_case_string if $snake_case_string.contains: / \s | '/' /;
    $snake_case_string.=subst: / <after <:Ll>> (<:Lu>|<:digit>+) /, {'_' ~ $0.lc}, :g;
    $snake_case_string.=subst: / <after <:digit>> (<:Lu>) /, {'_' ~ $0.lc}, :g;
}

sub toCamelCase (Str $CamelCaseString is copy) {
    $CamelCaseString.=trim;
    return $CamelCaseString if $CamelCaseString.contains: / \s | '/' /;
    $CamelCaseString.=subst: / ('_') (\w) /, {$1.uc}, :g;
}

sub to-kebab-case (Str $kebab-case-string is copy) {
    $kebab-case-string.=trim;
    return $kebab-case-string if $kebab-case-string.contains: / \s | '/' /;
    $kebab-case-string.=subst: / ('_') (\w) /, {'-' ~ $1.lc}, :g;
    $kebab-case-string.=subst: / <after <:Ll>> (<:Lu>|<:digit>+) /, {'-' ~ $0.lc}, :g;
    $kebab-case-string.=subst: / <after <:digit>> (<:Lu>) /, {'-' ~ $0.lc}, :g;
}

say   "{' ' x 30}to_snake_case";
printf "%33s ==> %s\n", $_, .&to_snake_case for @tests;
say "\n{' ' x 30}toCamelCase";
printf "%33s ==> %s\n", $_,   .&toCamelCase for @tests;
say "\n{' ' x 30}to-kabab-case";
printf "%33s ==> %s\n", $_, .&to-kebab-case for @tests;
Output:
                              to_snake_case
                        snakeCase ==> snake_case
                       snake_case ==> snake_case
                 variable_10_case ==> variable_10_case
                   variable10Case ==> variable_10_case
                     ɛrgo rE tHis ==> ɛrgo rE tHis
                    hurry-up-joe! ==> hurry-up-joe!
c://my-docs/happy_Flag-Day/12.doc ==> c://my-docs/happy_Flag-Day/12.doc
                         spaces   ==> spaces

                              toCamelCase
                        snakeCase ==> snakeCase
                       snake_case ==> snakeCase
                 variable_10_case ==> variable10Case
                   variable10Case ==> variable10Case
                     ɛrgo rE tHis ==> ɛrgo rE tHis
                    hurry-up-joe! ==> hurry-up-joe!
c://my-docs/happy_Flag-Day/12.doc ==> c://my-docs/happy_Flag-Day/12.doc
                         spaces   ==> spaces

                              to-kabab-case
                        snakeCase ==> snake-case
                       snake_case ==> snake-case
                 variable_10_case ==> variable-10-case
                   variable10Case ==> variable-10-case
                     ɛrgo rE tHis ==> ɛrgo rE tHis
                    hurry-up-joe! ==> hurry-up-joe!
c://my-docs/happy_Flag-Day/12.doc ==> c://my-docs/happy_Flag-Day/12.doc
                         spaces   ==> spaces
Rebol [
    title: "Rosetta code: Camel case and snake case"
    file:  %Camel_case_and_snake_case.r3
    url:   https://rosettacode.org/wiki/Camel_case_and_snake_case
]

cammel-case-split: function/with [
    "Split a camelCase string into a block of words"
    input [string!]
][
    parse/case input [
        collect any [
            [
                ahead upper s: skip [to upper | to end] e:
                | end reject
                | s: [to upper | to end] e:
            ] keep ( copy/part s e )
        ]
    ]
][  upper: charset [#"A" - #"Z"] ]

to-snake-case: function[
    "Convert a string to snake_case"
    input [string!]
][
    out: lowercase ajoin/with cammel-case-split input #"_"
    div: charset " -_"
    parse trim/head/tail out [any [to div change some div #"_"]]
    out
]

to-camel-case: function[
    "Convert a string to camelCase"
    input [string!]
][
    out: copy ""
    foreach p split input charset " _-" [
        append out uppercase/part p 1
    ]
    lowercase/part out 1
    out
]

tests: [
    "snakeCase"
    "snake_case"
    "variable_10_case"
    "variable10Case"
    "ɛrgo rE tHis"
    "hurry-up-joe!"
    "c://my-docs/happy_Flag-Day/12.doc"
    "  spaces  "
]

print "                             === To snake_case ==="
foreach test tests [
    printf [-35 " --> " ][mold test mold to-snake-case test]
]
print ""
print "                             === To camelCase ==="
foreach test tests [
    printf [-35 " --> " ][mold test mold to-camel-case test]
]
Output:
                             === To snake_case ===
                        "snakeCase" --> "snake_case"
                       "snake_case" --> "snake_case"
                 "variable_10_case" --> "variable_10_case"
                   "variable10Case" --> "variable10_case"
                     "ɛrgo rE tHis" --> "ɛrgo_r_e_t_his"
                    "hurry-up-joe!" --> "hurry_up_joe!"
"c://my-docs/happy_Flag-Day/12.doc" --> "c://my_docs/happy_flag_day/12.doc"
                       "  spaces  " --> "spaces"

                             === To camelCase ===
                        "snakeCase" --> "snakeCase"
                       "snake_case" --> "snakeCase"
                 "variable_10_case" --> "variable10Case"
                   "variable10Case" --> "variable10Case"
                     "ɛrgo rE tHis" --> "ɛrgoRETHis"
                    "hurry-up-joe!" --> "hurryUpJoe!"
"c://my-docs/happy_Flag-Day/12.doc" --> "c://myDocs/happyFlagDay/12.doc"
                       "  spaces  " --> "spaces"
« 1
  WHILE DUP2 DUP SUB " " == REPEAT 1 + END 
  OVER DUP SIZE
  WHILE DUP2 DUP SUB " " == REPEAT 1 - END 
  SWAP DROP SUB
» 'TRIM' STO

« TRIM → s
  « "" 
    1 s SIZE FOR j
       s j DUP SUB 
       CASE
          "- " OVER POS THEN            
             DROP "_"  END
          DUP "A" ≥ OVER "Z" ≤ AND THEN 
             NUM 32 + CHR 
             IF OVER DUP SIZE DUP SUB "_" ≠ THEN "_" SWAP + END
             END
       END
       +
    NEXT 
» » '→SNAKE' STO

« TRIM → s
  « "" 1 CF
    1 s SIZE FOR j
       s j DUP SUB 
       CASE
          "-_ " OVER POS THEN            
             DROP "" 1 SF END
          DUP "a" ≥ OVER "z" ≤ AND 1 FS?C AND THEN 
             NUM 32 - CHR END
       END
       +
    NEXT 
» » '→CAMEL' STO

« { "snakeCase" "snake_case" "variable_10_case" "variable10Case"
   "εrgo rE tHis" "hurry-up-joe!" "c://my-docs/happy_Flag-Day/12.doc" "  spaces  " } 
  DUP  1 « →SNAKE » DOLIST
  SWAP 1 « →CAMEL » DOLIST
» 'TASK' STO 
Output:
2: { "snake_case" "snake_case" "variable_10_case" "variable10_case" "εrgo_r_e_t_his" "hurry_up_joe!" "c://my_docs/happy_flag_day/12.doc" "spaces" }
1: { "snakeCase" "snakeCase" "variable10Case" "variable10Case" "εrgoRETHis" "hurryUpJoe!" "c://myDocs/happyFlagDay/12.doc" "spaces" }


Works with: Rust
Translation of: C++
const HYPHEN: char = '-';
const SPACE: char = ' ';
const UNDERSCORE: char = '_';
const WHITESPACE: &str = " \n\r\t\u{0C}\u{0B}";

fn left_trim(text: &str) -> &str {
    text.trim_start_matches(WHITESPACE.chars().collect::<Vec<_>>().as_slice())
}

fn right_trim(text: &str) -> &str {
    text.trim_end_matches(WHITESPACE.chars().collect::<Vec<_>>().as_slice())
}

fn trim(text: &str) -> &str {
    text.trim_matches(WHITESPACE.chars().collect::<Vec<_>>().as_slice())
}

fn prepare_for_conversion(text: &mut String) {
    *text = trim(text).to_string();
    *text = text.replace(SPACE, &UNDERSCORE.to_string());
    *text = text.replace(HYPHEN, &UNDERSCORE.to_string());
}

fn to_snake_case(camel: &str) -> String {
    let mut text = camel.to_string();
    prepare_for_conversion(&mut text);
    
    let mut snake = String::new();
    let mut first = true;
    
    for ch in text.chars() {
        if first {
            snake.push(ch);
            first = false;
        } else if ch.is_ascii_uppercase() {
            if snake.chars().last() == Some(UNDERSCORE) {
                snake.push(ch.to_ascii_lowercase());
            } else {
                snake.push(UNDERSCORE);
                snake.push(ch.to_ascii_lowercase());
            }
        } else {
            snake.push(ch);
        }
    }
    
    snake
}

fn to_camel_case(snake: &str) -> String {
    let mut text = snake.to_string();
    prepare_for_conversion(&mut text);
    
    let mut camel = String::new();
    let mut underscore = false;
    
    for ch in text.chars() {
        if ch == UNDERSCORE {
            underscore = true;
        } else if underscore {
            camel.push(ch.to_ascii_uppercase());
            underscore = false;
        } else {
            camel.push(ch);
        }
    }
    
    camel
}

fn main() {
    let variable_names = vec![
        "snakeCase",
        "snake_case",
        "variable_10_case",
        "variable10Case",
        "ergo rE tHis",
        "hurry-up-joe!",
        "c://my-docs/happy_Flag-Day/12.doc",
        "  spaces  "
    ];

    println!("{:>48}", "=== To snake_case ===");
    for text in &variable_names {
        println!("{:>34} --> {}", text, to_snake_case(text));
    }

    println!();
    println!("{:>48}", "=== To camelCase ===");
    for text in &variable_names {
        println!("{:>34} --> {}", text, to_camel_case(text));
    }
}
Output:
                           === To snake_case ===
                         snakeCase --> snake_case
                        snake_case --> snake_case
                  variable_10_case --> variable_10_case
                    variable10Case --> variable10_case
                      ergo rE tHis --> ergo_r_e_t_his
                     hurry-up-joe! --> hurry_up_joe!
 c://my-docs/happy_Flag-Day/12.doc --> c://my_docs/happy_flag_day/12.doc
                          spaces   --> spaces

                            === To camelCase ===
                         snakeCase --> snakeCase
                        snake_case --> snakeCase
                  variable_10_case --> variable10Case
                    variable10Case --> variable10Case
                      ergo rE tHis --> ergoRETHis
                     hurry-up-joe! --> hurryUpJoe!
 c://my-docs/happy_Flag-Day/12.doc --> c://myDocs/happyFlagDay/12.doc
                          spaces   --> spaces



Translation of: Java
object CamelCaseAndSnakeCase extends App {

  val variableNames = List("snakeCase", "snake_case", "variable_10_case", "variable10Case",
    "ergo rE tHis", "hurry-up-joe!", "c://my-docs/happy_Flag-Day/12.doc", "  spaces  ")

  println(" " * 26 + "=== To snake_case ===")
  variableNames.foreach { text =>
    println(f"$text%34s --> ${toSnakeCase(text)}")
  }

  println("\n" + " " * 26 + "=== To camelCase ===")
  variableNames.foreach { text =>
    println(f"$text%34s --> ${toCamelCase(text)}")
  }

  def toSnakeCase(camel: String): String = {
    val snake = new StringBuilder
    camel.trim.replace(" ", "_").replace("-", "_").foreach { ch =>
      if (snake.isEmpty || snake.last != '_' || ch != '_') {
        if (ch.isUpper && snake.nonEmpty && snake.last != '_') snake.append('_')
        snake.append(ch.toLower)
      }
    }
    snake.toString
  }

  def toCamelCase(snake: String): String = {
    val camel = new StringBuilder
    var underscore = false
    snake.trim.replace(" ", "_").replace("-", "_").foreach { ch =>
      if (ch == '_') underscore = true
      else if (underscore) {
        camel.append(ch.toUpper)
        underscore = false
      } else camel.append(ch)
    }
    camel.toString
  }
}
Output:
                          === To snake_case ===
                         snakeCase --> snake_case
                        snake_case --> snake_case
                  variable_10_case --> variable_10_case
                    variable10Case --> variable10_case
                      ergo rE tHis --> ergo_r_e_t_his
                     hurry-up-joe! --> hurry_up_joe!
 c://my-docs/happy_Flag-Day/12.doc --> c://my_docs/happy_flag_day/12.doc
                          spaces   --> spaces

                          === To camelCase ===
                         snakeCase --> snakeCase
                        snake_case --> snakeCase
                  variable_10_case --> variable10Case
                    variable10Case --> variable10Case
                      ergo rE tHis --> ergoRETHis
                     hurry-up-joe! --> hurryUpJoe!
 c://my-docs/happy_Flag-Day/12.doc --> c://myDocs/happyFlagDay/12.doc
                          spaces   --> spaces

Translation of: Wren
fn to_camel(snake string) string {
    mut camel := ''
    mut underscore := false
    letters := snake.trim(' ').runes()
    for c in letters {
        if c.str() in [' ','-','_'] {
            underscore = true
        } else if underscore {
            camel += c.str().to_upper()
            underscore = false
        } else {
            camel += c.str()
        }
    }
    return camel
}
fn to_snake(camel string) string {
    mut snake := ''
    mut first := true
    letters := camel.trim(' ').replace(' ','_').runes()
    for c in letters {
        if first {
            snake+=c.str()
            first = false
        } else if !first && (c.str().is_upper() && c.bytes().len ==1 && c.bytes()[0].is_letter()) {
            if snake[snake.len-1..snake.len] == '_' || snake[snake.len-1..snake.len] == '-' {
                snake += c.str().to_lower()
            }else {
                snake += '_'+c.str().to_lower()
            }
        }else{
            snake+=c.str()
        }
    }
    return snake
}
const tests = ["snakeCase", "snake_case", "variable_10_case", "variable10Case", "ɛrgo rE tHis",
    "hurry-up-joe!", "c://my-docs/happy_Flag-Day/12.doc", "  spaces  "]
fn main() {
    println('                          === to_snake_case ===')
    for word in tests {
        println('${word:33} -> ${to_snake(word)}')
    }
    println('                          === to_camel_case ===')
    for word in tests {
        println('${word:33} -> ${to_camel(word)}')
    }
}
Output:
Same as Wren entry
Library: Wren-str
Library: Wren-fmt

Well, I'm not entirely sure what I'm doing here as a result of space and hyphen being treated as equivalent to underscore but, in the case of the 'to snake' conversion:

1. I've retained any hyphens in the result string but replaced spaces with underscores as it says that white space is not permitted as part of the variable name.

2. I've assumed that an underscore should not be added if the previous character was already a separator.

import "./str" for Char
import "./fmt" for Fmt

var toCamel = Fn.new { |snake|
    snake = snake.trim()
    var camel = ""
    var underscore = false
    for (c in snake) {
        if ("_- ".contains(c)) {
            underscore = true
        } else if (underscore) {
            camel = camel + Char.upper(c)
            underscore = false
        } else {
            camel = camel + c
        }
    }
    return camel
}

var toSnake = Fn.new { |camel|
    camel = camel.trim().replace(" ", "_") // we don't want any spaces in the result
    var snake = ""
    var first = true
    for (c in camel) {
        if (first) {
            snake = snake + c
            first = false
        } else if (!first && Char.isUpper(c)) {
            if (snake[-1] == "_" || snake[-1] == "-") {
                snake = snake + Char.lower(c)
            } else {
                snake = snake + "_" + Char.lower(c)
            }
        } else {
            snake = snake + c
        }
    }
    return snake
}

var tests = [
    "snakeCase", "snake_case", "variable_10_case", "variable10Case", "ɛrgo rE tHis",
    "hurry-up-joe!", "c://my-docs/happy_Flag-Day/12.doc", "  spaces  "
]

System.print("                          === to_snake_case ===")
for (camel in tests) {
    Fmt.print("$33s -> $s", camel, toSnake.call(camel))
}

System.print("\n                         === toCamelCase ===")
for (snake in tests) {
    Fmt.print("$33s -> $s", snake, toCamel.call(snake))
}
Output:
                          === to_snake_case ===
                        snakeCase -> snake_case
                       snake_case -> snake_case
                 variable_10_case -> variable_10_case
                   variable10Case -> variable10_case
                     ɛrgo rE tHis -> ɛrgo_r_e_t_his
                    hurry-up-joe! -> hurry-up-joe!
c://my-docs/happy_Flag-Day/12.doc -> c://my-docs/happy_flag-day/12.doc
                         spaces   -> spaces

                         === toCamelCase ===
                        snakeCase -> snakeCase
                       snake_case -> snakeCase
                 variable_10_case -> variable10Case
                   variable10Case -> variable10Case
                     ɛrgo rE tHis -> ɛrgoRETHis
                    hurry-up-joe! -> hurryUpJoe!
c://my-docs/happy_Flag-Day/12.doc -> c://myDocs/happyFlagDay/12.doc
                         spaces   -> spaces
string  0;              \use zero-terminated strings
char Out(100);          \output string (made global for safety)

func Trim(Str);         \Trim leading and trailing spaces from string
char Str;
int  I;
[while Str(0) = $20 do Str:= Str+1;     \skip leading spaces
I:= 0;                                  \skip to end of string (+1)
while Str(I) # 0 do I:= I+1;
while I>0 & Str(I-1)=$20 do I:= I-1;    \skip back to first non-space
Str(I):= 0;                             \chop off any trailing spaces
return Str;
];

func ToSnake(In);       \Convert string to snake_case
char In;
int  I, J, C, UL;
[I:= 0;  J:= 0;  UL:= true;             \suppress leading & redundant underlines
repeat  C:= In(I);  I:= I+1;            \get character from input string
        if C>=^A & C<=^Z then           \convert uppercase to "_" + lowercase
                [if not UL then [Out(J):= ^_;  J:= J+1];
                Out(J):= C+$20;  J:= J+1;
                UL:= false;
                ]
        else if C=$20 or C=^- then      \convert to underlines
                [if not UL then [Out(J):= ^_;  J:= J+1;  UL:= true]
                ]
        else    [Out(J):= C;  J:= J+1;  UL:= C=^_];
until   C = 0;
return Out;
];

func ToCamel(In);       \Convert string to camelCase
char In;
int  I, J, C;
[I:= 0;  J:= 0;
repeat  C:= In(I);  I:= I+1;
        if C=^_ or C=^- or C=$20 then
                [C:= In(I);  I:= I+1;
                if C>=^a & C<=^z then C:= C-$20;
                Out(J):= C;  J:= J+1;
                ]
        else    [Out(J):= C;   J:= J+1];
until   C = 0;
return Out;
];

int Strings, I;
[Strings:= [
 "snakeCase", "snake_case", "variable_10_case", "variable10Case", "\u025brgo rE tHis",
 "hurry-up-joe!", "c://my-docs/happy_Flag-Day/12.doc", "  spaces  "];
Text(0, "To snake case:^M^J");
for I:= 0 to 7 do
    [Text(0, Strings(I));
    Text(0, " -> ");
    Text(0, ToSnake(Trim(Strings(I))));
    CrLf(0);
    ];
Text(0, "To camel case:^M^J");
for I:= 0 to 7 do
    [Text(0, Strings(I));
    Text(0, " -> ");
    Text(0, ToCamel(Trim(Strings(I))));
    CrLf(0);
    ];
]
Output:
To snake case:
snakeCase -> snake_case
snake_case -> snake_case
variable_10_case -> variable_10_case
variable10Case -> variable10_case
\u025brgo rE tHis -> \u025brgo_r_e_t_his
hurry-up-joe! -> hurry_up_joe!
c://my-docs/happy_Flag-Day/12.doc -> c://my_docs/happy_flag_day/12.doc
  spaces   -> spaces
To camel case:
snakeCase -> snakeCase
snake_case -> snakeCase
variable_10_case -> variable10Case
variable10Case -> variable10Case
\u025brgo rE tHis -> \u025brgoRETHis
hurry-up-joe! -> hurryUpJoe!
c://my-docs/happy_Flag-Day/12.doc -> c://myDocs/happyFlagDay/12.doc
  spaces -> spaces



Works with: Zig version 0.14.1
Translation of: Rust
const std = @import("std");
const print = std.debug.print;
const ArrayList = std.ArrayList;

const HYPHEN: u8 = '-';
const SPACE: u8 = ' ';
const UNDERSCORE: u8 = '_';
const WHITESPACE = " \n\r\t\x0C\x0B";

fn isWhitespace(ch: u8) bool {
    for (WHITESPACE) |ws| {
        if (ch == ws) return true;
    }
    return false;
}

fn leftTrim(text: []const u8) []const u8 {
    var start: usize = 0;
    while (start < text.len and isWhitespace(text[start])) {
        start += 1;
    }
    return text[start..];
}

fn rightTrim(text: []const u8) []const u8 {
    var end: usize = text.len;
    while (end > 0 and isWhitespace(text[end - 1])) {
        end -= 1;
    }
    return text[0..end];
}

fn trim(text: []const u8) []const u8 {
    return rightTrim(leftTrim(text));
}

fn prepareForConversion(allocator: std.mem.Allocator, text: []const u8) ![]u8 {
    const trimmed = trim(text);
    var result = try ArrayList(u8).initCapacity(allocator, trimmed.len);
    defer result.deinit();
    
    for (trimmed) |ch| {
        if (ch == SPACE or ch == HYPHEN) {
            try result.append(UNDERSCORE);
        } else {
            try result.append(ch);
        }
    }
    
    return result.toOwnedSlice();
}

fn toSnakeCase(allocator: std.mem.Allocator, camel: []const u8) ![]u8 {
    const text = try prepareForConversion(allocator, camel);
    defer allocator.free(text);
    
    var snake = ArrayList(u8).init(allocator);
    defer snake.deinit();
    
    var first = true;
    
    for (text) |ch| {
        if (first) {
            try snake.append(ch);
            first = false;
        } else if (std.ascii.isUpper(ch)) {
            if (snake.items.len > 0 and snake.items[snake.items.len - 1] == UNDERSCORE) {
                try snake.append(std.ascii.toLower(ch));
            } else {
                try snake.append(UNDERSCORE);
                try snake.append(std.ascii.toLower(ch));
            }
        } else {
            try snake.append(ch);
        }
    }
    
    return snake.toOwnedSlice();
}

fn toCamelCase(allocator: std.mem.Allocator, snake: []const u8) ![]u8 {
    const text = try prepareForConversion(allocator, snake);
    defer allocator.free(text);
    
    var camel = ArrayList(u8).init(allocator);
    defer camel.deinit();
    
    var underscore = false;
    
    for (text) |ch| {
        if (ch == UNDERSCORE) {
            underscore = true;
        } else if (underscore) {
            try camel.append(std.ascii.toUpper(ch));
            underscore = false;
        } else {
            try camel.append(ch);
        }
    }
    
    return camel.toOwnedSlice();
}

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();
    
    const variable_names = [_][]const u8{
        "snakeCase",
        "snake_case",
        "variable_10_case",
        "variable10Case",
        "ergo rE tHis",
        "hurry-up-joe!",
        "c://my-docs/happy_Flag-Day/12.doc",
        "  spaces  "
    };

    print("{s:>48}\n", .{"=== To snake_case ==="});
    for (variable_names) |text| {
        const snake = try toSnakeCase(allocator, text);
        defer allocator.free(snake);
        print("{s:>34} --> {s}\n", .{ text, snake });
    }

    print("\n", .{});
    print("{s:>48}\n", .{"=== To camelCase ==="});
    for (variable_names) |text| {
        const camel = try toCamelCase(allocator, text);
        defer allocator.free(camel);
        print("{s:>34} --> {s}\n", .{ text, camel });
    }
}
Output:
                           === To snake_case ===
                         snakeCase --> snake_case
                        snake_case --> snake_case
                  variable_10_case --> variable_10_case
                    variable10Case --> variable10_case
                      ergo rE tHis --> ergo_r_e_t_his
                     hurry-up-joe! --> hurry_up_joe!
 c://my-docs/happy_Flag-Day/12.doc --> c://my_docs/happy_flag_day/12.doc
                          spaces   --> spaces

                            === To camelCase ===
                         snakeCase --> snakeCase
                        snake_case --> snakeCase
                  variable_10_case --> variable10Case
                    variable10Case --> variable10Case
                      ergo rE tHis --> ergoRETHis
                     hurry-up-joe! --> hurryUpJoe!
 c://my-docs/happy_Flag-Day/12.doc --> c://myDocs/happyFlagDay/12.doc
                          spaces   --> spaces
Cookies help us deliver our services. By using our services, you agree to our use of cookies.