summaryrefslogtreecommitdiff
path: root/vim/extline/autoload/extline.vim
blob: ea9ec1a432ab555e2309886f75d4965c72708a6c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
" Autoloads for Vim extline plugin.

if exists("g:autoloaded_extline")
    finish
endif
let g:autoloaded_extline = 1

" Save 'cpoptions' and set Vim default to enable line continuations.
let s:save_cpoptions = &cpoptions
set cpoptions&vim

function! extline#lstrip(s)
    return substitute(a:s, '^\s*', '', '')
endfunction

function! extline#rstrip(s)
    return substitute(a:s, '\s*$', '', '')
endfunction

function! extline#strip(s)
    return extline#lstrip(extline#rstrip(a:s))
endfunction

function! extline#leadingWhitespace(s)
    return substitute(a:s, '^\s*\zs\(.*\)$', '', '')
endfunction

function! extline#getMonochar(s)
    let monochar = substitute(extline#strip(a:s), '^\(\S\)\1*$', '\1', '')
    if len(monochar) > 1
        let monochar = ''
    endif
    return monochar
endfunction

" Return monochar that is non-alphanumeric.
function! extline#getPuncMonochar(s)
    let monochar = extline#getMonochar(a:s)
    if match(monochar, '[:alnum:]') >= 0
        let monochar = ''
    endif
    return monochar
endfunction

function! extline#firstNonEmpty(strings)
    for s in a:strings
        if s != ''
            return s
        endif
    endfor
    return a:strings[0]
endfunction

function! extline#probeTitle(titleLineNum)
    let titleText = getline(a:titleLineNum)
    let title = extline#strip(titleText)
    let titlePrefix = extline#leadingWhitespace(titleText)
    if extline#getPuncMonochar(title) != ''
        " Title cannot be a line of monochar punctuation characters.
        let title = ''
    endif
    " Title Group
    let tg = {
                \ 'titleLineNum': a:titleLineNum,
                \ 'title': title,
                \ 'titlePrefix': titlePrefix,
                \ 'overChar': '',
                \ 'underChar': '',
                \ }

    if title != ''
        " Consider non-existing line numbers.
        let overText = extline#strip(getline(a:titleLineNum - 1))
        let underText = extline#strip(getline(a:titleLineNum + 1))
        let tg['overChar'] = extline#getPuncMonochar(overText)
        let tg['underChar'] = extline#getPuncMonochar(underText)
    endif
    return tg
endfunction

function! extline#probeTitleNearby()
    let lineNum = line('.')
    let text = extline#strip(getline(lineNum))
    let monochar = extline#getPuncMonochar(text)
    if text == '' || monochar != ''
        let tg = extline#probeTitle(lineNum - 1)
        if tg['title'] == ''
            let tg = extline#probeTitle(lineNum + 1)
        endif
    else
        let tg = extline#probeTitle(lineNum)
    endif
    return tg
endfunction

function! extline#changeTitleLine(tg, lineType, lineTypePresent)
    " lineType is 'over' or 'under'
    " lineTypePresent is 1 or 0 to use or not use lineType.
    let charType = a:lineType . 'Char'
    if a:lineTypePresent && a:tg[charType] == ''
        if charType == 'overChar'
            let otherCharType = 'underChar'
            exe a:tg['titleLineNum'] . 'copy ' . (a:tg['titleLineNum'] - 1)
            let a:tg['titleLineNum'] = (a:tg['titleLineNum'] + 1)
        else
            let otherCharType = 'overChar'
            exe a:tg['titleLineNum'] . 'copy ' . a:tg['titleLineNum']
        endif
        let a:tg[charType] = a:tg[otherCharType]
        if a:tg[charType] == ''
            let a:tg[charType] = '='
        endif
    endif
    if !a:lineTypePresent && a:tg[charType] != ''
        if charType == 'overChar'
            exe (a:tg['titleLineNum'] - 1) . 'del'
            let a:tg['titleLineNum'] = (a:tg['titleLineNum'] - 1)
        else
            exe (a:tg['titleLineNum'] + 1) . 'del'
        endif
        let a:tg[charType] = ''
    endif
endfunction

function! extline#updateTitle(tg)
    let titleLineNum = a:tg['titleLineNum']
    let titleLen = len(a:tg['title'])
    let underChar = a:tg['underChar']
    let overChar = a:tg['overChar']
    let titlePrefix = a:tg['titlePrefix']

    if overChar != ''
        let lineText = titlePrefix . repeat(overChar, titleLen)
        exe (titleLineNum - 1) . 's/^.*/\=lineText/g'
    endif
    exe titleLineNum
    normal! $
    if underChar != ''
        let lineText = titlePrefix . repeat(underChar, titleLen)
        exe (titleLineNum + 1) . 's/^.*/\=lineText/g'
        normal! $
    endif
endfunction

function! extline#makeTitle(forceMonochar, useOver, useUnder)
    let tg = extline#probeTitleNearby()
    if tg['title'] != ''
        " Always add a line before removing the other line.
        if a:useOver
            call extline#changeTitleLine(tg, 'over', a:useOver)
            call extline#changeTitleLine(tg, 'under', a:useUnder)
        else
            call extline#changeTitleLine(tg, 'under', a:useUnder)
            call extline#changeTitleLine(tg, 'over', a:useOver)
        endif
        if a:forceMonochar != ''
            if a:useOver
                let tg['overChar'] = a:forceMonochar
            endif
            if a:useUnder
                let tg['underChar'] = a:forceMonochar
            endif
        endif
        call extline#updateTitle(tg)
    endif
    return tg['title'] != ''
endfunction

function! extline#makeHline()
    let lineNum = line('.')
    let t = extline#rstrip(getline(lineNum))
    let monochar = extline#getMonochar(t)
    if monochar != ''
        let lineText = (t . repeat(monochar, 80))[:77]
        exe 's/^.*/' . escape(lineText, '/') . '/g'
        normal! $
    endif
endfunction

function! extline#autoTitle()
    let tg = extline#probeTitleNearby()
    if tg['title'] != ''
        if tg['overChar'] == '' && tg['underChar'] == ''
            if tg['titleLineNum'] > line(".")
                " Title was after cursor line, use overTitle.
                call extline#changeTitleLine(tg, 'over', 1)
            else
                call extline#changeTitleLine(tg, 'under', 1)
            endif
        endif
        call extline#updateTitle(tg)
    else
        call extline#makeHline()
    endif
endfunction