由于时间久远,这里就写出当时制作的大致思路。
基本思想是,另外开一个线程,每隔一段时间检测你的latex文件是否有改动,如果有改动则调用latex程序编译一下。如果使用bibtex的话注意需要有四个过程。至于查看需要借助SumatraPDF这个软件,因为它支持pdf动态修改并重新显示。
只要明白这个思路无论哪个程序做都行,比如其实用C#做就感觉比ruby方便(窗体程序)
一开始制作的是控制台程序,后来我尝试用ruby的TK实现窗体程序,在使用中又增加了一些细节修改,方便使用。然后一些软件及文件都用yaml配置文件进行配置
更新
2017-3-30在ruby3中发现有个API变了
@console_hand=Win32API.new('kernel32', 'GetConsoleWindow', 'i', 'l').call(0) # 貌似必须要传参
主程序如下
# 长虹剑 2015-11-16 bibtex是后续修改的
=begin
@main_file 这个我先固定了
编译时间,及是否编译可以控制
使用了TK,又让我对窗体编程有所了解,而且对ruby的对象机制有所了解。
root=TkRoot.new 生成一个类
class<<root
写你自己要加入的东西
end
定义各种部件的时候要传入root,一些控制的东西都通过root,所以root这个single类要定义好
Tk.mainloop运行
----------------------------- TK 布局等说明
http://www.tutorialspoint.com/ruby/ruby_tk_button.htm button
=end
require 'yaml'
require 'tk'
require 'Win32API'
root=TkRoot.new{title 'latex即时编译工具-made by CHJ'}
# my_object.instance_eval {}
class <<root #只有在root类中的才可以 ******
attr_accessor :compiler,:thread #不属于自己的不能直接用@
def run_base
@compiler=Latex_runtime_complie.new
@compiler.load_config
@compiler.sleep_time=3
@compiler.listen_control=:run
#隐藏掉控制台
@console_hand=Win32API.new('kernel32', 'GetConsoleWindow', 'v', 'l').call
@show_console=true
trigger_console
end #run
def trigger_console
if @show_console==true
Win32API.new('user32', 'ShowWindow', 'li', 'i').call(@console_hand, 0)
@show_console=false
else
Win32API.new('user32', 'ShowWindow', 'li', 'i').call(@console_hand, 1)
@show_console=true
end
end
class Latex_runtime_complie
attr_accessor :listen_control
attr_accessor :sleep_time
def initialize
@is_bibtex="T"
@config_file=FILEPATH+"/config.yaml"
@latex_file_path=""
@latex_file="LaTeX1"
# 我后来把这个放到配置文件中了 #@pdflatex_exe='...LaTeX\MiKTeX_2.9\miktex\bin\pdflatex.exe' #防止转意
#@bibtex_exe='...LaTeX\MiKTeX_2.9\miktex\bin\bibtex.exe' #防止转意
#多线程控制
@sleep_time=3
@listen_control=:run
# run 正常 pause 暂停 stop 退出
@last_file_mtime=-1 # 这样一开始一定会编译
end
def load_config
data = YAML.load_file(@config_file)
@pdflatex_exe=data['config']['pdflatex_exe']
@bibtex_exe=data['config']['bibtex_exe']
@is_bibtex=data['config']['is_bibtex']
@latex_file_path=data['config']['latex_file_path']
@latex_file=data['config']['latex_file']
@main_file=@latex_file_path+"\\"+@latex_file+".tex"
puts @main_file
@argument=%Q[-synctex=-1 -interaction=nonstopmode "#{@main_file}" ]
#puts @argument
# ***** 这里修改运行目录
Dir.chdir(@latex_file_path)
end
# 这个就是编译程序,ruby调用,bitex调用四次,普通的一次就行
def compile
#puts @pdflatex_exe+""+@argument
if @is_bibtex=="T"
puts system(@pdflatex_exe+" "+@latex_file);
puts system(@bibtex_exe +" "+@latex_file);
puts system(@pdflatex_exe+" "+@latex_file);
end
puts system(@pdflatex_exe+" "+@argument); #输出信息
#system(@pdflatex_exe+" "+@argument);
end
## 核心,通过文件修改时间决定是否重新编译
def listening
compile
bg=@last_file_mtime #File.mtime(@main_file)
while true
case @listen_control
when :run
ed=File.mtime(@main_file)
if bg!=ed
bg=ed
compile
end
when :pause
when :stop
@last_file_mtime=bg
return
end
sleep(@sleep_time)
end
end
end #class Latex_runtime_complie
end #添加的类属性
#相当于设置了主窗体
TkLabel.new {
width 15
height 3
#pack
grid('row'=>0, 'column'=>0)
}
BTrun=TkButton.new(root){
text " 运行 "
width 8
#height 1
#pack :padx=>2,:pady=>2,:side=>'bottom'
grid('row'=>0, 'column'=>3,'padx'=>5,'pady'=>5)
command{
root.compiler.listen_control=:run
if root.thread && root.thread.alive?
root.thread.exit
end
root.thread = Thread.new {root.compiler.listening}
BTstop.state="normal"
BTrun.state="disabled"
}
}
BTstop=TkButton.new(root){
text " 停止 "
width 8
state "disabled"
#pack :padx=>3,:pady=>2,:side=>'bottom'
grid('row'=>1, 'column'=>3,'padx'=>5,'pady'=>5)
command{
root.compiler.listen_control=:stop if root.thread
BTrun.state="normal"
BTstop.state="disabled"
}
}
TkButton.new(root){
text "exit"
#pack :padx=>2,:pady=>2,:side=>'bottom'
grid('row'=>0, 'column'=>0,'padx'=>5,'pady'=>5) #,'columnspan'=>2
command{
if root.thread
root.thread.exit if root.thread.alive?
end
exit
}
}
var=TkVariable.new
TkEntry.new(root){
text var #这个变量就会不断被监控
width 5
grid('row'=>1, 'column'=>1)
}
TkButton.new(root){
text "set"
#pack :padx=>2,:pady=>2,:side=>'bottom'
grid('row'=>1, 'column'=>0,'padx'=>5,'pady'=>5)
command{
if var=~/\d+/
var=var.to_i
if var>=1
root.compiler.sleep_time=var
#puts var
end
end
}
}
TkButton.new(root){
text "控制台"
#pack :padx=>2,:pady=>2,:side=>'bottom'
grid('row'=>0, 'column'=>1,'padx'=>5,'pady'=>5)
command{
root.trigger_console
}
}
root.run_base
Tk.mainloop
config.yaml 文件内容如下
config:
is_bibtex: T
pdflatex_exe: pdflatex.exe 的绝对路径
bibtex_exe: bibtex.exe 的绝对路径
latex_file_path: 你的latex文件的目录
latex_file: 你的latex文件名(不加后缀.tex)
# bibtex 取值为 T / F