Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add auto-alignment of class definition with tabular #86

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ Provides

* Formatting based on the latest Puppetlabs Style Guide
* Syntax highlighting compatible with puppet 4.x
* Automatic => alignment
* Automatic '=>' alignment
* If you don't like that, add `let g:puppet_align_hashes = 0` to your vimrc.
* Aligning '=' in class definition by pressing `<C-a>` ([tabular](https://github.com/godlygeek/tabular) is required)
* If you don't like that, add `let g:puppet_align_classes = 0` to your vimrc.
* Ctags support
* Doesn't require a bloated JRE
* Doesn't take minutes to open
Expand All @@ -27,6 +29,7 @@ Additional useful plugins
[snipmate](https://github.com/garbas/vim-snipmate) and
[ultisnips](https://github.com/SirVer/ultisnips).
* [Tagbar](https://github.com/majutsushi/tagbar) plugin for Ctags support.
* [Tabular](https://github.com/godlygeek/tabular) plugin for an automatical aligning.

Installation
------------
Expand Down
70 changes: 70 additions & 0 deletions after/plugin/puppet_tabular.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
if !exists('g:puppet_align_classes')
let g:puppet_align_classes = 1
endif
if !exists('g:puppet_align_hashes')
let g:puppet_align_hashes = 1
endif

if exists(':AddTabularPipeline') && g:puppet_align_classes
" The function for an aligning each block of selectors separately
function! AlignSelectorsByBlock(lines)
let i = 0
let blStart = 0
let blocks = {}
" Write each block of selectors to dict {'idx_of_block_start':
" ['selector', 'strings']}
while i < len(a:lines)
if a:lines[i] == ''
let i += 1
continue
endif
if i == 0 || a:lines[i-1] == ''
" Start new block
let blStart = i
let blocks[blStart] = [a:lines[i]]
let i += 1
continue
else
" Or append to existing
let blocks[blStart] += [a:lines[i]]
let i += 1
continue
endif
endwhile
" Align each block separately and write back to selectors list
for k in keys(blocks)
call tabular#TabularizeStrings(blocks[k], '=>')
for str in blocks[k]
let a:lines[k] = str
let k += 1
endfor
endfor
endfunction


" The function is filtering definition by '$' or '=>', then applies tabular to
" payload and join again. Source for this taken from
" https://unix.stackexchange.com/questions/35787/indent-the-middle-of-multiple-lines
function! AlignPuppetClass(lines)
" List of payload, must contain '$' AND not contain '=>', ignore
" comments lines
let attributes = map(copy(a:lines), '(v:val =~ "[$]" && v:val !~ "=>" && v:val !~ ''^\s*#'') ? v:val : ""')
" List of selectors, each block will be aligned separately, ignore
" comments lines
let selectors = map(copy(a:lines), '(v:val =~ "=>" && v:val !~ ''^\s*#'') ? v:val : ""')
" List of noise, haven't '$' or '=>'. Also comments
let noise = map(copy(a:lines), '(v:val !~ "[$]" && v:val !~ "=>" || v:val =~ ''^\s*#'') ? v:val : ""')
if g:puppet_align_hashes
call AlignSelectorsByBlock(selectors)
endif
" Splitting by first '$attribute' and '='
call tabular#TabularizeStrings(attributes, '\v^[^$]*\zs(\s+\$\w+(>|,?))|(\=)', 'l0l0r1r1')
call map(a:lines, 'remove(attributes, 0) . remove(noise, 0) . remove(selectors, 0)')
endfunction

" The class definition could be interrupted with enum's multiline, selectors
" or whatever else, so tabular will search for any of `[$['",#]` symbols and
" pass them into AlignPuppetClass function.
au FileType puppet AddTabularPipeline! puppet_class /[$['",#]/ AlignPuppetClass(a:lines)
au FileType puppet inoremap <buffer> <silent> <C-a> <Esc>:Tabularize puppet_class<CR>A
endif
137 changes: 137 additions & 0 deletions test/aligning/bundle.vader
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
Given puppet (Sample class):
class some::example (
# It's not possible to allign class without leading spaces/tabs. Sad but true
$the_most_longest_argument,
String $arg2,
$arg3=4,
$rsa_private_key = undef,
Type::Server::Hostname $hostname =$::hostname,
Type::Inet $intern_ip= $::intern_ip,
Optional[Type::Inet6] $primary_ip6 = defined('$::primary_ip6') ? {
true=>$::primary_ip6,
false=> undef,
},
# comment with => and $var inside
# comment with only =>
# comment with only $argument
Type::Server::Hostname $project = $::project,
Enum[
'online',
'offline',
'WIP'
] $state= $::state,
String[1] $environment = $::environment,
Optional[String[1]] $function = $::function,
Type::Server::Hostname $monitoring_queue = $::monitoring_queue,
Array[Pattern[/\A[a-z][a-z0-9_-]*\Z/]] $monitoring_checks =$::monitoring_checks,
Optional[Type::Server::Hostname] $project_network= defined('$::project_network') ? {
true => $::project_network,
false =>undef,
default=>'',
},
) {
file { '/just_example':
ensure=>'directory',
require=>Package['example'],
}
}

Execute (Tabularize class and resource):
2 Tabularize puppet_class
33 Tabularize puppet_class

Expect (Aligning works fine):
class some::example (
# It's not possible to allign class without leading spaces/tabs. Sad but true
$the_most_longest_argument,
String $arg2,
$arg3 = 4,
$rsa_private_key = undef,
Type::Server::Hostname $hostname = $::hostname,
Type::Inet $intern_ip = $::intern_ip,
Optional[Type::Inet6] $primary_ip6 = defined('$::primary_ip6') ? {
true => $::primary_ip6,
false => undef,
},
# comment with => and $var inside
# comment with only =>
# comment with only $argument
Type::Server::Hostname $project = $::project,
Enum[
'online',
'offline',
'WIP'
] $state = $::state,
String[1] $environment = $::environment,
Optional[String[1]] $function = $::function,
Type::Server::Hostname $monitoring_queue = $::monitoring_queue,
Array[Pattern[/\A[a-z][a-z0-9_-]*\Z/]] $monitoring_checks = $::monitoring_checks,
Optional[Type::Server::Hostname] $project_network = defined('$::project_network') ? {
true => $::project_network,
false => undef,
default => '',
},
) {
file { '/just_example':
ensure => 'directory',
require => Package['example'],
}
}

Given puppet (Resource brakes by Tabularize):
# Another useful case
# Breaks by <C-a>, works with => autoalignment
if $rsa_private_key != undef {
some::cool::helper { $user:
home_dir=> '/home/user',
authorized_keys =>[
convert_ssh_rsa_private_to_public_key($rsa_private_key)
],
rsa_private_key =>$rsa_private_key,
}
}

Execute (Tabularize in 4th line):
4 Tabularize puppet_class

Expect (Unhappily, the aligning here is broken):
# Another useful case
# Breaks by <C-a>, works with => autoalignment
if $rsa_private_key! = undef {
some::cool::helper { $user :
home_dir => '/home/user',
authorized_keys => [
convert_ssh_rsa_private_to_public_key($rsa_private_key)
],
rsa_private_key => $rsa_private_key,
}
}

Given puppet (Resource brakes by Tabularize):
# Another useful case
# Breaks by <C-a>, works with => autoalignment
if $rsa_private_key != undef {
some::cool::helper { $user:
home_dir=> '/home/user',
authorized_keys =>[
convert_ssh_rsa_private_to_public_key($rsa_private_key)
],
rsa_private_key =>$rsa_private_key,
}
}

Do (Apply '=>' aligning):
4jf=2s=>

Expect (Aligning with '=>' works):
# Another useful case
# Breaks by <C-a>, works with => autoalignment
if $rsa_private_key != undef {
some::cool::helper { $user:
home_dir => '/home/user',
authorized_keys => [
convert_ssh_rsa_private_to_public_key($rsa_private_key)
],
rsa_private_key => $rsa_private_key,
}
}
1 change: 1 addition & 0 deletions test/init.vim
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
set nocompatible
filetype off
set rtp+=vader.vim
set rtp+=tabular
set rtp+=.
set rtp+=after
filetype plugin indent on
Expand Down
4 changes: 4 additions & 0 deletions test/run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ cd "${SCRIPT_FOLDER}/.."
if [ ! -d "vader.vim" ]; then
git clone https://github.com/junegunn/vader.vim.git
fi
if [ ! -d "tabular" ]; then
git clone https://github.com/godlygeek/tabular.git
fi


"${RUNVIM}" -u test/init.vim -c 'Vader! test/**/*.vader' > /dev/null
vader_exit=$?
Expand Down