3
$\begingroup$

If we run this code:

FindCycle[1, 2, 3, 4, 5]

It will give a error information like:

How to get the error info promption of FindCycle::argb: FindCycle called with 5 arguments; between 1 and 3 arguments are expected.


As the comments,the method of Kuba's FindCycle::argb /. Messages[FindCycle] will get a string template with ` `.The same case of rcollyer's method.But actually I want get a string(..between 1 and 3 arguments..) but not a string template(..between `3` and `4` arguments..).

$\endgroup$
9
  • $\begingroup$ @Kuba ok. I was wrong. Here's the duplicate ... which I wrote. :P $\endgroup$
    – rcollyer
    Feb 26, 2017 at 16:57
  • 2
    $\begingroup$ @Kuba here it is Internal`HandlerBlock[{"MessageTextFilter", Print[{##}] &}, FindCycle[1, 2, 3, 4, 5]]. The first argument to "MessageTextFilter" gives the text. $\endgroup$
    – rcollyer
    Feb 26, 2017 at 17:00
  • 1
    $\begingroup$ This seems to me like a duplicate of mathematica.stackexchange.com/q/20367/121 $\endgroup$
    – Mr.Wizard
    Feb 26, 2017 at 20:15
  • 3
    $\begingroup$ @rhermans I appreciate your idea to move all external images to imgur SE. May be it is better to introduce a delay into your script, so that SE users, question authors and the front page do not get overwhelmed by updates. Such updates can be done in the same way like Community user bumps random questions once an hour. $\endgroup$
    – Ray Shadow
    May 12, 2017 at 15:51
  • 2
    $\begingroup$ @rhermans,yode I think this update is really good thing to do. I just suggest to update one question per hour (or so). $\endgroup$
    – Ray Shadow
    May 12, 2017 at 16:04

2 Answers 2

10
$\begingroup$

Something different:

Attributes[getMsgString] = HoldFirst;

getMsgString[x_] := 
 Block[{MessagePacket =Return[ToString@ToExpression[#3[[1, 1, 3]]], Block] &}, x]

Now:

FindCycle[1, 2, 3, 4, 5] // getMsgString
"FindCycle called with 5 arguments; between 1 and 3 arguments are expected. >>"

To address the case raised the comments here is one approach:

flatFraction = 
  StringReplace[#, 
    Shortest["\\!\\(" ~~ n__ ~~ "\\/" ~~ d__ ~~ "\\)"] :> n ~~ "/" ~~ d] &;

getMsgString[x_] := 
  Block[{MessagePacket =
    Return[#3[[1, 1, 3]] // flatFraction // ToExpression // ToString, Block] &}, x]

500 / 0 // getMsgString
Infinite expression 1/0 encountered. >>

Incidentally I copied the string above using Plain Text. The direct output is:

"Infinite expression \[NoBreak]1/0\[NoBreak] encountered. \[RightSkeleton]"

If that is a problem additional processing can be applied; let me know if you need help with that.


Edit for more general case

Attributes[getMsgString] = HoldFirst;

getMsgString[x_] := 
 Block[{MessagePacket = 
    Return[First[
       FrontEndExecute[
        FrontEnd`ExportPacket[
         First[MathLink`CallFrontEnd[
           FrontEnd`UndocumentedTestFEParserPacket[
            ToExpression[#3[[1, 1, 3]]], False]]], "PlainText"]]], 
      Block] &}, x]

Examples

enter image description here


More MessagePacket shenanigans:

$\endgroup$
7
  • $\begingroup$ I read all posts you linked,but I have to say your solution better than all of it.Just a preference for me.Your result not a normal string.If you can update a little,I will change the accepted. $\endgroup$
    – yode
    Feb 27, 2017 at 7:24
  • $\begingroup$ I have given a little change in your code for concise,if you mind that,you can rollback it.Actually make "Infinite expression \!\(\*FractionBox[\"1\", \"0\"]\) encountered." into "Infinite expression ∞ encountered.".It's seem not easy to do. $\endgroup$
    – yode
    Feb 27, 2017 at 7:38
  • $\begingroup$ @yode That is certainly possible on a case-by-case replacement but I suspect you mean more generally than that? I'll edit my answer with one possible method. $\endgroup$
    – Mr.Wizard
    Feb 27, 2017 at 13:17
  • $\begingroup$ @yode you should already know how to deal with string representation of expression inside strings: mathematica.stackexchange.com/a/138544/5478 $\endgroup$
    – Kuba
    Feb 28, 2017 at 8:33
  • $\begingroup$ @Kuba Funny,actually I have tried that method yesterday,it's not work.But I give another try just now.It work out.And have a update by your this code. $\endgroup$
    – yode
    Feb 28, 2017 at 9:26
5
$\begingroup$

The code below makes me think I have missed something obvious:

Quiet @Cases[
    Internal`HandlerBlock[
       {"Message", Sow}
     , Reap @ FindCycle[1, 2, 3, 4, 5]
   ]
 , HoldPattern[Message[mn : MessageName[head_, name_], params___]] :> 
      StringTemplate[mn /. Messages[head]][params]
 , ∞
]
{"FindCycle called with 5 arguments; between 1 and 3 arguments are \
 expected."}
$\endgroup$
4
  • $\begingroup$ We can use Quiet[Internal`HandlerBlock[...]] to get same result.But I have to say I cannot totally understand your mma syntax here. :) $\endgroup$
    – yode
    Feb 26, 2017 at 18:57
  • $\begingroup$ @yode I'm not sure what do you mean. Your short code returns: {FindCycle[1,2,3,4,5],{{Hold[Message[FindCycle::argb,FindCycle,5,1,3],False]}}} for me. $\endgroup$
    – Kuba
    Feb 26, 2017 at 18:59
  • $\begingroup$ I mean this. $\endgroup$
    – yode
    Feb 26, 2017 at 19:01
  • $\begingroup$ @yode Ok, now I understand, I though you meant I can use Quiet to make the code shorter :) $\endgroup$
    – Kuba
    Feb 26, 2017 at 19:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.