Skip to content
This repository has been archived by the owner on Jul 28, 2021. It is now read-only.

Commit

Permalink
initial import
Browse files Browse the repository at this point in the history
  • Loading branch information
naquad committed Jun 22, 2013
0 parents commit ecd3777
Show file tree
Hide file tree
Showing 11 changed files with 1,156 additions and 0 deletions.
39 changes: 39 additions & 0 deletions README.md
@@ -0,0 +1,39 @@
# LGS.vim

Adds integration with [Laravel 4 Generator bundle](https://github.com/JeffreyWay/Laravel-4-Generators) through LG command allowing user to generate various entities w/o leaving VIM. Convinient navigation through generated/updated files included. This is a very early release, please file bugs if you find any.

## Installation

If you're using Pathogen.vim, Vundle or similar software consult their documentation. In case if you're using plain VIM just throw contents of this repository to `~/.vim` directory (or ~/_vim Win32 users).

## Usage

LGS.vim provides one single command for invoking generators: `LG`

Examples:

```
" Generates NewModel
LG model NewModel
" Generates controller Controller
LG controller MyController
" Will insert form for model Model into current buffer at cursor position
LG form NewModel
" You can also specify options for generators
LG form --method=create --html=ul ModelName
" Syntax with = is supported too
LG controller --path=/path/to/template ControllerName
```

See documentation for more details.

## Known issues

First of all current discovery of models is very basic and fragile. It is a piece of code executed in `artisan ticker` console. You can find it in `misc/get_models.php`.

Environment discovery is very dumb: mock `Application` class, load `bootstrap/start.php` catch `detectEnvironment`. In case if `detectEnvironment` is called after some work with `Application` instance it'll just crash and you won't get any completion.
151 changes: 151 additions & 0 deletions autoload/lgs/artisan.vim
@@ -0,0 +1,151 @@
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"" LGS
""
"" VIM interface for Laravel 4 generator bundle
"" (https://github.com/JeffreyWay/Laravel-4-Generators)
""
"" Copyright 2013 Naquad.
""
"" This program is free software; you can redistribute it and/or modify
"" it under the terms of the GNU General Public License as published by
"" the Free Software Foundation; either version 3 of the License, or
"" (at your option) any later version.
""
"" This program is distributed in the hope that it will be useful,
"" but WITHOUT ANY WARRANTY; without even the implied warranty of
"" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
"" GNU General Public License <http://www.gnu.org/licenses/>
"" for more details.
""
""
"" Pack of Artisan-related functions. Running, parsing output
"" of generators etc...
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

if &cp || exists('g:lgs_artisan_autoload_done')
finish
endif

" Look through directories from current up to root
" for file artisan .
function! lgs#artisan#FindArtisan(start)
let path = fnamemodify(a:start, ':p')

if !isdirectory(path)
let path = fnamemodify(path, ':h')
endif

let min_len = has('win32') + 1

while strlen(path) > min_len
let artisan = path . '/artisan'

if filereadable(artisan)
return artisan
endif

let path = fnamemodify(path, ':h')
endwhile

return ''
endfunction

" Checks if buffer has associated artisan file path.
" Adds association if not.
function! lgs#artisan#SetArtisanPathIfNeed()
if !exists('b:artisan')
let b:artisan = lgs#artisan#FindArtisan(expand('%'))
return b:artisan != ''
elseif b:artisan != ''
return filereadable(b:artisan)
else
return 0
endif
endfunction

" Output of generators shows
" app/database/migrations/Create_Xyz_table.php
" while really it name is
" app/database/migrations/time_stamp_create_xyz_table.php
"
" To handle this case whenever path with /database/migrations/ substring
" is encountered it is transformed for glob() function and first globbed
" file is.
function! s:MigrationPattern(path)
return substitute(a:path, '\(/database/migrations/\)\(.\+\)', '\=submatch(1) . "*_" . tolower(submatch(2))', '')
endfunction

" Runs artisan analyzing its output.
" Lots of mess here, definitely requires refactoring. Once.
function! lgs#artisan#RunArtisan(cmd, parse)
let result = system(a:cmd . ' 2>&1')

if v:shell_error " exception raised
let error = matchlist(result, '\[.*Exception\]\_s\+\([^\n]\+\)')

if empty(error) " can we figure out what is the error?
return [0, insert(lgs#utils#StringList(result), 'UNKNOWN ERROR', 0)]
else " if yes then show pretty error
return [0, [substitute(error[1], '^\_s\+\|\_\s\+$', '', 'g')]
endif
elseif a:parse
let files = [1, []]

let base = fnamemodify(b:artisan, ':p:h') . '/'
let bl = strlen(base) - 1

" Here we're looking a file name in string.
" It is indeed possible to use known prefixes ("Created ", "Updated ", ...)
" but I didn't wan't to have hardcoded strings.
for line in lgs#utils#StringList(result)
let i = 0
let added = 0

while 1
let path = line[i :]
if path[: bl] == base " make path relative if possible
let path = path[bl + 1 : ]
endif

if match(path, '/database/migrations/') != -1 " is that migration?
let t = glob(s:MigrationPattern(path), 0, 1) " glob it first
if !empty(t) " file found, use it
let path = t[0]
endif
endif

if filereadable(path)
let added = 1
call add(files[1], {'filename': path, 'nr': len(files[1]), 'text': tolower(line[: i - 1])})
break
endif

let i = match(line, '\s', i + 1) + 1
if i == 0
break
endif
endwhile

if !added
call add(files[1], {'nr': len(files[1]), 'text': line})
endif
endfor

return files
else
return [1, lgs#utils#StringList(result)]
endif
endfunction

" Builds command line for invoking artisan
function! lgs#artisan#MakeArtisanCommand(...)
let cmd = ''

if !executable(b:artisan)
let cmd = shellescape(g:lg_php) . ' '
endif

return shellescape(b:artisan) . ' ' . join(map(copy(a:000), 'shellescape(v:val)'), ' ')
endfunction

let g:lgs_artisan_autoload_done = 1
137 changes: 137 additions & 0 deletions autoload/lgs/cmd.vim
@@ -0,0 +1,137 @@
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"" LGS
""
"" VIM interface for Laravel 4 generator bundle
"" (https://github.com/JeffreyWay/Laravel-4-Generators)
""
"" Copyright 2013 Naquad.
""
"" This program is free software; you can redistribute it and/or modify
"" it under the terms of the GNU General Public License as published by
"" the Free Software Foundation; either version 3 of the License, or
"" (at your option) any later version.
""
"" This program is distributed in the hope that it will be useful,
"" but WITHOUT ANY WARRANTY; without even the implied warranty of
"" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
"" GNU General Public License <http://www.gnu.org/licenses/>
"" for more details.
""
""
"" HARDCORE! This is implemnetation of parser for command line arguments.
"" Problem is that to provide reliable completion for commands
"" one needs to know all arguments. I didn't find anything in VIM
"" so had to write one.
""
"" Not sure this is a the best possible implementation, but it works.
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

if &cp || exists('g:lgs_cmd_autoload_done')
finish
endif

" Double quoted escape characters
let s:escaped = {
\ 't': "\t",
\ 'n': "\n",
\ 'r': "\r",
\ 'e': "\e",
\ 'b': "\b",
\ '"': "\"",
\ '\': "\\"
\ }

" Used in substitution
function! lgs#cmd#UnquoteString(m)
if empty(a:m)
return ''
endif

return get(s:escaped, a:m, a:m)
endfunction

" Here come the dragons.
" This is function implements finite state machine for parsing command line
" AND unquoting functionality.
" I think it is possible to make some more generic implementation of
" completion so this won't be needed, but same time I wanted more
" general solution that could be reused later.
function! lgs#cmd#Str2ParamList(str)
let len = strlen(a:str)
let slider = max([0, match(a:str, '\S')])
let start = slider
let stack = []

let params = []

while slider < len
let c = a:str[slider]

if c == ' ' && empty(stack) && slider > start
call add(params, [start, slider - 1, a:str[start : slider - 1]])

let slider = match(a:str, '\S', slider) - 1
if slider < 0
break
endif

let start = slider + 1
elseif c == '\'
if empty(stack) || stack[-1] == '"'
let slider = slider + 1
endif
elseif c == '"' || c == "'"
if empty(stack)
call add(stack, c)
elseif stack[-1] == c
call remove(stack, -1)

call add(params, [start, slider, a:str[start : slider]])
let start = max([slider + 1, match(a:str, '\S', slider + 1)])
endif
endif

let slider = slider + 1
endwhile

if start != slider && slider > 0
call add(params, [start, len, a:str[start :]])
endif

for param in params
let qtype = param[2][0]

if qtype == "'"
let param[2] =
\ substitute(substitute(param[2], "^'\\|'$", '', 'g'), "''", "'", 'g')
elseif qtype == '"'
let end = matchstr(param[2], '\\*"$')

if !empty(end) && strlen(end) % 2 == 1
let param[2] = param[2][:-2]
endif

let param[2] = substitute(param[2][1:], '\\\(.\?\)', '\=lgs#cmd#UnquoteString(submatch(1))', 'g')
endif
endfor

return params
endfunction

" Takes result of lgs#cmd#Str2ParamList and position in line
" returns number of argument that position is in.
function! lgs#cmd#Pos2ArgNo(params, pos)
let cnt = 0

for param in a:params
if param[1] >= a:pos
return cnt
endif

let cnt = cnt + 1
endfor

return cnt
endfunction

let g:lgs_cmd_autoload_done = 1

0 comments on commit ecd3777

Please sign in to comment.