無料Mathematica Player用のインタラクティブシェルをIronPythonで書いてみた

[pukiwiki]
[[こちらの記事の続きです:http://boxheadroom.com/2009/10/08/mathlink]]
Mathematica Playerで遊ぶのに、毎回 ソースを書き直すのがめんどくさかったので、対話的に作業できるように、ちょっとしたフロントエンドをIronPythonで書いてみました
人生初 .netアプリ (汗
Python用の開発環境、IDLEの操作に似せてあります
[/pukiwiki]

[pukiwiki]

*基本操作
-カーソルが最終行に有るときにEnter またはeval ボタン
 最終行をMathematica Playerのエンジンで評価
-カーソルが最終行 ”以外”に有るときにEnter
 現在行の内容を 最終行へ追加
 (Basicみたく、現在行を評価したほうが素直かな? IDLEに似せてあります)
-文字列を選択してEnter または eval ボタン
 選択中の文字列を評価
 複数行にまたがる命令を入力するときに使用
-Ctrl + Enter で改行文字の入力
 上記とあわせて使用
*特殊コマンド説明
! 1文字目がビックリマークだと Pythonの式として評価 (eval)
!exe ( “文” ) exec命令により Pythonの文として評価 
            (変数への代入などに必要)
!pretty() # 結果をちょっと凝った表示に
!simple() # 結果表示をシンプルに (デフォルト)

*特殊変数
_ # アンダースコアに、最期に評価した結果を格納。 Pythonで使用可能

*Todo
入力文字を評価するだけのプログラムのつもりが、だんだん肥大化(汗
Mathematicaアカデミック版なら3万円ぐらいらしいので、本格的に使うのであれば、あまり手をかけると、手間のほうがアレですが。

-リサイズに対応 
-演算結果を、output[idx] みたいな配列に保存して再利用可能に
-結果文字列が長いときの省略表示 (上記とあわせて)
-結果文字列をパースしてPythonで利用するためのパーサ
-GUI部分のコードを、もう少しきれいに。
*LANでWebサービス版
むしろ、CGIHttpServerモジュールなどを使って、Web経由で使えるようにしたほうが、ローカルでの使い手があるかも。Firefoxなどでは、 MathMLを使って数式表示できますし。
(IronPythonは、インストーラ版のみ、CPythonの標準ライブラリ同等品が付いてきます。)
参考
[[Python Snippet(アクセンス):http://omake.accense.com/wiki/Python/Snippet/%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF]]

[/pukiwiki]
こんな短いプログラムで数式処理(っぽいこと)ができるなんて、、、時代に進歩にびっくり
(コメントと、ライブラリのインポートが半分ぐらいなので、実質のコード量はかなり少ないです)

# -*- coding: cp932 -*-
"""
mathform.py

MathematicaPlayer intaractive shell

Enter-key on last line : execute last line
Enter-key on  previous line : copy previous line to last line
 (IDLE like)
Selection and Enter key : execute selection
                          (for multiline evaluation)

python mode

if first charactor is !  eval as python 
!expression  : eval(expression) in python
!exe( statement) : exec statement in python 
!setq( name, val) : name=val in python
!setq( name , val,index) : name[index]=val
input Enter  :  Ctrl + Enter


Output mode
!simple()   :  use EvaluateToOutputForm  (default)
!pretty()   : use EvaluateToInputForm
              print prettify  

"""
import clr , System
require=clr.AddReferenceByPartialName
#require=clr.AddReferenceToFile
require("System.Windows.Forms")
from System.Windows.Forms import Form,Button,TextBox,Application
require("Wolfram.NETLink")
from Wolfram.NETLink import *
require("System.Drawing")
from System.Drawing import Font
LN=System.Environment.NewLine

frm=Form(Height = 400,Width = 640)

frm.Text="Simple Window"
fnt = Font("MS ゴシック", 12);
frm.Show()
t1=TextBox(Left=20, Top=35, Width=600,Height=300,Font=fnt)
t1.Text=""
def q(sender, args):
  kernelLink.Close()
  frm.Close()

b2 = Button(Text="&Quit", Left=500, Top=340)
b2.Click+=q

t1.Multiline = True
t1.ScrollBars = System.Windows.Forms.ScrollBars.Vertical 
b1 = Button(Text="&Eval", Left=300, Top=340)

kernelLink=MathLinkFactory.CreateKernelLink()
kernelLink.WaitAndDiscardAnswer()

modedict={}
modedict["output"]=0 

def setq(name,val,index=None):
  if index is None:
    globals()[name]=val
  else :
    globals()[name][index]=val
  return val
def exe(txt):
  exec txt in globals()
  return ""
_=""
def evaluate(txt):
  global _
  if not txt : return ""
  if txt.split()[0].startswith("!"):
    _=eval(txt[1:])
  else :
    if not modedict["output"] : #simple
      _= kernelLink.EvaluateToInputForm( txt, 0)
    else :  #pretty
      _=kernelLink.EvaluateToOutputForm( txt, 0)
  return _

def mode(key,mode):
  modedict[key]=mode
  return key,mode
def pretty():
  mode("output",1)
  return "use EvaluateToOutputForm"
def simple():
  mode("output",0)
  return "use EvaluateToInputForm"
  
def b1_onclick(sender, args):
  sel=t1.SelectedText
  if sel :
    next= LN+str(evaluate(sel))+LN+LN
  else :
    lines=t1.Text.splitlines()
    ln=t1.GetLineFromCharIndex(t1.SelectionStart)
    next=""
    l=t1.Text.Length
    if not lines : return
    if l and  ln==t1.GetLineFromCharIndex(l):
      # execute last line 
      t1.Text+=LN
      txt=lines[-1]
      s=txt.split()
      if s and  s[0] and s[0]!=LN  :
          next= LN+str(evaluate(txt))+LN+LN
    else:
      #copy current line to last line
      next=lines[ln]

  t1.Text+=next
  t1.SelectionStart=t1.Text.Length
  t1.ScrollToCaret()

b1.Click+=b1_onclick
frm.AcceptButton=b1

frm.Controls.Add(t1)
frm.Controls.Add(b1)
frm.Controls.Add(b2)
Application.Run(frm)

コメントを残す

メールアドレスが公開されることはありません。