vim latex-suite Understand MainFileExpression - vim

I want to dynamically change the way latex-suite determines the MainFile.
The main file is usually the latex header file which includes other tex files (like chapters and so on). Using the MainFile it is possible to hit compile on some chapter-file so that latex-suite automatically compiles the header file instead.
This should be possible with g:Tex_MainFileExpression:
http://vim-latex.sourceforge.net/documentation/latex-suite/latex-master-file.html
However, the expression is not documented at all and even the example (which imo should reflect the default behavior) does not work.
let g:Tex_MainFileExpression = 'MainFile(modifier)'
function! MainFile(fmod)
if glob('*.latexmain') != ''
return fnamemodify(glob('*.latexmain'), a:fmod)
else
return ''
endif
endif
Can somebody please shortly point out to me how this is supposed to be used?
What return expression is expected? Why does the example not work?
Background: I have a latexmain file in the project root. I also have a figure subdirectory. For this subdirectory the root latex main should not be ignored, so that the current file itself is compiled.

I just ran into the problem of not knowing how to set g:Tex_MainFileExpression as well. The documentation and the example were not clear to me either. Turns out, the source code defines a function Tex_GetMainFileName, which sets the variable modifier from its arguments before executing g:Tex_MainFileExpression (see source code here). Therefore, g:Tex_MainFileExpression needs to be a function that has the argument modifier (not called differently!). The vim-latex documentation says, that modifier is a filetype-modifier, therefore your function needs to return fnamemodify(filename, modifier). So it has to look like this:
let g:Tex_MainFileExpression = 'MainFile(modifier)'
function! MainFile(fmod)
" Determine the full path to your main latex file that you want to compile.
" Store it e.g. in the variable `path`:
" let path = some/path/to/main.tex
" Apply `modifier` to your `path` variable
return fnamemodify(path, a:fmod)
endif
Example
I used this in a project where I have a two main latex files, one for the main document and one for supplementary material. The project structure looks like this:
project/
main.tex
sup.tex
.local-vimrc
main-source/
input1.tex
input2.tex
sup-source/
input1.tex
input2.tex
I load a .local-vimrc file (using the plugin MarcWeber/vim-addon-local-vimrc), where I set g:Tex_MainFileExpression such that <leader>ll compiles main.tex if the file in the current buffer is located in the folder main-source and compiles sup.tex if it is in the folder sup-source. Below is my .local-vimrc file. I have very little experience with vimscript, so this is probably a littly hacky, but it might help to get an idea on how to use g:Tex_MainFileExpression. Also, I have modified it to be less messy and not tested the following code explicitly.
let g:Tex_MainFileExpression = 'g:My_MainTexFile(modifier)'
function! g:My_MainTexFile(fmod)
" Get absolute (link resolved) paths to this script and the open buffer
let l:path_to_script = fnamemodify(resolve(expand('<sfile>:p')), ':h')
let l:path_to_buffer = fnamemodify(resolve(expand('%:p')), ':h')
" Check if the buffer file is a subdirectory of `main-source` or `sup-source`
" stridx(a, b) returns -1 only if b is not substring of a
if stridx(l:path_to_buffer, 'main-source') != -1
let l:name = 'main.tex'
elseif stridx(l:path_to_buffer, 'sup-source') != -1
let l:name = 'sup.tex'
else
echom "Don't know what's the root tex file. '".#%."' is not in 'main-source/' or 'sup-source/' directory."
return ''
endif
" Concatenate this script path with main latex file name
" NOTE: this assumes that this script is located in the same folder as the
" main latex files 'main.tex' and 'sup.tex'
let l:path = l:path_to_script.'/'.l:name
return fnamemodify(l:abs_path_main, a:fmod)
endfunction

Related

VIM Highlight Numbers in LineNumber Column based on .pdbrc file contents

Hi so I am looking for a method for highlighting a subset of numbers in the LineNumber column of vim. Maybe highlight is a bad choice, it could be as simple as just changing the background/foreground color of specific numbers.
My example
.pdbrc
b ~/foo.py:3
b ~/foo.py:7
when I open foo.py in VIM I would like lines 3 and 7 to be highlighted or have a different background color than the rest of the line numbers.
Basically I am just looking for a way to visually tell me, in VIM, where I have breakpoints set up in a file as per my .pdbrc
From my searching I believe this is not possible, but I don't know how VIM works very well and as such I may be misinterpreting the stackoverflow posts I have read.
What I've got so far, this will return a list of line numbers from the .pdbrc how do I take this list of numbers and highlight them or change their background color conditionally in vimscript?
function! s:parse_pdbrc(cur_file_abs_path)
" read the .pdbrc lines and search for current in
let s:lines = readfile("~/.pdbrc")
" parse the filepath to make it regexable
let s:file = substitute(a:cur_file_abs_path, "/", "\/", "")
let s:file = substitute(s:file, ".", "\.", "")
let s:regex = join(['b\s+',s:file,':(\d+)'],'')
" make some storage
let s:alist = []
" iterate over the lines
for s:line in s:lines
" check if cur_file in line
let s:match = matchlist(s:line, s:regex)
" if we have a match store it
if !empty(s:match)
let s:alist = add(s:alist, s:match[1])
endif
endfor
return s:alist
endfunction

Select a directory in vim and use it's name in function call

Inside a vim function I would like to have the user select a directory (instead of writing its name), I guess using :Explore, then get the filename of that directory and pass it to another function for example.
E.g. something like this
function! Test()
let directory = ????
call Test2(directory)
endfunction
This can be achieved with the browsedir() function:
function! Test()
let initialDir = '/home/'
let directory = browsedir('my prompt title', initialDir)
echo "directory = ".directory
endfunction

Linux application in livecode

Spell Check is a default application in Linux. With the help of that application, can we check the spelling of a text field while users enter data?
Some (or many?) Linux distributions contain a command line utility that is called spell. If you run this with words as parameters, you need to press return a second time, but if you use a file as a paramater, you don't need to press return again. This means that a solution could be:
write the text of a field to a file
run the command line utility from LiveCode's shell function with the file as parameter
parse the result returned by the shell function
Before you try this, open your terminal on Linux and type spell. Press enter to see if the command is recognised. If yes, then the script below should work.
This script writes the text of a field to a file, does a spell check on the file and returns the incorrect words to LiveCode. I haven't tested the script and you may have to tweak it a little.
function spellCheck theText
// works on Linux only
if the platform is "Linux" then
// remove everything that isn't a word
put replaceText(theText,"[^\w]","") into myWords
// write clean data to a temporary file
put the tempName into myTempFile
put myWords into url ("file:" & myTempFile)
// call spell with shell
put "spell" && myTempFile into myShell
// only return the incorrect words
put line 2 to -1 of shell(myShell) into myCorrections
// return the incorrect words to calling handler
return myCorrections
else
// this isn't Linux
return "error"
end if
end spellCheck
//theField is the short name of a field
on checkField theField
// call above function
put spellCheck(the text of fld theField) into myWords
// myWords should now contain the incorrect words
if myWords is not "error" then
lock screen
// parse incorrect words and mark them in the field
repeat with x = 1 to number of words of field theField
if myWord is among the lines of myWords then
// an incorrect word has been found and is marked red
set the textColor of word x of fld theField to red
end if
end repeat
unlock screen
end if
end checkField
Usage: checkField shortNameOfTheField

vim how to create a debug message fast

I am using ruby on rails but that does not matter much for this question. Let's say that i have a statement like this
error = 'this is an error message'
I have noticed that I end up doing this a lot
error = 'this is an error message'
puts "error = #{error.inspect}"
I am sure a macro can be written which would take the work on the left hand side of left most = and then create another line along with template shown above.
I am using mvim on mac. Any pointer in terms of where I should start to look for developing what I want.
Try snipmate:
http://www.vim.org/scripts/script.php?script_id=2540
I recorded a simple macro that does your sample. To record a macro type q followed by what register you want the macro to be put in (convention calls for qq). To play the macro type # then the macro register. You can view this at :help recording
To write the macro, use the following commands (and here is how is should look in the register)
^yEoputs "error = #{^Op.inspect}"^[
^ moves to the first non whitespace character of the line
yE yanks to the end of the space separated word.
o Puts you in insert mode on the next line
puts "error = #{ is the text that you type out
^O is ctrl+O (capital letter o) - this allows the next, and only the next command to be run in command mode, which is...
p Puts the yanked word, after this command is run you're still in insert mode
.inspect}" is the text that you type and finally...
^[ is Esc
I would go for:
nnoremap µ :s/^\s*\(\k\+\)\s*=.*/&\rputs "\1 = #{\1.inspect}"/<cr>
:s presents the advantage of doing the job plus matching the assigned variable if any. Doing the same thing with classical commands like yw, p, etc would be more cumbersome.
If the template become more complex, we can rely on template-file expanders as long as they easily permit to call viml function like matchstr(). Of course, in that case I would use mu-template with the following template-file:
VimL:" $Id: {rtp}/template/ruby/inspect.template
VimL: let s:value_start = '¡'
VimL: let s:value_end = '¡'
VimL: let s:reindent = 1
VimL: let s:marker_open = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:varname = matchstr(getline(line('.')-1), '^\s*\zs\k\+\ze\s*=')
VimL: if empty(s:varname) |throw "the previous line don't assign any variable" |endif
puts "¡s:varname¡ = #{¡s:varname¡.inspect}"<++>
VimL:"vim: encoding=utf-8
If you're doing these on the fly, a snipmate snippet could look like this:
${1:error} = '${2:error message here}'
puts "error = #{$1.inspect}"
If, on the other hand you're just wanting to output pre-existing variables for debugging purposes. Nick-Canzoneri's macro may be more useful.

In vim, how to write a partial line to a file?

I want to use vim to write a part of my file to another file. For example, I have the following file:
This is line 1
and this is the next line
I want my output file to read:
line 1
and this is
I know how to use vi to write a range of lines to a file:
:20,22 w partial.txt
An alternative is to visually select the desired text and then write:
:'<'> w partial.txt
However, when using this method, vim insists on writing the full line in the output, and I have found no way to write a partial line. Any thoughts?
I've got two (very similar) approaches to this. There's no way to do it with the built in write command, but it's fairly easy to generate your own function that should do what you want (and you can call it what you like - even W if you want).
A very simple approach that will only handle single-line ranges is to have a function like this:
command! -nargs=1 -complete=file -range WriteLinePart <line1>,<line2>call WriteLinePart(<f-args>)
function! WriteLinePart(filename) range
" Get the start and end of the ranges
let RangeStart = getpos("'<")
let RangeEnd = getpos("'>")
" Result is [bufnum, lnum, col, off]
" Check both the start and end are on the same line
if RangeStart[1] == RangeEnd[1]
" Get the whole line
let WholeLine = getline(RangeStart[1])
" Extract the relevant part and put it in a list
let PartLine = [WholeLine[RangeStart[2]-1:RangeEnd[2]-1]]
" Write to the requested file
call writefile(PartLine, a:filename)
endif
endfunction
This is called with :'<,'>WriteLinePart test.txt.
If you want to support multiple line ranges, you could either expand this to include varying conditions, or you could pinch the code from my answer to this question. Get rid of the bit about substituting backslashes and you could then have a very simple function that does something like (untested though...) this:
command! -nargs=1 -complete=file -range WriteLinePart <line1>,<line2>call writelines([GetVisualRange()], a:filename)

Resources