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



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


基本操作

  • カーソルが最終行に有るときに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(アクセンス)

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

# -*- 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)
Tags: ,

Related posts

タグ: ,

コメントは受け付けていません。