Vim LÖVEr + gnu preprocessor + make
Posted: Sun Dec 08, 2013 12:06 pm
I thought I'll share my love related environment, maybe someone else will find it useful.
This will be rather long, so take your popcorn and let's start the ride...
Preprocessor
What I was missing most, was the ability to create different versions of application (game).
Sure you can just put some if statements, but a) I don't want them in 'release code' b) even if they are false, I actually don't want those if statements executing (especially inside some tight loop).
So I thought about using some kind of preprocessor. Imagine you can write following code:
There are some simple preprocessors written in lua:
Even SimpleLuaPreprocessor would be fine for my needs, but I thought It'll be much easier to incorporate something I'm familiar with.
So here comes in GNU C preprocessor. In quite short time I've written following Makefile:
So inside dir I have mixture of *.lua and *.luah files. When I run make it converts all the *.luah-s to *lua-s than it runs LOVE, and after love terminates it removes 'generated' *.lua-s (leaving non-generated ones untouched).
Vim
This worked nicely, but as stated in subject, I'm a VIM user, and with stuff above syntax highlighting wasn't working as expected. So I've modified my lua.vim file to handle that. you'll find it in attachment. (In my case it resides inside c:\users\gim\vimfiles\syntax\)
Besides handling #ifdef blocks it also adds highlighting for some love modules and functions and also adds folding, more on that later.
As I've mentioned, small change in lua.vim also adds folding, this is fragment of my vimrc file:
This does two things a) turns on syntax-based folding for *.lua(h) files and b) maps f7 to make, so I can run LOVE using make from within VIM
This is how file actually looks right after loading with folding enabled:
errors (overkill?)
This all was working quite fine, but the problem I had is that whenever exception happened vim was pointing me at wrong locations
(to *.lua file instead of *.luah and numbers were all wrong - cause after preprocessing, line numer inside *.luah != line number in *.lua).
So I've did few things to fix this. First I've changed the way files are generated, and now from single *.luah I'm generating two files: *.lua and *.lua_x
*.lua_x is 'full' cpp output along with line informations (-P flag dropped), those informations are stripped with sed and output placed in *.lua, so corresponding line
from Makefile now looks like this:
Now Vim docs suggest creating filter for make (it receives make output so there is also love stacktrace there ).
So I've written small script in python, that does few things:
Now there's only one thing to do, tell vim to use preprocessor, and inform it how errorline looks like, _vimrc:
And that's how it finally looks:
now I can Enter or double click inside cope window
edit: forgot to attach lua.vim file
This will be rather long, so take your popcorn and let's start the ride...
Preprocessor
What I was missing most, was the ability to create different versions of application (game).
Sure you can just put some if statements, but a) I don't want them in 'release code' b) even if they are false, I actually don't want those if statements executing (especially inside some tight loop).
So I thought about using some kind of preprocessor. Imagine you can write following code:
Code: Select all
#ifdef DEBUG
math.randomseed(123)
#else
math.randomseed( tonumber(tostring(os.time()):reverse():sub(1,6)) ) -- from http://lua-users.org/wiki/MathLibraryTutorial
#endif
So here comes in GNU C preprocessor. In quite short time I've written following Makefile:
Code: Select all
LUAHS= $(wildcard engine/*.luah *.luah)
LUAS = $(LUAHS:.luah=.lua)
#LOVE = \projects\love-0.8.0-win-x64\love.exe
LOVE = \projects\love-luajit\love.exe
RM = rm
DEFINES = -DxMAP_33 -DMAP_FIXUP_DEBUG
all: clean
clean: run
$(RM) $(LUAS)
run: preprocess
$(LOVE) .
preprocess: $(LUAS)
%.lua: %.luah
$(CC) $(DEFINES) $(CFLAGS) -E -traditional -P -x c $< -o $@
Vim
This worked nicely, but as stated in subject, I'm a VIM user, and with stuff above syntax highlighting wasn't working as expected. So I've modified my lua.vim file to handle that. you'll find it in attachment. (In my case it resides inside c:\users\gim\vimfiles\syntax\)
Besides handling #ifdef blocks it also adds highlighting for some love modules and functions and also adds folding, more on that later.
As I've mentioned, small change in lua.vim also adds folding, this is fragment of my vimrc file:
Code: Select all
au BufRead,BufNewFile *.lua set foldmethod=syntax relativenumber
au BufRead,BufNewFile *.luah set foldmethod=syntax relativenumber
map <f7> :make<cr>
cope 5
This is how file actually looks right after loading with folding enabled:
errors (overkill?)
This all was working quite fine, but the problem I had is that whenever exception happened vim was pointing me at wrong locations
(to *.lua file instead of *.luah and numbers were all wrong - cause after preprocessing, line numer inside *.luah != line number in *.lua).
So I've did few things to fix this. First I've changed the way files are generated, and now from single *.luah I'm generating two files: *.lua and *.lua_x
*.lua_x is 'full' cpp output along with line informations (-P flag dropped), those informations are stripped with sed and output placed in *.lua, so corresponding line
from Makefile now looks like this:
Code: Select all
%.lua: %.luah
$(CC) $(DEFINES) $(CFLAGS) -E -traditional -x c $< -o $@_x
sed "s/^#.*//" $@_x > $@
So I've written small script in python, that does few things:
- In the input, it looks for beginning of stack trace (naively with: if line.startswith('Error'))
- It check if file exist, if not it assumes this file was produced from *.luah file, in such case:
- It opens *_x (extended) file, and goes through it, checking the cpp # directives, as they contain ORIGINAL line numbers
- Additionally it precedes every line with "Error" (will be handy in next step)
Code: Select all
#!/usr/bin/env python
import sys,re,os,os.path
gccNum=re.compile(r'# (\d+)')
def properNumber(fName, lineNo):
no = 0
virt = 0
for l in open(fName+'_x', 'r'):
no += 1
virt += 1
if no == lineNo:
break
m = gccNum.match(l)
if m:
virt = int(m.group(1)) -1
return virt
catMode=False
errorLine=re.compile(r'\s([^[:]+?):(\d+):(.*)')
for line in sys.stdin:
if line.startswith('Error: '):
catMode=True
line=line[6:]
if catMode:
m = errorLine.search(line)
if m and m.group(1).endswith('.lua'):
prefix='Error: '
if os.path.exists(m.group(1)):
print prefix+line,
else:
lineNo = properNumber(m.group(1), int(m.group(2)))
print prefix+m.group(1)+'h:'+str(lineNo)+':'+m.group(3)
# if you want to drop 'non-file' lines, drop this else block
else:
print line.strip()
Code: Select all
au BufRead,BufNewFile *.lua set foldmethod=syntax relativenumber mp=make\\\|python\ $HOME/vimfiles/makelove.py errorformat=Error:\ %f:%l:\ %m
au BufRead,BufNewFile *.luah set foldmethod=syntax relativenumber mp=make\\\|python\ $HOME/vimfiles/makelove.py errorformat=Error:\ %f:%l:\ %m
now I can Enter or double click inside cope window
edit: forgot to attach lua.vim file