用ruby实现latex自动编译

由于时间久远,这里就写出当时制作的大致思路。
基本思想是,另外开一个线程,每隔一段时间检测你的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<
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

你可能感兴趣的:(ruby)