Message Boards Message Boards

Converting a passed Symbol into being a String to create a gui object.

Posted 2 years ago

I can't figure out the right way to do this:

foo[symb1_] :=   Module[    {},    Switch[Head@symb1,
Symbol, symb1 = ToString@symb1,
String, symb1];
foo2[symb12_String] := Button[symb12, Speak@symb12];    foo2@symb1    ];
foo@Plot (*want to call foo this way without quotes*)

Foo would be typed within a Cell not ever within another function since it displays a gui object that I would interact with. My goal is to force the Symbol into a string so it can be passed to other functions that need string data which creates the GUI object. Bonus points, have the function and the passed Symbol get replaced by the GUI object it creates! Creating another brick in making my digital curb cut.

Thanks for your help.

POSTED BY: Andrew Meit
22 Replies
Posted 2 years ago

It is the metaphor for the tool am creating to help other disabled folks use MMA well. A 11 yr long project. A curb cut is made so wheelchairs can get onto a sidewalk without struggling over a 3 inch curb. The cool Code Assist is good but has limitations for me and other disabled folks. Instead of waiting for WRI to make the curb cut I have been requesting for a long time, am decided I was going to do it. You great help with me is going to help others. Thank you!

POSTED BY: Andrew Meit

What is a digital curb cut?

Regards

POSTED BY: Neil Singer
Posted 2 years ago

" I would also suggest that the last SelectionMove not go after the created cell but leave the cursor in the new cell ready to type the next input. " That does not seem to be happening; I suspect the CodeAssist UI interfering. Can I turn off the floating CodeAssist for that Cell?? Thanks

POSTED BY: Andrew Meit
Posted 2 years ago

Thanks; did you see my last post from last night. Remember the goal is not a button to speak but a way to create digital curb cut button. But your code taught more insights about working with Buttons; enjoy learning from you!

POSTED BY: Andrew Meit

Andrew,

this behaves as you asked. It is difficult to understand because it dives into the deep depths of how Mathematica constructs Boxes and Cells.

foo[symb1_Symbol] := 
  Module[{ sym = SymbolName[Unevaluated[symb1]]}, 
   foo[Evaluate[sym]]];
foo[symb1_String] := 
 Module[{ obj = EvaluationCell[], nb = EvaluationNotebook[]},
  SelectionMove[obj, All, Cell];
  NotebookDelete[nb]; 
  RawBoxes[
   ButtonBox[symb1, Appearance -> Automatic, 
    ButtonFunction :> Speak[symb1], Evaluator -> Automatic, 
    Method -> "Preemptive"]]]
SetAttributes[foo, HoldAll]

I have not figured out how to leave the cursor on the line after it evaluates but maybe someone else can figure it out or I can look at it later.

Regards

Neil

POSTED BY: Neil Singer

Andrew,

I just reread your post and I think I understand what you asked. You want to do this operation and then add more buttons to the same line?

The code I posted will not do that because it deletes the input line so anything earlier in the line is destroyed. The reason I printed the button was that if I just returned

Button[symb1, Speak@symb1]

The input cell became "Button["help",Speak["Help]]" instead of the actual button but when that line evaluated it became the actual button. By using Print, I made the code for the Button process into an actual button.

There should be a way to do what you want but I will have to think a bit about it tonight. It requires a bit more Notebook/Frontend programming. I would also suggest that the last SelectionMove not go after the created cell but leave the cursor in the new cell ready to type the next input. (minor point).

Regards,

Neil

POSTED BY: Neil Singer

Andrew,

When you print the button it is clickable. There is no need to change any code from what I posted.

Did you try it?

Regards

POSTED BY: Neil Singer
Posted 2 years ago

This is very very close to what I want; thank you for teaching new insights with your code.

foo5[symb1_Symbol] := 
 Module[{obj = EvaluationCell[], nb = EvaluationNotebook[]}, 
  SelectionMove[obj, All, Cell];
  NotebookDelete[nb];
  SelectionMove[nb, Next, Cell];
  SelectionMove[nb, After, Cell];
  Æ’Æ’@symb1  Defer[
    foo5@\[SelectionPlaceholder]]];  (* Æ’Æ’ is My digital curb cut \
function*)
SetAttributes[foo5, HoldAll]
POSTED BY: Andrew Meit
Posted 2 years ago

wow, thank you; learning even more.... Ok, I assume since you are printing the Button, the Cell no longer can accept input code unless the Cell style is restored to Input...I want to either 1. enter another foo@Symbol after the button when Cell style is Input; 2 when the Button is made foo@ is placed. See attached code.

foo3[symb1_] :=
  Module[{symb12, obj, nb},
   symb12 =
    Switch[Head@symb1,
     Symbol, SymbolName[Unevaluated[symb1]],
     String, symb1]; 
   foo2[symb12a_String] := Button[symb12a, Speak@symb12a];
   obj = EvaluationCell[];
   SelectionMove[obj, All, Cell]; nb = EvaluationNotebook[];
   Print[foo2@symb12 Defer[foo3[\[SelectionPlaceholder]]]; 
    NotebookDelete[nb];
    SelectionMove[nb, Next, Cell]; SelectionMove[nb, After, Cell]]];
POSTED BY: Andrew Meit

or better yet:

foo[symb1_Symbol] := 
  Module[{ sym = SymbolName[Unevaluated[symb1]]}, 
   foo[Evaluate[sym]]];
foo[symb1_String] := 
  Module[{ obj = EvaluationCell[], nb = EvaluationNotebook[]},
   SelectionMove[obj, All, Cell]; Print[Button[symb1, Speak@symb1]]; 
   NotebookDelete[nb]; SelectionMove[nb, Next, Cell]; 
   SelectionMove[nb, After, Cell]];
SetAttributes[foo, HoldAll]
POSTED BY: Neil Singer

Andrew,

Several comments:

The SetAttributes[foo, HoldAll] makes foo accept Symbols that are defined in the Kernel. This might never be an issue for your code but it is generally a good idea.

Modifying your latest post to put the button in place of what the user typed you can do:

foo[symb1_] := 
  Module[{symb12, obj, nb}, 
   symb12 = 
    Switch[Head@symb1, Symbol, SymbolName[Unevaluated[symb1]], String,
      symb1]; foo2[symb12a_String] := Button[symb12a, Speak@symb12a]; 
   obj = EvaluationCell[];
   SelectionMove[obj, All, Cell]; nb = EvaluationNotebook[]; 
   Print[foo2@symb12]; NotebookDelete[nb]; 
   SelectionMove[nb, Next, Cell]; SelectionMove[nb, After, Cell]];

This code uses Notebook Manipulation commands to select the current cell, print the button, delete the input that was typed by the user and move after the button so it looks like what you asked for.

Next it is a good idea to localize variables in a Module[]. You should not be creating global variables here. (symb12, obj, nb, and anything else you add)

Lastly, I Don't like using Switch[] in functions like this. Mathematica is suited to operator overloading and it makes for better code although this is a matter of programming style.

I would do:

foo[symb1_Symbol] := 
  Module[{ sym = SymbolName[Unevaluated[symb1]], obj, nb}, 
   obj = EvaluationCell[]; nb = EvaluationNotebook[];
   SelectionMove[obj, All, Cell]; Print[Button[sym, Speak@sym]]; 
   NotebookDelete[nb]; SelectionMove[nb, Next, Cell]; 
   SelectionMove[nb, After, Cell]];
foo[symb1_String] := 
  Module[{ obj, nb}, obj = EvaluationCell[]; nb = EvaluationNotebook[];
   SelectionMove[obj, All, Cell]; Print[Button[symb1, Speak@symb1]]; 
   NotebookDelete[nb]; SelectionMove[nb, Next, Cell]; 
   SelectionMove[nb, After, Cell]];
SetAttributes[foo, HoldAll]

This code defines a foo function for Symbols and a foo function that take strings. The appropriate function is used for the appropriate input. (operator overloading).

Regards

Neil

POSTED BY: Neil Singer
Posted 2 years ago

How about this for a new code icon; see attached image. sumbitted new coding icon.

POSTED BY: Andrew Meit
Posted 2 years ago

Ok discovered if I increased the Text zoom in Safari much higher than I usually have it, I see code formatting button! At a moderate zoom level, the Add Notebook btn hides the code formatting button! Your code for laying out the toolbar buttons has a bug. ;-p

Attachment

Attachments:
POSTED BY: Andrew Meit
Posted 2 years ago

The Doc center section on SymbolName does not explain well that SymbolName[Unevaluated[sym]] can be a solution handling SymbolNames in code. Neil, you gave great help.

POSTED BY: Andrew Meit
Posted 2 years ago

Ok, It works well without the SetAttributes; So will something break not using the SetAttributes?? Thanks for the elegant solution for the str = SymbolName[Unevaluated[sym]]. Thanks.

POSTED BY: Andrew Meit
Posted 2 years ago

Neil, Cool! Learning more!! Nearing the end of a long term goal for my digital curb cut. :-) The second code you showed really helps without having to rename my vars; Thank you!

POSTED BY: Andrew Meit
Posted 2 years ago

So SetAttributes[foo2, HoldAll] is placed after I defined foo using Module?

POSTED BY: Andrew Meit

Based on what I posted, This works exactly how you describe:

foo2[sym_Symbol] := 
 Button[SymbolName[Unevaluated[sym]], 
  Speak@SymbolName[Unevaluated[sym]]]
SetAttributes[foo2, HoldAll]

you can type foo2@help and get a button labeled help that says "help" when you click it.

or shorten it to

foo2[sym_Symbol] := 
 Module[{str = SymbolName[Unevaluated[sym]]}, Button[str, Speak@str]]
SetAttributes[foo2, HoldAll]

Regards,

Neil

POSTED BY: Neil Singer
Posted 2 years ago

Hummm...I will try again... Correct you are misunderstanding.

Ignore the speaking bit; its not my goal. The Button being created was with its functionality shaped by using a String passed to it from a System`Symbol.

Let me walk you through what am seeking...

I have a complex function, mkFoo, that creates a complex ActionMenu widget using the single argument of a Symbol -- many months of coding.

I want to use this function in this manner: you type mkFoo@SymbolName inside a Cell, note this a free standing code fragment NOT inside any other code. I want to hit enter at the end of the SymbolName so the function mkFoo uses the Symbol to make the ActionMenu. Of course it works when I put quotes around the Symbol name. Hence my need to convert that Symbol name into a String. From you comment on Protection/Side effects, I should use another variable name instead and use that for the rest of the code having now the SymbolName a proper String, "SymbolName". So, I rewrote the code, which does want the way I want to use it.

foo[symb1_] :=   Module[    {},    symb12 = Switch[Head@symb1,
Symbol, ToString@symb1,
String, symb1];
foo2[symb12a_String] := Button[symb12a, Speak@symb12a];    foo2@symb12    ];
POSTED BY: Andrew Meit

Andrew,

What you want is SymbolName[], not ToString[]. If you want to pass it to a function, foo. You will need to make foo not evaluate the argument:

foo[sym_Symbol] := SymbolName[Unevaluated[sym]]
SetAttributes[foo, HoldAll]
xxxy = 2;
foo[xxxy]

returns xxxy

The _Symbol is optional but it protects against passing things that are not symbols.

Regards,

Neil

POSTED BY: Neil Singer
Posted 2 years ago

Neil, yes a more elegant answer, thanks; now my code should be (btw, how do I get my code to look like the proper version in a box like others do?):

foo[symb1_] :=   Module[    {},    symb12 = Switch[Head@symb1,
Symbol, SymbolName[Unevaluated[symb1]],
String, symb1];    foo2[symb12a_String] := Button[symb12a, Speak@symb12a];
foo2@symb12    ]; foo@Activate

However I also want the code fragment be replaced by the Button created; doable??

POSTED BY: Andrew Meit
Posted 2 years ago

force the Symbol into a string

You already know how to do that--you're already doing it in your example: ToString[symbol]. I'm very confused by your question.

Also, when the Head of symb1 is Symbol, you have

symb1 = ToString@symb1

which will reassign the value of symb1, which seems like an undesirable side effect. And for built in functions, it'll fail because they're Protected.

In your example, what I'm inferring is that you want a button that displays "Plot" and Speaks "Plot". But that's just

Button[Plot, Speak@Plot]

It seems like you've already figured out how to do this, so I think I must be misinterpreting your question. Can you be more descriptive?

POSTED BY: Eric Rimbey
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract