From 7905d6fdb5cde48009a79d8d354f2bebfe186e90 Mon Sep 17 00:00:00 2001 From: Tony Duckles Date: Fri, 22 Dec 2017 10:07:16 -0600 Subject: [PATCH 01/16] .vimrc: Update comments --- .vimrc | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.vimrc b/.vimrc index e29fda8..d0c5145 100644 --- a/.vimrc +++ b/.vimrc @@ -75,12 +75,10 @@ if &t_Co > 2 || has("gui_running") set background=dark " dark background syntax enable " syntax highligting - " Solarized color-scheme - let g:solarized_termtrans=1 " Always use terminal's default bg color + let g:solarized_termtrans=1 " always use terminal's default bg color colorscheme solarized - " Airline solarized theme - let g:airline_theme='solarized16' - let g:solarized16_termcolors=16 + let g:airline_theme='solarized16' " vim-airline theme + let g:solarized16_termcolors=16 " always use 16 colors for 'solarized16' vim-airline theme endif " --------------------------------------------------------------------------- -- 2.45.2 From 17aa5c777e1c6b292faae78c0b0efb705ed6c2d6 Mon Sep 17 00:00:00 2001 From: Tony Duckles Date: Fri, 22 Dec 2017 22:23:19 -0600 Subject: [PATCH 02/16] .vimrc: Use g:solarized_termcolors=256 if supported --- .vimrc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.vimrc b/.vimrc index d0c5145..9ed9ed1 100644 --- a/.vimrc +++ b/.vimrc @@ -76,6 +76,9 @@ if &t_Co > 2 || has("gui_running") syntax enable " syntax highligting let g:solarized_termtrans=1 " always use terminal's default bg color + if &t_Co == 256 + let g:solarized_termcolors=256 " use 256 colors for solarized + endif colorscheme solarized let g:airline_theme='solarized16' " vim-airline theme let g:solarized16_termcolors=16 " always use 16 colors for 'solarized16' vim-airline theme -- 2.45.2 From 3486ec070ca75184c47033194f6e661c1bdc767d Mon Sep 17 00:00:00 2001 From: Tony Duckles Date: Fri, 22 Dec 2017 22:24:22 -0600 Subject: [PATCH 03/16] .vimrc: Always use terminal's default bg color --- .vimrc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.vimrc b/.vimrc index 9ed9ed1..4101794 100644 --- a/.vimrc +++ b/.vimrc @@ -75,7 +75,6 @@ if &t_Co > 2 || has("gui_running") set background=dark " dark background syntax enable " syntax highligting - let g:solarized_termtrans=1 " always use terminal's default bg color if &t_Co == 256 let g:solarized_termcolors=256 " use 256 colors for solarized endif @@ -88,6 +87,8 @@ endif " Highlight (Colors) " --------------------------------------------------------------------------- +" always use terminal's default bg color +highlight Normal ctermbg=None " comments highlight Comment ctermfg=DarkGrey guifg=#425257 " visual block @@ -100,7 +101,7 @@ if !exists(':AirlineTheme') endif " unprintable chars (listchars) highlight SpecialKey ctermfg=DarkGrey ctermbg=Black guifg=#374549 guibg=#06313c -" To-do comments +" to-do comments highlight Todo ctermfg=White ctermbg=Red guifg=#f2f2f2 guibg=#dc322f " ---------------------------------------------------------------------------- -- 2.45.2 From 12d4c06713b2b6ca798a0d05029c198a633807dc Mon Sep 17 00:00:00 2001 From: Tony Duckles Date: Sat, 23 Dec 2017 09:23:10 -0600 Subject: [PATCH 04/16] .vimrc: Cleanup 'highlight' overrides The current colorscheme should set all the standard 'highlight' groups. No need to override them locally. - Remove all 'guifg'/'guibg' overrides, keep only terminal-type overrides. GUI sessions (e.g. gvim) should use 24-bit colors as defined in current `colorscheme`. - Remove 'StatusLine' highlights. Everything status-line is handled by `vim-airline`. - Only define override 'SpecialKeys' highlights if we're using a 16-color $TERM [because I don't like the default solarized color- scheme 'SpecialKeys' highlight colors]. - Remove 'Todo' highlight. The current `colorscheme` should define this, no need to override it. --- .vimrc | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/.vimrc b/.vimrc index 4101794..5273608 100644 --- a/.vimrc +++ b/.vimrc @@ -88,21 +88,15 @@ endif " --------------------------------------------------------------------------- " always use terminal's default bg color -highlight Normal ctermbg=None +highlight Normal ctermbg=None " comments -highlight Comment ctermfg=DarkGrey guifg=#425257 +highlight Comment ctermfg=DarkGrey " visual block -highlight Visual term=reverse cterm=reverse ctermfg=DarkGreen ctermbg=White guifg=#4d830a guibg=#fdf6e3 -" statusline (active vs inactive) -if !exists(':AirlineTheme') - highlight StatusLine term=reverse cterm=reverse ctermfg=Black ctermbg=Grey guifg=#073642 guibg=#93A1A1 - highlight StatusLineNC term=reverse cterm=reverse ctermfg=Black ctermbg=DarkGrey guifg=#073642 guibg=#37555c - highlight User1 term=reverse cterm=reverse ctermfg=Black ctermbg=DarkGreen guifg=#4d830a guibg=#073642 +highlight Visual term=reverse cterm=reverse ctermfg=DarkGreen ctermbg=White +if &t_Co < 256 && !has("gui_running") + " unprintable chars (listchars) + highlight SpecialKey ctermfg=DarkGrey ctermbg=Black endif -" unprintable chars (listchars) -highlight SpecialKey ctermfg=DarkGrey ctermbg=Black guifg=#374549 guibg=#06313c -" to-do comments -highlight Todo ctermfg=White ctermbg=Red guifg=#f2f2f2 guibg=#dc322f " ---------------------------------------------------------------------------- " Backups -- 2.45.2 From 4ce758eae44751afcc410fe94b2fbcfa4c4fea87 Mon Sep 17 00:00:00 2001 From: Tony Duckles Date: Sat, 23 Dec 2017 09:51:20 -0600 Subject: [PATCH 05/16] .bashrc: Set fzf defaults --- .bashrc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.bashrc b/.bashrc index fdf26f9..907dfc1 100644 --- a/.bashrc +++ b/.bashrc @@ -439,6 +439,10 @@ MANPATH=$(puniq "$MANPATH") test -n "$PS1" && prompt_color +# fzf +export FZF_DEFAULT_COMMAND='rg --files --no-ignore --hidden --follow -g "!{.git,node_modules,*.swp,.venv}/*" 2> /dev/null' +export FZF_DEFAULT_OPTS='--bind J:down,K:up --reverse --ansi --multi' + # ------------------------------------------------------------------- # MOTD / FORTUNE # ------------------------------------------------------------------- -- 2.45.2 From 294f5e43e657b988822f882ee193c4c693117e4d Mon Sep 17 00:00:00 2001 From: Tony Duckles Date: Sat, 23 Dec 2017 19:33:04 -0600 Subject: [PATCH 06/16] .vimrc: Misc cleanup, re-arrange plugin settings --- .vimrc | 100 ++++++++++++++++++++++++++------------------------------- 1 file changed, 45 insertions(+), 55 deletions(-) diff --git a/.vimrc b/.vimrc index 5273608..1d4a5e9 100644 --- a/.vimrc +++ b/.vimrc @@ -40,6 +40,46 @@ if empty(glob('~/.vim/plugged')) autocmd VimEnter * PlugInstall --sync | source $MYVIMRC endif +" ---------------------------------------------------------------------------- +" Plugin Settings +" ---------------------------------------------------------------------------- + +" NERDTree +let NERDTreeShowHidden=1 " show dotfiles by default +let NERDTreeMinimalUI=1 " disable 'Press ? for help' text + +" Ctrl-P +let g:ctrlp_map = '' +let g:ctrlp_show_hidden = 1 +let g:ctrlp_cache_dir = $HOME.'/.vim/.cache/ctrlp' +let g:ctrlp_user_command = ['.git', 'cd %s && git ls-files . -co --exclude-standard', 'find %s -type f'] + +" Airline +let g:airline_mode_map = { + \ '__' : '-', + \ 'n' : 'N', + \ 'i' : 'I', + \ 'R' : 'R', + \ 'c' : 'C', + \ 'v' : 'V', + \ 'V' : 'V', + \ '' : 'V', + \ 's' : 'S', + \ 'S' : 'S', + \ '' : 'S', + \ } +if !exists('g:airline_symbols') + let g:airline_symbols = {} +endif +if has("gui_running") + let g:airline_powerline_fonts = 1 " use powerline font symbols +else + let g:airline_symbols_ascii = 1 " use plain ascii symbols + let g:airline_symbols.branch = 'BR:' +endif +let g:airline_symbols.linenr = '' +let g:airline_symbols.maxlinenr = '' + " --------------------------------------------------------------------------- " Terminal Settings " --------------------------------------------------------------------------- @@ -128,6 +168,9 @@ set nostartofline " don't jump to the start of line when scrolling set scrolloff=4 " vertical padding set sidescroll=40 " side-scrolling increment (for nowrap mode) set sidescrolloff=10 " horz padding +if version >= 700 + set tabpagemax=50 " open 50 tabs max +endif " ---------------------------------------------------------------------------- " Visual Cues @@ -155,31 +198,6 @@ if !exists(':AirlineTheme') set statusline+=\ %12.(%v,%l/%L%)\ \ %-4P " cursor position, % through file of viewport endif -let g:airline_mode_map = { - \ '__' : '-', - \ 'n' : 'N', - \ 'i' : 'I', - \ 'R' : 'R', - \ 'c' : 'C', - \ 'v' : 'V', - \ 'V' : 'V', - \ '' : 'V', - \ 's' : 'S', - \ 'S' : 'S', - \ '' : 'S', - \ } -if !exists('g:airline_symbols') - let g:airline_symbols = {} -endif -if has("gui_running") - let g:airline_powerline_fonts = 1 " use powerline font symbols -else - let g:airline_symbols_ascii = 1 " use plain ascii symbols - let g:airline_symbols.branch = 'BR:' -endif -let g:airline_symbols.linenr = '' -let g:airline_symbols.maxlinenr = '' - " ---------------------------------------------------------------------------- " Text Formatting " ---------------------------------------------------------------------------- @@ -198,7 +216,7 @@ set virtualedit=block " allow virtual edit in visual block .. set spelllang=en_us " spell-check dictionary " ---------------------------------------------------------------------------- -" Filename exclusions +" Filename Exclusions " ---------------------------------------------------------------------------- set wildignore+=.hg,.git,.svn " version control directories @@ -209,15 +227,7 @@ set wildignore+=*.sw? " Vim swap files set wildignore+=.DS_Store " OSX junk " ---------------------------------------------------------------------------- -" Tabs -" ---------------------------------------------------------------------------- - -if version >= 700 - set tabpagemax=50 " open 50 tabs max -endif - -" ---------------------------------------------------------------------------- -" Mappings +" Key Mappings " ---------------------------------------------------------------------------- " movement based on display lines not physical lines (sane movement with wrap turned on) @@ -333,19 +343,6 @@ function! ListLeaders() endfunction command! ListLeaders :call ListLeaders() -" ---------------------------------------------------------------------------- -" Plugin Settings -" ---------------------------------------------------------------------------- - -" NERDTree -let NERDTreeShowHidden=1 " show dotfiles by default -let NERDTreeMinimalUI=1 " disable 'Press ? for help' text -" Ctrl-P -let g:ctrlp_map = '' -let g:ctrlp_show_hidden = 1 -let g:ctrlp_cache_dir = $HOME.'/.vim/.cache/ctrlp' -let g:ctrlp_user_command = ['.git', 'cd %s && git ls-files . -co --exclude-standard', 'find %s -type f'] - " --------------------------------------------------------------------------- " Auto Commands / File Types " --------------------------------------------------------------------------- @@ -371,13 +368,6 @@ augroup vimrc_autocmds au FileType make setlocal noexpandtab augroup END -" -------------------------------------------------------------------------- -" ManPageView -" -------------------------------------------------------------------------- - -let g:manpageview_pgm= 'man -P "/usr/bin/less -is"' -let $MANPAGER = '/usr/bin/less -is' - " -------------------------------------------------------------------------- " Local Settings " -------------------------------------------------------------------------- -- 2.45.2 From 265b2cb060e4c7d46b979c5b6b49c75f70fa04a3 Mon Sep 17 00:00:00 2001 From: Tony Duckles Date: Sat, 23 Dec 2017 20:48:27 -0600 Subject: [PATCH 07/16] .vimrc: Tweaks to highlight colors Cleanup and simply the local 'highlight' rules so that we only override anything which I don't like from the default `solarized` colorscheme. --- .vimrc | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/.vimrc b/.vimrc index 1d4a5e9..4be3627 100644 --- a/.vimrc +++ b/.vimrc @@ -115,10 +115,9 @@ if &t_Co > 2 || has("gui_running") set background=dark " dark background syntax enable " syntax highligting - if &t_Co == 256 - let g:solarized_termcolors=256 " use 256 colors for solarized - endif + let g:solarized_termcolors=&t_Co " use 256 colors for solarized colorscheme solarized + let g:airline_theme='solarized16' " vim-airline theme let g:solarized16_termcolors=16 " always use 16 colors for 'solarized16' vim-airline theme endif @@ -127,15 +126,21 @@ endif " Highlight (Colors) " --------------------------------------------------------------------------- -" always use terminal's default bg color -highlight Normal ctermbg=None -" comments -highlight Comment ctermfg=DarkGrey -" visual block -highlight Visual term=reverse cterm=reverse ctermfg=DarkGreen ctermbg=White -if &t_Co < 256 && !has("gui_running") - " unprintable chars (listchars) - highlight SpecialKey ctermfg=DarkGrey ctermbg=Black +if !has("gui_running") + " always use terminal's default bg color, override solarized Normal ctermfg + highlight Normal ctermbg=None ctermfg=None + " override solarized Comment ctermfg + if &t_Co == 256 + highlight Comment ctermfg=241 + else + highlight Comment ctermfg=DarkGrey + endif + " visual block + highlight Visual term=reverse cterm=reverse ctermfg=DarkGreen ctermbg=White + if &t_Co < 256 + " unprintable chars (listchars) + highlight SpecialKey ctermfg=DarkGrey ctermbg=Black + endif endif " ---------------------------------------------------------------------------- -- 2.45.2 From e9a01289f053134b29fe9e9ec03c7ecc42ddbf0a Mon Sep 17 00:00:00 2001 From: Tony Duckles Date: Sun, 24 Dec 2017 12:58:51 -0600 Subject: [PATCH 08/16] .vim: Delete scripts/closetag.vim --- .vim/scripts/closetag.vim | 327 -------------------------------------- .vimrc | 2 - 2 files changed, 329 deletions(-) delete mode 100644 .vim/scripts/closetag.vim diff --git a/.vim/scripts/closetag.vim b/.vim/scripts/closetag.vim deleted file mode 100644 index 6ce41fb..0000000 --- a/.vim/scripts/closetag.vim +++ /dev/null @@ -1,327 +0,0 @@ -" File: closetag.vim -" Summary: Functions and mappings to close open HTML/XML tags -" Uses: -- close matching open tag -" Author: Steven Mueller -" Last Modified: Tue May 24 13:29:48 PDT 2005 -" Version: 0.9.1 -" XXX - breaks if close attempted while XIM is in preedit mode -" TODO - allow usability as a global plugin - -" Add g:unaryTagsStack - always contains html tags settings -" and g:closetag_default_xml - user should define this to default to xml -" When a close is attempted but b:unaryTagsStack undefined, -" use b:closetag_html_style to determine if the file is to be treated -" as html or xml. Failing that, check the filetype for xml or html. -" Finally, default to g:closetag_html_style. -" If the file is html, let b:unaryTagsStack=g:unaryTagsStack -" otherwise, let b:unaryTagsStack="" -" TODO - make matching work for all comments -" -- kinda works now, but needs syn sync minlines to be very long -" -- Only check whether in syntax in the beginning, then store comment tags -" in the tagstacks to determine whether to move into or out of comment mode -" TODO - The new normal mode mapping clears recent messages with its , and -" it doesn't fix the null-undo issue for vim 5.7 anyway. -" TODO - make use of the following neat features: -" -- the ternary ?: operator -" -- :echomsg and :echoerr -" -- curly brace expansion for variables and function name definitions? -" -- check up on map \FuncName -" -" Description: -" This script eases redundant typing when writing html or xml files (even if -" you're very good with ctrl-p and ctrl-n :). Hitting ctrl-_ will initiate a -" search for the most recent open tag above that is not closed in the -" intervening space and then insert the matching close tag at the cursor. In -" normal mode, the close tag is inserted one character after cursor rather than -" at it, as if a had been used. This allows putting close tags at the -" ends of lines while in normal mode, but disallows inserting them in the -" first column. -" -" For HTML, a configurable list of tags are ignored in the matching process. -" By default, the following tags will not be matched and thus not closed -" automatically: area, base, br, dd, dt, hr, img, input, link, meta, and -" param. -" -" For XML, all tags must have a closing match or be terminated by />, as in -" . These empty element tags are ignored for matching. -" -" Comment checking is now handled by vim's internal syntax checking. If tag -" closing is initiated outside a comment, only tags outside of comments will -" be matched. When closing tags in comments, only tags within comments will -" be matched, skipping any non-commented out code (wee!). However, the -" process of determining the syntax ID of an arbitrary position can still be -" erroneous if a comment is not detected because the syntax highlighting is -" out of sync, or really slow if syn sync minlines is large. -" Set the b:closetag_disable_synID variable to disable this feature if you -" have really big chunks of comment in your code and closing tags is too slow. -" -" If syntax highlighting is not enabled, comments will not be handled very -" well. Commenting out HTML in certain ways may cause a "tag mismatch" -" message and no completion. For example, '' -" between the cursor and the most recent unclosed open tag above causes -" trouble. Properly matched well formed tags in comments don't cause a -" problem. -" -" Install: -" To use, place this file in your standard vim scripts directory, and source -" it while editing the file you wish to close tags in. If the filetype is not -" set or the file is some sort of template with embedded HTML, you may force -" HTML style tag matching by first defining the b:closetag_html_style buffer -" variable. Otherwise, the default is XML style tag matching. -" -" Example: -" :let b:closetag_html_style=1 -" :source ~/.vim/scripts/closetag.vim -" -" For greater convenience, load this script in an autocommand: -" :au Filetype html,xml,xsl source ~/.vim/scripts/closetag.vim -" -" Also, set noignorecase for html files or edit b:unaryTagsStack to match your -" capitalization style. You may set this variable before or after loading the -" script, or simply change the file itself. -" -" Configuration Variables: -" -" b:unaryTagsStack Buffer local string containing a whitespace -" seperated list of element names that should be -" ignored while finding matching closetags. Checking -" is done according to the current setting of the -" ignorecase option. -" -" b:closetag_html_style Define this (as with let b:closetag_html_style=1) -" and source the script again to set the -" unaryTagsStack to its default value for html. -" -" b:closetag_disable_synID Define this to disable comment checking if tag -" closing is too slow. This can be set or unset -" without having to source again. -" -" Changelog: -" May 24, 2005 Tuesday -" * Changed function names to be script-local to avoid conflicts with other -" scripts' stack implementations. -" -" June 07, 2001 Thursday -" * Added comment handling. Currently relies on synID, so if syn sync -" minlines is small, the chance for failure is high, but if minlines is -" large, tagclosing becomes rather slow... -" -" * Changed normal mode closetag mapping to use in insert mode -" rather than p in normal mode. This has 2 implications: -" - Tag closing no longer clobbers the unnamed register -" - When tag closing fails or finds no match, no longer adds to the undo -" buffer for recent vim 6.0 development versions. -" - However, clears the last message when closing tags in normal mode -" -" * Changed the closetag_html_style variable to be buffer-local rather than -" global. -" -" * Expanded documentation - -"------------------------------------------------------------------------------ -" User configurable settings -"------------------------------------------------------------------------------ - -" if html, don't close certain tags. Works best if ignorecase is set. -" otherwise, capitalize these elements according to your html editing style -if !exists("b:unaryTagsStack") || exists("b:closetag_html_style") - if &filetype == "html" || exists("b:closetag_html_style") - let b:unaryTagsStack="area base br dd dt hr img input link meta param" - else " for xsl and xsl - let b:unaryTagsStack="" - endif -endif - -" Has this already been loaded? -if exists("loaded_closetag") - finish -endif -let loaded_closetag=1 - -" set up mappings for tag closing -inoremap =GetCloseTag() -map a - -"------------------------------------------------------------------------------ -" Tag closer - uses the stringstack implementation below -"------------------------------------------------------------------------------ - -" Returns the most recent unclosed tag-name -" (ignores tags in the variable referenced by a:unaryTagsStack) -function! GetLastOpenTag(unaryTagsStack) - " Search backwards through the file line by line using getline() - " Overall strategy (moving backwards through the file from the cursor): - " Push closing tags onto a stack. - " On an opening tag, if the tag matches the stack top, discard both. - " -- if the tag doesn't match, signal an error. - " -- if the stack is empty, use this tag - let linenum=line(".") - let lineend=col(".") - 1 " start: cursor position - let first=1 " flag for first line searched - let b:TagStack="" " main stack of tags - let startInComment=s:InComment() - - let tagpat='' - " Search for: closing tags - while (linenum>0) - " Every time we see an end-tag, we push it on the stack. When we see an - " open tag, if the stack isn't empty, we pop it and see if they match. - " If no, signal an error. - " If yes, continue searching backwards. - " If stack is empty, return this open tag as the one that needs closing. - let line=getline(linenum) - if first - let line=strpart(line,0,lineend) - else - let lineend=strlen(line) - endif - let b:lineTagStack="" - let mpos=0 - let b:TagCol=0 - " Search the current line in the forward direction, pushing any tags - " onto a special stack for the current line - while (mpos > -1) - let mpos=matchend(line,tagpat) - if mpos > -1 - let b:TagCol=b:TagCol+mpos - let tag=matchstr(line,tagpat) - - if exists("b:closetag_disable_synID") || startInComment==s:InCommentAt(linenum, b:TagCol) - let b:TagLine=linenum - call s:Push(matchstr(tag,'[^<>]\+'),"b:lineTagStack") - endif - "echo "Tag: ".tag." ending at position ".mpos." in '".line."'." - let lineend=lineend-mpos - let line=strpart(line,mpos,lineend) - endif - endwhile - " Process the current line stack - while (!s:EmptystackP("b:lineTagStack")) - let tag=s:Pop("b:lineTagStack") - if match(tag, "^/") == 0 "found end tag - call s:Push(tag,"b:TagStack") - "echo linenum." ".b:TagStack - elseif s:EmptystackP("b:TagStack") && !s:Instack(tag, a:unaryTagsStack) "found unclosed tag - return tag - else - let endtag=s:Peekstack("b:TagStack") - if endtag == "/".tag || endtag == "/" - call s:Pop("b:TagStack") "found a open/close tag pair - "echo linenum." ".b:TagStack - elseif !s:Instack(tag, a:unaryTagsStack) "we have a mismatch error - echohl Error - echon "\rError:" - echohl None - echo " tag mismatch: <".tag."> doesn't match <".endtag.">. (Line ".linenum." Tagstack: ".b:TagStack.")" - return "" - endif - endif - endwhile - let linenum=linenum-1 | let first=0 - endwhile - " At this point, we have exhausted the file and not found any opening tag - echo "No opening tags." - return "" -endfunction - -" Returns closing tag for most recent unclosed tag, respecting the -" current setting of b:unaryTagsStack for tags that should not be closed -function! GetCloseTag() - let tag=GetLastOpenTag("b:unaryTagsStack") - if tag == "" - return "" - else - return "" - endif -endfunction - -" return 1 if the cursor is in a syntactically identified comment field -" (fails for empty lines: always returns not-in-comment) -function! s:InComment() - return synIDattr(synID(line("."), col("."), 0), "name") =~ 'Comment' -endfunction - -" return 1 if the position specified is in a syntactically identified comment field -function! s:InCommentAt(line, col) - return synIDattr(synID(a:line, a:col, 0), "name") =~ 'Comment' -endfunction - -"------------------------------------------------------------------------------ -" String Stacks -"------------------------------------------------------------------------------ -" These are strings of whitespace-separated elements, matched using the \< and -" \> patterns after setting the iskeyword option. -" -" The sname argument should contain a symbolic reference to the stack variable -" on which method should operate on (i.e., sname should be a string containing -" a fully qualified (ie: g:, b:, etc) variable name.) - -" Helper functions -function! s:SetKeywords() - let g:IsKeywordBak=&iskeyword - let &iskeyword="33-255" -endfunction - -function! s:RestoreKeywords() - let &iskeyword=g:IsKeywordBak -endfunction - -" Push el onto the stack referenced by sname -function! s:Push(el, sname) - if !s:EmptystackP(a:sname) - exe "let ".a:sname."=a:el.' '.".a:sname - else - exe "let ".a:sname."=a:el" - endif -endfunction - -" Check whether the stack is empty -function! s:EmptystackP(sname) - exe "let stack=".a:sname - if match(stack,"^ *$") == 0 - return 1 - else - return 0 - endif -endfunction - -" Return 1 if el is in stack sname, else 0. -function! s:Instack(el, sname) - exe "let stack=".a:sname - call s:SetKeywords() - let m=match(stack, "\\<".a:el."\\>") - call s:RestoreKeywords() - if m < 0 - return 0 - else - return 1 - endif -endfunction - -" Return the first element in the stack -function! s:Peekstack(sname) - call s:SetKeywords() - exe "let stack=".a:sname - let top=matchstr(stack, "\\<.\\{-1,}\\>") - call s:RestoreKeywords() - return top -endfunction - -" Remove and return the first element in the stack -function! s:Pop(sname) - if s:EmptystackP(a:sname) - echo "Error! Stack ".a:sname." is empty and can't be popped." - return "" - endif - exe "let stack=".a:sname - " Find the first space, loc is 0-based. Marks the end of 1st elt in stack. - call s:SetKeywords() - let loc=matchend(stack,"\\<.\\{-1,}\\>") - exe "let ".a:sname."=strpart(stack, loc+1, strlen(stack))" - let top=strpart(stack, match(stack, "\\<"), loc) - call s:RestoreKeywords() - return top -endfunction - -function! s:Clearstack(sname) - exe "let ".a:sname."=''" -endfunction diff --git a/.vimrc b/.vimrc index 4be3627..14a08f5 100644 --- a/.vimrc +++ b/.vimrc @@ -363,8 +363,6 @@ augroup vimrc_autocmds let g:is_bash = 1 " git commit message au Filetype gitcommit set tw=68 spell - " html variants - au Filetype html,xml,xsl,rhtml source $HOME/.vim/scripts/closetag.vim " don't use cindent for javascript au FileType javascript setlocal nocindent " use Octopress syntax-highlighting for *.markdown files -- 2.45.2 From cefe08df4ba667c36d0de97e33566e725aae200e Mon Sep 17 00:00:00 2001 From: Tony Duckles Date: Sat, 30 Dec 2017 23:11:36 -0600 Subject: [PATCH 09/16] .vimrc: Add some new commands, misc cleanup --- .vim/bundle/whitespace/plugin/whitespace.vim | 9 -- .vimrc | 88 ++++++++++++++------ 2 files changed, 62 insertions(+), 35 deletions(-) delete mode 100644 .vim/bundle/whitespace/plugin/whitespace.vim diff --git a/.vim/bundle/whitespace/plugin/whitespace.vim b/.vim/bundle/whitespace/plugin/whitespace.vim deleted file mode 100644 index bd0bfe2..0000000 --- a/.vim/bundle/whitespace/plugin/whitespace.vim +++ /dev/null @@ -1,9 +0,0 @@ -" thanks to http://vimcasts.org/e/4 -function! whitespace#strip_trailing() - let previous_search=@/ - let previous_cursor_line=line('.') - let previous_cursor_column=col('.') - %s/\s\+$//e - let @/=previous_search - call cursor(previous_cursor_line, previous_cursor_column) -endfunction diff --git a/.vimrc b/.vimrc index 14a08f5..0269b4f 100644 --- a/.vimrc +++ b/.vimrc @@ -16,6 +16,7 @@ set autoread " reload files (no local changes only) " --------------------------------------------------------------------------- call plug#begin('~/.vim/plugged') + Plug 'altercation/vim-colors-solarized' Plug 'kien/ctrlp.vim' Plug 'kopischke/vim-fetch' @@ -30,9 +31,10 @@ Plug 'tpope/vim-surround' Plug 'tpope/vim-unimpaired' Plug 'vim-airline/vim-airline' Plug 'vim-airline/vim-airline-themes' + Plug '~/.vim/bundle/matchit' Plug '~/.vim/bundle/mumps' -Plug '~/.vim/bundle/whitespace' + call plug#end() " Automatic install @@ -288,6 +290,13 @@ nmap gp :Gpush " cd to the directory containing the file in the buffer nmap cd :lcd %:h " toggle diffmode for a buffer +function! DiffToggle() + if &diff + diffoff + else + diffthis + endif +endfunction nmap df :call DiffToggle() " quickly edit/reload vimrc nmap ev :edit $MYVIMRC @@ -295,7 +304,7 @@ nmap sv :source $MYVIMRC " find merge conflict markers nmap fc /\v^[<=>]{7}( .*\|$) " toggle hlsearch -nmap hs :set hlsearch! hlsearch? +nmap hls :set hlsearch! hlsearch? " upper/lower word nmap wu mQviwU`Q nmap wl mQviwu`Q @@ -304,8 +313,6 @@ nmap wU mQgewvU`Q nmap wL mQgewvu`Q " smart paste - enable paste-mode and paste contents of system clipboard map p :set pasteo"*]p:set nopaste -" strip all trailing whitespace in file -nmap sw :call whitespace#strip_trailing() " toggle spell-check nmap sp :setlocal spell! spell? " set text wrapping toggles @@ -319,34 +326,63 @@ nmap tag :split :exec("tag ".expand("")) " Functions " -------------------------------------------------------------------------- -" Toggle diff-mode -function! DiffToggle() - if &diff - diffoff +" :Redir +" Run vim command, redirect output to a scratch buffer +function! s:redir(cmd) + redir => message + silent execute a:cmd + redir END + if empty(message) + echoerr "no output" else - diffthis + new + setlocal buftype=nofile bufhidden=wipe noswapfile nobuflisted nomodified + silent! put=message + silent! g/^s*$/d endif endfunction +command! -nargs=+ -complete=command Redir call s:redir() +" :ListLeaders " Make a scratch buffer with all of the leader keybindings. -" Adapted from http://ctoomey.com/posts/an-incremental-approach-to-vim/ -function! ListLeaders() - silent! redir @b - silent! nmap - silent! redir END - silent! new - silent! set buftype=nofile - silent! set bufhidden=hide - silent! setlocal noswapfile - silent! put! b - silent! g/^s*$/d - silent! %s/^.*,// - silent! normal ggVg - silent! sort - silent! let lines = getline(1,"$") - silent! normal +command! ListLeaders :call s:redir('nmap ') + +" :Todo +" Use `git grep` to search for to-do comments, add matches to qflist +function! s:todo() abort + let entries = [] + for cmd in ['git grep -nI -e TODO -e FIXME -e XXX 2> /dev/null', + \ 'grep -rnI -e TODO -e FIXME -e XXX * 2> /dev/null'] + let lines = split(system(cmd), '\n') + if v:shell_error != 0 | continue | endif + for line in lines + let [fname, lno, text] = matchlist(line, '^\([^:]*\):\([^:]*\):\(.*\)')[1:3] + call add(entries, { 'filename': fname, 'lnum': lno, 'text': text }) + endfor + break + endfor + + if !empty(entries) + call setqflist(entries) + copen + endif +endfunction +command! Todo call s:todo() + +" :StripTrailingWhitespace +" Strip trailing whitespace +function! StripTrailingWhitespace() + " preparation: save last search, and cursor position. + let _s=@/ + let l = line(".") + let c = col(".") + " do the business + %s/\s\+$//e + " clean up: restore previous search history, and cursor position + let @/=_s + call cursor(l, c) endfunction -command! ListLeaders :call ListLeaders() +command! StripTrailingWhitespace call StripTrailingWhitespace() " --------------------------------------------------------------------------- " Auto Commands / File Types -- 2.45.2 From 4155e551d3086224820400bebdcc6e9c5577c856 Mon Sep 17 00:00:00 2001 From: Tony Duckles Date: Sun, 31 Dec 2017 10:32:27 -0600 Subject: [PATCH 10/16] bin/git-amend: Smarter 'git stash' handling - Fix 'stash pop' handling to always restore back to the stashed changes afterwards. - Only stash if there are local modifications. --- bin/git-amend | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/bin/git-amend b/bin/git-amend index 9101a67..7369128 100755 --- a/bin/git-amend +++ b/bin/git-amend @@ -23,12 +23,15 @@ test -z "$TARGET" && { exit 1 } -# stash off work tree modifications leaving the -# index for amending to the target commit -git stash save -q --keep-index git-amend - +# if there are local work tree modifications, stash those off leaving +# the index for amending to the target commit +DIRTY=0 +if ! git diff-files --quiet --ignore-submodules --; then + DIRTY=1 +fi +test $DIRTY -eq 1 && git stash save -q --keep-index git-amend # always restore from stash before exiting -trap 'git stash pop -q stash@{git-amend} 2>/dev/null' EXIT +test $DIRTY -eq 1 && trap 'git stash pop -q stash@{0} 2>/dev/null' EXIT # go back in history git checkout -q "$TARGET" || { -- 2.45.2 From 85863956d89796f760256c61c42a53a06658b1c1 Mon Sep 17 00:00:00 2001 From: Tony Duckles Date: Sun, 31 Dec 2017 15:13:07 -0600 Subject: [PATCH 11/16] .vimrc: Add vim-gitgutter plugin --- .vimrc | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.vimrc b/.vimrc index 0269b4f..0227c00 100644 --- a/.vimrc +++ b/.vimrc @@ -17,6 +17,7 @@ set autoread " reload files (no local changes only) call plug#begin('~/.vim/plugged') +Plug 'airblade/vim-gitgutter' Plug 'altercation/vim-colors-solarized' Plug 'kien/ctrlp.vim' Plug 'kopischke/vim-fetch' @@ -74,14 +75,17 @@ if !exists('g:airline_symbols') let g:airline_symbols = {} endif if has("gui_running") - let g:airline_powerline_fonts = 1 " use powerline font symbols + let g:airline_powerline_fonts = 1 " use powerline font symbols else - let g:airline_symbols_ascii = 1 " use plain ascii symbols + let g:airline_symbols_ascii = 1 " use plain ascii symbols let g:airline_symbols.branch = 'BR:' endif let g:airline_symbols.linenr = '' let g:airline_symbols.maxlinenr = '' +" gitgutter +let g:gitgutter_enabled = 0 " disable by default + " --------------------------------------------------------------------------- " Terminal Settings " --------------------------------------------------------------------------- @@ -154,6 +158,7 @@ set nowritebackup " do not keep a backup while working set backupcopy=yes " keep attributes of original file set backupskip=/tmp/*,$TMPDIR/*,$TMP/*,$TEMP/* set directory=.,~/tmp,~/.vim/swap " swap file directory-order +set updatetime=1000 " idle time before writing swap file to disk " ---------------------------------------------------------------------------- " UI @@ -321,6 +326,11 @@ nmap tw :set wrap! wrap? nmap ws :set list! list? " open tag definition in a horz split nmap tag :split :exec("tag ".expand("")) +" gitgutter +nmap ht :GitGutterToggle +nmap hp GitGutterPreviewHunk +nmap hu GitGutterUndoHunk +nmap hs GitGutterStageHunk " -------------------------------------------------------------------------- " Functions -- 2.45.2 From d57c72c9432094bd11a745be0e00db4640abd92a Mon Sep 17 00:00:00 2001 From: Tony Duckles Date: Sat, 30 Dec 2017 22:45:45 -0600 Subject: [PATCH 12/16] .vim: Support folding based on custom section markers --- .bashrc | 5 +++ .vim/bundle/autofolds/plugin/autofolds.vim | 43 ++++++++++++++++++++++ .vimrc | 3 ++ 3 files changed, 51 insertions(+) create mode 100644 .vim/bundle/autofolds/plugin/autofolds.vim diff --git a/.bashrc b/.bashrc index 907dfc1..6aff4c5 100644 --- a/.bashrc +++ b/.bashrc @@ -3,6 +3,10 @@ # A basically sane bash environment. # Tony Duckles (based on http://github.com/rtomayko/dotfiles) +# ---------------------------------------------------------------------- +# BASICS +# ---------------------------------------------------------------------- + # short-circuit for non-interactive sessions [ -z "$PS1" ] && return @@ -462,3 +466,4 @@ test -n "$INTERACTIVE" -a -n "$LOGIN" && { } # vim: ts=4 sts=4 shiftwidth=4 expandtab +# vim: foldmethod=expr foldexpr=autofolds#foldexpr(v\:lnum,'sh') foldtext=autofolds#foldtext() foldlevel=2 diff --git a/.vim/bundle/autofolds/plugin/autofolds.vim b/.vim/bundle/autofolds/plugin/autofolds.vim new file mode 100644 index 0000000..dafb546 --- /dev/null +++ b/.vim/bundle/autofolds/plugin/autofolds.vim @@ -0,0 +1,43 @@ +" autofolds +" ========= +" Automatic folding based on custom section markers +" Inspired by: https://vi.stackexchange.com/a/6608 + +function! autofolds#foldexpr(lnum, ...) + let s:filetype = a:0 > 0 ? a:1 : 'vim' " optional 'filetype' param + let s:comment_char = '' + if s:filetype == 'vim' + let s:comment_char = '"' + elseif s:filetype == 'sh' + let s:comment_char = '#' + endif + if s:comment_char == '' + return '=' + endif + let s:thisline = getline(a:lnum) + let s:two_following_lines = 0 + if line(a:lnum) + 2 <= line('$') + let s:line_1_after = getline(a:lnum+1) + let s:line_2_after = getline(a:lnum+2) + let s:two_following_lines = 1 + endif + if !s:two_following_lines + return '=' + endif + else + if (match(s:thisline, '^'.s:comment_char.' ----------') >= 0) && + \ (match(s:line_1_after, '^'.s:comment_char.' ') >= 0) && + \ (match(s:line_2_after, '^'.s:comment_char.' ----------') >= 0) + return '>1' + else + return '=' + endif + endif +endfunction + +function! autofolds#foldtext() + let s:lines = string(v:foldend-v:foldstart) " # of lines in fold range + let s:text = getline(v:foldstart+1)[2:] " extract text after leading comment marker + let s:text = substitute(s:text,'^\s*\(.\{-}\)\s*$', '\1', '') " strip leading/trailing whitespace + return '+'.repeat('-', 1 + v:foldlevel).repeat(' ', 3-len(s:lines)).s:lines.' lines: '.s:text.' ' " mimic standard foldtext() format +endfunction diff --git a/.vimrc b/.vimrc index 0227c00..1b6d7c9 100644 --- a/.vimrc +++ b/.vimrc @@ -33,6 +33,7 @@ Plug 'tpope/vim-unimpaired' Plug 'vim-airline/vim-airline' Plug 'vim-airline/vim-airline-themes' +Plug '~/.vim/bundle/autofolds' Plug '~/.vim/bundle/matchit' Plug '~/.vim/bundle/mumps' @@ -424,3 +425,5 @@ augroup END if filereadable(glob("~/.vimrc.local")) source ~/.vimrc.local endif + +" vim: foldmethod=expr foldexpr=autofolds#foldexpr(v\:lnum) foldtext=autofolds#foldtext() foldlevel=2 -- 2.45.2 From 668159f7a07ed2eb72e110b26f243ad60b8295c9 Mon Sep 17 00:00:00 2001 From: Tony Duckles Date: Mon, 1 Jan 2018 09:25:44 -0600 Subject: [PATCH 13/16] .vimrc: Put new vsplit windows to the right of the current --- .vimrc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.vimrc b/.vimrc index 1b6d7c9..ee4bc90 100644 --- a/.vimrc +++ b/.vimrc @@ -181,9 +181,8 @@ set nostartofline " don't jump to the start of line when scrolling set scrolloff=4 " vertical padding set sidescroll=40 " side-scrolling increment (for nowrap mode) set sidescrolloff=10 " horz padding -if version >= 700 - set tabpagemax=50 " open 50 tabs max -endif +set tabpagemax=15 " open 15 tabs max +set splitright " put new vsplit windows to the right of the current " ---------------------------------------------------------------------------- " Visual Cues -- 2.45.2 From f9c10e2e58708cce236c02dcca405084cfe71ebf Mon Sep 17 00:00:00 2001 From: Tony Duckles Date: Mon, 1 Jan 2018 10:56:22 -0600 Subject: [PATCH 14/16] bin/ack: ack v2.22 --- bin/ack | 898 +++++++++++++++++++++++++++----------------------------- 1 file changed, 425 insertions(+), 473 deletions(-) diff --git a/bin/ack b/bin/ack index 50d4290..80329a4 100755 --- a/bin/ack +++ b/bin/ack @@ -4,7 +4,7 @@ # Please DO NOT EDIT or send patches for it. # # Please take a look at the source from -# https://github.com/petdance/ack2 +# https://github.com/beyondgrep/ack2 # and submit patches against the individual files # that build ack. # @@ -13,8 +13,7 @@ package main; use strict; use warnings; - -our $VERSION = '2.15_01'; # Check http://beyondgrep.com/ for updates +our $VERSION = '2.22'; # Check https://beyondgrep.com/ for updates use 5.008008; use Getopt::Long 2.38 (); @@ -24,7 +23,7 @@ use File::Spec (); # XXX Don't make this so brute force -# See also: https://github.com/petdance/ack2/issues/89 +# See also: https://github.com/beyondgrep/ack2/issues/89 our $opt_after_context; our $opt_before_context; @@ -45,7 +44,8 @@ our $opt_L; our $opt_l; our $opt_passthru; our $opt_column; -# flag if we need any context tracking + +# Flag if we need any context tracking. our $is_tracking_context; # These are all our globals. @@ -63,9 +63,9 @@ MAIN: { last if ( $arg eq '--' ); # Get the --thpppt, --bar, --cathy checking out of the way. - $arg =~ /^--th[pt]+t+$/ and App::Ack::_thpppt($arg); - $arg eq '--bar' and App::Ack::_bar(); - $arg eq '--cathy' and App::Ack::_cathy(); + $arg =~ /^--th[pt]+t+$/ and App::Ack::thpppt($arg); + $arg eq '--bar' and App::Ack::ackbar(); + $arg eq '--cathy' and App::Ack::cathy(); # See if we want to ignore the environment. (Don't tell Al Gore.) $arg eq '--env' and $env_is_usable = 1; @@ -110,16 +110,16 @@ sub _compile_descend_filter { } } - # if we have one or more --noignore-dir directives, we can't ignore + # If we have one or more --noignore-dir directives, we can't ignore # entire subdirectory hierarchies, so we return an "accept all" - # filter and scrutinize the files more in _compile_file_filter + # filter and scrutinize the files more in _compile_file_filter. return if $dont_ignore_dirs; return unless $idirs; $idirs = $opt->{idirs}; return sub { - my $resource = App::Ack::Resource::Basic->new($File::Next::dir); + my $resource = App::Ack::Resource->new($File::Next::dir); return !grep { $_->filter($resource) } @{$idirs}; }; } @@ -147,8 +147,7 @@ sub _compile_file_filter { my @ignore_dir_filter = @{$opt->{idirs} || []}; my @is_inverted = map { $_->is_inverted() } @ignore_dir_filter; - # this depends on InverseFilter->invert returning the original - # filter (for optimization) + # This depends on InverseFilter->invert returning the original filter (for optimization). @ignore_dir_filter = map { $_->is_inverted() ? $_->invert() : $_ } @ignore_dir_filter; my $dont_ignore_dir_filter = grep { $_ } @is_inverted; my $previous_dir = ''; @@ -157,10 +156,10 @@ sub _compile_file_filter { return sub { if ( $opt_g ) { if ( $File::Next::name =~ /$opt_regex/ && $opt_v ) { - return; + return 0; } if ( $File::Next::name !~ /$opt_regex/ && !$opt_v ) { - return; + return 0; } } # ack always selects files that are specified on the command @@ -180,7 +179,7 @@ sub _compile_file_filter { my $is_ignoring = 0; for ( my $i = 0; $i < @dirs; $i++) { - my $dir_rsrc = App::Ack::Resource::Basic->new(File::Spec->catfile(@dirs[0 .. $i])); + my $dir_rsrc = App::Ack::Resource->new(File::Spec->catfile(@dirs[0 .. $i])); my $j = 0; for my $filter (@ignore_dir_filter) { @@ -218,7 +217,7 @@ sub _compile_file_filter { } } - my $resource = App::Ack::Resource::Basic->new($File::Next::name); + my $resource = App::Ack::Resource->new($File::Next::name); if ( $ifiles_filters && $ifiles_filters->filter($resource) ) { return 0; @@ -267,7 +266,7 @@ sub filetypes { my $filters = $App::Ack::mappings{$k}; foreach my $filter (@{$filters}) { - # clone the resource + # Clone the resource. my $clone = $resource->clone; if ( $filter->filter($clone) ) { push @matches, $k; @@ -291,12 +290,12 @@ sub get_file_id { return File::Next::reslash( $filename ); } else { - # XXX is this the best method? it always hits the FS + # XXX Is this the best method? It always hits the FS. if( my ( $dev, $inode ) = (stat($filename))[0, 1] ) { return join(':', $dev, $inode); } else { - # XXX this could be better + # XXX This could be better. return $filename; } } @@ -338,19 +337,19 @@ my $match_column_number; { -# number of context lines +# Number of context lines my $n_before_ctx_lines; my $n_after_ctx_lines; -# array to keep track of lines that might be required for a "before" context +# Array to keep track of lines that might be required for a "before" context my @before_context_buf; -# position to insert next line in @before_context_buf +# Position to insert next line in @before_context_buf my $before_context_pos; -# number of "after" context lines still pending +# Number of "after" context lines still pending my $after_context_pending; -# number of latest line that got printed +# Number of latest line that got printed my $printed_line_no; my $is_iterating; @@ -362,9 +361,8 @@ BEGIN { $has_printed_something = 0; } -# setup context tracking variables -sub setup_line_context { - +# Set up context tracking variables. +sub set_up_line_context { $n_before_ctx_lines = $opt_output ? 0 : ($opt_before_context || 0); $n_after_ctx_lines = $opt_output ? 0 : ($opt_after_context || 0); @@ -378,9 +376,8 @@ sub setup_line_context { return; } -# adjust context tracking variables when entering a new file -sub setup_line_context_for_file { - +# Adjust context tracking variables when entering a new file. +sub set_up_line_context_for_file { $printed_line_no = 0; $after_context_pending = 0; if ( $opt_heading && !$opt_lines ) { @@ -390,7 +387,7 @@ sub setup_line_context_for_file { return; } -=for Developers +=begin Developers This subroutine jumps through a number of optimization hoops to try to be fast in the more common use cases of ack. For one thing, @@ -402,10 +399,12 @@ to the others if they make sense. The non-context branches also inline does_match for performance reasons; any relevant changes that happen here must also happen there. +=end Developers + =cut sub print_matches_in_resource { - my ( $resource, $opt ) = @_; + my ( $resource ) = @_; my $max_count = $opt_m || -1; my $nmatches = 0; @@ -429,12 +428,11 @@ sub print_matches_in_resource { $display_filename = Term::ANSIColor::colored($display_filename, $ENV{ACK_COLOR_FILENAME}); } - # check for context before the main loop, so we don't - # pay for it if we don't need it + # Check for context before the main loop, so we don't pay for it if we don't need it. if ( $is_tracking_context ) { $after_context_pending = 0; while ( <$fh> ) { - if ( does_match($opt, $_) && $max_count ) { + if ( does_match( $_ ) && $max_count ) { if ( !$has_printed_for_this_resource ) { if ( $opt_break && $has_printed_something ) { App::Ack::print_blank_line(); @@ -443,32 +441,32 @@ sub print_matches_in_resource { App::Ack::print_filename( $display_filename, $ors ); } } - print_line_with_context($opt, $filename, $_, $.); + print_line_with_context( $filename, $_, $. ); $has_printed_for_this_resource = 1; $nmatches++; $max_count--; } elsif ( $opt_passthru ) { - chomp; # XXX proper newline handling? - # XXX inline this call? + chomp; # XXX Proper newline handling? + # XXX Inline this call? if ( $opt_break && !$has_printed_for_this_resource && $has_printed_something ) { App::Ack::print_blank_line(); } - print_line_with_options($opt, $filename, $_, $., ':'); + print_line_with_options( $filename, $_, $., ':' ); $has_printed_for_this_resource = 1; } else { - chomp; # XXX proper newline handling? - print_line_if_context($opt, $filename, $_, $., '-'); + chomp; # XXX Proper newline handling? + print_line_if_context( $filename, $_, $., '-' ); } last if ($max_count == 0) && ($after_context_pending == 0); } } else { - local $_; - if ( $opt_passthru ) { + local $_; + while ( <$fh> ) { $match_column_number = undef; if ( $opt_v ? !/$opt_regex/o : /$opt_regex/o ) { @@ -483,7 +481,7 @@ sub print_matches_in_resource { App::Ack::print_filename( $display_filename, $ors ); } } - print_line_with_context($opt, $filename, $_, $.); + print_line_with_context( $filename, $_, $. ); $has_printed_for_this_resource = 1; $nmatches++; $max_count--; @@ -493,13 +491,15 @@ sub print_matches_in_resource { if ( $opt_break && !$has_printed_for_this_resource && $has_printed_something ) { App::Ack::print_blank_line(); } - print_line_with_options($opt, $filename, $_, $., ':'); + print_line_with_options( $filename, $_, $., ':' ); $has_printed_for_this_resource = 1; } last unless $max_count != 0; } } elsif ( $opt_v ) { + local $_; + $match_column_number = undef; while ( <$fh> ) { if ( !/$opt_regex/o ) { @@ -511,7 +511,7 @@ sub print_matches_in_resource { App::Ack::print_filename( $display_filename, $ors ); } } - print_line_with_context($opt, $filename, $_, $.); + print_line_with_context( $filename, $_, $. ); $has_printed_for_this_resource = 1; $nmatches++; $max_count--; @@ -520,78 +520,39 @@ sub print_matches_in_resource { } } else { - # XXX unroll first match check ($has_printed_for_this_resource) - # XXX what if this is a *huge* file? (see also -l) - my $contents = do { - local $/; - <$fh>; - }; - - my $prev_match_end = 0; - my $line_no = 1; - - $match_column_number = undef; - while ( $contents =~ /$opt_regex/og ) { - my $match_start = $-[0]; - my $match_end = $+[0]; - - pos($contents) = $prev_match_end; - $prev_match_end = $match_end; - - while ( $contents =~ /\n/og && $-[0] < $match_start ) { - $line_no++; - } - - my $start_line = rindex($contents, "\n", $match_start); - my $end_line = index($contents, "\n", $match_end); - - if ( $start_line == -1 ) { - $start_line = 0; - } - else { - $start_line++; - } + local $_; - if ( $end_line == -1 ) { - $end_line = length($contents); - } - else { - $end_line--; - } - $match_column_number = $match_start - $start_line + 1; - if ( !$has_printed_for_this_resource ) { - if ( $opt_break && $has_printed_something ) { - App::Ack::print_blank_line(); - } - if ( $opt_show_filename && $opt_heading ) { - App::Ack::print_filename( $display_filename, $ors ); + while ( <$fh> ) { + $match_column_number = undef; + if ( /$opt_regex/o ) { + $match_column_number = $-[0] + 1; + if ( !$has_printed_for_this_resource ) { + if ( $opt_break && $has_printed_something ) { + App::Ack::print_blank_line(); + } + if ( $opt_show_filename && $opt_heading ) { + App::Ack::print_filename( $display_filename, $ors ); + } } + s/[\r\n]+$//g; + print_line_with_options( $filename, $_, $., ':' ); + $has_printed_for_this_resource = 1; + $nmatches++; + $max_count--; } - my $line = substr($contents, $start_line, $end_line - $start_line + 1); - $line =~ s/[\r\n]+$//g; - print_line_with_options($opt, $filename, $line, $line_no, ':'); - - pos($contents) = $end_line + 1; - - $has_printed_for_this_resource = 1; - $nmatches++; - $max_count--; - last unless $max_count != 0; } } } - $is_iterating = 0; # XXX this won't happen on an exception - # then again, do we care? ack doesn't really - # handle exceptions anyway. + $is_iterating = 0; return $nmatches; } sub print_line_with_options { - my ( $opt, $filename, $line, $line_no, $separator ) = @_; + my ( $filename, $line, $line_no, $separator ) = @_; $has_printed_something = 1; $printed_line_no = $line_no; @@ -621,22 +582,23 @@ sub print_line_with_options { } if( $opt_output ) { while ( $line =~ /$opt_regex/og ) { - # XXX We need to stop using eval() for --output. See https://github.com/petdance/ack2/issues/421 + # XXX We need to stop using eval() for --output. See https://github.com/beyondgrep/ack2/issues/421 my $output = eval $opt_output; App::Ack::print( join( $separator, @line_parts, $output ), $ors ); } } else { if ( $opt_color ) { - $line =~ /$opt_regex/o; # this match is redundant, but we need - # to perfom it in order to get if - # capture groups are set + # This match is redundant, but we need to perfom it in order to get if capture groups are set. + $line =~ /$opt_regex/o; - if ( @+ > 1 ) { # if we have captures + if ( @+ > 1 ) { # If we have captures... while ( $line =~ /$opt_regex/og ) { - my $offset = 0; # additional offset for when we add stuff + my $offset = 0; # Additional offset for when we add stuff. my $previous_match_end = 0; + last if $-[0] == $+[0]; + for ( my $i = 1; $i < @+; $i++ ) { my ( $match_start, $match_end ) = ( $-[$i], $+[$i] ); @@ -651,7 +613,7 @@ sub print_line_with_options { substr( $line, $offset + $match_start, $match_end - $match_start, $substitution ); - $previous_match_end = $match_end; # offsets do not need to be applied + $previous_match_end = $match_end; # Offsets do not need to be applied. $offset += length( $substitution ) - length( $substring ); } @@ -659,13 +621,14 @@ sub print_line_with_options { } } else { - my $matched = 0; # flag; if matched, need to escape afterwards + my $matched = 0; # If matched, need to escape afterwards. while ( $line =~ /$opt_regex/og ) { $matched = 1; my ( $match_start, $match_end ) = ($-[0], $+[0]); next unless defined($match_start); + last if $match_start == $match_end; my $substring = substr( $line, $match_start, $match_end - $match_start ); @@ -678,7 +641,7 @@ sub print_line_with_options { pos($line) = $match_end + (length( $substitution ) - length( $substring )); } - # XXX why do we do this? + # XXX Why do we do this? $line .= "\033[0m\033[K" if $matched; } } @@ -691,7 +654,7 @@ sub print_line_with_options { } sub iterate { - my ( $resource, $opt, $cb ) = @_; + my ( $resource, $cb ) = @_; $is_iterating = 1; @@ -719,29 +682,27 @@ sub iterate { } } - $is_iterating = 0; # XXX this won't happen on an exception - # then again, do we care? ack doesn't really - # handle exceptions anyway. + $is_iterating = 0; return; } sub print_line_with_context { - my ( $opt, $filename, $matching_line, $line_no ) = @_; + my ( $filename, $matching_line, $line_no ) = @_; my $ors = $opt_print0 ? "\0" : "\n"; my $is_tracking_context = $opt_after_context || $opt_before_context; $matching_line =~ s/[\r\n]+$//g; - # check if we need to print context lines first - if( $is_tracking_context ) { + # Check if we need to print context lines first. + if ( $is_tracking_context ) { my $before_unprinted = $line_no - $printed_line_no - 1; if ( !$is_first_match && ( !$printed_line_no || $before_unprinted > $n_before_ctx_lines ) ) { App::Ack::print('--', $ors); } - # We want at most $n_before_ctx_lines of context + # We want at most $n_before_ctx_lines of context. if ( $before_unprinted > $n_before_ctx_lines ) { $before_unprinted = $n_before_ctx_lines; } @@ -751,17 +712,17 @@ sub print_line_with_context { chomp $line; - # Disable $opt->{column} since there are no matches in the context lines + # Disable $opt->{column} since there are no matches in the context lines. local $opt_column = 0; - print_line_with_options($opt, $filename, $line, $line_no-$before_unprinted, '-'); + print_line_with_options( $filename, $line, $line_no-$before_unprinted, '-' ); $before_unprinted--; } } - print_line_with_options($opt, $filename, $matching_line, $line_no, ':'); + print_line_with_options( $filename, $matching_line, $line_no, ':' ); - # We want to get the next $n_after_ctx_lines printed + # We want to get the next $n_after_ctx_lines printed. $after_context_pending = $n_after_ctx_lines; $is_first_match = 0; @@ -769,18 +730,18 @@ sub print_line_with_context { return; } -# print the line only if it's part of a context we need to display +# Print the line only if it's part of a context we need to display. sub print_line_if_context { - my ( $opt, $filename, $line, $line_no, $separator ) = @_; + my ( $filename, $line, $line_no, $separator ) = @_; if ( $after_context_pending ) { - # Disable $opt->{column} since there are no matches in the context lines + # Disable $opt_column since there are no matches in the context lines. local $opt_column = 0; - print_line_with_options( $opt, $filename, $line, $line_no, $separator ); + print_line_with_options( $filename, $line, $line_no, $separator ); --$after_context_pending; } elsif ( $n_before_ctx_lines ) { - # save line for "before" context + # Save line for "before" context. $before_context_buf[$before_context_pos] = $_; $before_context_pos = ($before_context_pos+1) % $n_before_ctx_lines; } @@ -792,16 +753,18 @@ sub print_line_if_context { # does_match() MUST have an $opt_regex set. -=for Developers +=begin Developers This subroutine is inlined a few places in print_matches_in_resource for performance reasons, so any changes here must be copied there as well. +=end Developers + =cut sub does_match { - my ( $opt, $line ) = @_; + my ( $line ) = @_; $match_column_number = undef; @@ -826,7 +789,7 @@ sub get_match_column { } sub resource_has_match { - my ( $resource, $opt ) = @_; + my ( $resource ) = @_; my $has_match = 0; my $fh = $resource->open(); @@ -836,23 +799,12 @@ sub resource_has_match { } } else { - if ( $opt_v ) { - while ( <$fh> ) { - if (!/$opt_regex/o) { - $has_match = 1; - last; - } + while ( <$fh> ) { + if (/$opt_regex/o xor $opt_v) { + $has_match = 1; + last; } } - else { - # XXX read in chunks - # XXX only do this for certain file sizes? - my $content = do { - local $/; - <$fh>; - }; - $has_match = $content =~ /$opt_regex/o; - } close $fh; } @@ -860,7 +812,7 @@ sub resource_has_match { } sub count_matches_in_resource { - my ( $resource, $opt ) = @_; + my ( $resource ) = @_; my $nmatches = 0; my $fh = $resource->open(); @@ -870,17 +822,8 @@ sub count_matches_in_resource { } } else { - if ( $opt_v ) { - while ( <$fh> ) { - ++$nmatches if (!/$opt_regex/o); - } - } - else { - my $content = do { - local $/; - <$fh>; - }; - $nmatches =()= ($content =~ /$opt_regex/og); + while ( <$fh> ) { + ++$nmatches if (/$opt_regex/o xor $opt_v); } close $fh; } @@ -996,17 +939,15 @@ sub main { my $nmatches = 0; my $total_count = 0; - setup_line_context( $opt ); + set_up_line_context(); RESOURCES: while ( my $resource = $resources->next ) { if ($is_tracking_context) { - setup_line_context_for_file($opt); + set_up_line_context_for_file(); } - # XXX Combine the -f and -g functions if ( $opt_f ) { - # XXX printing should probably happen inside of App::Ack if ( $opt->{show_types} ) { show_types( $resource, $ors ); } @@ -1023,7 +964,7 @@ RESOURCES: else { local $opt_show_filename = 0; # XXX Why is this local? - print_line_with_options($opt, '', $resource->name, 0, $ors); + print_line_with_options( '', $resource->name, 0, $ors ); } ++$nmatches; last RESOURCES if defined($opt_m) && $nmatches >= $opt_m; @@ -1044,23 +985,23 @@ RESOURCES: local $opt_color = 0; - iterate($resource, $opt, sub { + iterate( $resource, sub { chomp; if ( $line_numbers{$.} ) { - print_line_with_context($opt, $filename, $_, $.); + print_line_with_context( $filename, $_, $. ); } elsif ( $opt_passthru ) { - print_line_with_options($opt, $filename, $_, $., ':'); + print_line_with_options( $filename, $_, $., ':' ); } elsif ( $is_tracking_context ) { - print_line_if_context($opt, $filename, $_, $., '-'); + print_line_if_context( $filename, $_, $., '-' ); } return 1; }); } elsif ( $opt_count ) { - my $matches_for_this_file = count_matches_in_resource( $resource, $opt ); + my $matches_for_this_file = count_matches_in_resource( $resource ); if ( not $opt_show_filename ) { $total_count += $matches_for_this_file; @@ -1077,7 +1018,7 @@ RESOURCES: } } elsif ( $opt_l || $opt_L ) { - my $is_match = resource_has_match( $resource, $opt ); + my $is_match = resource_has_match( $resource ); if ( $opt_L ? !$is_match : $is_match ) { App::Ack::print( $resource->name, $ors ); @@ -1103,7 +1044,9 @@ RESOURCES: App::Ack::exit_from_ack( $nmatches ); } +=pod +=encoding UTF-8 =head1 NAME @@ -1116,11 +1059,11 @@ ack - grep-like text finder =head1 DESCRIPTION -Ack is designed as an alternative to F for programmers. +ack is designed as an alternative to F for programmers. -Ack searches the named input FILEs (or standard input if no files -are named, or the file name - is given) for lines containing a match -to the given PATTERN. By default, ack prints the matching lines. +ack searches the named input files or directories for lines containing a +match to the given PATTERN. By default, ack prints the matching lines. +If no FILE or DIRECTORY is given, the current directory will be searched. PATTERN is a Perl regular expression. Perl regular expressions are commonly found in other programming languages, but for the particulars @@ -1217,6 +1160,8 @@ when used interactively. =item B<-C [I]>, B<--context[=I]> Print I lines (default 2) of context around matching lines. +You can specify zero lines of context to override another context +specified in an ackrc. =item B<-c>, B<--count> @@ -1301,9 +1246,26 @@ This is off by default. =item B<-g I> -Print files where the relative path + filename matches I. -This option can be combined with B<--color> to make it easier to spot -the match. +Print searchable files where the relative path + filename matches +I. + +Note that + + ack -g foo + +is exactly the same as + + ack -f | ack foo + +This means that just as ack will not search, for example, F<.jpg> +files, C<-g> will not list F<.jpg> files either. ack is not intended +to be a general-purpose file finder. + +Note also that if you have C<-i> in your .ackrc that the filenames +to be matched will be case-insensitive as well. + +This option can be combined with B<--color> to make it easier to +spot the match. =item B<--[no]group> @@ -1524,6 +1486,21 @@ Display version and copyright information. =item B<-w>, B<--word-regexp> +=item B<-w>, B<--word-regexp> + +Turn on "words mode". This sometimes matches a whole word, but the +semantics is quite subtle. If the passed regexp begins with a word +character, then a word boundary is required before the match. If the +passed regexp ends with a word character, or with a word character +followed by newline, then a word boundary is required after the match. + +Thus, for example, B<-w> with the regular expression C will not +match the strings C or C. However, if the regular +expression is C<(ox|ass)> then it will match those strings. Because +the regular expression's first character is C<(>, the B<-w> flag has +no effect at the start, and because the last character is C<)>, it has +no effect at the end. + Force PATTERN to match only whole words. The PATTERN is wrapped with C<\b> metacharacters. @@ -1565,7 +1542,7 @@ might look like this: # Always sort the files --sort-files - # Always color, even if piping to a another program + # Always color, even if piping to another program --color # Use "less -r" as my pager @@ -1587,6 +1564,12 @@ an F<.ackrc> file - then you do not have to define your types over and over again. In the following examples the options will always be shown on one command line so that they can be easily copy & pasted. +File types can be specified both with the the I<--type=xxx> option, +or the file type as an option itself. For example, if you create +a filetype of "cobol", you can specify I<--type=cobol> or simply +I<--cobol>. File types must be at least two characters long. This +is why the C language is I<--cc> and the R language is I<--rr>. + I searches for foo in all perl files. I tells you, that perl files are files ending in .pl, .pm, .pod or .t. So what if you would like to include .xs @@ -1618,7 +1601,6 @@ The following does B work in the F<.ackrc> file: --type-set eiffel:ext:e,eiffel - In order to see all currently defined types, use I<--help-types>, e.g. I @@ -1765,7 +1747,7 @@ these values. =head1 ACK & OTHER TOOLS -=head2 Vim integration +=head2 Simple vim integration F integrates easily with the Vim text editor. Set this in your F<.vimrc> to use F instead of F: @@ -1778,27 +1760,10 @@ with F and easily step through the results in Vim: :grep Dumper perllib -Miles Sterrett has written a Vim plugin for F which allows you to use -C<:Ack> instead of C<:grep>, as well as several other advanced features. - -L - -=head2 Emacs integration +=head2 Editor integration -Phil Jackson put together an F extension that "provides a -simple compilation mode ... has the ability to guess what files you -want to search for based on the major-mode." - -L - -=head2 TextMate integration - -Pedro Melo is a TextMate user who writes "I spend my day mostly -inside TextMate, and the built-in find-in-project sucks with large -projects. So I hacked a TextMate command that was using find + -grep to use ack. The result is the Search in Project with ack, and -you can find it here: -L" +Many users have integrated ack into their preferred text editors. +For details and links, see L. =head2 Shell and Return Code @@ -1920,22 +1885,28 @@ This shows how to pick out particular parts of a match using ( ) within regular input file contains "=head1 NAME" output "1 : NAME" -=head2 Share your knowledge +=head1 COMMUNITY -Join the ack-users mailing list. Send me your tips and I may add -them here. +There are ack mailing lists and a Slack channel for ack. See +L for details. =head1 FAQ =head2 Why isn't ack finding a match in (some file)? -Probably because it's of a type that ack doesn't recognize. ack's -searching behavior is driven by filetype. B +First, take a look and see if ack is even looking at the file. ack is +intelligent in what files it will search and which ones it won't, but +sometimes that can be surprising. -Use the C<-f> switch to see a list of files that ack will search -for you. You can use the C<--show-types> switch to show which type -ack thinks each file is. +Use the C<-f> switch, with no regex, to see a list of files that ack +will search for you. If your file doesn't show up in the list of files +that C shows, then ack never looks in it. + +NOTE: If you're using an old ack before 2.0, it's probably because it's of +a type that ack doesn't recognize. In ack 1.x, the searching behavior is +driven by filetype. B You can use the C<--show-types> switch to show +which type ack thinks each file is. =head2 Wouldn't it be great if F did search & replace? @@ -2003,9 +1974,15 @@ expression metacharacter!) =head2 Why does C<"ack '.{40000,}'"> fail? Isn't that a valid regex? -The Perl language limits the repetition quanitifier to 32K. You +The Perl language limits the repetition quantifier to 32K. You can search for C<.{32767}> but not C<.{32768}>. +=head2 Ack does "X" and shouldn't, should it? + +We try to remain as close to grep's behavior as possible, so when in doubt, +see what grep does! If there's a mismatch in functionality there, please +bring it up on the ack-users mailing list. + =head1 ACKRC LOCATION SEMANTICS Ack can load its configuration from many sources. The following list @@ -2220,7 +2197,7 @@ Andy Lester, C<< >> =head1 BUGS Please report any bugs or feature requests to the issues list at -Github: L +Github: L =head1 ENHANCEMENTS @@ -2230,7 +2207,7 @@ will not consider a request without it first getting seen by other ack users. This includes requests for new filetypes. There is a list of enhancements I want to make to F in the ack -issues list at Github: L +issues list at Github: L Patches are always welcome, but patches with tests get the most attention. @@ -2243,7 +2220,7 @@ Support for and information about F can be found at: =item * The ack homepage -L +L =item * The ack-users mailing list @@ -2251,7 +2228,7 @@ L =item * The ack issues list at Github -L +L =item * AnnoCPAN: Annotated CPAN documentation @@ -2265,9 +2242,13 @@ L L +=item * MetaCPAN + +L + =item * Git source repository -L +L =back @@ -2276,6 +2257,21 @@ L How appropriate to have Inowledgements! Thanks to everyone who has contributed to ack in any way, including +Michele Campeotto, +H.Merijn Brand, +Duke Leto, +Gerhard Poul, +Ethan Mallove, +Marek Kubica, +Ray Donnelly, +Nikolaj Schumacher, +Ed Avis, +Nick Morrott, +Austin Chamberlin, +Varadinsky, +SEbastien FeugEre, +Jakub Wilk, +Pete Houston, Stephen Thirlwall, Jonah Bishop, Chris Rebert, @@ -2377,7 +2373,7 @@ Rob Hoelz. =head1 COPYRIGHT & LICENSE -Copyright 2005-2015 Andy Lester. +Copyright 2005-2017 Andy Lester. This program is free software; you can redistribute it and/or modify it under the terms of the Artistic License v2.0. @@ -2395,8 +2391,8 @@ use strict; our $VERSION; our $COPYRIGHT; BEGIN { - $VERSION = '2.15_01'; - $COPYRIGHT = 'Copyright 2005-2015 Andy Lester.'; + $VERSION = '2.22'; + $COPYRIGHT = 'Copyright 2005-2017 Andy Lester.'; } our $fh; @@ -2425,7 +2421,7 @@ BEGIN { $output_to_pipe = not -t *STDOUT; $is_filter_mode = -p STDIN; - $is_cygwin = ($^O eq 'cygwin'); + $is_cygwin = ($^O eq 'cygwin' || $^O eq 'msys'); $is_windows = ($^O eq 'MSWin32'); $dir_sep_chars = $is_windows ? quotemeta( '\\/' ) : quotemeta( File::Spec->catfile( '', '' ) ); } @@ -2461,19 +2457,15 @@ sub filetypes_supported { return keys %mappings; } -sub _get_thpppt { +sub thpppt { my $y = q{_ /|,\\'!.x',=(www)=, U }; $y =~ tr/,x!w/\nOo_/; - return $y; -} -sub _thpppt { - my $y = _get_thpppt(); App::Ack::print( "$y ack $_[0]!\n" ); exit 0; } -sub _bar { +sub ackbar { my $x; $x = <<'_BAR'; 6?!I'7!I"?%+! @@ -2516,10 +2508,10 @@ sub _bar { 77I!+!7!?!7!I"71+!7, _BAR - return App::Ack::__pic($x); + return _pic_decode($x); } -sub _cathy { +sub cathy { my $x = <<'CATHY'; 0+!--+! 0|! "C!H!O!C!O!L!A!T!E!!! !|! @@ -2572,10 +2564,10 @@ sub _cathy { 0?!$! &N! )." .,! %."M! ":!M!.! 0 0N!:! %?!O! #.! ..! &,! &.!D!,! "N!I! 0 CATHY - return App::Ack::__pic($x); + return _pic_decode($x); } -sub __pic { +sub _pic_decode { my($compressed) = @_; $compressed =~ s/(.)(.)/$1x(ord($2)-32)/eg; App::Ack::print( $compressed ); @@ -2725,7 +2717,7 @@ Miscellaneous: Exit status is 0 if match, 1 if no match. -ack's home page is at http://beyondgrep.com/ +ack's home page is at https://beyondgrep.com/ The full ack manual is available by running "ack --man". @@ -2816,49 +2808,9 @@ sub get_copyright { } -# print*() subs added in order to make it easy for a third party -# module (such as App::Wack) to redefine the display methods -# and show the results in a different way. sub print { print {$fh} @_; return; } -sub print_first_filename { App::Ack::print( $_[0], "\n" ); return; } sub print_blank_line { App::Ack::print( "\n" ); return; } -sub print_separator { App::Ack::print( "--\n" ); return; } sub print_filename { App::Ack::print( $_[0], $_[1] ); return; } -sub print_line_no { App::Ack::print( $_[0], $_[1] ); return; } -sub print_column_no { App::Ack::print( $_[0], $_[1] ); return; } -sub print_count { - my $filename = shift; - my $nmatches = shift; - my $ors = shift; - my $count = shift; - my $show_filename = shift; - - if ($show_filename) { - App::Ack::print( $filename ); - App::Ack::print( ':', $nmatches ) if $count; - } - else { - App::Ack::print( $nmatches ) if $count; - } - App::Ack::print( $ors ); - - return; -} - -sub print_count0 { - my $filename = shift; - my $ors = shift; - my $show_filename = shift; - - if ($show_filename) { - App::Ack::print( $filename, ':0', $ors ); - } - else { - App::Ack::print( '0', $ors ); - } - - return; -} sub set_up_pager { my $command = shift; @@ -2898,59 +2850,159 @@ use strict; use overload '""' => 'name'; -sub FAIL { - require Carp; - Carp::confess( 'Must be overloaded' ); -} - sub new { - return FAIL(); + my $class = shift; + my $filename = shift; + + my $self = bless { + filename => $filename, + fh => undef, + opened => 0, + }, $class; + + if ( $self->{filename} eq '-' ) { + $self->{fh} = *STDIN; + $self->{opened} = 1; + } + + return $self; } + sub name { - return FAIL(); + return $_[0]->{filename}; } + sub basename { - return FAIL(); -} + my ( $self ) = @_; + # XXX Definedness? Pre-populate the slot with an undef? + unless ( exists $self->{basename} ) { + $self->{basename} = (File::Spec->splitpath($self->name))[2]; + } -sub is_binary { - return FAIL(); + return $self->{basename}; } + sub open { - return FAIL(); + my ( $self ) = @_; + + if ( !$self->{opened} ) { + if ( open $self->{fh}, '<', $self->{filename} ) { + $self->{opened} = 1; + } + else { + $self->{fh} = undef; + } + } + + return $self->{fh}; } + sub needs_line_scan { - return FAIL(); + my $self = shift; + my $opt = shift; + + return 1 if $opt->{v}; + + my $size = -s $self->{fh}; + if ( $size == 0 ) { + return 0; + } + elsif ( $size > 100_000 ) { + return 1; + } + + my $buffer; + my $rc = sysread( $self->{fh}, $buffer, $size ); + if ( !defined($rc) && $App::Ack::report_bad_filenames ) { + App::Ack::warn( "$self->{filename}: $!" ); + return 1; + } + return 0 unless $rc && ( $rc == $size ); + + return $buffer =~ /$opt->{regex}/m; } + sub reset { - return FAIL(); + my $self = shift; + + # Return if we haven't opened the file yet. + if ( !defined($self->{fh}) ) { + return; + } + + if ( !seek( $self->{fh}, 0, 0 ) && $App::Ack::report_bad_filenames ) { + App::Ack::warn( "$self->{filename}: $!" ); + } + + return; } + sub close { - return FAIL(); + my $self = shift; + + # Return if we haven't opened the file yet. + if ( !defined($self->{fh}) ) { + return; + } + + if ( !close($self->{fh}) && $App::Ack::report_bad_filenames ) { + App::Ack::warn( $self->name() . ": $!" ); + } + + $self->{opened} = 0; + + return; } + sub clone { - return FAIL(); + my ( $self ) = @_; + + return __PACKAGE__->new($self->name); } + sub firstliney { - return FAIL(); + my ( $self ) = @_; + + if ( !exists $self->{firstliney} ) { + my $fh = $self->open(); + if ( !$fh ) { + if ( $App::Ack::report_bad_filenames ) { + App::Ack::warn( $self->name . ': ' . $! ); + } + return ''; + } + + my $buffer = ''; + my $rc = sysread( $fh, $buffer, 250 ); + unless($rc) { # XXX handle this better? + $buffer = ''; + } + $buffer =~ s/[\r\n].*//s; + $self->{firstliney} = $buffer; + $self->reset; + + $self->close; + } + + return $self->{firstliney}; } 1; @@ -2958,6 +3010,8 @@ package App::Ack::Resources; +use Errno qw(EACCES); + use warnings; use strict; @@ -2967,9 +3021,7 @@ sub _generate_error_handler { if ( $opt->{dont_report_bad_filenames} ) { return sub { my $msg = shift; - # XXX restricting to specific error messages for now; I would - # prefer a different way of doing this - if ( $msg =~ /Permission denied/ ) { + if ( $! == EACCES ) { return; } App::Ack::warn( $msg ); @@ -3056,160 +3108,7 @@ sub next { my $file = $self->{iter}->() or return; - return App::Ack::Resource::Basic->new( $file ); -} - -1; -package App::Ack::Resource::Basic; - - -use warnings; -use strict; - -use Fcntl (); -use File::Spec (); - -BEGIN { - our @ISA = 'App::Ack::Resource'; -} - - - -sub new { - my $class = shift; - my $filename = shift; - - my $self = bless { - filename => $filename, - fh => undef, - opened => 0, - }, $class; - - if ( $self->{filename} eq '-' ) { - $self->{fh} = *STDIN; - $self->{opened} = 1; - } - - return $self; -} - - -sub name { - return $_[0]->{filename}; -} - -sub basename { - my ( $self ) = @_; - - # XXX definedness? pre-populate the slot with an undef? - unless ( exists $self->{basename} ) { - $self->{basename} = (File::Spec->splitpath($self->name))[2]; - } - - return $self->{basename}; -} - - -sub needs_line_scan { - my $self = shift; - my $opt = shift; - - return 1 if $opt->{v}; - - my $size = -s $self->{fh}; - if ( $size == 0 ) { - return 0; - } - elsif ( $size > 100_000 ) { - return 1; - } - - my $buffer; - my $rc = sysread( $self->{fh}, $buffer, $size ); - if ( !defined($rc) && $App::Ack::report_bad_filenames ) { - App::Ack::warn( "$self->{filename}: $!" ); - return 1; - } - return 0 unless $rc && ( $rc == $size ); - - my $regex = $opt->{regex}; - return $buffer =~ /$regex/m; -} - - -sub reset { - my $self = shift; - - # return if we haven't opened the file yet - if ( !defined($self->{fh}) ) { - return; - } - - if( !seek( $self->{fh}, 0, 0 ) && $App::Ack::report_bad_filenames ) { - App::Ack::warn( "$self->{filename}: $!" ); - } - - return; -} - - -sub close { - my $self = shift; - - # return if we haven't opened the file yet - if ( !defined($self->{fh}) ) { - return; - } - - if ( !close($self->{fh}) && $App::Ack::report_bad_filenames ) { - App::Ack::warn( $self->name() . ": $!" ); - } - - $self->{opened} = 0; - - return; -} - - -sub clone { - my ( $self ) = @_; - - return __PACKAGE__->new($self->name); -} - -sub firstliney { - my ( $self ) = @_; - - my $fh = $self->open(); - - if ( !exists $self->{firstliney} ) { - my $buffer = ''; - my $rc = sysread( $fh, $buffer, 250 ); - unless($rc) { # XXX handle this better? - $buffer = ''; - } - $buffer =~ s/[\r\n].*//s; - $self->{firstliney} = $buffer; - $self->reset; - } - - $self->close; - - return $self->{firstliney}; -} - -sub open { - my ( $self ) = @_; - - return $self->{fh} if $self->{opened}; - - if ( ! open $self->{fh}, '<', $self->{filename} ) { - return; - } - - $self->{opened} = 1; - - return $self->{fh}; + return App::Ack::Resource->new( $file ); } 1; @@ -3220,6 +3119,7 @@ use strict; + sub options { return split( /\n/, _options_block() ); } @@ -3267,6 +3167,8 @@ sub _options_block { # Git # http://git-scm.com/ --ignore-directory=is:.git +# When using submodules, .git is a file. +--ignore-file=is:.git # Mercurial # http://mercurial.selenic.com/ @@ -3419,7 +3321,7 @@ sub _options_block { # Clojure # http://clojure.org/ ---type-add=clojure:ext:clj +--type-add=clojure:ext:clj,cljs,edn,cljc # C # .xs are Perl C files @@ -3477,12 +3379,16 @@ sub _options_block { # http://groovy.codehaus.org/ --type-add=groovy:ext:groovy,gtmpl,gpp,grunit,gradle +# GSP +# http://groovy.codehaus.org/GSP +--type-add=gsp:ext:gsp + # Haskell # http://www.haskell.org/ --type-add=haskell:ext:hs,lhs # HTML ---type-add=html:ext:htm,html +--type-add=html:ext:htm,html,xhtml # Jade # http://jade-lang.com/ @@ -3497,12 +3403,16 @@ sub _options_block { # JSP # http://www.oracle.com/technetwork/java/javaee/jsp/index.html ---type-add=jsp:ext:jsp,jspx,jhtm,jhtml +--type-add=jsp:ext:jsp,jspx,jspf,jhtm,jhtml # JSON # http://www.json.org/ --type-add=json:ext:json +# Kotlin +# https://kotlinlang.org/ +--type-add=kotlin:ext:kt,kts + # Less # http://www.lesscss.org/ --type-add=less:ext:less @@ -3524,7 +3434,7 @@ sub _options_block { # OCaml # http://caml.inria.fr/ ---type-add=ocaml:ext:ml,mli +--type-add=ocaml:ext:ml,mli,mll,mly # Matlab # http://en.wikipedia.org/wiki/MATLAB @@ -3598,6 +3508,11 @@ sub _options_block { # http://learnboost.github.io/stylus/ --type-add=stylus:ext:styl +# Swift +# https://developer.apple.com/swift/ +--type-add=swift:ext:swift +--type-add=swift:firstlinematch:/^#!.*\bswift/ + # Tcl # http://www.tcl.tk/ --type-add=tcl:ext:tcl,itcl,itk @@ -3626,7 +3541,7 @@ sub _options_block { # XML # http://www.w3.org/TR/REC-xml/ ---type-add=xml:ext:xml,dtd,xsl,xslt,ent +--type-add=xml:ext:xml,dtd,xsd,xsl,xslt,ent,wsdl --type-add=xml:firstlinematch:/<[?]xml/ # YAML @@ -3712,8 +3627,10 @@ sub find_config_files { push @config_files, map { +{ path => $_ } } _check_for_ackrc($ENV{'HOME'}); } - # XXX This should go through some untainted cwd-fetching function, and not get untainted inline like this. my $cwd = Cwd::getcwd(); + return () unless defined $cwd; + + # XXX This should go through some untainted cwd-fetching function, and not get untainted brute-force like this. $cwd =~ /(.+)/; $cwd = $1; my @dirs = File::Spec->splitdir( $cwd ); @@ -3762,7 +3679,7 @@ use strict; use warnings; use Carp 1.04 (); -use Getopt::Long 2.35 (); +use Getopt::Long 2.38 (); use Text::ParseWords 3.1 (); @@ -3887,6 +3804,8 @@ sub uninvert_filter { $i--; } } + + return; } @@ -3987,7 +3906,7 @@ sub removed_option { $explanation ||= ''; return sub { - warn "Option '$option' is not valid in ack 2\n$explanation"; + warn "Option '$option' is not valid in ack 2.\n$explanation"; exit 1; }; } @@ -3997,19 +3916,28 @@ sub get_arg_spec { my ( $opt, $extra_specs ) = @_; my $dash_a_explanation = <<'EOT'; -This is because we now have -k/--known-types which makes it only select files -of known types, rather than any text file (which is the behavior of ack 1.x). -You may have options in a .ackrc, or in the ACKRC_OPTIONS environment variable. -Try using the --dump flag. +You don't need -a, ack 1.x users. This is because ack 2.x has +-k/--known-types which makes it only select files of known types, rather +than any text file (which is the behavior of ack 1.x). + +If you're surprised to see this message because you didn't put -a on the +command line, you may have options in an .ackrc, or in the ACKRC_OPTIONS +environment variable. Try using the --dump flag to help find it. EOT + sub _context_value { + my $val = shift; + + # Contexts default to 2. + return (!defined($val) || ($val < 0)) ? 2 : $val; + } + return { 1 => sub { $opt->{1} = $opt->{m} = 1 }, - 'A|after-context=i' => \$opt->{after_context}, - 'B|before-context=i' - => \$opt->{before_context}, - 'C|context:i' => sub { shift; my $val = shift; $opt->{before_context} = $opt->{after_context} = ($val || 2) }, + 'A|after-context:-1' => sub { shift; $opt->{after_context} = _context_value(shift) }, + 'B|before-context:-1' => sub { shift; $opt->{before_context} = _context_value(shift) }, + 'C|context:-1' => sub { shift; $opt->{before_context} = $opt->{after_context} = _context_value(shift) }, 'a' => removed_option('-a', $dash_a_explanation), 'all' => removed_option('--all', $dash_a_explanation), 'break!' => \$opt->{break}, @@ -4157,7 +4085,8 @@ sub process_other { die "Options --output, --pager and --match are forbidden in project .ackrc files.\n"; }; - $args_for_source = { %$args_for_source, + $args_for_source = { + %{$args_for_source}, 'output=s' => $illegal, 'pager:s' => $illegal, 'match=s' => $illegal, @@ -4416,6 +4345,8 @@ sub check_for_mutually_exclusive_options { } } } + + return; } @@ -4534,6 +4465,7 @@ sub retrieve_arg_sources { 1; # End of App::Ack::ConfigLoader package App::Ack::Filter; + use strict; use warnings; @@ -4589,6 +4521,7 @@ sub inspect { 1; package App::Ack::Filter::Extension; + use strict; use warnings; BEGIN { @@ -4644,6 +4577,8 @@ BEGIN { 1; package App::Ack::Filter::FirstLineMatch; + + use strict; use warnings; BEGIN { @@ -4698,6 +4633,7 @@ BEGIN { 1; package App::Ack::Filter::Is; + use strict; use warnings; BEGIN { @@ -4759,6 +4695,7 @@ BEGIN { use File::Spec 3.00; + sub new { my ( $class, $re ) = @_; @@ -4808,6 +4745,7 @@ BEGIN { 1; package App::Ack::Filter::Default; + use strict; use warnings; BEGIN { @@ -4829,6 +4767,8 @@ sub filter { 1; package App::Ack::Filter::Inverse; + + use strict; use warnings; BEGIN { @@ -4871,6 +4811,7 @@ sub inspect { 1; package App::Ack::Filter::Collection; + use strict; use warnings; BEGIN { @@ -4935,6 +4876,7 @@ sub to_string { 1; package App::Ack::Filter::IsGroup; + use strict; use warnings; BEGIN { @@ -4983,6 +4925,7 @@ sub to_string { 1; package App::Ack::Filter::ExtensionGroup; + use strict; use warnings; BEGIN { @@ -5032,6 +4975,7 @@ sub to_string { 1; package App::Ack::Filter::MatchGroup; + use strict; use warnings; BEGIN { @@ -5068,15 +5012,20 @@ sub filter { sub inspect { my ( $self ) = @_; + + # XXX Needs an explicit return. } sub to_string { my ( $self ) = @_; + + # XXX Needs an explicit return. } 1; package App::Ack::Filter::IsPath; + use strict; use warnings; BEGIN { @@ -5122,6 +5071,9 @@ sub to_string { 1; package App::Ack::Filter::IsPathGroup; + + + use strict; use warnings; BEGIN { @@ -5171,7 +5123,7 @@ use strict; use warnings; -our $VERSION = '1.12'; +our $VERSION = '1.16'; @@ -5187,7 +5139,7 @@ BEGIN { %files_defaults = ( file_filter => undef, descend_filter => undef, - error_handler => sub { CORE::die @_ }, + error_handler => sub { CORE::die $_[0] }, warning_handler => sub { CORE::warn @_ }, sort_files => undef, follow_symlinks => 1, @@ -5201,12 +5153,12 @@ sub files { die _bad_invocation() if @_ && defined($_[0]) && ($_[0] eq __PACKAGE__); my ($parms,@queue) = _setup( \%files_defaults, @_ ); - my $filter = $parms->{file_filter}; return sub { + my $filter = $parms->{file_filter}; while (@queue) { my ($dirname,$file,$fullpath) = splice( @queue, 0, 3 ); - if ( -f $fullpath || -p $fullpath || $fullpath =~ m{^/dev/fd} ) { + if ( -f $fullpath || -p _ || $fullpath =~ m{^/dev/fd} ) { if ( $filter ) { local $_ = $file; local $File::Next::dir = $dirname; @@ -5215,7 +5167,7 @@ sub files { } return wantarray ? ($dirname,$file,$fullpath) : $fullpath; } - elsif ( -d _ ) { + if ( -d _ ) { unshift( @queue, _candidate_files( $parms, $fullpath ) ); } } # while @@ -5234,7 +5186,7 @@ sub from_file { my ($parms,@queue) = _setup( \%files_defaults, @_ ); my $err = $parms->{error_handler}; - my $warn = $parms->{error_handler}; + my $warn = $parms->{warning_handler}; my $filename = $queue[1]; @@ -5249,13 +5201,13 @@ sub from_file { } else { if ( !open( $fh, '<', $filename ) ) { - $err->( "Unable to open $filename: $!" ); + $err->( "Unable to open $filename: $!", $! + 0 ); return undef; } } - my $filter = $parms->{file_filter}; return sub { + my $filter = $parms->{file_filter}; local $/ = $parms->{nul_separated} ? "\x00" : $/; while ( my $fullpath = <$fh> ) { chomp $fullpath; @@ -5348,7 +5300,7 @@ sub _candidate_files { my $dh; if ( !opendir $dh, $dirname ) { - $parms->{error_handler}->( "$dirname: $!" ); + $parms->{error_handler}->( "$dirname: $!", $! + 0 ); return; } @@ -5360,13 +5312,13 @@ sub _candidate_files { for my $file ( grep { !exists $skip_dirs{$_} } readdir $dh ) { my $has_stat; - # Only do directory checking if we have a descend_filter my $fullpath = File::Spec->catdir( $dirname, $file ); if ( !$follow_symlinks ) { next if -l $fullpath; $has_stat = 1; } + # Only do directory checking if we have a descend_filter if ( $descend_filter ) { if ( $has_stat ? (-d _) : (-d $fullpath) ) { local $File::Next::dir = $fullpath; -- 2.45.2 From c330b99d632821aa1b9d4e5d633185f279f95647 Mon Sep 17 00:00:00 2001 From: Tony Duckles Date: Thu, 4 Jan 2018 21:13:54 -0600 Subject: [PATCH 15/16] .vimrc: Add 'goyo' plugin - Distraction-free writing in Vim --- .vimrc | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/.vimrc b/.vimrc index ee4bc90..7e1ebb0 100644 --- a/.vimrc +++ b/.vimrc @@ -19,6 +19,8 @@ call plug#begin('~/.vim/plugged') Plug 'airblade/vim-gitgutter' Plug 'altercation/vim-colors-solarized' +Plug 'junegunn/goyo.vim' +Plug 'junegunn/limelight.vim' Plug 'kien/ctrlp.vim' Plug 'kopischke/vim-fetch' Plug 'mileszs/ack.vim' @@ -87,6 +89,27 @@ let g:airline_symbols.maxlinenr = '' " gitgutter let g:gitgutter_enabled = 0 " disable by default +" goyo + limelight +let g:goyo_width = 95 +let g:limelight_conceal_ctermfg = 240 + +function! s:goyo_enter() + if exists('$TMUX') + silent !tmux list-panes -F '\#F' | grep -q Z || tmux resize-pane -Z + endif + Limelight +endfunction + +function! s:goyo_leave() + if exists('$TMUX') + silent !tmux list-panes -F '\#F' | grep -q Z && tmux resize-pane -Z + endif + Limelight! +endfunction + +autocmd! User GoyoEnter nested call goyo_enter() +autocmd! User GoyoLeave nested call goyo_leave() + " --------------------------------------------------------------------------- " Terminal Settings " --------------------------------------------------------------------------- @@ -123,6 +146,7 @@ if &t_Co > 2 || has("gui_running") syntax enable " syntax highligting let g:solarized_termcolors=&t_Co " use 256 colors for solarized + let g:solarized_termtrans=1 colorscheme solarized let g:airline_theme='solarized16' " vim-airline theme @@ -331,6 +355,8 @@ nmap ht :GitGutterToggle nmap hp GitGutterPreviewHunk nmap hu GitGutterUndoHunk nmap hs GitGutterStageHunk +" goyo +nnoremap G :Goyo " -------------------------------------------------------------------------- " Functions -- 2.45.2 From c878dee518c0af3fbb6470d5932fcec31014d9f3 Mon Sep 17 00:00:00 2001 From: Tony Duckles Date: Fri, 5 Jan 2018 20:41:40 -0600 Subject: [PATCH 16/16] .vimrc: Tweak goyo settings --- .vimrc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.vimrc b/.vimrc index 7e1ebb0..e7abf52 100644 --- a/.vimrc +++ b/.vimrc @@ -90,13 +90,17 @@ let g:airline_symbols.maxlinenr = '' let g:gitgutter_enabled = 0 " disable by default " goyo + limelight -let g:goyo_width = 95 +let g:goyo_width = 80 let g:limelight_conceal_ctermfg = 240 +let g:limelight_default_coefficient = '.6' +let g:limelight_paragraph_span = 1 " show adjacent paragraphs +let g:limelight_priority = -1 " don't overrule hlsearch function! s:goyo_enter() if exists('$TMUX') silent !tmux list-panes -F '\#F' | grep -q Z || tmux resize-pane -Z endif + set scrolloff=999 Limelight endfunction @@ -104,6 +108,7 @@ function! s:goyo_leave() if exists('$TMUX') silent !tmux list-panes -F '\#F' | grep -q Z && tmux resize-pane -Z endif + set scrolloff=4 Limelight! endfunction -- 2.45.2