"============================================================================= " File : autoload/unite/sources/outline/defaults/lisp.vim " Author : adolenc " Updated : 2016-04-08 " " Licensed under the MIT license: " http://www.opensource.org/licenses/mit-license.php " "============================================================================= function! unite#sources#outline#defaults#lisp#outline_info() abort return s:outline_info endfunction let s:Util = unite#sources#outline#import('Util') "----------------------------------------------------------------------------- " Outline Info let s:DEF_PATTERN = '\(\S*:\)\?def\S*' let s:FEATURE_PATTERN = '#\(+\|-\)\(([^)]\+)\|\S[^(]*\)' let s:outline_info = { \ 'heading' : '^' . s:FEATURE_PATTERN . '\s*(\|^(\|^\s*(' . s:DEF_PATTERN, \ \ 'skip': { \ 'header': '^;', \ 'block': ['^\s*"', '[^\\]"'], \ }, \ \ 'not_match_patterns': [ \ s:Util.shared_pattern('*', 'parameter_list'), \ ], \ \ 'heading_groups': { \ 'function' : ['defun', 'defmacro', 'defgeneric', 'defmethod'], \ 'variable' : ['defvar', 'defparameter', 'defconstant'], \ 'type' : ['defclass', 'defstruct', 'define-condition', 'deftype'], \ 'method-combination' : ['define-method-combination'], \ 'compiler-macro' : ['define-compiler-macro'], \ 'package' : ['defpackage'], \ }, \ \ 'highlight_rules': [ \ { 'name' : 'function', \ 'pattern' : '/ [^ ]* \zs.*/' }, \ { 'name' : 'type', \ 'pattern' : '/' . s:DEF_PATTERN . '/' }, \ { 'name' : 'special', \ 'pattern' : '/.*:: toplevel form/' }, \ ], \} function! s:outline_info.create_heading(which, heading_line, matched_line, context) abort let first_form = s:remove_feature_check(a:heading_line) let heading = { \ 'word' : s:splice_form(first_form), \ 'level': s:Util.get_indent_level(a:context, a:context.heading_lnum), \ 'type' : matchstr(first_form, '^\s*(\zs\S\+\ze'), \ } let form_args = matchstr(heading.word, '^\S\+\s\+\zs.*') " Whether we are checking a def* or a top-level form, fix the heading by " appending appropriate type information after `::'. if heading.type =~ '^' . s:DEF_PATTERN let heading.word = heading.type . ' ' . s:add_ldots(form_args) else let heading.word = s:add_ldots(heading.word) . ' :: toplevel form' endif return heading endfunction function! s:count_occurences(char, string) abort " Count number of occurences of {char} in {string}. return len(split(a:string, a:char, 1)) - 1 endfunction function! s:has_balanced_chars(line, open, close) abort " Check whether {line} has balanced {open} and {close} characters. " Actually just fake it by checking if they appear same number of times let n_open_chars = s:count_occurences(a:open, a:line) if a:open == a:close return (n_open_chars % 2) == 0 endif let n_close_chars = s:count_occurences(a:close, a:line) return n_open_chars == n_close_chars endfunction function! s:splice_form(line) abort " Remove the outermost parentheses from {line}. if s:has_balanced_chars(a:line, '(', ')') return matchstr(a:line, '^\s*(\zs.*\ze)\s*$') else return matchstr(a:line, '^\s*(\zs.*') endif endfunction function! s:remove_feature_check(line) abort " Remove the (#+|#-)[feature] expression from {line} if it exists. return matchstr(a:line, '^\(' . s:FEATURE_PATTERN . '\)\?\zs.*') endfunction function! s:add_ldots(line) abort " Add `...' to the end of {line} in case it has unbalanced parentheses or " quotes. if !s:has_balanced_chars(a:line, '(', ')') || !s:has_balanced_chars(a:line, '"', '"') return a:line . ' ...' endif return a:line endfunction