从vim发送代码到stata

8 投票
4 回答
1569 浏览
提问于 2025-04-16 07:20

我在大学里用Vim写Stata脚本已经有一段时间了。现在我正在学习R,并且想完全换成Linux系统(我最近在我的笔记本上安装了Ubuntu)。R在Windows和Linux上都能和Vim很好地配合使用,不过我有时候还是需要用到Stata。在Windows上,我用一个Stata用户提供的简单AutoIt脚本,把代码行或整个文件发送到Stata进行评估。但是这个脚本在Linux上不管用。

这个脚本长这样:

; AutoIt v3 script to run a Stata do-file from an external text editor
; Version 3.1, Friedrich Huebler, fhuebler@gmail.com, www.huebler.info, 30 March 2009

; Declare variables
Global $ini, $statapath, $statawin, $dofile, $winpause, $keypause, $clippause

; File locations
; Path to INI file
$ini = @ScriptDir & "\rundo.ini"
; Path to Stata executable
$statapath = IniRead($ini, "Stata", "statapath", "C:\Program Files\Stata10\wsestata.exe")
; Title of Stata window
$statawin = IniRead($ini, "Stata", "statawin", "Stata/SE 10.1")

; Path to do-file that is passed to AutoIt
; Edit line to match editor used, if necessary
$dofile = $CmdLine[1]

; Delays
; Pause after copying of Stata commands to clipboard
$clippause = IniRead($ini, "Delays", "clippause", "100")
; Pause between window-related operations
$winpause = IniRead($ini, "Delays", "winpause", "200")
; Pause between keystrokes sent to Stata
$keypause = IniRead($ini, "Delays", "keypause", "1")

; Set SendKeyDelay and WinWaitDelay to speed up or slow down script
Opt("WinWaitDelay", $winpause)
Opt("SendKeyDelay", $keypause)

; If more than one Stata window is open, the window 
; that was most recently active will be matched
Opt("WinTitleMatchMode", 2)

; Check if Stata is already open, start Stata if not
If WinExists($statawin) Then
  WinActivate($statawin)
  WinWaitActive($statawin)
  ; Activate Stata Command Window and select text (if any)
  Send("^4")
  Send("^a")
  ; Run saved do-file
  ; Double quotes around $dofile needed in case path contains blanks
  ClipPut("do " & '"' & $dofile & '"')
  ; Pause avoids problem with clipboard, may be AutoIt or Windows bug
  Sleep($clippause)
  Send("^v" & "{Enter}")
Else
  Run($statapath)
  WinWaitActive($statawin)
  ; Activate Stata Command Window
  Send("^4")
  ; Run saved do-file
  ; Double quotes around $dofile needed in case path contains blanks
  ClipPut("do " & '"' & $dofile & '"')
  ; Pause avoids problem with clipboard, may be AutoIt or Windows bug
  Sleep($clippause)
  Send("^v" & "{Enter}")
EndIf

; End of script

在我的vimrc文件里有以下内容:

" STATA DO-FILE SCRIPTS

fun! RunIt()
  w
  !start "C:\Programme\Stata10\integvim\rundo3\rundo.exe" "%:p"
endfun
map <F8> :<C-U>call RunIt()<CR><CR>
imap <F8> <Esc>:<C-U>call RunIt()<CR><CR>

fun! RunDoLines()
  let selectedLines = getbufline('%', line("'<"), line("'>"))
 if col("'>") < strlen(getline(line("'>")))
  let selectedLines[-1] = strpart(selectedLines[-1], 0, col("'>"))
  endif
 if col("'<") != 1
  let selectedLines[0] = strpart(selectedLines[0], col("'<")-1)
  endif
 let temp = tempname() . ".do"
  call writefile(selectedLines, temp)
    exec "!start C:\\Programme\\Stata10\\integvim\\rundo3\\rundo.exe " . temp
    au VimLeave * exe "!del -y" temp
endfun
map <F9> :<C-U>call RunDoLines()<CR><CR> 
imap <F9> <Esc>:<C-U>call RunDoLines()<CR><CR> 

这个功能非常实用,几乎是我还在坚持用Windows的唯一原因。我该如何在Ubuntu上实现类似的功能呢?我对Linux还很陌生,除了统计学之外,对编程了解不多。任何帮助都非常感谢。 (请不要建议使用emacs,因为emacs对Stata的支持有问题,虽然它和R的结合要好得多,但我现在还是想继续用Vim。)

另外一个可能相关的话题是:我在考虑学习Python,因为我可能会长时间处理数据和进行实证分析,我觉得这对一些任务可能会有帮助,比如解决像这样的难题或从网站解析数据。你觉得这样推荐吗,还是我应该看看其他语言(或者干脆放弃这个想法)?

4 个回答

1

[编辑]: 哎呀,我注意到你的主要问题是关于AutoIt脚本的,抱歉我不知道怎么把这个转换到Linux上。我觉得没有简单的方法。你可以看看xautomation或者其他类似的工具,但那完全是另外一回事。

在你的 .vimrc 文件中,把:

!start "C:\Programme\Stata10\integvim\rundo3\rundo.exe" "%:p"

替换成在Linux中做同样事情的命令。它应该看起来像这样:

!/usr/share/... "%:p"

因为我对Stata一无所知,你得从其他人那里找到确切的命令。

另外,我不太确定 "%:p" 是什么:请查阅vim的帮助文档,比较一下Windows和Linux之间的区别。

1

如果你打算长期使用Linux,建议你可以做以下几件事:
1. 打电话给Stata,把你的许可证换成Linux版本的(他们会免费帮你处理),然后在Linux上直接安装Stata。这样你就可以通过vim启动Stata,只需要写一个bash脚本就行(我对vim不是很在行)。
2. 你也可以购买Stata 11,这个版本的许可证可以在所有支持的平台上使用。
3. 你还可以用Wine来安装Stata(我用Play on Linux让这个过程变得简单),但我遇到的问题是Wine只能给Stata分配不到一半的内存,所以我最终选择安装了原生的Stata 10。

我用gedit来写Python、Stata、R、LaTeX等等,它能处理各种文件,而且gtksourceview也很容易添加语法高亮和样式等功能。

Python在数据分析方面非常不错,推荐你看看这些网站:
http://www.scipy.org/
http://openopt.org/Welcome
http://www.macworld.com/appguide/app.html?id=63924&expand=false

如果你想抓取网站数据,可以参考这些:
http://scrapy.org/
http://wwwsearch.sourceforge.net/mechanize/

而对于从文本中解析数据,我们通常会用到:
http://pyparsing.wikispaces.com/

我有一些你可能会觉得有用的文件(比如Stata和其他软件的gtksourceview语言定义,还有一些书的PDF版本(有些是共享版权的)),但我不知道怎么在这个网站上附加文件。

1

我现在很少用stata了,但之前有一段时间用bash写了个简单的解决方案。这个脚本可以通过在我的.vimrc文件里加几行代码来执行,效果不错。不过你可能需要根据自己电脑的情况调整一下延迟时间。

#!/bin/bash

# needs wmctrl, xte and xsel
# to get them run
# sudo apt-get install wmctrl xautomation xsel
# in debian/ubuntu linux

#copy to clipboard "do filename"
echo 'do ' '"'$1'"' | xsel -b

# get current window id
winid = $(xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}')

# check for stata window, if found activate else execute
# use correct version here
if [ "$(pgrep stata)" ] 
then
    wmctrl -a 'Stata/MP 11.2'
else
    xstata &
    sleep .1 
fi

# delay depends on window manager etc
# .1 ok with xmonad in 10.04
sleep .1 

# switch to command line, ctrl-4 in stata 10, ctrl-1 in 11/12
# and select existing text via ctrl-a
xte 'keydown Control_L' 'key 1' 'key A' 'usleep 100' \
    'key V' 'keyup Control_L' 
sleep .1
xte 'key Return'
sleep .3


# go back to editor window
wmctrl -i -a $winid 

调整一下这个内容,然后把它放到你的vimrc文件里。

"" STATA DO-FILE SCRIPTS
fun! RunIt()
  w
  "adjust this path to the bash script
  !sh "/home/username/.rundo.sh" "%:p"
endfun
au FileType stata noremap <F8> :<C-U>call RunIt()<CR><CR>
fun! RunDoLines()
  let selectedLines = getbufline('%', line("'<"), line("'>"))
 if col("'>") < strlen(getline(line("'>")))
  let selectedLines[-1] = strpart(selectedLines[-1], 0, col("'>"))
  endif
 if col("'<") != 1
  let selectedLines[0] = strpart(selectedLines[0], col("'<")-1)
  endif
 let temp = tempname() . ".do"
  call writefile(selectedLines, temp)
          "adjust this path to the bash script
          exec "!sh /home/username/.rundo.sh " . temp
    "au VimLeave * exe "!del -y" temp
    au VimLeave * silent exe '!del /Q "'.$TEMP.'\*.tmp.do"'
endfun
au FileType stata noremap <F9> :<C-U>call RunDoLines()<CR><CR> 

撰写回答