我想要一个elisp脚本在光标下执行Python一行代码

时间:2013-02-09 02:34:40

标签: python elisp

我是Emacs的重要人物。我在本月初开始使用Emacs。

我想将小Vim脚本移植到Emacs。这些脚本也使我们能够在Emacs中这样计算。

http://www.youtube.com/watch?v=yDR0dTPu6M4

我尝试移植下面写的Vim脚本。

function! s:ExecPySf_1liner()
    let l:strAt = getline(".")
    call writefile([strAt], "temp.pysf")

    let l:strAt = system("python -u -m sfPP -fl temp.pysf")
    if @0 == 0
        let @0 = l:strAt
    else
        let @0 = l:strAt
    endif

    let @" = @0
    if match(&clipboard, "unnamed") >= 0
        let @* = @0
    endif
    echo @0
endfunction         

但我已经筋疲力尽了。我花了整整3天时间写下以下代码。

(defun ExecPySf_1liner ()
    (let (  (strAt
             (buffer-substring-no-properties (point-at-bol) (point-at-eol))
            )
         )
    ) 
)

我想让Emacs做以下行动。

1 read one line under the cursor.
2 write down the one line string into temp.pysf file in current directory
3 execute "python -u -m sfPP -fl temp.pysf" in a shell.
4 display the returned calculated string in echo arear
5 and copy the string in the clipboard to enable a user to past the calculated result.

请指出相应的elisp功能或代码。

提前致谢

===============================

你好克里斯。我修改了你的代码,如下所示。

(defun __getLineOmittingComment ()
    "Get position after ';;' string. If there is no ;; then return line-beginning-posiion"
    (interactive)
    (goto-char (line-beginning-position))
    (let (( posAt (search-forward ";;" (line-end-position) t) ))
     (if (equal posAt nil) (line-beginning-position) posAt)
    )
)

(defun ExecPySf_1liner()
    "Evaluates the current line in PythonSf, then copies the result to the clipboard."
    (interactive)
    (write-region (__getLineOmittingComment) (line-end-position) "temp.pysf" nil)

    (let ((strAt
           (shell-command-to-string "python -u -m sfPP -fl temp.pysf" )
         ))
        (message strAt)
        (kill-new strAt)))

ExecPySf_1liner()计算勒让德符号:http://en.wikipedia.org/wiki/Legendre_symbol,如下所示。

import sympy as ts; Lgndr=lambda a,b:(lambda c=a%b:0 if ts.gcd(c,b)!=1 else 1 if any((c-k^2)%b==0 for k in range(1,b//2+2)) else -1)(); [Lgndr(3,p) for p in ts.primerange(3,100)] 
===============================
[0, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1]
  

你应该看看IPython。它带有一个Emacs模式,可以完成所有这些以及更多

我能理解你的意见。但是你可能会忽略这样一个事实:Python单行程序是函数式编程并且在单行程序中完成。因为他们不使用if then else语法。他们必须使用lambda函数,不要使用def函数。虽然它们不是严格的引用透明,但它们是elisp脚本的函数式编程。数学问题很容易用函数编程风格编写,比如上面的勒让德符号。

IPython可以将他们的笔记保存为Matlab,Mathematica,您可以重复使用它们。但是这些笔记的内容整体纠结在一起。普通人在许多糟糕的表情之后写了一个有价值的表达。在许多情况下,有价值的表达取决于一些正向表达。将依赖的表达式汇集在一起​​是很麻烦的。所以这张纸条纠缠不清。

一年之后,当你想重新使用有价值的表达时,你会忘记笔记的细节,很难重复使用有价值的表达。因为你必须记住整个细节。

但每个Python单线程本身都是完整的。几年后,您可以轻松地重复使用它们。您可以轻松地合并Python单行,因为它们是函数式编程。

你可能比IPython中的Python表达式更容易处理Python单行。


我从修改你的elisp代码中学到了很多东西。我成了一个elisp爱好者。而且我对elisp比Vim脚本更熟悉。非常感谢。

=============================================== ================================

  

你应该看看IPython :)。它带有一个Emacs模式,可以完成所有这些以及更多。 :)?   我能理解你的意见。但我声称使用Emacs AS IPython比使用IPython AS Emacs要好。

我稍微扩展了Python用于数学。 sfPP.py是一个预处理器,它按照以下代码更改一行代码。您不需要编写“print”,因为sfPP.py会添加打印指令。

' xy"' in 'abcd"xy"efg'
===============================
False

type __tempConverted.py
from __future__ import division
# -*- encoding: utf-8 -*-
from pysf.sfFnctns import *
setDctGlobals(globals())
from pysf.customize import *
if os.path.exists('./sfCrrntIni.py'):
    from sfCrrntIni import *
rightSideValueAt__= ' xy"' in 'abcd"xy"efg'
print "==============================="
print rightSideValueAt__
putPv(rightSideValueAt__, '_dt')

'"xy"' in 'abcd"xy"efg'
===============================
True

(这个例子代码也说明了为什么我敢用临时单行文件。聪明的Chris会理解原因。)

您可以在Emacs中轻松观看Python源代码,如下所示。

source(np.source)
In file: C:\Python27\lib\site-packages\numpy\lib\utils.py

def source(object, output=sys.stdout):
        snipped
    import inspect
    try:
        print >> output,  "In file: %s\n" % inspect.getsourcefile(object)
        print >> output,  inspect.getsource(object)
    except:
        print >> output,  "Not available for this object."

===============================
None
  

你应该看看IPython   我一直在看IPython youtube视频:IPython深入一点写一篇文章:“使用Vim / Emacs作为IPython”

你同意我使用Emacs作为IPython吗?


最后一个问题。 我想按下接受按钮。但我不知道它在哪里。 “这个帖子对你有用吗?是/否按钮”可能不是那个。

2 个答案:

答案 0 :(得分:2)

这是我掀起的事情:

(defun get-current-line ()
  (buffer-substring-no-properties (line-beginning-position)
                                  (line-end-position)))

(defun run-python-command (str)
  (shell-command-to-string
   (concat "/usr/bin/env python -u -m sfPP -c "
           (shell-quote-argument (concat "print(" str ")")))))

(defun eval-line-in-python ()
  "Evaluates the current line in python, then copies the result to the clipboard."
  (interactive)
  (let ((str (run-python-command (get-current-line))))
    (message str)
    (kill-new str)))

您可以使用M-x eval-line-in-python运行它。

我更改了它,因此它不使用临时文件,而是直接评估该行。如果你仍想写一个临时文件,这是一个微不足道的改变。

答案 1 :(得分:0)

对于偶然发现这一点的其他人,我修改了@Chris Barrett,以防止新行被python的print追加。此外,由于某种原因,使用-m module导入模块使命令返回无输出,因此我在literal命令中导入模块。

(defun run-python-command (str)
  (shell-command-to-string
   (concat "/usr/bin/python -c "
           (shell-quote-argument (concat "from myutils import *; import sys; sys.stdout.write(" str ")")))))