Squashed 'vim/bundle/go/' changes from 3efc952a7..bf390af42
bf390af42 New release: v1.16 e0f9c34ff Merge pull request #1626 from delphinus/feature/add-note-for-vim8 b670f2372 Add note for deoplete on Vim 8 6fb095f1d update CHANGELOG.md for #1611 19ae4ac25 Merge pull request #1611 from hiberabyss/master d6609168e verify 'vsplit' first c5d695482 also check whether mode contains 'vertical' 3a8cc93e5 Fix go#template#create() for directories that don't exist yet (#1618) 60a03b1ba fix errorformat for compilation errors (#1620) 7836e8a06 match vsplit instead of vertical ebe70faf6 improve neovim support f4b4ba13f Merge pull request #1583 from bhcleek/tests/test-output-parsing 40e2e1992 update changelog 6bfc9e2a6 Merge pull request #1613 from bhcleek/fix-neovim-tests 869928c83 Run all test files for Neovim, but skip :GoTest tests 3bc0099e4 Make sure all tests run in Neovim 978f01054 Merge pull request #1607 from Carpetsmoker/fillstruct-line 85c966323 change go_test_prepend_name to go_test_show_name 3f53d9bc7 add tests for test output parsing b8ad7d0eb Implement -line for fillstruct 0c98bdf53 Another Travis test 3df438c7d See if this get build on master b50d8f2c8 Fix installing `gocode` on Windows (#1606) 2a4272238 Append Go file type when creating temporary file (#1601) 7904a2776 Add support for denite.nvim about :GoDecls / :GoDeclsDir (#1604) 47251aa65 improve testing story (#1605) 21c262935 Update changelog.md 48c12aa1a Merge pull request #1597 from fatih/go-doc-url 2fe16b99f Support minisnip (#1589) 6366c6ef2 Code coverage reports with covimerage (#1586) 539cec678 Highlighting arguments (#1587) 7f4673573 Merge pull request #1602 from mocheryl/rename-usage-function a8af95cc2 Rename the usage function to make it callable 7938c88eb Update Changelog.md 3953d53e6 doc: use isnot instead of != for better safety 5daaaf640 guru: scope is not needed for describe mode (#1596) 07af1c520 doc: make godoc instance configurable bbe47d165 Revert "Use :sbuffer in :GoAlternate" (#1595) b870a052c Merge pull request #1592 from bhcleek/fix-vim-vint f63ac32c4 fix vim-vint installation c923e2927 update CHANGELOG.md for #1585 feee7fa82 Merge pull request #1585 from Carpetsmoker/test-alternate 8554d229a show compiler errors when :GoTest fails (#1588) 48ecb61af Use :sbuffer in :GoAlternate ccf98e095 Update CHANGELOG 974b2896c Remove g:go_autodetect_gopath (#1525) a9bf3cbaa Some small test running improvements (#1584) 6318e1aa0 Sync syntax from start after gofmt (#1582) c191a672e Fix :GoImpl completion (#1581) 432dc7f7f prepend test name to test errors (#1578) e2559cb3f update CHANGELOG.md (#1577) ca8ef8a9f Merge pull request #1513 from bhcleek/fix-test-error-processing 57ac640df improve test output handling 456186fd0 update CHANGELOG.md (#1573) bcd555d47 Merge pull request #1527 from bhcleek/fix-fugitive-errors a50c83146 Add test and fix Exec() call 4fe11eacf eliminate errors when trying to run a command in a directory that does not exist ebbc5b34d Add some VimScript lint tools (#1558) a81c1bd52 Merge pull request #1565 from bhcleek/changelog/1562-1563 e581f3f01 typo (#1569) c6ea0c1fe update CHANGELOG.md for #1562 c0d209cce Merge pull request #1562 from washtubs/master d79dd9cbe update CHANGELOG.md for #1563 90384c0ca Merge pull request #1563 from horgh/horgh/run-gometalinter-on-tests 770164ab2 Add --tests only when using the default gometalinter command 70ecda391 Pass --tests flag to gometalinter so that we lint test files d05d93a7e Make :GoTestCompile respect build tags ba6ce99a6 Expand test framework (#1548) bd35a4ec2 Add scripts/docker-test (#1550) 3eefef0b1 Merge pull request #1553 from wuzangsama/master 8ee54fa96 comment out err modeline d735fc9fc Merge pull request #1551 from bhcleek/docker-image-install-vim ee377102d run scripts directly instead of via make in Dockerfile 95584e32d install vim in the Docker image d27a937a3 Ask for "go env" (#1547) 7efc3fe06 Better testing (#1476) 40e02891d Fix UltiSnips gpl snippet (#1535) 44e7173aa add modeline to CHANGELOG.md (#1546) 4409db9b2 Merge pull request #1540 from bhcleek/changelog/1538 06ba514d0 update CHANGELOG.md 5a3a2319a Merge pull request #1538 from 'tmatias:toggle_same_ids_check_group' ee76970c5 improve go#guru#ClearSameIds readability d3832a4e1 check group in when toggling same ids 087899210 Display warning when people use an older Vim (#1524) cc93090b0 Add .editorconfig (#1523) b28351fdd Merge pull request #1528 from bhcleek/add-modelines 4a8e342e8 Merge pull request #1529 from fatih/fix-go-play 219b9a12c tool: fix :GoPlay by using the correct IsMac() function 448a95767 add missing modelines 51dbbc412 Merge pull request #1461 from bhcleek/gopath-autodetect-default 2e6b84757 disable g:go_autodetect_gopath by default faf628814 Merge pull request #1521 from bhcleek/changelog-1519 544c894c3 update changelog 0643e9ecc Merge pull request #1519 from bhcleek/fix-go-test-compile b2ffdaa8e do not try to run tests for :GoTestCompile 011dcadc0 normalize message output (#1512) f6196ad98 Update ChangeLog 112ea9090 Merge pull request #1465 from Carpetsmoker/rename-complete 57d60ff05 Also clarify docs a bit d3a07e2c3 Address PR feedback 172139cab Better prefill and completion for :GoRename 2f838940e Clarify documentation for g:go_play_browser_command (#1495) bd5bd982d edit issue template (#1502) f61f97fbb edit help file and function description (#1503) da4a86afa Update CHANGELOG 6ba5992fc Turnoff window resize if its still visible (#1488) 8ccaa5134 edit documentation (#1504) 863008a33 Fix util echo function: ensure l:msg is a list after split() (#1498) 96995056c Merge pull request #1492 from fatih/new-release 010d0cc59 New release: v1.15 4d518eef8 Merge pull request #1491 from fatih/update-changelog a0a528a0f Update CHANGELOG.md e3725d45a Merge pull request #1474 from bhcleek/close-gofmt-list-vim7.4 be4133a0b Merge pull request #1485 from cassiobotaro/master 1c1980fd6 ensure fmt list gets closed when title cannot be checked 7cb6d701c Fix #1484 GoDecls break when motion returns empty dcd3e3bfb Don't use `v:t_list`. (#1479) 54150c199 Fix GoInstallBinaries error message (#1478) 8914c7e39 Allow arguments for :Go{Install,Update}Binaries (#1467) 2a9c03edd Clarify the documentation for the guru scope. (#1466) ff2936872 Add go#util#Exec() (#1471) 620717490 Documentation for syntax highlighting (#1469) 78b7db128 Support fzf on GoDecls[Dir] (#1437) 458d23085 Merge pull request #1463 from bhcleek/better-assignment-highlight 09911f93f update CHANGELOG.md (#1451) 8fe9a2425 reduce goVarAssignment regex branches 40bdb6ab0 Implement :GoFillStruct (#1443) 0371da68c Show multiline errors (#1456) 40bf77e5f teach goVarAssign about all assignment operators 5e4ed05df Merge pull request #1460 from bhcleek/update-change-log-higlight-assignment 7a3316f59 update changelog 7a7af87f8 Merge pull request #1458 from xlucas/master 7fbccd9da Variable assignments syntax highlight 1e7560e0e Merge pull request #1453 from Carpetsmoker/fix-list-type-commands 6ce489126 Fix string comparison 2b2ffcdde Fix syntax for `s:default_list_type_commands` 2162c2fa1 Fix :GoBuild shell escaping (#1450) 5730b71ea Merge pull request #1449 from bhcleek/consolidate-list-type-command-keys b319ed975 Load ftplugin/html.vim for gohtmltmpl (#1442) 2b3610ff5 fix arguments to jobcontrol#s:spawn (#1448) 0ff17516c change GoModifyTags default list type ce9e0fcd8 refactor for maintainability 262fb6308 doc: add example for go_list_type_commands 6b7bab65a Update CHANGELOG.md df60f2652 support for customizable lists types (#1415) dfc89933c Update CHANGELOG.md eac41c98a Merge pull request #1439 from guns/fix-async-guru-data-race 17c03852f Parse messages from guru on close_cb, not exit_cb b71f2b757 Fix ChangeLog links (#1436) 5f0c5941b Fix go#package#FromPath() (#1435) 2d36a7882 Merge pull request #1434 from fatih/remove-brackets a5cdeb59d CHANGELOG.md: fix GH links syntax e287f9b83 Merge pull request #1433 from fatih/fix-issue-links 5ecd7966f CHANGELOG.md: fix markdown syntax to link to GH issues/pr's b88a5c989 Proof read documentation: "Intro", "Install", and README (#1432) f71d6e70a Update CHANGELOG 75d0e9f7a GoImpl: support relative (vendor) imports (#1322) 37e5082d4 Add support for unite.vim for :GoDecls / :GoDeclsDir (#1391) 54bcb5bfa Fix g:go_fold_enable, 'comment' value aa526f0fb Update CHANGELOG 9cce36bd8 Allow folding any comment (#1428) 0be825dd4 Vim syntax match for variable definitions (#1426) 5db7dd6a6 Load buffers with :GoDef relative to cwd (#1277) 506ddafc2 Add support of g:go_doc_command option (#1420) 67a3e972a Show output of vimhelplint failures (#1430) ea3346620 Remove accidentally committed file; update CHANGELOG 55a54f149 Merge branch 'pr-1414' 63c76f919 Update CHANGELOG.md b0ae2c584 Merge pull request #1386 from Carpetsmoker/goimpl 6d15159e8 Update CHANGELOG.md 18eba1a08 Merge pull request #1411 from kirstein/master cdd056ff8 Merge pull request #1377 from Carpetsmoker/fold-pkgcmt 8ba55ec3c Update Changelog.md fb2763465 Merge pull request #1422 from jasonkeene/ginkgo-faq 79f451448 Some small :GoImpl improvements 125d5caf3 Fold package-level comments c420b47cd Add FAQ entry for how to run focused ginkgo tests 117c33413 update comment b5271d098 Fix to fails of GoMetalinter result filepath in subdir. resolve #1413 79152447b term: exit insert mode 52c5b1f74 fmt: fix backwards compatibility with getqflist df99b193e Update CHANGELOG.md 9a433e5db Merge pull request #1407 from fatih/fix-autoclose-gofmt a9ad6b3f0 fmt.vim: only close quickfix if its belongs to gofmt dfd860471 Add initial commit 8eef8ea57 Add all release information to changelog 4fd3a60da Add old changelog (v1.3) 5939bdd8f Add old changelog (v1.4) 9391a575a Add old changelog (v1.5) 30d036a02 Update CHANGELOG.md ba09b8fef Merge pull request #1401 from fatih/gomodifytags-improvements e655a39ba Update CHANGELOG.md a0ecfabad Merge pull request #1400 from cfsalguero/issue-1396 386e81004 tags: use -modified flag and show errors 525fe8af9 Update CHANGELOG.md e8e49eac5 Merge pull request #1387 from Carpetsmoker/import-comments cf15171af Add demo link to syntax based folding 25d00acf3 New release: v1.14 5d5c96665 Updaste Changelog.md c9052d527 def: only show filename to prevent showing long paths 250c6397c Merge pull request #1385 from Carpetsmoker/godef-msg 78a87d866 Merge pull request #1384 from Carpetsmoker/fold-var 9c292d9ee Update CHANGELOG.md 9c49d42a0 Merge pull request #1394 from mikelue/master 239cbec81 Update CHANGELOG.md 6a470dac4 Update CHANGELOG.md ebdcf3ad9 Merge pull request #1382 from Carpetsmoker/lint d758e7f52 Update CHANGELOG.md 13b9eb578 Merge pull request #1381 from Carpetsmoker/vet 805334818 Document how to use a different Go binary (#1373) d4f931d7e Merge pull request #1395 from deltaskelta/doc-typo-fix e8cf579db Issue 1396 go#def#tab fails if file is already open 60db0a282 Typo fix c16c29a8a Complement the path of command for different situations of Cygwin environment ec6500bb4 Allow comments in import blocks 436bfd58f Show message when using :GoDef and opening a new buffer a683b6a38 Fixes for folding var/const blocks 2d91dbdcf Run :GoLint against the package of the open file f439c0cb5 Fix filepaths in the quickfix list for :GoVet 76cd99db6 Merge pull request #1356 from antoineco/master 8de2e7df9 Clarify :helpt prerequisite for using :help vim-go a35c51f3e Update CHANGELOG.md 68c70160f Merge pull request #1371 from Carpetsmoker/new-file 0da59fe21 Update CHANGELOG.md 629cd6d42 Merge pull request #1372 from Carpetsmoker/gofiles-types 3ba1fefa0 Update CHANGELOG.md 307180cd7 Merge pull request #1374 from Carpetsmoker/spaces 82f7e25c5 Update CHANGELOG.md 64bdf041f Merge pull request #1379 from Carpetsmoker/missing-gogetdoc 026728c51 Merge pull request #1378 from clee/fix-contributing-link 64bd8ddd3 Don't show window if "gogetdoc" command isn't found f8ce5e051 Fix link in CONTRIBUTING.md 6be1c2175 Preserve cursor column through formatting (#1369) 857eaa5b9 Fix various commands when GOPATH contains spaces. 702b1a490 Make :GoDef work if a file path contains spaces 3b7b37626 Allow specifying which filestypes to list for :GoFiles bd6c4562b Show correct message when editing a new file 2d89f0052 Merge pull request #1368 from anarchyrucks/patch-1 f95eb84f6 Fix typo 1575dcab2 Update CHANGELOG.md d5f55053f Fold import, var, and const blocks (#1339) 3b6270e06 Update CHANGELOG.md ab0df08ca Merge pull request #1367 from fatih/improve-cursor-replacement-fmt 838492059 fmt.vim: fix cursor staying on the same line when goimports is used ca1d7127b Update CHANGELOG.md e0e8032a7 Merge pull request #1366 from fatih/fix-multiple-src 02c5d8a57 path: fix autp detecting of GOPATH for import paths with string 'src' d98b80ecf Update CHANGELOG.md cc28ff699 Merge pull request #1365 from fatih/fix-gofmt-list e4e992a1c fmt.vim: default to quickfix list for showing errors d5979c91e Merge pull request #1364 from Carpetsmoker/hl-type dd6e15468 Don't add offset to goTypeConstructor. 82998ea2f Update CHANGELOG.md 872bef43d Merge pull request #1363 from fatih/fix-array-index 6d8b86ed9 path: fix gobin path for go => 1.7 bfcf8b057 Update CHANGELOG.md e56673862 Merge pull request #1361 from seanpile/keep_list_open 4e3f55be7 Update CHANGELOG.md b54de478e Merge pull request #1362 from fatih/fix-swap-file fd44242d5 fmt: fix blocking ui when swapfile is enabled 06987d569 Added ability to keep the quickfix/location list window open after successful operations instead of autoclosing 58bfea76b Update CHANGELOG.md 8b02779ba Merge pull request #1345 from fatih/include-func-variable 789ffb460 textobj: include function variable for anonymous functions f08fcab5c Update CHANGELOG.md 657d0937f Merge pull request #1338 from Carpetsmoker/fix-1282 2647e9bda Merge pull request #1340 from Carpetsmoker/vimhelplint 971f3071f Update CHANGELOG.md acd0be01a Merge pull request #1344 from robot-dreams/patch-1 1a946d9be Fix warning when goimports doesn't support srcdir 55ba44a57 Fix doc lint error f7df583a0 Add vimhelplint to Travis tests cfa9713eb Match zero-width in goTypeConstructor bcf3f23dd Update CHANGELOG.md 0a8af0caa Update CHANGELOG.md 4787f2762 Merge pull request #1335 from Carpetsmoker/go_doc_max_height 290887538 Update CHANGELOG.md 4fd118269 coverage.vim: add echo message for GoCoverage 837143b72 Merge pull request #1336 from rhysd/fix-typo 841457035 fix typos in docs, changelog and sources 2eb88b70a Add g:go_doc_max_height setting 3806c4e59 Update Changelog.md 2df21ebaf Merge pull request #1330 from fatih/go-build-cache e1c0d7b0b cmd: add -i flag to go build 182a9dd14 Add a note about the recent test refactor 7b93bae4b commands: expose :GoDecls{Dir} command to show a warning 147360e9a Update Changelog.md 91b159a7e Merge pull request #1326 from tmc/coverage-args f5898d3c8 Create CHANGELOG.md aefc0a2a0 Merge pull request #1327 from fatih/fix-echo-output-tesst 21cfbbc0d test: fix outputing message when test finishes b9bef683b coverage.vim: pass along arguments to coverage_job fec6321d2 Update CHANGELOG.md d75e17546 Fix syntastic help (#1323) 4f2bdd61a Update Changelog.md bf9cdc211 Update Changelog.md 913c181b8 Merge pull request #1321 from fatih/improve-import-path 15d3b3c86 package: improve import_path by using go list 61b897f14 Update CHANGELOG.md bc097c164 Merge pull request #1320 from fatih/cache-env-calls 52e5ad5cf Update CHANGELOG.md e2be1fa7e Update CHANGELOG.md a4b64e28e Merge pull request #1318 from bhcleek/feature-test-template f4be8f612 Use a different template for test files 4f04d680e New release: v1.13 b0a11f016 Improve caching for go env calls d2e1e1764 Update CHANGELOG.md 404dca66d Merge pull request #1319 from fatih/fix-def-tags 150b2cc05 def: fix passing build tags to guru 16e0ccf28 Update CHANGELOG.md 196792d20 Merge pull request #1317 from fatih/test-compile 21376e689 test.vim: more efficient compiling of test files 7fafcb14f fix coverage to use new test.vim file 9b3aa3f2d Update CHANGELOG.md 161bc4632 Merge pull request #1316 from fatih/fix-test-coloni 8f0029172 test.vim: fix messages with colons 57aaa95ac Merge pull request #1315 from fatih/standalone-test-parsing d2ff39ca7 test.vim: refactor to use its own parse function 76044c0c5 Merge pull request #1314 from fatih/refactor-parsing 8f9699486 Refactor all test related commands into test.vim 899b741f2 Merge pull request #1311 from tgrosinger/typo-fix 57e062a27 docs: fix typo in command 476239117 Update Changelog.md 60565da2d goimports fails when proj symlinked in GOPATH (#1310) aec329223 Update Changelog.md 0325c5e04 Specifies the type of list to use in GoMetaLinter, by go_list_type (#1309) aab6381ea Update Changelog.md 016c03c99 path: do not use a dedicated function for cygwin 3f5dd0a5a Add path convertion for native-win-vim with Cygwin support (#1092) 0235a8f85 Update Changelog.md 66b04e85d Merge pull request #1308 from fatih/improve-fmt-commands e6533efc8 fmt: change go_fmt_options's type to dict 00ab89e4d Update CHANGELOG.md b8a6dc963 Merge pull request #1296 from fatih/term-neovim-fix ff3c10ec4 Update CHANGELOG.md e63e16602 Merge pull request #1304 from fatih/add-listtype-support e3760a58d fmt: add support of 'go_list_type' for :GoFmt and :GoImports 8efd1dd73 Update CHANGELOG.md 66e3d342f Merge pull request #1301 from zkry/highlight-interface-struct-fix f8863b067 Fix the highlighting error by putting the interface\|struct section inside \( \) to correctly identify word boundries 403b9bb29 Merge pull request #1300 from robphoenix/master 276e7abc2 fix single spelling error in vim-go.txt 7b311be14 Update CHANGELOG.md 162e26369 do not jump to the quickfix window when gometalinter is executed (#1293) 1cc18529e Merge pull request #1299 from fatih/fix-tags-settings 07e055236 addtags: unify settings for case setting c1ae945f6 util: remove nonused go#util#AddTags function 4fda59601 term: fix cwd after running command 05efdfe80 Update CHANGELOG.md 2e1979847 Merge pull request #1295 from etdub/master fd7d4d40d Change GoLint command to lint the current directory instead of the current file (issue #1263) 7fb96896f Update CHANGELOG.md 26e61829c Merge pull request #1280 from fatih/fix-autodetect-gopath c609352bb path: return the unmodified GOPATH if autodetect is disabled 6f392c454 Update CONTRIBUTING.md 1143f398e Merge pull request #1279 from fatih/update-docs 8b7d743e5 docs: add new :GoDef mouse mappings 1c6ccb1f2 Update CHANGELOG.md eb739e185 Merge pull request #1264 from lilydjwg/master 4cdb20ca5 Update CHANGELOG.md f6554604f Add :GoAddTags transform (#1275) 8532385af Update CHANGELOG.md 8e0ddef60 Merge pull request #1276 from creaky/master d92a4f6f0 Updated code based on feedback and further analysis 27228dada Merge pull request #1278 from dorons/master 872e4e190 Fixed indent for 'ife' snippet b57ee9088 Update CHANGELOG.md 1a7887e32 Include keyify support (#1258) e9bb5eaa4 Fixed issue Vim-Go broken on freebsd #1224 aab745ece Update CHANGELOG.md cdffa16f5 Merge pull request #1268 from Foxboron/patch-1 f1c6f6649 Include if with inline error handling 78c2a9a0b support <C-LeftMouse> as well b4936d89b Update README.md ae5e0d887 Merge pull request #1255 from fatih/readme-improvement 580103e67 Simplify Readme.md 08d0c34d0 Update changelog.md c71c75e4c Merge pull request #1247 from pborzenkov/close-race 48e0660e2 Update Changelog and add docs for new gometalinter feature 18a5dad3c Merge pull request #1253 from redforks/master 882a1932e Add go_metalinter_excludes config variable 55906b13d Merge pull request #1250 from bradleyfalzon/patch-1 f16e5d9fe Minor typo in change log 26362e4bf New release: v1.12 c20e192ea Update CHANGELOG.md 7871cd94b Update CHANGELOG.md 727aed364 Merge pull request #1248 from fatih/default-gopath 6db12a966 Go 1.8 compatible GOPATH improvements 5c721a278 job: fix race between channel close and job exit 411981189 Update CHANGELOG.md b14621829 Merge pull request #1246 from fatih/fix-install-arg 58adebd7a cmd: we don't need to shellescape for jobs e0a7b12e1 Update CHANGELOG.md 5d684f6da Merge pull request #1235 from thsnr/master 58853d520 Update CHANGELOG.md a83c4c0bc Merge pull request #1242 from danielheller/godef-help-explicit-arguments cec0fc361 Update GoDef help: remove explicit arguments 1aa048b2d Allow trimming around comments in gotexttmpl syntax. 362e15ab4 Merge pull request #1233 from rigelrozanski/patch-1 8cb66af59 Updated Broken Link eb8adf52b Tidy up and fix typos 091a8c1f9 Update CHANGELOG.md 0586539e0 Add :GoBuildTags to set build tags (#1232) cf3aad953 Update CHANGELOG.md 03fc6a710 Add build tags support for gorename (#1225) b9c815626 Update CHANGELOG.md 71efb2e6d Set GOPATH for both possible go guru execution paths (#1193) 7ff6d8e06 Update CHANGELOG.md 92d0d07a6 Merge pull request #1195 from haleyrc/master 70aba7c27 Update CHANGELOG.md ac2f89b41 Merge pull request #1197 from jhillyerd/noshowdoc 7149f3eec Update CHANGELOG.md 468fa9823 Merge pull request #1199 from tarrant/master 9a9f010ec Update CHANGELOG.md 2fc67cd72 Merge pull request #1211 from cespare/goimports-options ded4d3169 Respect go_fmt_options when running goimports 4490a1f67 Fix whitespace and typo (#1201) 68f398b3b Update CHANGELOG.md a8a253bb8 Update CHANGELOG.md e4e5e2267 Merge pull request #1204 from fatih/gotags eca86e03f New GoTags improvements d3f90c21e Set the filename in the location-list d5d826a69 Document 'noshowmode' requirement for echo_go_info 884870e88 Modify the resize behavior for godoc 1425decf6 Update CHANGELOG.md fc1ab4052 Merge pull request #1194 from jblebrun/no-gopath-env-fix a4edbfc8e Ensure no trailing : in gopath 9b0362562 Update CHANGELOG.md 119eec1b3 Merge pull request #1177 from francescomari/guru-tags 0dacf2917 Update CHANGELOG.md 86834ce79 Merge pull request #1184 from mattn/non-utf8 9cb5965f5 Update CHANGELOG.md 6e832e6c0 Merge pull request #1185 from mattn/errl f6ad41d15 Update CHANGELOG.md a8592baf7 Merge pull request #1192 from vieiralucas/patch-1 375ce716c Update CHANGELOG.md 3c5f09de5 Merge pull request #1176 from joshuarubin/neovim_go_build_fixes d7860c34d Lowercase <Leader> in mappings examples c29fac849 log.Fatal(err) is useful ddf3ad471 Support 'encoding != utf-8' 3e8551253 Correctly report the value of the 'g:go_guru_tags' variable 83296ac0b fix :GoBuild issues in neovim 3eb57ac3a New release: v1.11 07dabeb11 Update CHANGELOG.md 001cce799 Merge pull request #1174 from zmb3/zb-godoc-browser e3a760fd9 Fix :GoDocBrowser for third party package doc. ba08326b2 Update CHANGELOG.md 41f5fd135 Merge pull request #1146 from horgh/master 7635fc0eb Update CHANGELOG.md f9391628d Merge pull request #1152 from ismail/ismail-patch-1 8775ba7f5 Merge pull request #1168 from fatih/fix-docs e3e9fef6a Update CHANGELOG.md fba058f98 Merge pull request #1167 from fatih/disable-highlight 16ffe5d88 docs: fix unused feature 0a3b205c8 syntax: switch options to off 47447feea Update CHANGELOG.md 283fe500e Merge pull request #1160 from thsnr/master 10af7bc2a Use go_metalinter_command as List after split(). d7c628ff2 Merge pull request #1159 from fatih/godef-tests e27a00365 tests: add def_test.vim a9bc540b0 Update readme.md 73f707d46 Merge pull request #1158 from fatih/improve_tests b586c7e4f tests: add new test, update runttest.vim b27031ab0 Update CHANGELOG.md bd6e33ed4 Merge pull request #1157 from fatih/vim-go-tests 145893132 Add travis integration and initial test suite 7d3e4bc8b Merge pull request #1156 from bhcleek/fix-sameids-BufWinEnter ffe8fc402 clear buffer-local BufWinEnter properly fa7dc2eaa Update CHANGELOG.md edcd9c813 Merge pull request #1155 from bhcleek/fix-guru-async 7eeb2f87e use funcref() instead of function() for closures used as callbacks 407dcda3f If GOPATH is empty check for the value of go env GOPATH 95be72ddd go_metalinter_deadline applies in async mode now e46dd4dde Update CHANGELOG.md 708861202 Merge pull request #1133 from bhcleek/fix-godef-stack-pop 66c72b4ad def: indent d5abc9d80 Update CHANGELOG.md 054951253 Merge pull request #1132 from bhcleek/fix-godef-split 57e19fa7a Update CHANGELOG.md 398680c1f job: set explicit bang to avoid errors in case it's being used cd793b75a Update CHANGELOG.md 9f9b93767 Merge pull request #1124 from jimmyfrasche/master ca4b4437b Update CHANGELOG.md 86adc49b1 Merge pull request #1136 from jdhenke/master 0eaa355a7 Update CHANGELOG.md 8e44afc0f Merge pull request #1145 from entombedvirus/fix_jobcontrol_on_exit_err 709a4585e Update CHANGELOG.md e15c781d1 Merge pull request #1143 from kechako/fix-indentation-broken 69e2b2c66 Update CHANGELOG.md 7cde15acd Merge pull request #1141 from oystedal/oystedal/1140 39ebca3a1 fixes #1144: "E118: Too many arguments for function: <SNR>173_on_exit" d1f5dd3bd Update README.md a55c85338 Fix indentation broken when using a action with a minus sign like `{{-' d3c9fc07b Change default value of `g:go_asmfmt_autosave` to 0. 93984b340 fix bug in guru vim script 08c881dea Changelog.md: add requirement 66ce0c0d3 make requested changes to documentation and setting name 6bf649098 Merge pull request #1135 from fatih/fix-setloclist edacc3687 list: set title only for recent Vim versions 6094a38b2 allow popping from jump list when buffer is modified 973ba8c29 handle :GoDef from modified buffer 4a993be12 Update CHANGELOG.md 309c94fbe Merge pull request #1128 from fatih/fix-coverage-syntax 10a8ddcda coverage: no need to change turn on/off syntax eeae7b0bf Update CHANGELOG.md b882d1fa7 Merge pull request #1127 from fatih/fix-coverage 4aee04ff7 cmd: do not expand coverage arguments 6ee972ddd Update ISSUE_TEMPLATE.md d277006b4 Update CHANGELOG.md 01ec25cae Provide a descriptive quickfix/location list title. (#1004) 9e88616c2 Add option to use cwd as package name instead of template 96a07bd88 Update CHANGELOG.md cb88925a4 Merge pull request #1123 from pborzenkov/job-ccl 40344d43b job: close quickfix window if a job has succeeded c07e9e0a3 Update CHANGELOG.md 1a9f0ee2e Merge pull request #1122 from fatih/patch-echom-fix dd2a13642 path: use echom so it's showed when used completion 4944f0ef8 Update Changelog.md f60e4fd42 Merge pull request #1121 from pborzenkov/statusbar-update 5265ad2da Update CHANGELOG.md 7785d369c Merge pull request #1055 from svanharmelen/f-setlocal-updatetime 0996bdacb Add `g:go_updatetime` to configure a custom `updatetime` 79fa535b1 Always use full path as statusline target directory bf2110457 Update CHANGELOG.md b4adab50e Merge pull request #1120 from fatih/gometalinter-statusline c27297286 lint: add statusline support for GoMetaLinter d07982689 Update CHANGELOG.md dcbedd7b8 New release: v1.10 824f44ab8 Merge branch 'master' of https://github.com/fatih/vim-go 8df04a986 New release: v1.10 f3ee8cd5c Update CHANGELOG.md c0b180a52 Update CHANGELOG.md d9194b7d1 Update CHANGELOG.md c44f799be Merge pull request #1089 from tdilo/add-golint-plug-mapping 0b6d16c57 Merge pull request #1119 from fatih/goinfo-improvements 05f7fb837 info: add option to change underlying tool for :GoInfo cb8329a2b Update CHANGELOG.md b84f01ae9 Merge pull request #1033 from pborzenkov/coverage 2b34076d0 coverage: allow to run coverage on _test.go files in subdirs 7c27c6be9 Merge pull request #1118 from fatih/fix-wall d35e866a8 cmd: wall tries to write to unnamed buffer, neglect errors 3b6da4942 Merge pull request #1117 from fatih/test-func-fix 303c0a2bc cmd: fix :GoTestFunc for job API d3c4fb3d2 Merge branch 'master' of https://github.com/fatih/vim-go 505e726e2 Update README.md 75b6713bc Merge pull request #1114 from fatih/check-job 86c7e12f5 vim: require at least 8.0.0087 for +job features c212e28fa guru: do not use abort, is not compatible with old Vim versions b2ecbf8c0 Merge pull request #1110 from fatih/fix-new-variables b82060212 go: do not use new type variables 59c56f090 Merge pull request #1104 from fatih/vim-8.0-squash dc8073386 Add vim-8.0 support 362decf1a complete: disable unimported support 303667f4f Update CHANGELOG.md e198faaa7 Merge pull request #1100 from Alok/add-abort 37f828315 Update CHANGELOG.md de782e8ac Merge pull request #1101 from haya14busa/option-go_echo_type_info ec9f4ac3f Merge pull request #1102 from stamm/patch-1 26d766a27 typos in changelog 298520ce1 add an option to show type info when completion is done a822b9792 Add abort to every autoload function d85444b32 lint: add (go-lint) plug mapping 10c805b83 Update CHANGELOG.md fcd04ce1f Merge pull request #954 from fatih/fix-gocode-goroot 23c0cb00c Update CHANGELOG.md 42bc216cc Merge pull request #1067 from bhcleek/fix-sameids-change-buffer 0b631151f Update CHANGELOG.md be4eae0ba Merge pull request #1070 from svanharmelen/f-highlight-func-calls 64021135f Update CHANGELOG.md b76d55f52 Merge pull request #1075 from magicalbanana/allow-nested-struct-highlighting 936837ec0 Update CHANGELOG.md 8b73c3f71 Merge pull request #1084 from zmb3/unimported-packages 54b2650c4 Provide completions for unimported packages. 7461762f7 Update CHANGELOG.md 127ecfedd Merge pull request #1083 from fatih/fix-jumping-to-split-modified 54fa4679a def: do not open a split for modified file 80b0ca2d1 Make sure builtins are hightlighted correctly 31c13f672 Syntax nested structs 1f8e10ceb Merge pull request #1072 from hitjim/patch-1 f41f55323 Update license to credit Renee French for Gopher 8faedbebf Update CHANGELOG.md 977b68d22 Merge pull request #1048 from svanharmelen/f-highlight-func-calls a09d179d8 Clear most recent goSameId highlights groups bae1529cd util: add go#util#env function 6ca257751 Update CHANGELOG.md 32f9d2bf5 Merge pull request #1062 from lukatendai/master acab9b3f6 Update cmd.vim 2b19e6c18 Merge pull request #1047 from abhinav/patch-1 4bf1d139f skip go#util#Shelllist if nvim is being used 09522e50c Update CHANGELOG.md fc4f5a432 Merge pull request #1061 from egonelbre/master 4e3628042 Use transparent background for image. fecb68867 Update CHANGELOG.md 5fda1883f Merge pull request #1060 from fatih/assets 38ff97edc Add vim-go logo /cc @egonelbre d6c1ec9a4 Add assets dir with new logo from @egonelbre 8205e3542 Merge pull request #1052 from mattn/sock_type 86b1e7aa2 fix default sock type 961466fb2 Add support for highlighting function calls 7fd92a842 Update CHANGELOG.md ac4a9757d Merge pull request #1049 from nhooyr/syntax-fix 451f8a0da goPredefinedIdentifiers should link to goBoolean by default b14be232b Fix reference to go_highlight_{structs,interface} d9fa1bcca New release: v1.9 b52601889 Update CHANGELOG.md 417fd0ca7 Merge pull request #1046 from mattn/v8.0 168c4a4b3 better to use exists('*exepath') 8575d9e3c Fix bug in syntax highlighting (#1035) 0a25a0ddd Update CHANGELOG.md 8d6356616 Exclude iota and nil from goBoolean (#1030) c63c798f7 Update CHANGELOG.md a5222bfdc fmt: print full goimports path if it's not compatible 2aad0a8a6 Update CHANGELOG.md 495cf403c Merge pull request #1007 from magicalbanana/highlight-field-field 990916af8 Update CHANGELOG.md 1f143f3dc Merge pull request #1020 from kaneshin/patch-1 5b53a72bb Update CHANGELOG.md d5ac28c35 Merge pull request #1011 from ArkBriar/master 804130fc9 Update CHANGELOG.md 8de252ae9 allow :GoDoc on modified buffers (#1014) 9380cc445 Update CHANGELOG.md 31ea0aaf7 Merge pull request #1017 from fd0/add-hint-updatetime b76f8f501 Update CHANGELOG.md cbe7d101b Merge pull request #1029 from nhooyr/master 5d4fcaa47 Update CHANGELOG.md 0a66df41d Merge pull request #1023 from yyoshiki41/update/doc 4b9258e8a update jumplist in :GoDef c306de904 Add go_highlight_generate_tags in docs 313127ee4 Rename GoMetalinterAutoSaveToggle to GoMetaLinterAutoSaveToggle 63bdcdf65 Update CHANGELOG.md f1f6e71a3 Merge pull request #1016 from kisielk/patch-1 241818330 SameIds: Fix Sentence, add hint to 'updatetime' 41dfa207b set updatetime if g:go_auto_sameids is enabled d72ed3ab5 Fix syntax goFormatSpecifier: check '%%' 359a8c5ca Highlight nested fields or chained fields a4ba0a5b1 Update CHANGELOG.md 973724f6e Merge pull request #998 from bhcleek/sameid-autocmd a0edd32f7 Update CHANGELOG.md 4c2069649 Merge pull request #999 from umitkablan/master 2514a4221 Update CHANGELOG.md 67084f500 Merge pull request #1000 from fatih/add-gocode-socket-type d9c531fca complete: add g:go_gocode_socket_type setting a6e097cb9 Fixed Windows tagbar&GoCallers errors with g:go#use_vimproc=0. 7d1433761 Re-evaluate sameids after buffer is re-entered a0d769dd9 Update CHANGELOG.md e7f5e5756 Update CHANGELOG.md 37b95186a Fix :GoSameIds for light background, GUI, and after changing colour schemes (#983) ecac6556a util: do not clear the screen 99d5bf8e0 Update CHANGELOG.md 445e5bf10 use guru's -modified flag (#944) af2798046 Update CHANGELOG.md 49f4e2a34 Doc cleanup (#987) 7bcf1f554 Update CHANGELOG.md 011d76fbd Merge pull request #988 from Carpetsmoker/windows-shell 2dfd933c5 Use go#util#IsWin 53261bc0a More robust resetting of the shell. 3030ecc86 New release: v1.8 12b3f65a0 Update CHANGELOG.md 4f06fda92 Merge pull request #971 from fatih/gooaddtags 6e0d6c363 commands: add :GoAddTags 13affe57d fixed goField regexp (#981) 51930f327 Update CHANGELOG.md 7af695b1b add commands to toggle settings that control auto behavior (#945) 55fe1705d Escape all template path special characters (#966) d3fb314ea Update CHANGELOG.md 881a9cc0f Reset shell before running a command in go#util#System (#967) 9ed023b39 Merge pull request #972 from roxma/master b329b1c10 Merge pull request #974 from bhcleek/sameid-warning 6adfed303 Update CHANGELOG.md 4a403b6e3 Merge pull request #980 from fatih/fixes-from-wladh 7e30f82b5 Add guifg to go coverage syntax. 4c8a7046e Make GoInstall use detected $GOPATH 85a9d62e4 Merge pull request #979 from datanoise/master 59f38f020 link goPointerOperator and goVarArgs to goOperator. 5e36218d0 goVarArgs highlight groups is too gready. 7689ab482 add warning to GoSameIds when matchaddpos is unavailable bc2746c1e add SimpleAutoComplPop to the list 59a236108 Merge pull request #969 from vrischmann/master 62d6026b9 tool: use double quotes in PackageName for Windows compatibility 69e038e5c Update CHANGELOG.md a4c9c4e44 Merge pull request #968 from fatih/idawes-master d24cd35a1 doc: add more context 844cf27ca Consisten mappings and commands e272cf309 Merge branch 'auto-toggle' into idawes-master 271766d76 Merge branch 'master' of https://github.com/idawes/vim-go into idawes-master e977689a3 guru: add GoSameidsAutoToggle c8cf79257 Merge pull request #946 from bhcleek/buffer-sameids b7ac76ad7 Update CHANGELOG.md 1e7d0480a Merge pull request #962 from fatih/separate-coverage-syntax e648b71f6 syntax: add goCoverage specific highlights c3cd94941 Update README.md 368f72927 Update README.md 9754508b3 Merge pull request #958 from datanoise/master 7c096c20e go#fmt#Format fails on new unsaved files c5101afa6 Update CHANGELOG.md 4de469674 Merge pull request #957 from fatih/make-goimports-great-again 5fb42bd4e fmt: pass full name to -srcdir for upcoming new features 0faef8a43 refactor: use lowercase function names 2db19ffd2 Merge pull request #952 from magicalbanana/fix-setfperm d8eb1cdb7 Fixes the 'setfperm' issue 8ce50ff3e guru: make whicherrs usable for empty results 23abbac23 Update CHANGELOG.md 81bee4405 Merge pull request #948 from krishicks/guru-add-whicherrs 71aeea6d5 Merge pull request #949 from ArkBriar/master 1a38ce6c7 Merge pull request #942 from dobegor/patch-1 c38cb772d Update CHANGELOG.md 902f626c4 Merge pull request #922 from joegrasse/master 3a86d0f8a guru: add :GoWhicherrs 140a2ff75 Replace 'he=e-1' with '\ze' to avoid conflicts with other highlight plugins (e.g. luochen1990/rainbow). e53e6126f use CursorHold instead of CursorMove for go_auto_sameids 081f3423e Vim & Neovim now both support JSON 595df5118 Update CHANGELOG.md 684548da2 Merge pull request #937 from dangogh/yaml-tag 9fce7407a Merge pull request #939 from bhcleek/allow-disable-auto-features 96105a22a Merge pull request #938 from bhcleek/reduce-guru-what-flicker 94f579cdc Merge pull request #940 from bhcleek/customizable-goSameId-highlight 4801d2853 Add ToggleSameIds df02251e4 Neovim supports JSON, :GoSameIds now works. 3715a8908 allow goSameId highlight group to be overridden 30a6a2c6c allow auto features to be disabled without restarting Vim 7a312d97f reduce flicker when using go_auto_sameids 789de8e4e Update CHANGELOG.md 78a766756 Merge pull request #936 from fatih/bhcleek-master 41ae14a74 guru: improvements 6de8841f0 Add support to run Guru commands on umodified buffers 82ff2d872 add setting to automatically run :GoSameIds 16f3d7415 implement :GoSameIds f9549b752 add yaml tags completion 7fe846b1c Merge pull request #930 from datanoise/master ab01e7e5a Merge pull request #931 from svanburen/patch-1 7d1616ad4 Fix typo in docs 9816d691a small syntax fixes dede10f4a Update CHANGELOG.md 0b1fa09d9 Merge pull request #927 from fatih/json-snippet-case-type 153f2231e snippet: make json field tag expansion smarter 7876aaf55 snippets: make json snippet more smarter a049691f0 snippet: fix panic 01624ffc3 Update CHANGELOG.md 98d4f5eee Merge pull request #926 from fatih/add-snippet-err-panic cb442358b snippets: add errp for error panic 48d31eb2b Change setting name to something better and coherent with others 4778de4ae Update CHANGELOG.md d142f7db3 Merge pull request #918 from fatih/auto-create-template 23b7c2268 Fill the content of a new file automatically based on the context eb585ff6d Merge pull request #924 from tsne/fix-type-highlighting cd35ebdf5 fix highlight type keyword 2c5295871 Restore original files permissions 25bbb3135 Update CHANGELOG.md d3fb19d78 Merge pull request #920 from dobegor/master 498e709cf Fixed typo causing GoDocBrowser to fail 7c3414e5f Update CHANGELOG.md 50ceca52a Various improvements to syntax highlighting. (#917) ecfd5cff3 Update CHANGELOG.md 1a9cc7867 Merge pull request #915 from fatih/indentations-fixes 5a4abb592 style: use two spaces for all files a7a37517a Update CHANGELOG.md 1e9590dba Merge pull request #910 from fatih/def-modified-file 336e3b090 def: support modified files b12fd9bb5 Update CHANGELOG.md 9875a4690 Merge pull request #909 from fatih/fix-go-test-compile 1457e6e2c cmd: fix :GoTestCompile leaving behind artifacts 523d5a435 Update CHANGELOG.md 7b92adf89 Merge pull request #904 from fatih/fix-goimports-picking-srcdir 67489a688 fmt: fix goimports picking up -srcdir 6efcfb275 Update CHANGELOG.md 4f20c2524 Merge pull request #900 from fatih/fix-coverage-nvim f846d078e coverage: fix running coverage for neovim 76d295c19 Update CHANGELOG.md 478a23942 Merge pull request #897 from ryunix/fix-doc 1147bbc70 Update CHANGELOG.md a3452fdf2 Merge pull request #895 from mattn/fix-openbrowser 492e54bb2 Update CHANGELOG.md 8d73ed0bc Merge pull request #894 from mattn/godoc 85579cbd5 Fix doc 98fe1f95e escape # cf4f0ea1e open GodocView if argument is provided for :GoDoc 6a0c880df New Release: v1.7.1 0fd6f46e7 doc: fix wrong documentation about field and struct highlighting 8c9cbabfd Merge pull request #892 from ryunix/fix-typo ab62d6ddd Fix typo 191ba9a60 New release: v1.7 28e63a50b Update CHANGELOG.md 9b198271a Merge pull request #888 from fatih/go-def 10187323d def: add go_def_mode setting, we now support godef too 3c099cc66 cmd: check test files only for coverage 473c0bdfb Update CHANGELOG.md a284b6196 Merge pull request #854 from hhsnopek/hs.goField ae89f68f1 add goField 2f115dcf7 Update CHANGELOG.md e46c5efcd Merge pull request #883 from macb/get_update 04a0faae2 make go get -u configurable 211289683 Update CHANGELOG.md 28d6c0048 Increase compatibility with tcsh (#869) 684be5dfb Merge pull request #882 from yukidarake/fix-neosnippet-invalid-syntax 485d8ba3c Fix broken snippets c72fd199f Update CHANGELOG.md 99e06a043 cmd: fix showing SUCCESS for non tests b7147085c Revert wrong fix 8e0ea1266 cmd: run tests only if the test file exists e6a76161c cmd: fix runtime error for :GoCoverage acb2d8c91 docs: add docs for go-import and go-imports bc3726303 Update CHANGELOG.md 572617f16 Merge pull request #879 from fatih/do-not-create-test-binary be326e6a8 cmd: do not create test binary artifact for :GoTestCompile a9611d7d6 Properly use exepath for CheckBinPath (#864) b25dbfb23 Update CHANGELOG.md b74234bbd Merge pull request #878 from edganiukov/goimports-mapping 484ead33c added goimports mapping e9f44d933 fmt: use helper function to print warning 53c779f82 Update CHANGELOG.md 0a1f71faa Merge branch 'master' of https://github.com/fatih/vim-go 46da9d331 coverage: use color aliases for backwards compability 42c73c2a8 Update CHANGELOG.md 92632a024 def: quote the file argument completely for tcsh 8b1c0e93f Update CHANGELOG.md dc1496713 Merge pull request #862 from fatih/fix-lint-escape eb19cc520 textobj: escape files for motion as well c1e976135 Merge pull request #866 from trayo/master 76d43aca5 fixes typo d54819ddc Update CHANGELOG.md 5d5a5b228 Merge pull request #861 from DeepAnchor/master d909e2e41 lint: escape directory for shell invocation d570e89b4 Add non-standard workspaces to package path list 48cc65dfb Update CHANGELOG.md 8765cee38 Update CHANGELOG.md a3c0dab15 Merge pull request #856 from fatih/add-gocode-autobuild b0e00f631 complete: enable autobuild and propose-builtins 5c74881e0 Update CHANGELOG.md fea6ef317 Merge pull request #855 from fatih/fix-gorename 4311f5b18 rename: reload all files to reflect the new changes 1ec3373f2 Update CHANGELOG.md 96b0aa584 Merge pull request #847 from shawnps/patch-1 eb6ae9d1c use https in playground URL for GoPlay 1f2245335 impl: this is a better copy 5e589bba6 Update CHANGELOG.md 87a3bb954 impl: add vim-go-impl (#846) 1dfaae447 Added http to http handler snippet (#843) 78c56adc1 Update CHANGELOG.md 927e31ad2 add nnoremap <buffer> <silent> <C-w><C-]> :<C-u>call go#def#Jump(spli… (#838) 2d9124f1a Updated `benchmark` snippet to use for loop (#840) 9f0cf00f6 path: do not exepath ca46f2d0a Update CHANGELOG.md 95f43b8ab Update CHANGELOG.md 62f8aa38e don't default to binaries in the PATH (#823) d2f22ba3d Update CHANGELOG.md ff70ed5b6 Snippets for Example and Benchmark (#836) 5a846f358 Document using quickfix list for syntastic (#834) 91ffc4108 Update CHANGELOG.md 7a5dc84aa Merge branch 'master' of https://github.com/fatih/vim-go bbe4357a6 mappings: fix freevars mapping 849a8bb0b guru: fix preventing printing the output twice 91ff811b6 Update CHANGELOG.md 36e96cd52 Update CHANGELOG.md 56ac0d7dc guru: fix providing meaningful error messages instead of showing "-1" e3ebd69d2 Update CHANGELOG.md 93831e8b3 guru: implements needs scope to function well 1ebda8368 Update CHANGELOG.md 2541180a5 Merge pull request #813 from fatih/fix-gohtmltmpl 4679725cf Update CHANGELOG.md 1469db423 Merge pull request #827 from fatih/fix-coverage-syntax 766e836bc coverage: fix for cases of syntax=off dcbe7cef6 Update CHANGELOG.md 42a782f38 Merge pull request #821 from sillyousu/master 6e2df56e7 Merge pull request #826 from mattn/fixes-824 7a8384acc exit code should be checked with 0 12e8bed78 pass -tags flag to guru dfb0ee1ec Update CHANGELOG.md f830d0dc1 use go#util#system(), go#util#shell_errors() instead of system(), v:shell_error (#801) e9df17fc7 Update CHANGELOG.md 08a9c7c70 Merge pull request #816 from andrewstuart/master ede2ec511 Add http handler snippets 480b7660f New release: v1.6 8a78ded14 def: reuse is a better word d439e855a ftplugin: add gohtmltmpl.vim a605c6216 Merge pull request #812 from fatih/coverage-improvements 7351848a2 coverage: add :GoCoverageClear and :GoCoverageToggle 4f67ae2dc Merge pull request #802 from sethvargo/patch-1 4c7967c08 Clarify that mappings are enabled by default b3fddb60f Merge branch 'master' of https://github.com/fatih/vim-go abd3d1490 doc: fix wording for (go-run) mapping fd10ba68f Handle windows paths (#799) 5c45ba9c4 coverage: check if matchaddpos exists a0f8bd34d def: fix selecting from tag stack c3fdca0e4 def: fix displaying guru errors cd473451e Update CHANGELOG 24aeacc43 def: jump to an existing buffer if its exist 58d73af73 Merge branch 'master' of https://github.com/fatih/vim-go 53e924411 def.vim: revert back mapping to ctrl-t c0f7d3ee8 Update CHANGELOG.md 16cc4d62c mappings: change CTRL-t to CTRL-T for compatibility cce10c75d guru: fix output format ab55541df def: use script local variable 3a596f5bf Update README.md 2e5996015 Merge pull request #781 from fatih/guru 3eac959bf Add support for new guru tool b97962689 Merge pull request #794 from cuzelac/master 985c0922a Update CHANGELOG.md 075cfb3a7 Update CHANGELOG.md fbc9b4e6c Update CHANGELOG.md 6d88d521b improve :GoDef and tag stack commands 449dc59a4 GoTestFunc: support testable examples 80f6cf8fa Add custom godef jump stack (fixes #667) (#776) 385a92f01 Update Changelog 7f248b206 Merge pull request #782 from fatih/godoc-improvement 160bedc2b syntax: remove not used godoc.vim f478b530c doc: use gogetdoc to display docs in a better way 9f2fac6cb Merge pull request #790 from fatih/coverage-term-fix 52dbc47b7 coverage: fix not working if go_term_enabled is set 5ce65295c coverage: open only if file exists a4f44db42 Merge pull request #746 from eliasgs/master 451cb1acc Update README.md f6c71e7c7 Update docs fe718fc9c Merge branch 'master' of https://github.com/fatih/vim-go dc98bc775 Update Readme.md aea106131 Merge pull request #787 from cespare/optional-format-highlight cc4584404 Remove whitespaces 952b75259 Add go_highlight_format_strings option for printf-style format strings 1ac0d1f8e Update Changelog e35dfca6c Remove artifact 407908ad6 Merge pull request #786 from fatih/t-yuki-vim-go-coverlay 0eff02604 coverage: improvements and integration into vim-go f92fac2fd Add vim-go-coverlay e93048420 fmt: use shellescape instead of fnameescape 5c282de1a Update CHANGELOG.md 1a82fb7d5 Add fix c4183771f term: close location list if cmd's result is successful ef9bc716a term: close location list if cmd's result is successful 230b1bb69 Update CHANGELOG.md 0ff0a2dde Add CHANGELOG.md 19cfa6fbb jobcontrol: add AddHandler and RemoveHandler API to catch on_exit callback for callers of caller git-subtree-dir: vim/bundle/go git-subtree-split: bf390af42c53ae217356d7763ac3e7767f0162a4
This commit is contained in:
parent
c9ca63a819
commit
c7496b2816
3
.coveragerc
Normal file
3
.coveragerc
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[run]
|
||||||
|
plugins = covimerage
|
||||||
|
data_file = .coverage.covimerage
|
||||||
2
.dockerignore
Normal file
2
.dockerignore
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
.local/
|
||||||
|
.git/
|
||||||
17
.editorconfig
Normal file
17
.editorconfig
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# http://EditorConfig.org
|
||||||
|
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.go]
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[Makefile]
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 8
|
||||||
15
.github/CONTRIBUTING.md
vendored
15
.github/CONTRIBUTING.md
vendored
@ -1,9 +1,12 @@
|
|||||||
Thanks for improving vim-go! Before you dive in please read the following:
|
Thanks for improving vim-go! Before you dive in please read the following:
|
||||||
|
|
||||||
1. Please read our
|
1. Please read our
|
||||||
[FAQ](https://github.com/fatih/vim-go/wiki/FAQ-Troubleshooting), it might
|
[Documentation](https://github.com/fatih/vim-go/blob/master/doc/vim-go.txt),
|
||||||
have answers for your problem
|
it might have a solution to your problem.
|
||||||
2. If you add a new feature please don't forget to update the documentation:
|
2. If you add a new feature then please don't forget to update the documentation:
|
||||||
[doc/vim-go.txt](doc/vim-go.txt)
|
[doc/vim-go.txt](https://github.com/fatih/vim-go/blob/master/doc/vim-go.txt).
|
||||||
3. If it's a breaking change or exceed +100 lines please open an issue first
|
3. If it's a breaking change or exceeds 100 lines of code then please open an
|
||||||
and describe the changes you want to make.
|
issue first and describe the changes you want to make.
|
||||||
|
4. See `:help go-development` for instructions on how to run and write tests. If
|
||||||
|
you add a new feature be sure you also include a test if feasible.
|
||||||
|
|
||||||
|
|||||||
30
.github/ISSUE_TEMPLATE.md
vendored
30
.github/ISSUE_TEMPLATE.md
vendored
@ -1,28 +1,22 @@
|
|||||||
### Actual behavior
|
### What did you do? (required. The issue will be **closed** when not provided.)
|
||||||
|
|
||||||
Write here what's happening ...
|
|
||||||
|
|
||||||
### Expected behavior
|
### What did you expect to happen?
|
||||||
|
|
||||||
Write here what you're expecting ...
|
|
||||||
|
|
||||||
### Steps to reproduce:
|
### What happened instead?
|
||||||
|
|
||||||
Please create a reproducible case of your problem. Re produce it
|
|
||||||
with a minimal `vimrc` with all plugins disabled and only `vim-go`
|
|
||||||
enabled:
|
|
||||||
|
|
||||||
1.
|
### Configuration (**MUST** fill this out):
|
||||||
2.
|
|
||||||
3.
|
|
||||||
|
|
||||||
### Configuration
|
* Vim version (first two lines from `:version`):
|
||||||
|
|
||||||
Add here your current configuration and additional information that might be
|
* Go version (`go version`):
|
||||||
useful, such as:
|
|
||||||
|
* Go environment (`go env`):
|
||||||
|
|
||||||
|
* vim-go version:
|
||||||
|
|
||||||
|
* `vimrc` you used to reproduce (use a *minimal* vimrc with other plugins disabled; do not link to a 2,000 line vimrc):
|
||||||
|
|
||||||
* `vimrc` you used to reproduce
|
|
||||||
* vim version:
|
|
||||||
* vim-go version
|
|
||||||
* go version
|
|
||||||
|
|
||||||
|
|||||||
6
.gitignore
vendored
6
.gitignore
vendored
@ -1 +1,5 @@
|
|||||||
doc/tags
|
.DS_Store
|
||||||
|
/doc/tags
|
||||||
|
/.coverage.covimerage
|
||||||
|
/coverage.xml
|
||||||
|
*.pyc
|
||||||
|
|||||||
14
.travis.yml
Normal file
14
.travis.yml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
language: go
|
||||||
|
notifications:
|
||||||
|
email: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- env: SCRIPT="test -c" VIM_VERSION=vim-7.4
|
||||||
|
- env: SCRIPT="test -c" VIM_VERSION=vim-8.0
|
||||||
|
- env: SCRIPT="test -c" VIM_VERSION=nvim
|
||||||
|
- env: SCRIPT=lint VIM_VERSION=vim-8.0
|
||||||
|
install:
|
||||||
|
- ./scripts/install-vim $VIM_VERSION
|
||||||
|
- pip install --user vim-vint covimerage codecov
|
||||||
|
script:
|
||||||
|
- ./scripts/$SCRIPT $VIM_VERSION
|
||||||
7
.vintrc.yaml
Normal file
7
.vintrc.yaml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
policies:
|
||||||
|
ProhibitUnnecessaryDoubleQuote:
|
||||||
|
enabled: false
|
||||||
|
ProhibitEqualTildeOperator:
|
||||||
|
enabled: false
|
||||||
|
ProhibitNoAbortFunction:
|
||||||
|
enabled: false
|
||||||
1093
CHANGELOG.md
Normal file
1093
CHANGELOG.md
Normal file
File diff suppressed because it is too large
Load Diff
20
Dockerfile
Normal file
20
Dockerfile
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
FROM golang:1.9.2
|
||||||
|
|
||||||
|
RUN apt-get update -y && \
|
||||||
|
apt-get install -y build-essential curl git libncurses5-dev python3-pip && \
|
||||||
|
apt-get clean && \
|
||||||
|
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||||
|
|
||||||
|
RUN pip3 install vim-vint
|
||||||
|
|
||||||
|
RUN useradd -ms /bin/bash -d /vim-go vim-go
|
||||||
|
USER vim-go
|
||||||
|
|
||||||
|
COPY . /vim-go/
|
||||||
|
WORKDIR /vim-go
|
||||||
|
|
||||||
|
RUN scripts/install-vim vim-7.4
|
||||||
|
RUN scripts/install-vim vim-8.0
|
||||||
|
RUN scripts/install-vim nvim
|
||||||
|
|
||||||
|
ENTRYPOINT ["make"]
|
||||||
2
LICENSE
2
LICENSE
@ -56,3 +56,5 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
The Go gopher was designed by Renee French. http://reneefrench.blogspot.com/ The design is licensed under the Creative Commons 3.0 Attributions license. Read this article for more details: https://blog.golang.org/gopher
|
||||||
|
|||||||
29
Makefile
Normal file
29
Makefile
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
VIMS ?= vim-7.4 vim-8.0 nvim
|
||||||
|
|
||||||
|
all: install test lint
|
||||||
|
|
||||||
|
install:
|
||||||
|
@echo "==> Installing Vims: $(VIMS)"
|
||||||
|
@for vim in $(VIMS); do \
|
||||||
|
./scripts/install-vim $$vim; \
|
||||||
|
done
|
||||||
|
|
||||||
|
test:
|
||||||
|
@echo "==> Running tests for $(VIMS)"
|
||||||
|
@for vim in $(VIMS); do \
|
||||||
|
./scripts/test $$vim; \
|
||||||
|
done
|
||||||
|
|
||||||
|
lint:
|
||||||
|
@echo "==> Running linting tools"
|
||||||
|
@./scripts/lint vim-8.0
|
||||||
|
|
||||||
|
docker:
|
||||||
|
@echo "==> Building/starting Docker container"
|
||||||
|
@./scripts/docker-test
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@echo "==> Cleaning /tmp/vim-go-test"
|
||||||
|
@rm -rf /tmp/vim-go-test
|
||||||
|
|
||||||
|
.PHONY: all test install clean lint docker
|
||||||
307
README.md
307
README.md
@ -1,282 +1,71 @@
|
|||||||
# vim-go
|
# vim-go [](https://travis-ci.org/fatih/vim-go)
|
||||||
|
|
||||||
Go (golang) support for Vim, which comes with pre-defined sensible settings (like
|
|
||||||
auto gofmt on save), with autocomplete, snippet support, improved syntax
|
|
||||||
highlighting, go toolchain commands, and more. If needed vim-go installs all
|
|
||||||
necessary binaries for providing seamless Vim integration with current
|
|
||||||
commands. It's highly customizable and each individual feature can be
|
|
||||||
disabled/enabled easily.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img style="float: right;" src="assets/vim-go.png" alt="Vim-go logo"/>
|
||||||
|
</p>
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
* Improved Syntax highlighting with items such as Functions, Operators, Methods.
|
This plugin adds Go language support for Vim, with the following main features:
|
||||||
* Auto completion support via `gocode`
|
|
||||||
* Better `gofmt` on save, which keeps cursor position and doesn't break your undo
|
|
||||||
history
|
|
||||||
* Go to symbol/declaration with `:GoDef`
|
|
||||||
* Look up documentation with `:GoDoc` inside Vim or open it in browser
|
|
||||||
* Automatically import packages via `:GoImport` or plug it into autosave
|
|
||||||
* Compile your package with `:GoBuild`, install it with `:GoInstall` or test
|
|
||||||
them with `:GoTest` (also supports running single tests via `:GoTestFunc`)
|
|
||||||
* Quickly execute your current file/files with `:GoRun`
|
|
||||||
* Automatic `GOPATH` detection based on the directory structure (i.e. `gb`
|
|
||||||
projects, `godep` vendored projects)
|
|
||||||
* Change or display `GOPATH` with `:GoPath`
|
|
||||||
* Create a coverage profile and display annotated source code in browser to see
|
|
||||||
which functions are covered with `:GoCoverage`
|
|
||||||
* Call `gometalinter` with `:GoMetaLinter`, which invokes all possible linters
|
|
||||||
(golint, vet, errcheck, deadcode, etc..) and shows the warnings/errors
|
|
||||||
* Lint your code with `:GoLint`
|
|
||||||
* Run your code through `:GoVet` to catch static errors
|
|
||||||
* Advanced source analysis tools utilizing oracle, such as `:GoImplements`,
|
|
||||||
`:GoCallees`, and `:GoReferrers`
|
|
||||||
* Precise type-safe renaming of identifiers with `:GoRename`
|
|
||||||
* List all source files and dependencies
|
|
||||||
* Unchecked error checking with `:GoErrCheck`
|
|
||||||
* Integrated and improved snippets, supporting `ultisnips` or `neosnippet`
|
|
||||||
* Share your current code to [play.golang.org](http://play.golang.org) with `:GoPlay`
|
|
||||||
* On-the-fly type information about the word under the cursor. Plug it into
|
|
||||||
your custom vim function.
|
|
||||||
* Go asm formatting on save
|
|
||||||
* Tagbar support to show tags of the source code in a sidebar with `gotags`
|
|
||||||
* Custom vim text objects such as `a function` or `inner function`
|
|
||||||
list.
|
|
||||||
* A async launcher for the go command is implemented for Neovim, fully async
|
|
||||||
building and testing (beta).
|
|
||||||
* Integrated with the Neovim terminal, launch `:GoRun` and other go commands
|
|
||||||
in their own new terminal. (beta)
|
|
||||||
* Alternate between implementation and test code with `:GoAlternate`
|
|
||||||
|
|
||||||
## Donation
|
* Compile your package with `:GoBuild`, install it with `:GoInstall` or test it
|
||||||
|
with `:GoTest`. Run a single tests with `:GoTestFunc`).
|
||||||
People have asked for this for a long time, now you can be a fully supporter by [being a patron](https://www.patreon.com/fatih)! This is fully optional and is just a way to support vim-go's ongoing development directly. Thanks!
|
* Quickly execute your current file(s) with `:GoRun`.
|
||||||
|
* Improved syntax highlighting and folding.
|
||||||
[https://www.patreon.com/fatih](https://www.patreon.com/fatih)
|
* Completion support via `gocode`.
|
||||||
|
* `gofmt` or `goimports` on save keeps the cursor position and undo history.
|
||||||
|
* Go to symbol/declaration with `:GoDef`.
|
||||||
|
* Look up documentation with `:GoDoc` or `:GoDocBrowser`.
|
||||||
|
* Easily import packages via `:GoImport`, remove them via `:GoDrop`.
|
||||||
|
* Automatic `GOPATH` detection which works with `gb` and `godep`. Change or
|
||||||
|
display `GOPATH` with `:GoPath`.
|
||||||
|
* See which code is covered by tests with `:GoCoverage`.
|
||||||
|
* Add or remove tags on struct fields with `:GoAddTags` and `:GoRemoveTags`.
|
||||||
|
* Call `gometalinter` with `:GoMetaLinter` to invoke all possible linters
|
||||||
|
(`golint`, `vet`, `errcheck`, `deadcode`, etc.) and put the result in the
|
||||||
|
quickfix or location list.
|
||||||
|
* Lint your code with `:GoLint`, run your code through `:GoVet` to catch static
|
||||||
|
errors, or make sure errors are checked with `:GoErrCheck`.
|
||||||
|
* Advanced source analysis tools utilizing `guru`, such as `:GoImplements`,
|
||||||
|
`:GoCallees`, and `:GoReferrers`.
|
||||||
|
* Precise type-safe renaming of identifiers with `:GoRename`.
|
||||||
|
* ... and many more! Please see [doc/vim-go.txt](doc/vim-go.txt) for more
|
||||||
|
information.
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
Vim-go follows the standard runtime path structure, so I highly recommend to
|
The [**latest stable release**](https://github.com/fatih/vim-go/releases/latest) is the
|
||||||
use a common and well known plugin manager to install vim-go. Do not use vim-go
|
recommended version to use. If you choose to use the master branch instead,
|
||||||
with other Go oriented vim plugins. For Pathogen just clone the repo. For other
|
please do so with caution; it is a _development_ branch.
|
||||||
plugin managers add the appropriate lines and execute the plugin's install
|
|
||||||
command.
|
|
||||||
|
|
||||||
|
vim-go follows the standard runtime path structure. Below are some helper lines
|
||||||
|
for popular package managers:
|
||||||
|
|
||||||
|
* [Vim 8 packages](http://vimhelp.appspot.com/repeat.txt.html#packages)
|
||||||
|
* `git clone https://github.com/fatih/vim-go.git ~/.vim/pack/plugins/start/vim-go`
|
||||||
* [Pathogen](https://github.com/tpope/vim-pathogen)
|
* [Pathogen](https://github.com/tpope/vim-pathogen)
|
||||||
* `git clone https://github.com/fatih/vim-go.git ~/.vim/bundle/vim-go`
|
* `git clone https://github.com/fatih/vim-go.git ~/.vim/bundle/vim-go`
|
||||||
* [vim-plug](https://github.com/junegunn/vim-plug)
|
* [vim-plug](https://github.com/junegunn/vim-plug)
|
||||||
* `Plug 'fatih/vim-go'`
|
* `Plug 'fatih/vim-go'`
|
||||||
* [NeoBundle](https://github.com/Shougo/neobundle.vim)
|
|
||||||
* `NeoBundle 'fatih/vim-go'`
|
|
||||||
* [Vundle](https://github.com/gmarik/vundle)
|
|
||||||
* `Plugin 'fatih/vim-go'`
|
|
||||||
|
|
||||||
Please be sure all necessary binaries are installed (such as `gocode`, `godef`,
|
You will also need to install all the necessary binaries. vim-go makes it easy
|
||||||
`goimports`, etc.). You can easily install them with the included
|
to install all of them by providing a command, `:GoInstallBinaries`, which will
|
||||||
`:GoInstallBinaries` command. If invoked, all necessary binaries will be
|
`go get` all the required binaries.
|
||||||
automatically downloaded and installed to your `$GOBIN` environment (if not set
|
|
||||||
it will use `$GOPATH/bin`). Note that this command requires `git` for fetching
|
|
||||||
the individual Go packages. Additionally, use `:GoUpdateBinaries` to update the
|
|
||||||
installed binaries.
|
|
||||||
|
|
||||||
### Optional
|
Check out the Install section in [the documentation](doc/vim-go.txt) for more
|
||||||
|
detailed instructions (`:help go-install`).
|
||||||
* Autocompletion is enabled by default via `<C-x><C-o>`. To get real-time
|
|
||||||
completion (completion by type) install:
|
|
||||||
[neocomplete](https://github.com/Shougo/neocomplete.vim) for Vim or
|
|
||||||
[deoplete](https://github.com/Shougo/deoplete.nvim) and
|
|
||||||
[deoplete-go](https://github.com/zchee/deoplete-go) for NeoVim
|
|
||||||
* To display source code tag information on a sidebar install
|
|
||||||
[tagbar](https://github.com/majutsushi/tagbar).
|
|
||||||
* For snippet features install:
|
|
||||||
[neosnippet](https://github.com/Shougo/neosnippet.vim) or
|
|
||||||
[ultisnips](https://github.com/SirVer/ultisnips).
|
|
||||||
* Screenshot color scheme is a slightly modified molokai:
|
|
||||||
[fatih/molokai](https://github.com/fatih/molokai).
|
|
||||||
* For a better documentation viewer checkout:
|
|
||||||
[go-explorer](https://github.com/garyburd/go-explorer).
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Many of the plugin's [features](#features) are enabled by default. There are no
|
The full documentation can be found at [doc/vim-go.txt](doc/vim-go.txt). You can
|
||||||
additional settings needed. All usages and commands are listed in
|
display it from within Vim with `:help vim-go`.
|
||||||
`doc/vim-go.txt`. Note that help tags needs to be populated. Check your plugin
|
|
||||||
manager settings to generate the documentation (some do it automatically).
|
|
||||||
After that just open the help page to see all commands:
|
|
||||||
|
|
||||||
:help vim-go
|
Depending on your installation method, you may have to generate the plugin's
|
||||||
|
[`help tags`](http://vimhelp.appspot.com/helphelp.txt.html#%3Ahelptags)
|
||||||
|
manually (e.g. `:helptags ALL`).
|
||||||
|
|
||||||
## Mappings
|
We also have an [official vim-go tutorial](https://github.com/fatih/vim-go-tutorial).
|
||||||
|
|
||||||
vim-go has several `<Plug>` mappings which can be used to create custom
|
|
||||||
mappings. Below are some examples you might find useful:
|
|
||||||
|
|
||||||
Run commands such as `go run` for the current file with `<leader>r` or `go
|
|
||||||
build` and `go test` for the current package with `<leader>b` and `<leader>t`
|
|
||||||
respectively. Display beautifully annotated source code to see which functions
|
|
||||||
are covered with `<leader>c`.
|
|
||||||
|
|
||||||
```vim
|
|
||||||
au FileType go nmap <leader>r <Plug>(go-run)
|
|
||||||
au FileType go nmap <leader>b <Plug>(go-build)
|
|
||||||
au FileType go nmap <leader>t <Plug>(go-test)
|
|
||||||
au FileType go nmap <leader>c <Plug>(go-coverage)
|
|
||||||
```
|
|
||||||
|
|
||||||
By default the mapping `gd` is enabled, which opens the target identifier in
|
|
||||||
current buffer. You can also open the definition/declaration, in a new vertical,
|
|
||||||
horizontal, or tab, for the word under your cursor:
|
|
||||||
|
|
||||||
```vim
|
|
||||||
au FileType go nmap <Leader>ds <Plug>(go-def-split)
|
|
||||||
au FileType go nmap <Leader>dv <Plug>(go-def-vertical)
|
|
||||||
au FileType go nmap <Leader>dt <Plug>(go-def-tab)
|
|
||||||
```
|
|
||||||
|
|
||||||
Open the relevant Godoc for the word under the cursor with `<leader>gd` or open
|
|
||||||
it vertically with `<leader>gv`
|
|
||||||
|
|
||||||
```vim
|
|
||||||
au FileType go nmap <Leader>gd <Plug>(go-doc)
|
|
||||||
au FileType go nmap <Leader>gv <Plug>(go-doc-vertical)
|
|
||||||
```
|
|
||||||
|
|
||||||
Or open the Godoc in browser
|
|
||||||
|
|
||||||
```vim
|
|
||||||
au FileType go nmap <Leader>gb <Plug>(go-doc-browser)
|
|
||||||
```
|
|
||||||
|
|
||||||
Show a list of interfaces which is implemented by the type under your cursor
|
|
||||||
with `<leader>s`
|
|
||||||
|
|
||||||
```vim
|
|
||||||
au FileType go nmap <Leader>s <Plug>(go-implements)
|
|
||||||
```
|
|
||||||
|
|
||||||
Show type info for the word under your cursor with `<leader>i` (useful if you
|
|
||||||
have disabled auto showing type info via `g:go_auto_type_info`)
|
|
||||||
|
|
||||||
```vim
|
|
||||||
au FileType go nmap <Leader>i <Plug>(go-info)
|
|
||||||
```
|
|
||||||
|
|
||||||
Rename the identifier under the cursor to a new name
|
|
||||||
|
|
||||||
```vim
|
|
||||||
au FileType go nmap <Leader>e <Plug>(go-rename)
|
|
||||||
```
|
|
||||||
|
|
||||||
More `<Plug>` mappings can be seen with `:he go-mappings`. Also these are just
|
|
||||||
recommendations, you are free to create more advanced mappings or functions
|
|
||||||
based on `:he go-commands`.
|
|
||||||
|
|
||||||
## Settings
|
|
||||||
Below are some settings you might find useful. For the full list see `:he
|
|
||||||
go-settings`.
|
|
||||||
|
|
||||||
By default syntax-highlighting for Functions, Methods and Structs is disabled.
|
|
||||||
To change it:
|
|
||||||
```vim
|
|
||||||
let g:go_highlight_functions = 1
|
|
||||||
let g:go_highlight_methods = 1
|
|
||||||
let g:go_highlight_structs = 1
|
|
||||||
let g:go_highlight_interfaces = 1
|
|
||||||
let g:go_highlight_operators = 1
|
|
||||||
let g:go_highlight_build_constraints = 1
|
|
||||||
```
|
|
||||||
|
|
||||||
Enable goimports to automatically insert import paths instead of gofmt:
|
|
||||||
|
|
||||||
```vim
|
|
||||||
let g:go_fmt_command = "goimports"
|
|
||||||
```
|
|
||||||
|
|
||||||
By default vim-go shows errors for the fmt command, to disable it:
|
|
||||||
|
|
||||||
```vim
|
|
||||||
let g:go_fmt_fail_silently = 1
|
|
||||||
```
|
|
||||||
|
|
||||||
Disable auto fmt on save:
|
|
||||||
|
|
||||||
```vim
|
|
||||||
let g:go_fmt_autosave = 0
|
|
||||||
```
|
|
||||||
|
|
||||||
Disable opening browser after posting your snippet to `play.golang.org`:
|
|
||||||
|
|
||||||
```vim
|
|
||||||
let g:go_play_open_browser = 0
|
|
||||||
```
|
|
||||||
|
|
||||||
By default when `:GoInstallBinaries` is called, the binaries are installed to
|
|
||||||
`$GOBIN` or `$GOPATH/bin`. To change it:
|
|
||||||
|
|
||||||
```vim
|
|
||||||
let g:go_bin_path = expand("~/.gotools")
|
|
||||||
let g:go_bin_path = "/home/fatih/.mypath" "or give absolute path
|
|
||||||
```
|
|
||||||
|
|
||||||
### Using with Neovim (beta)
|
|
||||||
|
|
||||||
Note: Neovim currently is not a first class citizen for vim-go. You are free
|
|
||||||
to open bugs but I'm not going to look at them. Even though I'm using Neovim
|
|
||||||
myself, Neovim itself is still alpha. So vim-go might not work well as good as
|
|
||||||
in Vim. I'm happy to accept pull requests or very detailed bug reports.
|
|
||||||
|
|
||||||
|
|
||||||
Run `:GoRun` in a new tab, horizontal split or vertical split terminal
|
|
||||||
|
|
||||||
```vim
|
|
||||||
au FileType go nmap <leader>rt <Plug>(go-run-tab)
|
|
||||||
au FileType go nmap <Leader>rs <Plug>(go-run-split)
|
|
||||||
au FileType go nmap <Leader>rv <Plug>(go-run-vertical)
|
|
||||||
```
|
|
||||||
|
|
||||||
By default new terminals are opened in a vertical split. To change it
|
|
||||||
|
|
||||||
```vim
|
|
||||||
let g:go_term_mode = "split"
|
|
||||||
```
|
|
||||||
|
|
||||||
By default the testing commands run asynchronously in the background and
|
|
||||||
display results with `go#jobcontrol#Statusline()`. To make them run in a new
|
|
||||||
terminal
|
|
||||||
|
|
||||||
```vim
|
|
||||||
let g:go_term_enabled = 1
|
|
||||||
```
|
|
||||||
|
|
||||||
### Using with Syntastic
|
|
||||||
Sometimes when using both `vim-go` and `syntastic` Vim will start lagging while
|
|
||||||
saving and opening files. The following fixes this:
|
|
||||||
|
|
||||||
```vim
|
|
||||||
let g:syntastic_go_checkers = ['golint', 'govet', 'errcheck']
|
|
||||||
let g:syntastic_mode_map = { 'mode': 'active', 'passive_filetypes': ['go'] }
|
|
||||||
```
|
|
||||||
|
|
||||||
## More info
|
|
||||||
|
|
||||||
Check out the [Wiki](https://github.com/fatih/vim-go/wiki) page for more
|
|
||||||
information. It includes
|
|
||||||
[Screencasts](https://github.com/fatih/vim-go/wiki/Screencasts), an [FAQ
|
|
||||||
section](https://github.com/fatih/vim-go/wiki/FAQ-Troubleshooting), and many
|
|
||||||
other [various pieces](https://github.com/fatih/vim-go/wiki) of information.
|
|
||||||
|
|
||||||
## Credits
|
|
||||||
|
|
||||||
* Go Authors for official vim plugins
|
|
||||||
* Gocode, Godef, Golint, Oracle, Goimports, Gotags, Errcheck projects and
|
|
||||||
authors of those projects.
|
|
||||||
* Other vim-plugins, thanks for inspiration (vim-golang, go.vim, vim-gocode,
|
|
||||||
vim-godef)
|
|
||||||
* [Contributors](https://github.com/fatih/vim-go/graphs/contributors) of vim-go
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
The BSD 3-Clause License - see `LICENSE` for more details
|
The BSD 3-Clause License - see [`LICENSE`](LICENSE) for more details
|
||||||
|
|||||||
BIN
assets/screenshot.png
Normal file
BIN
assets/screenshot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 747 KiB |
BIN
assets/vim-go.png
Normal file
BIN
assets/vim-go.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
821
assets/vim-go.svg
Normal file
821
assets/vim-go.svg
Normal file
@ -0,0 +1,821 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="173.53481mm"
|
||||||
|
height="147.26407mm"
|
||||||
|
viewBox="0 0 614.88711 521.80181"
|
||||||
|
id="svg2"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.91 r13725"
|
||||||
|
sodipodi:docname="vim-go.svg"
|
||||||
|
style="enable-background:new"
|
||||||
|
inkscape:export-filename="F:\Go\src\github.com\egonelbre\vim-go\assets\vim-go.png"
|
||||||
|
inkscape:export-xdpi="46.84"
|
||||||
|
inkscape:export-ydpi="46.84">
|
||||||
|
<defs
|
||||||
|
id="defs4">
|
||||||
|
<linearGradient
|
||||||
|
id="gopher-iris"
|
||||||
|
osb:paint="solid"
|
||||||
|
gradientTransform="translate(-9.2596241,38.869516)">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#394455;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop4317" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="docker-iris"
|
||||||
|
osb:paint="solid">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#394d54;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop4311" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="docker-jaw"
|
||||||
|
osb:paint="solid">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#d4edf1;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop4305" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="docker-eye"
|
||||||
|
osb:paint="solid">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop4299" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="docker-line"
|
||||||
|
osb:paint="solid">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#394d54;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop4293" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="docker-body"
|
||||||
|
osb:paint="solid">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#24b8eb;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop4287" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="gopher-limbs"
|
||||||
|
osb:paint="solid">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#e1d6b9;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop4269" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="gopher-nose"
|
||||||
|
osb:paint="solid">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#e1d0cb;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop4263" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="gopher-body"
|
||||||
|
osb:paint="solid"
|
||||||
|
gradientTransform="matrix(-0.18574987,-0.98259706,0.98259706,-0.18574987,-1213.2665,1828.8814)">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#96d6ff;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop4334" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient4253">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#bce8ff;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop4194" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient4182">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#2e3436;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop4184" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="gopher-eye"
|
||||||
|
osb:paint="solid"
|
||||||
|
gradientTransform="translate(381.30424,802.02286)">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop4178" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="gopher-lines"
|
||||||
|
osb:paint="solid"
|
||||||
|
gradientTransform="matrix(2.0620253,3.9293227,1.3839016,-0.24027903,2506.9621,8572.3972)">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#394655;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop4166" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#gopher-lines"
|
||||||
|
id="linearGradient4168"
|
||||||
|
x1="776.14288"
|
||||||
|
y1="39.505058"
|
||||||
|
x2="822.42859"
|
||||||
|
y2="39.505058"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.92105265,0,0,0.92105265,79.548449,262.52483)" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#gopher-eye"
|
||||||
|
id="linearGradient4180"
|
||||||
|
x1="776.14288"
|
||||||
|
y1="90.770309"
|
||||||
|
x2="822.42859"
|
||||||
|
y2="90.770309"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.92105266,0,0,0.92105266,124.54841,215.30684)" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#gopher-body"
|
||||||
|
id="linearGradient4336"
|
||||||
|
x1="-628.69226"
|
||||||
|
y1="371.77307"
|
||||||
|
x2="-151.41731"
|
||||||
|
y2="371.77307"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(-1,0,0,1,-681.83098,347.55492)" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#gopher-nose"
|
||||||
|
id="linearGradient4265"
|
||||||
|
x1="198.05417"
|
||||||
|
y1="374.50043"
|
||||||
|
x2="263.28683"
|
||||||
|
y2="374.50043"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.65610141,0,0,0.65610141,185.97779,480.81383)" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#gopher-limbs"
|
||||||
|
id="linearGradient4271"
|
||||||
|
x1="730.36273"
|
||||||
|
y1="373.60995"
|
||||||
|
x2="831.0592"
|
||||||
|
y2="373.60995"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.90381797,-0.29515654,-0.62039307,-0.90381797,-597.71307,820.3894)" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#gopher-limbs"
|
||||||
|
id="linearGradient4273"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(-0.54351115,-0.65417141,-1.0770811,0.54351115,655.01412,667.6722)" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#gopher-limbs"
|
||||||
|
id="linearGradient4275"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(-0.94401471,-0.3302474,-0.32955964,0.94401471,1151.0861,721.50542)" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#gopher-limbs"
|
||||||
|
id="linearGradient4279"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.89463991,0.4064691,0.49110603,-0.89463991,-749.6705,579.40921)" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#gopher-limbs"
|
||||||
|
id="linearGradient4281"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.49170605,0.377674,2.0076181,-0.49170605,229.12024,357.65841)" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#gopher-iris"
|
||||||
|
id="linearGradient4319"
|
||||||
|
x1="427.26477"
|
||||||
|
y1="316.13431"
|
||||||
|
x2="488.88409"
|
||||||
|
y2="316.13431"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(-1,0,0,1,744.54563,401.01143)" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#gopher-iris"
|
||||||
|
id="linearGradient4321"
|
||||||
|
gradientTransform="matrix(5.6994379,2.2315229,-1.9072375,4.8711945,4487.6828,1182.8772)"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="0.76274166"
|
||||||
|
inkscape:cx="499.78979"
|
||||||
|
inkscape:cy="92.336365"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer11"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1018"
|
||||||
|
inkscape:window-x="1912"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:snap-bbox="true"
|
||||||
|
inkscape:bbox-nodes="true"
|
||||||
|
inkscape:snap-global="false"
|
||||||
|
showguides="true"
|
||||||
|
fit-margin-top="0"
|
||||||
|
fit-margin-left="0"
|
||||||
|
fit-margin-right="0"
|
||||||
|
fit-margin-bottom="0">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid4305"
|
||||||
|
originx="-15.732723"
|
||||||
|
originy="-274.01154" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata7">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer11"
|
||||||
|
inkscape:label="background"
|
||||||
|
style="display:none"
|
||||||
|
transform="translate(-15.732722,-256.54886)">
|
||||||
|
<rect
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#d3e5de;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
id="rect4347"
|
||||||
|
width="614.88708"
|
||||||
|
height="521.80182"
|
||||||
|
x="15.732722"
|
||||||
|
y="256.54886"
|
||||||
|
inkscape:export-filename="vim-go.png"
|
||||||
|
inkscape:export-xdpi="46.84"
|
||||||
|
inkscape:export-ydpi="46.84" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer6"
|
||||||
|
inkscape:label="shadow"
|
||||||
|
transform="translate(-15.732722,-256.54886)">
|
||||||
|
<path
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#2e4233;fill-opacity:0.10714285;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 287.3893,695.44531 c -50.0612,-2.78118 -62.1134,11.12305 -91.7793,11.12305 -29.6659,0 -47.28069,-6.48881 -76.01953,-1.85352 -28.738834,4.6353 -40.790093,3.70867 -55.623042,16.6875 -14.832949,12.97883 -21.926707,11.85327 -18.541016,20.39454 1.318705,3.32677 3.956373,1.53579 10.703125,0.83984 115.165183,-11.87969 237.050993,16.53486 337.406243,16.77539 83.20192,0.19942 110.33047,-21.09623 105.22253,-34.76541 -16.86616,-45.13499 -81.24683,-23.67849 -211.36901,-29.20139 z"
|
||||||
|
id="path4349"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="csssssssc" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="cape-back"
|
||||||
|
style="display:inline"
|
||||||
|
sodipodi:insensitive="true"
|
||||||
|
transform="translate(-15.732722,-256.54886)">
|
||||||
|
<path
|
||||||
|
style="fill:#0c7a31;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 260.24444,535.87695 c -20.68496,5.13447 -3.94094,36.63825 -23.78246,45.53288 -18.22356,8.16932 -29.87743,27.29784 -48.21487,37.53094 -24.3143,13.56845 -47.25416,17.93122 -70.94376,35.71927 -11.54022,8.66532 -48.036929,3.46906 -49.132109,17.96915 56.226929,-8.73065 86.269619,15.95087 120.882979,20.57024 30.54605,4.07656 53.64011,2.39756 79.48357,-7.50413 89.71977,-34.37532 52.16171,-111.74704 51.81195,-135.28471 -17.69563,-3.28964 -42.98659,-18.78289 -60.1053,-14.53364 z"
|
||||||
|
id="path4321"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="sssscsscs" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer5"
|
||||||
|
inkscape:label="gopher-body"
|
||||||
|
style="display:inline;opacity:1"
|
||||||
|
sodipodi:insensitive="true"
|
||||||
|
transform="translate(-15.732722,-256.54886)">
|
||||||
|
<g
|
||||||
|
style="display:inline;opacity:1"
|
||||||
|
transform="matrix(-0.34823803,-0.28093567,-0.33018747,0.52325377,856.33627,409.62314)"
|
||||||
|
id="g4537">
|
||||||
|
<path
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#linearGradient4275);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 419.84023,584.57289 c -1.11092,4.23495 -3.11543,7.14238 -5.84936,9.02308 -2.73394,1.8807 -6.19236,2.76095 -10.13743,3.23943 -3.94504,0.47846 -8.37351,0.59759 -13.05363,0.66122 -4.6801,0.0636 -9.60653,0.0259 -14.5852,-0.15006 -4.97865,-0.17599 -9.67742,-0.66266 -13.94891,-1.44453 -4.27148,-0.78187 -8.12262,-1.83504 -11.28827,-3.15781 -3.16564,-1.32277 -5.63542,-2.92368 -7.07427,-4.89074 -1.43884,-1.96709 -1.83785,-4.30021 -0.94134,-7.07932 0.89648,-2.77911 2.64686,-4.65171 5.05838,-5.71202 2.41152,-1.06032 5.47772,-1.29847 8.97039,-1.04717 3.49268,0.25132 7.40119,0.98198 11.60615,1.60695 4.20496,0.62498 8.71575,1.10136 13.55734,0.95747 4.84159,-0.14387 9.82241,-1.20624 14.59946,-2.18657 4.77703,-0.9803 9.35663,-1.80521 13.2055,-1.76209 3.8489,0.0431 6.93814,0.92314 8.72484,2.84805 1.78673,1.92488 0.0493,13.32997 1.15633,9.09414 z"
|
||||||
|
id="path4539"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cssssssssssssssssc" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#gopher-lines);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 411.66722,570.50504 c -3.64483,-0.3204 -7.91192,0.0353 -12.44327,0.67313 -5.17866,0.72899 -10.69026,1.78243 -16.25596,1.96339 -5.56571,0.181 -10.75654,-0.27799 -15.6406,-0.87383 -4.8841,-0.59575 -9.46828,-1.26261 -13.59381,-1.35067 -4.12552,-0.0881 -7.77812,0.41271 -10.6665,1.77043 -2.88834,1.35772 -5.00621,3.55109 -6.11385,6.60546 -1.10762,3.05438 -0.68341,5.7953 0.96623,8.19507 1.64966,2.39979 4.51594,4.46252 8.19691,6.21125 3.681,1.74874 8.16283,3.1933 13.12136,4.28264 4.95854,1.08935 10.4013,1.79657 16.15733,2.05756 5.756,0.26106 11.2421,0.29972 16.33832,0.21929 5.09618,-0.0804 9.79866,-0.25121 13.94009,-0.87517 1.57579,-0.23741 3.06793,-0.55279 4.47088,-0.96129 2.8331,-0.82603 3.60613,-5.66983 1.06694,-4.35369 -2.35253,1.21937 -5.13009,1.88834 -8.23473,2.27934 -3.78352,0.47652 -8.03435,0.60519 -12.52976,0.67623 -4.49538,0.071 -9.22983,0.0403 -14.01368,-0.12137 -4.78387,-0.16172 -9.29761,-0.62006 -13.39935,-1.36274 -4.10176,-0.74271 -7.79879,-1.74643 -10.8363,-3.01023 -3.03748,-1.2638 -5.40588,-2.79646 -6.78423,-4.6796 -1.37835,-1.88316 -1.75885,-4.11616 -0.89417,-6.78092 0.86467,-2.66475 2.54876,-4.4645 4.86314,-5.48862 2.31437,-1.0241 5.2526,-1.265 8.60072,-1.03925 3.34811,0.22576 7.09649,0.90864 11.13305,1.49473 4.03653,0.5862 8.37113,1.03632 13.02879,0.89877 4.65766,-0.13756 9.45383,-1.14909 14.04535,-2.09377 4.59152,-0.94468 8.9823,-1.75345 12.66755,-1.73592 0.46066,0.002 0.91144,0.0161 1.3482,0.0436 1.1223,0.0708 2.1698,0.20509 3.10067,0.47739 1.0735,0.314 2.95461,-2.6047 -0.11758,-2.94357 -0.49859,-0.055 -1.54942,0.19872 -1.52174,-0.17766 z"
|
||||||
|
id="path4541"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="csscsscssssssssssssssssssssccsssc" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(-0.20408679,0.36109427,0.8060854,0.48598006,286.09208,226.24278)"
|
||||||
|
id="g4640"
|
||||||
|
style="display:inline;opacity:1">
|
||||||
|
<path
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#gopher-lines);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 767.29926,387.32674 c 11.1235,7.96555 31.77795,11.29978 44.73159,15.54502 12.95363,4.24526 18.14889,9.35948 22.12936,13.37285 3.98046,4.01338 5.94428,7.14463 4.71807,9.52723 -1.2262,2.38259 -5.54351,3.99405 -14.00119,4.81166 -8.45765,0.81761 -15.90978,0.12055 -23.02358,-1.72572 -7.11381,-1.84628 -13.80694,-4.86649 -21.70559,-8.603 -7.89866,-3.73649 -17.3272,-8.0507 -25.81115,-14.18439 -8.48395,-6.13369 -17.62324,-13.90003 -23.14238,-24.13356 -5.51915,-10.23352 -5.78201,-21.34406 -5.37146,-30.88264 0.41055,-9.53859 1.51092,-17.55377 2.71572,-23.74931 1.20482,-6.19553 2.71509,-10.67437 4.77102,-13.66952 2.05591,-2.99513 4.65165,-4.52673 7.71923,-4.52673 3.06759,0 5.70357,1.83092 7.62535,5.49926 1.9218,3.66832 3.04778,9.24444 3.28639,16.76004 0.23861,7.51561 -0.67126,17.08072 0.34029,27.19831 1.01155,10.1176 3.89485,20.79494 15.01833,28.7605 z"
|
||||||
|
id="path4642"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="sssssssssssssssss" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#linearGradient4281);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 760.81735,387.61463 c 8.35351,7.22933 23.40419,11.34465 36.92829,14.85447 13.52408,3.50986 21.76315,7.50998 26.41399,11.29491 4.65086,3.78492 7.04347,6.96136 6.89289,9.28045 -0.15059,2.31908 -3.07202,3.85186 -9.99413,4.53735 -6.92209,0.68549 -13.12478,-0.17957 -19.18856,-2.15841 -6.06375,-1.97886 -12.01277,-5.06603 -19.62326,-8.64782 -7.61047,-3.5818 -16.94465,-7.61787 -24.98938,-13.21535 -8.04472,-5.59749 -15.82286,-12.65396 -20.9022,-21.24583 -5.07935,-8.59186 -6.01346,-17.801 -5.99188,-25.91871 0.0216,-8.1177 0.93462,-15.14861 1.86635,-20.66954 0.93173,-5.52092 2.01706,-9.59713 3.38259,-12.30465 1.36554,-2.70753 3.03466,-4.06947 5.01979,-4.01398 1.98511,0.0555 3.57672,1.84704 4.61437,5.2751 1.03765,3.42807 1.44745,8.54444 1.4737,15.15288 0.0262,6.60845 -0.43638,14.76057 0.91317,23.27473 1.34954,8.51418 4.83074,17.27506 13.18427,24.5044 z"
|
||||||
|
id="path4644"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="sssssssssssssssss" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
style="display:inline;opacity:1"
|
||||||
|
id="g4594"
|
||||||
|
transform="matrix(-0.13664232,-0.29657059,-0.88136995,0.09664282,727.56031,790.52022)">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sssssssssssssssss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path4588"
|
||||||
|
d="m 767.29926,387.32674 c 11.1235,7.96555 31.77795,11.29978 44.73159,15.54502 12.95363,4.24526 18.14889,9.35948 22.12936,13.37285 3.98046,4.01338 5.94428,7.14463 4.71807,9.52723 -1.2262,2.38259 -5.54351,3.99405 -14.00119,4.81166 -8.45765,0.81761 -15.90978,0.12055 -23.02358,-1.72572 -7.11381,-1.84628 -13.80694,-4.86649 -21.70559,-8.603 -7.89866,-3.73649 -17.3272,-8.0507 -25.81115,-14.18439 -8.48395,-6.13369 -17.62324,-13.90003 -23.14238,-24.13356 -5.51915,-10.23352 -5.78201,-21.34406 -5.37146,-30.88264 0.41055,-9.53859 1.51092,-17.55377 2.71572,-23.74931 1.20482,-6.19553 2.71509,-10.67437 4.77102,-13.66952 2.05591,-2.99513 4.65165,-4.52673 7.71923,-4.52673 3.06759,0 5.70357,1.83092 7.62535,5.49926 1.9218,3.66832 3.04778,9.24444 3.28639,16.76004 0.23861,7.51561 -0.67126,17.08072 0.34029,27.19831 1.01155,10.1176 3.89485,20.79494 15.01833,28.7605 z"
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#gopher-lines);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sssssssssssssssss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="ellipse4590"
|
||||||
|
d="m 760.81735,387.61463 c 8.35351,7.22933 23.40419,11.34465 36.92829,14.85447 13.52408,3.50986 21.76315,7.50998 26.41399,11.29491 4.65086,3.78492 7.04347,6.96136 6.89289,9.28045 -0.15059,2.31908 -3.07202,3.85186 -9.99413,4.53735 -6.92209,0.68549 -13.12478,-0.17957 -19.18856,-2.15841 -6.06375,-1.97886 -12.01277,-5.06603 -19.62326,-8.64782 -7.61047,-3.5818 -16.94465,-7.61787 -24.98938,-13.21535 -8.04472,-5.59749 -15.82286,-12.65396 -20.9022,-21.24583 -5.07935,-8.59186 -6.01346,-17.801 -5.99188,-25.91871 0.0216,-8.1177 0.93462,-15.14861 1.86635,-20.66954 0.93173,-5.52092 2.01706,-9.59713 3.38259,-12.30465 1.36554,-2.70753 3.03466,-4.06947 5.01979,-4.01398 1.98511,0.0555 3.57672,1.84704 4.61437,5.2751 1.03765,3.42807 1.44745,8.54444 1.4737,15.15288 0.0262,6.60845 -0.43638,14.76057 0.91317,23.27473 1.34954,8.51418 4.83074,17.27506 13.18427,24.5044 z"
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#linearGradient4271);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
style="display:inline"
|
||||||
|
id="g4533-2"
|
||||||
|
transform="matrix(-0.60102903,0.32221978,0.53870829,0.77401445,526.12645,47.501077)" />
|
||||||
|
<g
|
||||||
|
style="opacity:1"
|
||||||
|
transform="matrix(-0.32879267,0.17361606,0.20143296,0.28338802,143.13323,319.59452)"
|
||||||
|
id="g4404">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sssssssssssssssss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path4406"
|
||||||
|
d="m -626.54672,402.3529 c 2.22767,10.86299 0.34493,21.82632 -3.86747,31.42527 -4.21252,9.59894 -10.55173,17.86115 -17.72096,24.29983 -7.1694,6.43883 -15.25476,11.10591 -24.5716,13.61353 -9.31698,2.50761 -20.94966,4.46936 -31.63903,1.98398 -10.68939,-2.48537 -18.0688,-9.22838 -24.09401,-15.89285 -6.02508,-6.66442 -12.35923,-14.47524 -22.96531,-22.06805 -10.60584,-7.59266 -20.8648,-15.59839 -25.16123,-23.3775 -4.29632,-7.77931 -7.008,-15.66934 -7.81517,-23.39095 -0.80717,-7.7215 0.35908,-14.55922 3.12288,-20.54462 2.76393,-5.98548 7.12557,-11.1208 12.7854,-15.40902 5.65998,-4.28811 12.61751,-7.73606 20.64204,-10.24271 8.02465,-2.50651 17.11262,-4.07552 27.13941,-4.41504 10.0268,-0.3395 20.06604,0.59388 29.76158,2.87504 9.69543,2.2813 19.05511,5.92037 27.47739,11.02309 8.42215,5.10286 15.89307,11.69212 21.60465,19.6287 5.71147,7.93674 13.0738,19.62846 15.30143,30.4913 z"
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#gopher-body);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="csssccscsccscscccsccscsssscscscc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path4408"
|
||||||
|
d="m -784.21409,457.33922 c -0.56136,0.0656 -1.08141,0.1809 -1.55606,0.33615 -0.63289,0.20699 -1.18396,0.48516 -1.6349,0.82686 -0.45093,0.3417 -0.80184,0.74659 -1.02778,1.21891 -0.22595,0.47234 -0.32669,1.01119 -0.27449,1.62035 0.0522,0.60917 0.25282,1.23371 0.57968,1.84938 0.32687,0.61567 0.98957,1.25218 1.83531,1.84156 0.84574,0.58937 1.35671,1.20529 1.82543,1.72857 0.46713,0.52147 1.13451,0.85371 2.02424,0.92674 0.10253,0.008 0.12328,-0.30471 0.0344,-0.32876 -0.78083,-0.20262 -1.25826,-0.72023 -1.71877,-1.11076 -0.4254,-0.46645 -0.87231,-1.01406 -1.62104,-1.54604 -0.74871,-0.53197 -1.47289,-1.09304 -1.77689,-1.63886 -0.30398,-0.54584 -0.49685,-1.10009 -0.55469,-1.64239 -0.0579,-0.54231 0.0245,-1.0222 0.21918,-1.44322 0.19469,-0.42103 0.50198,-0.78371 0.90168,-1.08623 0.39973,-0.30252 0.89062,-0.54587 1.4577,-0.7237 0.28355,-0.0889 0.5872,-0.16119 0.90722,-0.21465 0.32002,-0.0535 0.6576,-0.0885 1.01178,-0.10163 0.70839,-0.0255 1.4163,0.0392 2.10043,0.1987 0.68412,0.15947 1.34499,0.41522 1.93838,0.77329 0.59338,0.35806 1.11885,0.81986 1.52108,1.37653 0.40222,0.55667 0.92117,1.37523 1.07925,2.13677 0.12981,0.62539 0.0734,1.25844 -0.13288,1.83379 -0.0385,0.10712 0.4977,0.29416 0.62787,-0.0111 0.24265,-0.5698 0.23445,-1.24057 0.1026,-1.8741 -0.17834,-0.85666 -0.69031,-1.76937 -1.13671,-2.40019 -0.4464,-0.6308 -1.03123,-1.15292 -1.68895,-1.55276 -0.65772,-0.39984 -1.38674,-0.68003 -2.14271,-0.85021 -0.75599,-0.17016 -1.54036,-0.23166 -2.32498,-0.19142 -0.19617,0.0101 -0.38815,0.0268 -0.57528,0.0484 z"
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#gopher-lines);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
transform="matrix(13.851095,0,0,13.851095,10133.213,-6001.611)" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#gopher-lines);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m -753.77185,413.0219 c -0.13663,-2.61847 2.18018,-4.94804 7.2193,-6.20054 7.65443,-1.90257 20.03831,1.84566 27.93811,5.67152 4.33357,2.09883 8.88981,3.89076 12.66635,7.19411 1.28185,1.12133 2.51799,2.28349 3.36855,4.40869 -1.65849,0.577 -4.10492,-0.92134 -5.87278,-2.13046 -6.96771,-4.76531 -14.69502,-8.08983 -22.67695,-9.12646 -6.71591,-0.87187 -8.86923,-3.11022 -14.75541,-2.56175 -3.72583,0.34716 -4.90626,2.13878 -7.88716,2.74489 z"
|
||||||
|
id="path4365-1-2"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cssscsssc" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#gopher-lines);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m -720.16989,411.68353 c 0.28532,-2.32502 0.86962,3.90377 -0.31886,5.45995 -4.46007,5.84 -8.20289,12.32072 -12.42083,18.36519 -1.37385,1.96787 -3.29463,0.0414 -2.42738,-2.09874 0.88118,-2.1739 2.06053,-3.99898 3.34915,-5.8153 1.20809,-1.70147 2.81353,-3.0576 3.88834,-4.85958 2.06619,-3.46267 2.39577,-6.62873 4.25443,-10.2393 0.63712,-1.23818 3.5225,0.42546 3.67386,-0.80905 z"
|
||||||
|
id="path4367-9-2"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="sssssssss" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
style="display:inline;opacity:1"
|
||||||
|
id="g4198"
|
||||||
|
transform="matrix(0.69027452,0,0,0.73815345,642.18876,259.65104)">
|
||||||
|
<path
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#gopher-lines);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m -140.71724,398.66408 c -9.31409,71.69689 -25.7611,141.32 -83.87724,188.8641 -73.31672,59.97949 -208.09131,67.90599 -303.42706,10.99618 -27.57065,-16.45805 -49.52457,-62.17665 -53.04177,-91.74122 -7.35191,-61.79791 19.82699,-103.64945 13.47928,-160.67805 -5.05249,-45.39216 -29.63784,-82.95495 -27.30836,-137.00138 1.56315,-36.26681 11.06536,-78.46439 40.50727,-100.88356 38.57103,-29.370718 83.60539,-46.188952 134.68095,-45.031125 72.73731,1.648875 151.17838,6.326503 212.18714,49.939365 43.544,31.12796 68.50323,82.53699 72.90385,135.3004 4.52019,54.19698 -0.16075,104.48555 -6.10406,150.23529 z"
|
||||||
|
id="path4188"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="sssssssssss" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#linearGradient4336);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m -158.93683,464.92976 c -15.56115,65.9367 -58.42288,127.39267 -134.42207,151.72082 -70.61462,22.6045 -163.49236,17.29949 -232.18476,-25.54762 -26.14623,-16.30879 -46.09162,-61.46233 -48.95901,-89.47579 -6.03547,-58.9646 19.04741,-102.17429 13.30293,-156.59502 -4.7951,-45.42661 -28.02123,-78.34585 -27.29597,-132.22289 0.47399,-35.21112 8.99044,-76.95773 37.82112,-98.79995 36.52466,-27.671205 78.3526,-45.238515 126.45621,-45.012482 76.22124,0.358155 162.16208,5.533182 222.84373,56.658952 55.47879,46.74224 63.38318,129.04796 60.81019,193.3049 -2.12217,52.99813 -7.67242,100.63054 -18.37237,145.96908 z"
|
||||||
|
id="ellipse4190"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="sssssssssss" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g4376"
|
||||||
|
transform="matrix(0.40138799,-0.13710458,0.13710458,0.40138799,470.81791,82.723801)"
|
||||||
|
style="opacity:1">
|
||||||
|
<path
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#gopher-body);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m -626.57295,401.69566 c 2.24713,11.35067 0.36741,22.38948 -3.843,32.03835 -4.21053,9.64886 -10.54997,17.90531 -17.7192,24.34399 -7.1694,6.43883 -15.25457,11.1106 -24.57171,13.61082 -9.31727,2.5002 -20.94956,4.47176 -31.64526,1.82793 -10.69571,-2.64383 -18.09209,-9.81214 -24.14818,-17.25062 -6.05597,-7.43843 -12.44269,-16.56671 -23.09665,-25.35944 -10.65372,-8.79255 -20.95218,-17.78817 -25.30072,-26.87318 -4.34843,-9.08528 -7.1154,-18.36084 -7.98,-27.52156 -0.86459,-9.1606 0.24716,-17.36404 2.9617,-24.58398 2.71467,-7.22004 7.03243,-13.45488 12.66059,-18.5369 5.6283,-5.08191 12.56665,-9.01064 20.59229,-11.48936 8.02576,-2.47858 17.13537,-3.50537 27.20916,-2.66707 10.0738,0.83832 20.1809,3.47234 29.95223,7.6529 9.77122,4.18068 19.21426,9.9086 27.71179,16.89733 8.49741,6.98886 16.03465,15.24007 21.79567,24.41557 5.7609,9.17565 13.1742,22.14471 15.42129,33.49522 z"
|
||||||
|
id="path4398"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="sssssssssssssssss" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#gopher-lines);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m -784.27135,455.90422 c -0.56339,0.0147 -1.08437,0.10666 -1.55902,0.26191 -0.63289,0.20699 -1.18231,0.52669 -1.63059,0.93484 -0.44828,0.40815 -0.79558,0.90361 -1.01756,1.4752 -0.22199,0.5716 -0.31844,1.21792 -0.26185,1.93717 0.0566,0.71926 0.26134,1.4471 0.59196,2.157 0.33063,0.7099 0.99621,1.41858 1.84494,2.08284 0.84872,0.66425 1.36325,1.36931 1.83382,1.93901 0.46898,0.56774 1.13678,0.9105 2.02675,0.98962 0.10256,0.009 0.12294,-0.31321 0.034,-0.33899 -0.78143,-0.21746 -1.26048,-0.77583 -1.72293,-1.21489 -0.42768,-0.5236 -0.87838,-1.16625 -1.63058,-1.78505 -0.75217,-0.61879 -1.47924,-1.25213 -1.78697,-1.89162 -0.30772,-0.63951 -0.50455,-1.29287 -0.56648,-1.9378 -0.062,-0.64492 0.0165,-1.22191 0.20772,-1.73042 0.1912,-0.50852 0.49539,-0.94884 0.89287,-1.30706 0.3975,-0.35822 0.88707,-0.63484 1.45426,-0.80994 0.2836,-0.0875 0.58767,-0.1494 0.90851,-0.1822 0.32084,-0.0328 0.65966,-0.0369 1.01552,-0.008 0.71174,0.0585 1.42446,0.24383 2.11396,0.53794 0.6895,0.29412 1.35628,0.69807 1.95502,1.19025 0.59873,0.49218 1.12894,1.07271 1.53474,1.71893 0.4058,0.64623 0.9285,1.5589 1.08808,2.35795 0.13104,0.65619 0.075,1.29927 -0.13103,1.88026 -0.0384,0.10817 0.49808,0.30362 0.62824,-0.002 0.24262,-0.57052 0.23429,-1.24452 0.10166,-1.89748 -0.17938,-0.88293 -0.69436,-1.871 -1.14416,-2.58711 -0.44981,-0.71609 -1.03943,-1.35821 -1.70275,-1.89855 -0.66333,-0.54034 -1.3987,-0.97968 -2.16052,-1.29649 -0.76184,-0.31679 -1.55154,-0.51173 -2.33984,-0.56369 -0.19709,-0.013 -0.38986,-0.0163 -0.57767,-0.0116 z"
|
||||||
|
id="path4369"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="csssccscsccscscccsccscsssscscscc"
|
||||||
|
transform="matrix(13.851095,0,0,13.851095,10133.213,-6001.611)" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#gopher-lines);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m -730.27274,382.91266 c 1.8068,-2.76405 6.31309,-3.63001 13.24575,-1.6171 10.53068,3.05761 22.43414,14.97755 28.94834,24.04709 3.57338,4.97534 7.6424,9.78266 9.64772,15.62449 0.68055,1.98294 1.27611,3.97774 0.68898,6.70435 -2.4056,-0.49416 -4.1871,-3.62313 -5.37952,-6.01329 -4.69962,-9.4202 -11.38574,-17.86492 -20.09536,-24.13889 -7.3284,-5.27852 -8.20487,-8.9719 -15.61502,-12.25742 -4.69053,-2.07967 -7.44128,-1.02076 -11.44089,-2.34923 z"
|
||||||
|
id="path4365-1"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cssscsssc" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#gopher-lines);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m -689.31909,403.49962 c 2.08771,-2.1886 -1.9021,4.5559 -4.48533,5.36905 -9.69439,3.05157 -19.01784,7.22624 -28.57811,10.64488 -3.11327,1.11257 -3.94795,-2.11026 -1.30738,-3.72982 2.68251,-1.64492 5.45711,-2.73872 8.35507,-3.75217 2.71578,-0.94874 5.64428,-1.2851 8.27731,-2.4236 5.06052,-2.18718 7.83343,-5.20599 12.75841,-7.67984 1.68866,-0.84854 3.86766,2.73608 4.97603,1.5739 z"
|
||||||
|
id="path4367-9"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="sssssssss" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g4634"
|
||||||
|
transform="matrix(0.13058783,-0.42795023,-0.60869797,-0.11092817,632.15501,956.21909)"
|
||||||
|
style="display:inline;opacity:1">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sssssssssssssssss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path4636"
|
||||||
|
d="m 423.50332,581.83521 c -0.004,4.40048 -1.19837,7.58856 -3.37524,9.82844 -2.17687,2.23987 -5.33154,3.55156 -9.14619,4.44292 -3.81465,0.89135 -8.28246,1.39523 -13.05675,1.83828 -4.77428,0.44304 -9.85163,0.79076 -14.95001,1.09928 -5.09838,0.30851 -9.94541,0.34741 -14.40217,0.0862 -4.45676,-0.26122 -8.52354,-0.79908 -11.99271,-1.71189 -3.46915,-0.91282 -6.33736,-2.21356 -8.3562,-4.09288 -2.01885,-1.87935 -3.18709,-4.34475 -3.25466,-7.51083 -0.0676,-3.16607 0.9983,-5.4859 2.92534,-7.0838 1.92703,-1.5979 4.71248,-2.46394 8.09977,-2.84688 3.38729,-0.38293 7.37282,-0.28336 11.77044,-0.16051 4.39762,0.12284 9.21051,0.23456 14.33166,-0.12202 5.12115,-0.35659 10.27171,-1.47349 15.16022,-2.54099 4.88852,-1.06749 9.50395,-2.05149 13.43823,-2.27114 3.9343,-0.21967 7.17754,0.32322 9.39823,2.04598 2.22069,1.72276 3.41425,4.59936 3.41004,8.99986 z"
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#linearGradient4279);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="csscsscssssssssssssssssssssccsssc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path4638"
|
||||||
|
d="m 411.91406,568.54883 c -3.75011,-0.0271 -8.08701,0.53975 -12.76172,1.28711 -5.34251,0.85413 -11.10706,1.92059 -17.00976,2.32617 -5.9027,0.40562 -11.41103,0.38326 -16.44727,0.41406 -5.03624,0.0309 -9.6045,0.1607 -13.50781,0.85938 -3.9033,0.69867 -7.13503,1.96743 -9.4082,3.96875 -2.27316,2.00131 -3.58535,4.71676 -3.65235,8.17578 -0.067,3.45901 1.21821,6.3073 3.54297,8.58008 2.32476,2.27278 5.68789,3.9795 9.76172,5.25 4.07385,1.27051 8.85237,2.11894 14.05664,2.59765 5.20427,0.47871 10.83381,0.56134 16.70313,0.22266 5.86931,-0.33868 11.47146,-0.78653 16.60547,-1.34961 5.13399,-0.56309 9.79334,-1.22365 13.70703,-2.34375 1.48913,-0.4262 2.86677,-0.9287 4.12695,-1.51953 2.54507,-1.19325 2.05015,-6.17249 -0.0996,-4.54102 -1.99172,1.51153 -4.14364,1.68162 -7.15735,2.35061 -3.67269,0.81527 -8.18136,0.99111 -12.55008,1.3428 -4.3687,0.35167 -8.7789,1.78431 -13.31332,2.07736 -4.53444,0.29304 -8.86787,0.32801 -12.93181,0.0702 -4.06396,-0.25785 -7.85651,-0.78075 -11.12475,-1.64296 -3.26823,-0.86221 -5.99695,-2.08037 -7.8846,-3.81399 -1.88765,-1.73365 -2.92537,-3.9871 -2.97865,-6.80086 -0.0533,-2.81374 0.90176,-4.8192 2.66881,-6.10562 1.76704,-1.28641 5.61732,-0.58475 8.69196,-0.71399 3.07463,-0.12925 6.90624,-0.54484 10.78772,-0.41733 3.88147,0.12754 6.54592,-0.48119 11.04844,-1.2139 4.50252,-0.73264 9.15212,-2.3434 13.88736,-3.72101 4.73523,-1.37761 9.22461,-2.34259 13.00861,-2.55385 0.473,-0.0264 0.93707,-0.0422 1.38868,-0.0449 1.16046,-0.007 2.25007,0.0442 3.25,0.23633 1.15313,0.22156 2.31543,-2.86146 -0.83789,-2.92773 -0.51177,-0.0108 -1.03459,-0.045 -1.57032,-0.0488 z"
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#gopher-lines);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer9"
|
||||||
|
inkscape:label="gopher-shadow"
|
||||||
|
style="display:inline;opacity:0.06000001"
|
||||||
|
sodipodi:insensitive="true"
|
||||||
|
transform="translate(-15.732722,-256.54886)">
|
||||||
|
<ellipse
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
id="path4544"
|
||||||
|
cx="-467.52527"
|
||||||
|
cy="482.66467"
|
||||||
|
rx="22.450642"
|
||||||
|
ry="20.682871"
|
||||||
|
transform="scale(-1,1)" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 234.60547,309.98047 c -6.62163,-0.0703 -10.7426,0.83465 -15.61133,3.26758 -5.0378,2.51742 -10.044,7.91661 -11.55273,12.45898 -2.26972,6.83348 -0.42196,14.92592 5.01757,21.97656 3.19606,4.1427 6.84938,6.56071 14.60938,9.66993 3.20846,1.28553 7.68985,3.50108 9.95898,4.92382 5.6211,3.52442 9.83526,5.31873 13.54102,5.76563 2.42194,0.29208 3.11523,0.63719 3.11523,1.55469 0,0.89182 -0.7061,1.28567 -2.89062,1.61328 -1.58919,0.23867 -3.77121,0.24076 -4.84961,0.004 -1.95019,-0.42833 -1.9703,-0.40483 -3.65625,4.68555 -3.87667,11.7048 -5.82609,25.85658 -5.80859,42.15625 0.0196,18.31899 1.82597,28.89111 9.58007,56.04688 5.56137,19.47655 7.15656,26.40249 8.58008,37.26171 2.05331,15.66359 1.31467,26.60445 -3.90625,57.79102 -4.8641,29.05517 -5.15869,31.69637 -5.18359,46.54297 -0.0239,14.28001 0.63486,19.84952 3.52539,29.8125 5.44577,18.77032 13.72789,34.11825 23.9082,44.30078 8.00321,8.00498 22.62783,16.26261 41.23438,23.2832 5.47456,2.06566 5.83617,2.12101 6.46679,0.99414 1.72277,-3.07839 3.2087,-3.7772 9.33203,-3.79882 -38.68101,-33.75954 -34.48259,-82.29367 -25.52281,-108.9339 7.33431,-21.80723 31.77025,-53.23407 31.77025,-53.23407 l -22.41052,-1.98245 c 0,0 -7.25969,-42.63753 -13.15682,-59.9065 -22.58603,-66.14023 -29.82384,-120.35922 4.37069,-158.19894 5.84309,-6.46598 12.5988,-11.21335 19.60937,-14.69727 -9.02679,1.89877 -18.30173,4.80561 -26.41601,8.32813 -6.65247,2.88791 -19.01394,9.90994 -18.99415,10.78906 0.009,0.39075 0.30731,1.97487 0.66407,3.52148 0.79845,3.46141 -0.0807,5.55969 -2.20117,5.25782 -1.1871,-0.16901 -1.49742,-0.76108 -1.83008,-3.48633 -0.63121,-5.17109 -3.20076,-9.39815 -9.06836,-14.91797 -9.25402,-8.70552 -17.29671,-12.21829 -29.22461,-12.76172 -1.05756,-0.0482 -2.05405,-0.0778 -3,-0.0879 z m 1.38086,24.10156 c 1.88404,0.0642 3.99413,0.41696 5.88476,1.04492 3.99187,1.32589 12.35644,6.69047 14.31446,9.17969 3.00519,3.82048 1.04901,4.01008 -3.4043,0.33008 -1.74522,-1.44216 -3.36983,-2.6211 -3.60937,-2.6211 -0.23954,0 -2.78812,1.91597 -5.66407,4.25782 -2.87594,2.34185 -5.59815,4.25776 -6.04883,4.25976 -1.88842,0.007 -0.56519,-2.08264 3.10938,-4.91015 4.64288,-3.57262 5.88952,-5.38766 4.12891,-6.00977 -0.64649,-0.22845 -2.92374,-1.13445 -5.06055,-2.01367 -3.0123,-1.23949 -4.52138,-1.50334 -6.71875,-1.17383 -3.06661,0.45987 -3.82178,-0.39095 -1.46485,-1.65234 0.9899,-0.52978 2.64916,-0.75563 4.53321,-0.69141 z m 103.78515,383.73633 c -0.005,0.0152 -0.007,0.0256 -0.0117,0.041 l -0.70118,2.28906 5.65625,1.01562 c 0.0901,0.0162 0.20551,0.0326 0.29688,0.0488 -1.81728,-1.11236 -3.56263,-2.24473 -5.24024,-3.39453 z"
|
||||||
|
id="path4271"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="sssssssscssssssssssscsccsscscssssssscsssscscsssscccccccc" />
|
||||||
|
<path
|
||||||
|
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 328.4205,548.25967 -4.47623,14.88037 c 2.60939,0.0254 9.84161,-6.41982 16.75619,-6.818 76.94638,-4.43102 125.04829,-0.40565 187.26295,-5.40532 1.45456,-0.11689 3.76527,-0.10936 5.20677,0.2079 5.21485,1.14773 8.09003,14.3736 9.3628,13.60525 0.6055,-14.12878 -2.32372,-19.14168 -5.81784,-22.69773 z"
|
||||||
|
id="path4275"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccsssccc" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer2"
|
||||||
|
inkscape:label="gopher-face"
|
||||||
|
style="display:inline"
|
||||||
|
sodipodi:insensitive="true"
|
||||||
|
transform="translate(-15.732722,-256.54886)">
|
||||||
|
<g
|
||||||
|
id="g4818"
|
||||||
|
transform="matrix(-0.65610141,0,0,0.65610141,655.70091,210.42145)">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sssssssssssssssss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path4812"
|
||||||
|
d="m 547.42756,318.16456 c -0.44046,14.77191 -4.12869,29.02667 -10.38967,42.25266 -6.26099,13.22599 -15.09198,25.42687 -25.80466,35.99686 -10.71268,10.57 -23.30432,19.50822 -37.11826,26.08983 -13.81394,6.58161 -28.85103,10.80263 -44.50193,11.8618 -15.65091,1.05917 -30.4406,-1.15844 -43.81781,-6.16756 -13.37721,-5.00911 -25.3405,-12.8075 -35.30087,-22.80416 -9.96037,-9.99666 -17.91599,-22.19037 -23.26581,-35.90798 -5.34983,-13.71761 -8.0915,-28.95913 -7.64195,-44.98105 0.44955,-16.02192 4.04447,-31.2937 10.1422,-45.07896 6.09773,-13.78526 14.69591,-26.08175 25.16951,-36.25747 10.4736,-10.17571 22.82245,-18.23043 36.46168,-23.66123 13.63924,-5.4308 28.57214,-8.24285 44.22923,-8.02541 15.6571,0.21745 30.56095,3.42714 44.11009,8.94154 13.54914,5.5144 25.7404,13.33722 35.92568,22.91495 10.18529,9.57774 18.36233,20.91345 23.87736,33.53282 5.51504,12.61936 8.36566,26.52144 7.92521,41.29336 z"
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#gopher-lines);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sssssssssssssssss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="ellipse4814"
|
||||||
|
d="m 539.72249,314.79002 c 10e-4,13.89984 -3.01572,27.53808 -8.51346,40.35257 -5.49774,12.81449 -13.48047,24.80543 -23.37659,35.2527 -9.89612,10.44726 -21.70519,19.34133 -34.78531,25.87862 -13.08011,6.53727 -27.4256,10.71236 -42.3773,11.7667 -14.9517,1.05435 -29.09103,-1.11258 -41.85904,-5.93108 -12.76803,-4.81852 -24.16883,-12.28715 -33.66552,-21.79076 -9.49671,-9.50362 -17.08979,-21.04298 -22.23241,-33.95465 -5.14261,-12.91166 -7.83328,-27.19561 -7.52333,-42.13595 0.30995,-14.94034 3.58995,-29.10832 9.22975,-41.85842 5.63981,-12.7501 13.63743,-24.08168 23.39638,-33.47108 9.75897,-9.38941 21.27795,-16.83842 34.00359,-21.94183 12.72563,-5.10342 26.66067,-7.86812 41.28534,-7.94317 14.62467,-0.0751 28.55938,2.53224 41.26083,7.24431 12.70145,4.71207 24.16709,11.5339 33.81555,20.03646 9.64847,8.50257 17.47884,18.68937 22.90117,30.21241 5.42232,11.52304 8.43889,24.38332 8.44035,38.28317 z"
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#gopher-eye);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||||
|
<circle
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#linearGradient4319);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
id="path4828"
|
||||||
|
cx="458.07443"
|
||||||
|
cy="316.13431"
|
||||||
|
r="30.809652" />
|
||||||
|
<circle
|
||||||
|
r="15.152287"
|
||||||
|
cy="301.99216"
|
||||||
|
cx="444.43738"
|
||||||
|
id="circle4830"
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#gopher-eye);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(-0.49821858,-0.255998,-0.255998,0.49821858,841.05915,359.59091)"
|
||||||
|
id="g4822">
|
||||||
|
<path
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#gopher-lines);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 544.2609,323.96628 c -5.95391,12.33766 -15.20034,24.2228 -25.89846,35.91934 -10.69814,11.69654 -22.74349,23.28172 -34.52447,34.21851 -11.78099,10.93679 -23.27607,21.15489 -34.23709,29.30247 -10.96102,8.14759 -21.47285,14.18083 -32.04267,16.95199 -10.56982,2.77117 -20.29711,2.02561 -29.30402,-1.67713 -9.00692,-3.70274 -20.58076,-7.76561 -27.66538,-16.71749 -7.08461,-8.95188 -12.84054,-20.18257 -16.5035,-33.03389 -3.66297,-12.85133 -5.229,-27.32914 -3.92417,-42.72858 1.30484,-15.39944 5.36688,-30.24976 11.81788,-43.75488 6.45101,-13.5051 15.29008,-25.65823 26.00811,-35.78271 10.71803,-10.12447 28.44246,-20.29305 42.24879,-25.86698 13.80633,-5.57394 28.83304,-8.62768 44.20973,-8.80364 15.3767,-0.17594 29.62737,2.52591 41.94358,7.37479 12.31622,4.84887 22.69735,11.85058 30.35956,20.34718 7.66222,8.49661 12.60139,18.48263 14.06496,29.34879 1.4636,10.86615 -0.59894,22.56457 -6.55285,34.90223 z"
|
||||||
|
id="path4824"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="sssssssssssssssss" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 538.18032,322.65868 c -5.17728,11.63182 -13.27733,23.10077 -22.96883,34.40428 -9.69151,11.30351 -20.93897,22.46482 -32.34413,32.7753 -11.40514,10.31051 -22.90789,19.71873 -33.85893,27.13351 -10.95103,7.41476 -21.39599,12.82014 -31.59528,15.28718 -10.19931,2.46703 -19.30202,1.76338 -27.56839,-1.62958 -8.26637,-3.39295 -19.13397,-6.9512 -25.3913,-15.16185 -6.25732,-8.21068 -11.24381,-18.53447 -14.30417,-30.37519 -3.06035,-11.84072 -4.18965,-25.20221 -2.68634,-39.42576 1.5033,-14.22354 5.50837,-27.94818 11.67956,-40.43838 6.17119,-12.4902 14.50792,-23.74111 24.54768,-33.13895 10.03978,-9.39782 26.99021,-19.0621 39.83566,-24.2929 12.84546,-5.2308 26.78412,-8.15811 41.0009,-8.45853 14.21678,-0.30038 27.34319,2.03758 38.64284,6.33106 11.29965,4.29349 20.7704,10.54463 27.74089,18.16875 6.97048,7.62413 11.43794,16.6127 12.81335,26.51165 1.37541,9.89894 -0.36624,20.67759 -5.54351,32.30941 z"
|
||||||
|
id="path4826"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="sssssssssssssssss" />
|
||||||
|
<circle
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#linearGradient4321);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
id="path4828-0"
|
||||||
|
cx="438.70038"
|
||||||
|
cy="219.30804"
|
||||||
|
r="27.721321"
|
||||||
|
transform="matrix(0.98640333,0.16434257,-0.16434257,0.98640333,0,0)" />
|
||||||
|
<circle
|
||||||
|
r="13.633434"
|
||||||
|
cy="205.95601"
|
||||||
|
cx="431.24106"
|
||||||
|
id="circle4830-3"
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
transform="matrix(0.98640333,0.16434257,-0.16434257,0.98640333,0,0)" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer7"
|
||||||
|
inkscape:label="gopher-mouth"
|
||||||
|
style="display:inline"
|
||||||
|
sodipodi:insensitive="true"
|
||||||
|
transform="translate(-15.732722,-256.54886)">
|
||||||
|
<path
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 477.59321,477.72343 -6.36763,0.0828 -3.71113,-0.0821 c -1.18372,-0.0262 -2.23819,0.53559 -3.00662,1.36379 -0.76845,0.82822 -1.14658,1.97521 -1.32551,3.22687 l -1.01303,7.08562 -1.40711,7.111 c -0.25342,1.28069 0.0841,2.40965 0.70518,3.23132 0.6211,0.82165 1.57363,1.28978 2.69674,1.31649 l 3.7446,0.0891 7.40657,-0.17258 c 1.42055,-0.0331 2.74014,-0.58514 3.70785,-1.43299 0.96771,-0.84787 1.54004,-2.00084 1.65553,-3.2592 l 0.6476,-7.05621 0.52522,-7.04505 c 0.0935,-1.25398 -0.46676,-2.37726 -1.25366,-3.18163 -0.78689,-0.80437 -1.85738,-1.2842 -3.00457,-1.27716 z"
|
||||||
|
id="rect4659"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="scssscssscssscsss" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 476.43064,479.86835 -5.19684,0.0698 -2.47497,-0.10149 c -0.94018,-0.0386 -1.80825,0.43586 -2.46124,1.11384 -0.65298,0.67797 -1.03424,1.61771 -1.21175,2.64338 l -1.0026,5.79325 -1.25494,5.80832 c -0.22406,1.03701 0.002,1.97056 0.48938,2.64162 0.48783,0.67105 1.26653,1.03411 2.19892,1.07115 l 2.54193,0.101 5.88547,-0.12754 c 1.11447,-0.0242 2.17518,-0.47212 2.97321,-1.1643 0.79803,-0.69218 1.30904,-1.6349 1.43939,-2.66511 l 0.73009,-5.77006 0.63032,-5.76301 c 0.11259,-1.02637 -0.28558,-1.94744 -0.89178,-2.6062 -0.60618,-0.65877 -1.45658,-1.05733 -2.39458,-1.04471 z"
|
||||||
|
id="rect4661"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="scssscssscssscsss" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#gopher-lines);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 447.45177,471.71537 c 0.17729,2.27145 1.57656,4.32647 3.56538,6.17684 1.98881,1.85037 4.73553,3.49055 7.9169,4.83408 3.18137,1.34353 6.76993,2.37673 10.40491,2.92876 3.63499,0.55204 7.31771,0.61337 10.93742,0.17695 3.61969,-0.43645 6.8614,-1.30517 9.67542,-2.37849 2.81402,-1.07332 5.17844,-2.3467 7.04073,-3.75925 1.86231,-1.41254 3.23922,-2.97722 4.10853,-4.72358 0.86932,-1.74636 1.22997,-3.67959 0.91461,-5.76285 -0.31535,-2.08326 -1.29186,-4.11481 -2.79935,-5.98131 -1.5075,-1.86649 -3.53491,-3.56576 -5.91642,-4.97983 -2.3815,-1.41407 -5.11304,-2.54212 -8.12844,-3.28158 -3.0154,-0.73946 -6.31783,-1.09096 -9.93094,-0.97174 -3.6131,0.11924 -7.2186,0.69446 -10.6419,1.64517 -3.4233,0.95069 -6.6496,2.2832 -9.33875,3.91065 -2.68913,1.62746 -4.89892,3.50256 -6.18894,5.61926 -1.32139,2.16817 -1.77021,4.61153 -1.61916,6.54692 z"
|
||||||
|
id="ellipse4650"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="sssssssssssssssss" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#linearGradient4265);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 455.1011,471.20532 c 0.31019,1.80429 1.36577,3.48937 2.98663,4.99917 1.62086,1.5098 3.80505,2.84719 6.28703,3.91437 2.48197,1.06719 5.24944,1.8562 8.07117,2.27071 2.82174,0.4145 5.70079,0.45265 8.53169,0.10713 2.83089,-0.34553 5.35911,-1.02976 7.553,-1.90451 2.19389,-0.87475 4.04484,-1.93848 5.497,-3.12538 1.45217,-1.1869 2.50911,-2.50179 3.13219,-3.93394 0.62308,-1.43214 0.81446,-2.98543 0.48985,-4.63056 -0.32461,-1.64514 -1.13916,-3.22548 -2.3414,-4.6674 -1.20224,-1.44192 -2.78948,-2.74346 -4.65903,-3.82078 -1.86955,-1.07733 -4.01937,-1.92982 -6.38974,-2.4811 -2.37037,-0.55129 -4.96168,-0.80162 -7.76722,-0.68542 -2.80553,0.11621 -5.57317,0.58631 -8.1874,1.34158 -2.61424,0.75528 -5.07126,1.79757 -7.14628,3.06167 -2.07504,1.26412 -3.75959,2.75051 -4.8326,4.37276 -1.07302,1.62225 -1.53509,3.37741 -1.22489,5.1817 z"
|
||||||
|
id="ellipse4652"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="sssssssssssssssss" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#gopher-lines);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 465.13937,460.19393 c 0.45232,1.29294 1.43586,2.44115 2.79664,3.4102 1.36078,0.96906 3.0934,1.76079 4.97332,2.36791 1.87992,0.60712 3.89927,1.0315 5.87533,1.25741 1.97606,0.2259 3.90879,0.25223 5.71982,0.052 1.81102,-0.20028 3.33955,-0.60742 4.63321,-1.17435 1.29367,-0.56695 2.35232,-1.29343 3.18646,-2.14861 0.83413,-0.85519 1.44471,-1.8405 1.79916,-2.93195 0.35445,-1.09146 0.45213,-2.29028 0.21175,-3.55738 -0.24038,-1.2671 -0.80099,-2.48156 -1.64917,-3.57911 -0.84818,-1.09755 -1.9831,-2.07741 -3.35494,-2.8723 -1.37184,-0.7949 -2.98056,-1.40441 -4.76729,-1.7664 -1.78672,-0.36199 -3.75169,-0.47615 -5.82322,-0.29097 -2.07153,0.18518 -4.05358,0.65136 -5.84566,1.3298 -1.79207,0.67844 -3.39432,1.56902 -4.69144,2.60198 -1.29713,1.03296 -2.28898,2.20893 -2.84443,3.45293 -0.55546,1.24399 -0.67186,2.55593 -0.21954,3.84888 z"
|
||||||
|
id="path4648"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="sssssssssssssssss" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer12"
|
||||||
|
inkscape:label="gopher-hands"
|
||||||
|
style="display:inline"
|
||||||
|
sodipodi:insensitive="true"
|
||||||
|
transform="translate(-15.732722,-256.54886)">
|
||||||
|
<g
|
||||||
|
id="g4533"
|
||||||
|
transform="matrix(-0.28489616,-0.34500545,-0.42832103,0.44649678,715.99765,474.46827)">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sssssssssssssssss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="ellipse4523"
|
||||||
|
d="m 423.50332,581.83521 c -0.004,4.40048 -1.19837,7.58856 -3.37524,9.82844 -2.17687,2.23987 -5.33154,3.55156 -9.14619,4.44292 -3.81465,0.89135 -8.28246,1.39523 -13.05675,1.83828 -4.77428,0.44304 -9.85163,0.79076 -14.95001,1.09928 -5.09838,0.30851 -9.94541,0.34741 -14.40217,0.0862 -4.45676,-0.26122 -8.52354,-0.79908 -11.99271,-1.71189 -3.46915,-0.91282 -6.33736,-2.21356 -8.3562,-4.09288 -2.01885,-1.87935 -3.18709,-4.34475 -3.25466,-7.51083 -0.0676,-3.16607 0.9983,-5.4859 2.92534,-7.0838 1.92703,-1.5979 4.71248,-2.46394 8.09977,-2.84688 3.38729,-0.38293 7.37282,-0.28336 11.77044,-0.16051 4.39762,0.12284 9.21051,0.23456 14.33166,-0.12202 5.12115,-0.35659 10.27171,-1.47349 15.16022,-2.54099 4.88852,-1.06749 9.50395,-2.05149 13.43823,-2.27114 3.9343,-0.21967 7.17754,0.32322 9.39823,2.04598 2.22069,1.72276 3.41425,4.59936 3.41004,8.99986 z"
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#linearGradient4273);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ssscsscssssssssssssssssssssccsss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path4521"
|
||||||
|
d="m 411.91406,568.54883 c -3.75011,-0.0271 -8.08701,0.53975 -12.76172,1.28711 -5.34251,0.85413 -11.10706,1.92059 -17.00976,2.32617 -5.9027,0.40562 -11.41103,0.38326 -16.44727,0.41406 -5.03624,0.0309 -9.6045,0.1607 -13.50781,0.85938 -3.9033,0.69867 -7.13503,1.96743 -9.4082,3.96875 -2.27316,2.00131 -3.58535,4.71676 -3.65235,8.17578 -0.067,3.45901 1.21821,6.3073 3.54297,8.58008 2.32476,2.27278 5.68789,3.9795 9.76172,5.25 4.07385,1.27051 8.85237,2.11894 14.05664,2.59765 5.20427,0.47871 10.83381,0.56134 16.70313,0.22266 5.86931,-0.33868 11.47146,-0.78653 16.60547,-1.34961 5.13399,-0.56309 9.79334,-1.22365 13.70703,-2.34375 1.48913,-0.4262 2.86677,-0.9287 4.12695,-1.51953 2.54507,-1.19325 2.05015,-6.17249 -0.0996,-4.54102 -1.99172,1.51153 -4.55969,2.50355 -7.57031,3.20703 -3.66893,0.85731 -7.96668,1.34146 -12.5586,1.76758 -4.59191,0.42612 -9.47527,0.75991 -14.3789,1.05664 -4.90363,0.29673 -9.56506,0.33523 -13.85156,0.084 -4.28652,-0.25124 -8.19851,-0.76855 -11.53516,-1.64649 -3.33664,-0.87795 -6.09539,-2.12996 -8.03711,-3.9375 -1.94173,-1.80756 -3.06587,-4.17751 -3.13086,-7.22265 -0.065,-3.04513 0.96102,-5.2776 2.81445,-6.81446 1.85342,-1.53686 4.53117,-2.36997 7.78907,-2.73828 3.2579,-0.36831 7.09262,-0.27244 11.32226,-0.1543 4.22963,0.11816 8.85767,0.22578 13.7832,-0.11718 4.92553,-0.34297 9.88026,-1.41664 14.58204,-2.44336 4.70178,-1.02671 9.13982,-1.97234 12.92382,-2.1836 0.473,-0.0264 0.93707,-0.0422 1.38868,-0.0449 1.16046,-0.007 2.25007,0.0442 3.25,0.23633 1.15313,0.22156 2.31543,-2.86146 -0.83789,-2.92773 -0.51177,-0.0108 -1.03459,-0.045 -1.57032,-0.0488 z"
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#gopher-lines);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer3"
|
||||||
|
inkscape:label="cape-front"
|
||||||
|
style="display:inline"
|
||||||
|
transform="translate(-15.732722,-256.54886)">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cssscscc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path4248"
|
||||||
|
d="m 250.62773,531.91504 c -9.09672,21.35801 -15.29674,29.07226 -30.27188,44.83759 -11.50237,12.10933 -28.85117,24.46609 -43.81134,39.61682 -13.55246,13.72509 -26.12338,21.00434 -64.22257,32.01103 -11.97434,3.45934 -44.031036,6.55017 -51.472472,37.30246 C 107.21772,654.7909 183.17617,662.32228 228.40418,636.09787 266.34279,614.10005 317.82474,552.6315 355.9453,547.7268 284.49621,547.05928 263.34291,542.49874 250.62773,531.91504 Z"
|
||||||
|
style="display:inline;fill:#019833;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
style="fill:#019833;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 473.29262,543.99873 73.7751,-5.10117 c 0,0 2.29258,1.0455 2.68673,2.11494 7.36409,19.98076 -12.72148,60.84328 -12.72148,60.84328 0,-2.97132 13.53121,-43.94425 -5.91529,-53.46522 -16.4456,-8.05173 -38.16124,-2.06803 -57.82506,-4.39183 z"
|
||||||
|
id="path4265"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccscsc" />
|
||||||
|
<path
|
||||||
|
style="display:inline;fill:#019432;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 249.90625,533.57227 c -8.70868,20.08478 -14.97837,27.83833 -29.55078,43.17968 -11.50237,12.10933 -28.85038,24.46646 -43.81055,39.61719 -13.55246,13.72509 -26.12346,21.00503 -64.22265,32.01172 -10.63128,3.07133 -37.077893,5.86957 -48.087895,27.97656 2.731585,-3.48747 7.206694,-4.8761 9.881319,-8.70029 4.506995,-6.44411 60.824806,-11.61546 75.673426,-21.06752 9.77176,-6.22033 32.61216,-17.69963 44.08393,-25.40211 11.47178,-7.70248 50.16856,-39.82139 59.98047,-41.62695 30.99143,-5.70295 56.04882,-31.95703 56.04882,-31.95703 0,0 -5.76873,-1.34099 -7.30468,-1.69727 -26.4653,-1.9743 -39.57284,-5.58234 -48.29883,-11.28125 -1.77957,-0.42346 -3.78649,-0.89828 -4.39258,-1.05273 z"
|
||||||
|
id="path4280"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cssscsssscccc" />
|
||||||
|
<path
|
||||||
|
style="fill:#01a939;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 250.88543,527.29897 c 4.9284,1.23444 7.57648,5.23948 12.39942,6.83706 14.83134,4.91283 28.22069,8.13985 43.80356,9.2706 19.18619,1.39223 40.09821,1.50171 59.33179,1.15882 36.63136,-0.65304 73.4946,-1.92414 110.08831,-3.70824 19.9513,-0.97271 40.58394,-2.2893 60.49061,-3.94 3.86874,-0.3208 7.97563,-6.05622 11.58825,-4.6353 2.39418,0.94168 2.01049,3.29975 2.64058,5.79412 2.44082,4.93143 0.14511,6.64447 -5.65353,7.64824 -19.43937,3.05253 -39.20884,3.55847 -58.86827,4.40354 -48.01128,2.06378 -96.10464,2.11621 -144.15772,1.62235 -17.00379,-0.17475 -34.11943,0.52285 -50.98827,-1.62235 -13.27515,-1.68819 -26.90453,-3.45163 -39.16825,-8.80707 -4.12399,-1.80091 -7.99437,-2.72852 -8.97266,-7.12095 -0.30759,-1.38101 1.19417,-2.17728 1.88173,-3.29956 0.57446,-0.93767 0.21317,-2.26036 1.23886,-2.84803 1.34064,-0.76812 2.84679,-1.12864 4.34559,-0.75323 z"
|
||||||
|
id="path4267"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="sssssssccssssssss" />
|
||||||
|
<path
|
||||||
|
style="fill:#019d35;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 245.9043,528.82812 c -0.24767,0.63868 -0.21658,1.44068 -0.60352,2.07227 -0.68756,1.12228 -2.18845,1.91782 -1.88086,3.29883 0.97829,4.39243 4.84867,5.32018 8.97266,7.12109 12.26372,5.35544 25.89282,7.11845 39.16797,8.80664 16.86884,2.1452 33.98449,1.4483 50.98828,1.62305 48.05308,0.49386 96.14692,0.44073 144.1582,-1.62305 19.65943,-0.84507 39.42782,-1.34981 58.86719,-4.40234 5.79864,-1.00377 8.09512,-2.71701 5.6543,-7.64844 -0.0557,-0.22031 -0.0962,-0.43699 -0.13868,-0.65429 0.48647,4.64963 -6.66572,4.9037 -11.87478,5.92187 -33.64204,6.57569 -68.48165,3.5437 -102.75586,4.0957 -42.87828,0.69057 -93.34812,6.52037 -135.57053,-0.98242 -17.79033,-3.16129 -43.90403,-10.17243 -54.98437,-17.62891 z"
|
||||||
|
id="path4340"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="csssssscccsssc" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer8"
|
||||||
|
inkscape:label="vim"
|
||||||
|
transform="translate(-15.732722,-256.54886)">
|
||||||
|
<g
|
||||||
|
id="g4330">
|
||||||
|
<rect
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#005d04;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
id="rect4293"
|
||||||
|
width="194.71968"
|
||||||
|
height="194.71968"
|
||||||
|
x="-29.381023"
|
||||||
|
y="744.44128"
|
||||||
|
transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)" />
|
||||||
|
<rect
|
||||||
|
transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)"
|
||||||
|
y="753.35699"
|
||||||
|
x="-20.465342"
|
||||||
|
height="176.88821"
|
||||||
|
width="176.88821"
|
||||||
|
id="rect4283"
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#019833;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||||
|
<g
|
||||||
|
id="text4285"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:203.27047729px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#fefefe;fill-opacity:1;stroke:#005d04;stroke-width:4;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
transform="matrix(1.0880646,0,-0.29154603,1.0880646,-528.83975,-369.0604)">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cccccccccccccccsc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path4324"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-family:Eczar;-inkscape-font-specification:'Eczar Ultra-Bold';fill:#fefefe;fill-opacity:1;stroke:#005d04;stroke-width:5.01092911;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 202.34975,1029.0537 -56.02157,-157.11507 -17.82505,-3.05571 0.25466,-14.0054 89.88914,0 1.52787,8.1486 c -2.7162,2.2069 -5.77193,4.32893 -9.16717,6.36609 -3.22549,2.03714 -6.70561,3.98941 -10.44038,5.85679 l 26.38345,87.17129 39.56921,-89.71773 -21.89934,-3.81964 0.25464,-14.0054 72.06411,0 -68.4991,168.82868 0.25465,0.2547 c -6.28122,1.0184 -13.49612,1.9522 -21.6447,2.8011 -8.14859,0.8487 -16.38207,1.6126 -24.70042,2.2917 z" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<use
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
xlink:href="#g4330"
|
||||||
|
id="use4338"
|
||||||
|
transform="matrix(0.4546439,-0.10745401,-0.02175104,0.44922994,711.99298,282.73776)"
|
||||||
|
width="100%"
|
||||||
|
height="100%" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer4"
|
||||||
|
inkscape:label="palette"
|
||||||
|
style="display:inline"
|
||||||
|
sodipodi:insensitive="true"
|
||||||
|
transform="translate(-15.732722,-256.54886)">
|
||||||
|
<rect
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#linearGradient4168);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21052647;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
id="rect4162"
|
||||||
|
width="40.789474"
|
||||||
|
height="40.789474"
|
||||||
|
x="779.60529"
|
||||||
|
y="21.967466" />
|
||||||
|
<rect
|
||||||
|
y="21.967466"
|
||||||
|
x="824.60529"
|
||||||
|
height="40.789474"
|
||||||
|
width="40.789474"
|
||||||
|
id="rect4170"
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#linearGradient4180);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21052742;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||||
|
<rect
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#bce8ff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21052647;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
id="rect4208"
|
||||||
|
width="40.789474"
|
||||||
|
height="40.789474"
|
||||||
|
x="779.60529"
|
||||||
|
y="86.967468" />
|
||||||
|
<rect
|
||||||
|
y="-127.75694"
|
||||||
|
x="824.60529"
|
||||||
|
height="40.789474"
|
||||||
|
width="40.789474"
|
||||||
|
id="rect4223"
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#abccd9;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21052647;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
transform="scale(1,-1)" />
|
||||||
|
<rect
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#c3b0cb;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21052647;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
id="rect4227"
|
||||||
|
width="40.789474"
|
||||||
|
height="40.789474"
|
||||||
|
x="779.60529"
|
||||||
|
y="131.96747" />
|
||||||
|
<rect
|
||||||
|
y="131.96747"
|
||||||
|
x="824.60529"
|
||||||
|
height="40.789474"
|
||||||
|
width="40.789474"
|
||||||
|
id="rect4231"
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#e1d0cb;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21052647;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||||
|
<rect
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f5c3d2;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21052647;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
id="rect4233"
|
||||||
|
width="40.789474"
|
||||||
|
height="40.789474"
|
||||||
|
x="869.60529"
|
||||||
|
y="131.96747" />
|
||||||
|
<rect
|
||||||
|
y="176.96747"
|
||||||
|
x="779.60529"
|
||||||
|
height="40.789474"
|
||||||
|
width="40.789474"
|
||||||
|
id="rect4248"
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#cec4ad;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21052647;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||||
|
<rect
|
||||||
|
transform="scale(1,-1)"
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#96d6ff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21052647;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
id="rect4263"
|
||||||
|
width="40.789474"
|
||||||
|
height="40.789474"
|
||||||
|
x="869.60529"
|
||||||
|
y="-127.75694" />
|
||||||
|
<rect
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f2f2ce;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21052647;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
id="rect4267"
|
||||||
|
width="40.789474"
|
||||||
|
height="40.789474"
|
||||||
|
x="824.60529"
|
||||||
|
y="176.96747" />
|
||||||
|
<rect
|
||||||
|
y="-327.75693"
|
||||||
|
x="779.60529"
|
||||||
|
height="40.789474"
|
||||||
|
width="40.789474"
|
||||||
|
id="rect4280"
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#24b8eb;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21052647;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
transform="scale(1,-1)" />
|
||||||
|
<rect
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#8aa9ff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21052647;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
id="rect4284"
|
||||||
|
width="40.789474"
|
||||||
|
height="40.789474"
|
||||||
|
x="824.60529"
|
||||||
|
y="286.96747" />
|
||||||
|
<rect
|
||||||
|
y="331.96747"
|
||||||
|
x="779.60529"
|
||||||
|
height="40.789474"
|
||||||
|
width="40.789474"
|
||||||
|
id="rect4297"
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#d4edf1;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21052647;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||||
|
<rect
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#394d54;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21052647;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
id="rect4301"
|
||||||
|
width="40.789474"
|
||||||
|
height="40.789474"
|
||||||
|
x="779.60529"
|
||||||
|
y="241.96747" />
|
||||||
|
<rect
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#d6e2ff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21052647;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
id="rect4303"
|
||||||
|
width="40.789474"
|
||||||
|
height="40.789474"
|
||||||
|
x="824.60529"
|
||||||
|
y="331.96747" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 84 KiB |
@ -14,12 +14,12 @@ else
|
|||||||
let g:ctrlp_ext_vars = [s:go_decls_var]
|
let g:ctrlp_ext_vars = [s:go_decls_var]
|
||||||
endif
|
endif
|
||||||
|
|
||||||
function! ctrlp#decls#init()
|
function! ctrlp#decls#init() abort
|
||||||
cal s:enable_syntax()
|
cal s:enable_syntax()
|
||||||
return s:decls
|
return s:decls
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! ctrlp#decls#exit()
|
function! ctrlp#decls#exit() abort
|
||||||
unlet! s:decls s:current_dir s:target
|
unlet! s:decls s:current_dir s:target
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ endfunction
|
|||||||
" a:mode the mode that has been chosen by pressing <cr> <c-v> <c-t> or <c-x>
|
" a:mode the mode that has been chosen by pressing <cr> <c-v> <c-t> or <c-x>
|
||||||
" the values are 'e', 'v', 't' and 'h', respectively
|
" the values are 'e', 'v', 't' and 'h', respectively
|
||||||
" a:str the selected string
|
" a:str the selected string
|
||||||
function! ctrlp#decls#accept(mode, str)
|
function! ctrlp#decls#accept(mode, str) abort
|
||||||
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
||||||
let dir = getcwd()
|
let dir = getcwd()
|
||||||
try
|
try
|
||||||
@ -56,7 +56,7 @@ function! ctrlp#decls#accept(mode, str)
|
|||||||
endtry
|
endtry
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! ctrlp#decls#enter()
|
function! ctrlp#decls#enter() abort
|
||||||
let s:current_dir = fnameescape(expand('%:p:h'))
|
let s:current_dir = fnameescape(expand('%:p:h'))
|
||||||
let s:decls = []
|
let s:decls = []
|
||||||
|
|
||||||
@ -87,16 +87,12 @@ function! ctrlp#decls#enter()
|
|||||||
let command .= printf(" -dir %s", dir)
|
let command .= printf(" -dir %s", dir)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let out = system(command)
|
let out = go#util#System(command)
|
||||||
if v:shell_error != 0
|
if go#util#ShellError() != 0
|
||||||
call go#util#EchoError(out)
|
call go#util#EchoError(out)
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if exists("l:tmpname")
|
|
||||||
call delete(l:tmpname)
|
|
||||||
endif
|
|
||||||
|
|
||||||
let result = eval(out)
|
let result = eval(out)
|
||||||
if type(result) != 4 || !has_key(result, 'decls')
|
if type(result) != 4 || !has_key(result, 'decls')
|
||||||
return
|
return
|
||||||
@ -130,7 +126,7 @@ function! ctrlp#decls#enter()
|
|||||||
endfor
|
endfor
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
function! s:enable_syntax()
|
function! s:enable_syntax() abort
|
||||||
if !(has('syntax') && exists('g:syntax_on'))
|
if !(has('syntax') && exists('g:syntax_on'))
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
@ -148,7 +144,7 @@ endfunction
|
|||||||
|
|
||||||
let s:id = g:ctrlp_builtins + len(g:ctrlp_ext_vars)
|
let s:id = g:ctrlp_builtins + len(g:ctrlp_ext_vars)
|
||||||
|
|
||||||
function! ctrlp#decls#cmd(mode, ...)
|
function! ctrlp#decls#cmd(mode, ...) abort
|
||||||
let s:mode = a:mode
|
let s:mode = a:mode
|
||||||
if a:0 && !empty(a:1)
|
if a:0 && !empty(a:1)
|
||||||
let s:target = a:1
|
let s:target = a:1
|
||||||
@ -156,3 +152,4 @@ function! ctrlp#decls#cmd(mode, ...)
|
|||||||
return s:id
|
return s:id
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
150
autoload/fzf/decls.vim
Normal file
150
autoload/fzf/decls.vim
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
function! s:code(group, attr) abort
|
||||||
|
let code = synIDattr(synIDtrans(hlID(a:group)), a:attr, "cterm")
|
||||||
|
if code =~ '^[0-9]\+$'
|
||||||
|
return code
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:color(str, group) abort
|
||||||
|
let fg = s:code(a:group, "fg")
|
||||||
|
let bg = s:code(a:group, "bg")
|
||||||
|
let bold = s:code(a:group, "bold")
|
||||||
|
let italic = s:code(a:group, "italic")
|
||||||
|
let reverse = s:code(a:group, "reverse")
|
||||||
|
let underline = s:code(a:group, "underline")
|
||||||
|
let color = (empty(fg) ? "" : ("38;5;".fg)) .
|
||||||
|
\ (empty(bg) ? "" : (";48;5;".bg)) .
|
||||||
|
\ (empty(bold) ? "" : ";1") .
|
||||||
|
\ (empty(italic) ? "" : ";3") .
|
||||||
|
\ (empty(reverse) ? "" : ";7") .
|
||||||
|
\ (empty(underline) ? "" : ";4")
|
||||||
|
return printf("\x1b[%sm%s\x1b[m", color, a:str)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:sink(str) abort
|
||||||
|
if len(a:str) < 2
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
||||||
|
let dir = getcwd()
|
||||||
|
try
|
||||||
|
" we jump to the file directory so we can get the fullpath via fnamemodify
|
||||||
|
" below
|
||||||
|
execute cd . fnameescape(s:current_dir)
|
||||||
|
|
||||||
|
let vals = matchlist(a:str[1], '|\(.\{-}\):\(\d\+\):\(\d\+\)\s*\(.*\)|')
|
||||||
|
|
||||||
|
" i.e: main.go
|
||||||
|
let filename = vals[1]
|
||||||
|
let line = vals[2]
|
||||||
|
let col = vals[3]
|
||||||
|
|
||||||
|
" i.e: /Users/fatih/vim-go/main.go
|
||||||
|
let filepath = fnamemodify(filename, ":p")
|
||||||
|
|
||||||
|
let cmd = get({'ctrl-x': 'split',
|
||||||
|
\ 'ctrl-v': 'vertical split',
|
||||||
|
\ 'ctrl-t': 'tabe'}, a:str[0], 'e')
|
||||||
|
execute cmd fnameescape(filepath)
|
||||||
|
call cursor(line, col)
|
||||||
|
silent! norm! zvzz
|
||||||
|
finally
|
||||||
|
"jump back to old dir
|
||||||
|
execute cd . fnameescape(dir)
|
||||||
|
endtry
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:source(mode,...) abort
|
||||||
|
let s:current_dir = expand('%:p:h')
|
||||||
|
let ret_decls = []
|
||||||
|
|
||||||
|
let bin_path = go#path#CheckBinPath('motion')
|
||||||
|
if empty(bin_path)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
let command = printf("%s -format vim -mode decls", bin_path)
|
||||||
|
let command .= " -include ". get(g:, "go_decls_includes", "func,type")
|
||||||
|
|
||||||
|
call go#cmd#autowrite()
|
||||||
|
|
||||||
|
if a:mode == 0
|
||||||
|
" current file mode
|
||||||
|
let fname = expand("%:p")
|
||||||
|
if a:0 && !empty(a:1)
|
||||||
|
let fname = a:1
|
||||||
|
endif
|
||||||
|
|
||||||
|
let command .= printf(" -file %s", shellescape(fname))
|
||||||
|
else
|
||||||
|
" all functions mode
|
||||||
|
if a:0 && !empty(a:1)
|
||||||
|
let s:current_dir = a:1
|
||||||
|
endif
|
||||||
|
|
||||||
|
let command .= printf(" -dir %s", shellescape(s:current_dir))
|
||||||
|
endif
|
||||||
|
|
||||||
|
let out = go#util#System(command)
|
||||||
|
if go#util#ShellError() != 0
|
||||||
|
call go#util#EchoError(out)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let result = eval(out)
|
||||||
|
if type(result) != 4 || !has_key(result, 'decls')
|
||||||
|
return ret_decls
|
||||||
|
endif
|
||||||
|
|
||||||
|
let decls = result.decls
|
||||||
|
|
||||||
|
" find the maximum function name
|
||||||
|
let max_len = 0
|
||||||
|
for decl in decls
|
||||||
|
if len(decl.ident)> max_len
|
||||||
|
let max_len = len(decl.ident)
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
|
||||||
|
for decl in decls
|
||||||
|
" paddings
|
||||||
|
let space = " "
|
||||||
|
for i in range(max_len - len(decl.ident))
|
||||||
|
let space .= " "
|
||||||
|
endfor
|
||||||
|
|
||||||
|
let pos = printf("|%s:%s:%s|",
|
||||||
|
\ fnamemodify(decl.filename, ":t"),
|
||||||
|
\ decl.line,
|
||||||
|
\ decl.col
|
||||||
|
\)
|
||||||
|
call add(ret_decls, printf("%s\t%s %s\t%s",
|
||||||
|
\ s:color(decl.ident . space, "Function"),
|
||||||
|
\ s:color(decl.keyword, "Keyword"),
|
||||||
|
\ s:color(pos, "SpecialComment"),
|
||||||
|
\ s:color(decl.full, "Comment"),
|
||||||
|
\))
|
||||||
|
endfor
|
||||||
|
|
||||||
|
return ret_decls
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
function! fzf#decls#cmd(...) abort
|
||||||
|
let normal_fg = s:code("Normal", "fg")
|
||||||
|
let normal_bg = s:code("Normal", "bg")
|
||||||
|
let cursor_fg = s:code("CursorLine", "fg")
|
||||||
|
let cursor_bg = s:code("CursorLine", "bg")
|
||||||
|
let colors = printf(" --color %s%s%s%s%s",
|
||||||
|
\ &background,
|
||||||
|
\ empty(normal_fg) ? "" : (",fg:".normal_fg),
|
||||||
|
\ empty(normal_bg) ? "" : (",bg:".normal_bg),
|
||||||
|
\ empty(cursor_fg) ? "" : (",fg+:".cursor_fg),
|
||||||
|
\ empty(cursor_bg) ? "" : (",bg+:".cursor_bg),
|
||||||
|
\)
|
||||||
|
call fzf#run(fzf#wrap('GoDecls', {
|
||||||
|
\ 'source': call('<sid>source', a:000),
|
||||||
|
\ 'options': '-n 1 --ansi --prompt "GoDecls> " --expect=ctrl-t,ctrl-v,ctrl-x'.colors,
|
||||||
|
\ 'sink*': function('s:sink')
|
||||||
|
\ }))
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
@ -4,7 +4,7 @@ if !exists("g:go_alternate_mode")
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
" Test alternates between the implementation of code and the test code.
|
" Test alternates between the implementation of code and the test code.
|
||||||
function! go#alternate#Switch(bang, cmd)
|
function! go#alternate#Switch(bang, cmd) abort
|
||||||
let file = expand('%')
|
let file = expand('%')
|
||||||
if empty(file)
|
if empty(file)
|
||||||
call go#util#EchoError("no buffer name")
|
call go#util#EchoError("no buffer name")
|
||||||
@ -28,3 +28,5 @@ function! go#alternate#Switch(bang, cmd)
|
|||||||
execute ":" . a:cmd . " " . alt_file
|
execute ":" . a:cmd . " " . alt_file
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
"
|
"
|
||||||
" Options:
|
" Options:
|
||||||
"
|
"
|
||||||
" g:go_asmfmt_autosave [default=1]
|
" g:go_asmfmt_autosave [default=0]
|
||||||
"
|
"
|
||||||
" Flag to automatically call :Fmt when file is saved.
|
" Flag to automatically call :Fmt when file is saved.
|
||||||
|
|
||||||
@ -19,29 +19,33 @@ let s:got_fmt_error = 0
|
|||||||
|
|
||||||
" This is a trimmed-down version of the logic in fmt.vim.
|
" This is a trimmed-down version of the logic in fmt.vim.
|
||||||
|
|
||||||
function! go#asmfmt#Format()
|
function! go#asmfmt#Format() abort
|
||||||
" Save state.
|
" Save state.
|
||||||
let l:curw = winsaveview()
|
let l:curw = winsaveview()
|
||||||
|
|
||||||
" Write the current buffer to a tempfile.
|
" Write the current buffer to a tempfile.
|
||||||
let l:tmpname = tempname()
|
let l:tmpname = tempname()
|
||||||
call writefile(getline(1, '$'), l:tmpname)
|
call writefile(go#util#GetLines(), l:tmpname)
|
||||||
|
|
||||||
" Run asmfmt.
|
" Run asmfmt.
|
||||||
let path = go#path#CheckBinPath("asmfmt")
|
let path = go#path#CheckBinPath("asmfmt")
|
||||||
if empty(path)
|
if empty(path)
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
let out = system(path . ' -w ' . l:tmpname)
|
let out = go#util#System(path . ' -w ' . l:tmpname)
|
||||||
|
|
||||||
" If there's no error, replace the current file with the output.
|
" If there's no error, replace the current file with the output.
|
||||||
if v:shell_error == 0
|
if go#util#ShellError() == 0
|
||||||
" Remove undo point caused by BufWritePre.
|
" Remove undo point caused by BufWritePre.
|
||||||
try | silent undojoin | catch | endtry
|
try | silent undojoin | catch | endtry
|
||||||
|
|
||||||
" Replace the current file with the temp file; then reload the buffer.
|
" Replace the current file with the temp file; then reload the buffer.
|
||||||
let old_fileformat = &fileformat
|
let old_fileformat = &fileformat
|
||||||
|
" save old file permissions
|
||||||
|
let original_fperm = getfperm(expand('%'))
|
||||||
call rename(l:tmpname, expand('%'))
|
call rename(l:tmpname, expand('%'))
|
||||||
|
" restore old file permissions
|
||||||
|
call setfperm(expand('%'), original_fperm)
|
||||||
silent edit!
|
silent edit!
|
||||||
let &fileformat = old_fileformat
|
let &fileformat = old_fileformat
|
||||||
let &syntax = &syntax
|
let &syntax = &syntax
|
||||||
@ -50,3 +54,16 @@ function! go#asmfmt#Format()
|
|||||||
" Restore the cursor/window positions.
|
" Restore the cursor/window positions.
|
||||||
call winrestview(l:curw)
|
call winrestview(l:curw)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
function! go#asmfmt#ToggleAsmFmtAutoSave() abort
|
||||||
|
if get(g:, "go_asmfmt_autosave", 0)
|
||||||
|
let g:go_asmfmt_autosave = 1
|
||||||
|
call go#util#EchoProgress("auto asmfmt enabled")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
let g:go_asmfmt_autosave = 0
|
||||||
|
call go#util#EchoProgress("auto asmfmt disabled")
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
@ -1,53 +1,57 @@
|
|||||||
if !exists("g:go_dispatch_enabled")
|
function! go#cmd#autowrite() abort
|
||||||
let g:go_dispatch_enabled = 0
|
|
||||||
endif
|
|
||||||
|
|
||||||
function! go#cmd#autowrite()
|
|
||||||
if &autowrite == 1
|
if &autowrite == 1
|
||||||
silent wall
|
silent! wall
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
" Build builds the source code without producing any output binary. We live in
|
||||||
" Build builds the source code without producting any output binary. We live in
|
|
||||||
" an editor so the best is to build it to catch errors and fix them. By
|
" an editor so the best is to build it to catch errors and fix them. By
|
||||||
" default it tries to call simply 'go build', but it first tries to get all
|
" default it tries to call simply 'go build', but it first tries to get all
|
||||||
" dependent files for the current folder and passes it to go build.
|
" dependent files for the current folder and passes it to go build.
|
||||||
function! go#cmd#Build(bang, ...)
|
function! go#cmd#Build(bang, ...) abort
|
||||||
" expand all wildcards(i.e: '%' to the current file name)
|
" Create our command arguments. go build discards any results when it
|
||||||
let goargs = map(copy(a:000), "expand(v:val)")
|
|
||||||
|
|
||||||
" escape all shell arguments before we pass it to make
|
|
||||||
let goargs = go#util#Shelllist(goargs, 1)
|
|
||||||
|
|
||||||
" create our command arguments. go build discards any results when it
|
|
||||||
" compiles multiple packages. So we pass the `errors` package just as an
|
" compiles multiple packages. So we pass the `errors` package just as an
|
||||||
" placeholder with the current folder (indicated with '.')
|
" placeholder with the current folder (indicated with '.'). We also pass -i
|
||||||
let args = ["build"] + goargs + [".", "errors"]
|
" that tries to install the dependencies, this has the side effect that it
|
||||||
|
" caches the build results, so every other build is faster.
|
||||||
|
let args =
|
||||||
|
\ ["build"] +
|
||||||
|
\ map(copy(a:000), "expand(v:val)") +
|
||||||
|
\ ["-i", ".", "errors"]
|
||||||
|
|
||||||
" if we have nvim, call it asynchronously and return early ;)
|
" Vim async.
|
||||||
if has('nvim')
|
if go#util#has_job()
|
||||||
|
if get(g:, 'go_echo_command_info', 1)
|
||||||
call go#util#EchoProgress("building dispatched ...")
|
call go#util#EchoProgress("building dispatched ...")
|
||||||
call go#jobcontrol#Spawn(a:bang, "build", args)
|
|
||||||
return
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let old_gopath = $GOPATH
|
call s:cmd_job({
|
||||||
let $GOPATH = go#path#Detect()
|
\ 'cmd': ['go'] + args,
|
||||||
let default_makeprg = &makeprg
|
\ 'bang': a:bang,
|
||||||
let &makeprg = "go " . join(args, ' ')
|
\ 'for': 'GoBuild',
|
||||||
|
\})
|
||||||
|
|
||||||
let l:listtype = go#list#Type("quickfix")
|
" Nvim async.
|
||||||
|
elseif has('nvim')
|
||||||
|
if get(g:, 'go_echo_command_info', 1)
|
||||||
|
call go#util#EchoProgress("building dispatched ...")
|
||||||
|
endif
|
||||||
|
|
||||||
|
call go#jobcontrol#Spawn(a:bang, "build", "GoBuild", args)
|
||||||
|
|
||||||
|
" Vim 7.4 without async
|
||||||
|
else
|
||||||
|
let default_makeprg = &makeprg
|
||||||
|
let &makeprg = "go " . join(go#util#Shelllist(args), ' ')
|
||||||
|
|
||||||
|
let l:listtype = go#list#Type("GoBuild")
|
||||||
" execute make inside the source folder so we can parse the errors
|
" execute make inside the source folder so we can parse the errors
|
||||||
" correctly
|
" correctly
|
||||||
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
||||||
let dir = getcwd()
|
let dir = getcwd()
|
||||||
try
|
try
|
||||||
execute cd . fnameescape(expand("%:p:h"))
|
execute cd . fnameescape(expand("%:p:h"))
|
||||||
if g:go_dispatch_enabled && exists(':Make') == 2
|
if l:listtype == "locationlist"
|
||||||
call go#util#EchoProgress("building dispatched ...")
|
|
||||||
silent! exe 'Make'
|
|
||||||
elseif l:listtype == "locationlist"
|
|
||||||
silent! exe 'lmake!'
|
silent! exe 'lmake!'
|
||||||
else
|
else
|
||||||
silent! exe 'make!'
|
silent! exe 'make!'
|
||||||
@ -59,22 +63,41 @@ function! go#cmd#Build(bang, ...)
|
|||||||
|
|
||||||
let errors = go#list#Get(l:listtype)
|
let errors = go#list#Get(l:listtype)
|
||||||
call go#list#Window(l:listtype, len(errors))
|
call go#list#Window(l:listtype, len(errors))
|
||||||
|
if !empty(errors) && !a:bang
|
||||||
if !empty(errors)
|
|
||||||
if !a:bang
|
|
||||||
call go#list#JumpToFirst(l:listtype)
|
call go#list#JumpToFirst(l:listtype)
|
||||||
endif
|
|
||||||
else
|
else
|
||||||
call go#util#EchoSuccess("[build] SUCCESS")
|
call go#util#EchoSuccess("[build] SUCCESS")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let &makeprg = default_makeprg
|
let &makeprg = default_makeprg
|
||||||
let $GOPATH = old_gopath
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
" BuildTags sets or shows the current build tags used for tools
|
||||||
|
function! go#cmd#BuildTags(bang, ...) abort
|
||||||
|
if a:0
|
||||||
|
if a:0 == 1 && a:1 == '""'
|
||||||
|
unlet g:go_build_tags
|
||||||
|
call go#util#EchoSuccess("build tags are cleared")
|
||||||
|
else
|
||||||
|
let g:go_build_tags = a:1
|
||||||
|
call go#util#EchoSuccess("build tags are changed to: ". a:1)
|
||||||
|
endif
|
||||||
|
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
if !exists('g:go_build_tags')
|
||||||
|
call go#util#EchoSuccess("build tags are not set")
|
||||||
|
else
|
||||||
|
call go#util#EchoSuccess("current build tags: ". g:go_build_tags)
|
||||||
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
" Run runs the current file (and their dependencies if any) in a new terminal.
|
" Run runs the current file (and their dependencies if any) in a new terminal.
|
||||||
function! go#cmd#RunTerm(bang, mode, files)
|
function! go#cmd#RunTerm(bang, mode, files) abort
|
||||||
if empty(a:files)
|
if empty(a:files)
|
||||||
let cmd = "go run ". go#util#Shelljoin(go#tool#Files())
|
let cmd = "go run ". go#util#Shelljoin(go#tool#Files())
|
||||||
else
|
else
|
||||||
@ -84,17 +107,20 @@ function! go#cmd#RunTerm(bang, mode, files)
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Run runs the current file (and their dependencies if any) and outputs it.
|
" Run runs the current file (and their dependencies if any) and outputs it.
|
||||||
" This is intented to test small programs and play with them. It's not
|
" This is intended to test small programs and play with them. It's not
|
||||||
" suitable for long running apps, because vim is blocking by default and
|
" suitable for long running apps, because vim is blocking by default and
|
||||||
" calling long running apps will block the whole UI.
|
" calling long running apps will block the whole UI.
|
||||||
function! go#cmd#Run(bang, ...)
|
function! go#cmd#Run(bang, ...) abort
|
||||||
if has('nvim')
|
if has('nvim')
|
||||||
call go#cmd#RunTerm(a:bang, '', a:000)
|
call go#cmd#RunTerm(a:bang, '', a:000)
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let old_gopath = $GOPATH
|
if go#util#has_job()
|
||||||
let $GOPATH = go#path#Detect()
|
" NOTE(arslan): 'term': 'open' case is not implement for +jobs. This means
|
||||||
|
" executions waiting for stdin will not work. That's why we don't do
|
||||||
|
" anything. Once this is implemented we're going to make :GoRun async
|
||||||
|
endif
|
||||||
|
|
||||||
if go#util#IsWin()
|
if go#util#IsWin()
|
||||||
exec '!go run ' . go#util#Shelljoin(go#tool#Files())
|
exec '!go run ' . go#util#Shelljoin(go#tool#Files())
|
||||||
@ -104,7 +130,6 @@ function! go#cmd#Run(bang, ...)
|
|||||||
redraws! | echon "vim-go: [run] " | echohl Function | echon "SUCCESS"| echohl None
|
redraws! | echon "vim-go: [run] " | echohl Function | echon "SUCCESS"| echohl None
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let $GOPATH = old_gopath
|
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -116,11 +141,9 @@ function! go#cmd#Run(bang, ...)
|
|||||||
let &makeprg = "go run " . go#util#Shelljoin(map(copy(a:000), "expand(v:val)"), 1)
|
let &makeprg = "go run " . go#util#Shelljoin(map(copy(a:000), "expand(v:val)"), 1)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let l:listtype = go#list#Type("quickfix")
|
let l:listtype = go#list#Type("GoRun")
|
||||||
|
|
||||||
if g:go_dispatch_enabled && exists(':Make') == 2
|
if l:listtype == "locationlist"
|
||||||
silent! exe 'Make'
|
|
||||||
elseif l:listtype == "locationlist"
|
|
||||||
exe 'lmake!'
|
exe 'lmake!'
|
||||||
else
|
else
|
||||||
exe 'make!'
|
exe 'make!'
|
||||||
@ -129,37 +152,50 @@ function! go#cmd#Run(bang, ...)
|
|||||||
let items = go#list#Get(l:listtype)
|
let items = go#list#Get(l:listtype)
|
||||||
let errors = go#tool#FilterValids(items)
|
let errors = go#tool#FilterValids(items)
|
||||||
|
|
||||||
call go#list#Populate(l:listtype, errors)
|
call go#list#Populate(l:listtype, errors, &makeprg)
|
||||||
call go#list#Window(l:listtype, len(errors))
|
call go#list#Window(l:listtype, len(errors))
|
||||||
if !empty(errors) && !a:bang
|
if !empty(errors) && !a:bang
|
||||||
call go#list#JumpToFirst(l:listtype)
|
call go#list#JumpToFirst(l:listtype)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let $GOPATH = old_gopath
|
|
||||||
let &makeprg = default_makeprg
|
let &makeprg = default_makeprg
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Install installs the package by simple calling 'go install'. If any argument
|
" Install installs the package by simple calling 'go install'. If any argument
|
||||||
" is given(which are passed directly to 'go install') it tries to install those
|
" is given(which are passed directly to 'go install') it tries to install
|
||||||
" packages. Errors are populated in the location window.
|
" those packages. Errors are populated in the location window.
|
||||||
function! go#cmd#Install(bang, ...)
|
function! go#cmd#Install(bang, ...) abort
|
||||||
|
" use vim's job functionality to call it asynchronously
|
||||||
|
if go#util#has_job()
|
||||||
|
" expand all wildcards(i.e: '%' to the current file name)
|
||||||
|
let goargs = map(copy(a:000), "expand(v:val)")
|
||||||
|
|
||||||
|
if get(g:, 'go_echo_command_info', 1)
|
||||||
|
call go#util#EchoProgress("installing dispatched ...")
|
||||||
|
endif
|
||||||
|
|
||||||
|
call s:cmd_job({
|
||||||
|
\ 'cmd': ['go', 'install'] + goargs,
|
||||||
|
\ 'bang': a:bang,
|
||||||
|
\ 'for': 'GoInstall',
|
||||||
|
\})
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
let default_makeprg = &makeprg
|
let default_makeprg = &makeprg
|
||||||
|
|
||||||
" :make expands '%' and '#' wildcards, so they must also be escaped
|
" :make expands '%' and '#' wildcards, so they must also be escaped
|
||||||
let goargs = go#util#Shelljoin(map(copy(a:000), "expand(v:val)"), 1)
|
let goargs = go#util#Shelljoin(map(copy(a:000), "expand(v:val)"), 1)
|
||||||
let &makeprg = "go install " . goargs
|
let &makeprg = "go install " . goargs
|
||||||
|
|
||||||
let l:listtype = go#list#Type("quickfix")
|
let l:listtype = go#list#Type("GoInstall")
|
||||||
" execute make inside the source folder so we can parse the errors
|
" execute make inside the source folder so we can parse the errors
|
||||||
" correctly
|
" correctly
|
||||||
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
||||||
let dir = getcwd()
|
let dir = getcwd()
|
||||||
try
|
try
|
||||||
execute cd . fnameescape(expand("%:p:h"))
|
execute cd . fnameescape(expand("%:p:h"))
|
||||||
if g:go_dispatch_enabled && exists(':Make') == 2
|
if l:listtype == "locationlist"
|
||||||
call go#util#EchoProgress("building dispatched ...")
|
|
||||||
silent! exe 'Make'
|
|
||||||
elseif l:listtype == "locationlist"
|
|
||||||
silent! exe 'lmake!'
|
silent! exe 'lmake!'
|
||||||
else
|
else
|
||||||
silent! exe 'make!'
|
silent! exe 'make!'
|
||||||
@ -171,177 +207,32 @@ function! go#cmd#Install(bang, ...)
|
|||||||
|
|
||||||
let errors = go#list#Get(l:listtype)
|
let errors = go#list#Get(l:listtype)
|
||||||
call go#list#Window(l:listtype, len(errors))
|
call go#list#Window(l:listtype, len(errors))
|
||||||
if !empty(errors)
|
if !empty(errors) && !a:bang
|
||||||
if !a:bang
|
|
||||||
call go#list#JumpToFirst(l:listtype)
|
call go#list#JumpToFirst(l:listtype)
|
||||||
endif
|
|
||||||
else
|
else
|
||||||
redraws! | echon "vim-go: " | echohl Function | echon "installed to ". $GOPATH | echohl None
|
call go#util#EchoSuccess("installed to ". go#path#Default())
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let &makeprg = default_makeprg
|
let &makeprg = default_makeprg
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Test runs `go test` in the current directory. If compile is true, it'll
|
|
||||||
" compile the tests instead of running them (useful to catch errors in the
|
|
||||||
" test files). Any other argument is appendend to the final `go test` command
|
|
||||||
function! go#cmd#Test(bang, compile, ...)
|
|
||||||
let args = ["test"]
|
|
||||||
|
|
||||||
" don't run the test, only compile it. Useful to capture and fix errors or
|
|
||||||
" to create a test binary.
|
|
||||||
if a:compile
|
|
||||||
call add(args, "-c")
|
|
||||||
endif
|
|
||||||
|
|
||||||
if a:0
|
|
||||||
" expand all wildcards(i.e: '%' to the current file name)
|
|
||||||
let goargs = map(copy(a:000), "expand(v:val)")
|
|
||||||
|
|
||||||
call extend(args, goargs, 1)
|
|
||||||
else
|
|
||||||
" only add this if no custom flags are passed
|
|
||||||
let timeout = get(g:, 'go_test_timeout', '10s')
|
|
||||||
call add(args, printf("-timeout=%s", timeout))
|
|
||||||
endif
|
|
||||||
|
|
||||||
if a:compile
|
|
||||||
echon "vim-go: " | echohl Identifier | echon "compiling tests ..." | echohl None
|
|
||||||
else
|
|
||||||
echon "vim-go: " | echohl Identifier | echon "testing ..." | echohl None
|
|
||||||
endif
|
|
||||||
|
|
||||||
if has('nvim')
|
|
||||||
if get(g:, 'go_term_enabled', 0)
|
|
||||||
call go#term#new(a:bang, ["go"] + args)
|
|
||||||
else
|
|
||||||
call go#jobcontrol#Spawn(a:bang, "test", args)
|
|
||||||
endif
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
|
|
||||||
call go#cmd#autowrite()
|
|
||||||
redraw
|
|
||||||
|
|
||||||
let command = "go " . join(args, ' ')
|
|
||||||
|
|
||||||
let out = go#tool#ExecuteInDir(command)
|
|
||||||
|
|
||||||
let l:listtype = "quickfix"
|
|
||||||
|
|
||||||
if v:shell_error
|
|
||||||
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
|
||||||
let dir = getcwd()
|
|
||||||
try
|
|
||||||
execute cd fnameescape(expand("%:p:h"))
|
|
||||||
let errors = go#tool#ParseErrors(split(out, '\n'))
|
|
||||||
let errors = go#tool#FilterValids(errors)
|
|
||||||
finally
|
|
||||||
execute cd . fnameescape(dir)
|
|
||||||
endtry
|
|
||||||
|
|
||||||
call go#list#Populate(l:listtype, errors)
|
|
||||||
call go#list#Window(l:listtype, len(errors))
|
|
||||||
if !empty(errors) && !a:bang
|
|
||||||
call go#list#JumpToFirst(l:listtype)
|
|
||||||
elseif empty(errors)
|
|
||||||
" failed to parse errors, output the original content
|
|
||||||
call go#util#EchoError(out)
|
|
||||||
endif
|
|
||||||
echon "vim-go: " | echohl ErrorMsg | echon "[test] FAIL" | echohl None
|
|
||||||
else
|
|
||||||
call go#list#Clean(l:listtype)
|
|
||||||
call go#list#Window(l:listtype)
|
|
||||||
|
|
||||||
if a:compile
|
|
||||||
echon "vim-go: " | echohl Function | echon "[test] SUCCESS" | echohl None
|
|
||||||
else
|
|
||||||
echon "vim-go: " | echohl Function | echon "[test] PASS" | echohl None
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Testfunc runs a single test that surrounds the current cursor position.
|
|
||||||
" Arguments are passed to the `go test` command.
|
|
||||||
function! go#cmd#TestFunc(bang, ...)
|
|
||||||
" search flags legend (used only)
|
|
||||||
" 'b' search backward instead of forward
|
|
||||||
" 'c' accept a match at the cursor position
|
|
||||||
" 'n' do Not move the cursor
|
|
||||||
" 'W' don't wrap around the end of the file
|
|
||||||
"
|
|
||||||
" for the full list
|
|
||||||
" :help search
|
|
||||||
let test = search("func Test", "bcnW")
|
|
||||||
|
|
||||||
if test == 0
|
|
||||||
echo "vim-go: [test] no test found immediate to cursor"
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
let line = getline(test)
|
|
||||||
let name = split(split(line, " ")[1], "(")[0]
|
|
||||||
let args = [a:bang, 0, "-run", name . "$"]
|
|
||||||
|
|
||||||
if a:0
|
|
||||||
call extend(args, a:000)
|
|
||||||
endif
|
|
||||||
|
|
||||||
call call('go#cmd#Test', args)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Coverage creates a new cover profile with 'go test -coverprofile' and opens
|
|
||||||
" a new HTML coverage page from that profile.
|
|
||||||
function! go#cmd#Coverage(bang, ...)
|
|
||||||
let l:tmpname=tempname()
|
|
||||||
|
|
||||||
let command = "go test -coverprofile=" . l:tmpname . ' ' . go#util#Shelljoin(a:000)
|
|
||||||
|
|
||||||
|
|
||||||
let l:listtype = "quickfix"
|
|
||||||
call go#cmd#autowrite()
|
|
||||||
let out = go#tool#ExecuteInDir(command)
|
|
||||||
if v:shell_error
|
|
||||||
let errors = go#tool#ParseErrors(split(out, '\n'))
|
|
||||||
call go#list#Populate(l:listtype, errors)
|
|
||||||
call go#list#Window(l:listtype, len(errors))
|
|
||||||
if !empty(errors) && !a:bang
|
|
||||||
call go#list#JumpToFirst(l:listtype)
|
|
||||||
endif
|
|
||||||
else
|
|
||||||
" clear previous location list
|
|
||||||
call go#list#Clean(l:listtype)
|
|
||||||
call go#list#Window(l:listtype)
|
|
||||||
|
|
||||||
let openHTML = 'go tool cover -html='.l:tmpname
|
|
||||||
call go#tool#ExecuteInDir(openHTML)
|
|
||||||
endif
|
|
||||||
|
|
||||||
call delete(l:tmpname)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Generate runs 'go generate' in similar fashion to go#cmd#Build()
|
" Generate runs 'go generate' in similar fashion to go#cmd#Build()
|
||||||
function! go#cmd#Generate(bang, ...)
|
function! go#cmd#Generate(bang, ...) abort
|
||||||
let default_makeprg = &makeprg
|
let default_makeprg = &makeprg
|
||||||
|
|
||||||
let old_gopath = $GOPATH
|
|
||||||
let $GOPATH = go#path#Detect()
|
|
||||||
|
|
||||||
" :make expands '%' and '#' wildcards, so they must also be escaped
|
" :make expands '%' and '#' wildcards, so they must also be escaped
|
||||||
let goargs = go#util#Shelljoin(map(copy(a:000), "expand(v:val)"), 1)
|
let goargs = go#util#Shelljoin(map(copy(a:000), "expand(v:val)"), 1)
|
||||||
if v:shell_error
|
if go#util#ShellError() != 0
|
||||||
let &makeprg = "go generate " . goargs
|
let &makeprg = "go generate " . goargs
|
||||||
else
|
else
|
||||||
let gofiles = go#util#Shelljoin(go#tool#Files(), 1)
|
let gofiles = go#util#Shelljoin(go#tool#Files(), 1)
|
||||||
let &makeprg = "go generate " . goargs . ' ' . gofiles
|
let &makeprg = "go generate " . goargs . ' ' . gofiles
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let l:listtype = go#list#Type("quickfix")
|
let l:listtype = go#list#Type("GoGenerate")
|
||||||
|
|
||||||
echon "vim-go: " | echohl Identifier | echon "generating ..."| echohl None
|
echon "vim-go: " | echohl Identifier | echon "generating ..."| echohl None
|
||||||
if g:go_dispatch_enabled && exists(':Make') == 2
|
if l:listtype == "locationlist"
|
||||||
silent! exe 'Make'
|
|
||||||
elseif l:listtype == "locationlist"
|
|
||||||
silent! exe 'lmake!'
|
silent! exe 'lmake!'
|
||||||
else
|
else
|
||||||
silent! exe 'make!'
|
silent! exe 'make!'
|
||||||
@ -359,7 +250,62 @@ function! go#cmd#Generate(bang, ...)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
let &makeprg = default_makeprg
|
let &makeprg = default_makeprg
|
||||||
let $GOPATH = old_gopath
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
" ---------------------
|
||||||
|
" | Vim job callbacks |
|
||||||
|
" ---------------------
|
||||||
|
|
||||||
|
function s:cmd_job(args) abort
|
||||||
|
let status_dir = expand('%:p:h')
|
||||||
|
let started_at = reltime()
|
||||||
|
|
||||||
|
call go#statusline#Update(status_dir, {
|
||||||
|
\ 'desc': "current status",
|
||||||
|
\ 'type': a:args.cmd[1],
|
||||||
|
\ 'state': "started",
|
||||||
|
\})
|
||||||
|
|
||||||
|
" autowrite is not enabled for jobs
|
||||||
|
call go#cmd#autowrite()
|
||||||
|
|
||||||
|
function! s:error_info_cb(job, exit_status, data) closure abort
|
||||||
|
let status = {
|
||||||
|
\ 'desc': 'last status',
|
||||||
|
\ 'type': a:args.cmd[1],
|
||||||
|
\ 'state': "success",
|
||||||
|
\ }
|
||||||
|
|
||||||
|
if a:exit_status
|
||||||
|
let status.state = "failed"
|
||||||
|
endif
|
||||||
|
|
||||||
|
let elapsed_time = reltimestr(reltime(started_at))
|
||||||
|
" strip whitespace
|
||||||
|
let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '')
|
||||||
|
let status.state .= printf(" (%ss)", elapsed_time)
|
||||||
|
|
||||||
|
call go#statusline#Update(status_dir, status)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
let a:args.error_info_cb = funcref('s:error_info_cb')
|
||||||
|
let callbacks = go#job#Spawn(a:args)
|
||||||
|
|
||||||
|
let start_options = {
|
||||||
|
\ 'callback': callbacks.callback,
|
||||||
|
\ 'exit_cb': callbacks.exit_cb,
|
||||||
|
\ }
|
||||||
|
|
||||||
|
" pre start
|
||||||
|
let dir = getcwd()
|
||||||
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
||||||
|
let jobdir = fnameescape(expand("%:p:h"))
|
||||||
|
execute cd . jobdir
|
||||||
|
|
||||||
|
call job_start(a:args.cmd, start_options)
|
||||||
|
|
||||||
|
" post start
|
||||||
|
execute cd . fnameescape(dir)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
@ -1,79 +1,45 @@
|
|||||||
if !exists("g:go_gocode_bin")
|
let s:sock_type = (has('win32') || has('win64')) ? 'tcp' : 'unix'
|
||||||
let g:go_gocode_bin = "gocode"
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
function! s:gocodeCurrentBuffer() abort
|
||||||
fu! s:gocodeCurrentBuffer()
|
|
||||||
let buf = getline(1, '$')
|
|
||||||
if &encoding != 'utf-8'
|
|
||||||
let buf = map(buf, 'iconv(v:val, &encoding, "utf-8")')
|
|
||||||
endif
|
|
||||||
if &l:fileformat == 'dos'
|
|
||||||
" XXX: line2byte() depend on 'fileformat' option.
|
|
||||||
" so if fileformat is 'dos', 'buf' must include '\r'.
|
|
||||||
let buf = map(buf, 'v:val."\r"')
|
|
||||||
endif
|
|
||||||
let file = tempname()
|
let file = tempname()
|
||||||
call writefile(buf, file)
|
call writefile(go#util#GetLines(), file)
|
||||||
|
|
||||||
return file
|
return file
|
||||||
endf
|
endfunction
|
||||||
|
|
||||||
if go#vimproc#has_vimproc()
|
function! s:gocodeCommand(cmd, preargs, args) abort
|
||||||
let s:vim_system = get(g:, 'gocomplete#system_function', 'vimproc#system2')
|
|
||||||
let s:vim_shell_error = get(g:, 'gocomplete#shell_error_function', 'vimproc#get_last_status')
|
|
||||||
else
|
|
||||||
let s:vim_system = get(g:, 'gocomplete#system_function', 'system')
|
|
||||||
let s:vim_shell_error = ''
|
|
||||||
endif
|
|
||||||
|
|
||||||
fu! s:shell_error()
|
|
||||||
if empty(s:vim_shell_error)
|
|
||||||
return v:shell_error
|
|
||||||
endif
|
|
||||||
return call(s:vim_shell_error, [])
|
|
||||||
endf
|
|
||||||
|
|
||||||
fu! s:system(str, ...)
|
|
||||||
return call(s:vim_system, [a:str] + a:000)
|
|
||||||
endf
|
|
||||||
|
|
||||||
fu! s:gocodeShellescape(arg)
|
|
||||||
if go#vimproc#has_vimproc()
|
|
||||||
return vimproc#shellescape(a:arg)
|
|
||||||
endif
|
|
||||||
try
|
|
||||||
let ssl_save = &shellslash
|
|
||||||
set noshellslash
|
|
||||||
return shellescape(a:arg)
|
|
||||||
finally
|
|
||||||
let &shellslash = ssl_save
|
|
||||||
endtry
|
|
||||||
endf
|
|
||||||
|
|
||||||
fu! s:gocodeCommand(cmd, preargs, args)
|
|
||||||
for i in range(0, len(a:args) - 1)
|
for i in range(0, len(a:args) - 1)
|
||||||
let a:args[i] = s:gocodeShellescape(a:args[i])
|
let a:args[i] = go#util#Shellescape(a:args[i])
|
||||||
endfor
|
endfor
|
||||||
for i in range(0, len(a:preargs) - 1)
|
for i in range(0, len(a:preargs) - 1)
|
||||||
let a:preargs[i] = s:gocodeShellescape(a:preargs[i])
|
let a:preargs[i] = go#util#Shellescape(a:preargs[i])
|
||||||
endfor
|
endfor
|
||||||
|
|
||||||
let bin_path = go#path#CheckBinPath(g:go_gocode_bin)
|
let bin_path = go#path#CheckBinPath("gocode")
|
||||||
if empty(bin_path)
|
if empty(bin_path)
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" we might hit cache problems, as gocode doesn't handle well different
|
" We might hit cache problems, as gocode doesn't handle different GOPATHs
|
||||||
" GOPATHS: https://github.com/nsf/gocode/issues/239
|
" well. See: https://github.com/nsf/gocode/issues/239
|
||||||
let old_gopath = $GOPATH
|
let old_goroot = $GOROOT
|
||||||
let $GOPATH = go#path#Detect()
|
let $GOROOT = go#util#env("goroot")
|
||||||
|
|
||||||
let result = s:system(printf('%s %s %s %s', s:gocodeShellescape(bin_path), join(a:preargs), s:gocodeShellescape(a:cmd), join(a:args)))
|
try
|
||||||
|
let socket_type = get(g:, 'go_gocode_socket_type', s:sock_type)
|
||||||
|
let cmd = printf('%s -sock %s %s %s %s',
|
||||||
|
\ go#util#Shellescape(bin_path),
|
||||||
|
\ socket_type,
|
||||||
|
\ join(a:preargs),
|
||||||
|
\ go#util#Shellescape(a:cmd),
|
||||||
|
\ join(a:args)
|
||||||
|
\ )
|
||||||
|
|
||||||
let $GOPATH = old_gopath
|
let result = go#util#System(cmd)
|
||||||
|
finally
|
||||||
|
let $GOROOT = old_goroot
|
||||||
|
endtry
|
||||||
|
|
||||||
if s:shell_error() != 0
|
if go#util#ShellError() != 0
|
||||||
return "[\"0\", []]"
|
return "[\"0\", []]"
|
||||||
else
|
else
|
||||||
if &encoding != 'utf-8'
|
if &encoding != 'utf-8'
|
||||||
@ -81,22 +47,46 @@ fu! s:gocodeCommand(cmd, preargs, args)
|
|||||||
endif
|
endif
|
||||||
return result
|
return result
|
||||||
endif
|
endif
|
||||||
endf
|
endfunction
|
||||||
|
|
||||||
fu! s:gocodeCurrentBufferOpt(filename)
|
function! s:gocodeCurrentBufferOpt(filename) abort
|
||||||
return '-in=' . a:filename
|
return '-in=' . a:filename
|
||||||
endf
|
endfunction
|
||||||
|
|
||||||
|
let s:optionsEnabled = 0
|
||||||
|
function! s:gocodeEnableOptions() abort
|
||||||
|
if s:optionsEnabled
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let bin_path = go#path#CheckBinPath("gocode")
|
||||||
|
if empty(bin_path)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let s:optionsEnabled = 1
|
||||||
|
|
||||||
|
call go#util#System(printf('%s set propose-builtins %s', go#util#Shellescape(bin_path), s:toBool(get(g:, 'go_gocode_propose_builtins', 1))))
|
||||||
|
call go#util#System(printf('%s set autobuild %s', go#util#Shellescape(bin_path), s:toBool(get(g:, 'go_gocode_autobuild', 1))))
|
||||||
|
call go#util#System(printf('%s set unimported-packages %s', go#util#Shellescape(bin_path), s:toBool(get(g:, 'go_gocode_unimported_packages', 0))))
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:toBool(val) abort
|
||||||
|
if a:val | return 'true ' | else | return 'false' | endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:gocodeAutocomplete() abort
|
||||||
|
call s:gocodeEnableOptions()
|
||||||
|
|
||||||
fu! s:gocodeAutocomplete()
|
|
||||||
let filename = s:gocodeCurrentBuffer()
|
let filename = s:gocodeCurrentBuffer()
|
||||||
let result = s:gocodeCommand('autocomplete',
|
let result = s:gocodeCommand('autocomplete',
|
||||||
\ [s:gocodeCurrentBufferOpt(filename), '-f=vim'],
|
\ [s:gocodeCurrentBufferOpt(filename), '-f=vim'],
|
||||||
\ [expand('%:p'), go#util#OffsetCursor()])
|
\ [expand('%:p'), go#util#OffsetCursor()])
|
||||||
call delete(filename)
|
call delete(filename)
|
||||||
return result
|
return result
|
||||||
endf
|
endfunction
|
||||||
|
|
||||||
function! go#complete#GetInfo()
|
function! go#complete#GetInfo() abort
|
||||||
let offset = go#util#OffsetCursor()+1
|
let offset = go#util#OffsetCursor()+1
|
||||||
let filename = s:gocodeCurrentBuffer()
|
let filename = s:gocodeCurrentBuffer()
|
||||||
let result = s:gocodeCommand('autocomplete',
|
let result = s:gocodeCommand('autocomplete',
|
||||||
@ -113,7 +103,7 @@ function! go#complete#GetInfo()
|
|||||||
return ""
|
return ""
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" only one candiate is found
|
" only one candidate is found
|
||||||
if len(out) == 2
|
if len(out) == 2
|
||||||
return split(out[1], ',,')[0]
|
return split(out[1], ',,')[0]
|
||||||
endif
|
endif
|
||||||
@ -137,7 +127,7 @@ function! go#complete#GetInfo()
|
|||||||
return ""
|
return ""
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! go#complete#Info(auto)
|
function! go#complete#Info(auto) abort
|
||||||
" auto is true if we were called by g:go_auto_type_info's autocmd
|
" auto is true if we were called by g:go_auto_type_info's autocmd
|
||||||
let result = go#complete#GetInfo()
|
let result = go#complete#GetInfo()
|
||||||
if !empty(result)
|
if !empty(result)
|
||||||
@ -147,12 +137,12 @@ function! go#complete#Info(auto)
|
|||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:trim_bracket(val)
|
function! s:trim_bracket(val) abort
|
||||||
let a:val.word = substitute(a:val.word, '[(){}\[\]]\+$', '', '')
|
let a:val.word = substitute(a:val.word, '[(){}\[\]]\+$', '', '')
|
||||||
return a:val
|
return a:val
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
fu! go#complete#Complete(findstart, base)
|
function! go#complete#Complete(findstart, base) abort
|
||||||
"findstart = 1 when we need to get the text length
|
"findstart = 1 when we need to get the text length
|
||||||
if a:findstart == 1
|
if a:findstart == 1
|
||||||
execute "silent let g:gocomplete_completions = " . s:gocodeAutocomplete()
|
execute "silent let g:gocomplete_completions = " . s:gocodeAutocomplete()
|
||||||
@ -167,4 +157,16 @@ fu! go#complete#Complete(findstart, base)
|
|||||||
endif
|
endif
|
||||||
endf
|
endf
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
function! go#complete#ToggleAutoTypeInfo() abort
|
||||||
|
if get(g:, "go_auto_type_info", 0)
|
||||||
|
let g:go_auto_type_info = 0
|
||||||
|
call go#util#EchoProgress("auto type info disabled")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
let g:go_auto_type_info = 1
|
||||||
|
call go#util#EchoProgress("auto type info enabled")
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
375
autoload/go/coverage.vim
Normal file
375
autoload/go/coverage.vim
Normal file
@ -0,0 +1,375 @@
|
|||||||
|
let s:toggle = 0
|
||||||
|
|
||||||
|
" Buffer creates a new cover profile with 'go test -coverprofile' and changes
|
||||||
|
" the current buffers highlighting to show covered and uncovered sections of
|
||||||
|
" the code. If run again it clears the annotation.
|
||||||
|
function! go#coverage#BufferToggle(bang, ...) abort
|
||||||
|
if s:toggle
|
||||||
|
call go#coverage#Clear()
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
if a:0 == 0
|
||||||
|
return call(function('go#coverage#Buffer'), [a:bang])
|
||||||
|
endif
|
||||||
|
|
||||||
|
return call(function('go#coverage#Buffer'), [a:bang] + a:000)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Buffer creates a new cover profile with 'go test -coverprofile' and changes
|
||||||
|
" the current buffers highlighting to show covered and uncovered sections of
|
||||||
|
" the code. Calling it again reruns the tests and shows the last updated
|
||||||
|
" coverage.
|
||||||
|
function! go#coverage#Buffer(bang, ...) abort
|
||||||
|
" we use matchaddpos() which was introduce with 7.4.330, be sure we have
|
||||||
|
" it: http://ftp.vim.org/vim/patches/7.4/7.4.330
|
||||||
|
if !exists("*matchaddpos")
|
||||||
|
call go#util#EchoError("GoCoverage is supported with Vim version 7.4-330 or later")
|
||||||
|
return -1
|
||||||
|
endif
|
||||||
|
|
||||||
|
" check if there is any test file, if not we just return
|
||||||
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
||||||
|
let dir = getcwd()
|
||||||
|
try
|
||||||
|
execute cd . fnameescape(expand("%:p:h"))
|
||||||
|
if empty(glob("*_test.go"))
|
||||||
|
call go#util#EchoError("no test files available")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
finally
|
||||||
|
execute cd . fnameescape(dir)
|
||||||
|
endtry
|
||||||
|
|
||||||
|
let s:toggle = 1
|
||||||
|
let l:tmpname = tempname()
|
||||||
|
|
||||||
|
if get(g:, 'go_echo_command_info', 1)
|
||||||
|
echon "vim-go: " | echohl Identifier | echon "testing ..." | echohl None
|
||||||
|
endif
|
||||||
|
|
||||||
|
if go#util#has_job()
|
||||||
|
call s:coverage_job({
|
||||||
|
\ 'cmd': ['go', 'test', '-coverprofile', l:tmpname] + a:000,
|
||||||
|
\ 'custom_cb': function('s:coverage_callback', [l:tmpname]),
|
||||||
|
\ 'bang': a:bang,
|
||||||
|
\ 'for': 'GoTest',
|
||||||
|
\ })
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let args = [a:bang, 0, "-coverprofile", l:tmpname]
|
||||||
|
if a:0
|
||||||
|
call extend(args, a:000)
|
||||||
|
endif
|
||||||
|
|
||||||
|
let disabled_term = 0
|
||||||
|
if get(g:, 'go_term_enabled')
|
||||||
|
let disabled_term = 1
|
||||||
|
let g:go_term_enabled = 0
|
||||||
|
endif
|
||||||
|
|
||||||
|
let id = call('go#test#Test', args)
|
||||||
|
|
||||||
|
if disabled_term
|
||||||
|
let g:go_term_enabled = 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
if has('nvim')
|
||||||
|
call go#jobcontrol#AddHandler(function('s:coverage_handler'))
|
||||||
|
let s:coverage_handler_jobs[id] = l:tmpname
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
if go#util#ShellError() == 0
|
||||||
|
call go#coverage#overlay(l:tmpname)
|
||||||
|
endif
|
||||||
|
|
||||||
|
call delete(l:tmpname)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Clear clears and resets the buffer annotation matches
|
||||||
|
function! go#coverage#Clear() abort
|
||||||
|
call clearmatches()
|
||||||
|
|
||||||
|
if exists("s:toggle") | let s:toggle = 0 | endif
|
||||||
|
|
||||||
|
" remove the autocmd we defined
|
||||||
|
augroup vim-go-coverage
|
||||||
|
autocmd!
|
||||||
|
augroup end
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Browser creates a new cover profile with 'go test -coverprofile' and opens
|
||||||
|
" a new HTML coverage page from that profile in a new browser
|
||||||
|
function! go#coverage#Browser(bang, ...) abort
|
||||||
|
let l:tmpname = tempname()
|
||||||
|
if go#util#has_job()
|
||||||
|
call s:coverage_job({
|
||||||
|
\ 'cmd': ['go', 'test', '-coverprofile', l:tmpname],
|
||||||
|
\ 'custom_cb': function('s:coverage_browser_callback', [l:tmpname]),
|
||||||
|
\ 'bang': a:bang,
|
||||||
|
\ 'for': 'GoTest',
|
||||||
|
\ })
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let args = [a:bang, 0, "-coverprofile", l:tmpname]
|
||||||
|
if a:0
|
||||||
|
call extend(args, a:000)
|
||||||
|
endif
|
||||||
|
|
||||||
|
let id = call('go#test#Test', args)
|
||||||
|
if has('nvim')
|
||||||
|
call go#jobcontrol#AddHandler(function('s:coverage_browser_handler'))
|
||||||
|
let s:coverage_browser_handler_jobs[id] = l:tmpname
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
if go#util#ShellError() == 0
|
||||||
|
let openHTML = 'go tool cover -html='.l:tmpname
|
||||||
|
call go#tool#ExecuteInDir(openHTML)
|
||||||
|
endif
|
||||||
|
|
||||||
|
call delete(l:tmpname)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Parses a single line from the cover file generated via go test -coverprofile
|
||||||
|
" and returns a single coverage profile block.
|
||||||
|
function! go#coverage#parsegocoverline(line) abort
|
||||||
|
" file:startline.col,endline.col numstmt count
|
||||||
|
let mx = '\([^:]\+\):\(\d\+\)\.\(\d\+\),\(\d\+\)\.\(\d\+\)\s\(\d\+\)\s\(\d\+\)'
|
||||||
|
let tokens = matchlist(a:line, mx)
|
||||||
|
let ret = {}
|
||||||
|
let ret.file = tokens[1]
|
||||||
|
let ret.startline = str2nr(tokens[2])
|
||||||
|
let ret.startcol = str2nr(tokens[3])
|
||||||
|
let ret.endline = str2nr(tokens[4])
|
||||||
|
let ret.endcol = str2nr(tokens[5])
|
||||||
|
let ret.numstmt = tokens[6]
|
||||||
|
let ret.cnt = tokens[7]
|
||||||
|
return ret
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Generates matches to be added to matchaddpos for the given coverage profile
|
||||||
|
" block
|
||||||
|
function! go#coverage#genmatch(cov) abort
|
||||||
|
let color = 'goCoverageCovered'
|
||||||
|
if a:cov.cnt == 0
|
||||||
|
let color = 'goCoverageUncover'
|
||||||
|
endif
|
||||||
|
|
||||||
|
let matches = []
|
||||||
|
|
||||||
|
" if start and end are the same, also specify the byte length
|
||||||
|
" example: foo.go:92.2,92.65 1 0
|
||||||
|
if a:cov.startline == a:cov.endline
|
||||||
|
call add(matches, {
|
||||||
|
\ 'group': color,
|
||||||
|
\ 'pos': [[a:cov.startline, a:cov.startcol, a:cov.endcol - a:cov.startcol]],
|
||||||
|
\ 'priority': 2,
|
||||||
|
\ })
|
||||||
|
return matches
|
||||||
|
endif
|
||||||
|
|
||||||
|
" add start columns. Because we don't know the length of the of
|
||||||
|
" the line, we assume it is at maximum 200 bytes. I know this is hacky,
|
||||||
|
" but that's only way of fixing the issue
|
||||||
|
call add(matches, {
|
||||||
|
\ 'group': color,
|
||||||
|
\ 'pos': [[a:cov.startline, a:cov.startcol, 200]],
|
||||||
|
\ 'priority': 2,
|
||||||
|
\ })
|
||||||
|
|
||||||
|
" and then the remaining lines
|
||||||
|
let start_line = a:cov.startline
|
||||||
|
while start_line < a:cov.endline
|
||||||
|
let start_line += 1
|
||||||
|
call add(matches, {
|
||||||
|
\ 'group': color,
|
||||||
|
\ 'pos': [[start_line]],
|
||||||
|
\ 'priority': 2,
|
||||||
|
\ })
|
||||||
|
endwhile
|
||||||
|
|
||||||
|
" finally end columns
|
||||||
|
call add(matches, {
|
||||||
|
\ 'group': color,
|
||||||
|
\ 'pos': [[a:cov.endline, a:cov.endcol-1]],
|
||||||
|
\ 'priority': 2,
|
||||||
|
\ })
|
||||||
|
|
||||||
|
return matches
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Reads the given coverprofile file and annotates the current buffer
|
||||||
|
function! go#coverage#overlay(file) abort
|
||||||
|
if !filereadable(a:file)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
let lines = readfile(a:file)
|
||||||
|
|
||||||
|
" cover mode, by default it's 'set'. Just here for debugging purposes
|
||||||
|
let mode = lines[0]
|
||||||
|
|
||||||
|
" contains matches for matchaddpos()
|
||||||
|
let matches = []
|
||||||
|
|
||||||
|
" first mark all lines as goCoverageNormalText. We use a custom group to not
|
||||||
|
" interfere with other buffers highlightings. Because the priority is
|
||||||
|
" lower than the cover and uncover matches, it'll be overridden.
|
||||||
|
let cnt = 1
|
||||||
|
while cnt <= line('$')
|
||||||
|
call add(matches, {'group': 'goCoverageNormalText', 'pos': [cnt], 'priority': 1})
|
||||||
|
let cnt += 1
|
||||||
|
endwhile
|
||||||
|
|
||||||
|
let fname = expand('%')
|
||||||
|
|
||||||
|
" when called for a _test.go file, run the coverage for the actuall file
|
||||||
|
" file
|
||||||
|
if fname =~# '^\f\+_test\.go$'
|
||||||
|
let l:root = split(fname, '_test.go$')[0]
|
||||||
|
let fname = l:root . ".go"
|
||||||
|
|
||||||
|
if !filereadable(fname)
|
||||||
|
call go#util#EchoError("couldn't find ".fname)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
" open the alternate file to show the coverage
|
||||||
|
exe ":edit ". fnamemodify(fname, ":p")
|
||||||
|
endif
|
||||||
|
|
||||||
|
" cov.file includes only the filename itself, without full path
|
||||||
|
let fname = fnamemodify(fname, ":t")
|
||||||
|
|
||||||
|
for line in lines[1:]
|
||||||
|
let cov = go#coverage#parsegocoverline(line)
|
||||||
|
|
||||||
|
" TODO(arslan): for now only include the coverage for the current
|
||||||
|
" buffer
|
||||||
|
if fname != fnamemodify(cov.file, ':t')
|
||||||
|
continue
|
||||||
|
endif
|
||||||
|
|
||||||
|
call extend(matches, go#coverage#genmatch(cov))
|
||||||
|
endfor
|
||||||
|
|
||||||
|
" clear the matches if we leave the buffer
|
||||||
|
augroup vim-go-coverage
|
||||||
|
autocmd!
|
||||||
|
autocmd BufWinLeave <buffer> call go#coverage#Clear()
|
||||||
|
augroup end
|
||||||
|
|
||||||
|
for m in matches
|
||||||
|
call matchaddpos(m.group, m.pos)
|
||||||
|
endfor
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
" ---------------------
|
||||||
|
" | Vim job callbacks |
|
||||||
|
" ---------------------
|
||||||
|
"
|
||||||
|
function s:coverage_job(args)
|
||||||
|
" autowrite is not enabled for jobs
|
||||||
|
call go#cmd#autowrite()
|
||||||
|
|
||||||
|
let status_dir = expand('%:p:h')
|
||||||
|
function! s:error_info_cb(job, exit_status, data) closure
|
||||||
|
let status = {
|
||||||
|
\ 'desc': 'last status',
|
||||||
|
\ 'type': "coverage",
|
||||||
|
\ 'state': "finished",
|
||||||
|
\ }
|
||||||
|
|
||||||
|
if a:exit_status
|
||||||
|
let status.state = "failed"
|
||||||
|
endif
|
||||||
|
|
||||||
|
call go#statusline#Update(status_dir, status)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
let a:args.error_info_cb = funcref('s:error_info_cb')
|
||||||
|
let callbacks = go#job#Spawn(a:args)
|
||||||
|
|
||||||
|
let start_options = {
|
||||||
|
\ 'callback': callbacks.callback,
|
||||||
|
\ 'exit_cb': callbacks.exit_cb,
|
||||||
|
\ }
|
||||||
|
|
||||||
|
" pre start
|
||||||
|
let dir = getcwd()
|
||||||
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
||||||
|
let jobdir = fnameescape(expand("%:p:h"))
|
||||||
|
execute cd . jobdir
|
||||||
|
|
||||||
|
call go#statusline#Update(status_dir, {
|
||||||
|
\ 'desc': "current status",
|
||||||
|
\ 'type': "coverage",
|
||||||
|
\ 'state': "started",
|
||||||
|
\})
|
||||||
|
|
||||||
|
call job_start(a:args.cmd, start_options)
|
||||||
|
|
||||||
|
" post start
|
||||||
|
execute cd . fnameescape(dir)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" coverage_callback is called when the coverage execution is finished
|
||||||
|
function! s:coverage_callback(coverfile, job, exit_status, data)
|
||||||
|
if a:exit_status == 0
|
||||||
|
call go#coverage#overlay(a:coverfile)
|
||||||
|
endif
|
||||||
|
|
||||||
|
call delete(a:coverfile)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:coverage_browser_callback(coverfile, job, exit_status, data)
|
||||||
|
if a:exit_status == 0
|
||||||
|
let openHTML = 'go tool cover -html='.a:coverfile
|
||||||
|
call go#tool#ExecuteInDir(openHTML)
|
||||||
|
endif
|
||||||
|
|
||||||
|
call delete(a:coverfile)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" -----------------------
|
||||||
|
" | Neovim job handlers |
|
||||||
|
" -----------------------
|
||||||
|
|
||||||
|
let s:coverage_handler_jobs = {}
|
||||||
|
let s:coverage_browser_handler_jobs = {}
|
||||||
|
|
||||||
|
function! s:coverage_handler(job, exit_status, data) abort
|
||||||
|
if !has_key(s:coverage_handler_jobs, a:job.id)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
let l:tmpname = s:coverage_handler_jobs[a:job.id]
|
||||||
|
if a:exit_status == 0
|
||||||
|
call go#coverage#overlay(l:tmpname)
|
||||||
|
endif
|
||||||
|
|
||||||
|
call delete(l:tmpname)
|
||||||
|
unlet s:coverage_handler_jobs[a:job.id]
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:coverage_browser_handler(job, exit_status, data) abort
|
||||||
|
if !has_key(s:coverage_browser_handler_jobs, a:job.id)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let l:tmpname = s:coverage_browser_handler_jobs[a:job.id]
|
||||||
|
if a:exit_status == 0
|
||||||
|
let openHTML = 'go tool cover -html='.l:tmpname
|
||||||
|
call go#tool#ExecuteInDir(openHTML)
|
||||||
|
endif
|
||||||
|
|
||||||
|
call delete(l:tmpname)
|
||||||
|
unlet s:coverage_browser_handler_jobs[a:job.id]
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
21
autoload/go/decls.vim
Normal file
21
autoload/go/decls.vim
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
if !exists('g:go_decls_mode')
|
||||||
|
let g:go_decls_mode = ''
|
||||||
|
endif
|
||||||
|
|
||||||
|
function! go#decls#Decls(mode, ...) abort
|
||||||
|
if g:go_decls_mode == 'ctrlp'
|
||||||
|
call ctrlp#init(call("ctrlp#decls#cmd", [a:mode] + a:000))
|
||||||
|
elseif g:go_decls_mode == 'fzf'
|
||||||
|
call call("fzf#decls#cmd", [a:mode] + a:000)
|
||||||
|
else
|
||||||
|
if globpath(&rtp, 'plugin/ctrlp.vim') != ""
|
||||||
|
call ctrlp#init(call("ctrlp#decls#cmd", [a:mode] + a:000))
|
||||||
|
elseif globpath(&rtp, 'plugin/fzf.vim') != ""
|
||||||
|
call call("fzf#decls#cmd", [a:mode] + a:000)
|
||||||
|
else
|
||||||
|
call go#util#EchoError("neither ctrlp.vim nor fzf.vim are installed. Please install either one")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
@ -1,111 +1,317 @@
|
|||||||
if !exists("g:go_godef_bin")
|
let s:go_stack = []
|
||||||
let g:go_godef_bin = "godef"
|
let s:go_stack_level = 0
|
||||||
endif
|
|
||||||
|
|
||||||
if go#vimproc#has_vimproc()
|
function! go#def#Jump(mode) abort
|
||||||
let s:vim_system = get(g:, 'gocomplete#system_function', 'vimproc#system2')
|
let fname = fnamemodify(expand("%"), ':p:gs?\\?/?')
|
||||||
else
|
|
||||||
let s:vim_system = get(g:, 'gocomplete#system_function', 'system')
|
|
||||||
endif
|
|
||||||
|
|
||||||
fu! s:system(str, ...)
|
" so guru right now is slow for some people. previously we were using
|
||||||
return call(s:vim_system, [a:str] + a:000)
|
" godef which also has it's own quirks. But this issue come up so many
|
||||||
endf
|
" times I've decided to support both. By default we still use guru as it
|
||||||
|
" covers all edge cases, but now anyone can switch to godef if they wish
|
||||||
" modified and improved version of vim-godef
|
let bin_name = get(g:, 'go_def_mode', 'guru')
|
||||||
function! go#def#Jump(...)
|
if bin_name == 'godef'
|
||||||
if !len(a:000)
|
if &modified
|
||||||
let arg = "-o=" . go#util#OffsetCursor()
|
" Write current unsaved buffer to a temp file and use the modified content
|
||||||
else
|
let l:tmpname = tempname()
|
||||||
let arg = a:1
|
call writefile(go#util#GetLines(), l:tmpname)
|
||||||
|
let fname = l:tmpname
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let bin_path = go#path#CheckBinPath(g:go_godef_bin)
|
let bin_path = go#path#CheckBinPath("godef")
|
||||||
|
if empty(bin_path)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
let command = printf("%s -f=%s -o=%s -t", go#util#Shellescape(bin_path),
|
||||||
|
\ go#util#Shellescape(fname), go#util#OffsetCursor())
|
||||||
|
let out = go#util#System(command)
|
||||||
|
if exists("l:tmpname")
|
||||||
|
call delete(l:tmpname)
|
||||||
|
endif
|
||||||
|
elseif bin_name == 'guru'
|
||||||
|
let bin_path = go#path#CheckBinPath("guru")
|
||||||
if empty(bin_path)
|
if empty(bin_path)
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let old_gopath = $GOPATH
|
let cmd = [bin_path]
|
||||||
let $GOPATH = go#path#Detect()
|
let stdin_content = ""
|
||||||
|
|
||||||
let fname = fnamemodify(expand("%"), ':p:gs?\\?/?')
|
if &modified
|
||||||
let command = bin_path . " -f=" . shellescape(fname) . " -i " . shellescape(arg)
|
let content = join(go#util#GetLines(), "\n")
|
||||||
|
let stdin_content = fname . "\n" . strlen(content) . "\n" . content
|
||||||
|
call add(cmd, "-modified")
|
||||||
|
endif
|
||||||
|
|
||||||
" get output of godef
|
if exists('g:go_build_tags')
|
||||||
let out = s:system(command, join(getbufline(bufnr('%'), 1, '$'), go#util#LineEnding()))
|
let tags = get(g:, 'go_build_tags')
|
||||||
|
call extend(cmd, ["-tags", tags])
|
||||||
|
endif
|
||||||
|
|
||||||
" jump to it
|
let fname = fname.':#'.go#util#OffsetCursor()
|
||||||
call s:godefJump(out, "")
|
call extend(cmd, ["definition", fname])
|
||||||
let $GOPATH = old_gopath
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
if go#util#has_job()
|
||||||
|
let l:spawn_args = {
|
||||||
|
\ 'cmd': cmd,
|
||||||
|
\ 'custom_cb': function('s:jump_to_declaration_cb', [a:mode, bin_name]),
|
||||||
|
\ }
|
||||||
|
|
||||||
function! go#def#JumpMode(mode)
|
if &modified
|
||||||
let arg = "-o=" . go#util#OffsetCursor()
|
let l:spawn_args.input = stdin_content
|
||||||
|
endif
|
||||||
|
|
||||||
let bin_path = go#path#CheckBinPath(g:go_godef_bin)
|
call go#util#EchoProgress("searching declaration ...")
|
||||||
if empty(bin_path)
|
|
||||||
|
call s:def_job(spawn_args)
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let old_gopath = $GOPATH
|
let command = join(cmd, " ")
|
||||||
let $GOPATH = go#path#Detect()
|
if &modified
|
||||||
|
let out = go#util#System(command, stdin_content)
|
||||||
let fname = fnamemodify(expand("%"), ':p:gs?\\?/?')
|
|
||||||
let command = bin_path . " -f=" . shellescape(fname) . " -i " . shellescape(arg)
|
|
||||||
|
|
||||||
" get output of godef
|
|
||||||
let out = s:system(command, join(getbufline(bufnr('%'), 1, '$'), go#util#LineEnding()))
|
|
||||||
|
|
||||||
call s:godefJump(out, a:mode)
|
|
||||||
let $GOPATH = old_gopath
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
function! s:getOffset()
|
|
||||||
return "-o=" . go#util#OffsetCursor()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
function! s:godefJump(out, mode)
|
|
||||||
let old_errorformat = &errorformat
|
|
||||||
let &errorformat = "%f:%l:%c"
|
|
||||||
|
|
||||||
if a:out =~ 'godef: '
|
|
||||||
let out = substitute(a:out, go#util#LineEnding() . '$', '', '')
|
|
||||||
echom out
|
|
||||||
else
|
else
|
||||||
let parts = split(a:out, ':')
|
let out = go#util#System(command)
|
||||||
" parts[0] contains filename
|
endif
|
||||||
let fileName = parts[0]
|
else
|
||||||
|
call go#util#EchoError('go_def_mode value: '. bin_name .' is not valid. Valid values are: [godef, guru]')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
" put the error format into location list so we can jump automatically to
|
if go#util#ShellError() != 0
|
||||||
" it
|
call go#util#EchoError(out)
|
||||||
lgetexpr a:out
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
call go#def#jump_to_declaration(out, a:mode, bin_name)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:jump_to_declaration_cb(mode, bin_name, job, exit_status, data) abort
|
||||||
|
if a:exit_status != 0
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
call go#def#jump_to_declaration(a:data[0], a:mode, a:bin_name)
|
||||||
|
call go#util#EchoSuccess(fnamemodify(a:data[0], ":t"))
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! go#def#jump_to_declaration(out, mode, bin_name) abort
|
||||||
|
let final_out = a:out
|
||||||
|
if a:bin_name == "godef"
|
||||||
|
" append the type information to the same line so our we can parse it.
|
||||||
|
" This makes it compatible with guru output.
|
||||||
|
let final_out = join(split(a:out, '\n'), ':')
|
||||||
|
endif
|
||||||
|
|
||||||
|
" strip line ending
|
||||||
|
let out = split(final_out, go#util#LineEnding())[0]
|
||||||
|
if go#util#IsWin()
|
||||||
|
let parts = split(out, '\(^[a-zA-Z]\)\@<!:')
|
||||||
|
else
|
||||||
|
let parts = split(out, ':')
|
||||||
|
endif
|
||||||
|
|
||||||
|
let filename = parts[0]
|
||||||
|
let line = parts[1]
|
||||||
|
let col = parts[2]
|
||||||
|
let ident = parts[3]
|
||||||
|
|
||||||
|
" Remove anything newer than the current position, just like basic
|
||||||
|
" vim tag support
|
||||||
|
if s:go_stack_level == 0
|
||||||
|
let s:go_stack = []
|
||||||
|
else
|
||||||
|
let s:go_stack = s:go_stack[0:s:go_stack_level-1]
|
||||||
|
endif
|
||||||
|
|
||||||
|
" increment the stack counter
|
||||||
|
let s:go_stack_level += 1
|
||||||
|
|
||||||
|
" push it on to the jumpstack
|
||||||
|
let stack_entry = {'line': line("."), 'col': col("."), 'file': expand('%:p'), 'ident': ident}
|
||||||
|
call add(s:go_stack, stack_entry)
|
||||||
|
|
||||||
" needed for restoring back user setting this is because there are two
|
" needed for restoring back user setting this is because there are two
|
||||||
" modes of switchbuf which we need based on the split mode
|
" modes of switchbuf which we need based on the split mode
|
||||||
let old_switchbuf = &switchbuf
|
let old_switchbuf = &switchbuf
|
||||||
|
|
||||||
if a:mode == "tab"
|
normal! m'
|
||||||
let &switchbuf = "usetab"
|
if filename != fnamemodify(expand("%"), ':p:gs?\\?/?')
|
||||||
|
" jump to existing buffer if, 1. we have enabled it, 2. the buffer is loaded
|
||||||
if bufloaded(fileName) == 0
|
" and 3. there is buffer window number we switch to
|
||||||
tab split
|
if get(g:, 'go_def_reuse_buffer', 0) && bufloaded(filename) != 0 && bufwinnr(filename) != -1
|
||||||
endif
|
" jumpt to existing buffer if it exists
|
||||||
|
execute bufwinnr(filename) . 'wincmd w'
|
||||||
else
|
else
|
||||||
if a:mode == "split"
|
if &modified
|
||||||
|
let cmd = 'hide edit'
|
||||||
|
else
|
||||||
|
let cmd = 'edit'
|
||||||
|
endif
|
||||||
|
|
||||||
|
if a:mode == "tab"
|
||||||
|
let &switchbuf = "useopen,usetab,newtab"
|
||||||
|
if bufloaded(filename) == 0
|
||||||
|
tab split
|
||||||
|
else
|
||||||
|
let cmd = 'sbuf'
|
||||||
|
endif
|
||||||
|
elseif a:mode == "split"
|
||||||
split
|
split
|
||||||
elseif a:mode == "vsplit"
|
elseif a:mode == "vsplit"
|
||||||
vsplit
|
vsplit
|
||||||
endif
|
endif
|
||||||
endif
|
|
||||||
|
|
||||||
" jump to file now
|
" open the file and jump to line and column
|
||||||
sil ll 1
|
exec cmd fnameescape(fnamemodify(filename, ':.'))
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
call cursor(line, col)
|
||||||
|
|
||||||
|
" also align the line to middle of the view
|
||||||
normal! zz
|
normal! zz
|
||||||
|
|
||||||
let &switchbuf = old_switchbuf
|
let &switchbuf = old_switchbuf
|
||||||
end
|
|
||||||
let &errorformat = old_errorformat
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
function! go#def#SelectStackEntry() abort
|
||||||
|
let target_window = go#ui#GetReturnWindow()
|
||||||
|
if empty(target_window)
|
||||||
|
let target_window = winnr()
|
||||||
|
endif
|
||||||
|
|
||||||
|
let highlighted_stack_entry = matchstr(getline("."), '^..\zs\(\d\+\)')
|
||||||
|
if !empty(highlighted_stack_entry)
|
||||||
|
execute target_window . "wincmd w"
|
||||||
|
call go#def#Stack(str2nr(highlighted_stack_entry))
|
||||||
|
endif
|
||||||
|
|
||||||
|
call go#ui#CloseWindow()
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! go#def#StackUI() abort
|
||||||
|
if len(s:go_stack) == 0
|
||||||
|
call go#util#EchoError("godef stack empty")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let stackOut = ['" <Up>,<Down>:navigate <Enter>:jump <Esc>,q:exit']
|
||||||
|
|
||||||
|
let i = 0
|
||||||
|
while i < len(s:go_stack)
|
||||||
|
let entry = s:go_stack[i]
|
||||||
|
let prefix = ""
|
||||||
|
|
||||||
|
if i == s:go_stack_level
|
||||||
|
let prefix = ">"
|
||||||
|
else
|
||||||
|
let prefix = " "
|
||||||
|
endif
|
||||||
|
|
||||||
|
call add(stackOut, printf("%s %d %s|%d col %d|%s",
|
||||||
|
\ prefix, i+1, entry["file"], entry["line"], entry["col"], entry["ident"]))
|
||||||
|
let i += 1
|
||||||
|
endwhile
|
||||||
|
|
||||||
|
if s:go_stack_level == i
|
||||||
|
call add(stackOut, "> ")
|
||||||
|
endif
|
||||||
|
|
||||||
|
call go#ui#OpenWindow("GoDef Stack", stackOut, "godefstack")
|
||||||
|
|
||||||
|
noremap <buffer> <silent> <CR> :<C-U>call go#def#SelectStackEntry()<CR>
|
||||||
|
noremap <buffer> <silent> <Esc> :<C-U>call go#ui#CloseWindow()<CR>
|
||||||
|
noremap <buffer> <silent> q :<C-U>call go#ui#CloseWindow()<CR>
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! go#def#StackClear(...) abort
|
||||||
|
let s:go_stack = []
|
||||||
|
let s:go_stack_level = 0
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! go#def#StackPop(...) abort
|
||||||
|
if len(s:go_stack) == 0
|
||||||
|
call go#util#EchoError("godef stack empty")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
if s:go_stack_level == 0
|
||||||
|
call go#util#EchoError("at bottom of the godef stack")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
if !len(a:000)
|
||||||
|
let numPop = 1
|
||||||
|
else
|
||||||
|
let numPop = a:1
|
||||||
|
endif
|
||||||
|
|
||||||
|
let newLevel = str2nr(s:go_stack_level) - str2nr(numPop)
|
||||||
|
call go#def#Stack(newLevel + 1)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! go#def#Stack(...) abort
|
||||||
|
if len(s:go_stack) == 0
|
||||||
|
call go#util#EchoError("godef stack empty")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
if !len(a:000)
|
||||||
|
" Display interactive stack
|
||||||
|
call go#def#StackUI()
|
||||||
|
return
|
||||||
|
else
|
||||||
|
let jumpTarget = a:1
|
||||||
|
endif
|
||||||
|
|
||||||
|
if jumpTarget !~ '^\d\+$'
|
||||||
|
if jumpTarget !~ '^\s*$'
|
||||||
|
call go#util#EchoError("location must be a number")
|
||||||
|
endif
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let jumpTarget = str2nr(jumpTarget) - 1
|
||||||
|
|
||||||
|
if jumpTarget >= 0 && jumpTarget < len(s:go_stack)
|
||||||
|
let s:go_stack_level = jumpTarget
|
||||||
|
let target = s:go_stack[s:go_stack_level]
|
||||||
|
|
||||||
|
" jump
|
||||||
|
if expand('%:p') != target["file"]
|
||||||
|
if &modified
|
||||||
|
exec 'hide edit' target["file"]
|
||||||
|
else
|
||||||
|
exec 'edit' target["file"]
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
call cursor(target["line"], target["col"])
|
||||||
|
normal! zz
|
||||||
|
else
|
||||||
|
call go#util#EchoError("invalid location. Try :GoDefStack to see the list of valid entries")
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function s:def_job(args) abort
|
||||||
|
function! s:error_info_cb(job, exit_status, data) closure
|
||||||
|
" do not print anything during async definition search&jump
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
let a:args.error_info_cb = funcref('s:error_info_cb')
|
||||||
|
let callbacks = go#job#Spawn(a:args)
|
||||||
|
|
||||||
|
let start_options = {
|
||||||
|
\ 'callback': callbacks.callback,
|
||||||
|
\ 'exit_cb': callbacks.exit_cb,
|
||||||
|
\ }
|
||||||
|
|
||||||
|
if &modified
|
||||||
|
let l:tmpname = tempname()
|
||||||
|
call writefile(split(a:args.input, "\n"), l:tmpname, "b")
|
||||||
|
let l:start_options.in_io = "file"
|
||||||
|
let l:start_options.in_name = l:tmpname
|
||||||
|
endif
|
||||||
|
|
||||||
|
call job_start(a:args.cmd, start_options)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
37
autoload/go/def_test.vim
Normal file
37
autoload/go/def_test.vim
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
func! Test_jump_to_declaration_guru() abort
|
||||||
|
try
|
||||||
|
let l:filename = 'def/jump.go'
|
||||||
|
let lnum = 5
|
||||||
|
let col = 6
|
||||||
|
let l:tmp = gotest#load_fixture(l:filename)
|
||||||
|
|
||||||
|
let guru_out = printf("%s:%d:%d: defined here as func main", filename, lnum, col)
|
||||||
|
call go#def#jump_to_declaration(guru_out, "", 'guru')
|
||||||
|
|
||||||
|
call assert_equal(filename, bufname("%"))
|
||||||
|
call assert_equal(lnum, getcurpos()[1])
|
||||||
|
call assert_equal(col, getcurpos()[2])
|
||||||
|
finally
|
||||||
|
call delete(l:tmp, 'rf')
|
||||||
|
endtry
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func! Test_jump_to_declaration_godef() abort
|
||||||
|
try
|
||||||
|
let filename = 'def/jump.go'
|
||||||
|
let lnum = 5
|
||||||
|
let col = 6
|
||||||
|
let l:tmp = gotest#load_fixture(l:filename)
|
||||||
|
|
||||||
|
let godef_out = printf("%s:%d:%d\ndefined here as func main", filename, lnum, col)
|
||||||
|
call go#def#jump_to_declaration(godef_out, "", 'godef')
|
||||||
|
|
||||||
|
call assert_equal(filename, bufname("%"))
|
||||||
|
call assert_equal(lnum, getcurpos()[1])
|
||||||
|
call assert_equal(col, getcurpos()[2])
|
||||||
|
finally
|
||||||
|
call delete(l:tmp, 'rf')
|
||||||
|
endtry
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
@ -1,42 +1,188 @@
|
|||||||
" Copyright 2011 The Go Authors. All rights reserved.
|
" Copyright 2011 The Go Authors. All rights reserved.
|
||||||
" Use of this source code is governed by a BSD-style
|
" Use of this source code is governed by a BSD-style
|
||||||
" license that can be found in the LICENSE file.
|
" license that can be found in the LICENSE file.
|
||||||
"
|
|
||||||
" godoc.vim: Vim command to see godoc.
|
|
||||||
"
|
|
||||||
"
|
|
||||||
" Commands:
|
|
||||||
"
|
|
||||||
" :GoDoc
|
|
||||||
"
|
|
||||||
" Open the relevant Godoc for either the word[s] passed to the command or
|
|
||||||
" the, by default, the word under the cursor.
|
|
||||||
"
|
|
||||||
" Options:
|
|
||||||
"
|
|
||||||
" g:go_godoc_commands [default=1]
|
|
||||||
"
|
|
||||||
" Flag to indicate whether to enable the commands listed above.
|
|
||||||
|
|
||||||
let s:buf_nr = -1
|
let s:buf_nr = -1
|
||||||
|
|
||||||
if !exists("g:go_doc_command")
|
if !exists("g:go_doc_command")
|
||||||
let g:go_doc_command = "godoc"
|
let g:go_doc_command = ["godoc"]
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if !exists("g:go_doc_options")
|
function! go#doc#OpenBrowser(...) abort
|
||||||
let g:go_doc_options = ""
|
" check if we have gogetdoc as it gives us more and accurate information.
|
||||||
endif
|
" Only supported if we have json_decode as it's not worth to parse the plain
|
||||||
|
" non-json output of gogetdoc
|
||||||
|
let bin_path = go#path#CheckBinPath('gogetdoc')
|
||||||
|
if !empty(bin_path) && exists('*json_decode')
|
||||||
|
let json_out = s:gogetdoc(1)
|
||||||
|
if go#util#ShellError() != 0
|
||||||
|
call go#util#EchoError(json_out)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let out = json_decode(json_out)
|
||||||
|
if type(out) != type({})
|
||||||
|
call go#util#EchoError("gogetdoc output is malformed")
|
||||||
|
endif
|
||||||
|
|
||||||
|
let import = out["import"]
|
||||||
|
let name = out["name"]
|
||||||
|
let decl = out["decl"]
|
||||||
|
|
||||||
|
let godoc_url = get(g:, 'go_doc_url', 'https://godoc.org')
|
||||||
|
if godoc_url isnot 'https://godoc.org'
|
||||||
|
" strip last '/' character if available
|
||||||
|
let last_char = strlen(godoc_url) - 1
|
||||||
|
if godoc_url[last_char] == '/'
|
||||||
|
let godoc_url = strpart(godoc_url, 0, last_char)
|
||||||
|
endif
|
||||||
|
|
||||||
|
" custom godoc installations expects it
|
||||||
|
let godoc_url .= "/pkg"
|
||||||
|
endif
|
||||||
|
|
||||||
|
let godoc_url .= "/" . import
|
||||||
|
if decl !~ "^package"
|
||||||
|
let godoc_url .= "#" . name
|
||||||
|
endif
|
||||||
|
|
||||||
|
echo godoc_url
|
||||||
|
|
||||||
|
call go#tool#OpenBrowser(godoc_url)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let pkgs = s:godocWord(a:000)
|
||||||
|
if empty(pkgs)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let pkg = pkgs[0]
|
||||||
|
let exported_name = pkgs[1]
|
||||||
|
|
||||||
|
" example url: https://godoc.org/github.com/fatih/set#Set
|
||||||
|
let godoc_url = "https://godoc.org/" . pkg . "#" . exported_name
|
||||||
|
call go#tool#OpenBrowser(godoc_url)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! go#doc#Open(newmode, mode, ...) abort
|
||||||
|
" With argument: run "godoc [arg]".
|
||||||
|
if len(a:000)
|
||||||
|
if empty(go#path#CheckBinPath(g:go_doc_command[0]))
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let command = printf("%s %s", go#util#Shelljoin(g:go_doc_command), join(a:000, ' '))
|
||||||
|
let out = go#util#System(command)
|
||||||
|
" Without argument: run gogetdoc on cursor position.
|
||||||
|
else
|
||||||
|
let out = s:gogetdoc(0)
|
||||||
|
if out == -1
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
if go#util#ShellError() != 0
|
||||||
|
call go#util#EchoError(out)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
call s:GodocView(a:newmode, a:mode, out)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:GodocView(newposition, position, content) abort
|
||||||
|
" reuse existing buffer window if it exists otherwise create a new one
|
||||||
|
let is_visible = bufexists(s:buf_nr) && bufwinnr(s:buf_nr) != -1
|
||||||
|
if !bufexists(s:buf_nr)
|
||||||
|
execute a:newposition
|
||||||
|
sil file `="[Godoc]"`
|
||||||
|
let s:buf_nr = bufnr('%')
|
||||||
|
elseif bufwinnr(s:buf_nr) == -1
|
||||||
|
execute a:position
|
||||||
|
execute s:buf_nr . 'buffer'
|
||||||
|
elseif bufwinnr(s:buf_nr) != bufwinnr('%')
|
||||||
|
execute bufwinnr(s:buf_nr) . 'wincmd w'
|
||||||
|
endif
|
||||||
|
|
||||||
|
" if window was not visible then resize it
|
||||||
|
if !is_visible
|
||||||
|
if a:position == "split"
|
||||||
|
" cap window height to 20, but resize it for smaller contents
|
||||||
|
let max_height = get(g:, "go_doc_max_height", 20)
|
||||||
|
let content_height = len(split(a:content, "\n"))
|
||||||
|
if content_height > max_height
|
||||||
|
exe 'resize ' . max_height
|
||||||
|
else
|
||||||
|
exe 'resize ' . content_height
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
" set a sane maximum width for vertical splits. In this case the minimum
|
||||||
|
" that fits the godoc for package http without extra linebreaks and line
|
||||||
|
" numbers on
|
||||||
|
exe 'vertical resize 84'
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
setlocal filetype=godoc
|
||||||
|
setlocal bufhidden=delete
|
||||||
|
setlocal buftype=nofile
|
||||||
|
setlocal noswapfile
|
||||||
|
setlocal nobuflisted
|
||||||
|
setlocal nocursorline
|
||||||
|
setlocal nocursorcolumn
|
||||||
|
setlocal iskeyword+=:
|
||||||
|
setlocal iskeyword-=-
|
||||||
|
|
||||||
|
setlocal modifiable
|
||||||
|
%delete _
|
||||||
|
call append(0, split(a:content, "\n"))
|
||||||
|
sil $delete _
|
||||||
|
setlocal nomodifiable
|
||||||
|
sil normal! gg
|
||||||
|
|
||||||
|
" close easily with <esc> or enter
|
||||||
|
noremap <buffer> <silent> <CR> :<C-U>close<CR>
|
||||||
|
noremap <buffer> <silent> <Esc> :<C-U>close<CR>
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:gogetdoc(json) abort
|
||||||
|
" check if we have 'gogetdoc' and use it automatically
|
||||||
|
let bin_path = go#path#CheckBinPath('gogetdoc')
|
||||||
|
if empty(bin_path)
|
||||||
|
return -1
|
||||||
|
endif
|
||||||
|
|
||||||
|
let cmd = [go#util#Shellescape(bin_path)]
|
||||||
|
|
||||||
|
let offset = go#util#OffsetCursor()
|
||||||
|
let fname = expand("%:p:gs!\\!/!")
|
||||||
|
let pos = shellescape(fname.':#'.offset)
|
||||||
|
|
||||||
|
let cmd += ["-pos", pos]
|
||||||
|
if a:json
|
||||||
|
let cmd += ["-json"]
|
||||||
|
endif
|
||||||
|
|
||||||
|
let command = join(cmd, " ")
|
||||||
|
|
||||||
|
if &modified
|
||||||
|
let command .= " -modified"
|
||||||
|
let out = go#util#System(command, go#util#archive())
|
||||||
|
else
|
||||||
|
let out = go#util#System(command)
|
||||||
|
endif
|
||||||
|
|
||||||
|
return out
|
||||||
|
endfunction
|
||||||
|
|
||||||
" returns the package and exported name. exported name might be empty.
|
" returns the package and exported name. exported name might be empty.
|
||||||
" ie: fmt and Println
|
" ie: fmt and Println
|
||||||
" ie: github.com/fatih/set and New
|
" ie: github.com/fatih/set and New
|
||||||
function! s:godocWord(args)
|
function! s:godocWord(args) abort
|
||||||
if !executable('godoc')
|
if !executable('godoc')
|
||||||
echohl WarningMsg
|
let msg = "godoc command not found."
|
||||||
echo "godoc command not found."
|
let msg .= " install with: go get golang.org/x/tools/cmd/godoc"
|
||||||
echo " install with: go get golang.org/x/tools/cmd/godoc"
|
call go#util#EchoWarning(msg)
|
||||||
echohl None
|
|
||||||
return []
|
return []
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -71,7 +217,7 @@ function! s:godocWord(args)
|
|||||||
return [pkg, exported_name]
|
return [pkg, exported_name]
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:godocNotFound(content)
|
function! s:godocNotFound(content) abort
|
||||||
if len(a:content) == 0
|
if len(a:content) == 0
|
||||||
return 1
|
return 1
|
||||||
endif
|
endif
|
||||||
@ -79,93 +225,5 @@ function! s:godocNotFound(content)
|
|||||||
return a:content =~# '^.*: no such file or directory\n$'
|
return a:content =~# '^.*: no such file or directory\n$'
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! go#doc#OpenBrowser(...)
|
|
||||||
let pkgs = s:godocWord(a:000)
|
|
||||||
if empty(pkgs)
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
|
|
||||||
let pkg = pkgs[0]
|
" vim: sw=2 ts=2 et
|
||||||
let exported_name = pkgs[1]
|
|
||||||
|
|
||||||
" example url: https://godoc.org/github.com/fatih/set#Set
|
|
||||||
let godoc_url = "https://godoc.org/" . pkg . "#" . exported_name
|
|
||||||
call go#tool#OpenBrowser(godoc_url)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! go#doc#Open(newmode, mode, ...)
|
|
||||||
let pkgs = s:godocWord(a:000)
|
|
||||||
if empty(pkgs)
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
|
|
||||||
let pkg = pkgs[0]
|
|
||||||
let exported_name = pkgs[1]
|
|
||||||
|
|
||||||
let command = g:go_doc_command . ' ' . g:go_doc_options . ' ' . pkg
|
|
||||||
|
|
||||||
silent! let content = system(command)
|
|
||||||
if v:shell_error || s:godocNotFound(content)
|
|
||||||
echo 'No documentation found for "' . pkg . '".'
|
|
||||||
return -1
|
|
||||||
endif
|
|
||||||
|
|
||||||
call s:GodocView(a:newmode, a:mode, content)
|
|
||||||
|
|
||||||
if exported_name == ''
|
|
||||||
silent! normal! gg
|
|
||||||
return -1
|
|
||||||
endif
|
|
||||||
|
|
||||||
" jump to the specified name
|
|
||||||
if search('^func ' . exported_name . '(')
|
|
||||||
silent! normal! zt
|
|
||||||
return -1
|
|
||||||
endif
|
|
||||||
|
|
||||||
if search('^type ' . exported_name)
|
|
||||||
silent! normal! zt
|
|
||||||
return -1
|
|
||||||
endif
|
|
||||||
|
|
||||||
if search('^\%(const\|var\|type\|\s\+\) ' . pkg . '\s\+=\s')
|
|
||||||
silent! normal! zt
|
|
||||||
return -1
|
|
||||||
endif
|
|
||||||
|
|
||||||
" nothing found, jump to top
|
|
||||||
silent! normal! gg
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! s:GodocView(newposition, position, content)
|
|
||||||
" reuse existing buffer window if it exists otherwise create a new one
|
|
||||||
if !bufexists(s:buf_nr)
|
|
||||||
execute a:newposition
|
|
||||||
sil file `="[Godoc]"`
|
|
||||||
let s:buf_nr = bufnr('%')
|
|
||||||
elseif bufwinnr(s:buf_nr) == -1
|
|
||||||
execute a:position
|
|
||||||
execute s:buf_nr . 'buffer'
|
|
||||||
elseif bufwinnr(s:buf_nr) != bufwinnr('%')
|
|
||||||
execute bufwinnr(s:buf_nr) . 'wincmd w'
|
|
||||||
endif
|
|
||||||
|
|
||||||
setlocal filetype=godoc
|
|
||||||
setlocal bufhidden=delete
|
|
||||||
setlocal buftype=nofile
|
|
||||||
setlocal noswapfile
|
|
||||||
setlocal nobuflisted
|
|
||||||
setlocal nocursorline
|
|
||||||
setlocal nocursorcolumn
|
|
||||||
setlocal iskeyword+=:
|
|
||||||
setlocal iskeyword-=-
|
|
||||||
|
|
||||||
setlocal modifiable
|
|
||||||
%delete _
|
|
||||||
call append(0, split(a:content, "\n"))
|
|
||||||
sil $delete _
|
|
||||||
setlocal nomodifiable
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
|
||||||
|
|||||||
62
autoload/go/fillstruct.vim
Normal file
62
autoload/go/fillstruct.vim
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
function! go#fillstruct#FillStruct() abort
|
||||||
|
let l:cmd = ['fillstruct',
|
||||||
|
\ '-file', bufname(''),
|
||||||
|
\ '-offset', go#util#OffsetCursor(),
|
||||||
|
\ '-line', line('.')]
|
||||||
|
|
||||||
|
" Read from stdin if modified.
|
||||||
|
if &modified
|
||||||
|
call add(l:cmd, '-modified')
|
||||||
|
let [l:out, l:err] = go#util#Exec(l:cmd, go#util#archive())
|
||||||
|
else
|
||||||
|
let [l:out, l:err] = go#util#Exec(l:cmd)
|
||||||
|
endif
|
||||||
|
|
||||||
|
if l:err
|
||||||
|
call go#util#EchoError(l:out)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
try
|
||||||
|
let l:json = json_decode(l:out)
|
||||||
|
catch
|
||||||
|
call go#util#EchoError(l:out)
|
||||||
|
return
|
||||||
|
endtry
|
||||||
|
|
||||||
|
" Output is array:
|
||||||
|
"[
|
||||||
|
" {"start": 92, "end": 106, "code": "mail.Address{\n\tName: \"\",\n\tAddress: \"\",\n}"},
|
||||||
|
" {...second struct...}
|
||||||
|
" ]
|
||||||
|
|
||||||
|
let l:pos = getpos('.')
|
||||||
|
|
||||||
|
try
|
||||||
|
for l:struct in l:json
|
||||||
|
let l:code = split(l:struct['code'], "\n")
|
||||||
|
|
||||||
|
" Add any code before/after the struct.
|
||||||
|
exe l:struct['start'] . 'go'
|
||||||
|
let l:code[0] = getline('.')[:col('.')-1] . l:code[0]
|
||||||
|
exe l:struct['end'] . 'go'
|
||||||
|
let l:code[len(l:code)-1] .= getline('.')[col('.'):]
|
||||||
|
|
||||||
|
" Indent every line except the first one; makes it look nice.
|
||||||
|
let l:indent = repeat("\t", indent('.') / &tabstop)
|
||||||
|
for l:i in range(1, len(l:code)-1)
|
||||||
|
let l:code[l:i] = l:indent . l:code[l:i]
|
||||||
|
endfor
|
||||||
|
|
||||||
|
" Out with the old ...
|
||||||
|
exe 'normal! ' . l:struct['start'] . 'gov' . l:struct['end'] . 'gox'
|
||||||
|
" ... in with the new.
|
||||||
|
call setline('.', l:code[0])
|
||||||
|
call append('.', l:code[1:])
|
||||||
|
endfor
|
||||||
|
finally
|
||||||
|
call setpos('.', l:pos)
|
||||||
|
endtry
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
90
autoload/go/fillstruct_test.vim
Normal file
90
autoload/go/fillstruct_test.vim
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
func! Test_fillstruct() abort
|
||||||
|
try
|
||||||
|
let l:tmp = gotest#write_file('a/a.go', [
|
||||||
|
\ 'package a',
|
||||||
|
\ 'import "net/mail"',
|
||||||
|
\ "var addr = mail.\x1fAddress{}"])
|
||||||
|
|
||||||
|
call go#fillstruct#FillStruct()
|
||||||
|
call gotest#assert_buffer(1, [
|
||||||
|
\ 'var addr = mail.Address{',
|
||||||
|
\ '\tName: "",',
|
||||||
|
\ '\tAddress: "",',
|
||||||
|
\ '}'])
|
||||||
|
finally
|
||||||
|
call delete(l:tmp, 'rf')
|
||||||
|
endtry
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func! Test_fillstruct_line() abort
|
||||||
|
try
|
||||||
|
let l:tmp = gotest#write_file('a/a.go', [
|
||||||
|
\ 'package a',
|
||||||
|
\ 'import "net/mail"',
|
||||||
|
\ "\x1f" . 'var addr = mail.Address{}'])
|
||||||
|
|
||||||
|
call go#fillstruct#FillStruct()
|
||||||
|
call gotest#assert_buffer(1, [
|
||||||
|
\ 'var addr = mail.Address{',
|
||||||
|
\ '\tName: "",',
|
||||||
|
\ '\tAddress: "",',
|
||||||
|
\ '}'])
|
||||||
|
finally
|
||||||
|
call delete(l:tmp, 'rf')
|
||||||
|
endtry
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func! Test_fillstruct_two_line() abort
|
||||||
|
try
|
||||||
|
let l:tmp = gotest#write_file('a/a.go', [
|
||||||
|
\ 'package a',
|
||||||
|
\ 'import (',
|
||||||
|
\ '"fmt"',
|
||||||
|
\ '"net/mail"',
|
||||||
|
\ ')',
|
||||||
|
\ "\x1f" . 'func x() { fmt.Println(mail.Address{}, mail.Address{}) }'])
|
||||||
|
|
||||||
|
call go#fillstruct#FillStruct()
|
||||||
|
call gotest#assert_buffer(1, [
|
||||||
|
\ 'import (',
|
||||||
|
\ '"fmt"',
|
||||||
|
\ '"net/mail"',
|
||||||
|
\ ')',
|
||||||
|
\ 'func x() { fmt.Println(mail.Address{',
|
||||||
|
\ '\tName: "",',
|
||||||
|
\ '\tAddress: "",',
|
||||||
|
\ '}, mail.Address{',
|
||||||
|
\ '\tName: "",',
|
||||||
|
\ '\tAddress: "",',
|
||||||
|
\ '}) }'])
|
||||||
|
finally
|
||||||
|
"call delete(l:tmp, 'rf')
|
||||||
|
endtry
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func! Test_fillstruct_two_cursor() abort
|
||||||
|
try
|
||||||
|
let l:tmp = gotest#write_file('a/a.go', [
|
||||||
|
\ 'package a',
|
||||||
|
\ 'import (',
|
||||||
|
\ '"fmt"',
|
||||||
|
\ '"net/mail"',
|
||||||
|
\ ')',
|
||||||
|
\ "func x() { fmt.Println(mail.Address{}, mail.Ad\x1fdress{}) }"])
|
||||||
|
|
||||||
|
call go#fillstruct#FillStruct()
|
||||||
|
call gotest#assert_buffer(1, [
|
||||||
|
\ 'import (',
|
||||||
|
\ '"fmt"',
|
||||||
|
\ '"net/mail"',
|
||||||
|
\ ')',
|
||||||
|
\ 'func x() { fmt.Println(mail.Address{}, mail.Address{',
|
||||||
|
\ '\tName: "",',
|
||||||
|
\ '\tAddress: "",',
|
||||||
|
\ '}) }'])
|
||||||
|
finally
|
||||||
|
call delete(l:tmp, 'rf')
|
||||||
|
endtry
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
@ -2,43 +2,21 @@
|
|||||||
" Use of this source code is governed by a BSD-style
|
" Use of this source code is governed by a BSD-style
|
||||||
" license that can be found in the LICENSE file.
|
" license that can be found in the LICENSE file.
|
||||||
"
|
"
|
||||||
" fmt.vim: Vim command to format Go files with gofmt.
|
" fmt.vim: Vim command to format Go files with gofmt (and gofmt compatible
|
||||||
"
|
" toorls, such as goimports).
|
||||||
" This filetype plugin add a new commands for go buffers:
|
|
||||||
"
|
|
||||||
" :Fmt
|
|
||||||
"
|
|
||||||
" Filter the current Go buffer through gofmt.
|
|
||||||
" It tries to preserve cursor position and avoids
|
|
||||||
" replacing the buffer with stderr output.
|
|
||||||
"
|
|
||||||
" Options:
|
|
||||||
"
|
|
||||||
" g:go_fmt_command [default="gofmt"]
|
|
||||||
"
|
|
||||||
" Flag naming the gofmt executable to use.
|
|
||||||
"
|
|
||||||
" g:go_fmt_autosave [default=1]
|
|
||||||
"
|
|
||||||
" Flag to auto call :Fmt when saved file
|
|
||||||
"
|
|
||||||
|
|
||||||
if !exists("g:go_fmt_command")
|
if !exists("g:go_fmt_command")
|
||||||
let g:go_fmt_command = "gofmt"
|
let g:go_fmt_command = "gofmt"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if !exists("g:go_goimports_bin")
|
if !exists('g:go_fmt_options')
|
||||||
let g:go_goimports_bin = "goimports"
|
let g:go_fmt_options = ''
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if !exists('g:go_fmt_fail_silently')
|
if !exists('g:go_fmt_fail_silently')
|
||||||
let g:go_fmt_fail_silently = 0
|
let g:go_fmt_fail_silently = 0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if !exists('g:go_fmt_options')
|
|
||||||
let g:go_fmt_options = ''
|
|
||||||
endif
|
|
||||||
|
|
||||||
if !exists("g:go_fmt_experimental")
|
if !exists("g:go_fmt_experimental")
|
||||||
let g:go_fmt_experimental = 0
|
let g:go_fmt_experimental = 0
|
||||||
endif
|
endif
|
||||||
@ -51,7 +29,7 @@ endif
|
|||||||
" it doesn't undo changes and break undo history. If you are here reading
|
" it doesn't undo changes and break undo history. If you are here reading
|
||||||
" this and have VimL experience, please look at the function for
|
" this and have VimL experience, please look at the function for
|
||||||
" improvements, patches are welcome :)
|
" improvements, patches are welcome :)
|
||||||
function! go#fmt#Format(withGoimport)
|
function! go#fmt#Format(withGoimport) abort
|
||||||
if g:go_fmt_experimental == 1
|
if g:go_fmt_experimental == 1
|
||||||
" Using winsaveview to save/restore cursor state has the problem of
|
" Using winsaveview to save/restore cursor state has the problem of
|
||||||
" closing folds on save:
|
" closing folds on save:
|
||||||
@ -65,135 +43,51 @@ function! go#fmt#Format(withGoimport)
|
|||||||
try
|
try
|
||||||
mkview!
|
mkview!
|
||||||
catch
|
catch
|
||||||
let l:curw=winsaveview()
|
let l:curw = winsaveview()
|
||||||
endtry
|
endtry
|
||||||
else
|
|
||||||
" Save cursor position and many other things.
|
|
||||||
let l:curw=winsaveview()
|
|
||||||
endif
|
|
||||||
|
|
||||||
" Write current unsaved buffer to a temp file
|
|
||||||
let l:tmpname = tempname()
|
|
||||||
call writefile(getline(1, '$'), l:tmpname)
|
|
||||||
|
|
||||||
if g:go_fmt_experimental == 1
|
|
||||||
" save our undo file to be restored after we are done. This is needed to
|
" save our undo file to be restored after we are done. This is needed to
|
||||||
" prevent an additional undo jump due to BufWritePre auto command and also
|
" prevent an additional undo jump due to BufWritePre auto command and also
|
||||||
" restore 'redo' history because it's getting being destroyed every
|
" restore 'redo' history because it's getting being destroyed every
|
||||||
" BufWritePre
|
" BufWritePre
|
||||||
let tmpundofile=tempname()
|
let tmpundofile = tempname()
|
||||||
exe 'wundo! ' . tmpundofile
|
exe 'wundo! ' . tmpundofile
|
||||||
endif
|
|
||||||
|
|
||||||
" get the command first so we can test it
|
|
||||||
let fmt_command = g:go_fmt_command
|
|
||||||
if a:withGoimport == 1
|
|
||||||
let fmt_command = g:go_goimports_bin
|
|
||||||
endif
|
|
||||||
|
|
||||||
" check if the user has installed command binary.
|
|
||||||
" For example if it's goimports, let us check if it's installed,
|
|
||||||
" if not the user get's a warning via go#path#CheckBinPath()
|
|
||||||
let bin_path = go#path#CheckBinPath(fmt_command)
|
|
||||||
if empty(bin_path)
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
|
|
||||||
if fmt_command != "gofmt"
|
|
||||||
" change GOPATH too, so goimports can pick up the correct library
|
|
||||||
let old_gopath = $GOPATH
|
|
||||||
let $GOPATH = go#path#Detect()
|
|
||||||
|
|
||||||
let fmt_command = bin_path
|
|
||||||
endif
|
|
||||||
|
|
||||||
" populate the final command with user based fmt options
|
|
||||||
let command = fmt_command . ' -w '
|
|
||||||
if a:withGoimport != 1
|
|
||||||
let command = command . g:go_fmt_options
|
|
||||||
endif
|
|
||||||
|
|
||||||
if fmt_command == "goimports"
|
|
||||||
if !exists('b:goimports_vendor_compatible')
|
|
||||||
let out = system("goimports --help")
|
|
||||||
if out !~ "-srcdir"
|
|
||||||
echohl WarningMsg
|
|
||||||
echomsg "vim-go: goimports does not support srcdir."
|
|
||||||
echomsg " update with: :GoUpdateBinaries"
|
|
||||||
echohl None
|
|
||||||
else
|
else
|
||||||
let b:goimports_vendor_compatible = 1
|
" Save cursor position and many other things.
|
||||||
endif
|
let l:curw = winsaveview()
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if exists('b:goimports_vendor_compatible') && b:goimports_vendor_compatible
|
" Write current unsaved buffer to a temp file
|
||||||
let command = command . '-srcdir ' . fnameescape(expand("%:p:h"))
|
let l:tmpname = tempname() . '.go'
|
||||||
endif
|
call writefile(go#util#GetLines(), l:tmpname)
|
||||||
|
if go#util#IsWin()
|
||||||
|
let l:tmpname = tr(l:tmpname, '\', '/')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" execute our command...
|
let bin_name = g:go_fmt_command
|
||||||
let out = system(command . " " . l:tmpname)
|
if a:withGoimport == 1
|
||||||
|
let bin_name = "goimports"
|
||||||
if fmt_command != "gofmt"
|
|
||||||
let $GOPATH = old_gopath
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let l:listtype = "locationlist"
|
let current_col = col('.')
|
||||||
"if there is no error on the temp file replace the output with the current
|
let out = go#fmt#run(bin_name, l:tmpname, expand('%'))
|
||||||
"file (if this fails, we can always check the outputs first line with:
|
let diff_offset = len(readfile(l:tmpname)) - line('$')
|
||||||
"splitted =~ 'package \w\+')
|
|
||||||
if v:shell_error == 0
|
|
||||||
" remove undo point caused via BufWritePre
|
|
||||||
try | silent undojoin | catch | endtry
|
|
||||||
|
|
||||||
" Replace current file with temp file, then reload buffer
|
if go#util#ShellError() == 0
|
||||||
let old_fileformat = &fileformat
|
call go#fmt#update_file(l:tmpname, expand('%'))
|
||||||
call rename(l:tmpname, expand('%'))
|
|
||||||
silent edit!
|
|
||||||
let &fileformat = old_fileformat
|
|
||||||
let &syntax = &syntax
|
|
||||||
|
|
||||||
" clean up previous location list, but only if it's due to fmt
|
|
||||||
if exists('b:got_fmt_error') && b:got_fmt_error
|
|
||||||
let b:got_fmt_error = 0
|
|
||||||
call go#list#Clean(l:listtype)
|
|
||||||
call go#list#Window(l:listtype)
|
|
||||||
endif
|
|
||||||
elseif g:go_fmt_fail_silently == 0
|
elseif g:go_fmt_fail_silently == 0
|
||||||
let splitted = split(out, '\n')
|
let errors = s:parse_errors(expand('%'), out)
|
||||||
"otherwise get the errors and put them to location list
|
call s:show_errors(errors)
|
||||||
let errors = []
|
|
||||||
for line in splitted
|
|
||||||
let tokens = matchlist(line, '^\(.\{-}\):\(\d\+\):\(\d\+\)\s*\(.*\)')
|
|
||||||
if !empty(tokens)
|
|
||||||
call add(errors, {"filename": @%,
|
|
||||||
\"lnum": tokens[2],
|
|
||||||
\"col": tokens[3],
|
|
||||||
\"text": tokens[4]})
|
|
||||||
endif
|
endif
|
||||||
endfor
|
|
||||||
if empty(errors)
|
|
||||||
% | " Couldn't detect gofmt error format, output errors
|
|
||||||
endif
|
|
||||||
if !empty(errors)
|
|
||||||
call go#list#Populate(l:listtype, errors)
|
|
||||||
echohl Error | echomsg "Gofmt returned error" | echohl None
|
|
||||||
endif
|
|
||||||
|
|
||||||
let b:got_fmt_error = 1
|
|
||||||
call go#list#Window(l:listtype, len(errors))
|
|
||||||
|
|
||||||
" We didn't use the temp file, so clean up
|
" We didn't use the temp file, so clean up
|
||||||
call delete(l:tmpname)
|
call delete(l:tmpname)
|
||||||
endif
|
|
||||||
|
|
||||||
if g:go_fmt_experimental == 1
|
if g:go_fmt_experimental == 1
|
||||||
" restore our undo history
|
" restore our undo history
|
||||||
silent! exe 'rundo ' . tmpundofile
|
silent! exe 'rundo ' . tmpundofile
|
||||||
call delete(tmpundofile)
|
call delete(tmpundofile)
|
||||||
endif
|
|
||||||
|
|
||||||
if g:go_fmt_experimental == 1
|
|
||||||
" Restore our cursor/windows positions, folds, etc.
|
" Restore our cursor/windows positions, folds, etc.
|
||||||
if empty(l:curw)
|
if empty(l:curw)
|
||||||
silent! loadview
|
silent! loadview
|
||||||
@ -204,7 +98,171 @@ function! go#fmt#Format(withGoimport)
|
|||||||
" Restore our cursor/windows positions.
|
" Restore our cursor/windows positions.
|
||||||
call winrestview(l:curw)
|
call winrestview(l:curw)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
" be smart and jump to the line the new statement was added/removed
|
||||||
|
call cursor(line('.') + diff_offset, current_col)
|
||||||
|
|
||||||
|
" Syntax highlighting breaks less often.
|
||||||
|
syntax sync fromstart
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
" update_file updates the target file with the given formatted source
|
||||||
|
function! go#fmt#update_file(source, target)
|
||||||
|
" remove undo point caused via BufWritePre
|
||||||
|
try | silent undojoin | catch | endtry
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
let old_fileformat = &fileformat
|
||||||
|
if exists("*getfperm")
|
||||||
|
" save file permissions
|
||||||
|
let original_fperm = getfperm(a:target)
|
||||||
|
endif
|
||||||
|
|
||||||
|
call rename(a:source, a:target)
|
||||||
|
|
||||||
|
" restore file permissions
|
||||||
|
if exists("*setfperm") && original_fperm != ''
|
||||||
|
call setfperm(a:target , original_fperm)
|
||||||
|
endif
|
||||||
|
|
||||||
|
" reload buffer to reflect latest changes
|
||||||
|
silent edit!
|
||||||
|
|
||||||
|
let &fileformat = old_fileformat
|
||||||
|
let &syntax = &syntax
|
||||||
|
|
||||||
|
let l:listtype = go#list#Type("GoFmt")
|
||||||
|
|
||||||
|
" the title information was introduced with 7.4-2200
|
||||||
|
" https://github.com/vim/vim/commit/d823fa910cca43fec3c31c030ee908a14c272640
|
||||||
|
if has('patch-7.4.2200')
|
||||||
|
" clean up previous list
|
||||||
|
if l:listtype == "quickfix"
|
||||||
|
let l:list_title = getqflist({'title': 1})
|
||||||
|
else
|
||||||
|
let l:list_title = getloclist(0, {'title': 1})
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
" can't check the title, so assume that the list was for go fmt.
|
||||||
|
let l:list_title = {'title': 'Format'}
|
||||||
|
endif
|
||||||
|
|
||||||
|
if has_key(l:list_title, "title") && l:list_title['title'] == "Format"
|
||||||
|
call go#list#Clean(l:listtype)
|
||||||
|
call go#list#Window(l:listtype)
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" run runs the gofmt/goimport command for the given source file and returns
|
||||||
|
" the output of the executed command. Target is the real file to be formatted.
|
||||||
|
function! go#fmt#run(bin_name, source, target)
|
||||||
|
let cmd = s:fmt_cmd(a:bin_name, a:source, a:target)
|
||||||
|
if empty(cmd)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let command = join(cmd, " ")
|
||||||
|
|
||||||
|
" execute our command...
|
||||||
|
let out = go#util#System(command)
|
||||||
|
|
||||||
|
return out
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" fmt_cmd returns a dict that contains the command to execute gofmt (or
|
||||||
|
" goimports). args is dict with
|
||||||
|
function! s:fmt_cmd(bin_name, source, target)
|
||||||
|
" check if the user has installed command binary.
|
||||||
|
" For example if it's goimports, let us check if it's installed,
|
||||||
|
" if not the user get's a warning via go#path#CheckBinPath()
|
||||||
|
let bin_path = go#path#CheckBinPath(a:bin_name)
|
||||||
|
if empty(bin_path)
|
||||||
|
return []
|
||||||
|
endif
|
||||||
|
|
||||||
|
" start constructing the command
|
||||||
|
let bin_path = go#util#Shellescape(bin_path)
|
||||||
|
let cmd = [bin_path]
|
||||||
|
call add(cmd, "-w")
|
||||||
|
|
||||||
|
" add the options for binary (if any). go_fmt_options was by default of type
|
||||||
|
" string, however to allow customization it's now a dictionary of binary
|
||||||
|
" name mapping to options.
|
||||||
|
let opts = g:go_fmt_options
|
||||||
|
if type(g:go_fmt_options) == type({})
|
||||||
|
let opts = has_key(g:go_fmt_options, a:bin_name) ? g:go_fmt_options[a:bin_name] : ""
|
||||||
|
endif
|
||||||
|
call extend(cmd, split(opts, " "))
|
||||||
|
|
||||||
|
if a:bin_name == "goimports"
|
||||||
|
" lazy check if goimports support `-srcdir`. We should eventually remove
|
||||||
|
" this in the future
|
||||||
|
if !exists('b:goimports_vendor_compatible')
|
||||||
|
let out = go#util#System(bin_path . " --help")
|
||||||
|
if out !~ "-srcdir"
|
||||||
|
call go#util#EchoWarning(printf("vim-go: goimports (%s) does not support srcdir. Update with: :GoUpdateBinaries", bin_path))
|
||||||
|
else
|
||||||
|
let b:goimports_vendor_compatible = 1
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
if exists('b:goimports_vendor_compatible') && b:goimports_vendor_compatible
|
||||||
|
let ssl_save = &shellslash
|
||||||
|
set noshellslash
|
||||||
|
" use the filename without the fully qualified name if the tree is
|
||||||
|
" symlinked into the GOPATH, goimports won't work properly.
|
||||||
|
call extend(cmd, ["-srcdir", shellescape(a:target)])
|
||||||
|
let &shellslash = ssl_save
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
call add(cmd, a:source)
|
||||||
|
return cmd
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" parse_errors parses the given errors and returns a list of parsed errors
|
||||||
|
function! s:parse_errors(filename, content) abort
|
||||||
|
let splitted = split(a:content, '\n')
|
||||||
|
|
||||||
|
" list of errors to be put into location list
|
||||||
|
let errors = []
|
||||||
|
for line in splitted
|
||||||
|
let tokens = matchlist(line, '^\(.\{-}\):\(\d\+\):\(\d\+\)\s*\(.*\)')
|
||||||
|
if !empty(tokens)
|
||||||
|
call add(errors,{
|
||||||
|
\"filename": a:filename,
|
||||||
|
\"lnum": tokens[2],
|
||||||
|
\"col": tokens[3],
|
||||||
|
\"text": tokens[4],
|
||||||
|
\ })
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
|
||||||
|
return errors
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" show_errors opens a location list and shows the given errors. If the given
|
||||||
|
" errors is empty, it closes the the location list
|
||||||
|
function! s:show_errors(errors) abort
|
||||||
|
let l:listtype = go#list#Type("GoFmt")
|
||||||
|
if !empty(a:errors)
|
||||||
|
call go#list#Populate(l:listtype, a:errors, 'Format')
|
||||||
|
echohl Error | echomsg "Gofmt returned error" | echohl None
|
||||||
|
endif
|
||||||
|
|
||||||
|
" this closes the window if there are no errors or it opens
|
||||||
|
" it if there is any
|
||||||
|
call go#list#Window(l:listtype, len(a:errors))
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! go#fmt#ToggleFmtAutoSave() abort
|
||||||
|
if get(g:, "go_fmt_autosave", 1)
|
||||||
|
let g:go_fmt_autosave = 0
|
||||||
|
call go#util#EchoProgress("auto fmt disabled")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
let g:go_fmt_autosave = 1
|
||||||
|
call go#util#EchoProgress("auto fmt enabled")
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
49
autoload/go/fmt_test.vim
Normal file
49
autoload/go/fmt_test.vim
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
func! Test_run_fmt() abort
|
||||||
|
let actual_file = tempname()
|
||||||
|
call writefile(readfile("test-fixtures/fmt/hello.go"), actual_file)
|
||||||
|
|
||||||
|
let expected = join(readfile("test-fixtures/fmt/hello_golden.go"), "\n")
|
||||||
|
|
||||||
|
" run our code
|
||||||
|
call go#fmt#run("gofmt", actual_file, "test-fixtures/fmt/hello.go")
|
||||||
|
|
||||||
|
" this should now contain the formatted code
|
||||||
|
let actual = join(readfile(actual_file), "\n")
|
||||||
|
|
||||||
|
call assert_equal(expected, actual)
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func! Test_update_file() abort
|
||||||
|
let expected = join(readfile("test-fixtures/fmt/hello_golden.go"), "\n")
|
||||||
|
let source_file = tempname()
|
||||||
|
call writefile(readfile("test-fixtures/fmt/hello_golden.go"), source_file)
|
||||||
|
|
||||||
|
let target_file = tempname()
|
||||||
|
call writefile([""], target_file)
|
||||||
|
|
||||||
|
" update_file now
|
||||||
|
call go#fmt#update_file(source_file, target_file)
|
||||||
|
|
||||||
|
" this should now contain the formatted code
|
||||||
|
let actual = join(readfile(target_file), "\n")
|
||||||
|
|
||||||
|
call assert_equal(expected, actual)
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func! Test_goimports() abort
|
||||||
|
let $GOPATH = 'test-fixtures/fmt/'
|
||||||
|
let actual_file = tempname()
|
||||||
|
call writefile(readfile("test-fixtures/fmt/src/imports/goimports.go"), actual_file)
|
||||||
|
|
||||||
|
let expected = join(readfile("test-fixtures/fmt/src/imports/goimports_golden.go"), "\n")
|
||||||
|
|
||||||
|
" run our code
|
||||||
|
call go#fmt#run("goimports", actual_file, "test-fixtures/fmt/src/imports/goimports.go")
|
||||||
|
|
||||||
|
" this should now contain the formatted code
|
||||||
|
let actual = join(readfile(actual_file), "\n")
|
||||||
|
|
||||||
|
call assert_equal(expected, actual)
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
628
autoload/go/guru.vim
Normal file
628
autoload/go/guru.vim
Normal file
@ -0,0 +1,628 @@
|
|||||||
|
" guru.vim -- Vim integration for the Go guru.
|
||||||
|
|
||||||
|
" guru_cmd returns a dict that contains the command to execute guru. args
|
||||||
|
" is dict with following options:
|
||||||
|
" mode : guru mode, such as 'implements'
|
||||||
|
" format : output format, either 'plain' or 'json'
|
||||||
|
" needs_scope : if 1, adds the current package to the scope
|
||||||
|
" selected : if 1, means it's a range of selection, otherwise it picks up the
|
||||||
|
" offset under the cursor
|
||||||
|
" example output:
|
||||||
|
" {'cmd' : ['guru', '-json', 'implements', 'demo/demo.go:#66']}
|
||||||
|
function! s:guru_cmd(args) range abort
|
||||||
|
let mode = a:args.mode
|
||||||
|
let format = a:args.format
|
||||||
|
let needs_scope = a:args.needs_scope
|
||||||
|
let selected = a:args.selected
|
||||||
|
|
||||||
|
let result = {}
|
||||||
|
let pkg = go#package#ImportPath()
|
||||||
|
|
||||||
|
" this is important, check it!
|
||||||
|
if pkg == -1 && needs_scope
|
||||||
|
return {'err': "current directory is not inside of a valid GOPATH"}
|
||||||
|
endif
|
||||||
|
|
||||||
|
"return with a warning if the binary doesn't exist
|
||||||
|
let bin_path = go#path#CheckBinPath("guru")
|
||||||
|
if empty(bin_path)
|
||||||
|
return {'err': "bin path not found"}
|
||||||
|
endif
|
||||||
|
|
||||||
|
" start constructing the command
|
||||||
|
let cmd = [bin_path]
|
||||||
|
|
||||||
|
let filename = fnamemodify(expand("%"), ':p:gs?\\?/?')
|
||||||
|
if &modified
|
||||||
|
let result.stdin_content = go#util#archive()
|
||||||
|
call add(cmd, "-modified")
|
||||||
|
endif
|
||||||
|
|
||||||
|
" enable outputting in json format
|
||||||
|
if format == "json"
|
||||||
|
call add(cmd, "-json")
|
||||||
|
endif
|
||||||
|
|
||||||
|
" check for any tags
|
||||||
|
if exists('g:go_build_tags')
|
||||||
|
let tags = get(g:, 'go_build_tags')
|
||||||
|
call extend(cmd, ["-tags", tags])
|
||||||
|
let result.tags = tags
|
||||||
|
endif
|
||||||
|
|
||||||
|
" some modes require scope to be defined (such as callers). For these we
|
||||||
|
" choose a sensible setting, which is using the current file's package
|
||||||
|
let scopes = []
|
||||||
|
if needs_scope
|
||||||
|
let scopes = [pkg]
|
||||||
|
endif
|
||||||
|
|
||||||
|
" check for any user defined scope setting. users can define the scope,
|
||||||
|
" in package pattern form. examples:
|
||||||
|
" golang.org/x/tools/cmd/guru # a single package
|
||||||
|
" golang.org/x/tools/... # all packages beneath dir
|
||||||
|
" ... # the entire workspace.
|
||||||
|
if exists('g:go_guru_scope')
|
||||||
|
" check that the setting is of type list
|
||||||
|
if type(get(g:, 'go_guru_scope')) != type([])
|
||||||
|
return {'err' : "go_guru_scope should of type list"}
|
||||||
|
endif
|
||||||
|
|
||||||
|
let scopes = get(g:, 'go_guru_scope')
|
||||||
|
endif
|
||||||
|
|
||||||
|
" now add the scope to our command if there is any
|
||||||
|
if !empty(scopes)
|
||||||
|
" strip trailing slashes for each path in scoped. bug:
|
||||||
|
" https://github.com/golang/go/issues/14584
|
||||||
|
let scopes = go#util#StripTrailingSlash(scopes)
|
||||||
|
|
||||||
|
" create shell-safe entries of the list
|
||||||
|
if !go#util#has_job() | let scopes = go#util#Shelllist(scopes) | endif
|
||||||
|
|
||||||
|
" guru expect a comma-separated list of patterns, construct it
|
||||||
|
let l:scope = join(scopes, ",")
|
||||||
|
let result.scope = l:scope
|
||||||
|
call extend(cmd, ["-scope", l:scope])
|
||||||
|
endif
|
||||||
|
|
||||||
|
let pos = printf("#%s", go#util#OffsetCursor())
|
||||||
|
if selected != -1
|
||||||
|
" means we have a range, get it
|
||||||
|
let pos1 = go#util#Offset(line("'<"), col("'<"))
|
||||||
|
let pos2 = go#util#Offset(line("'>"), col("'>"))
|
||||||
|
let pos = printf("#%s,#%s", pos1, pos2)
|
||||||
|
endif
|
||||||
|
|
||||||
|
let filename .= ':'.pos
|
||||||
|
call extend(cmd, [mode, filename])
|
||||||
|
|
||||||
|
let result.cmd = cmd
|
||||||
|
return result
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" sync_guru runs guru in sync mode with the given arguments
|
||||||
|
function! s:sync_guru(args) abort
|
||||||
|
let result = s:guru_cmd(a:args)
|
||||||
|
if has_key(result, 'err')
|
||||||
|
call go#util#EchoError(result.err)
|
||||||
|
return -1
|
||||||
|
endif
|
||||||
|
|
||||||
|
if !has_key(a:args, 'disable_progress')
|
||||||
|
if a:args.needs_scope
|
||||||
|
call go#util#EchoProgress("analysing with scope ". result.scope .
|
||||||
|
\ " (see ':help go-guru-scope' if this doesn't work)...")
|
||||||
|
elseif a:args.mode !=# 'what'
|
||||||
|
" the query might take time, let us give some feedback
|
||||||
|
call go#util#EchoProgress("analysing ...")
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
" run, forrest run!!!
|
||||||
|
let command = join(result.cmd, " ")
|
||||||
|
if has_key(result, 'stdin_content')
|
||||||
|
let out = go#util#System(command, result.stdin_content)
|
||||||
|
else
|
||||||
|
let out = go#util#System(command)
|
||||||
|
endif
|
||||||
|
|
||||||
|
if has_key(a:args, 'custom_parse')
|
||||||
|
call a:args.custom_parse(go#util#ShellError(), out)
|
||||||
|
else
|
||||||
|
call s:parse_guru_output(go#util#ShellError(), out, a:args.mode)
|
||||||
|
endif
|
||||||
|
|
||||||
|
return out
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" async_guru runs guru in async mode with the given arguments
|
||||||
|
function! s:async_guru(args) abort
|
||||||
|
let result = s:guru_cmd(a:args)
|
||||||
|
if has_key(result, 'err')
|
||||||
|
call go#util#EchoError(result.err)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let status_dir = expand('%:p:h')
|
||||||
|
let statusline_type = printf("%s", a:args.mode)
|
||||||
|
|
||||||
|
if !has_key(a:args, 'disable_progress')
|
||||||
|
if a:args.needs_scope
|
||||||
|
call go#util#EchoProgress("analysing with scope " . result.scope .
|
||||||
|
\ " (see ':help go-guru-scope' if this doesn't work)...")
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
let messages = []
|
||||||
|
function! s:callback(chan, msg) closure
|
||||||
|
call add(messages, a:msg)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
let status = {}
|
||||||
|
let exitval = 0
|
||||||
|
|
||||||
|
function! s:exit_cb(job, exitval) closure
|
||||||
|
let status = {
|
||||||
|
\ 'desc': 'last status',
|
||||||
|
\ 'type': statusline_type,
|
||||||
|
\ 'state': "finished",
|
||||||
|
\ }
|
||||||
|
|
||||||
|
if a:exitval
|
||||||
|
let exitval = a:exitval
|
||||||
|
let status.state = "failed"
|
||||||
|
endif
|
||||||
|
|
||||||
|
call go#statusline#Update(status_dir, status)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:close_cb(ch) closure
|
||||||
|
let out = join(messages, "\n")
|
||||||
|
|
||||||
|
if has_key(a:args, 'custom_parse')
|
||||||
|
call a:args.custom_parse(exitval, out)
|
||||||
|
else
|
||||||
|
call s:parse_guru_output(exitval, out, a:args.mode)
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
let start_options = {
|
||||||
|
\ 'callback': funcref("s:callback"),
|
||||||
|
\ 'exit_cb': funcref("s:exit_cb"),
|
||||||
|
\ 'close_cb': funcref("s:close_cb"),
|
||||||
|
\ }
|
||||||
|
|
||||||
|
if has_key(result, 'stdin_content')
|
||||||
|
let l:tmpname = tempname()
|
||||||
|
call writefile(split(result.stdin_content, "\n"), l:tmpname, "b")
|
||||||
|
let l:start_options.in_io = "file"
|
||||||
|
let l:start_options.in_name = l:tmpname
|
||||||
|
endif
|
||||||
|
|
||||||
|
call go#statusline#Update(status_dir, {
|
||||||
|
\ 'desc': "current status",
|
||||||
|
\ 'type': statusline_type,
|
||||||
|
\ 'state': "analysing",
|
||||||
|
\})
|
||||||
|
|
||||||
|
return job_start(result.cmd, start_options)
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" run_guru runs the given guru argument
|
||||||
|
function! s:run_guru(args) abort
|
||||||
|
if go#util#has_job()
|
||||||
|
let res = s:async_guru(a:args)
|
||||||
|
else
|
||||||
|
let res = s:sync_guru(a:args)
|
||||||
|
endif
|
||||||
|
|
||||||
|
return res
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Show 'implements' relation for selected package
|
||||||
|
function! go#guru#Implements(selected) abort
|
||||||
|
let args = {
|
||||||
|
\ 'mode': 'implements',
|
||||||
|
\ 'format': 'plain',
|
||||||
|
\ 'selected': a:selected,
|
||||||
|
\ 'needs_scope': 1,
|
||||||
|
\ }
|
||||||
|
|
||||||
|
call s:run_guru(args)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Report the possible constants, global variables, and concrete types that may
|
||||||
|
" appear in a value of type error
|
||||||
|
function! go#guru#Whicherrs(selected) abort
|
||||||
|
let args = {
|
||||||
|
\ 'mode': 'whicherrs',
|
||||||
|
\ 'format': 'plain',
|
||||||
|
\ 'selected': a:selected,
|
||||||
|
\ 'needs_scope': 1,
|
||||||
|
\ }
|
||||||
|
|
||||||
|
|
||||||
|
" TODO(arslan): handle empty case for both sync/async
|
||||||
|
" if empty(out.out)
|
||||||
|
" call go#util#EchoSuccess("no error variables found. Try to change the scope with :GoGuruScope")
|
||||||
|
" return
|
||||||
|
" endif
|
||||||
|
call s:run_guru(args)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Describe selected syntax: definition, methods, etc
|
||||||
|
function! go#guru#Describe(selected) abort
|
||||||
|
let args = {
|
||||||
|
\ 'mode': 'describe',
|
||||||
|
\ 'format': 'plain',
|
||||||
|
\ 'selected': a:selected,
|
||||||
|
\ 'needs_scope': 1,
|
||||||
|
\ }
|
||||||
|
|
||||||
|
call s:run_guru(args)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! go#guru#DescribeInfo() abort
|
||||||
|
" json_encode() and friends are introduced with this patch (7.4.1304)
|
||||||
|
" vim: https://groups.google.com/d/msg/vim_dev/vLupTNhQhZ8/cDGIk0JEDgAJ
|
||||||
|
" nvim: https://github.com/neovim/neovim/pull/4131
|
||||||
|
if !exists("*json_decode")
|
||||||
|
call go#util#EchoError("requires 'json_decode'. Update your Vim/Neovim version.")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
function! s:info(exit_val, output)
|
||||||
|
if a:exit_val != 0
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
if a:output[0] !=# '{'
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
if empty(a:output) || type(a:output) != type("")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let result = json_decode(a:output)
|
||||||
|
if type(result) != type({})
|
||||||
|
call go#util#EchoError(printf("malformed output from guru: %s", a:output))
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
if !has_key(result, 'detail')
|
||||||
|
" if there is no detail check if there is a description and print it
|
||||||
|
if has_key(result, "desc")
|
||||||
|
call go#util#EchoInfo(result["desc"])
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
call go#util#EchoError("detail key is missing. Please open a bug report on vim-go repo.")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let detail = result['detail']
|
||||||
|
let info = ""
|
||||||
|
|
||||||
|
" guru gives different information based on the detail mode. Let try to
|
||||||
|
" extract the most useful information
|
||||||
|
|
||||||
|
if detail == "value"
|
||||||
|
if !has_key(result, 'value')
|
||||||
|
call go#util#EchoError("value key is missing. Please open a bug report on vim-go repo.")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let val = result["value"]
|
||||||
|
if !has_key(val, 'type')
|
||||||
|
call go#util#EchoError("type key is missing (value.type). Please open a bug report on vim-go repo.")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let info = val["type"]
|
||||||
|
elseif detail == "type"
|
||||||
|
if !has_key(result, 'type')
|
||||||
|
call go#util#EchoError("type key is missing. Please open a bug report on vim-go repo.")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let type = result["type"]
|
||||||
|
if !has_key(type, 'type')
|
||||||
|
call go#util#EchoError("type key is missing (type.type). Please open a bug report on vim-go repo.")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let info = type["type"]
|
||||||
|
elseif detail == "package"
|
||||||
|
if !has_key(result, 'package')
|
||||||
|
call go#util#EchoError("package key is missing. Please open a bug report on vim-go repo.")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let package = result["package"]
|
||||||
|
if !has_key(package, 'path')
|
||||||
|
call go#util#EchoError("path key is missing (package.path). Please open a bug report on vim-go repo.")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let info = printf("package %s", package["path"])
|
||||||
|
elseif detail == "unknown"
|
||||||
|
let info = result["desc"]
|
||||||
|
else
|
||||||
|
call go#util#EchoError(printf("unknown detail mode found '%s'. Please open a bug report on vim-go repo", detail))
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
call go#util#EchoInfo(info)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
let args = {
|
||||||
|
\ 'mode': 'describe',
|
||||||
|
\ 'format': 'json',
|
||||||
|
\ 'selected': -1,
|
||||||
|
\ 'needs_scope': 0,
|
||||||
|
\ 'custom_parse': function('s:info'),
|
||||||
|
\ 'disable_progress': 1,
|
||||||
|
\ }
|
||||||
|
|
||||||
|
call s:run_guru(args)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Show possible targets of selected function call
|
||||||
|
function! go#guru#Callees(selected) abort
|
||||||
|
let args = {
|
||||||
|
\ 'mode': 'callees',
|
||||||
|
\ 'format': 'plain',
|
||||||
|
\ 'selected': a:selected,
|
||||||
|
\ 'needs_scope': 1,
|
||||||
|
\ }
|
||||||
|
|
||||||
|
call s:run_guru(args)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Show possible callers of selected function
|
||||||
|
function! go#guru#Callers(selected) abort
|
||||||
|
let args = {
|
||||||
|
\ 'mode': 'callers',
|
||||||
|
\ 'format': 'plain',
|
||||||
|
\ 'selected': a:selected,
|
||||||
|
\ 'needs_scope': 1,
|
||||||
|
\ }
|
||||||
|
|
||||||
|
call s:run_guru(args)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Show path from callgraph root to selected function
|
||||||
|
function! go#guru#Callstack(selected) abort
|
||||||
|
let args = {
|
||||||
|
\ 'mode': 'callstack',
|
||||||
|
\ 'format': 'plain',
|
||||||
|
\ 'selected': a:selected,
|
||||||
|
\ 'needs_scope': 1,
|
||||||
|
\ }
|
||||||
|
|
||||||
|
call s:run_guru(args)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Show free variables of selection
|
||||||
|
function! go#guru#Freevars(selected) abort
|
||||||
|
" Freevars requires a selection
|
||||||
|
if a:selected == -1
|
||||||
|
call go#util#EchoError("GoFreevars requires a selection (range) of code")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let args = {
|
||||||
|
\ 'mode': 'freevars',
|
||||||
|
\ 'format': 'plain',
|
||||||
|
\ 'selected': 1,
|
||||||
|
\ 'needs_scope': 0,
|
||||||
|
\ }
|
||||||
|
|
||||||
|
call s:run_guru(args)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Show send/receive corresponding to selected channel op
|
||||||
|
function! go#guru#ChannelPeers(selected) abort
|
||||||
|
let args = {
|
||||||
|
\ 'mode': 'peers',
|
||||||
|
\ 'format': 'plain',
|
||||||
|
\ 'selected': a:selected,
|
||||||
|
\ 'needs_scope': 1,
|
||||||
|
\ }
|
||||||
|
|
||||||
|
call s:run_guru(args)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Show all refs to entity denoted by selected identifier
|
||||||
|
function! go#guru#Referrers(selected) abort
|
||||||
|
let args = {
|
||||||
|
\ 'mode': 'referrers',
|
||||||
|
\ 'format': 'plain',
|
||||||
|
\ 'selected': a:selected,
|
||||||
|
\ 'needs_scope': 0,
|
||||||
|
\ }
|
||||||
|
|
||||||
|
call s:run_guru(args)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! go#guru#SameIdsTimer() abort
|
||||||
|
call timer_start(200, function('go#guru#SameIds'), {'repeat': -1})
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! go#guru#SameIds() abort
|
||||||
|
" we use matchaddpos() which was introduce with 7.4.330, be sure we have
|
||||||
|
" it: http://ftp.vim.org/vim/patches/7.4/7.4.330
|
||||||
|
if !exists("*matchaddpos")
|
||||||
|
call go#util#EchoError("GoSameIds requires 'matchaddpos'. Update your Vim/Neovim version.")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
" json_encode() and friends are introduced with this patch (7.4.1304)
|
||||||
|
" vim: https://groups.google.com/d/msg/vim_dev/vLupTNhQhZ8/cDGIk0JEDgAJ
|
||||||
|
" nvim: https://github.com/neovim/neovim/pull/4131
|
||||||
|
if !exists("*json_decode")
|
||||||
|
call go#util#EchoError("GoSameIds requires 'json_decode'. Update your Vim/Neovim version.")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let args = {
|
||||||
|
\ 'mode': 'what',
|
||||||
|
\ 'format': 'json',
|
||||||
|
\ 'selected': -1,
|
||||||
|
\ 'needs_scope': 0,
|
||||||
|
\ 'custom_parse': function('s:same_ids_highlight'),
|
||||||
|
\ }
|
||||||
|
|
||||||
|
call s:run_guru(args)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:same_ids_highlight(exit_val, output) abort
|
||||||
|
call go#guru#ClearSameIds() " run after calling guru to reduce flicker.
|
||||||
|
|
||||||
|
if a:output[0] !=# '{'
|
||||||
|
if !get(g:, 'go_auto_sameids', 0)
|
||||||
|
call go#util#EchoError(a:output)
|
||||||
|
endif
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let result = json_decode(a:output)
|
||||||
|
if type(result) != type({}) && !get(g:, 'go_auto_sameids', 0)
|
||||||
|
call go#util#EchoError("malformed output from guru")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
if !has_key(result, 'sameids')
|
||||||
|
if !get(g:, 'go_auto_sameids', 0)
|
||||||
|
call go#util#EchoError("no same_ids founds for the given identifier")
|
||||||
|
endif
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let poslen = 0
|
||||||
|
for enclosing in result['enclosing']
|
||||||
|
if enclosing['desc'] == 'identifier'
|
||||||
|
let poslen = enclosing['end'] - enclosing['start']
|
||||||
|
break
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
|
||||||
|
" return when there's no identifier to highlight.
|
||||||
|
if poslen == 0
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let same_ids = result['sameids']
|
||||||
|
" highlight the lines
|
||||||
|
for item in same_ids
|
||||||
|
let pos = split(item, ':')
|
||||||
|
call matchaddpos('goSameId', [[str2nr(pos[-2]), str2nr(pos[-1]), str2nr(poslen)]])
|
||||||
|
endfor
|
||||||
|
|
||||||
|
if get(g:, "go_auto_sameids", 0)
|
||||||
|
" re-apply SameIds at the current cursor position at the time the buffer
|
||||||
|
" is redisplayed: e.g. :edit, :GoRename, etc.
|
||||||
|
augroup vim-go-sameids
|
||||||
|
autocmd!
|
||||||
|
autocmd BufWinEnter <buffer> nested call go#guru#SameIds()
|
||||||
|
augroup end
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" ClearSameIds returns 0 when it removes goSameId groups and non-zero if no
|
||||||
|
" goSameId groups are found.
|
||||||
|
function! go#guru#ClearSameIds() abort
|
||||||
|
let l:cleared = 0
|
||||||
|
|
||||||
|
let m = getmatches()
|
||||||
|
for item in m
|
||||||
|
if item['group'] == 'goSameId'
|
||||||
|
call matchdelete(item['id'])
|
||||||
|
let l:cleared = 1
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
|
||||||
|
if !l:cleared
|
||||||
|
return 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
" remove the autocmds we defined
|
||||||
|
augroup vim-go-sameids
|
||||||
|
autocmd!
|
||||||
|
augroup end
|
||||||
|
|
||||||
|
return 0
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! go#guru#ToggleSameIds() abort
|
||||||
|
if go#guru#ClearSameIds() != 0
|
||||||
|
call go#guru#SameIds()
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! go#guru#AutoToogleSameIds() abort
|
||||||
|
if get(g:, "go_auto_sameids", 0)
|
||||||
|
call go#util#EchoProgress("sameids auto highlighting disabled")
|
||||||
|
call go#guru#ClearSameIds()
|
||||||
|
let g:go_auto_sameids = 0
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
call go#util#EchoSuccess("sameids auto highlighting enabled")
|
||||||
|
let g:go_auto_sameids = 1
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
""""""""""""""""""""""""""""""""""""""""
|
||||||
|
"" HELPER FUNCTIONS
|
||||||
|
""""""""""""""""""""""""""""""""""""""""
|
||||||
|
|
||||||
|
" This uses Vim's errorformat to parse the output from Guru's 'plain output
|
||||||
|
" and put it into location list. I believe using errorformat is much more
|
||||||
|
" easier to use. If we need more power we can always switch back to parse it
|
||||||
|
" via regex. Match two possible styles of errorformats:
|
||||||
|
"
|
||||||
|
" 'file:line.col-line2.col2: message'
|
||||||
|
" 'file:line:col: message'
|
||||||
|
"
|
||||||
|
" We discard line2 and col2 for the first errorformat, because it's not
|
||||||
|
" useful and location only has the ability to show one line and column
|
||||||
|
" number
|
||||||
|
function! s:parse_guru_output(exit_val, output, title) abort
|
||||||
|
if a:exit_val
|
||||||
|
call go#util#EchoError(a:output)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let errformat = "%f:%l.%c-%[%^:]%#:\ %m,%f:%l:%c:\ %m"
|
||||||
|
let l:listtype = go#list#Type("_guru")
|
||||||
|
call go#list#ParseFormat(l:listtype, errformat, a:output, a:title)
|
||||||
|
|
||||||
|
let errors = go#list#Get(l:listtype)
|
||||||
|
call go#list#Window(l:listtype, len(errors))
|
||||||
|
endfun
|
||||||
|
|
||||||
|
function! go#guru#Scope(...) abort
|
||||||
|
if a:0
|
||||||
|
if a:0 == 1 && a:1 == '""'
|
||||||
|
unlet g:go_guru_scope
|
||||||
|
call go#util#EchoSuccess("guru scope is cleared")
|
||||||
|
else
|
||||||
|
let g:go_guru_scope = a:000
|
||||||
|
call go#util#EchoSuccess("guru scope changed to: ". join(a:000, ","))
|
||||||
|
endif
|
||||||
|
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
if !exists('g:go_guru_scope')
|
||||||
|
call go#util#EchoError("guru scope is not set")
|
||||||
|
else
|
||||||
|
call go#util#EchoSuccess("current guru scope: ". join(g:go_guru_scope, ","))
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
140
autoload/go/impl.vim
Normal file
140
autoload/go/impl.vim
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
function! go#impl#Impl(...) abort
|
||||||
|
let recv = ""
|
||||||
|
let iface = ""
|
||||||
|
let interactive = 0
|
||||||
|
|
||||||
|
let pos = getpos('.')
|
||||||
|
|
||||||
|
if a:0 is 0
|
||||||
|
" Interactive mode if user didn't pass any arguments.
|
||||||
|
let recv = s:getReceiver()
|
||||||
|
let iface = input("vim-go: generating method stubs for interface: ")
|
||||||
|
redraw!
|
||||||
|
if empty(iface)
|
||||||
|
call go#util#EchoError('usage: interface type is not provided')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
elseif a:0 is 1
|
||||||
|
" we assume the user only passed the interface type,
|
||||||
|
" i.e: ':GoImpl io.Writer'
|
||||||
|
let recv = s:getReceiver()
|
||||||
|
let iface = a:1
|
||||||
|
elseif a:0 > 2
|
||||||
|
" user passed receiver and interface type both,
|
||||||
|
" i.e: 'GoImpl f *Foo io.Writer'
|
||||||
|
let recv = join(a:000[:-2], ' ')
|
||||||
|
let iface = a:000[-1]
|
||||||
|
else
|
||||||
|
call go#util#EchoError('usage: GoImpl {receiver} {interface}')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Make sure we put the generated code *after* the struct.
|
||||||
|
if getline(".") =~ "struct "
|
||||||
|
normal! $%
|
||||||
|
endif
|
||||||
|
|
||||||
|
try
|
||||||
|
let dirname = fnameescape(expand('%:p:h'))
|
||||||
|
let [result, err] = go#util#Exec(['impl', '-dir', dirname, recv, iface])
|
||||||
|
let result = substitute(result, "\n*$", "", "")
|
||||||
|
if err
|
||||||
|
call go#util#EchoError(result)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
if result is# ''
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
put =''
|
||||||
|
silent put =result
|
||||||
|
finally
|
||||||
|
call setpos('.', pos)
|
||||||
|
endtry
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:getReceiver()
|
||||||
|
let receiveType = expand("<cword>")
|
||||||
|
if receiveType == "type"
|
||||||
|
normal! w
|
||||||
|
let receiveType = expand("<cword>")
|
||||||
|
elseif receiveType == "struct"
|
||||||
|
normal! ge
|
||||||
|
let receiveType = expand("<cword>")
|
||||||
|
endif
|
||||||
|
return printf("%s *%s", tolower(receiveType)[0], receiveType)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
if exists('*uniq')
|
||||||
|
function! s:uniq(list)
|
||||||
|
return uniq(a:list)
|
||||||
|
endfunction
|
||||||
|
else
|
||||||
|
" Note: Believe that the list is sorted
|
||||||
|
function! s:uniq(list)
|
||||||
|
let i = len(a:list) - 1
|
||||||
|
while 0 < i
|
||||||
|
if a:list[i-1] ==# a:list[i]
|
||||||
|
call remove(a:list, i)
|
||||||
|
let i -= 2
|
||||||
|
else
|
||||||
|
let i -= 1
|
||||||
|
endif
|
||||||
|
endwhile
|
||||||
|
return a:list
|
||||||
|
endfunction
|
||||||
|
endif
|
||||||
|
|
||||||
|
function! s:root_dirs() abort
|
||||||
|
let dirs = []
|
||||||
|
let root = go#util#env("goroot")
|
||||||
|
if root !=# '' && isdirectory(root)
|
||||||
|
call add(dirs, root)
|
||||||
|
endif
|
||||||
|
|
||||||
|
let paths = map(split(go#util#env("gopath"), go#util#PathListSep()), "substitute(v:val, '\\\\', '/', 'g')")
|
||||||
|
if !empty(filter(paths, 'isdirectory(v:val)'))
|
||||||
|
call extend(dirs, paths)
|
||||||
|
endif
|
||||||
|
|
||||||
|
return dirs
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:go_packages(dirs) abort
|
||||||
|
let pkgs = []
|
||||||
|
for d in a:dirs
|
||||||
|
let pkg_root = expand(d . '/pkg/' . go#util#osarch())
|
||||||
|
call extend(pkgs, split(globpath(pkg_root, '**/*.a', 1), "\n"))
|
||||||
|
endfor
|
||||||
|
return map(pkgs, "fnamemodify(v:val, ':t:r')")
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:interface_list(pkg) abort
|
||||||
|
let [contents, err] = go#util#Exec(['go', 'doc', a:pkg])
|
||||||
|
if err
|
||||||
|
return []
|
||||||
|
endif
|
||||||
|
|
||||||
|
let contents = split(contents, "\n")
|
||||||
|
call filter(contents, 'v:val =~# ''^type\s\+\h\w*\s\+interface''')
|
||||||
|
return map(contents, 'a:pkg . "." . matchstr(v:val, ''^type\s\+\zs\h\w*\ze\s\+interface'')')
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Complete package and interface for {interface}
|
||||||
|
function! go#impl#Complete(arglead, cmdline, cursorpos) abort
|
||||||
|
let words = split(a:cmdline, '\s\+', 1)
|
||||||
|
if words[-1] ==# ''
|
||||||
|
return s:uniq(sort(s:go_packages(s:root_dirs())))
|
||||||
|
elseif words[-1] =~# '^\h\w*$'
|
||||||
|
return s:uniq(sort(filter(s:go_packages(s:root_dirs()), 'stridx(v:val, words[-1]) == 0')))
|
||||||
|
elseif words[-1] =~# '^\h\w*\.\%(\h\w*\)\=$'
|
||||||
|
let [pkg, interface] = split(words[-1], '\.', 1)
|
||||||
|
echomsg pkg
|
||||||
|
return s:uniq(sort(filter(s:interface_list(pkg), 'v:val =~? words[-1]')))
|
||||||
|
else
|
||||||
|
return []
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
37
autoload/go/impl_test.vim
Normal file
37
autoload/go/impl_test.vim
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
func! Test_impl() abort
|
||||||
|
try
|
||||||
|
let l:tmp = gotest#write_file('a/a.go', [
|
||||||
|
\ 'package a',
|
||||||
|
\ '',
|
||||||
|
\ ''])
|
||||||
|
|
||||||
|
call go#impl#Impl('r', 'reader', 'io.Reader')
|
||||||
|
call gotest#assert_buffer(1, [
|
||||||
|
\ 'func (r reader) Read(p []byte) (n int, err error) {',
|
||||||
|
\ ' panic("not implemented")',
|
||||||
|
\ '}'])
|
||||||
|
finally
|
||||||
|
call delete(l:tmp, 'rf')
|
||||||
|
endtry
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func! Test_impl_get() abort
|
||||||
|
try
|
||||||
|
let l:tmp = gotest#write_file('a/a.go', [
|
||||||
|
\ 'package a',
|
||||||
|
\ '',
|
||||||
|
\ 'type reader struct {}'])
|
||||||
|
|
||||||
|
call go#impl#Impl('io.Reader')
|
||||||
|
call gotest#assert_buffer(0, [
|
||||||
|
\ 'package a',
|
||||||
|
\ '',
|
||||||
|
\ 'type reader struct {}',
|
||||||
|
\ '',
|
||||||
|
\ 'func (r *reader) Read(p []byte) (n int, err error) {',
|
||||||
|
\ ' panic("not implemented")',
|
||||||
|
\ '}'])
|
||||||
|
finally
|
||||||
|
call delete(l:tmp, 'rf')
|
||||||
|
endtry
|
||||||
|
endfunc
|
||||||
@ -4,7 +4,7 @@
|
|||||||
"
|
"
|
||||||
" Check out the docs for more information at /doc/vim-go.txt
|
" Check out the docs for more information at /doc/vim-go.txt
|
||||||
"
|
"
|
||||||
function! go#import#SwitchImport(enabled, localname, path, bang)
|
function! go#import#SwitchImport(enabled, localname, path, bang) abort
|
||||||
let view = winsaveview()
|
let view = winsaveview()
|
||||||
let path = substitute(a:path, '^\s*\(.\{-}\)\s*$', '\1', '')
|
let path = substitute(a:path, '^\s*\(.\{-}\)\s*$', '\1', '')
|
||||||
|
|
||||||
@ -27,8 +27,8 @@ function! go#import#SwitchImport(enabled, localname, path, bang)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
if a:bang == "!"
|
if a:bang == "!"
|
||||||
let out = system("go get -u -v ".shellescape(path))
|
let out = go#util#System("go get -u -v ".shellescape(path))
|
||||||
if v:shell_error
|
if go#util#ShellError() != 0
|
||||||
call s:Error("Can't find import: " . path . ":" . out)
|
call s:Error("Can't find import: " . path . ":" . out)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
@ -205,9 +205,9 @@ function! go#import#SwitchImport(enabled, localname, path, bang)
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! s:Error(s)
|
function! s:Error(s) abort
|
||||||
echohl Error | echo a:s | echohl None
|
echohl Error | echo a:s | echohl None
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
102
autoload/go/job.vim
Normal file
102
autoload/go/job.vim
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
" Spawn returns callbacks to be used with job_start. It's abstracted to be
|
||||||
|
" used with various go command, such as build, test, install, etc.. This avoid
|
||||||
|
" us to write the same callback over and over for some commands. It's fully
|
||||||
|
" customizable so each command can change it to it's own logic.
|
||||||
|
function go#job#Spawn(args)
|
||||||
|
let cbs = {
|
||||||
|
\ 'winnr': winnr(),
|
||||||
|
\ 'dir': getcwd(),
|
||||||
|
\ 'jobdir': fnameescape(expand("%:p:h")),
|
||||||
|
\ 'messages': [],
|
||||||
|
\ 'args': a:args.cmd,
|
||||||
|
\ 'bang': 0,
|
||||||
|
\ 'for': "_job",
|
||||||
|
\ }
|
||||||
|
|
||||||
|
if has_key(a:args, 'bang')
|
||||||
|
let cbs.bang = a:args.bang
|
||||||
|
endif
|
||||||
|
|
||||||
|
if has_key(a:args, 'for')
|
||||||
|
let cbs.for = a:args.for
|
||||||
|
endif
|
||||||
|
|
||||||
|
" add final callback to be called if async job is finished
|
||||||
|
" The signature should be in form: func(job, exit_status, messages)
|
||||||
|
if has_key(a:args, 'custom_cb')
|
||||||
|
let cbs.custom_cb = a:args.custom_cb
|
||||||
|
endif
|
||||||
|
|
||||||
|
if has_key(a:args, 'error_info_cb')
|
||||||
|
let cbs.error_info_cb = a:args.error_info_cb
|
||||||
|
endif
|
||||||
|
|
||||||
|
function cbs.callback(chan, msg) dict
|
||||||
|
call add(self.messages, a:msg)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function cbs.exit_cb(job, exitval) dict
|
||||||
|
if has_key(self, 'error_info_cb')
|
||||||
|
call self.error_info_cb(a:job, a:exitval, self.messages)
|
||||||
|
endif
|
||||||
|
|
||||||
|
if get(g:, 'go_echo_command_info', 1)
|
||||||
|
if a:exitval == 0
|
||||||
|
call go#util#EchoSuccess("SUCCESS")
|
||||||
|
else
|
||||||
|
call go#util#EchoError("FAILED")
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
if has_key(self, 'custom_cb')
|
||||||
|
call self.custom_cb(a:job, a:exitval, self.messages)
|
||||||
|
endif
|
||||||
|
|
||||||
|
let l:listtype = go#list#Type(self.for)
|
||||||
|
if a:exitval == 0
|
||||||
|
call go#list#Clean(l:listtype)
|
||||||
|
call go#list#Window(l:listtype)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
call self.show_errors(l:listtype)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function cbs.show_errors(listtype) dict
|
||||||
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
||||||
|
try
|
||||||
|
execute cd self.jobdir
|
||||||
|
let errors = go#tool#ParseErrors(self.messages)
|
||||||
|
let errors = go#tool#FilterValids(errors)
|
||||||
|
finally
|
||||||
|
execute cd . fnameescape(self.dir)
|
||||||
|
endtry
|
||||||
|
|
||||||
|
if !len(errors)
|
||||||
|
" failed to parse errors, output the original content
|
||||||
|
call go#util#EchoError(self.messages + [self.dir])
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
if self.winnr == winnr()
|
||||||
|
call go#list#Populate(a:listtype, errors, join(self.args))
|
||||||
|
call go#list#Window(a:listtype, len(errors))
|
||||||
|
if !empty(errors) && !self.bang
|
||||||
|
call go#list#JumpToFirst(a:listtype)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" override callback handler if user provided it
|
||||||
|
if has_key(a:args, 'callback')
|
||||||
|
let cbs.callback = a:args.callback
|
||||||
|
endif
|
||||||
|
|
||||||
|
" override exit callback handler if user provided it
|
||||||
|
if has_key(a:args, 'exit_cb')
|
||||||
|
let cbs.exit_cb = a:args.exit_cb
|
||||||
|
endif
|
||||||
|
|
||||||
|
return cbs
|
||||||
|
endfunction
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
@ -2,62 +2,68 @@
|
|||||||
" internal function s:spawn
|
" internal function s:spawn
|
||||||
let s:jobs = {}
|
let s:jobs = {}
|
||||||
|
|
||||||
|
" s:handlers is a global event handlers for all jobs started with Spawn() or
|
||||||
|
" with the internal function s:spawn
|
||||||
|
let s:handlers = {}
|
||||||
|
|
||||||
" Spawn is a wrapper around s:spawn. It can be executed by other files and
|
" Spawn is a wrapper around s:spawn. It can be executed by other files and
|
||||||
" scripts if needed. Desc defines the description for printing the status
|
" scripts if needed. Desc defines the description for printing the status
|
||||||
" during the job execution (useful for statusline integration).
|
" during the job execution (useful for statusline integration).
|
||||||
function! go#jobcontrol#Spawn(bang, desc, args)
|
function! go#jobcontrol#Spawn(bang, desc, for, args) abort
|
||||||
" autowrite is not enabled for jobs
|
" autowrite is not enabled for jobs
|
||||||
call go#cmd#autowrite()
|
call go#cmd#autowrite()
|
||||||
|
|
||||||
let job = s:spawn(a:bang, a:desc, a:args)
|
let job = s:spawn(a:bang, a:desc, a:for, a:args)
|
||||||
return job.id
|
return job.id
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Statusline returns the current status of the job
|
" AddHandler adds a on_exit callback handler and returns the id.
|
||||||
function! go#jobcontrol#Statusline() abort
|
function! go#jobcontrol#AddHandler(handler) abort
|
||||||
if empty(s:jobs)
|
let i = len(s:handlers)
|
||||||
return ''
|
while has_key(s:handlers, string(i))
|
||||||
endif
|
let i += 1
|
||||||
|
break
|
||||||
let import_path = go#package#ImportPath(expand('%:p:h'))
|
endwhile
|
||||||
|
let s:handlers[string(i)] = a:handler
|
||||||
for job in values(s:jobs)
|
return string(i)
|
||||||
if job.importpath != import_path
|
|
||||||
continue
|
|
||||||
endif
|
|
||||||
|
|
||||||
if job.state == "SUCCESS"
|
|
||||||
return ''
|
|
||||||
endif
|
|
||||||
|
|
||||||
return printf("%s ... [%s]", job.desc, job.state)
|
|
||||||
endfor
|
|
||||||
|
|
||||||
return ''
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" spawn spawns a go subcommand with the name and arguments with jobstart. Once
|
" RemoveHandler removes a callback handler by id.
|
||||||
" a job is started a reference will be stored inside s:jobs. spawn changes the
|
function! go#jobcontrol#RemoveHandler(id) abort
|
||||||
" GOPATH when g:go_autodetect_gopath is enabled. The job is started inside the
|
unlet s:handlers[a:id]
|
||||||
" current files folder.
|
endfunction
|
||||||
function! s:spawn(bang, desc, args)
|
|
||||||
|
" spawn spawns a go subcommand with the name and arguments with jobstart. Once a
|
||||||
|
" job is started a reference will be stored inside s:jobs. The job is started
|
||||||
|
" inside the current files folder.
|
||||||
|
function! s:spawn(bang, desc, for, args) abort
|
||||||
|
let status_type = a:args[0]
|
||||||
|
let status_dir = expand('%:p:h')
|
||||||
|
let started_at = reltime()
|
||||||
|
|
||||||
|
call go#statusline#Update(status_dir, {
|
||||||
|
\ 'desc': "current status",
|
||||||
|
\ 'type': status_type,
|
||||||
|
\ 'state': "started",
|
||||||
|
\})
|
||||||
|
|
||||||
let job = {
|
let job = {
|
||||||
\ 'desc': a:desc,
|
\ 'desc': a:desc,
|
||||||
\ 'bang': a:bang,
|
\ 'bang': a:bang,
|
||||||
\ 'winnr': winnr(),
|
\ 'winnr': winnr(),
|
||||||
\ 'importpath': go#package#ImportPath(expand('%:p:h')),
|
\ 'importpath': go#package#ImportPath(),
|
||||||
\ 'state': "RUNNING",
|
\ 'state': "RUNNING",
|
||||||
\ 'stderr' : [],
|
\ 'stderr' : [],
|
||||||
\ 'stdout' : [],
|
\ 'stdout' : [],
|
||||||
\ 'on_stdout': function('s:on_stdout'),
|
\ 'on_stdout': function('s:on_stdout'),
|
||||||
\ 'on_stderr': function('s:on_stderr'),
|
\ 'on_stderr': function('s:on_stderr'),
|
||||||
\ 'on_exit' : function('s:on_exit'),
|
\ 'on_exit' : function('s:on_exit'),
|
||||||
|
\ 'status_type' : status_type,
|
||||||
|
\ 'status_dir' : status_dir,
|
||||||
|
\ 'started_at' : started_at,
|
||||||
|
\ 'for' : a:for,
|
||||||
\ }
|
\ }
|
||||||
|
|
||||||
" modify GOPATH if needed
|
|
||||||
let old_gopath = $GOPATH
|
|
||||||
let $GOPATH = go#path#Detect()
|
|
||||||
|
|
||||||
" execute go build in the files directory
|
" execute go build in the files directory
|
||||||
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
||||||
|
|
||||||
@ -83,9 +89,6 @@ function! s:spawn(bang, desc, args)
|
|||||||
|
|
||||||
execute cd . fnameescape(dir)
|
execute cd . fnameescape(dir)
|
||||||
|
|
||||||
" restore back GOPATH
|
|
||||||
let $GOPATH = old_gopath
|
|
||||||
|
|
||||||
return job
|
return job
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
@ -93,29 +96,57 @@ endfunction
|
|||||||
" references and also displaying errors in the quickfix window collected by
|
" references and also displaying errors in the quickfix window collected by
|
||||||
" on_stderr handler. If there are no errors and a quickfix window is open,
|
" on_stderr handler. If there are no errors and a quickfix window is open,
|
||||||
" it'll be closed.
|
" it'll be closed.
|
||||||
function! s:on_exit(job_id, exit_status)
|
function! s:on_exit(job_id, exit_status, event) dict abort
|
||||||
|
let status = {
|
||||||
|
\ 'desc': 'last status',
|
||||||
|
\ 'type': self.status_type,
|
||||||
|
\ 'state': "success",
|
||||||
|
\ }
|
||||||
|
|
||||||
|
if a:exit_status
|
||||||
|
let status.state = "failed"
|
||||||
|
endif
|
||||||
|
|
||||||
|
let elapsed_time = reltimestr(reltime(self.started_at))
|
||||||
|
" strip whitespace
|
||||||
|
let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '')
|
||||||
|
let status.state .= printf(" (%ss)", elapsed_time)
|
||||||
|
|
||||||
|
call go#statusline#Update(self.status_dir, status)
|
||||||
|
|
||||||
let std_combined = self.stderr + self.stdout
|
let std_combined = self.stderr + self.stdout
|
||||||
|
|
||||||
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
||||||
|
let dir = getcwd()
|
||||||
|
execute cd self.dir
|
||||||
|
|
||||||
|
call s:callback_handlers_on_exit(s:jobs[a:job_id], a:exit_status, std_combined)
|
||||||
|
|
||||||
|
let l:listtype = go#list#Type(self.for)
|
||||||
if a:exit_status == 0
|
if a:exit_status == 0
|
||||||
call go#list#Clean(0)
|
call go#list#Clean(l:listtype)
|
||||||
call go#list#Window(0)
|
call go#list#Window(l:listtype)
|
||||||
|
|
||||||
let self.state = "SUCCESS"
|
let self.state = "SUCCESS"
|
||||||
call go#util#EchoSuccess("SUCCESS")
|
|
||||||
|
if get(g:, 'go_echo_command_info', 1)
|
||||||
|
call go#util#EchoSuccess("[" . self.status_type . "] SUCCESS")
|
||||||
|
endif
|
||||||
|
|
||||||
|
execute cd . fnameescape(dir)
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let self.state = "FAILED"
|
let self.state = "FAILED"
|
||||||
call go#util#EchoError("FAILED")
|
|
||||||
|
|
||||||
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
if get(g:, 'go_echo_command_info', 1)
|
||||||
let dir = getcwd()
|
call go#util#EchoError("[" . self.status_type . "] FAILED")
|
||||||
try
|
endif
|
||||||
execute cd self.dir
|
|
||||||
let errors = go#tool#ParseErrors(std_combined)
|
let errors = go#tool#ParseErrors(std_combined)
|
||||||
let errors = go#tool#FilterValids(errors)
|
let errors = go#tool#FilterValids(errors)
|
||||||
finally
|
|
||||||
execute cd . fnameescape(dir)
|
execute cd . fnameescape(dir)
|
||||||
endtry
|
|
||||||
|
|
||||||
if !len(errors)
|
if !len(errors)
|
||||||
" failed to parse errors, output the original content
|
" failed to parse errors, output the original content
|
||||||
@ -125,8 +156,7 @@ function! s:on_exit(job_id, exit_status)
|
|||||||
|
|
||||||
" if we are still in the same windows show the list
|
" if we are still in the same windows show the list
|
||||||
if self.winnr == winnr()
|
if self.winnr == winnr()
|
||||||
let l:listtype = "locationlist"
|
call go#list#Populate(l:listtype, errors, self.desc)
|
||||||
call go#list#Populate(l:listtype, errors)
|
|
||||||
call go#list#Window(l:listtype, len(errors))
|
call go#list#Window(l:listtype, len(errors))
|
||||||
if !empty(errors) && !self.bang
|
if !empty(errors) && !self.bang
|
||||||
call go#list#JumpToFirst(l:listtype)
|
call go#list#JumpToFirst(l:listtype)
|
||||||
@ -134,46 +164,27 @@ function! s:on_exit(job_id, exit_status)
|
|||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
" callback_handlers_on_exit runs all handlers for job on exit event.
|
||||||
|
function! s:callback_handlers_on_exit(job, exit_status, data) abort
|
||||||
|
if empty(s:handlers)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
for s:handler in values(s:handlers)
|
||||||
|
call s:handler(a:job, a:exit_status, a:data)
|
||||||
|
endfor
|
||||||
|
endfunction
|
||||||
|
|
||||||
" on_stdout is the stdout handler for jobstart(). It collects the output of
|
" on_stdout is the stdout handler for jobstart(). It collects the output of
|
||||||
" stderr and stores them to the jobs internal stdout list.
|
" stderr and stores them to the jobs internal stdout list.
|
||||||
function! s:on_stdout(job_id, data)
|
function! s:on_stdout(job_id, data, event) dict abort
|
||||||
call extend(self.stdout, a:data)
|
call extend(self.stdout, a:data)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" on_stderr is the stderr handler for jobstart(). It collects the output of
|
" on_stderr is the stderr handler for jobstart(). It collects the output of
|
||||||
" stderr and stores them to the jobs internal stderr list.
|
" stderr and stores them to the jobs internal stderr list.
|
||||||
function! s:on_stderr(job_id, data)
|
function! s:on_stderr(job_id, data, event) dict abort
|
||||||
call extend(self.stderr, a:data)
|
call extend(self.stderr, a:data)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" abort_all aborts all current jobs created with s:spawn()
|
" vim: sw=2 ts=2 et
|
||||||
function! s:abort_all()
|
|
||||||
if empty(s:jobs)
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
|
|
||||||
for id in keys(s:jobs)
|
|
||||||
if id > 0
|
|
||||||
silent! call jobstop(id)
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
|
|
||||||
let s:jobs = {}
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" abort aborts the job with the given name, where name is the first argument
|
|
||||||
" passed to s:spawn()
|
|
||||||
function! s:abort(path)
|
|
||||||
if empty(s:jobs)
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
|
|
||||||
for job in values(s:jobs)
|
|
||||||
if job.importpath == path && job.id > 0
|
|
||||||
silent! call jobstop(job.id)
|
|
||||||
unlet s:jobs['job.id']
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" vim:ts=2:sw=2:et
|
|
||||||
|
|||||||
56
autoload/go/keyify.vim
Normal file
56
autoload/go/keyify.vim
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
function! go#keyify#Keyify()
|
||||||
|
let bin_path = go#path#CheckBinPath("keyify")
|
||||||
|
let fname = fnamemodify(expand("%"), ':p:gs?\\?/?')
|
||||||
|
|
||||||
|
if empty(bin_path) || !exists('*json_decode')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Get result of command as json, that contains `start`, `end` and `replacement`
|
||||||
|
let command = printf("%s -json %s:#%s", go#util#Shellescape(bin_path),
|
||||||
|
\ go#util#Shellescape(fname), go#util#OffsetCursor())
|
||||||
|
let output = go#util#System(command)
|
||||||
|
silent! let result = json_decode(output)
|
||||||
|
|
||||||
|
" We want to output the error message in case the result isn't a JSON
|
||||||
|
if type(result) != type({})
|
||||||
|
call go#util#EchoError(s:chomp(output))
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Because keyify returns the byte before the region we want, we goto the
|
||||||
|
" byte after that
|
||||||
|
execute "goto" result.start + 1
|
||||||
|
let start = getpos('.')
|
||||||
|
execute "goto" result.end
|
||||||
|
let end = getpos('.')
|
||||||
|
|
||||||
|
let vis_start = getpos("'<")
|
||||||
|
let vis_end = getpos("'>")
|
||||||
|
|
||||||
|
" Replace contents between start and end with `replacement`
|
||||||
|
call setpos("'<", start)
|
||||||
|
call setpos("'>", end)
|
||||||
|
|
||||||
|
let select = 'gv'
|
||||||
|
|
||||||
|
" Make sure the visual mode is 'v', to avoid some bugs
|
||||||
|
normal! gv
|
||||||
|
if mode() !=# 'v'
|
||||||
|
let select .= 'v'
|
||||||
|
endif
|
||||||
|
|
||||||
|
silent! execute "normal!" select."\"=result.replacement\<cr>p"
|
||||||
|
|
||||||
|
" Replacement text isn't aligned, so it needs fix
|
||||||
|
normal! '<v'>=
|
||||||
|
|
||||||
|
call setpos("'<", vis_start)
|
||||||
|
call setpos("'>", vis_end)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:chomp(string)
|
||||||
|
return substitute(a:string, '\n\+$', '', '')
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
@ -10,8 +10,8 @@ if !exists("g:go_metalinter_enabled")
|
|||||||
let g:go_metalinter_enabled = ['vet', 'golint', 'errcheck']
|
let g:go_metalinter_enabled = ['vet', 'golint', 'errcheck']
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if !exists("g:go_metalinter_deadline")
|
if !exists("g:go_metalinter_excludes")
|
||||||
let g:go_metalinter_deadline = "5s"
|
let g:go_metalinter_excludes = []
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if !exists("g:go_golint_bin")
|
if !exists("g:go_golint_bin")
|
||||||
@ -24,47 +24,80 @@ endif
|
|||||||
|
|
||||||
function! go#lint#Gometa(autosave, ...) abort
|
function! go#lint#Gometa(autosave, ...) abort
|
||||||
if a:0 == 0
|
if a:0 == 0
|
||||||
let goargs = expand('%:p:h')
|
let goargs = shellescape(expand('%:p:h'))
|
||||||
else
|
else
|
||||||
let goargs = go#util#Shelljoin(a:000)
|
let goargs = go#util#Shelljoin(a:000)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let meta_command = "gometalinter --disable-all"
|
|
||||||
if a:autosave || empty(g:go_metalinter_command)
|
|
||||||
let bin_path = go#path#CheckBinPath("gometalinter")
|
let bin_path = go#path#CheckBinPath("gometalinter")
|
||||||
if empty(bin_path)
|
if empty(bin_path)
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if a:autosave
|
let cmd = [bin_path]
|
||||||
" include only messages for the active buffer
|
let cmd += ["--disable-all"]
|
||||||
let meta_command .= " --include='^" . expand('%:p') . ".*$'"
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
if a:autosave || empty(g:go_metalinter_command)
|
||||||
" linters
|
" linters
|
||||||
let linters = a:autosave ? g:go_metalinter_autosave_enabled : g:go_metalinter_enabled
|
let linters = a:autosave ? g:go_metalinter_autosave_enabled : g:go_metalinter_enabled
|
||||||
for linter in linters
|
for linter in linters
|
||||||
let meta_command .= " --enable=".linter
|
let cmd += ["--enable=".linter]
|
||||||
endfor
|
endfor
|
||||||
|
|
||||||
" deadline
|
for exclude in g:go_metalinter_excludes
|
||||||
let meta_command .= " --deadline=" . g:go_metalinter_deadline
|
let cmd += ["--exclude=".exclude]
|
||||||
|
endfor
|
||||||
|
|
||||||
|
" gometalinter has a --tests flag to tell its linters whether to run
|
||||||
|
" against tests. While not all of its linters respect this flag, for those
|
||||||
|
" that do, it means if we don't pass --tests, the linter won't run against
|
||||||
|
" test files. One example of a linter that will not run against tests if
|
||||||
|
" we do not specify this flag is errcheck.
|
||||||
|
let cmd += ["--tests"]
|
||||||
|
|
||||||
" path
|
" path
|
||||||
let meta_command .= " " . goargs
|
let cmd += [expand('%:p:h')]
|
||||||
else
|
else
|
||||||
" the user wants something else, let us use it.
|
" the user wants something else, let us use it.
|
||||||
let meta_command = g:go_metalinter_command
|
let cmd += split(g:go_metalinter_command, " ")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" comment out the following two lines for debugging
|
" gometalinter has a default deadline of 5 seconds.
|
||||||
" echo meta_command
|
"
|
||||||
" return
|
" For async mode (s:lint_job), we want to override the default deadline only
|
||||||
|
" if we have a deadline configured.
|
||||||
|
"
|
||||||
|
" For sync mode (go#util#System), always explicitly pass the 5 seconds
|
||||||
|
" deadline if there is no other deadline configured. If a deadline is
|
||||||
|
" configured, then use it.
|
||||||
|
|
||||||
let out = go#tool#ExecuteInDir(meta_command)
|
" Call gometalinter asynchronously.
|
||||||
|
if go#util#has_job() && has('lambda')
|
||||||
|
let deadline = get(g:, 'go_metalinter_deadline', 0)
|
||||||
|
if deadline != 0
|
||||||
|
let cmd += ["--deadline=" . deadline]
|
||||||
|
endif
|
||||||
|
|
||||||
let l:listtype = "quickfix"
|
call s:lint_job({'cmd': cmd})
|
||||||
if v:shell_error == 0
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
" We're calling gometalinter synchronously.
|
||||||
|
|
||||||
|
let cmd += ["--deadline=" . get(g:, 'go_metalinter_deadline', "5s")]
|
||||||
|
|
||||||
|
if a:autosave
|
||||||
|
" include only messages for the active buffer
|
||||||
|
let cmd += ["--include='^" . expand('%:p') . ".*$'"]
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
let meta_command = join(cmd, " ")
|
||||||
|
|
||||||
|
let out = go#util#System(meta_command)
|
||||||
|
|
||||||
|
let l:listtype = go#list#Type("GoMetaLinter")
|
||||||
|
if go#util#ShellError() == 0
|
||||||
redraw | echo
|
redraw | echo
|
||||||
call go#list#Clean(l:listtype)
|
call go#list#Clean(l:listtype)
|
||||||
call go#list#Window(l:listtype)
|
call go#list#Window(l:listtype)
|
||||||
@ -77,7 +110,7 @@ function! go#lint#Gometa(autosave, ...) abort
|
|||||||
let errformat = "%f:%l:%c:%t%*[^:]:\ %m,%f:%l::%t%*[^:]:\ %m"
|
let errformat = "%f:%l:%c:%t%*[^:]:\ %m,%f:%l::%t%*[^:]:\ %m"
|
||||||
|
|
||||||
" Parse and populate our location list
|
" Parse and populate our location list
|
||||||
call go#list#ParseFormat(l:listtype, errformat, split(out, "\n"))
|
call go#list#ParseFormat(l:listtype, errformat, split(out, "\n"), 'GoMetaLinter')
|
||||||
|
|
||||||
let errors = go#list#Get(l:listtype)
|
let errors = go#list#Get(l:listtype)
|
||||||
call go#list#Window(l:listtype, len(errors))
|
call go#list#Window(l:listtype, len(errors))
|
||||||
@ -95,20 +128,20 @@ function! go#lint#Golint(...) abort
|
|||||||
if empty(bin_path)
|
if empty(bin_path)
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
let bin_path = go#util#Shellescape(bin_path)
|
||||||
|
|
||||||
if a:0 == 0
|
if a:0 == 0
|
||||||
let goargs = shellescape(expand('%'))
|
let out = go#util#System(bin_path . " " . go#util#Shellescape(go#package#ImportPath()))
|
||||||
else
|
else
|
||||||
let goargs = go#util#Shelljoin(a:000)
|
let out = go#util#System(bin_path . " " . go#util#Shelljoin(a:000))
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let out = system(bin_path . " " . goargs)
|
|
||||||
if empty(out)
|
if empty(out)
|
||||||
echon "vim-go: " | echohl Function | echon "[lint] PASS" | echohl None
|
echon "vim-go: " | echohl Function | echon "[lint] PASS" | echohl None
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let l:listtype = "quickfix"
|
let l:listtype = go#list#Type("GoLint")
|
||||||
call go#list#Parse(l:listtype, out)
|
call go#list#Parse(l:listtype, out)
|
||||||
let errors = go#list#Get(l:listtype)
|
let errors = go#list#Get(l:listtype)
|
||||||
call go#list#Window(l:listtype, len(errors))
|
call go#list#Window(l:listtype, len(errors))
|
||||||
@ -117,19 +150,19 @@ endfunction
|
|||||||
|
|
||||||
" Vet calls 'go vet' on the current directory. Any warnings are populated in
|
" Vet calls 'go vet' on the current directory. Any warnings are populated in
|
||||||
" the location list
|
" the location list
|
||||||
function! go#lint#Vet(bang, ...)
|
function! go#lint#Vet(bang, ...) abort
|
||||||
call go#cmd#autowrite()
|
call go#cmd#autowrite()
|
||||||
echon "vim-go: " | echohl Identifier | echon "calling vet..." | echohl None
|
echon "vim-go: " | echohl Identifier | echon "calling vet..." | echohl None
|
||||||
if a:0 == 0
|
if a:0 == 0
|
||||||
let out = go#tool#ExecuteInDir('go vet')
|
let out = go#util#System('go vet ' . go#util#Shellescape(go#package#ImportPath()))
|
||||||
else
|
else
|
||||||
let out = go#tool#ExecuteInDir('go tool vet ' . go#util#Shelljoin(a:000))
|
let out = go#util#System('go tool vet ' . go#util#Shelljoin(a:000))
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let l:listtype = "quickfix"
|
let l:listtype = go#list#Type("GoVet")
|
||||||
if v:shell_error
|
if go#util#ShellError() != 0
|
||||||
let errors = go#tool#ParseErrors(split(out, '\n'))
|
let errors = go#tool#ParseErrors(split(out, '\n'))
|
||||||
call go#list#Populate(l:listtype, errors)
|
call go#list#Populate(l:listtype, errors, 'Vet')
|
||||||
call go#list#Window(l:listtype, len(errors))
|
call go#list#Window(l:listtype, len(errors))
|
||||||
if !empty(errors) && !a:bang
|
if !empty(errors) && !a:bang
|
||||||
call go#list#JumpToFirst(l:listtype)
|
call go#list#JumpToFirst(l:listtype)
|
||||||
@ -146,13 +179,13 @@ endfunction
|
|||||||
" the location list
|
" the location list
|
||||||
function! go#lint#Errcheck(...) abort
|
function! go#lint#Errcheck(...) abort
|
||||||
if a:0 == 0
|
if a:0 == 0
|
||||||
let goargs = go#package#ImportPath(expand('%:p:h'))
|
let import_path = go#package#ImportPath()
|
||||||
if goargs == -1
|
if import_path == -1
|
||||||
echohl Error | echomsg "vim-go: package is not inside GOPATH src" | echohl None
|
echohl Error | echomsg "vim-go: package is not inside GOPATH src" | echohl None
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
let goargs = go#util#Shelljoin(a:000)
|
let import_path = go#util#Shelljoin(a:000)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let bin_path = go#path#CheckBinPath(g:go_errcheck_bin)
|
let bin_path = go#path#CheckBinPath(g:go_errcheck_bin)
|
||||||
@ -163,18 +196,17 @@ function! go#lint#Errcheck(...) abort
|
|||||||
echon "vim-go: " | echohl Identifier | echon "errcheck analysing ..." | echohl None
|
echon "vim-go: " | echohl Identifier | echon "errcheck analysing ..." | echohl None
|
||||||
redraw
|
redraw
|
||||||
|
|
||||||
let command = bin_path . ' -abspath ' . goargs
|
let command = go#util#Shellescape(bin_path) . ' -abspath ' . import_path
|
||||||
let out = go#tool#ExecuteInDir(command)
|
let out = go#tool#ExecuteInDir(command)
|
||||||
|
|
||||||
let l:listtype = "quickfix"
|
let l:listtype = go#list#Type("GoErrCheck")
|
||||||
if v:shell_error
|
if go#util#ShellError() != 0
|
||||||
let errformat = "%f:%l:%c:\ %m, %f:%l:%c\ %#%m"
|
let errformat = "%f:%l:%c:\ %m, %f:%l:%c\ %#%m"
|
||||||
|
|
||||||
" Parse and populate our location list
|
" Parse and populate our location list
|
||||||
call go#list#ParseFormat(l:listtype, errformat, split(out, "\n"))
|
call go#list#ParseFormat(l:listtype, errformat, split(out, "\n"), 'Errcheck')
|
||||||
|
|
||||||
let errors = go#list#Get(l:listtype)
|
let errors = go#list#Get(l:listtype)
|
||||||
|
|
||||||
if empty(errors)
|
if empty(errors)
|
||||||
echohl Error | echomsg "GoErrCheck returned error" | echohl None
|
echohl Error | echomsg "GoErrCheck returned error" | echohl None
|
||||||
echo out
|
echo out
|
||||||
@ -182,7 +214,8 @@ function! go#lint#Errcheck(...) abort
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
if !empty(errors)
|
if !empty(errors)
|
||||||
call go#list#Populate(l:listtype, errors)
|
echohl Error | echomsg "GoErrCheck found errors" | echohl None
|
||||||
|
call go#list#Populate(l:listtype, errors, 'Errcheck')
|
||||||
call go#list#Window(l:listtype, len(errors))
|
call go#list#Window(l:listtype, len(errors))
|
||||||
if !empty(errors)
|
if !empty(errors)
|
||||||
call go#list#JumpToFirst(l:listtype)
|
call go#list#JumpToFirst(l:listtype)
|
||||||
@ -196,4 +229,101 @@ function! go#lint#Errcheck(...) abort
|
|||||||
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
function! go#lint#ToggleMetaLinterAutoSave() abort
|
||||||
|
if get(g:, "go_metalinter_autosave", 0)
|
||||||
|
let g:go_metalinter_autosave = 0
|
||||||
|
call go#util#EchoProgress("auto metalinter disabled")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
let g:go_metalinter_autosave = 1
|
||||||
|
call go#util#EchoProgress("auto metalinter enabled")
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function s:lint_job(args)
|
||||||
|
let status_dir = expand('%:p:h')
|
||||||
|
let started_at = reltime()
|
||||||
|
|
||||||
|
call go#statusline#Update(status_dir, {
|
||||||
|
\ 'desc': "current status",
|
||||||
|
\ 'type': "gometalinter",
|
||||||
|
\ 'state': "analysing",
|
||||||
|
\})
|
||||||
|
|
||||||
|
" autowrite is not enabled for jobs
|
||||||
|
call go#cmd#autowrite()
|
||||||
|
|
||||||
|
let l:listtype = go#list#Type("GoMetaLinter")
|
||||||
|
let l:errformat = '%f:%l:%c:%t%*[^:]:\ %m,%f:%l::%t%*[^:]:\ %m'
|
||||||
|
|
||||||
|
function! s:callback(chan, msg) closure
|
||||||
|
let old_errorformat = &errorformat
|
||||||
|
let &errorformat = l:errformat
|
||||||
|
try
|
||||||
|
if l:listtype == "locationlist"
|
||||||
|
lad a:msg
|
||||||
|
elseif l:listtype == "quickfix"
|
||||||
|
caddexpr a:msg
|
||||||
|
endif
|
||||||
|
finally
|
||||||
|
let &errorformat = old_errorformat
|
||||||
|
endtry
|
||||||
|
|
||||||
|
" TODO(jinleileiking): give a configure to jump or not
|
||||||
|
let l:winnr = winnr()
|
||||||
|
|
||||||
|
let errors = go#list#Get(l:listtype)
|
||||||
|
call go#list#Window(l:listtype, len(errors))
|
||||||
|
|
||||||
|
exe l:winnr . "wincmd w"
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:exit_cb(job, exitval) closure
|
||||||
|
let status = {
|
||||||
|
\ 'desc': 'last status',
|
||||||
|
\ 'type': "gometaliner",
|
||||||
|
\ 'state': "finished",
|
||||||
|
\ }
|
||||||
|
|
||||||
|
if a:exitval
|
||||||
|
let status.state = "failed"
|
||||||
|
endif
|
||||||
|
|
||||||
|
let elapsed_time = reltimestr(reltime(started_at))
|
||||||
|
" strip whitespace
|
||||||
|
let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '')
|
||||||
|
let status.state .= printf(" (%ss)", elapsed_time)
|
||||||
|
|
||||||
|
call go#statusline#Update(status_dir, status)
|
||||||
|
|
||||||
|
let errors = go#list#Get(l:listtype)
|
||||||
|
if empty(errors)
|
||||||
|
call go#list#Window(l:listtype, len(errors))
|
||||||
|
elseif has("patch-7.4.2200")
|
||||||
|
if l:listtype == 'quickfix'
|
||||||
|
call setqflist([], 'a', {'title': 'GoMetaLinter'})
|
||||||
|
else
|
||||||
|
call setloclist(0, [], 'a', {'title': 'GoMetaLinter'})
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
if get(g:, 'go_echo_command_info', 1)
|
||||||
|
call go#util#EchoSuccess("linting finished")
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
let start_options = {
|
||||||
|
\ 'callback': funcref("s:callback"),
|
||||||
|
\ 'exit_cb': funcref("s:exit_cb"),
|
||||||
|
\ }
|
||||||
|
|
||||||
|
call job_start(a:args.cmd, start_options)
|
||||||
|
|
||||||
|
call go#list#Clean(l:listtype)
|
||||||
|
|
||||||
|
if get(g:, 'go_echo_command_info', 1)
|
||||||
|
call go#util#EchoProgress("linting started ...")
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
@ -2,22 +2,30 @@ if !exists("g:go_list_type")
|
|||||||
let g:go_list_type = ""
|
let g:go_list_type = ""
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if !exists("g:go_list_type_commands")
|
||||||
|
let g:go_list_type_commands = {}
|
||||||
|
endif
|
||||||
|
|
||||||
" Window opens the list with the given height up to 10 lines maximum.
|
" Window opens the list with the given height up to 10 lines maximum.
|
||||||
" Otherwise g:go_loclist_height is used. If no or zero height is given it
|
" Otherwise g:go_loclist_height is used.
|
||||||
" closes the window
|
"
|
||||||
function! go#list#Window(listtype, ...)
|
" If no or zero height is given it closes the window by default.
|
||||||
let l:listtype = go#list#Type(a:listtype)
|
" To prevent this, set g:go_list_autoclose = 0
|
||||||
|
function! go#list#Window(listtype, ...) abort
|
||||||
" we don't use lwindow to close the location list as we need also the
|
" we don't use lwindow to close the location list as we need also the
|
||||||
" ability to resize the window. So, we are going to use lopen and lclose
|
" ability to resize the window. So, we are going to use lopen and lclose
|
||||||
" for a better user experience. If the number of errors in a current
|
" for a better user experience. If the number of errors in a current
|
||||||
" location list increases/decreases, cwindow will not resize when a new
|
" location list increases/decreases, cwindow will not resize when a new
|
||||||
" updated height is passed. lopen in the other hand resizes the screen.
|
" updated height is passed. lopen in the other hand resizes the screen.
|
||||||
if !a:0 || a:1 == 0
|
if !a:0 || a:1 == 0
|
||||||
if l:listtype == "locationlist"
|
let autoclose_window = get(g:, 'go_list_autoclose', 1)
|
||||||
|
if autoclose_window
|
||||||
|
if a:listtype == "locationlist"
|
||||||
lclose
|
lclose
|
||||||
else
|
else
|
||||||
cclose
|
cclose
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -31,7 +39,7 @@ function! go#list#Window(listtype, ...)
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if l:listtype == "locationlist"
|
if a:listtype == "locationlist"
|
||||||
exe 'lopen ' . height
|
exe 'lopen ' . height
|
||||||
else
|
else
|
||||||
exe 'copen ' . height
|
exe 'copen ' . height
|
||||||
@ -39,54 +47,55 @@ function! go#list#Window(listtype, ...)
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
" Get returns the current list of items from the location list
|
" Get returns the current items from the list
|
||||||
function! go#list#Get(listtype)
|
function! go#list#Get(listtype) abort
|
||||||
let l:listtype = go#list#Type(a:listtype)
|
if a:listtype == "locationlist"
|
||||||
if l:listtype == "locationlist"
|
|
||||||
return getloclist(0)
|
return getloclist(0)
|
||||||
else
|
else
|
||||||
return getqflist()
|
return getqflist()
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Populate populate the location list with the given items
|
" Populate populate the list with the given items
|
||||||
function! go#list#Populate(listtype, items)
|
function! go#list#Populate(listtype, items, title) abort
|
||||||
let l:listtype = go#list#Type(a:listtype)
|
if a:listtype == "locationlist"
|
||||||
if l:listtype == "locationlist"
|
|
||||||
call setloclist(0, a:items, 'r')
|
call setloclist(0, a:items, 'r')
|
||||||
|
|
||||||
|
" The last argument ({what}) is introduced with 7.4.2200:
|
||||||
|
" https://github.com/vim/vim/commit/d823fa910cca43fec3c31c030ee908a14c272640
|
||||||
|
if has("patch-7.4.2200") | call setloclist(0, [], 'a', {'title': a:title}) | endif
|
||||||
else
|
else
|
||||||
call setqflist(a:items, 'r')
|
call setqflist(a:items, 'r')
|
||||||
|
if has("patch-7.4.2200") | call setqflist([], 'a', {'title': a:title}) | endif
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! go#list#PopulateWin(winnr, items)
|
" Parse parses the given items based on the specified errorformat and
|
||||||
call setloclist(a:winnr, a:items, 'r')
|
" populates the list.
|
||||||
endfunction
|
function! go#list#ParseFormat(listtype, errformat, items, title) abort
|
||||||
|
|
||||||
" Parse parses the given items based on the specified errorformat nad
|
|
||||||
" populates the location list.
|
|
||||||
function! go#list#ParseFormat(listtype, errformat, items)
|
|
||||||
let l:listtype = go#list#Type(a:listtype)
|
|
||||||
" backup users errorformat, will be restored once we are finished
|
" backup users errorformat, will be restored once we are finished
|
||||||
let old_errorformat = &errorformat
|
let old_errorformat = &errorformat
|
||||||
|
|
||||||
" parse and populate the location list
|
" parse and populate the location list
|
||||||
let &errorformat = a:errformat
|
let &errorformat = a:errformat
|
||||||
if l:listtype == "locationlist"
|
try
|
||||||
|
if a:listtype == "locationlist"
|
||||||
lgetexpr a:items
|
lgetexpr a:items
|
||||||
|
if has("patch-7.4.2200") | call setloclist(0, [], 'a', {'title': a:title}) | endif
|
||||||
else
|
else
|
||||||
cgetexpr a:items
|
cgetexpr a:items
|
||||||
|
if has("patch-7.4.2200") | call setqflist([], 'a', {'title': a:title}) | endif
|
||||||
endif
|
endif
|
||||||
|
finally
|
||||||
"restore back
|
"restore back
|
||||||
let &errorformat = old_errorformat
|
let &errorformat = old_errorformat
|
||||||
|
endtry
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Parse parses the given items based on the global errorformat and
|
" Parse parses the given items based on the global errorformat and
|
||||||
" populates the location list.
|
" populates the list.
|
||||||
function! go#list#Parse(listtype, items)
|
function! go#list#Parse(listtype, items) abort
|
||||||
let l:listtype = go#list#Type(a:listtype)
|
if a:listtype == "locationlist"
|
||||||
if l:listtype == "locationlist"
|
|
||||||
lgetexpr a:items
|
lgetexpr a:items
|
||||||
else
|
else
|
||||||
cgetexpr a:items
|
cgetexpr a:items
|
||||||
@ -94,9 +103,8 @@ function! go#list#Parse(listtype, items)
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" JumpToFirst jumps to the first item in the location list
|
" JumpToFirst jumps to the first item in the location list
|
||||||
function! go#list#JumpToFirst(listtype)
|
function! go#list#JumpToFirst(listtype) abort
|
||||||
let l:listtype = go#list#Type(a:listtype)
|
if a:listtype == "locationlist"
|
||||||
if l:listtype == "locationlist"
|
|
||||||
ll 1
|
ll 1
|
||||||
else
|
else
|
||||||
cc 1
|
cc 1
|
||||||
@ -104,23 +112,58 @@ function! go#list#JumpToFirst(listtype)
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Clean cleans the location list
|
" Clean cleans the location list
|
||||||
function! go#list#Clean(listtype)
|
function! go#list#Clean(listtype) abort
|
||||||
let l:listtype = go#list#Type(a:listtype)
|
if a:listtype == "locationlist"
|
||||||
if l:listtype == "locationlist"
|
|
||||||
lex []
|
lex []
|
||||||
else
|
else
|
||||||
cex []
|
cex []
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! go#list#Type(listtype)
|
function! s:listtype(listtype) abort
|
||||||
if g:go_list_type == "locationlist"
|
if g:go_list_type == "locationlist"
|
||||||
return "locationlist"
|
return "locationlist"
|
||||||
elseif g:go_list_type == "quickfix"
|
elseif g:go_list_type == "quickfix"
|
||||||
return "quickfix"
|
return "quickfix"
|
||||||
else
|
|
||||||
return a:listtype
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
return a:listtype
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
" s:default_list_type_commands is the defaults that will be used for each of
|
||||||
|
" the supported commands (see documentation for g:go_list_type_commands). When
|
||||||
|
" defining a default, quickfix should be used if the command operates on
|
||||||
|
" multiple files, while locationlist should be used if the command operates on a
|
||||||
|
" single file or buffer. Keys that begin with an underscore are not supported
|
||||||
|
" in g:go_list_type_commands.
|
||||||
|
let s:default_list_type_commands = {
|
||||||
|
\ "GoBuild": "quickfix",
|
||||||
|
\ "GoErrCheck": "quickfix",
|
||||||
|
\ "GoFmt": "locationlist",
|
||||||
|
\ "GoGenerate": "quickfix",
|
||||||
|
\ "GoInstall": "quickfix",
|
||||||
|
\ "GoLint": "quickfix",
|
||||||
|
\ "GoMetaLinter": "quickfix",
|
||||||
|
\ "GoModifyTags": "locationlist",
|
||||||
|
\ "GoRename": "quickfix",
|
||||||
|
\ "GoRun": "quickfix",
|
||||||
|
\ "GoTest": "quickfix",
|
||||||
|
\ "GoVet": "quickfix",
|
||||||
|
\ "_guru": "locationlist",
|
||||||
|
\ "_term": "locationlist",
|
||||||
|
\ "_job": "locationlist",
|
||||||
|
\ }
|
||||||
|
|
||||||
|
function! go#list#Type(for) abort
|
||||||
|
let l:listtype = s:listtype(get(s:default_list_type_commands, a:for))
|
||||||
|
if l:listtype == "0"
|
||||||
|
call go#util#EchoError(printf(
|
||||||
|
\ "unknown list type command value found ('%s'). Please open a bug report in the vim-go repo.",
|
||||||
|
\ a:for))
|
||||||
|
let l:listtype = "quickfix"
|
||||||
|
endif
|
||||||
|
|
||||||
|
return get(g:go_list_type_commands, a:for, l:listtype)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
@ -1,233 +0,0 @@
|
|||||||
" oracle.vim -- Vim integration for the Go oracle.
|
|
||||||
"
|
|
||||||
" Part of this plugin was taken directly from the oracle repo, however it's
|
|
||||||
" massively changed for a better integration into vim-go. Thanks Alan Donovan
|
|
||||||
" for the first iteration based on quickfix! - Fatih Arslan
|
|
||||||
"
|
|
||||||
|
|
||||||
if !exists("g:go_oracle_bin")
|
|
||||||
let g:go_oracle_bin = "oracle"
|
|
||||||
endif
|
|
||||||
|
|
||||||
" Parses (via regex) Oracle's 'plain' format output and puts them into a
|
|
||||||
" location list
|
|
||||||
func! s:loclist(output)
|
|
||||||
let llist = []
|
|
||||||
" Parse GNU-style 'file:line.col-line.col: message' format.
|
|
||||||
let mx = '^\(\a:[\\/][^:]\+\|[^:]\+\):\(\d\+\):\(\d\+\):\(.*\)$'
|
|
||||||
for line in split(a:output, "\n")
|
|
||||||
let ml = matchlist(line, mx)
|
|
||||||
|
|
||||||
" Ignore non-match lines or warnings
|
|
||||||
if ml == [] || ml[4] =~ '^ warning:'
|
|
||||||
continue
|
|
||||||
endif
|
|
||||||
|
|
||||||
let item = {
|
|
||||||
\ 'filename': ml[1],
|
|
||||||
\ 'text': ml[4],
|
|
||||||
\ 'lnum': ml[2],
|
|
||||||
\ 'col': ml[3],
|
|
||||||
\}
|
|
||||||
let bnr = bufnr(fnameescape(ml[1]))
|
|
||||||
if bnr != -1
|
|
||||||
let item['bufnr'] = bnr
|
|
||||||
endif
|
|
||||||
call add(llist, item)
|
|
||||||
endfor
|
|
||||||
call go#list#Populate("locationlist", llist)
|
|
||||||
call go#list#Window("locationlist", len(llist))
|
|
||||||
endfun
|
|
||||||
|
|
||||||
" This uses Vim's errorformat to parse the output from Oracle's 'plain output
|
|
||||||
" and put it into location list. I believe using errorformat is much more
|
|
||||||
" easier to use. If we need more power we can always switch back to parse it
|
|
||||||
" via regex.
|
|
||||||
func! s:loclistSecond(output)
|
|
||||||
" backup users errorformat, will be restored once we are finished
|
|
||||||
let old_errorformat = &errorformat
|
|
||||||
|
|
||||||
" match two possible styles of errorformats:
|
|
||||||
"
|
|
||||||
" 'file:line.col-line2.col2: message'
|
|
||||||
" 'file:line:col: message'
|
|
||||||
"
|
|
||||||
" We discard line2 and col2 for the first errorformat, because it's not
|
|
||||||
" useful and location only has the ability to show one line and column
|
|
||||||
" number
|
|
||||||
let errformat = "%f:%l.%c-%[%^:]%#:\ %m,%f:%l:%c:\ %m"
|
|
||||||
call go#list#ParseFormat("locationlist", errformat, split(a:output, "\n"))
|
|
||||||
|
|
||||||
let errors = go#list#Get("locationlist")
|
|
||||||
call go#list#Window("locationlist", len(errors))
|
|
||||||
endfun
|
|
||||||
|
|
||||||
func! s:RunOracle(mode, selected, needs_package) range abort
|
|
||||||
let fname = expand('%:p')
|
|
||||||
let dname = expand('%:p:h')
|
|
||||||
let pkg = go#package#ImportPath(dname)
|
|
||||||
|
|
||||||
if exists('g:go_oracle_scope')
|
|
||||||
" let the user defines the scope, must be a space separated string,
|
|
||||||
" example: 'fmt math net/http'
|
|
||||||
let scopes = split(get(g:, 'go_oracle_scope'))
|
|
||||||
elseif a:needs_package || exists('g:go_oracle_include_tests') && pkg != -1
|
|
||||||
" give import path so it includes all _test.go files too
|
|
||||||
let scopes = [pkg]
|
|
||||||
else
|
|
||||||
" best usable way, only pass the package itself, without the test
|
|
||||||
" files
|
|
||||||
let scopes = go#tool#Files()
|
|
||||||
endif
|
|
||||||
|
|
||||||
"return with a warning if the bin doesn't exist
|
|
||||||
let bin_path = go#path#CheckBinPath(g:go_oracle_bin)
|
|
||||||
if empty(bin_path)
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
|
|
||||||
if exists('g:go_oracle_tags')
|
|
||||||
let tags = get(g:, 'go_oracle_tags')
|
|
||||||
else
|
|
||||||
let tags = ""
|
|
||||||
endif
|
|
||||||
|
|
||||||
if a:selected != -1
|
|
||||||
let pos1 = go#util#Offset(line("'<"), col("'<"))
|
|
||||||
let pos2 = go#util#Offset(line("'>"), col("'>"))
|
|
||||||
let cmd = printf('%s -format plain -pos=%s:#%d,#%d -tags=%s %s',
|
|
||||||
\ bin_path,
|
|
||||||
\ shellescape(fname), pos1, pos2, tags, a:mode)
|
|
||||||
else
|
|
||||||
let pos = go#util#OffsetCursor()
|
|
||||||
let cmd = printf('%s -format plain -pos=%s:#%d -tags=%s %s',
|
|
||||||
\ bin_path,
|
|
||||||
\ shellescape(fname), pos, tags, a:mode)
|
|
||||||
endif
|
|
||||||
|
|
||||||
" strip trailing slashes for each path in scoped. bug:
|
|
||||||
" https://github.com/golang/go/issues/14584
|
|
||||||
let scopes = go#util#StripTrailingSlash(scopes)
|
|
||||||
|
|
||||||
" now append each scope to the end as Oracle's scope parameter. It can be
|
|
||||||
" a packages or go files, dependent on the User's own choice. For more
|
|
||||||
" info check Oracle's User Manual section about scopes:
|
|
||||||
" https://docs.google.com/document/d/1SLk36YRjjMgKqe490mSRzOPYEDe0Y_WQNRv-EiFYUyw/view#heading=h.nwso96pj07q8
|
|
||||||
let cmd .= ' ' . go#util#Shelljoin(scopes)
|
|
||||||
|
|
||||||
echon "vim-go: " | echohl Identifier | echon "analysing ..." | echohl None
|
|
||||||
|
|
||||||
let old_gopath = $GOPATH
|
|
||||||
let $GOPATH = go#path#Detect()
|
|
||||||
|
|
||||||
let out = system(cmd)
|
|
||||||
|
|
||||||
let $GOPATH = old_gopath
|
|
||||||
|
|
||||||
if v:shell_error
|
|
||||||
" unfortunaly oracle outputs a very long stack trace that is not
|
|
||||||
" parsable to show the real error. But the main issue is usually the
|
|
||||||
" package which doesn't build.
|
|
||||||
redraw | echon "vim-go: " | echohl Statement | echon out | echohl None
|
|
||||||
return ""
|
|
||||||
endif
|
|
||||||
|
|
||||||
return out
|
|
||||||
endfunc
|
|
||||||
|
|
||||||
function! go#oracle#Scope(...)
|
|
||||||
if a:0
|
|
||||||
if a:0 == 1 && a:1 == '""'
|
|
||||||
unlet g:go_oracle_scope
|
|
||||||
echon "vim-go: " | echohl Function | echon "oracle scope is cleared"| echohl None
|
|
||||||
else
|
|
||||||
let g:go_oracle_scope = join(a:000, ' ')
|
|
||||||
echon "vim-go: " | echohl Function | echon "oracle scope changed to: '". g:go_oracle_scope ."'" | echohl None
|
|
||||||
endif
|
|
||||||
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
|
|
||||||
if !exists('g:go_oracle_scope')
|
|
||||||
echon "vim-go: " | echohl Function | echon "oracle scope is not set"| echohl None
|
|
||||||
else
|
|
||||||
echon "vim-go: " | echohl Function | echon "current oracle scope: '". g:go_oracle_scope ."'" | echohl None
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! go#oracle#Tags(...)
|
|
||||||
if a:0
|
|
||||||
if a:0 == 1 && a:1 == '""'
|
|
||||||
unlet g:go_oracle_tags
|
|
||||||
echon "vim-go: " | echohl Function | echon "oracle tags is cleared"| echohl None
|
|
||||||
else
|
|
||||||
let g:go_oracle_tags = a:1
|
|
||||||
echon "vim-go: " | echohl Function | echon "oracle tags changed to: '". g:go_oracle_tags ."'" | echohl None
|
|
||||||
endif
|
|
||||||
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
|
|
||||||
if !exists('g:go_oracle_tags')
|
|
||||||
echon "vim-go: " | echohl Function | echon "oracle tags is not set"| echohl None
|
|
||||||
else
|
|
||||||
echon "vim-go: " | echohl Function | echon "current oracle tags: '". g:go_oracle_tags ."'" | echohl None
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Show 'implements' relation for selected package
|
|
||||||
function! go#oracle#Implements(selected)
|
|
||||||
let out = s:RunOracle('implements', a:selected, 0)
|
|
||||||
call s:loclistSecond(out)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Describe selected syntax: definition, methods, etc
|
|
||||||
function! go#oracle#Describe(selected)
|
|
||||||
let out = s:RunOracle('describe', a:selected, 0)
|
|
||||||
call s:loclistSecond(out)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Show possible targets of selected function call
|
|
||||||
function! go#oracle#Callees(selected)
|
|
||||||
let out = s:RunOracle('callees', a:selected, 1)
|
|
||||||
call s:loclistSecond(out)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Show possible callers of selected function
|
|
||||||
function! go#oracle#Callers(selected)
|
|
||||||
let out = s:RunOracle('callers', a:selected, 1)
|
|
||||||
call s:loclistSecond(out)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Show path from callgraph root to selected function
|
|
||||||
function! go#oracle#Callstack(selected)
|
|
||||||
let out = s:RunOracle('callstack', a:selected, 1)
|
|
||||||
call s:loclistSecond(out)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Show free variables of selection
|
|
||||||
function! go#oracle#Freevars(selected)
|
|
||||||
" Freevars requires a selection
|
|
||||||
if a:selected == -1
|
|
||||||
echon "vim-go: " | echohl Statement | echon "GoFreevars requires a selection (range) of code "| echohl None
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
|
|
||||||
let out = s:RunOracle('freevars', a:selected, 0)
|
|
||||||
call s:loclistSecond(out)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Show send/receive corresponding to selected channel op
|
|
||||||
function! go#oracle#ChannelPeers(selected)
|
|
||||||
let out = s:RunOracle('peers', a:selected, 1)
|
|
||||||
call s:loclistSecond(out)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Show all refs to entity denoted by selected identifier
|
|
||||||
function! go#oracle#Referrers(selected)
|
|
||||||
let out = s:RunOracle('referrers', a:selected, 0)
|
|
||||||
call s:loclistSecond(out)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
|
||||||
"
|
|
||||||
@ -28,13 +28,13 @@ if len(s:goarch) == 0
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
function! go#package#Paths()
|
function! go#package#Paths() abort
|
||||||
let dirs = []
|
let dirs = []
|
||||||
|
|
||||||
if !exists("s:goroot")
|
if !exists("s:goroot")
|
||||||
if executable('go')
|
if executable('go')
|
||||||
let s:goroot = substitute(system('go env GOROOT'), '\n', '', 'g')
|
let s:goroot = go#util#env("goroot")
|
||||||
if v:shell_error
|
if go#util#ShellError() != 0
|
||||||
echomsg '''go env GOROOT'' failed'
|
echomsg '''go env GOROOT'' failed'
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
@ -46,7 +46,7 @@ function! go#package#Paths()
|
|||||||
let dirs += [s:goroot]
|
let dirs += [s:goroot]
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let workspaces = split($GOPATH, go#util#PathListSep())
|
let workspaces = split(go#path#Default(), go#util#PathListSep())
|
||||||
if workspaces != []
|
if workspaces != []
|
||||||
let dirs += workspaces
|
let dirs += workspaces
|
||||||
endif
|
endif
|
||||||
@ -54,31 +54,33 @@ function! go#package#Paths()
|
|||||||
return dirs
|
return dirs
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! go#package#ImportPath(arg)
|
" ImportPath returns the import path in the current directory it was executed
|
||||||
let path = fnamemodify(resolve(a:arg), ':p')
|
function! go#package#ImportPath() abort
|
||||||
let dirs = go#package#Paths()
|
let out = go#tool#ExecuteInDir("go list")
|
||||||
|
if go#util#ShellError() != 0
|
||||||
for dir in dirs
|
|
||||||
if len(dir) && match(path, dir) == 0
|
|
||||||
let workspace = dir
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
|
|
||||||
if !exists('workspace')
|
|
||||||
return -1
|
return -1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let srcdir = substitute(workspace . '/src/', '//', '/', '')
|
let import_path = split(out, '\n')[0]
|
||||||
return substitute(path, srcdir, '', '')
|
|
||||||
|
" go list returns '_CURRENTDIRECTORY' if the directory is not inside GOPATH.
|
||||||
|
" Check it and retun an error if that is the case
|
||||||
|
if import_path[0] ==# '_'
|
||||||
|
return -1
|
||||||
|
endif
|
||||||
|
|
||||||
|
return import_path
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! go#package#FromPath(arg)
|
|
||||||
|
function! go#package#FromPath(arg) abort
|
||||||
let path = fnamemodify(resolve(a:arg), ':p')
|
let path = fnamemodify(resolve(a:arg), ':p')
|
||||||
let dirs = go#package#Paths()
|
let dirs = go#package#Paths()
|
||||||
|
|
||||||
for dir in dirs
|
for dir in dirs
|
||||||
if len(dir) && match(path, dir) == 0
|
if len(dir) && match(path, dir) == 0
|
||||||
let workspace = dir
|
let workspace = dir
|
||||||
|
break
|
||||||
endif
|
endif
|
||||||
endfor
|
endfor
|
||||||
|
|
||||||
@ -86,17 +88,19 @@ function! go#package#FromPath(arg)
|
|||||||
return -1
|
return -1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
let path = substitute(path, '/*$', '', '')
|
||||||
|
let workspace = substitute(workspace . '/src/', '/+', '', '')
|
||||||
if isdirectory(path)
|
if isdirectory(path)
|
||||||
return substitute(path, workspace . 'src/', '', '')
|
return substitute(path, workspace, '', '')
|
||||||
else
|
else
|
||||||
return substitute(substitute(path, workspace . 'src/', '', ''),
|
return substitute(substitute(path, workspace, '', ''),
|
||||||
\ '/' . fnamemodify(path, ':t'), '', '')
|
\ '/' . fnamemodify(path, ':t'), '', '')
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! go#package#CompleteMembers(package, member)
|
function! go#package#CompleteMembers(package, member) abort
|
||||||
silent! let content = system('godoc ' . a:package)
|
silent! let content = go#util#System('godoc ' . a:package)
|
||||||
if v:shell_error || !len(content)
|
if go#util#ShellError() || !len(content)
|
||||||
return []
|
return []
|
||||||
endif
|
endif
|
||||||
let lines = filter(split(content, "\n"),"v:val !~ '^\\s\\+$'")
|
let lines = filter(split(content, "\n"),"v:val !~ '^\\s\\+$'")
|
||||||
@ -113,11 +117,11 @@ function! go#package#CompleteMembers(package, member)
|
|||||||
endtry
|
endtry
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! go#package#Complete(ArgLead, CmdLine, CursorPos)
|
function! go#package#Complete(ArgLead, CmdLine, CursorPos) abort
|
||||||
let words = split(a:CmdLine, '\s\+', 1)
|
let words = split(a:CmdLine, '\s\+', 1)
|
||||||
|
|
||||||
" do not complete package members for these commands
|
" do not complete package members for these commands
|
||||||
let neglect_commands = ["GoImportAs", "GoOracleScope"]
|
let neglect_commands = ["GoImportAs", "GoGuruScope"]
|
||||||
|
|
||||||
if len(words) > 2 && index(neglect_commands, words[0]) == -1
|
if len(words) > 2 && index(neglect_commands, words[0]) == -1
|
||||||
" Complete package members
|
" Complete package members
|
||||||
@ -157,4 +161,4 @@ function! go#package#Complete(ArgLead, CmdLine, CursorPos)
|
|||||||
return sort(keys(ret))
|
return sort(keys(ret))
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" vim:sw=4:et
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
@ -4,13 +4,18 @@
|
|||||||
" :GoPath is used
|
" :GoPath is used
|
||||||
let s:initial_go_path = ""
|
let s:initial_go_path = ""
|
||||||
|
|
||||||
" GoPath sets or returns the current GOPATH. If no arguments are passed it
|
" GoPath sets or echos the current GOPATH. If no arguments are passed it
|
||||||
" echoes the current GOPATH, if an argument is passed it replaces the current
|
" echoes the current GOPATH, if an argument is passed it replaces the current
|
||||||
" GOPATH with it. If two double quotes are passed (the empty string in go),
|
" GOPATH with it. If two double quotes are passed (the empty string in go),
|
||||||
" it'll clear the GOPATH and will restore to the initial GOPATH.
|
" it'll clear the GOPATH and will restore to the initial GOPATH.
|
||||||
function! go#path#GoPath(...)
|
function! go#path#GoPath(...) abort
|
||||||
|
" no argument, show GOPATH
|
||||||
|
if len(a:000) == 0
|
||||||
|
echo go#path#Default()
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
" we have an argument, replace GOPATH
|
" we have an argument, replace GOPATH
|
||||||
if len(a:000)
|
|
||||||
" clears the current manually set GOPATH and restores it to the
|
" clears the current manually set GOPATH and restores it to the
|
||||||
" initial GOPATH, which was set when Vim was started.
|
" initial GOPATH, which was set when Vim was started.
|
||||||
if len(a:000) == 1 && a:1 == '""'
|
if len(a:000) == 1 && a:1 == '""'
|
||||||
@ -26,29 +31,24 @@ function! go#path#GoPath(...)
|
|||||||
echon "vim-go: " | echohl Function | echon "GOPATH changed to ". a:1 | echohl None
|
echon "vim-go: " | echohl Function | echon "GOPATH changed to ". a:1 | echohl None
|
||||||
let s:initial_go_path = $GOPATH
|
let s:initial_go_path = $GOPATH
|
||||||
let $GOPATH = a:1
|
let $GOPATH = a:1
|
||||||
return
|
|
||||||
endif
|
|
||||||
|
|
||||||
echo go#path#Detect()
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Default returns the default GOPATH. If there is a single GOPATH it returns
|
" Default returns the default GOPATH. If GOPATH is not set, it uses the
|
||||||
" it. For multiple GOPATHS separated with a the OS specific separator, only
|
" default GOPATH set starting with Go 1.8. This GOPATH can be retrieved via
|
||||||
" the first one is returned
|
" 'go env GOPATH'
|
||||||
function! go#path#Default()
|
function! go#path#Default() abort
|
||||||
let go_paths = split($GOPATH, go#util#PathListSep())
|
if $GOPATH == ""
|
||||||
|
" use default GOPATH via go env
|
||||||
if len(go_paths) == 1
|
return go#util#env("gopath")
|
||||||
return $GOPATH
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
return go_paths[0]
|
return $GOPATH
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" HasPath checks whether the given path exists in GOPATH environment variable
|
" HasPath checks whether the given path exists in GOPATH environment variable
|
||||||
" or not
|
" or not
|
||||||
function! go#path#HasPath(path)
|
function! go#path#HasPath(path) abort
|
||||||
let go_paths = split($GOPATH, go#util#PathListSep())
|
let go_paths = split(go#path#Default(), go#util#PathListSep())
|
||||||
let last_char = strlen(a:path) - 1
|
let last_char = strlen(a:path) - 1
|
||||||
|
|
||||||
" check cases of '/foo/bar/' and '/foo/bar'
|
" check cases of '/foo/bar/' and '/foo/bar'
|
||||||
@ -69,13 +69,8 @@ endfunction
|
|||||||
" Godeps, GB, it will modify the GOPATH so those directories take precedence
|
" Godeps, GB, it will modify the GOPATH so those directories take precedence
|
||||||
" over the current GOPATH. It also detects diretories whose are outside
|
" over the current GOPATH. It also detects diretories whose are outside
|
||||||
" GOPATH.
|
" GOPATH.
|
||||||
function! go#path#Detect()
|
function! go#path#Detect() abort
|
||||||
let gopath = $GOPATH
|
let gopath = go#path#Default()
|
||||||
|
|
||||||
" don't lookup for godeps if autodetect is disabled.
|
|
||||||
if !get(g:, "go_autodetect_gopath", 1)
|
|
||||||
return gopath
|
|
||||||
endif
|
|
||||||
|
|
||||||
let current_dir = fnameescape(expand('%:p:h'))
|
let current_dir = fnameescape(expand('%:p:h'))
|
||||||
|
|
||||||
@ -83,8 +78,16 @@ function! go#path#Detect()
|
|||||||
" fetched from a customizable list. The user should define any new package
|
" fetched from a customizable list. The user should define any new package
|
||||||
" management tool by it's own.
|
" management tool by it's own.
|
||||||
|
|
||||||
" src folder outside $GOPATH
|
" src folders outside $GOPATH
|
||||||
let src_root = finddir("src", current_dir .";")
|
let src_roots = finddir("src", current_dir .";", -1)
|
||||||
|
|
||||||
|
" for cases like GOPATH/src/foo/src/bar, pick up GOPATH/src instead of
|
||||||
|
" GOPATH/src/foo/src
|
||||||
|
let src_root = ""
|
||||||
|
if len(src_roots) > 0
|
||||||
|
let src_root = src_roots[-1]
|
||||||
|
endif
|
||||||
|
|
||||||
if !empty(src_root)
|
if !empty(src_root)
|
||||||
let src_path = fnamemodify(src_root, ':p:h:h') . go#util#PathSep()
|
let src_path = fnamemodify(src_root, ':p:h:h') . go#util#PathSep()
|
||||||
|
|
||||||
@ -110,24 +113,28 @@ function! go#path#Detect()
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
" Fix up the case where initial $GOPATH is empty,
|
||||||
|
" and we end up with a trailing :
|
||||||
|
let gopath = substitute(gopath, ":$", "", "")
|
||||||
return gopath
|
return gopath
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
" BinPath returns the binary path of installed go tools.
|
" BinPath returns the binary path of installed go tools.
|
||||||
function! go#path#BinPath()
|
function! go#path#BinPath() abort
|
||||||
let bin_path = ""
|
let bin_path = ""
|
||||||
|
|
||||||
" check if our global custom path is set, if not check if $GOBIN is set so
|
" check if our global custom path is set, if not check if $GOBIN is set so
|
||||||
" we can use it, otherwise use $GOPATH + '/bin'
|
" we can use it, otherwise use default GOPATH
|
||||||
if exists("g:go_bin_path")
|
if exists("g:go_bin_path")
|
||||||
let bin_path = g:go_bin_path
|
let bin_path = g:go_bin_path
|
||||||
elseif $GOBIN != ""
|
elseif $GOBIN != ""
|
||||||
let bin_path = $GOBIN
|
let bin_path = $GOBIN
|
||||||
elseif $GOPATH != ""
|
|
||||||
let bin_path = expand(go#path#Default() . "/bin/")
|
|
||||||
else
|
else
|
||||||
" could not find anything
|
let go_paths = split(go#path#Default(), go#util#PathListSep())
|
||||||
|
if len(go_paths) == 0
|
||||||
|
return "" "nothing found
|
||||||
|
endif
|
||||||
|
let bin_path = expand(go_paths[0] . "/bin/")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
return bin_path
|
return bin_path
|
||||||
@ -135,32 +142,39 @@ endfunction
|
|||||||
|
|
||||||
" CheckBinPath checks whether the given binary exists or not and returns the
|
" CheckBinPath checks whether the given binary exists or not and returns the
|
||||||
" path of the binary. It returns an empty string doesn't exists.
|
" path of the binary. It returns an empty string doesn't exists.
|
||||||
function! go#path#CheckBinPath(binpath)
|
function! go#path#CheckBinPath(binpath) abort
|
||||||
" remove whitespaces if user applied something like 'goimports '
|
" remove whitespaces if user applied something like 'goimports '
|
||||||
let binpath = substitute(a:binpath, '^\s*\(.\{-}\)\s*$', '\1', '')
|
let binpath = substitute(a:binpath, '^\s*\(.\{-}\)\s*$', '\1', '')
|
||||||
|
" save off original path
|
||||||
|
let old_path = $PATH
|
||||||
|
|
||||||
|
" check if we have an appropriate bin_path
|
||||||
|
let go_bin_path = go#path#BinPath()
|
||||||
|
if !empty(go_bin_path)
|
||||||
|
" append our GOBIN and GOPATH paths and be sure they can be found there...
|
||||||
|
" let us search in our GOBIN and GOPATH paths
|
||||||
|
let $PATH = go_bin_path . go#util#PathListSep() . $PATH
|
||||||
|
endif
|
||||||
|
|
||||||
" if it's in PATH just return it
|
" if it's in PATH just return it
|
||||||
if executable(binpath)
|
if executable(binpath)
|
||||||
|
if exists('*exepath')
|
||||||
|
let binpath = exepath(binpath)
|
||||||
|
endif
|
||||||
|
let $PATH = old_path
|
||||||
|
|
||||||
|
if go#util#IsUsingCygwinShell() == 1
|
||||||
|
return go#path#CygwinPath(binpath)
|
||||||
|
endif
|
||||||
|
|
||||||
return binpath
|
return binpath
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" just get the basename
|
" just get the basename
|
||||||
let basename = fnamemodify(binpath, ":t")
|
let basename = fnamemodify(binpath, ":t")
|
||||||
|
|
||||||
" check if we have an appropriate bin_path
|
|
||||||
let go_bin_path = go#path#BinPath()
|
|
||||||
if empty(go_bin_path)
|
|
||||||
echo "vim-go: could not find '" . basename . "'. Run :GoInstallBinaries to fix it."
|
|
||||||
return ""
|
|
||||||
endif
|
|
||||||
|
|
||||||
" append our GOBIN and GOPATH paths and be sure they can be found there...
|
|
||||||
" let us search in our GOBIN and GOPATH paths
|
|
||||||
let old_path = $PATH
|
|
||||||
let $PATH = $PATH . go#util#PathListSep() .go_bin_path
|
|
||||||
|
|
||||||
if !executable(basename)
|
if !executable(basename)
|
||||||
echo "vim-go: could not find '" . basename . "'. Run :GoInstallBinaries to fix it."
|
call go#util#EchoError(printf("could not find '%s'. Run :GoInstallBinaries to fix it", basename))
|
||||||
|
|
||||||
" restore back!
|
" restore back!
|
||||||
let $PATH = old_path
|
let $PATH = old_path
|
||||||
return ""
|
return ""
|
||||||
@ -168,7 +182,15 @@ function! go#path#CheckBinPath(binpath)
|
|||||||
|
|
||||||
let $PATH = old_path
|
let $PATH = old_path
|
||||||
|
|
||||||
|
if go#util#IsUsingCygwinShell() == 1
|
||||||
|
return go#path#CygwinPath(a:binpath)
|
||||||
|
endif
|
||||||
|
|
||||||
return go_bin_path . go#util#PathSep() . basename
|
return go_bin_path . go#util#PathSep() . basename
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
function! go#path#CygwinPath(path)
|
||||||
|
return substitute(a:path, '\\', '/', "g")
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
@ -3,7 +3,7 @@ if !exists("g:go_play_open_browser")
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
function! go#play#Share(count, line1, line2)
|
function! go#play#Share(count, line1, line2) abort
|
||||||
if !executable('curl')
|
if !executable('curl')
|
||||||
echohl ErrorMsg | echomsg "vim-go: require 'curl' command" | echohl None
|
echohl ErrorMsg | echomsg "vim-go: require 'curl' command" | echohl None
|
||||||
return
|
return
|
||||||
@ -13,14 +13,14 @@ function! go#play#Share(count, line1, line2)
|
|||||||
let share_file = tempname()
|
let share_file = tempname()
|
||||||
call writefile(split(content, "\n"), share_file, "b")
|
call writefile(split(content, "\n"), share_file, "b")
|
||||||
|
|
||||||
let command = "curl -s -X POST http://play.golang.org/share --data-binary '@".share_file."'"
|
let command = "curl -s -X POST https://play.golang.org/share --data-binary '@".share_file."'"
|
||||||
let snippet_id = system(command)
|
let snippet_id = go#util#System(command)
|
||||||
|
|
||||||
" we can remove the temp file because it's now posted.
|
" we can remove the temp file because it's now posted.
|
||||||
call delete(share_file)
|
call delete(share_file)
|
||||||
|
|
||||||
if v:shell_error
|
if go#util#ShellError() != 0
|
||||||
echo 'A error has occured. Run this command to see what the problem is:'
|
echo 'A error has occurred. Run this command to see what the problem is:'
|
||||||
echo command
|
echo command
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
@ -42,7 +42,7 @@ function! go#play#Share(count, line1, line2)
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! s:get_visual_content()
|
function! s:get_visual_content() abort
|
||||||
let save_regcont = @"
|
let save_regcont = @"
|
||||||
let save_regtype = getregtype('"')
|
let save_regtype = getregtype('"')
|
||||||
silent! normal! gvy
|
silent! normal! gvy
|
||||||
@ -55,7 +55,7 @@ endfunction
|
|||||||
" http://stackoverflow.com/questions/1533565/how-to-get-visually-selected-text-in-vimscript
|
" http://stackoverflow.com/questions/1533565/how-to-get-visually-selected-text-in-vimscript
|
||||||
" another function that returns the content of visual selection, it's not used
|
" another function that returns the content of visual selection, it's not used
|
||||||
" but might be useful in the future
|
" but might be useful in the future
|
||||||
function! s:get_visual_selection()
|
function! s:get_visual_selection() abort
|
||||||
let [lnum1, col1] = getpos("'<")[1:2]
|
let [lnum1, col1] = getpos("'<")[1:2]
|
||||||
let [lnum2, col2] = getpos("'>")[1:2]
|
let [lnum2, col2] = getpos("'>")[1:2]
|
||||||
|
|
||||||
@ -70,25 +70,4 @@ function! s:get_visual_selection()
|
|||||||
return join(lines, "\n")
|
return join(lines, "\n")
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" following two functions are from: https://github.com/mattn/gist-vim
|
" vim: sw=2 ts=2 et
|
||||||
" thanks @mattn
|
|
||||||
function! s:get_browser_command()
|
|
||||||
let go_play_browser_command = get(g:, 'go_play_browser_command', '')
|
|
||||||
if go_play_browser_command == ''
|
|
||||||
if has('win32') || has('win64')
|
|
||||||
let go_play_browser_command = '!start rundll32 url.dll,FileProtocolHandler %URL%'
|
|
||||||
elseif has('mac') || has('macunix') || has('gui_macvim') || system('uname') =~? '^darwin'
|
|
||||||
let go_play_browser_command = 'open %URL%'
|
|
||||||
elseif executable('xdg-open')
|
|
||||||
let go_play_browser_command = 'xdg-open %URL%'
|
|
||||||
elseif executable('firefox')
|
|
||||||
let go_play_browser_command = 'firefox %URL% &'
|
|
||||||
else
|
|
||||||
let go_play_browser_command = ''
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
return go_play_browser_command
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
|
||||||
|
|||||||
@ -2,29 +2,37 @@ if !exists("g:go_gorename_bin")
|
|||||||
let g:go_gorename_bin = "gorename"
|
let g:go_gorename_bin = "gorename"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if !exists("g:go_gorename_prefill")
|
" Set the default value. A value of "1" is a shortcut for this, for
|
||||||
let g:go_gorename_prefill = 1
|
" compatibility reasons.
|
||||||
endif
|
function! s:default() abort
|
||||||
|
if !exists("g:go_gorename_prefill") || g:go_gorename_prefill == 1
|
||||||
|
let g:go_gorename_prefill = 'expand("<cword>") =~# "^[A-Z]"' .
|
||||||
|
\ '? go#util#pascalcase(expand("<cword>"))' .
|
||||||
|
\ ': go#util#camelcase(expand("<cword>"))'
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
call s:default()
|
||||||
|
|
||||||
function! go#rename#Rename(bang, ...)
|
function! go#rename#Rename(bang, ...) abort
|
||||||
let to = ""
|
call s:default()
|
||||||
|
|
||||||
|
let to_identifier = ""
|
||||||
if a:0 == 0
|
if a:0 == 0
|
||||||
let from = expand("<cword>")
|
let ask = printf("vim-go: rename '%s' to: ", expand("<cword>"))
|
||||||
let ask = printf("vim-go: rename '%s' to: ", from)
|
if g:go_gorename_prefill != ''
|
||||||
if g:go_gorename_prefill
|
let to_identifier = input(ask, eval(g:go_gorename_prefill))
|
||||||
let to = input(ask, from)
|
|
||||||
else
|
else
|
||||||
let to = input(ask)
|
let to_identifier = input(ask)
|
||||||
endif
|
endif
|
||||||
redraw!
|
redraw!
|
||||||
if empty(to)
|
if empty(to_identifier)
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
let to = a:1
|
let to_identifier = a:1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
"return with a warning if the bin doesn't exist
|
" return with a warning if the bin doesn't exist
|
||||||
let bin_path = go#path#CheckBinPath(g:go_gorename_bin)
|
let bin_path = go#path#CheckBinPath(g:go_gorename_bin)
|
||||||
if empty(bin_path)
|
if empty(bin_path)
|
||||||
return
|
return
|
||||||
@ -32,31 +40,106 @@ function! go#rename#Rename(bang, ...)
|
|||||||
|
|
||||||
let fname = expand('%:p')
|
let fname = expand('%:p')
|
||||||
let pos = go#util#OffsetCursor()
|
let pos = go#util#OffsetCursor()
|
||||||
let cmd = printf('%s -offset %s -to %s', shellescape(bin_path), shellescape(printf('%s:#%d', fname, pos)), shellescape(to))
|
let offset = printf('%s:#%d', fname, pos)
|
||||||
|
|
||||||
let out = go#tool#ExecuteInDir(cmd)
|
" no need to escape for job call
|
||||||
|
let bin_path = go#util#has_job() ? bin_path : shellescape(bin_path)
|
||||||
|
let offset = go#util#has_job() ? offset : shellescape(offset)
|
||||||
|
let to_identifier = go#util#has_job() ? to_identifier : shellescape(to_identifier)
|
||||||
|
|
||||||
" strip out newline on the end that gorename puts. If we don't remove, it
|
let cmd = [bin_path, "-offset", offset, "-to", to_identifier]
|
||||||
" will trigger the 'Hit ENTER to continue' prompt
|
|
||||||
let clean = split(out, '\n')
|
|
||||||
|
|
||||||
let l:listtype = "quickfix"
|
" check for any tags
|
||||||
if v:shell_error
|
if exists('g:go_build_tags')
|
||||||
let errors = go#tool#ParseErrors(split(out, '\n'))
|
let tags = get(g:, 'go_build_tags')
|
||||||
call go#list#Populate(l:listtype, errors)
|
call extend(cmd, ["-tags", tags])
|
||||||
|
endif
|
||||||
|
|
||||||
|
if go#util#has_job()
|
||||||
|
call go#util#EchoProgress(printf("renaming to '%s' ...", to_identifier))
|
||||||
|
call s:rename_job({
|
||||||
|
\ 'cmd': cmd,
|
||||||
|
\ 'bang': a:bang,
|
||||||
|
\})
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let command = join(cmd, " ")
|
||||||
|
let out = go#tool#ExecuteInDir(command)
|
||||||
|
|
||||||
|
let splitted = split(out, '\n')
|
||||||
|
call s:parse_errors(go#util#ShellError(), a:bang, splitted)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function s:rename_job(args)
|
||||||
|
let messages = []
|
||||||
|
function! s:callback(chan, msg) closure
|
||||||
|
call add(messages, a:msg)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
let status_dir = expand('%:p:h')
|
||||||
|
|
||||||
|
function! s:exit_cb(job, exitval) closure
|
||||||
|
let status = {
|
||||||
|
\ 'desc': 'last status',
|
||||||
|
\ 'type': "gorename",
|
||||||
|
\ 'state': "finished",
|
||||||
|
\ }
|
||||||
|
|
||||||
|
if a:exitval
|
||||||
|
let status.state = "failed"
|
||||||
|
endif
|
||||||
|
|
||||||
|
call go#statusline#Update(status_dir, status)
|
||||||
|
|
||||||
|
call s:parse_errors(a:exitval, a:args.bang, messages)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
let start_options = {
|
||||||
|
\ 'callback': funcref("s:callback"),
|
||||||
|
\ 'exit_cb': funcref("s:exit_cb"),
|
||||||
|
\ }
|
||||||
|
|
||||||
|
call go#statusline#Update(status_dir, {
|
||||||
|
\ 'desc': "current status",
|
||||||
|
\ 'type': "gorename",
|
||||||
|
\ 'state': "started",
|
||||||
|
\})
|
||||||
|
|
||||||
|
call job_start(a:args.cmd, start_options)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function s:parse_errors(exit_val, bang, out)
|
||||||
|
" reload all files to reflect the new changes. We explicitly call
|
||||||
|
" checktime to trigger a reload of all files. See
|
||||||
|
" http://www.mail-archive.com/vim@vim.org/msg05900.html for more info
|
||||||
|
" about the autoread bug
|
||||||
|
let current_autoread = &autoread
|
||||||
|
set autoread
|
||||||
|
silent! checktime
|
||||||
|
let &autoread = current_autoread
|
||||||
|
|
||||||
|
let l:listtype = go#list#Type("GoRename")
|
||||||
|
if a:exit_val != 0
|
||||||
|
call go#util#EchoError("FAILED")
|
||||||
|
let errors = go#tool#ParseErrors(a:out)
|
||||||
|
call go#list#Populate(l:listtype, errors, 'Rename')
|
||||||
call go#list#Window(l:listtype, len(errors))
|
call go#list#Window(l:listtype, len(errors))
|
||||||
if !empty(errors) && !a:bang
|
if !empty(errors) && !a:bang
|
||||||
call go#list#JumpToFirst(l:listtype)
|
call go#list#JumpToFirst(l:listtype)
|
||||||
elseif empty(errors)
|
elseif empty(errors)
|
||||||
" failed to parse errors, output the original content
|
" failed to parse errors, output the original content
|
||||||
call go#util#EchoError(out)
|
call go#util#EchoError(a:out)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
return
|
return
|
||||||
else
|
endif
|
||||||
|
|
||||||
|
" strip out newline on the end that gorename puts. If we don't remove, it
|
||||||
|
" will trigger the 'Hit ENTER to continue' prompt
|
||||||
call go#list#Clean(l:listtype)
|
call go#list#Clean(l:listtype)
|
||||||
call go#list#Window(l:listtype)
|
call go#list#Window(l:listtype)
|
||||||
redraw | echon "vim-go: " | echohl Function | echon clean[0] | echohl None
|
call go#util#EchoSuccess(a:out[0])
|
||||||
endif
|
|
||||||
|
|
||||||
" refresh the buffer so we can see the new content
|
" refresh the buffer so we can see the new content
|
||||||
" TODO(arslan): also find all other buffers and refresh them too. For this
|
" TODO(arslan): also find all other buffers and refresh them too. For this
|
||||||
@ -65,5 +148,13 @@ function! go#rename#Rename(bang, ...)
|
|||||||
silent execute ":e"
|
silent execute ":e"
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
" Commandline completion: original, unexported camelCase, and exported
|
||||||
"
|
" CamelCase.
|
||||||
|
function! go#rename#Complete(lead, cmdline, cursor)
|
||||||
|
let l:word = expand('<cword>')
|
||||||
|
return filter(uniq(sort(
|
||||||
|
\ [l:word, go#util#camelcase(l:word), go#util#pascalcase(l:word)])),
|
||||||
|
\ 'strpart(v:val, 0, len(a:lead)) == a:lead')
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
112
autoload/go/statusline.vim
Normal file
112
autoload/go/statusline.vim
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
" Statusline
|
||||||
|
""""""""""""""""""""""""""""""""
|
||||||
|
|
||||||
|
" s:statuses is a global reference to all statuses. It stores the statuses per
|
||||||
|
" import paths (map[string]status), where each status is unique per its
|
||||||
|
" type. Current status dict is in form:
|
||||||
|
" {
|
||||||
|
" 'desc' : 'Job description',
|
||||||
|
" 'state' : 'Job state, such as success, failure, etc..',
|
||||||
|
" 'type' : 'Job type, such as build, test, etc..'
|
||||||
|
" 'created_at' : 'Time it was created as seconds since 1st Jan 1970'
|
||||||
|
" }
|
||||||
|
let s:statuses = {}
|
||||||
|
|
||||||
|
" timer_id for cleaner
|
||||||
|
let s:timer_id = 0
|
||||||
|
|
||||||
|
" last_status stores the last generated text per status
|
||||||
|
let s:last_status = ""
|
||||||
|
|
||||||
|
" Show returns the current status of the job for 20 seconds (configurable). It
|
||||||
|
" displays it in form of 'desc: [type|state]' if there is any state available,
|
||||||
|
" if not it returns an empty string. This function should be plugged directly
|
||||||
|
" into the statusline.
|
||||||
|
function! go#statusline#Show() abort
|
||||||
|
" lazy initialiation of the cleaner
|
||||||
|
if !s:timer_id
|
||||||
|
" clean every 60 seconds all statuses
|
||||||
|
let interval = get(g:, 'go_statusline_duration', 60000)
|
||||||
|
let s:timer_id = timer_start(interval, function('go#statusline#Clear'), {'repeat': -1})
|
||||||
|
endif
|
||||||
|
|
||||||
|
" nothing to show
|
||||||
|
if empty(s:statuses)
|
||||||
|
return ''
|
||||||
|
endif
|
||||||
|
|
||||||
|
let status_dir = expand('%:p:h')
|
||||||
|
|
||||||
|
if !has_key(s:statuses, status_dir)
|
||||||
|
return ''
|
||||||
|
endif
|
||||||
|
|
||||||
|
let status = s:statuses[status_dir]
|
||||||
|
if !has_key(status, 'desc') || !has_key(status, 'state') || !has_key(status, 'type')
|
||||||
|
return ''
|
||||||
|
endif
|
||||||
|
|
||||||
|
let status_text = printf("[%s|%s]", status.type, status.state)
|
||||||
|
if empty(status_text)
|
||||||
|
return ''
|
||||||
|
endif
|
||||||
|
|
||||||
|
" only update highlight if status has changed.
|
||||||
|
if status_text != s:last_status
|
||||||
|
if status.state =~ "success" || status.state =~ "finished" || status.state =~ "pass"
|
||||||
|
hi goStatusLineColor cterm=bold ctermbg=76 ctermfg=22
|
||||||
|
elseif status.state =~ "started" || status.state =~ "analysing" || status.state =~ "compiling"
|
||||||
|
hi goStatusLineColor cterm=bold ctermbg=208 ctermfg=88
|
||||||
|
elseif status.state =~ "failed"
|
||||||
|
hi goStatusLineColor cterm=bold ctermbg=196 ctermfg=52
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
let s:last_status = status_text
|
||||||
|
return status_text
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Update updates (adds) the statusline for the given status_dir with the
|
||||||
|
" given status dict. It overrides any previously set status.
|
||||||
|
function! go#statusline#Update(status_dir, status) abort
|
||||||
|
let a:status.created_at = reltime()
|
||||||
|
let s:statuses[a:status_dir] = a:status
|
||||||
|
|
||||||
|
" force to update the statusline, otherwise the user needs to move the
|
||||||
|
" cursor
|
||||||
|
exe 'let &ro = &ro'
|
||||||
|
|
||||||
|
" before we stop the timer, check if we have any previous jobs to be cleaned
|
||||||
|
" up. Otherwise every job will reset the timer when this function is called
|
||||||
|
" and thus old jobs will never be cleaned
|
||||||
|
call go#statusline#Clear(0)
|
||||||
|
|
||||||
|
" also reset the timer, so the user has time to see it in the statusline.
|
||||||
|
" Setting the timer_id to 0 will trigger a new cleaner routine.
|
||||||
|
call timer_stop(s:timer_id)
|
||||||
|
let s:timer_id = 0
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Clear clears all currently stored statusline data. The timer_id argument is
|
||||||
|
" just a placeholder so we can pass it to a timer_start() function if needed.
|
||||||
|
function! go#statusline#Clear(timer_id) abort
|
||||||
|
for [status_dir, status] in items(s:statuses)
|
||||||
|
let elapsed_time = reltimestr(reltime(status.created_at))
|
||||||
|
" strip whitespace
|
||||||
|
let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '')
|
||||||
|
|
||||||
|
if str2nr(elapsed_time) > 10
|
||||||
|
call remove(s:statuses, status_dir)
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
|
||||||
|
if len(s:statuses) == 0
|
||||||
|
let s:statuses = {}
|
||||||
|
endif
|
||||||
|
|
||||||
|
" force to update the statusline, otherwise the user needs to move the
|
||||||
|
" cursor
|
||||||
|
exe 'let &ro = &ro'
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
214
autoload/go/tags.vim
Normal file
214
autoload/go/tags.vim
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
" mapped to :GoAddTags
|
||||||
|
function! go#tags#Add(start, end, count, ...) abort
|
||||||
|
let fname = fnamemodify(expand("%"), ':p:gs?\\?/?')
|
||||||
|
let offset = 0
|
||||||
|
if a:count == -1
|
||||||
|
let offset = go#util#OffsetCursor()
|
||||||
|
endif
|
||||||
|
|
||||||
|
let test_mode = 0
|
||||||
|
call call("go#tags#run", [a:start, a:end, offset, "add", fname, test_mode] + a:000)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" mapped to :GoRemoveTags
|
||||||
|
function! go#tags#Remove(start, end, count, ...) abort
|
||||||
|
let fname = fnamemodify(expand("%"), ':p:gs?\\?/?')
|
||||||
|
let offset = 0
|
||||||
|
if a:count == -1
|
||||||
|
let offset = go#util#OffsetCursor()
|
||||||
|
endif
|
||||||
|
|
||||||
|
let test_mode = 0
|
||||||
|
call call("go#tags#run", [a:start, a:end, offset, "remove", fname, test_mode] + a:000)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" run runs gomodifytag. This is an internal test so we can test it
|
||||||
|
function! go#tags#run(start, end, offset, mode, fname, test_mode, ...) abort
|
||||||
|
" do not split this into multiple lines, somehow tests fail in that case
|
||||||
|
let args = {'mode': a:mode,'start': a:start,'end': a:end,'offset': a:offset,'fname': a:fname,'cmd_args': a:000}
|
||||||
|
|
||||||
|
if &modified
|
||||||
|
let args["modified"] = 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
let result = s:create_cmd(args)
|
||||||
|
if has_key(result, 'err')
|
||||||
|
call go#util#EchoError(result.err)
|
||||||
|
return -1
|
||||||
|
endif
|
||||||
|
|
||||||
|
let command = join(result.cmd, " ")
|
||||||
|
|
||||||
|
if &modified
|
||||||
|
let filename = expand("%:p:gs!\\!/!")
|
||||||
|
let content = join(go#util#GetLines(), "\n")
|
||||||
|
let in = filename . "\n" . strlen(content) . "\n" . content
|
||||||
|
let out = go#util#System(command, in)
|
||||||
|
else
|
||||||
|
let out = go#util#System(command)
|
||||||
|
endif
|
||||||
|
|
||||||
|
if go#util#ShellError() != 0
|
||||||
|
call go#util#EchoError(out)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
if a:test_mode
|
||||||
|
exe 'edit ' . a:fname
|
||||||
|
endif
|
||||||
|
|
||||||
|
call s:write_out(out)
|
||||||
|
|
||||||
|
if a:test_mode
|
||||||
|
exe 'write! ' . a:fname
|
||||||
|
endif
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
|
||||||
|
" write_out writes back the given output to the current buffer
|
||||||
|
func s:write_out(out) abort
|
||||||
|
" not a json output
|
||||||
|
if a:out[0] !=# '{'
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
" nothing to do
|
||||||
|
if empty(a:out) || type(a:out) != type("")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let result = json_decode(a:out)
|
||||||
|
if type(result) != type({})
|
||||||
|
call go#util#EchoError(printf("malformed output from gomodifytags: %s", a:out))
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let lines = result['lines']
|
||||||
|
let start_line = result['start']
|
||||||
|
let end_line = result['end']
|
||||||
|
|
||||||
|
let index = 0
|
||||||
|
for line in range(start_line, end_line)
|
||||||
|
call setline(line, lines[index])
|
||||||
|
let index += 1
|
||||||
|
endfor
|
||||||
|
|
||||||
|
if has_key(result, 'errors')
|
||||||
|
let l:winnr = winnr()
|
||||||
|
let l:listtype = go#list#Type("GoModifyTags")
|
||||||
|
call go#list#ParseFormat(l:listtype, "%f:%l:%c:%m", result['errors'], "gomodifytags")
|
||||||
|
call go#list#Window(l:listtype, len(result['errors']))
|
||||||
|
|
||||||
|
"prevent jumping to quickfix list
|
||||||
|
exe l:winnr . "wincmd w"
|
||||||
|
endif
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
|
||||||
|
" create_cmd returns a dict that contains the command to execute gomodifytags
|
||||||
|
func s:create_cmd(args) abort
|
||||||
|
if !exists("*json_decode")
|
||||||
|
return {'err': "requires 'json_decode'. Update your Vim/Neovim version."}
|
||||||
|
endif
|
||||||
|
|
||||||
|
let bin_path = go#path#CheckBinPath('gomodifytags')
|
||||||
|
if empty(bin_path)
|
||||||
|
return {'err': "gomodifytags does not exist"}
|
||||||
|
endif
|
||||||
|
let bin_path = go#util#Shellescape(bin_path)
|
||||||
|
|
||||||
|
let l:start = a:args.start
|
||||||
|
let l:end = a:args.end
|
||||||
|
let l:offset = a:args.offset
|
||||||
|
let l:mode = a:args.mode
|
||||||
|
let l:cmd_args = a:args.cmd_args
|
||||||
|
let l:modifytags_transform = get(g:, 'go_addtags_transform', "snakecase")
|
||||||
|
|
||||||
|
" start constructing the command
|
||||||
|
let cmd = [bin_path]
|
||||||
|
call extend(cmd, ["-format", "json"])
|
||||||
|
call extend(cmd, ["-file", go#util#Shellescape(a:args.fname)])
|
||||||
|
call extend(cmd, ["-transform", l:modifytags_transform])
|
||||||
|
|
||||||
|
if has_key(a:args, "modified")
|
||||||
|
call add(cmd, "-modified")
|
||||||
|
endif
|
||||||
|
|
||||||
|
if l:offset != 0
|
||||||
|
call extend(cmd, ["-offset", l:offset])
|
||||||
|
else
|
||||||
|
let range = printf("%d,%d", l:start, l:end)
|
||||||
|
call extend(cmd, ["-line", range])
|
||||||
|
endif
|
||||||
|
|
||||||
|
if l:mode == "add"
|
||||||
|
let l:tags = []
|
||||||
|
let l:options = []
|
||||||
|
|
||||||
|
if !empty(l:cmd_args)
|
||||||
|
for item in l:cmd_args
|
||||||
|
let splitted = split(item, ",")
|
||||||
|
|
||||||
|
" tag only
|
||||||
|
if len(splitted) == 1
|
||||||
|
call add(l:tags, splitted[0])
|
||||||
|
endif
|
||||||
|
|
||||||
|
" options only
|
||||||
|
if len(splitted) == 2
|
||||||
|
call add(l:tags, splitted[0])
|
||||||
|
call add(l:options, printf("%s=%s", splitted[0], splitted[1]))
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
endif
|
||||||
|
|
||||||
|
" construct options
|
||||||
|
if !empty(l:options)
|
||||||
|
call extend(cmd, ["-add-options", join(l:options, ",")])
|
||||||
|
else
|
||||||
|
" default value
|
||||||
|
if empty(l:tags)
|
||||||
|
let l:tags = ["json"]
|
||||||
|
endif
|
||||||
|
|
||||||
|
" construct tags
|
||||||
|
call extend(cmd, ["-add-tags", join(l:tags, ",")])
|
||||||
|
endif
|
||||||
|
elseif l:mode == "remove"
|
||||||
|
if empty(l:cmd_args)
|
||||||
|
call add(cmd, "-clear-tags")
|
||||||
|
else
|
||||||
|
let l:tags = []
|
||||||
|
let l:options = []
|
||||||
|
for item in l:cmd_args
|
||||||
|
let splitted = split(item, ",")
|
||||||
|
|
||||||
|
" tag only
|
||||||
|
if len(splitted) == 1
|
||||||
|
call add(l:tags, splitted[0])
|
||||||
|
endif
|
||||||
|
|
||||||
|
" options only
|
||||||
|
if len(splitted) == 2
|
||||||
|
call add(l:options, printf("%s=%s", splitted[0], splitted[1]))
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
|
||||||
|
" construct tags
|
||||||
|
if !empty(l:tags)
|
||||||
|
call extend(cmd, ["-remove-tags", join(l:tags, ",")])
|
||||||
|
endif
|
||||||
|
|
||||||
|
" construct options
|
||||||
|
if !empty(l:options)
|
||||||
|
call extend(cmd, ["-remove-options", join(l:options, ",")])
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
return {'err': printf("unknown mode: %s", l:mode)}
|
||||||
|
endif
|
||||||
|
|
||||||
|
return {'cmd': cmd}
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
22
autoload/go/tags_test.vim
Normal file
22
autoload/go/tags_test.vim
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
func! Test_add_tags() abort
|
||||||
|
try
|
||||||
|
let l:tmp = gotest#load_fixture('tags/add_all_input.go')
|
||||||
|
silent call go#tags#run(0, 0, 40, "add", bufname(''), 1)
|
||||||
|
call gotest#assert_fixture('tags/add_all_golden.go')
|
||||||
|
finally
|
||||||
|
call delete(l:tmp, 'rf')
|
||||||
|
endtry
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
|
||||||
|
func! Test_remove_tags() abort
|
||||||
|
try
|
||||||
|
let l:tmp = gotest#load_fixture('tags/remove_all_input.go')
|
||||||
|
silent call go#tags#run(0, 0, 40, "remove", bufname(''), 1)
|
||||||
|
call gotest#assert_fixture('tags/remove_all_golden.go')
|
||||||
|
finally
|
||||||
|
call delete(l:tmp, 'rf')
|
||||||
|
endtry
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" vim:ts=2:sts=2:sw=2:et
|
||||||
53
autoload/go/template.vim
Normal file
53
autoload/go/template.vim
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
let s:current_file = expand("<sfile>")
|
||||||
|
|
||||||
|
function! go#template#create() abort
|
||||||
|
let l:go_template_use_pkg = get(g:, 'go_template_use_pkg', 0)
|
||||||
|
let l:root_dir = fnamemodify(s:current_file, ':h:h:h')
|
||||||
|
|
||||||
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
||||||
|
let dir = getcwd()
|
||||||
|
let l:package_name = -1
|
||||||
|
|
||||||
|
if isdirectory(expand('%:p:h'))
|
||||||
|
execute cd . fnameescape(expand('%:p:h'))
|
||||||
|
let l:package_name = go#tool#PackageName()
|
||||||
|
endif
|
||||||
|
|
||||||
|
" if we can't figure out any package name(no Go files or non Go package
|
||||||
|
" files) from the directory create the template or use the cwd
|
||||||
|
" as the name
|
||||||
|
if l:package_name == -1 && l:go_template_use_pkg != 1
|
||||||
|
let l:filename = fnamemodify(expand("%"), ':t')
|
||||||
|
if l:filename =~ "_test.go$"
|
||||||
|
let l:template_file = get(g:, 'go_template_test_file', "hello_world_test.go")
|
||||||
|
else
|
||||||
|
let l:template_file = get(g:, 'go_template_file', "hello_world.go")
|
||||||
|
endif
|
||||||
|
let l:template_path = go#util#Join(l:root_dir, "templates", l:template_file)
|
||||||
|
silent exe '0r ' . fnameescape(l:template_path)
|
||||||
|
elseif l:package_name == -1 && l:go_template_use_pkg == 1
|
||||||
|
" cwd is now the dir of the package
|
||||||
|
let l:path = fnamemodify(getcwd(), ':t')
|
||||||
|
let l:content = printf("package %s", l:path)
|
||||||
|
call append(0, l:content)
|
||||||
|
else
|
||||||
|
let l:content = printf("package %s", l:package_name)
|
||||||
|
call append(0, l:content)
|
||||||
|
endif
|
||||||
|
$delete _
|
||||||
|
|
||||||
|
execute cd . fnameescape(dir)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! go#template#ToggleAutoCreate() abort
|
||||||
|
if get(g:, "go_template_autocreate", 1)
|
||||||
|
let g:go_template_autocreate = 0
|
||||||
|
call go#util#EchoProgress("auto template create disabled")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
let g:go_template_autocreate = 1
|
||||||
|
call go#util#EchoProgress("auto template create enabled")
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
@ -7,22 +7,19 @@ let s:jobs = {}
|
|||||||
|
|
||||||
" new creates a new terminal with the given command. Mode is set based on the
|
" new creates a new terminal with the given command. Mode is set based on the
|
||||||
" global variable g:go_term_mode, which is by default set to :vsplit
|
" global variable g:go_term_mode, which is by default set to :vsplit
|
||||||
function! go#term#new(bang, cmd)
|
function! go#term#new(bang, cmd) abort
|
||||||
return go#term#newmode(a:bang, a:cmd, g:go_term_mode)
|
return go#term#newmode(a:bang, a:cmd, g:go_term_mode)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" new creates a new terminal with the given command and window mode.
|
" new creates a new terminal with the given command and window mode.
|
||||||
function! go#term#newmode(bang, cmd, mode)
|
function! go#term#newmode(bang, cmd, mode) abort
|
||||||
let mode = a:mode
|
let mode = a:mode
|
||||||
if empty(mode)
|
if empty(mode)
|
||||||
let mode = g:go_term_mode
|
let mode = g:go_term_mode
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" modify GOPATH if needed
|
|
||||||
let old_gopath = $GOPATH
|
|
||||||
let $GOPATH = go#path#Detect()
|
|
||||||
|
|
||||||
" execute go build in the files directory
|
" execute go build in the files directory
|
||||||
|
let l:winnr = winnr()
|
||||||
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
||||||
let dir = getcwd()
|
let dir = getcwd()
|
||||||
|
|
||||||
@ -49,32 +46,37 @@ function! go#term#newmode(bang, cmd, mode)
|
|||||||
|
|
||||||
execute cd . fnameescape(dir)
|
execute cd . fnameescape(dir)
|
||||||
|
|
||||||
" restore back GOPATH
|
|
||||||
let $GOPATH = old_gopath
|
|
||||||
|
|
||||||
let job.id = id
|
let job.id = id
|
||||||
|
let job.cmd = a:cmd
|
||||||
startinsert
|
startinsert
|
||||||
|
|
||||||
" resize new term if needed.
|
" resize new term if needed.
|
||||||
let height = get(g:, 'go_term_height', winheight(0))
|
let height = get(g:, 'go_term_height', winheight(0))
|
||||||
let width = get(g:, 'go_term_width', winwidth(0))
|
let width = get(g:, 'go_term_width', winwidth(0))
|
||||||
|
|
||||||
" we are careful how to resize. for example it's vertical we don't change
|
" we are careful how to resize. for example it's vsplit we don't change
|
||||||
" the height. The below command resizes the buffer
|
" the height. The below command resizes the buffer
|
||||||
if a:mode == "split"
|
|
||||||
exe 'resize ' . height
|
if mode =~ "vertical" || mode =~ "vsplit" || mode =~ "vnew"
|
||||||
elseif a:mode == "vertical"
|
|
||||||
exe 'vertical resize ' . width
|
exe 'vertical resize ' . width
|
||||||
|
elseif mode =~ "split" || mode =~ "new"
|
||||||
|
exe 'resize ' . height
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" we also need to resize the pty, so there you go...
|
" we also need to resize the pty, so there you go...
|
||||||
call jobresize(id, width, height)
|
call jobresize(id, width, height)
|
||||||
|
|
||||||
let s:jobs[id] = job
|
let s:jobs[id] = job
|
||||||
|
stopinsert
|
||||||
|
|
||||||
|
if l:winnr !=# winnr()
|
||||||
|
exe l:winnr . "wincmd w"
|
||||||
|
endif
|
||||||
|
|
||||||
return id
|
return id
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:on_stdout(job_id, data)
|
function! s:on_stdout(job_id, data, event) dict abort
|
||||||
if !has_key(s:jobs, a:job_id)
|
if !has_key(s:jobs, a:job_id)
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
@ -83,7 +85,7 @@ function! s:on_stdout(job_id, data)
|
|||||||
call extend(job.stdout, a:data)
|
call extend(job.stdout, a:data)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:on_stderr(job_id, data)
|
function! s:on_stderr(job_id, data, event) dict abort
|
||||||
if !has_key(s:jobs, a:job_id)
|
if !has_key(s:jobs, a:job_id)
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
@ -92,37 +94,47 @@ function! s:on_stderr(job_id, data)
|
|||||||
call extend(job.stderr, a:data)
|
call extend(job.stderr, a:data)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:on_exit(job_id, data)
|
function! s:on_exit(job_id, exit_status, event) dict abort
|
||||||
if !has_key(s:jobs, a:job_id)
|
if !has_key(s:jobs, a:job_id)
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
let job = s:jobs[a:job_id]
|
let job = s:jobs[a:job_id]
|
||||||
|
|
||||||
let l:listtype = "locationlist"
|
let l:listtype = go#list#Type("_term")
|
||||||
|
|
||||||
" usually there is always output so never branch into this clause
|
" usually there is always output so never branch into this clause
|
||||||
if empty(job.stdout)
|
if empty(job.stdout)
|
||||||
call go#list#Clean(l:listtype)
|
call go#list#Clean(l:listtype)
|
||||||
call go#list#Window(l:listtype)
|
call go#list#Window(l:listtype)
|
||||||
else
|
unlet s:jobs[a:job_id]
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
let errors = go#tool#ParseErrors(job.stdout)
|
let errors = go#tool#ParseErrors(job.stdout)
|
||||||
let errors = go#tool#FilterValids(errors)
|
let errors = go#tool#FilterValids(errors)
|
||||||
|
|
||||||
if !empty(errors)
|
if !empty(errors)
|
||||||
" close terminal we don't need it
|
" close terminal we don't need it anymore
|
||||||
close
|
close
|
||||||
|
|
||||||
call go#list#Populate(l:listtype, errors)
|
call go#list#Populate(l:listtype, errors, job.cmd)
|
||||||
call go#list#Window(l:listtype, len(errors))
|
call go#list#Window(l:listtype, len(errors))
|
||||||
if !self.bang
|
if !self.bang
|
||||||
call go#list#JumpToFirst(l:listtype)
|
call go#list#JumpToFirst(l:listtype)
|
||||||
endif
|
endif
|
||||||
else
|
unlet s:jobs[a:job_id]
|
||||||
call go#list#Clean(l:listtype)
|
return
|
||||||
call go#list#Window(l:listtype)
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
endif
|
" tests are passing clean the list and close the list. But we only can
|
||||||
|
" close them from a normal view, so jump back, close the list and then
|
||||||
|
" again jump back to the terminal
|
||||||
|
wincmd p
|
||||||
|
call go#list#Clean(l:listtype)
|
||||||
|
call go#list#Window(l:listtype)
|
||||||
|
wincmd p
|
||||||
|
|
||||||
unlet s:jobs[a:job_id]
|
unlet s:jobs[a:job_id]
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
7
autoload/go/test-fixtures/def/jump.go
Normal file
7
autoload/go/test-fixtures/def/jump.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("vim-go")
|
||||||
|
}
|
||||||
7
autoload/go/test-fixtures/fmt/hello.go
Normal file
7
autoload/go/test-fixtures/fmt/hello.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("vim-go")
|
||||||
|
}
|
||||||
7
autoload/go/test-fixtures/fmt/hello_golden.go
Normal file
7
autoload/go/test-fixtures/fmt/hello_golden.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("vim-go")
|
||||||
|
}
|
||||||
13
autoload/go/test-fixtures/fmt/imports/goimports.go
Normal file
13
autoload/go/test-fixtures/fmt/imports/goimports.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Foo(log *logging.TestLogger) {
|
||||||
|
log.Debug("vim-go")
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("vim-go")
|
||||||
|
}
|
||||||
15
autoload/go/test-fixtures/fmt/imports/goimports_golden.go
Normal file
15
autoload/go/test-fixtures/fmt/imports/goimports_golden.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
logging "gh.com/gi/foo-logging"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Foo(log *logging.TestLogger) {
|
||||||
|
log.Debug("vim-go")
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("vim-go")
|
||||||
|
}
|
||||||
12
autoload/go/test-fixtures/fmt/imports/vendor/gh.com/gi/foo-logging/logger.go
generated
vendored
Normal file
12
autoload/go/test-fixtures/fmt/imports/vendor/gh.com/gi/foo-logging/logger.go
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package logging
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type TestLogger struct {
|
||||||
|
Value string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *TestLogger) Debug(msg string) {
|
||||||
|
fmt.Println(msg)
|
||||||
|
fmt.Println(l.Value)
|
||||||
|
}
|
||||||
1
autoload/go/test-fixtures/fmt/src/imports
Symbolic link
1
autoload/go/test-fixtures/fmt/src/imports
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../imports/
|
||||||
16
autoload/go/test-fixtures/tags/add_all_golden.go
Normal file
16
autoload/go/test-fixtures/tags/add_all_golden.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type Server struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
ID int `json:"id"`
|
||||||
|
MyHomeAddress string `json:"my_home_address"`
|
||||||
|
SubDomains []string `json:"sub_domains"`
|
||||||
|
Empty string `json:"empty"`
|
||||||
|
Example int64 `json:"example"`
|
||||||
|
Example2 string `json:"example_2"`
|
||||||
|
Bar struct {
|
||||||
|
Four string `json:"four"`
|
||||||
|
Five string `json:"five"`
|
||||||
|
} `json:"bar"`
|
||||||
|
Lala interface{} `json:"lala"`
|
||||||
|
}
|
||||||
16
autoload/go/test-fixtures/tags/add_all_input.go
Normal file
16
autoload/go/test-fixtures/tags/add_all_input.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type Server struct {
|
||||||
|
Name string
|
||||||
|
ID int
|
||||||
|
MyHomeAddress string
|
||||||
|
SubDomains []string
|
||||||
|
Empty string
|
||||||
|
Example int64
|
||||||
|
Example2 string
|
||||||
|
Bar struct {
|
||||||
|
Four string
|
||||||
|
Five string
|
||||||
|
}
|
||||||
|
Lala interface{}
|
||||||
|
}
|
||||||
16
autoload/go/test-fixtures/tags/remove_all_golden.go
Normal file
16
autoload/go/test-fixtures/tags/remove_all_golden.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type Server struct {
|
||||||
|
Name string
|
||||||
|
ID int
|
||||||
|
MyHomeAddress string
|
||||||
|
SubDomains []string
|
||||||
|
Empty string
|
||||||
|
Example int64
|
||||||
|
Example2 string
|
||||||
|
Bar struct {
|
||||||
|
Four string
|
||||||
|
Five string
|
||||||
|
}
|
||||||
|
Lala interface{}
|
||||||
|
}
|
||||||
16
autoload/go/test-fixtures/tags/remove_all_input.go
Normal file
16
autoload/go/test-fixtures/tags/remove_all_input.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type Server struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
ID int `json:"id"`
|
||||||
|
MyHomeAddress string `json:"my_home_address"`
|
||||||
|
SubDomains []string `json:"sub_domains"`
|
||||||
|
Empty string `json:"empty"`
|
||||||
|
Example int64 `json:"example"`
|
||||||
|
Example2 string `json:"example_2"`
|
||||||
|
Bar struct {
|
||||||
|
Four string `json:"four"`
|
||||||
|
Five string `json:"five"`
|
||||||
|
} `json:"bar"`
|
||||||
|
Lala interface{} `json:"lala"`
|
||||||
|
}
|
||||||
1
autoload/go/test-fixtures/test/.gitignore
vendored
Normal file
1
autoload/go/test-fixtures/test/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/pkg
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("vim-go"
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
package mock
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func Fail(t *testing.T) {
|
||||||
|
t.Fatal("another package badness")
|
||||||
|
}
|
||||||
58
autoload/go/test-fixtures/test/src/play/play_test.go
Normal file
58
autoload/go/test-fixtures/test/src/play/play_test.go
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
package play
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"play/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTopSubHelper(t *testing.T) {
|
||||||
|
t.Run("sub", func(t *testing.T) {
|
||||||
|
t.Log("log message")
|
||||||
|
t.Error("sub badness")
|
||||||
|
})
|
||||||
|
t.Error("badness")
|
||||||
|
helper(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMultiline(t *testing.T) {
|
||||||
|
t.Error("this is an error\nand a second line, too")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSub(t *testing.T) {
|
||||||
|
t.Run("indented", func(t *testing.T) {
|
||||||
|
t.Error("this is a sub-test error\nand a second line, too")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOK(t *testing.T) {
|
||||||
|
t.Run("log", func(t *testing.T) {
|
||||||
|
t.Log("goodness")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestMocked tests behavior similar to what users may experience when using
|
||||||
|
// github.com/golang/mock/gomock.
|
||||||
|
func TestMocked(t *testing.T) {
|
||||||
|
mock.Fail(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPanic(t *testing.T) {
|
||||||
|
panic("worst ever")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConcurrentPanic(t *testing.T) {
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
panic("concurrent fail")
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func helper(t *testing.T) {
|
||||||
|
t.Helper()
|
||||||
|
t.Fatal("helper badness")
|
||||||
|
}
|
||||||
389
autoload/go/test.vim
Normal file
389
autoload/go/test.vim
Normal file
@ -0,0 +1,389 @@
|
|||||||
|
" Test runs `go test` in the current directory. If compile is true, it'll
|
||||||
|
" compile the tests instead of running them (useful to catch errors in the
|
||||||
|
" test files). Any other argument is appended to the final `go test` command.
|
||||||
|
function! go#test#Test(bang, compile, ...) abort
|
||||||
|
let args = ["test"]
|
||||||
|
|
||||||
|
" don't run the test, only compile it. Useful to capture and fix errors.
|
||||||
|
if a:compile
|
||||||
|
let testfile = tempname() . ".vim-go.test"
|
||||||
|
call extend(args, ["-c", "-o", testfile])
|
||||||
|
endif
|
||||||
|
|
||||||
|
if exists('g:go_build_tags')
|
||||||
|
let tags = get(g:, 'go_build_tags')
|
||||||
|
call extend(args, ["-tags", tags])
|
||||||
|
endif
|
||||||
|
|
||||||
|
if a:0
|
||||||
|
let goargs = a:000
|
||||||
|
|
||||||
|
" do not expand for coverage mode as we're passing the arg ourself
|
||||||
|
if a:1 != '-coverprofile'
|
||||||
|
" expand all wildcards(i.e: '%' to the current file name)
|
||||||
|
let goargs = map(copy(a:000), "expand(v:val)")
|
||||||
|
endif
|
||||||
|
|
||||||
|
if !(has('nvim') || go#util#has_job())
|
||||||
|
let goargs = go#util#Shelllist(goargs, 1)
|
||||||
|
endif
|
||||||
|
|
||||||
|
call extend(args, goargs, 1)
|
||||||
|
else
|
||||||
|
" only add this if no custom flags are passed
|
||||||
|
let timeout = get(g:, 'go_test_timeout', '10s')
|
||||||
|
call add(args, printf("-timeout=%s", timeout))
|
||||||
|
endif
|
||||||
|
|
||||||
|
if get(g:, 'go_echo_command_info', 1)
|
||||||
|
if a:compile
|
||||||
|
call go#util#EchoProgress("compiling tests ...")
|
||||||
|
else
|
||||||
|
call go#util#EchoProgress("testing...")
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
if go#util#has_job()
|
||||||
|
" use vim's job functionality to call it asynchronously
|
||||||
|
let job_args = {
|
||||||
|
\ 'cmd': ['go'] + args,
|
||||||
|
\ 'bang': a:bang,
|
||||||
|
\ 'winnr': winnr(),
|
||||||
|
\ 'dir': getcwd(),
|
||||||
|
\ 'compile_test': a:compile,
|
||||||
|
\ 'jobdir': fnameescape(expand("%:p:h")),
|
||||||
|
\ }
|
||||||
|
|
||||||
|
call s:test_job(job_args)
|
||||||
|
return
|
||||||
|
elseif has('nvim')
|
||||||
|
" use nvims's job functionality
|
||||||
|
if get(g:, 'go_term_enabled', 0)
|
||||||
|
let id = go#term#new(a:bang, ["go"] + args)
|
||||||
|
else
|
||||||
|
let id = go#jobcontrol#Spawn(a:bang, "test", "GoTest", args)
|
||||||
|
endif
|
||||||
|
|
||||||
|
return id
|
||||||
|
endif
|
||||||
|
|
||||||
|
call go#cmd#autowrite()
|
||||||
|
redraw
|
||||||
|
|
||||||
|
let command = "go " . join(args, ' ')
|
||||||
|
let out = go#tool#ExecuteInDir(command)
|
||||||
|
" TODO(bc): When the output is JSON, the JSON should be run through a
|
||||||
|
" filter to produce lines that are more easily described by errorformat.
|
||||||
|
|
||||||
|
let l:listtype = go#list#Type("GoTest")
|
||||||
|
|
||||||
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
||||||
|
let dir = getcwd()
|
||||||
|
execute cd fnameescape(expand("%:p:h"))
|
||||||
|
|
||||||
|
if go#util#ShellError() != 0
|
||||||
|
call go#list#ParseFormat(l:listtype, s:errorformat(), split(out, '\n'), command)
|
||||||
|
let errors = go#list#Get(l:listtype)
|
||||||
|
call go#list#Window(l:listtype, len(errors))
|
||||||
|
if !empty(errors) && !a:bang
|
||||||
|
call go#list#JumpToFirst(l:listtype)
|
||||||
|
elseif empty(errors)
|
||||||
|
" failed to parse errors, output the original content
|
||||||
|
call go#util#EchoError(out)
|
||||||
|
endif
|
||||||
|
call go#util#EchoError("[test] FAIL")
|
||||||
|
else
|
||||||
|
call go#list#Clean(l:listtype)
|
||||||
|
call go#list#Window(l:listtype)
|
||||||
|
|
||||||
|
if a:compile
|
||||||
|
call go#util#EchoSuccess("[test] SUCCESS")
|
||||||
|
else
|
||||||
|
call go#util#EchoSuccess("[test] PASS")
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
execute cd . fnameescape(dir)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Testfunc runs a single test that surrounds the current cursor position.
|
||||||
|
" Arguments are passed to the `go test` command.
|
||||||
|
function! go#test#Func(bang, ...) abort
|
||||||
|
" search flags legend (used only)
|
||||||
|
" 'b' search backward instead of forward
|
||||||
|
" 'c' accept a match at the cursor position
|
||||||
|
" 'n' do Not move the cursor
|
||||||
|
" 'W' don't wrap around the end of the file
|
||||||
|
"
|
||||||
|
" for the full list
|
||||||
|
" :help search
|
||||||
|
let test = search('func \(Test\|Example\)', "bcnW")
|
||||||
|
|
||||||
|
if test == 0
|
||||||
|
echo "vim-go: [test] no test found immediate to cursor"
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
let line = getline(test)
|
||||||
|
let name = split(split(line, " ")[1], "(")[0]
|
||||||
|
let args = [a:bang, 0, "-run", name . "$"]
|
||||||
|
|
||||||
|
if a:0
|
||||||
|
call extend(args, a:000)
|
||||||
|
endif
|
||||||
|
|
||||||
|
call call('go#test#Test', args)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:test_job(args) abort
|
||||||
|
let status_dir = expand('%:p:h')
|
||||||
|
let started_at = reltime()
|
||||||
|
|
||||||
|
let status = {
|
||||||
|
\ 'desc': 'current status',
|
||||||
|
\ 'type': "test",
|
||||||
|
\ 'state': "started",
|
||||||
|
\ }
|
||||||
|
|
||||||
|
if a:args.compile_test
|
||||||
|
let status.state = "compiling"
|
||||||
|
endif
|
||||||
|
|
||||||
|
call go#statusline#Update(status_dir, status)
|
||||||
|
|
||||||
|
" autowrite is not enabled for jobs
|
||||||
|
call go#cmd#autowrite()
|
||||||
|
|
||||||
|
let messages = []
|
||||||
|
function! s:callback(chan, msg) closure
|
||||||
|
call add(messages, a:msg)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:exit_cb(job, exitval) closure
|
||||||
|
let status = {
|
||||||
|
\ 'desc': 'last status',
|
||||||
|
\ 'type': "test",
|
||||||
|
\ 'state': "pass",
|
||||||
|
\ }
|
||||||
|
|
||||||
|
if a:args.compile_test
|
||||||
|
let status.state = "success"
|
||||||
|
endif
|
||||||
|
|
||||||
|
if a:exitval
|
||||||
|
let status.state = "failed"
|
||||||
|
endif
|
||||||
|
|
||||||
|
if get(g:, 'go_echo_command_info', 1)
|
||||||
|
if a:exitval == 0
|
||||||
|
if a:args.compile_test
|
||||||
|
call go#util#EchoSuccess("[test] SUCCESS")
|
||||||
|
else
|
||||||
|
call go#util#EchoSuccess("[test] PASS")
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
call go#util#EchoError("[test] FAIL")
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
let elapsed_time = reltimestr(reltime(started_at))
|
||||||
|
" strip whitespace
|
||||||
|
let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '')
|
||||||
|
let status.state .= printf(" (%ss)", elapsed_time)
|
||||||
|
|
||||||
|
call go#statusline#Update(status_dir, status)
|
||||||
|
|
||||||
|
let l:listtype = go#list#Type("GoTest")
|
||||||
|
if a:exitval == 0
|
||||||
|
call go#list#Clean(l:listtype)
|
||||||
|
call go#list#Window(l:listtype)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
" TODO(bc): When messages is JSON, the JSON should be run through a
|
||||||
|
" filter to produce lines that are more easily described by errorformat.
|
||||||
|
call s:show_errors(a:args, a:exitval, messages)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
let start_options = {
|
||||||
|
\ 'callback': funcref("s:callback"),
|
||||||
|
\ 'exit_cb': funcref("s:exit_cb"),
|
||||||
|
\ }
|
||||||
|
|
||||||
|
" pre start
|
||||||
|
let dir = getcwd()
|
||||||
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
||||||
|
let jobdir = fnameescape(expand("%:p:h"))
|
||||||
|
execute cd . jobdir
|
||||||
|
|
||||||
|
call job_start(a:args.cmd, start_options)
|
||||||
|
|
||||||
|
" post start
|
||||||
|
execute cd . fnameescape(dir)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" show_errors parses the given list of lines of a 'go test' output and returns
|
||||||
|
" a quickfix compatible list of errors. It's intended to be used only for go
|
||||||
|
" test output.
|
||||||
|
function! s:show_errors(args, exit_val, messages) abort
|
||||||
|
let l:listtype = go#list#Type("GoTest")
|
||||||
|
|
||||||
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
||||||
|
try
|
||||||
|
execute cd a:args.jobdir
|
||||||
|
call go#list#ParseFormat(l:listtype, s:errorformat(), a:messages, join(a:args.cmd))
|
||||||
|
let errors = go#list#Get(l:listtype)
|
||||||
|
finally
|
||||||
|
execute cd . fnameescape(a:args.dir)
|
||||||
|
endtry
|
||||||
|
|
||||||
|
if !len(errors)
|
||||||
|
" failed to parse errors, output the original content
|
||||||
|
call go#util#EchoError(a:messages)
|
||||||
|
call go#util#EchoError(a:args.dir)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
if a:args.winnr == winnr()
|
||||||
|
call go#list#Window(l:listtype, len(errors))
|
||||||
|
if !empty(errors) && !a:args.bang
|
||||||
|
call go#list#JumpToFirst(l:listtype)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
let s:efm= ""
|
||||||
|
|
||||||
|
function! s:errorformat() abort
|
||||||
|
" NOTE(arslan): once we get JSON output everything will be easier :).
|
||||||
|
" TODO(bc): When the output is JSON, the JSON should be run through a
|
||||||
|
" filter to produce lines that are more easily described by errorformat.
|
||||||
|
" https://github.com/golang/go/issues/2981.
|
||||||
|
let goroot = go#util#goroot()
|
||||||
|
|
||||||
|
if s:efm != ""
|
||||||
|
return s:efm
|
||||||
|
endif
|
||||||
|
|
||||||
|
" each level of test indents the test output 4 spaces.
|
||||||
|
" TODO(bc): figure out how to use 0 or more groups of four spaces for the
|
||||||
|
" indentation. '%\\( %\\)%#' should work, but doesn't.
|
||||||
|
let indent = " %#"
|
||||||
|
|
||||||
|
" match compiler errors
|
||||||
|
let format = "%f:%l:%c: %m"
|
||||||
|
|
||||||
|
" ignore `go test -v` output for starting tests
|
||||||
|
let format .= ",%-G=== RUN %.%#"
|
||||||
|
" ignore `go test -v` output for passing tests
|
||||||
|
let format .= ",%-G" . indent . "--- PASS: %.%#"
|
||||||
|
|
||||||
|
" Match failure lines.
|
||||||
|
"
|
||||||
|
" Test failures start with '--- FAIL: ', followed by the test name followed
|
||||||
|
" by a space the duration of the test in parentheses
|
||||||
|
"
|
||||||
|
" e.g.:
|
||||||
|
" '--- FAIL: TestSomething (0.00s)'
|
||||||
|
if get(g:, 'go_test_show_name', 0)
|
||||||
|
let format .= ",%+G" . indent . "--- FAIL: %.%#"
|
||||||
|
else
|
||||||
|
let format .= ",%-G" . indent . "--- FAIL: %.%#"
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Matches test output lines.
|
||||||
|
"
|
||||||
|
" All test output lines start with the test indentation and a tab, followed
|
||||||
|
" by the filename, a colon, the line number, another colon, a space, and the
|
||||||
|
" message. e.g.:
|
||||||
|
" '\ttime_test.go:30: Likely problem: the time zone files have not been installed.'
|
||||||
|
let format .= ",%A" . indent . "%\\t%\\+%f:%l: %m"
|
||||||
|
|
||||||
|
" Match the 2nd and later lines of multi-line output. These lines are
|
||||||
|
" indented the number of spaces for the level of nesting of the test,
|
||||||
|
" followed by two tabs, followed by the message.
|
||||||
|
"
|
||||||
|
" Treat these lines as if they are stand-alone lines of output by using %G.
|
||||||
|
" It would also be valid to treat these lines as if they were the
|
||||||
|
" continuation of a multi-line error by using %C instead of %G, but that
|
||||||
|
" would also require that all test errors using a %A or %E modifier to
|
||||||
|
" indicate that they're multiple lines of output, but in that case the lines
|
||||||
|
" get concatenated in the quickfix list, which is not what users typically
|
||||||
|
" want when writing a newline into their test output.
|
||||||
|
let format .= ",%G" . indent . "%\\t%\\{2}%m"
|
||||||
|
|
||||||
|
" set the format for panics.
|
||||||
|
|
||||||
|
" In addition to 'panic', check for 'fatal error' to support older versions
|
||||||
|
" of Go that used 'fatal error'.
|
||||||
|
"
|
||||||
|
" Panics come in two flavors. When the goroutine running the tests panics,
|
||||||
|
" `go test` recovers and tries to exit more cleanly. In that case, the panic
|
||||||
|
" message is suffixed with ' [recovered]'. If the panic occurs in a
|
||||||
|
" different goroutine, it will not be suffixed with ' [recovered]'.
|
||||||
|
let format .= ",%+Afatal error: %.%# [recovered]"
|
||||||
|
let format .= ",%+Apanic: %.%# [recovered]"
|
||||||
|
let format .= ",%+Afatal error: %.%#"
|
||||||
|
let format .= ",%+Apanic: %.%#"
|
||||||
|
|
||||||
|
" Match address lines in stacktraces produced by panic.
|
||||||
|
"
|
||||||
|
" Address lines in the stack trace have leading tabs, followed by the path
|
||||||
|
" to the file. The file path is followed by a colon and then the line number
|
||||||
|
" within the file where the panic occurred. After that there's a space and
|
||||||
|
" hexadecimal number.
|
||||||
|
"
|
||||||
|
" e.g.:
|
||||||
|
" '\t/usr/local/go/src/time.go:1313 +0x5d'
|
||||||
|
|
||||||
|
" panicaddress, and readyaddress are identical except for
|
||||||
|
" panicaddress sets the filename and line number.
|
||||||
|
let panicaddress = "%\\t%f:%l +0x%[0-9A-Fa-f]%\\+"
|
||||||
|
let readyaddress = "%\\t%\\f%\\+:%\\d%\\+ +0x%[0-9A-Fa-f]%\\+"
|
||||||
|
" stdlib address is identical to readyaddress, except it matches files
|
||||||
|
" inside GOROOT.
|
||||||
|
let stdlibaddress = "%\\t" . goroot . "%\\f%\\+:%\\d%\\+ +0x%[0-9A-Fa-f]%\\+"
|
||||||
|
|
||||||
|
" Match and ignore the running goroutine line.
|
||||||
|
let format .= ",%-Cgoroutine %\\d%\\+ [running]:"
|
||||||
|
" Match address lines that refer to stdlib, but consider them informational
|
||||||
|
" only. This is to catch the lines after the first address line in the
|
||||||
|
" running goroutine of a panic stack trace. Ideally, this wouldn't be
|
||||||
|
" necessary, but when a panic happens in the goroutine running a test, it's
|
||||||
|
" recovered and another panic is created, so the stack trace actually has
|
||||||
|
" the line that caused the original panic a couple of addresses down the
|
||||||
|
" stack.
|
||||||
|
let format .= ",%-C" . stdlibaddress
|
||||||
|
" Match address lines in the first matching goroutine. This means the panic
|
||||||
|
" message will only be shown as the error message in the first address of
|
||||||
|
" the running goroutine's stack.
|
||||||
|
let format .= ",%Z" . panicaddress
|
||||||
|
|
||||||
|
" Match and ignore panic address without being part of a multi-line message.
|
||||||
|
" This is to catch those lines that come after the top most non-standard
|
||||||
|
" library line in stack traces.
|
||||||
|
let format .= ",%-G" . readyaddress
|
||||||
|
|
||||||
|
" Match and ignore exit status lines (produced when go test panics) whether
|
||||||
|
" part of a multi-line message or not, because these lines sometimes come
|
||||||
|
" before and sometimes after panic stacktraces.
|
||||||
|
let format .= ",%-Cexit status %[0-9]%\\+"
|
||||||
|
"let format .= ",exit status %[0-9]%\\+"
|
||||||
|
|
||||||
|
" Match and ignore exit failure lines whether part of a multi-line message
|
||||||
|
" or not, because these lines sometimes come before and sometimes after
|
||||||
|
" panic stacktraces.
|
||||||
|
let format .= ",%-CFAIL%\\t%.%#"
|
||||||
|
"let format .= ",FAIL%\\t%.%#"
|
||||||
|
|
||||||
|
" Match and ignore everything else in multi-line messages.
|
||||||
|
let format .= ",%-C%.%#"
|
||||||
|
" Match and ignore everything else not in a multi-line message:
|
||||||
|
let format .= ",%-G%.%#"
|
||||||
|
|
||||||
|
let s:efm = format
|
||||||
|
|
||||||
|
return s:efm
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
123
autoload/go/test_test.vim
Normal file
123
autoload/go/test_test.vim
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
func! Test_GoTest() abort
|
||||||
|
let expected = [
|
||||||
|
\ {'lnum': 12, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'log message'},
|
||||||
|
\ {'lnum': 13, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'sub badness'},
|
||||||
|
\ {'lnum': 15, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'badness'},
|
||||||
|
\ {'lnum': 16, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'helper badness'},
|
||||||
|
\ {'lnum': 20, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'this is an error'},
|
||||||
|
\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'and a second line, too'},
|
||||||
|
\ {'lnum': 25, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'this is a sub-test error'},
|
||||||
|
\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'and a second line, too'},
|
||||||
|
\ {'lnum': 6, 'bufnr': 3, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'another package badness'},
|
||||||
|
\ {'lnum': 42, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'panic: worst ever [recovered]'}
|
||||||
|
\ ]
|
||||||
|
call s:test('play/play_test.go', expected)
|
||||||
|
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func! Test_GoTestConcurrentPanic()
|
||||||
|
let expected = [
|
||||||
|
\ {'lnum': 49, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'panic: concurrent fail'}
|
||||||
|
\ ]
|
||||||
|
call s:test('play/play_test.go', expected, "-run", "TestConcurrentPanic")
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func! Test_GoTestVerbose() abort
|
||||||
|
let expected = [
|
||||||
|
\ {'lnum': 12, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'log message'},
|
||||||
|
\ {'lnum': 13, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'sub badness'},
|
||||||
|
\ {'lnum': 15, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'badness'},
|
||||||
|
\ {'lnum': 16, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'helper badness'},
|
||||||
|
\ {'lnum': 20, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'this is an error'},
|
||||||
|
\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'and a second line, too'},
|
||||||
|
\ {'lnum': 25, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'this is a sub-test error'},
|
||||||
|
\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'and a second line, too'},
|
||||||
|
\ {'lnum': 31, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'goodness'},
|
||||||
|
\ {'lnum': 6, 'bufnr': 3, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'another package badness'},
|
||||||
|
\ {'lnum': 42, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'panic: worst ever [recovered]'}
|
||||||
|
\ ]
|
||||||
|
call s:test('play/play_test.go', expected, "-v")
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func! Test_GoTestCompilerError() abort
|
||||||
|
let expected = [
|
||||||
|
\ {'lnum': 6, 'bufnr': 6, 'col': 22, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'syntax error: unexpected newline, expecting comma or )'}
|
||||||
|
\ ]
|
||||||
|
|
||||||
|
call s:test('compilerror/compilerror_test.go', expected)
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func! s:test(file, expected, ...) abort
|
||||||
|
if has('nvim')
|
||||||
|
" nvim mostly shows test errors correctly, but the the expected errors are
|
||||||
|
" slightly different; buffer numbers are not the same and stderr doesn't
|
||||||
|
" seem to be redirected to the job, so the lines from the panic aren't in
|
||||||
|
" the output to be parsed, and hence are not in the quickfix lists. Once
|
||||||
|
" those two issues are resolved, this early return should be removed so
|
||||||
|
" the tests will run for Neovim, too.
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
let $GOPATH = fnameescape(expand("%:p:h")) . '/test-fixtures/test'
|
||||||
|
silent exe 'e ' . $GOPATH . '/src/' . a:file
|
||||||
|
|
||||||
|
" clear the quickfix lists
|
||||||
|
call setqflist([], 'r')
|
||||||
|
|
||||||
|
let args = [1,0]
|
||||||
|
if a:0
|
||||||
|
let args += a:000
|
||||||
|
endif
|
||||||
|
|
||||||
|
" run the tests
|
||||||
|
call call(function('go#test#Test'), args)
|
||||||
|
|
||||||
|
let actual = getqflist()
|
||||||
|
let start = reltime()
|
||||||
|
while len(actual) == 0 && reltimefloat(reltime(start)) < 10
|
||||||
|
sleep 100m
|
||||||
|
let actual = getqflist()
|
||||||
|
endwhile
|
||||||
|
|
||||||
|
" for some reason, when run headless, the quickfix lists includes a line
|
||||||
|
" that should have been filtered out; remove it manually. The line is not
|
||||||
|
" present when run manually.
|
||||||
|
let i = 0
|
||||||
|
while i < len(actual)
|
||||||
|
if actual[i].text =~# '^=== RUN .*'
|
||||||
|
call remove(actual, i)
|
||||||
|
endif
|
||||||
|
let i += 1
|
||||||
|
endwhile
|
||||||
|
|
||||||
|
call assert_equal(len(a:expected), len(actual), "number of errors")
|
||||||
|
if len(a:expected) != len(actual)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let i = 0
|
||||||
|
while i < len(a:expected)
|
||||||
|
let expected_item = a:expected[i]
|
||||||
|
let actual_item = actual[i]
|
||||||
|
let i += 1
|
||||||
|
|
||||||
|
call assert_equal(expected_item.bufnr, actual_item.bufnr, "bufnr")
|
||||||
|
call assert_equal(expected_item.lnum, actual_item.lnum, "lnum")
|
||||||
|
call assert_equal(expected_item.col, actual_item.col, "col")
|
||||||
|
call assert_equal(expected_item.vcol, actual_item.vcol, "vcol")
|
||||||
|
call assert_equal(expected_item.nr, actual_item.nr, "nr")
|
||||||
|
call assert_equal(expected_item.pattern, actual_item.pattern, "pattern")
|
||||||
|
|
||||||
|
let expected_text = s:normalize_durations(expected_item.text)
|
||||||
|
let actual_text = s:normalize_durations(actual_item.text)
|
||||||
|
|
||||||
|
call assert_equal(expected_text, actual_text, "text")
|
||||||
|
call assert_equal(expected_item.type, actual_item.type, "type")
|
||||||
|
call assert_equal(expected_item.valid, actual_item.valid, "valid")
|
||||||
|
endwhile
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func! s:normalize_durations(str) abort
|
||||||
|
return substitute(a:str, '[0-9]\+\(\.[0-9]\+\)\?s', '0.000s', 'g')
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
@ -6,6 +6,10 @@ if !exists("g:go_textobj_include_function_doc")
|
|||||||
let g:go_textobj_include_function_doc = 1
|
let g:go_textobj_include_function_doc = 1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if !exists("g:go_textobj_include_variable")
|
||||||
|
let g:go_textobj_include_variable = 1
|
||||||
|
endif
|
||||||
|
|
||||||
" ( ) motions
|
" ( ) motions
|
||||||
" { } motions
|
" { } motions
|
||||||
" s for sentence
|
" s for sentence
|
||||||
@ -13,14 +17,14 @@ endif
|
|||||||
" < >
|
" < >
|
||||||
" t for tag
|
" t for tag
|
||||||
|
|
||||||
function! go#textobj#Function(mode)
|
function! go#textobj#Function(mode) abort
|
||||||
let offset = go#util#OffsetCursor()
|
let offset = go#util#OffsetCursor()
|
||||||
|
|
||||||
let fname = expand("%:p")
|
let fname = shellescape(expand("%:p"))
|
||||||
if &modified
|
if &modified
|
||||||
" Write current unsaved buffer to a temp file and use the modified content
|
" Write current unsaved buffer to a temp file and use the modified content
|
||||||
let l:tmpname = tempname()
|
let l:tmpname = tempname()
|
||||||
call writefile(getline(1, '$'), l:tmpname)
|
call writefile(go#util#GetLines(), l:tmpname)
|
||||||
let fname = l:tmpname
|
let fname = l:tmpname
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -36,8 +40,8 @@ function! go#textobj#Function(mode)
|
|||||||
let command .= " -parse-comments"
|
let command .= " -parse-comments"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let out = system(command)
|
let out = go#util#System(command)
|
||||||
if v:shell_error != 0
|
if go#util#ShellError() != 0
|
||||||
call go#util#EchoError(out)
|
call go#util#EchoError(out)
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
@ -60,6 +64,16 @@ function! go#textobj#Function(mode)
|
|||||||
" want's to include doc comments for function declarations
|
" want's to include doc comments for function declarations
|
||||||
if has_key(info, 'doc') && g:go_textobj_include_function_doc
|
if has_key(info, 'doc') && g:go_textobj_include_function_doc
|
||||||
call cursor(info.doc.line, info.doc.col)
|
call cursor(info.doc.line, info.doc.col)
|
||||||
|
elseif info['sig']['name'] == '' && g:go_textobj_include_variable
|
||||||
|
" one liner anonymous functions
|
||||||
|
if info.lbrace.line == info.rbrace.line
|
||||||
|
" jump to first nonblack char, to get the correct column
|
||||||
|
call cursor(info.lbrace.line, 0 )
|
||||||
|
normal! ^
|
||||||
|
call cursor(info.func.line, col("."))
|
||||||
|
else
|
||||||
|
call cursor(info.func.line, info.rbrace.col)
|
||||||
|
endif
|
||||||
else
|
else
|
||||||
call cursor(info.func.line, info.func.col)
|
call cursor(info.func.line, info.func.col)
|
||||||
endif
|
endif
|
||||||
@ -84,7 +98,7 @@ function! go#textobj#Function(mode)
|
|||||||
call cursor(info.rbrace.line-1, 1)
|
call cursor(info.rbrace.line-1, 1)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! go#textobj#FunctionJump(mode, direction)
|
function! go#textobj#FunctionJump(mode, direction) abort
|
||||||
" get count of the motion. This should be done before all the normal
|
" get count of the motion. This should be done before all the normal
|
||||||
" expressions below as those reset this value(because they have zero
|
" expressions below as those reset this value(because they have zero
|
||||||
" count!). We abstract -1 because the index starts from 0 in motion.
|
" count!). We abstract -1 because the index starts from 0 in motion.
|
||||||
@ -103,11 +117,11 @@ function! go#textobj#FunctionJump(mode, direction)
|
|||||||
|
|
||||||
let offset = go#util#OffsetCursor()
|
let offset = go#util#OffsetCursor()
|
||||||
|
|
||||||
let fname = expand("%:p")
|
let fname = shellescape(expand("%:p"))
|
||||||
if &modified
|
if &modified
|
||||||
" Write current unsaved buffer to a temp file and use the modified content
|
" Write current unsaved buffer to a temp file and use the modified content
|
||||||
let l:tmpname = tempname()
|
let l:tmpname = tempname()
|
||||||
call writefile(getline(1, '$'), l:tmpname)
|
call writefile(go#util#GetLines(), l:tmpname)
|
||||||
let fname = l:tmpname
|
let fname = l:tmpname
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -129,8 +143,8 @@ function! go#textobj#FunctionJump(mode, direction)
|
|||||||
let command .= " -parse-comments"
|
let command .= " -parse-comments"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let out = system(command)
|
let out = go#util#System(command)
|
||||||
if v:shell_error != 0
|
if go#util#ShellError() != 0
|
||||||
call go#util#EchoError(out)
|
call go#util#EchoError(out)
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
@ -177,4 +191,4 @@ function! go#textobj#FunctionJump(mode, direction)
|
|||||||
keepjumps call cursor(info.func.line, 1)
|
keepjumps call cursor(info.func.line, 1)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" vim:ts=2:sw=2:et
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
@ -1,38 +1,72 @@
|
|||||||
function! go#tool#Files()
|
" From "go list -h".
|
||||||
if go#util#IsWin()
|
function! go#tool#ValidFiles(...)
|
||||||
let command = 'go list -f "{{range $f := .GoFiles}}{{$.Dir}}\{{$f}}{{printf \"\n\"}}{{end}}{{range $f := .CgoFiles}}{{$.Dir}}\{{$f}}{{printf \"\n\"}}{{end}}"'
|
let l:list = ["GoFiles", "CgoFiles", "IgnoredGoFiles", "CFiles", "CXXFiles",
|
||||||
else
|
\ "MFiles", "HFiles", "FFiles", "SFiles", "SwigFiles", "SwigCXXFiles",
|
||||||
let command = "go list -f '{{range $f := .GoFiles}}{{$.Dir}}/{{$f}}{{printf \"\\n\"}}{{end}}{{range $f := .CgoFiles}}{{$.Dir}}/{{$f}}{{printf \"\\n\"}}{{end}}'"
|
\ "SysoFiles", "TestGoFiles", "XTestGoFiles"]
|
||||||
|
|
||||||
|
" Used as completion
|
||||||
|
if len(a:000) > 0
|
||||||
|
let l:list = filter(l:list, 'strpart(v:val, 0, len(a:1)) == a:1')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
return l:list
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! go#tool#Files(...) abort
|
||||||
|
if len(a:000) > 0
|
||||||
|
let source_files = a:000
|
||||||
|
else
|
||||||
|
let source_files = ['GoFiles']
|
||||||
|
endif
|
||||||
|
|
||||||
|
let combined = ''
|
||||||
|
for sf in source_files
|
||||||
|
" Strip dot in case people used ":GoFiles .GoFiles".
|
||||||
|
let sf = substitute(sf, '^\.', '', '')
|
||||||
|
|
||||||
|
" Make sure the passed options are valid.
|
||||||
|
if index(go#tool#ValidFiles(), sf) == -1
|
||||||
|
echoerr "unknown source file variable: " . sf
|
||||||
|
endif
|
||||||
|
|
||||||
|
if go#util#IsWin()
|
||||||
|
let combined .= '{{range $f := .' . sf . '}}{{$.Dir}}\{{$f}}{{printf \"\n\"}}{{end}}{{range $f := .CgoFiles}}{{$.Dir}}\{{$f}}{{printf \"\n\"}}{{end}}'
|
||||||
|
else
|
||||||
|
let combined .= "{{range $f := ." . sf . "}}{{$.Dir}}/{{$f}}{{printf \"\\n\"}}{{end}}{{range $f := .CgoFiles}}{{$.Dir}}/{{$f}}{{printf \"\\n\"}}{{end}}"
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
|
||||||
|
let out = go#tool#ExecuteInDir('go list -f ' . shellescape(combined))
|
||||||
|
return split(out, '\n')
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! go#tool#Deps() abort
|
||||||
|
if go#util#IsWin()
|
||||||
|
let format = '{{range $f := .Deps}}{{$f}}{{printf \"\n\"}}{{end}}'
|
||||||
|
else
|
||||||
|
let format = "{{range $f := .Deps}}{{$f}}\n{{end}}"
|
||||||
|
endif
|
||||||
|
let command = 'go list -f '.shellescape(format)
|
||||||
let out = go#tool#ExecuteInDir(command)
|
let out = go#tool#ExecuteInDir(command)
|
||||||
return split(out, '\n')
|
return split(out, '\n')
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! go#tool#Deps()
|
function! go#tool#Imports() abort
|
||||||
if go#util#IsWin()
|
|
||||||
let command = 'go list -f "{{range $f := .Deps}}{{$f}}{{printf \"\n\"}}{{end}}"'
|
|
||||||
else
|
|
||||||
let command = "go list -f $'{{range $f := .Deps}}{{$f}}\n{{end}}'"
|
|
||||||
endif
|
|
||||||
let out = go#tool#ExecuteInDir(command)
|
|
||||||
return split(out, '\n')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! go#tool#Imports()
|
|
||||||
let imports = {}
|
let imports = {}
|
||||||
if go#util#IsWin()
|
if go#util#IsWin()
|
||||||
let command = 'go list -f "{{range $f := .Imports}}{{$f}}{{printf \"\n\"}}{{end}}"'
|
let format = '{{range $f := .Imports}}{{$f}}{{printf \"\n\"}}{{end}}'
|
||||||
else
|
else
|
||||||
let command = "go list -f $'{{range $f := .Imports}}{{$f}}\n{{end}}'"
|
let format = "{{range $f := .Imports}}{{$f}}{{printf \"\\n\"}}{{end}}"
|
||||||
endif
|
endif
|
||||||
|
let command = 'go list -f '.shellescape(format)
|
||||||
let out = go#tool#ExecuteInDir(command)
|
let out = go#tool#ExecuteInDir(command)
|
||||||
if v:shell_error
|
if go#util#ShellError() != 0
|
||||||
echo out
|
echo out
|
||||||
return imports
|
return imports
|
||||||
endif
|
endif
|
||||||
|
|
||||||
for package_path in split(out, '\n')
|
for package_path in split(out, '\n')
|
||||||
let cmd = "go list -f {{.Name}} " . package_path
|
let cmd = "go list -f '{{.Name}}' " . shellescape(package_path)
|
||||||
let package_name = substitute(go#tool#ExecuteInDir(cmd), '\n$', '', '')
|
let package_name = substitute(go#tool#ExecuteInDir(cmd), '\n$', '', '')
|
||||||
let imports[package_name] = package_path
|
let imports[package_name] = package_path
|
||||||
endfor
|
endfor
|
||||||
@ -40,7 +74,28 @@ function! go#tool#Imports()
|
|||||||
return imports
|
return imports
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! go#tool#ParseErrors(lines)
|
function! go#tool#Info(auto) abort
|
||||||
|
let l:mode = get(g:, 'go_info_mode', 'gocode')
|
||||||
|
if l:mode == 'gocode'
|
||||||
|
call go#complete#Info(a:auto)
|
||||||
|
elseif l:mode == 'guru'
|
||||||
|
call go#guru#DescribeInfo()
|
||||||
|
else
|
||||||
|
call go#util#EchoError('go_info_mode value: '. l:mode .' is not valid. Valid values are: [gocode, guru]')
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! go#tool#PackageName() abort
|
||||||
|
let command = "go list -f \"{{.Name}}\""
|
||||||
|
let out = go#tool#ExecuteInDir(command)
|
||||||
|
if go#util#ShellError() != 0
|
||||||
|
return -1
|
||||||
|
endif
|
||||||
|
|
||||||
|
return split(out, '\n')[0]
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! go#tool#ParseErrors(lines) abort
|
||||||
let errors = []
|
let errors = []
|
||||||
|
|
||||||
for line in a:lines
|
for line in a:lines
|
||||||
@ -51,7 +106,7 @@ function! go#tool#ParseErrors(lines)
|
|||||||
call add(errors, {"text": fatalerrors[1]})
|
call add(errors, {"text": fatalerrors[1]})
|
||||||
elseif !empty(tokens)
|
elseif !empty(tokens)
|
||||||
" strip endlines of form ^M
|
" strip endlines of form ^M
|
||||||
let out=substitute(tokens[3], '\r$', '', '')
|
let out = substitute(tokens[3], '\r$', '', '')
|
||||||
|
|
||||||
call add(errors, {
|
call add(errors, {
|
||||||
\ "filename" : fnamemodify(tokens[1], ':p'),
|
\ "filename" : fnamemodify(tokens[1], ':p'),
|
||||||
@ -72,7 +127,7 @@ endfunction
|
|||||||
|
|
||||||
"FilterValids filters the given items with only items that have a valid
|
"FilterValids filters the given items with only items that have a valid
|
||||||
"filename. Any non valid filename is filtered out.
|
"filename. Any non valid filename is filtered out.
|
||||||
function! go#tool#FilterValids(items)
|
function! go#tool#FilterValids(items) abort
|
||||||
" Remove any nonvalid filename from the location list to avoid opening an
|
" Remove any nonvalid filename from the location list to avoid opening an
|
||||||
" empty buffer. See https://github.com/fatih/vim-go/issues/287 for
|
" empty buffer. See https://github.com/fatih/vim-go/issues/287 for
|
||||||
" details.
|
" details.
|
||||||
@ -107,49 +162,57 @@ function! go#tool#FilterValids(items)
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! go#tool#ExecuteInDir(cmd) abort
|
function! go#tool#ExecuteInDir(cmd) abort
|
||||||
let old_gopath = $GOPATH
|
" Verify that the directory actually exists. If the directory does not
|
||||||
let $GOPATH = go#path#Detect()
|
" exist, then assume that the a:cmd should not be executed. Callers expect
|
||||||
|
" to check v:shell_error (via go#util#ShellError()), so execute a command
|
||||||
|
" that will return an error as if a:cmd was run and exited with an error.
|
||||||
|
" This helps avoid errors when working with plugins that use virtual files
|
||||||
|
" that don't actually exist on the file system (e.g. vim-fugitive's
|
||||||
|
" GitDiff).
|
||||||
|
if !isdirectory(expand("%:p:h"))
|
||||||
|
let [out, err] = go#util#Exec(["false"])
|
||||||
|
return ''
|
||||||
|
endif
|
||||||
|
|
||||||
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
||||||
let dir = getcwd()
|
let dir = getcwd()
|
||||||
try
|
try
|
||||||
execute cd . fnameescape(expand("%:p:h"))
|
execute cd . fnameescape(expand("%:p:h"))
|
||||||
let out = system(a:cmd)
|
let out = go#util#System(a:cmd)
|
||||||
finally
|
finally
|
||||||
execute cd . fnameescape(dir)
|
execute cd . fnameescape(dir)
|
||||||
endtry
|
endtry
|
||||||
|
|
||||||
let $GOPATH = old_gopath
|
|
||||||
return out
|
return out
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Exists checks whether the given importpath exists or not. It returns 0 if
|
" Exists checks whether the given importpath exists or not. It returns 0 if
|
||||||
" the importpath exists under GOPATH.
|
" the importpath exists under GOPATH.
|
||||||
function! go#tool#Exists(importpath)
|
function! go#tool#Exists(importpath) abort
|
||||||
let command = "go list ". a:importpath
|
let command = "go list ". a:importpath
|
||||||
let out = go#tool#ExecuteInDir(command)
|
let out = go#tool#ExecuteInDir(command)
|
||||||
|
|
||||||
if v:shell_error
|
if go#util#ShellError() != 0
|
||||||
return -1
|
return -1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
" following two functions are from: https://github.com/mattn/gist-vim
|
" following two functions are from: https://github.com/mattn/gist-vim
|
||||||
" thanks @mattn
|
" thanks @mattn
|
||||||
function! s:get_browser_command()
|
function! s:get_browser_command() abort
|
||||||
let go_play_browser_command = get(g:, 'go_play_browser_command', '')
|
let go_play_browser_command = get(g:, 'go_play_browser_command', '')
|
||||||
if go_play_browser_command == ''
|
if go_play_browser_command == ''
|
||||||
if go#util#IsWin()
|
if go#util#IsWin()
|
||||||
let go_play_browser_command = '!start rundll32 url.dll,FileProtocolHandler %URL%'
|
let go_play_browser_command = '!start rundll32 url.dll,FileProtocolHandler %URL%'
|
||||||
elseif has('mac') || has('macunix') || has('gui_macvim') || system('uname') =~? '^darwin'
|
elseif go#util#IsMac()
|
||||||
let go_play_browser_command = 'open %URL%'
|
let go_play_browser_command = 'open %URL%'
|
||||||
elseif executable('xdg-open')
|
elseif executable('xdg-open')
|
||||||
let go_play_browser_command = 'xdg-open %URL%'
|
let go_play_browser_command = 'xdg-open %URL%'
|
||||||
elseif executable('firefox')
|
elseif executable('firefox')
|
||||||
let go_play_browser_command = 'firefox %URL% &'
|
let go_play_browser_command = 'firefox %URL% &'
|
||||||
|
elseif executable('chromium')
|
||||||
|
let go_play_browser_command = 'chromium %URL% &'
|
||||||
else
|
else
|
||||||
let go_play_browser_command = ''
|
let go_play_browser_command = ''
|
||||||
endif
|
endif
|
||||||
@ -157,7 +220,7 @@ function! s:get_browser_command()
|
|||||||
return go_play_browser_command
|
return go_play_browser_command
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! go#tool#OpenBrowser(url)
|
function! go#tool#OpenBrowser(url) abort
|
||||||
let cmd = s:get_browser_command()
|
let cmd = s:get_browser_command()
|
||||||
if len(cmd) == 0
|
if len(cmd) == 0
|
||||||
redraw
|
redraw
|
||||||
@ -168,15 +231,15 @@ function! go#tool#OpenBrowser(url)
|
|||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
if cmd =~ '^!'
|
if cmd =~ '^!'
|
||||||
let cmd = substitute(cmd, '%URL%', '\=shellescape(a:url)', 'g')
|
let cmd = substitute(cmd, '%URL%', '\=escape(shellescape(a:url),"#")', 'g')
|
||||||
silent! exec cmd
|
silent! exec cmd
|
||||||
elseif cmd =~ '^:[A-Z]'
|
elseif cmd =~ '^:[A-Z]'
|
||||||
let cmd = substitute(cmd, '%URL%', '\=a:url', 'g')
|
let cmd = substitute(cmd, '%URL%', '\=escape(a:url,"#")', 'g')
|
||||||
exec cmd
|
exec cmd
|
||||||
else
|
else
|
||||||
let cmd = substitute(cmd, '%URL%', '\=shellescape(a:url)', 'g')
|
let cmd = substitute(cmd, '%URL%', '\=shellescape(a:url)', 'g')
|
||||||
call system(cmd)
|
call go#util#System(cmd)
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
23
autoload/go/tool_test.vim
Normal file
23
autoload/go/tool_test.vim
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
func! Test_ExecuteInDir() abort
|
||||||
|
let l:tmp = gotest#write_file('a/a.go', ['package a'])
|
||||||
|
try
|
||||||
|
let l:out = go#tool#ExecuteInDir("pwd")
|
||||||
|
call assert_equal(l:tmp . "/src/a\n", l:out)
|
||||||
|
finally
|
||||||
|
call delete(l:tmp, 'rf')
|
||||||
|
endtry
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func! Test_ExecuteInDir_nodir() abort
|
||||||
|
let l:tmp = go#util#tempdir("executeindir")
|
||||||
|
exe ':e ' . l:tmp . '/new-dir/a'
|
||||||
|
|
||||||
|
try
|
||||||
|
let l:out = go#tool#ExecuteInDir("pwd")
|
||||||
|
call assert_equal('', l:out)
|
||||||
|
finally
|
||||||
|
call delete(l:tmp, 'rf')
|
||||||
|
endtry
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
@ -1,7 +1,12 @@
|
|||||||
let s:buf_nr = -1
|
let s:buf_nr = -1
|
||||||
|
|
||||||
"OpenWindow opens a new scratch window and put's the content into the window
|
"OpenWindow opens a new scratch window and put's the content into the window
|
||||||
function! go#ui#OpenWindow(title, content)
|
function! go#ui#OpenWindow(title, content, filetype) abort
|
||||||
|
" Ensure there's only one return window in this session/tabpage
|
||||||
|
call go#util#Windo("unlet! w:vim_go_return_window")
|
||||||
|
" Mark the window we're leaving as such
|
||||||
|
let w:vim_go_return_window = 1
|
||||||
|
|
||||||
" reuse existing buffer window if it exists otherwise create a new one
|
" reuse existing buffer window if it exists otherwise create a new one
|
||||||
if !bufexists(s:buf_nr)
|
if !bufexists(s:buf_nr)
|
||||||
execute 'botright new'
|
execute 'botright new'
|
||||||
@ -14,24 +19,21 @@ function! go#ui#OpenWindow(title, content)
|
|||||||
execute bufwinnr(s:buf_nr) . 'wincmd w'
|
execute bufwinnr(s:buf_nr) . 'wincmd w'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
" Resize window to content length
|
||||||
|
exe 'resize' . len(a:content)
|
||||||
|
|
||||||
" Keep minimum height to 10, if there is more just increase it that it
|
execute "setlocal filetype=".a:filetype
|
||||||
" occupies all results
|
|
||||||
let buffer_height = 10
|
|
||||||
if len(a:content) < buffer_height
|
|
||||||
exe 'resize ' . buffer_height
|
|
||||||
else
|
|
||||||
exe 'resize ' . len(a:content)
|
|
||||||
endif
|
|
||||||
|
|
||||||
" some sane default values for a readonly buffer
|
" some sane default values for a readonly buffer
|
||||||
setlocal filetype=vimgo
|
|
||||||
setlocal bufhidden=delete
|
setlocal bufhidden=delete
|
||||||
setlocal buftype=nofile
|
setlocal buftype=nofile
|
||||||
setlocal noswapfile
|
setlocal noswapfile
|
||||||
setlocal nobuflisted
|
setlocal nobuflisted
|
||||||
setlocal winfixheight
|
setlocal winfixheight
|
||||||
setlocal cursorline " make it easy to distinguish
|
setlocal cursorline " make it easy to distinguish
|
||||||
|
setlocal nonumber
|
||||||
|
setlocal norelativenumber
|
||||||
|
setlocal showbreak=""
|
||||||
|
|
||||||
" we need this to purge the buffer content
|
" we need this to purge the buffer content
|
||||||
setlocal modifiable
|
setlocal modifiable
|
||||||
@ -47,23 +49,45 @@ function! go#ui#OpenWindow(title, content)
|
|||||||
|
|
||||||
" set it back to non modifiable
|
" set it back to non modifiable
|
||||||
setlocal nomodifiable
|
setlocal nomodifiable
|
||||||
|
|
||||||
|
" Remove the '... [New File]' message line from the command line
|
||||||
|
echon
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
function! go#ui#GetReturnWindow() abort
|
||||||
|
for l:wn in range(1, winnr("$"))
|
||||||
|
if !empty(getwinvar(l:wn, "vim_go_return_window"))
|
||||||
|
return l:wn
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
endfunction
|
||||||
|
|
||||||
" CloseWindow closes the current window
|
" CloseWindow closes the current window
|
||||||
function! go#ui#CloseWindow()
|
function! go#ui#CloseWindow() abort
|
||||||
close
|
" Close any window associated with the ui buffer, if it's there
|
||||||
echo ""
|
if bufexists(s:buf_nr)
|
||||||
|
let ui_window_number = bufwinnr(s:buf_nr)
|
||||||
|
if ui_window_number != -1
|
||||||
|
execute ui_window_number . 'close'
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
"return to original window, if it's there
|
||||||
|
let l:rw = go#ui#GetReturnWindow()
|
||||||
|
if !empty(l:rw)
|
||||||
|
execute l:rw . 'wincmd w'
|
||||||
|
unlet! w:vim_go_return_window
|
||||||
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" OpenDefinition parses the current line and jumps to it by openening a new
|
" OpenDefinition parses the current line and jumps to it by openening a new
|
||||||
" tab
|
" tab
|
||||||
function! go#ui#OpenDefinition(filter)
|
function! go#ui#OpenDefinition(filter) abort
|
||||||
let curline = getline('.')
|
let curline = getline('.')
|
||||||
|
|
||||||
" don't touch our first line or any blank line
|
" don't touch our first line or any blank line
|
||||||
if curline =~ a:filter || curline =~ "^$"
|
if curline =~ a:filter || curline =~ "^$"
|
||||||
" supress information about calling this function
|
" suppress information about calling this function
|
||||||
echo ""
|
echo ""
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
@ -87,3 +111,4 @@ function! go#ui#OpenDefinition(filter)
|
|||||||
norm! zz
|
norm! zz
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
" PathSep returns the appropriate OS specific path separator.
|
" PathSep returns the appropriate OS specific path separator.
|
||||||
function! go#util#PathSep()
|
function! go#util#PathSep() abort
|
||||||
if go#util#IsWin()
|
if go#util#IsWin()
|
||||||
return '\'
|
return '\'
|
||||||
endif
|
endif
|
||||||
@ -7,7 +7,7 @@ function! go#util#PathSep()
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" PathListSep returns the appropriate OS specific path list separator.
|
" PathListSep returns the appropriate OS specific path list separator.
|
||||||
function! go#util#PathListSep()
|
function! go#util#PathListSep() abort
|
||||||
if go#util#IsWin()
|
if go#util#IsWin()
|
||||||
return ";"
|
return ";"
|
||||||
endif
|
endif
|
||||||
@ -15,7 +15,7 @@ function! go#util#PathListSep()
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" LineEnding returns the correct line ending, based on the current fileformat
|
" LineEnding returns the correct line ending, based on the current fileformat
|
||||||
function! go#util#LineEnding()
|
function! go#util#LineEnding() abort
|
||||||
if &fileformat == 'dos'
|
if &fileformat == 'dos'
|
||||||
return "\r\n"
|
return "\r\n"
|
||||||
elseif &fileformat == 'mac'
|
elseif &fileformat == 'mac'
|
||||||
@ -25,8 +25,14 @@ function! go#util#LineEnding()
|
|||||||
return "\n"
|
return "\n"
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
" Join joins any number of path elements into a single path, adding a
|
||||||
|
" Separator if necessary and returns the result
|
||||||
|
function! go#util#Join(...) abort
|
||||||
|
return join(a:000, go#util#PathSep())
|
||||||
|
endfunction
|
||||||
|
|
||||||
" IsWin returns 1 if current OS is Windows or 0 otherwise
|
" IsWin returns 1 if current OS is Windows or 0 otherwise
|
||||||
function! go#util#IsWin()
|
function! go#util#IsWin() abort
|
||||||
let win = ['win16', 'win32', 'win64', 'win95']
|
let win = ['win16', 'win32', 'win64', 'win95']
|
||||||
for w in win
|
for w in win
|
||||||
if (has(w))
|
if (has(w))
|
||||||
@ -37,9 +43,136 @@ function! go#util#IsWin()
|
|||||||
return 0
|
return 0
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
" IsMac returns 1 if current OS is macOS or 0 otherwise.
|
||||||
|
function! go#util#IsMac() abort
|
||||||
|
return has('mac') ||
|
||||||
|
\ has('macunix') ||
|
||||||
|
\ has('gui_macvim') ||
|
||||||
|
\ go#util#System('uname') =~? '^darwin'
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Checks if using:
|
||||||
|
" 1) Windows system,
|
||||||
|
" 2) And has cygpath executable,
|
||||||
|
" 3) And uses *sh* as 'shell'
|
||||||
|
function! go#util#IsUsingCygwinShell()
|
||||||
|
return go#util#IsWin() && executable('cygpath') && &shell =~ '.*sh.*'
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! go#util#has_job() abort
|
||||||
|
" job was introduced in 7.4.xxx however there are multiple bug fixes and one
|
||||||
|
" of the latest is 8.0.0087 which is required for a stable async API.
|
||||||
|
return has('job') && has("patch-8.0.0087")
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
let s:env_cache = {}
|
||||||
|
|
||||||
|
" env returns the go environment variable for the given key. Where key can be
|
||||||
|
" GOARCH, GOOS, GOROOT, etc... It caches the result and returns the cached
|
||||||
|
" version.
|
||||||
|
function! go#util#env(key) abort
|
||||||
|
let l:key = tolower(a:key)
|
||||||
|
if has_key(s:env_cache, l:key)
|
||||||
|
return s:env_cache[l:key]
|
||||||
|
endif
|
||||||
|
|
||||||
|
if executable('go')
|
||||||
|
let l:var = call('go#util#'.l:key, [])
|
||||||
|
if go#util#ShellError() != 0
|
||||||
|
call go#util#EchoError(printf("'go env %s' failed", toupper(l:key)))
|
||||||
|
return ''
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
let l:var = eval("$".toupper(a:key))
|
||||||
|
endif
|
||||||
|
|
||||||
|
let s:env_cache[l:key] = l:var
|
||||||
|
return l:var
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" goarch returns 'go env GOARCH'. This is an internal function and shouldn't
|
||||||
|
" be used. Instead use 'go#util#env("goarch")'
|
||||||
|
function! go#util#goarch() abort
|
||||||
|
return substitute(go#util#System('go env GOARCH'), '\n', '', 'g')
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" goos returns 'go env GOOS'. This is an internal function and shouldn't
|
||||||
|
" be used. Instead use 'go#util#env("goos")'
|
||||||
|
function! go#util#goos() abort
|
||||||
|
return substitute(go#util#System('go env GOOS'), '\n', '', 'g')
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" goroot returns 'go env GOROOT'. This is an internal function and shouldn't
|
||||||
|
" be used. Instead use 'go#util#env("goroot")'
|
||||||
|
function! go#util#goroot() abort
|
||||||
|
return substitute(go#util#System('go env GOROOT'), '\n', '', 'g')
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" gopath returns 'go env GOPATH'. This is an internal function and shouldn't
|
||||||
|
" be used. Instead use 'go#util#env("gopath")'
|
||||||
|
function! go#util#gopath() abort
|
||||||
|
return substitute(go#util#System('go env GOPATH'), '\n', '', 'g')
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! go#util#osarch() abort
|
||||||
|
return go#util#env("goos") . '_' . go#util#env("goarch")
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Run a shell command.
|
||||||
|
"
|
||||||
|
" It will temporary set the shell to /bin/sh for Unix-like systems if possible,
|
||||||
|
" so that we always use a standard POSIX-compatible Bourne shell (and not e.g.
|
||||||
|
" csh, fish, etc.) See #988 and #1276.
|
||||||
|
function! s:system(cmd, ...) abort
|
||||||
|
" Preserve original shell and shellredir values
|
||||||
|
let l:shell = &shell
|
||||||
|
let l:shellredir = &shellredir
|
||||||
|
|
||||||
|
if !go#util#IsWin() && executable('/bin/sh')
|
||||||
|
set shell=/bin/sh shellredir=>%s\ 2>&1
|
||||||
|
endif
|
||||||
|
|
||||||
|
try
|
||||||
|
return call('system', [a:cmd] + a:000)
|
||||||
|
finally
|
||||||
|
" Restore original values
|
||||||
|
let &shell = l:shell
|
||||||
|
let &shellredir = l:shellredir
|
||||||
|
endtry
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" System runs a shell command "str". Every arguments after "str" is passed to
|
||||||
|
" stdin.
|
||||||
|
function! go#util#System(str, ...) abort
|
||||||
|
return call('s:system', [a:str] + a:000)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Exec runs a shell command "cmd", which must be a list, one argument per item.
|
||||||
|
" Every list entry will be automatically shell-escaped
|
||||||
|
" Every other argument is passed to stdin.
|
||||||
|
function! go#util#Exec(cmd, ...) abort
|
||||||
|
if len(a:cmd) == 0
|
||||||
|
call go#util#EchoError("go#util#Exec() called with empty a:cmd")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
" CheckBinPath will show a warning for us.
|
||||||
|
let l:bin = go#path#CheckBinPath(a:cmd[0])
|
||||||
|
if empty(l:bin)
|
||||||
|
return ["", 1]
|
||||||
|
endif
|
||||||
|
|
||||||
|
let l:out = call('s:system', [go#util#Shelljoin([l:bin] + a:cmd[1:])] + a:000)
|
||||||
|
return [l:out, go#util#ShellError()]
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! go#util#ShellError() abort
|
||||||
|
return v:shell_error
|
||||||
|
endfunction
|
||||||
|
|
||||||
" StripPath strips the path's last character if it's a path separator.
|
" StripPath strips the path's last character if it's a path separator.
|
||||||
" example: '/foo/bar/' -> '/foo/bar'
|
" example: '/foo/bar/' -> '/foo/bar'
|
||||||
function! go#util#StripPathSep(path)
|
function! go#util#StripPathSep(path) abort
|
||||||
let last_char = strlen(a:path) - 1
|
let last_char = strlen(a:path) - 1
|
||||||
if a:path[last_char] == go#util#PathSep()
|
if a:path[last_char] == go#util#PathSep()
|
||||||
return strpart(a:path, 0, last_char)
|
return strpart(a:path, 0, last_char)
|
||||||
@ -50,13 +183,13 @@ endfunction
|
|||||||
|
|
||||||
" StripTrailingSlash strips the trailing slash from the given path list.
|
" StripTrailingSlash strips the trailing slash from the given path list.
|
||||||
" example: ['/foo/bar/'] -> ['/foo/bar']
|
" example: ['/foo/bar/'] -> ['/foo/bar']
|
||||||
function! go#util#StripTrailingSlash(paths)
|
function! go#util#StripTrailingSlash(paths) abort
|
||||||
return map(copy(a:paths), 'go#util#StripPathSep(v:val)')
|
return map(copy(a:paths), 'go#util#StripPathSep(v:val)')
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Shelljoin returns a shell-safe string representation of arglist. The
|
" Shelljoin returns a shell-safe string representation of arglist. The
|
||||||
" {special} argument of shellescape() may optionally be passed.
|
" {special} argument of shellescape() may optionally be passed.
|
||||||
function! go#util#Shelljoin(arglist, ...)
|
function! go#util#Shelljoin(arglist, ...) abort
|
||||||
try
|
try
|
||||||
let ssl_save = &shellslash
|
let ssl_save = &shellslash
|
||||||
set noshellslash
|
set noshellslash
|
||||||
@ -70,9 +203,19 @@ function! go#util#Shelljoin(arglist, ...)
|
|||||||
endtry
|
endtry
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
fu! go#util#Shellescape(arg)
|
||||||
|
try
|
||||||
|
let ssl_save = &shellslash
|
||||||
|
set noshellslash
|
||||||
|
return shellescape(a:arg)
|
||||||
|
finally
|
||||||
|
let &shellslash = ssl_save
|
||||||
|
endtry
|
||||||
|
endf
|
||||||
|
|
||||||
" Shelllist returns a shell-safe representation of the items in the given
|
" Shelllist returns a shell-safe representation of the items in the given
|
||||||
" arglist. The {special} argument of shellescape() may optionally be passed.
|
" arglist. The {special} argument of shellescape() may optionally be passed.
|
||||||
function! go#util#Shelllist(arglist, ...)
|
function! go#util#Shelllist(arglist, ...) abort
|
||||||
try
|
try
|
||||||
let ssl_save = &shellslash
|
let ssl_save = &shellslash
|
||||||
set noshellslash
|
set noshellslash
|
||||||
@ -86,7 +229,7 @@ function! go#util#Shelllist(arglist, ...)
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Returns the byte offset for line and column
|
" Returns the byte offset for line and column
|
||||||
function! go#util#Offset(line, col)
|
function! go#util#Offset(line, col) abort
|
||||||
if &encoding != 'utf-8'
|
if &encoding != 'utf-8'
|
||||||
let sep = go#util#LineEnding()
|
let sep = go#util#LineEnding()
|
||||||
let buf = a:line == 1 ? '' : (join(getline(1, a:line-1), sep) . sep)
|
let buf = a:line == 1 ? '' : (join(getline(1, a:line-1), sep) . sep)
|
||||||
@ -97,27 +240,159 @@ function! go#util#Offset(line, col)
|
|||||||
endfunction
|
endfunction
|
||||||
"
|
"
|
||||||
" Returns the byte offset for the cursor
|
" Returns the byte offset for the cursor
|
||||||
function! go#util#OffsetCursor()
|
function! go#util#OffsetCursor() abort
|
||||||
return go#util#Offset(line('.'), col('.'))
|
return go#util#Offset(line('.'), col('.'))
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" TODO(arslan): I couldn't parameterize the highlight types. Check if we can
|
" Windo is like the built-in :windo, only it returns to the window the command
|
||||||
" simplify the following functions
|
" was issued from
|
||||||
|
function! go#util#Windo(command) abort
|
||||||
|
let s:currentWindow = winnr()
|
||||||
|
try
|
||||||
|
execute "windo " . a:command
|
||||||
|
finally
|
||||||
|
execute s:currentWindow. "wincmd w"
|
||||||
|
unlet s:currentWindow
|
||||||
|
endtry
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" snippetcase converts the given word to given preferred snippet setting type
|
||||||
|
" case.
|
||||||
|
function! go#util#snippetcase(word) abort
|
||||||
|
let l:snippet_case = get(g:, 'go_addtags_transform', "snakecase")
|
||||||
|
if l:snippet_case == "snakecase"
|
||||||
|
return go#util#snakecase(a:word)
|
||||||
|
elseif l:snippet_case == "camelcase"
|
||||||
|
return go#util#camelcase(a:word)
|
||||||
|
else
|
||||||
|
return a:word " do nothing
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" snakecase converts a string to snake case. i.e: FooBar -> foo_bar
|
||||||
|
" Copied from tpope/vim-abolish
|
||||||
|
function! go#util#snakecase(word) abort
|
||||||
|
let word = substitute(a:word, '::', '/', 'g')
|
||||||
|
let word = substitute(word, '\(\u\+\)\(\u\l\)', '\1_\2', 'g')
|
||||||
|
let word = substitute(word, '\(\l\|\d\)\(\u\)', '\1_\2', 'g')
|
||||||
|
let word = substitute(word, '[.-]', '_', 'g')
|
||||||
|
let word = tolower(word)
|
||||||
|
return word
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" camelcase converts a string to camel case. e.g. FooBar or foo_bar will become
|
||||||
|
" fooBar.
|
||||||
|
" Copied from tpope/vim-abolish.
|
||||||
|
function! go#util#camelcase(word) abort
|
||||||
|
let word = substitute(a:word, '-', '_', 'g')
|
||||||
|
if word !~# '_' && word =~# '\l'
|
||||||
|
return substitute(word, '^.', '\l&', '')
|
||||||
|
else
|
||||||
|
return substitute(word, '\C\(_\)\=\(.\)', '\=submatch(1)==""?tolower(submatch(2)) : toupper(submatch(2))','g')
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" pascalcase converts a string to 'PascalCase'. e.g. fooBar or foo_bar will
|
||||||
|
" become FooBar.
|
||||||
|
function! go#util#pascalcase(word) abort
|
||||||
|
let word = go#util#camelcase(a:word)
|
||||||
|
return toupper(word[0]) . word[1:]
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Echo a message to the screen and highlight it with the group in a:hi.
|
||||||
|
"
|
||||||
|
" The message can be a list or string; every line with be :echomsg'd separately.
|
||||||
|
function! s:echo(msg, hi)
|
||||||
|
let l:msg = []
|
||||||
|
if type(a:msg) != type([])
|
||||||
|
let l:msg = split(a:msg, "\n")
|
||||||
|
else
|
||||||
|
let l:msg = a:msg
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Tabs display as ^I or <09>, so manually expand them.
|
||||||
|
let l:msg = map(l:msg, 'substitute(v:val, "\t", " ", "")')
|
||||||
|
|
||||||
|
exe 'echohl ' . a:hi
|
||||||
|
for line in l:msg
|
||||||
|
echom "vim-go: " . line
|
||||||
|
endfor
|
||||||
|
echohl None
|
||||||
|
endfunction
|
||||||
|
|
||||||
function! go#util#EchoSuccess(msg)
|
function! go#util#EchoSuccess(msg)
|
||||||
redraws! | echon "vim-go: " | echohl Function | echon a:msg | echohl None
|
call s:echo(a:msg, 'Function')
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! go#util#EchoError(msg)
|
function! go#util#EchoError(msg)
|
||||||
redraws! | echon "vim-go: " | echohl ErrorMsg | echon a:msg | echohl None
|
call s:echo(a:msg, 'ErrorMsg')
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! go#util#EchoWarning(msg)
|
function! go#util#EchoWarning(msg)
|
||||||
redraws! | echon "vim-go: " | echohl WarningMsg | echon a:msg | echohl None
|
call s:echo(a:msg, 'WarningMsg')
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! go#util#EchoProgress(msg)
|
function! go#util#EchoProgress(msg)
|
||||||
redraws! | echon "vim-go: " | echohl Identifier | echon a:msg | echohl None
|
call s:echo(a:msg, 'Identifier')
|
||||||
|
endfunction
|
||||||
|
function! go#util#EchoInfo(msg)
|
||||||
|
call s:echo(a:msg, 'Debug')
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
" Get all lines in the buffer as a a list.
|
||||||
|
function! go#util#GetLines()
|
||||||
|
let buf = getline(1, '$')
|
||||||
|
if &encoding != 'utf-8'
|
||||||
|
let buf = map(buf, 'iconv(v:val, &encoding, "utf-8")')
|
||||||
|
endif
|
||||||
|
if &l:fileformat == 'dos'
|
||||||
|
" XXX: line2byte() depend on 'fileformat' option.
|
||||||
|
" so if fileformat is 'dos', 'buf' must include '\r'.
|
||||||
|
let buf = map(buf, 'v:val."\r"')
|
||||||
|
endif
|
||||||
|
return buf
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Convert the current buffer to the "archive" format of
|
||||||
|
" golang.org/x/tools/go/buildutil:
|
||||||
|
" https://godoc.org/golang.org/x/tools/go/buildutil#ParseOverlayArchive
|
||||||
|
"
|
||||||
|
" > The archive consists of a series of files. Each file consists of a name, a
|
||||||
|
" > decimal file size and the file contents, separated by newlinews. No newline
|
||||||
|
" > follows after the file contents.
|
||||||
|
function! go#util#archive()
|
||||||
|
let l:buffer = join(go#util#GetLines(), "\n")
|
||||||
|
return expand("%:p:gs!\\!/!") . "\n" . strlen(l:buffer) . "\n" . l:buffer
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
" Make a named temporary directory which starts with "prefix".
|
||||||
|
"
|
||||||
|
" Unfortunately Vim's tempname() is not portable enough across various systems;
|
||||||
|
" see: https://github.com/mattn/vim-go/pull/3#discussion_r138084911
|
||||||
|
function! go#util#tempdir(prefix) abort
|
||||||
|
" See :help tempfile
|
||||||
|
if go#util#IsWin()
|
||||||
|
let l:dirs = [$TMP, $TEMP, 'c:\tmp', 'c:\temp']
|
||||||
|
else
|
||||||
|
let l:dirs = [$TMPDIR, '/tmp', './', $HOME]
|
||||||
|
endif
|
||||||
|
|
||||||
|
let l:dir = ''
|
||||||
|
for l:d in dirs
|
||||||
|
if !empty(l:d) && filewritable(l:d) == 2
|
||||||
|
let l:dir = l:d
|
||||||
|
break
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
|
||||||
|
if l:dir == ''
|
||||||
|
echoerr 'Unable to find directory to store temporary directory in'
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Not great randomness, but "good enough" for our purpose here.
|
||||||
|
let l:rnd = sha256(printf('%s%s', localtime(), fnamemodify(bufname(''), ":p")))
|
||||||
|
let l:tmp = printf("%s/%s%s", l:dir, a:prefix, l:rnd)
|
||||||
|
call mkdir(l:tmp, 'p', 0700)
|
||||||
|
return l:tmp
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
@ -1,21 +0,0 @@
|
|||||||
"Check if has vimproc
|
|
||||||
function! go#vimproc#has_vimproc()
|
|
||||||
if !exists('g:go#use_vimproc')
|
|
||||||
if go#util#IsWin()
|
|
||||||
try
|
|
||||||
call vimproc#version()
|
|
||||||
let exists_vimproc = 1
|
|
||||||
catch
|
|
||||||
let exists_vimproc = 0
|
|
||||||
endtry
|
|
||||||
else
|
|
||||||
let exists_vimproc = 0
|
|
||||||
endif
|
|
||||||
|
|
||||||
let g:go#use_vimproc = exists_vimproc
|
|
||||||
endif
|
|
||||||
|
|
||||||
return g:go#use_vimproc
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
|
||||||
105
autoload/gotest.vim
Normal file
105
autoload/gotest.vim
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
" Write a Go file to a temporary directory and append this directory to $GOPATH.
|
||||||
|
"
|
||||||
|
" The file will written to a:path, which is relative to the temporary directory,
|
||||||
|
" and this file will be loaded as the current buffer.
|
||||||
|
"
|
||||||
|
" The cursor will be placed on the character before any 0x1f byte.
|
||||||
|
"
|
||||||
|
" The full path to the created directory is returned, it is the caller's
|
||||||
|
" responsibility to clean that up!
|
||||||
|
fun! gotest#write_file(path, contents) abort
|
||||||
|
let l:dir = go#util#tempdir("vim-go-test/testrun/")
|
||||||
|
let $GOPATH .= ':' . l:dir
|
||||||
|
let l:full_path = l:dir . '/src/' . a:path
|
||||||
|
|
||||||
|
call mkdir(fnamemodify(l:full_path, ':h'), 'p')
|
||||||
|
call writefile(a:contents, l:full_path)
|
||||||
|
exe 'cd ' . l:dir . '/src'
|
||||||
|
silent exe 'e! ' . a:path
|
||||||
|
|
||||||
|
" Set cursor.
|
||||||
|
let l:lnum = 1
|
||||||
|
for l:line in a:contents
|
||||||
|
let l:m = match(l:line, "\x1f")
|
||||||
|
if l:m > -1
|
||||||
|
call setpos('.', [0, l:lnum, l:m, 0])
|
||||||
|
call setline('.', substitute(getline('.'), "\x1f", '', ''))
|
||||||
|
break
|
||||||
|
endif
|
||||||
|
|
||||||
|
let l:lnum += 1
|
||||||
|
endfor
|
||||||
|
|
||||||
|
return l:dir
|
||||||
|
endfun
|
||||||
|
|
||||||
|
" Load a fixture file from test-fixtures.
|
||||||
|
"
|
||||||
|
" The file will be copied to a new GOPATH-compliant temporary directory and
|
||||||
|
" loaded as the current buffer.
|
||||||
|
fun! gotest#load_fixture(path) abort
|
||||||
|
let l:dir = go#util#tempdir("vim-go-test/testrun/")
|
||||||
|
let $GOPATH .= ':' . l:dir
|
||||||
|
let l:full_path = l:dir . '/src/' . a:path
|
||||||
|
|
||||||
|
call mkdir(fnamemodify(l:full_path, ':h'), 'p')
|
||||||
|
exe 'cd ' . l:dir . '/src'
|
||||||
|
silent exe 'noautocmd e ' . a:path
|
||||||
|
silent exe printf('read %s/test-fixtures/%s', g:vim_go_root, a:path)
|
||||||
|
silent noautocmd w!
|
||||||
|
|
||||||
|
return l:dir
|
||||||
|
endfun
|
||||||
|
|
||||||
|
" Diff the contents of the current buffer to a:want, which should be a list.
|
||||||
|
" If a:skipHeader is true we won't bother with the package and import
|
||||||
|
" declarations; so e.g.:
|
||||||
|
"
|
||||||
|
" let l:diff = s:diff_buffer(1, ['_ = mail.Address{}'])
|
||||||
|
"
|
||||||
|
" will pass, whereas otherwise you'd have to:
|
||||||
|
"
|
||||||
|
" let l:diff = s:diff_buffer(0, ['package main', 'import "net/mail", '_ = mail.Address{}'])
|
||||||
|
fun! gotest#assert_buffer(skipHeader, want) abort
|
||||||
|
let l:buffer = go#util#GetLines()
|
||||||
|
|
||||||
|
if a:skipHeader
|
||||||
|
for l:lnum in range(0, len(l:buffer) - 1)
|
||||||
|
" Bit rudimentary, but works reasonably well.
|
||||||
|
if match(l:buffer[l:lnum], '^\v(func|var|const|import \(|\))') > -1
|
||||||
|
" vint bug: https://github.com/Kuniwak/vint/issues/179
|
||||||
|
" vint: -ProhibitUsingUndeclaredVariable
|
||||||
|
let l:buffer = l:buffer[l:lnum:len(l:buffer)]
|
||||||
|
break
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Using ' is often easier so we don't have to escape ".
|
||||||
|
let l:want = map(a:want, 'substitute(v:val, "\\\\t", "\t", "")')
|
||||||
|
|
||||||
|
let l:tmp = go#util#tempdir('assert_buffer')
|
||||||
|
try
|
||||||
|
call writefile(l:buffer, l:tmp . '/have')
|
||||||
|
call writefile(l:want, l:tmp . '/want')
|
||||||
|
call go#fmt#run('gofmt', l:tmp . '/have', l:tmp . '/have')
|
||||||
|
call go#fmt#run('gofmt', l:tmp . '/want', l:tmp . '/want')
|
||||||
|
let [l:out, l:err] = go#util#Exec(["diff", "-u", l:tmp . '/have', l:tmp . '/want'])
|
||||||
|
finally
|
||||||
|
call delete(l:tmp . '/have')
|
||||||
|
call delete(l:tmp . '/want')
|
||||||
|
call delete(l:tmp, 'd')
|
||||||
|
endtry
|
||||||
|
|
||||||
|
if l:err || l:out != ''
|
||||||
|
let v:errors = extend(v:errors, split(l:out, "\n"))
|
||||||
|
endif
|
||||||
|
endfun
|
||||||
|
|
||||||
|
" Diff the contents of the current buffer to the fixture file in a:path.
|
||||||
|
fun! gotest#assert_fixture(path) abort
|
||||||
|
let l:want = readfile(printf('%s/test-fixtures/%s', g:vim_go_root, a:path))
|
||||||
|
call gotest#assert_buffer(0, l:want)
|
||||||
|
endfun
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
70
autoload/unite/sources/decls.vim
Normal file
70
autoload/unite/sources/decls.vim
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
let s:save_cpo = &cpoptions
|
||||||
|
set cpoptions&vim
|
||||||
|
|
||||||
|
let s:source = {
|
||||||
|
\ 'name': 'decls',
|
||||||
|
\ 'description': 'GoDecls implementation for unite',
|
||||||
|
\ 'syntax': 'uniteSource__Decls',
|
||||||
|
\ 'action_table': {},
|
||||||
|
\ 'hooks': {},
|
||||||
|
\ }
|
||||||
|
|
||||||
|
function! unite#sources#decls#define()
|
||||||
|
return s:source
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:source.gather_candidates(args, context) abort
|
||||||
|
let l:bin_path = go#path#CheckBinPath('motion')
|
||||||
|
if empty(l:bin_path)
|
||||||
|
return []
|
||||||
|
endif
|
||||||
|
|
||||||
|
let l:path = expand(get(a:args, 0, '%:p:h'))
|
||||||
|
if isdirectory(l:path)
|
||||||
|
let l:mode = 'dir'
|
||||||
|
elseif filereadable(l:path)
|
||||||
|
let l:mode = 'file'
|
||||||
|
else
|
||||||
|
return []
|
||||||
|
endif
|
||||||
|
|
||||||
|
let l:include = get(g:, 'go_decls_includes', 'func,type')
|
||||||
|
let l:command = printf('%s -format vim -mode decls -include %s -%s %s', l:bin_path, l:include, l:mode, shellescape(l:path))
|
||||||
|
let l:candidates = []
|
||||||
|
try
|
||||||
|
let l:result = eval(unite#util#system(l:command))
|
||||||
|
let l:candidates = get(l:result, 'decls', [])
|
||||||
|
catch
|
||||||
|
call unite#print_source_error(['command returned invalid response.', v:exception], s:source.name)
|
||||||
|
endtry
|
||||||
|
|
||||||
|
return map(l:candidates, "{
|
||||||
|
\ 'word': printf('%s :%d :%s', fnamemodify(v:val.filename, ':~:.'), v:val.line, v:val.full),
|
||||||
|
\ 'kind': 'jump_list',
|
||||||
|
\ 'action__path': v:val.filename,
|
||||||
|
\ 'action__line': v:val.line,
|
||||||
|
\ 'action__col': v:val.col,
|
||||||
|
\ }")
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:source.hooks.on_syntax(args, context) abort
|
||||||
|
syntax match uniteSource__Decls_Filepath /[^:]*\ze:/ contained containedin=uniteSource__Decls
|
||||||
|
syntax match uniteSource__Decls_Line /\d\+\ze :/ contained containedin=uniteSource__Decls
|
||||||
|
syntax match uniteSource__Decls_WholeFunction /\vfunc %(\([^)]+\) )?[^(]+/ contained containedin=uniteSource__Decls
|
||||||
|
syntax match uniteSource__Decls_Function /\S\+\ze(/ contained containedin=uniteSource__Decls_WholeFunction
|
||||||
|
syntax match uniteSource__Decls_WholeType /type \S\+/ contained containedin=uniteSource__Decls
|
||||||
|
syntax match uniteSource__Decls_Type /\v( )@<=\S+/ contained containedin=uniteSource__Decls_WholeType
|
||||||
|
highlight default link uniteSource__Decls_Filepath Comment
|
||||||
|
highlight default link uniteSource__Decls_Line LineNr
|
||||||
|
highlight default link uniteSource__Decls_Function Function
|
||||||
|
highlight default link uniteSource__Decls_Type Type
|
||||||
|
|
||||||
|
syntax match uniteSource__Decls_Separator /:/ contained containedin=uniteSource__Decls conceal
|
||||||
|
syntax match uniteSource__Decls_SeparatorFunction /func / contained containedin=uniteSource__Decls_WholeFunction conceal
|
||||||
|
syntax match uniteSource__Decls_SeparatorType /type / contained containedin=uniteSource__Decls_WholeType conceal
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
let &cpoptions = s:save_cpo
|
||||||
|
unlet s:save_cpo
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
@ -4,10 +4,10 @@
|
|||||||
"
|
"
|
||||||
" compiler/go.vim: Vim compiler file for Go.
|
" compiler/go.vim: Vim compiler file for Go.
|
||||||
|
|
||||||
if exists("current_compiler")
|
if exists("g:current_compiler")
|
||||||
finish
|
finish
|
||||||
endif
|
endif
|
||||||
let current_compiler = "go"
|
let g:current_compiler = "go"
|
||||||
|
|
||||||
if exists(":CompilerSet") != 2
|
if exists(":CompilerSet") != 2
|
||||||
command -nargs=* CompilerSet setlocal <args>
|
command -nargs=* CompilerSet setlocal <args>
|
||||||
@ -38,4 +38,4 @@ CompilerSet errorformat+=%-G%.%# " All lines not matching a
|
|||||||
let &cpo = s:save_cpo
|
let &cpo = s:save_cpo
|
||||||
unlet s:save_cpo
|
unlet s:save_cpo
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
1631
doc/vim-go.txt
1631
doc/vim-go.txt
File diff suppressed because it is too large
Load Diff
@ -18,14 +18,17 @@ function! s:gofiletype_post()
|
|||||||
let &g:fileencodings = s:current_fileencodings
|
let &g:fileencodings = s:current_fileencodings
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
au BufNewFile *.go setfiletype go | setlocal fileencoding=utf-8 fileformat=unix
|
augroup vim-go-filetype
|
||||||
au BufRead *.go call s:gofiletype_pre("go")
|
autocmd!
|
||||||
au BufReadPost *.go call s:gofiletype_post()
|
au BufNewFile *.go setfiletype go | setlocal fileencoding=utf-8 fileformat=unix
|
||||||
|
au BufRead *.go call s:gofiletype_pre("go")
|
||||||
|
au BufReadPost *.go call s:gofiletype_post()
|
||||||
|
|
||||||
au BufNewFile *.s setfiletype asm | setlocal fileencoding=utf-8 fileformat=unix
|
au BufNewFile *.s setfiletype asm | setlocal fileencoding=utf-8 fileformat=unix
|
||||||
au BufRead *.s call s:gofiletype_pre("asm")
|
au BufRead *.s call s:gofiletype_pre("asm")
|
||||||
au BufReadPost *.s call s:gofiletype_post()
|
au BufReadPost *.s call s:gofiletype_post()
|
||||||
|
|
||||||
au BufRead,BufNewFile *.tmpl set filetype=gohtmltmpl
|
au BufRead,BufNewFile *.tmpl set filetype=gohtmltmpl
|
||||||
|
augroup end
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
@ -15,3 +15,5 @@ setlocal commentstring=//\ %s
|
|||||||
setlocal noexpandtab
|
setlocal noexpandtab
|
||||||
|
|
||||||
command! -nargs=0 AsmFmt call go#asmfmt#Format()
|
command! -nargs=0 AsmFmt call go#asmfmt#Format()
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
@ -29,7 +29,15 @@ if get(g:, "go_doc_keywordprg_enabled", 1)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
if get(g:, "go_def_mapping_enabled", 1)
|
if get(g:, "go_def_mapping_enabled", 1)
|
||||||
|
" these are default Vim mappings, we're overriding them to make them
|
||||||
|
" useful again for Go source code
|
||||||
nnoremap <buffer> <silent> gd :GoDef<cr>
|
nnoremap <buffer> <silent> gd :GoDef<cr>
|
||||||
|
nnoremap <buffer> <silent> <C-]> :GoDef<cr>
|
||||||
|
nnoremap <buffer> <silent> <C-LeftMouse> <LeftMouse>:GoDef<cr>
|
||||||
|
nnoremap <buffer> <silent> g<LeftMouse> <LeftMouse>:GoDef<cr>
|
||||||
|
nnoremap <buffer> <silent> <C-w><C-]> :<C-u>call go#def#Jump("split")<CR>
|
||||||
|
nnoremap <buffer> <silent> <C-w>] :<C-u>call go#def#Jump("split")<CR>
|
||||||
|
nnoremap <buffer> <silent> <C-t> :<C-U>call go#def#StackPop(v:count1)<cr>
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if get(g:, "go_textobj_enabled", 1)
|
if get(g:, "go_textobj_enabled", 1)
|
||||||
@ -50,8 +58,76 @@ if get(g:, "go_textobj_enabled", 1)
|
|||||||
xnoremap <buffer> <silent> [[ :<c-u>call go#textobj#FunctionJump('v', 'prev')<cr>
|
xnoremap <buffer> <silent> [[ :<c-u>call go#textobj#FunctionJump('v', 'prev')<cr>
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if get(g:, "go_auto_type_info", 0)
|
if get(g:, "go_auto_type_info", 0) || get(g:, "go_auto_sameids", 0)
|
||||||
setlocal updatetime=800
|
let &l:updatetime= get(g:, "go_updatetime", 800)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
" NOTE(arslan): experimental, disabled by default, doesn't work well. No
|
||||||
|
" documentation as well. If anyone feels adventurous, enable the following and
|
||||||
|
" try to search for Go identifiers ;)
|
||||||
|
"
|
||||||
|
" if get(g:, "go_sameid_search_enabled", 0)
|
||||||
|
" autocmd FileType go nnoremap <buffer> <silent> * :<c-u>call Sameids_search(0)<CR>
|
||||||
|
" autocmd FileType go nnoremap <buffer> <silent> # :<c-u>call Sameids_search(1)<CR>
|
||||||
|
" autocmd FileType go nnoremap <buffer> <silent> n :<c-u>call Sameids_repeat(0)<CR>
|
||||||
|
" autocmd FileType go nnoremap <buffer> <silent> N :<c-u>call Sameids_repeat(1)<CR>
|
||||||
|
" autocmd FileType go cabbrev nohlsearch <C-r>=Sameids_nohlsearch()<CR>
|
||||||
|
" endif
|
||||||
|
|
||||||
|
" " mode 0: next 1: prev
|
||||||
|
" function! Sameids_repeat(mode)
|
||||||
|
" let matches = getmatches()
|
||||||
|
" if empty(matches)
|
||||||
|
" return
|
||||||
|
" endif
|
||||||
|
" let cur_offset = go#util#OffsetCursor()
|
||||||
|
|
||||||
|
" " reverse list to make it easy to find the prev occurrence
|
||||||
|
" if a:mode
|
||||||
|
" call reverse(matches)
|
||||||
|
" endif
|
||||||
|
|
||||||
|
" for m in matches
|
||||||
|
" if !has_key(m, "group")
|
||||||
|
" return
|
||||||
|
" endif
|
||||||
|
|
||||||
|
" if m.group != "goSameId"
|
||||||
|
" return
|
||||||
|
" endif
|
||||||
|
|
||||||
|
" let offset = go#util#Offset(m.pos1[0], m.pos1[1])
|
||||||
|
|
||||||
|
" if a:mode && cur_offset > offset
|
||||||
|
" call cursor(m.pos1[0], m.pos1[1])
|
||||||
|
" return
|
||||||
|
" elseif !a:mode && cur_offset < offset
|
||||||
|
" call cursor(m.pos1[0], m.pos1[1])
|
||||||
|
" return
|
||||||
|
" endif
|
||||||
|
" endfor
|
||||||
|
|
||||||
|
" " reached start/end, jump to the end/start
|
||||||
|
" let initial_match = matches[0]
|
||||||
|
" if !has_key(initial_match, "group")
|
||||||
|
" return
|
||||||
|
" endif
|
||||||
|
|
||||||
|
" if initial_match.group != "goSameId"
|
||||||
|
" return
|
||||||
|
" endif
|
||||||
|
|
||||||
|
" call cursor(initial_match.pos1[0], initial_match.pos1[1])
|
||||||
|
" endfunction
|
||||||
|
|
||||||
|
" function! Sameids_search(mode)
|
||||||
|
" call go#guru#SameIds()
|
||||||
|
" call Sameids_repeat(a:mode)
|
||||||
|
" endfunction
|
||||||
|
|
||||||
|
" function! Sameids_nohlsearch()
|
||||||
|
" call go#guru#ClearSameIds()
|
||||||
|
" return "nohlsearch"
|
||||||
|
" endfunction
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
@ -1,38 +1,59 @@
|
|||||||
" gorename
|
" -- gorename
|
||||||
command! -nargs=? GoRename call go#rename#Rename(<bang>0,<f-args>)
|
command! -nargs=? -complete=customlist,go#rename#Complete GoRename call go#rename#Rename(<bang>0, <f-args>)
|
||||||
|
|
||||||
" oracle
|
" -- guru
|
||||||
command! -nargs=* -complete=customlist,go#package#Complete GoOracleScope call go#oracle#Scope(<f-args>)
|
command! -nargs=* -complete=customlist,go#package#Complete GoGuruScope call go#guru#Scope(<f-args>)
|
||||||
command! -range=% GoImplements call go#oracle#Implements(<count>)
|
command! -range=% GoImplements call go#guru#Implements(<count>)
|
||||||
command! -range=% GoCallees call go#oracle#Callees(<count>)
|
command! -range=% GoWhicherrs call go#guru#Whicherrs(<count>)
|
||||||
command! -range=% GoDescribe call go#oracle#Describe(<count>)
|
command! -range=% GoCallees call go#guru#Callees(<count>)
|
||||||
command! -range=% GoCallers call go#oracle#Callers(<count>)
|
command! -range=% GoDescribe call go#guru#Describe(<count>)
|
||||||
command! -range=% GoCallstack call go#oracle#Callstack(<count>)
|
command! -range=% GoCallers call go#guru#Callers(<count>)
|
||||||
command! -range=% GoFreevars call go#oracle#Freevars(<count>)
|
command! -range=% GoCallstack call go#guru#Callstack(<count>)
|
||||||
command! -range=% GoChannelPeers call go#oracle#ChannelPeers(<count>)
|
command! -range=% GoFreevars call go#guru#Freevars(<count>)
|
||||||
command! -range=% GoReferrers call go#oracle#Referrers(<count>)
|
command! -range=% GoChannelPeers call go#guru#ChannelPeers(<count>)
|
||||||
command! -nargs=? GoOracleTags call go#oracle#Tags(<f-args>)
|
command! -range=% GoReferrers call go#guru#Referrers(<count>)
|
||||||
|
|
||||||
" tool
|
command! -range=0 GoSameIds call go#guru#SameIds()
|
||||||
command! -nargs=0 GoFiles echo go#tool#Files()
|
command! -range=0 GoSameIdsClear call go#guru#ClearSameIds()
|
||||||
|
command! -range=0 GoSameIdsToggle call go#guru#ToggleSameIds()
|
||||||
|
command! -range=0 GoSameIdsAutoToggle call go#guru#AutoToogleSameIds()
|
||||||
|
|
||||||
|
" -- tags
|
||||||
|
command! -nargs=* -range GoAddTags call go#tags#Add(<line1>, <line2>, <count>, <f-args>)
|
||||||
|
command! -nargs=* -range GoRemoveTags call go#tags#Remove(<line1>, <line2>, <count>, <f-args>)
|
||||||
|
|
||||||
|
" -- tool
|
||||||
|
command! -nargs=* -complete=customlist,go#tool#ValidFiles GoFiles echo go#tool#Files(<f-args>)
|
||||||
command! -nargs=0 GoDeps echo go#tool#Deps()
|
command! -nargs=0 GoDeps echo go#tool#Deps()
|
||||||
command! -nargs=* GoInfo call go#complete#Info(0)
|
command! -nargs=* GoInfo call go#tool#Info(0)
|
||||||
|
command! -nargs=0 GoAutoTypeInfoToggle call go#complete#ToggleAutoTypeInfo()
|
||||||
|
|
||||||
" cmd
|
" -- cmd
|
||||||
command! -nargs=* -bang GoBuild call go#cmd#Build(<bang>0,<f-args>)
|
command! -nargs=* -bang GoBuild call go#cmd#Build(<bang>0,<f-args>)
|
||||||
|
command! -nargs=? -bang GoBuildTags call go#cmd#BuildTags(<bang>0, <f-args>)
|
||||||
command! -nargs=* -bang GoGenerate call go#cmd#Generate(<bang>0,<f-args>)
|
command! -nargs=* -bang GoGenerate call go#cmd#Generate(<bang>0,<f-args>)
|
||||||
command! -nargs=* -bang -complete=file GoRun call go#cmd#Run(<bang>0,<f-args>)
|
command! -nargs=* -bang -complete=file GoRun call go#cmd#Run(<bang>0,<f-args>)
|
||||||
command! -nargs=* -bang GoInstall call go#cmd#Install(<bang>0, <f-args>)
|
command! -nargs=* -bang GoInstall call go#cmd#Install(<bang>0, <f-args>)
|
||||||
command! -nargs=* -bang GoTest call go#cmd#Test(<bang>0, 0, <f-args>)
|
|
||||||
command! -nargs=* -bang GoTestFunc call go#cmd#TestFunc(<bang>0, <f-args>)
|
" -- test
|
||||||
command! -nargs=* -bang GoTestCompile call go#cmd#Test(<bang>0, 1, <f-args>)
|
command! -nargs=* -bang GoTest call go#test#Test(<bang>0, 0, <f-args>)
|
||||||
command! -nargs=* -bang GoCoverage call go#cmd#Coverage(<bang>0, <f-args>)
|
command! -nargs=* -bang GoTestFunc call go#test#Func(<bang>0, <f-args>)
|
||||||
|
command! -nargs=* -bang GoTestCompile call go#test#Test(<bang>0, 1, <f-args>)
|
||||||
|
|
||||||
|
" -- cover
|
||||||
|
command! -nargs=* -bang GoCoverage call go#coverage#Buffer(<bang>0, <f-args>)
|
||||||
|
command! -nargs=* -bang GoCoverageClear call go#coverage#Clear()
|
||||||
|
command! -nargs=* -bang GoCoverageToggle call go#coverage#BufferToggle(<bang>0, <f-args>)
|
||||||
|
command! -nargs=* -bang GoCoverageBrowser call go#coverage#Browser(<bang>0, <f-args>)
|
||||||
|
|
||||||
" -- play
|
" -- play
|
||||||
command! -nargs=0 -range=% GoPlay call go#play#Share(<count>, <line1>, <line2>)
|
command! -nargs=0 -range=% GoPlay call go#play#Share(<count>, <line1>, <line2>)
|
||||||
|
|
||||||
" -- def
|
" -- def
|
||||||
command! -nargs=* -range GoDef :call go#def#Jump(<f-args>)
|
command! -nargs=* -range GoDef :call go#def#Jump('')
|
||||||
|
command! -nargs=? GoDefPop :call go#def#StackPop(<f-args>)
|
||||||
|
command! -nargs=? GoDefStack :call go#def#Stack(<f-args>)
|
||||||
|
command! -nargs=? GoDefStackClear :call go#def#StackClear(<f-args>)
|
||||||
|
|
||||||
" -- doc
|
" -- doc
|
||||||
command! -nargs=* -range -complete=customlist,go#package#Complete GoDoc call go#doc#Open('new', 'split', <f-args>)
|
command! -nargs=* -range -complete=customlist,go#package#Complete GoDoc call go#doc#Open('new', 'split', <f-args>)
|
||||||
@ -40,8 +61,12 @@ command! -nargs=* -range -complete=customlist,go#package#Complete GoDocBrowser c
|
|||||||
|
|
||||||
" -- fmt
|
" -- fmt
|
||||||
command! -nargs=0 GoFmt call go#fmt#Format(-1)
|
command! -nargs=0 GoFmt call go#fmt#Format(-1)
|
||||||
|
command! -nargs=0 GoFmtAutoSaveToggle call go#fmt#ToggleFmtAutoSave()
|
||||||
command! -nargs=0 GoImports call go#fmt#Format(1)
|
command! -nargs=0 GoImports call go#fmt#Format(1)
|
||||||
|
|
||||||
|
" -- asmfmt
|
||||||
|
command! -nargs=0 GoAsmFmtAutoSaveToggle call go#asmfmt#ToggleAsmFmtAutoSave()
|
||||||
|
|
||||||
" -- import
|
" -- import
|
||||||
command! -nargs=? -complete=customlist,go#package#Complete GoDrop call go#import#SwitchImport(0, '', <f-args>, '')
|
command! -nargs=? -complete=customlist,go#package#Complete GoDrop call go#import#SwitchImport(0, '', <f-args>, '')
|
||||||
command! -nargs=1 -bang -complete=customlist,go#package#Complete GoImport call go#import#SwitchImport(1, '', <f-args>, '<bang>')
|
command! -nargs=1 -bang -complete=customlist,go#package#Complete GoImport call go#import#SwitchImport(1, '', <f-args>, '<bang>')
|
||||||
@ -49,6 +74,7 @@ command! -nargs=* -bang -complete=customlist,go#package#Complete GoImportAs call
|
|||||||
|
|
||||||
" -- linters
|
" -- linters
|
||||||
command! -nargs=* GoMetaLinter call go#lint#Gometa(0, <f-args>)
|
command! -nargs=* GoMetaLinter call go#lint#Gometa(0, <f-args>)
|
||||||
|
command! -nargs=0 GoMetaLinterAutoSaveToggle call go#lint#ToggleMetaLinterAutoSave()
|
||||||
command! -nargs=* GoLint call go#lint#Golint(<f-args>)
|
command! -nargs=* GoLint call go#lint#Golint(<f-args>)
|
||||||
command! -nargs=* -bang GoVet call go#lint#Vet(<bang>0, <f-args>)
|
command! -nargs=* -bang GoVet call go#lint#Vet(<bang>0, <f-args>)
|
||||||
command! -nargs=* -complete=customlist,go#package#Complete GoErrCheck call go#lint#Errcheck(<f-args>)
|
command! -nargs=* -complete=customlist,go#package#Complete GoErrCheck call go#lint#Errcheck(<f-args>)
|
||||||
@ -56,10 +82,20 @@ command! -nargs=* -complete=customlist,go#package#Complete GoErrCheck call go#li
|
|||||||
" -- alternate
|
" -- alternate
|
||||||
command! -bang GoAlternate call go#alternate#Switch(<bang>0, '')
|
command! -bang GoAlternate call go#alternate#Switch(<bang>0, '')
|
||||||
|
|
||||||
" -- ctrlp
|
" -- decls
|
||||||
if globpath(&rtp, 'plugin/ctrlp.vim') != ""
|
command! -nargs=? -complete=file GoDecls call go#decls#Decls(0, <q-args>)
|
||||||
command! -nargs=? -complete=file GoDecls call ctrlp#init(ctrlp#decls#cmd(0, <q-args>))
|
command! -nargs=? -complete=dir GoDeclsDir call go#decls#Decls(1, <q-args>)
|
||||||
command! -nargs=? -complete=dir GoDeclsDir call ctrlp#init(ctrlp#decls#cmd(1, <q-args>))
|
|
||||||
endif
|
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
" -- impl
|
||||||
|
command! -nargs=* -complete=customlist,go#impl#Complete GoImpl call go#impl#Impl(<f-args>)
|
||||||
|
|
||||||
|
" -- template
|
||||||
|
command! -nargs=0 GoTemplateAutoCreateToggle call go#template#ToggleAutoCreate()
|
||||||
|
|
||||||
|
" -- keyify
|
||||||
|
command! -nargs=0 GoKeyify call go#keyify#Keyify()
|
||||||
|
|
||||||
|
" -- fillstruct
|
||||||
|
command! -nargs=0 GoFillStruct call go#fillstruct#FillStruct()
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
@ -20,31 +20,43 @@ endif
|
|||||||
nnoremap <silent> <Plug>(go-build) :<C-u>call go#cmd#Build(!g:go_jump_to_error)<CR>
|
nnoremap <silent> <Plug>(go-build) :<C-u>call go#cmd#Build(!g:go_jump_to_error)<CR>
|
||||||
nnoremap <silent> <Plug>(go-generate) :<C-u>call go#cmd#Generate(!g:go_jump_to_error)<CR>
|
nnoremap <silent> <Plug>(go-generate) :<C-u>call go#cmd#Generate(!g:go_jump_to_error)<CR>
|
||||||
nnoremap <silent> <Plug>(go-install) :<C-u>call go#cmd#Install(!g:go_jump_to_error)<CR>
|
nnoremap <silent> <Plug>(go-install) :<C-u>call go#cmd#Install(!g:go_jump_to_error)<CR>
|
||||||
nnoremap <silent> <Plug>(go-test) :<C-u>call go#cmd#Test(!g:go_jump_to_error, 0)<CR>
|
nnoremap <silent> <Plug>(go-test) :<C-u>call go#test#Test(!g:go_jump_to_error, 0)<CR>
|
||||||
nnoremap <silent> <Plug>(go-test-func) :<C-u>call go#cmd#TestFunc(!g:go_jump_to_error)<CR>
|
nnoremap <silent> <Plug>(go-test-func) :<C-u>call go#test#Func(!g:go_jump_to_error)<CR>
|
||||||
nnoremap <silent> <Plug>(go-test-compile) :<C-u>call go#cmd#Test(!g:go_jump_to_error, 1)<CR>
|
nnoremap <silent> <Plug>(go-test-compile) :<C-u>call go#test#Test(!g:go_jump_to_error, 1)<CR>
|
||||||
nnoremap <silent> <Plug>(go-coverage) :<C-u>call go#cmd#Coverage(!g:go_jump_to_error)<CR>
|
|
||||||
|
nnoremap <silent> <Plug>(go-coverage) :<C-u>call go#coverage#Buffer(!g:go_jump_to_error)<CR>
|
||||||
|
nnoremap <silent> <Plug>(go-coverage-clear) :<C-u>call go#coverage#Clear()<CR>
|
||||||
|
nnoremap <silent> <Plug>(go-coverage-toggle) :<C-u>call go#coverage#BufferToggle(!g:go_jump_to_error)<CR>
|
||||||
|
nnoremap <silent> <Plug>(go-coverage-browser) :<C-u>call go#coverage#Browser(!g:go_jump_to_error)<CR>
|
||||||
|
|
||||||
nnoremap <silent> <Plug>(go-files) :<C-u>call go#tool#Files()<CR>
|
nnoremap <silent> <Plug>(go-files) :<C-u>call go#tool#Files()<CR>
|
||||||
nnoremap <silent> <Plug>(go-deps) :<C-u>call go#tool#Deps()<CR>
|
nnoremap <silent> <Plug>(go-deps) :<C-u>call go#tool#Deps()<CR>
|
||||||
nnoremap <silent> <Plug>(go-info) :<C-u>call go#complete#Info(0)<CR>
|
nnoremap <silent> <Plug>(go-info) :<C-u>call go#tool#Info(0)<CR>
|
||||||
nnoremap <silent> <Plug>(go-import) :<C-u>call go#import#SwitchImport(1, '', expand('<cword>'), '')<CR>
|
nnoremap <silent> <Plug>(go-import) :<C-u>call go#import#SwitchImport(1, '', expand('<cword>'), '')<CR>
|
||||||
|
nnoremap <silent> <Plug>(go-imports) :<C-u>call go#fmt#Format(1)<CR>
|
||||||
|
|
||||||
nnoremap <silent> <Plug>(go-implements) :<C-u>call go#oracle#Implements(-1)<CR>
|
nnoremap <silent> <Plug>(go-implements) :<C-u>call go#guru#Implements(-1)<CR>
|
||||||
nnoremap <silent> <Plug>(go-callees) :<C-u>call go#oracle#Callees(-1)<CR>
|
nnoremap <silent> <Plug>(go-callees) :<C-u>call go#guru#Callees(-1)<CR>
|
||||||
nnoremap <silent> <Plug>(go-callers) :<C-u>call go#oracle#Callers(-1)<CR>
|
nnoremap <silent> <Plug>(go-callers) :<C-u>call go#guru#Callers(-1)<CR>
|
||||||
nnoremap <silent> <Plug>(go-describe) :<C-u>call go#oracle#Describe(-1)<CR>
|
nnoremap <silent> <Plug>(go-describe) :<C-u>call go#guru#Describe(-1)<CR>
|
||||||
nnoremap <silent> <Plug>(go-callstack) :<C-u>call go#oracle#Callstack(-1)<CR>
|
nnoremap <silent> <Plug>(go-callstack) :<C-u>call go#guru#Callstack(-1)<CR>
|
||||||
nnoremap <silent> <Plug>(go-freevars) :<C-u>call go#oracle#Freevars(-1)<CR>
|
xnoremap <silent> <Plug>(go-freevars) :<C-u>call go#guru#Freevars(0)<CR>
|
||||||
nnoremap <silent> <Plug>(go-channelpeers) :<C-u>call go#oracle#ChannelPeers(-1)<CR>
|
nnoremap <silent> <Plug>(go-channelpeers) :<C-u>call go#guru#ChannelPeers(-1)<CR>
|
||||||
nnoremap <silent> <Plug>(go-referrers) :<C-u>call go#oracle#Referrers(-1)<CR>
|
nnoremap <silent> <Plug>(go-referrers) :<C-u>call go#guru#Referrers(-1)<CR>
|
||||||
|
nnoremap <silent> <Plug>(go-sameids) :<C-u>call go#guru#SameIds()<CR>
|
||||||
|
nnoremap <silent> <Plug>(go-whicherrs) :<C-u>call go#guru#Whicherrs(-1)<CR>
|
||||||
|
nnoremap <silent> <Plug>(go-sameids-toggle) :<C-u>call go#guru#ToggleSameIds()<CR>
|
||||||
|
|
||||||
nnoremap <silent> <Plug>(go-rename) :<C-u>call go#rename#Rename(!g:go_jump_to_error)<CR>
|
nnoremap <silent> <Plug>(go-rename) :<C-u>call go#rename#Rename(!g:go_jump_to_error)<CR>
|
||||||
|
|
||||||
nnoremap <silent> <Plug>(go-def) :<C-u>call go#def#Jump()<CR>
|
nnoremap <silent> <Plug>(go-def) :<C-u>call go#def#Jump('')<CR>
|
||||||
nnoremap <silent> <Plug>(go-def-vertical) :<C-u>call go#def#JumpMode("vsplit")<CR>
|
nnoremap <silent> <Plug>(go-def-vertical) :<C-u>call go#def#Jump("vsplit")<CR>
|
||||||
nnoremap <silent> <Plug>(go-def-split) :<C-u>call go#def#JumpMode("split")<CR>
|
nnoremap <silent> <Plug>(go-def-split) :<C-u>call go#def#Jump("split")<CR>
|
||||||
nnoremap <silent> <Plug>(go-def-tab) :<C-u>call go#def#JumpMode("tab")<CR>
|
nnoremap <silent> <Plug>(go-def-tab) :<C-u>call go#def#Jump("tab")<CR>
|
||||||
|
|
||||||
|
nnoremap <silent> <Plug>(go-def-pop) :<C-u>call go#def#StackPop()<CR>
|
||||||
|
nnoremap <silent> <Plug>(go-def-stack) :<C-u>call go#def#Stack()<CR>
|
||||||
|
nnoremap <silent> <Plug>(go-def-stack-clear) :<C-u>call go#def#StackClear()<CR>
|
||||||
|
|
||||||
nnoremap <silent> <Plug>(go-doc) :<C-u>call go#doc#Open("new", "split")<CR>
|
nnoremap <silent> <Plug>(go-doc) :<C-u>call go#doc#Open("new", "split")<CR>
|
||||||
nnoremap <silent> <Plug>(go-doc-tab) :<C-u>call go#doc#Open("tabnew", "tabe")<CR>
|
nnoremap <silent> <Plug>(go-doc-tab) :<C-u>call go#doc#Open("tabnew", "tabe")<CR>
|
||||||
@ -53,8 +65,11 @@ nnoremap <silent> <Plug>(go-doc-split) :<C-u>call go#doc#Open("new", "split")<CR
|
|||||||
nnoremap <silent> <Plug>(go-doc-browser) :<C-u>call go#doc#OpenBrowser()<CR>
|
nnoremap <silent> <Plug>(go-doc-browser) :<C-u>call go#doc#OpenBrowser()<CR>
|
||||||
|
|
||||||
nnoremap <silent> <Plug>(go-metalinter) :<C-u>call go#lint#Gometa(0)<CR>
|
nnoremap <silent> <Plug>(go-metalinter) :<C-u>call go#lint#Gometa(0)<CR>
|
||||||
|
nnoremap <silent> <Plug>(go-lint) :<C-u>call go#lint#Golint()<CR>
|
||||||
nnoremap <silent> <Plug>(go-vet) :<C-u>call go#lint#Vet(!g:go_jump_to_error)<CR>
|
nnoremap <silent> <Plug>(go-vet) :<C-u>call go#lint#Vet(!g:go_jump_to_error)<CR>
|
||||||
|
|
||||||
nnoremap <silent> <Plug>(go-alternate-edit) :<C-u>call go#alternate#Switch(0, "edit")<CR>
|
nnoremap <silent> <Plug>(go-alternate-edit) :<C-u>call go#alternate#Switch(0, "edit")<CR>
|
||||||
nnoremap <silent> <Plug>(go-alternate-vertical) :<C-u>call go#alternate#Switch(0, "vsplit")<CR>
|
nnoremap <silent> <Plug>(go-alternate-vertical) :<C-u>call go#alternate#Switch(0, "vsplit")<CR>
|
||||||
nnoremap <silent> <Plug>(go-alternate-split) :<C-u>call go#alternate#Switch(0, "split")<CR>
|
nnoremap <silent> <Plug>(go-alternate-split) :<C-u>call go#alternate#Switch(0, "split")<CR>
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
@ -3,13 +3,8 @@ if exists("g:go_loaded_gosnippets")
|
|||||||
endif
|
endif
|
||||||
let g:go_loaded_gosnippets = 1
|
let g:go_loaded_gosnippets = 1
|
||||||
|
|
||||||
" by default UltiSnips
|
function! s:GoUltiSnips() abort
|
||||||
if !exists("g:go_snippet_engine")
|
if get(g:, 'did_plugin_ultisnips') isnot 1
|
||||||
let g:go_snippet_engine = "ultisnips"
|
|
||||||
endif
|
|
||||||
|
|
||||||
function! s:GoUltiSnips()
|
|
||||||
if globpath(&rtp, 'plugin/UltiSnips.vim') == ""
|
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -20,27 +15,53 @@ function! s:GoUltiSnips()
|
|||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:GoNeosnippet()
|
function! s:GoNeosnippet() abort
|
||||||
if globpath(&rtp, 'plugin/neosnippet.vim') == ""
|
if get(g:, 'loaded_neosnippet') isnot 1
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let g:neosnippet#enable_snipmate_compatibility = 1
|
let g:neosnippet#enable_snipmate_compatibility = 1
|
||||||
|
|
||||||
let gosnippets_dir = globpath(&rtp, 'gosnippets/snippets')
|
let l:gosnippets_dir = globpath(&rtp, 'gosnippets/snippets')
|
||||||
if type(g:neosnippet#snippets_directory) == type([])
|
if type(g:neosnippet#snippets_directory) == type([])
|
||||||
let g:neosnippet#snippets_directory += [gosnippets_dir]
|
let g:neosnippet#snippets_directory += [l:gosnippets_dir]
|
||||||
elseif type(g:neosnippet#snippets_directory) == type("")
|
elseif type(g:neosnippet#snippets_directory) == type("")
|
||||||
if strlen(g:neosnippet#snippets_directory) > 0
|
if strlen(g:neosnippet#snippets_directory) > 0
|
||||||
let g:neosnippet#snippets_directory = g:neosnippet#snippets_directory . "," . gosnippets_dir
|
let g:neosnippet#snippets_directory = g:neosnippet#snippets_directory . "," . l:gosnippets_dir
|
||||||
else
|
else
|
||||||
let g:neosnippet#snippets_directory = gosnippets_dir
|
let g:neosnippet#snippets_directory = l:gosnippets_dir
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
if g:go_snippet_engine == "ultisnips"
|
function! s:GoMinisnip() abort
|
||||||
|
if get(g:, 'loaded_minisnip') isnot 1
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
if exists('g:minisnip_dir')
|
||||||
|
let g:minisnip_dir .= ':' . globpath(&rtp, 'gosnippets/minisnip')
|
||||||
|
else
|
||||||
|
let g:minisnip_dir = globpath(&rtp, 'gosnippets/minisnip')
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
let s:engine = get(g:, 'go_snippet_engine', 'automatic')
|
||||||
|
if s:engine is? "automatic"
|
||||||
|
if get(g:, 'did_plugin_ultisnips') is 1
|
||||||
call s:GoUltiSnips()
|
call s:GoUltiSnips()
|
||||||
elseif g:go_snippet_engine == "neosnippet"
|
elseif get(g:, 'loaded_neosnippet') is 1
|
||||||
call s:GoNeosnippet()
|
call s:GoNeosnippet()
|
||||||
|
elseif get(g:, 'loaded_minisnip') is 1
|
||||||
|
call s:GoMinisnip()
|
||||||
|
endif
|
||||||
|
elseif s:engine is? "ultisnips"
|
||||||
|
call s:GoUltiSnips()
|
||||||
|
elseif s:engine is? "neosnippet"
|
||||||
|
call s:GoNeosnippet()
|
||||||
|
elseif s:engine is? "minisnip"
|
||||||
|
call s:GoMinisnip()
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
@ -45,7 +45,7 @@ function! s:SetTagbar()
|
|||||||
\ 'ctype' : 't',
|
\ 'ctype' : 't',
|
||||||
\ 'ntype' : 'n'
|
\ 'ntype' : 'n'
|
||||||
\ },
|
\ },
|
||||||
\ 'ctagsbin' : expand(bin_path),
|
\ 'ctagsbin' : bin_path,
|
||||||
\ 'ctagsargs' : '-sort -silent'
|
\ 'ctagsargs' : '-sort -silent'
|
||||||
\ }
|
\ }
|
||||||
endif
|
endif
|
||||||
@ -53,3 +53,5 @@ endfunction
|
|||||||
|
|
||||||
|
|
||||||
call s:SetTagbar()
|
call s:SetTagbar()
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
7
ftplugin/gohtmltmpl.vim
Normal file
7
ftplugin/gohtmltmpl.vim
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
if exists("b:did_ftplugin")
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
|
||||||
|
runtime! ftplugin/html.vim
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
@ -110,7 +110,7 @@ snippet gpl
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
* Copyright (C) ${1:Author}, `strftime("%Y")`
|
* Copyright (C) ${1:Author}, `!v strftime("%Y")`
|
||||||
*/
|
*/
|
||||||
${0}
|
${0}
|
||||||
endsnippet
|
endsnippet
|
||||||
@ -143,6 +143,13 @@ else {
|
|||||||
}
|
}
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
|
# if inline error
|
||||||
|
snippet ife "If with inline erro"
|
||||||
|
if err := ${1:condition}; err != nil {
|
||||||
|
${0:${VISUAL}}
|
||||||
|
}
|
||||||
|
endsnippet
|
||||||
|
|
||||||
# error snippet
|
# error snippet
|
||||||
snippet errn "Error return " !b
|
snippet errn "Error return " !b
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -151,14 +158,15 @@ if err != nil {
|
|||||||
${0}
|
${0}
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
# error snippet
|
# error log snippet
|
||||||
snippet errt "Error test fatal " !b
|
snippet errl "Error with log.Fatal(err)" !b
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
${0}
|
${0}
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
|
# error multiple return
|
||||||
snippet errn, "Error return with two return values" !b
|
snippet errn, "Error return with two return values" !b
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ${1:nil}, err
|
return ${1:nil}, err
|
||||||
@ -166,6 +174,23 @@ if err != nil {
|
|||||||
${0}
|
${0}
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
|
# error panic
|
||||||
|
snippet errp "Error panic" !b
|
||||||
|
if err != nil {
|
||||||
|
panic(${1})
|
||||||
|
}
|
||||||
|
${0}
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
# error test
|
||||||
|
snippet errt "Error test fatal " !b
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
${0}
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
# error handle
|
||||||
snippet errh "Error handle and return" !b
|
snippet errh "Error handle and return" !b
|
||||||
if err != nil {
|
if err != nil {
|
||||||
${1}
|
${1}
|
||||||
@ -174,8 +199,14 @@ if err != nil {
|
|||||||
${0}
|
${0}
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
|
# json field tag
|
||||||
snippet json "\`json:key\`"
|
snippet json "\`json:key\`"
|
||||||
\`json:"${1:keyName}"\`
|
\`json:"${1:`!v go#util#snippetcase(matchstr(getline("."), '\w\+'))`}"\`
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
# yaml field tag
|
||||||
|
snippet yaml "\`yaml:key\`"
|
||||||
|
\`yaml:"${1:`!v go#util#snippetcase(matchstr(getline("."), '\w\+'))`}"\`
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
# fallthrough
|
# fallthrough
|
||||||
@ -327,6 +358,18 @@ func Test${1:Function}(t *testing.T) {
|
|||||||
}
|
}
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
|
snippet hf "http.HandlerFunc" !b
|
||||||
|
func ${1:handler}(w http.ResponseWriter, r *http.Request) {
|
||||||
|
${0:fmt.Fprintf(w, "hello world")}
|
||||||
|
}
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet hhf "mux.HandleFunc" !b
|
||||||
|
${1:http}.HandleFunc("${2:/}", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
${0:fmt.Fprintf(w, "hello world")}
|
||||||
|
})
|
||||||
|
endsnippet
|
||||||
|
|
||||||
# quick test server
|
# quick test server
|
||||||
snippet tsrv "httptest.NewServer"
|
snippet tsrv "httptest.NewServer"
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -351,6 +394,21 @@ if err != nil {
|
|||||||
}
|
}
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
|
snippet example "func ExampleXYZ() { ... }"
|
||||||
|
func Example${1:Method}() {
|
||||||
|
${0:${VISUAL}}
|
||||||
|
// Output:
|
||||||
|
}
|
||||||
|
endsnippet
|
||||||
|
|
||||||
|
snippet benchmark "func BenchmarkXYZ(b *testing.B) { ... }"
|
||||||
|
func Benchmark${1:Method}(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
${0:${VISUAL}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endsnippet
|
||||||
|
|
||||||
# variable declaration
|
# variable declaration
|
||||||
snippet var "var x Type [= ...]"
|
snippet var "var x Type [= ...]"
|
||||||
var ${1:x} ${2:Type}${3: = ${0:value}}
|
var ${1:x} ${2:Type}${3: = ${0:value}}
|
||||||
@ -372,7 +430,6 @@ if !reflect.DeepEqual(${1:expected}, ${2:actual}) {
|
|||||||
}
|
}
|
||||||
endsnippet
|
endsnippet
|
||||||
|
|
||||||
|
|
||||||
global !p
|
global !p
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
|||||||
3
gosnippets/minisnip/_go_eq
Normal file
3
gosnippets/minisnip/_go_eq
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
if !reflect.DeepEqual({{+got+}}, {{+want+}}) {
|
||||||
|
t.Errorf("\ngot: %#v\nwant: %#v\n", {{+~\~2+}}, {{+~\~2+}})
|
||||||
|
}
|
||||||
3
gosnippets/minisnip/_go_err
Normal file
3
gosnippets/minisnip/_go_err
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
if err != nil {
|
||||||
|
return {{+err+}}
|
||||||
|
}
|
||||||
4
gosnippets/minisnip/_go_errt
Normal file
4
gosnippets/minisnip/_go_errt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
{{++}}
|
||||||
3
gosnippets/minisnip/_go_errw
Normal file
3
gosnippets/minisnip/_go_errw
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "{{++}}")
|
||||||
|
}
|
||||||
3
gosnippets/minisnip/_go_f
Normal file
3
gosnippets/minisnip/_go_f
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// {{++}}
|
||||||
|
func {{+~\~1+}}() {
|
||||||
|
}
|
||||||
1
gosnippets/minisnip/_go_ff
Normal file
1
gosnippets/minisnip/_go_ff
Normal file
@ -0,0 +1 @@
|
|||||||
|
fmt.Printf("%#v\n", {{++}})
|
||||||
3
gosnippets/minisnip/_go_fori
Normal file
3
gosnippets/minisnip/_go_fori
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
for i := 0; i < {{++}}; i++ {
|
||||||
|
{{++}}
|
||||||
|
}
|
||||||
2
gosnippets/minisnip/_go_pkg
Normal file
2
gosnippets/minisnip/_go_pkg
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Package {{+~expand('%:p:h:t')+}} {{++}}
|
||||||
|
package {{+~\~2+}}
|
||||||
2
gosnippets/minisnip/_go_sp
Normal file
2
gosnippets/minisnip/_go_sp
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
fmt.Sprintf("{{++}}", {{++}})
|
||||||
|
|
||||||
@ -118,6 +118,14 @@ snippet else
|
|||||||
else {
|
else {
|
||||||
${0}
|
${0}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# if inline error
|
||||||
|
snippet ife
|
||||||
|
abbr if err := ...; err != nil { ... }
|
||||||
|
if err := ${1:condition}; err != nil {
|
||||||
|
${0}
|
||||||
|
}
|
||||||
|
|
||||||
# error snippet
|
# error snippet
|
||||||
snippet errn
|
snippet errn
|
||||||
abbr if err != nil { ... }
|
abbr if err != nil { ... }
|
||||||
@ -132,6 +140,13 @@ abbr if err != nil { ... }
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# error snippet in log.Fatal
|
||||||
|
snippet errl
|
||||||
|
abbr if err != nil { ... }
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
# error snippet with two return values
|
# error snippet with two return values
|
||||||
snippet errn,
|
snippet errn,
|
||||||
abbr if err != nil { return [...], err }
|
abbr if err != nil { return [...], err }
|
||||||
@ -149,11 +164,24 @@ abbr if err != nil { return }
|
|||||||
}
|
}
|
||||||
${0}
|
${0}
|
||||||
|
|
||||||
|
# error snippet with panic
|
||||||
|
snippet errp
|
||||||
|
abbr if err != nil { ... }
|
||||||
|
if err != nil {
|
||||||
|
panic(${1})
|
||||||
|
}
|
||||||
|
${0}
|
||||||
|
|
||||||
# json snippet
|
# json snippet
|
||||||
snippet json
|
snippet json
|
||||||
abbr \`json:key\`
|
abbr \`json:key\`
|
||||||
\`json:"${1:keyName}"\`
|
\`json:"${1:keyName}"\`
|
||||||
|
|
||||||
|
# yaml snippet
|
||||||
|
snippet yaml
|
||||||
|
abbr \`yaml:key\`
|
||||||
|
\`yaml:"${1:keyName}"\`
|
||||||
|
|
||||||
# fallthrough
|
# fallthrough
|
||||||
snippet ft
|
snippet ft
|
||||||
abbr fallthrough
|
abbr fallthrough
|
||||||
@ -305,6 +333,19 @@ abbr if err != nil { t.Fatalf(...) }
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("${1}")
|
t.Fatalf("${1}")
|
||||||
}
|
}
|
||||||
|
# test example
|
||||||
|
snippet example
|
||||||
|
func Example${1:Method}() {
|
||||||
|
${0}
|
||||||
|
// Output:
|
||||||
|
}
|
||||||
|
# test benchmark
|
||||||
|
snippet benchmark
|
||||||
|
func Benchmark${1:Method}(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
${0}
|
||||||
|
}
|
||||||
|
}
|
||||||
# variable declaration
|
# variable declaration
|
||||||
snippet var
|
snippet var
|
||||||
abbr var x Type [= ...]
|
abbr var x Type [= ...]
|
||||||
@ -323,3 +364,15 @@ abbr equals: test two identifiers with DeepEqual
|
|||||||
fmt.Printf("%s:%d:\n\n\texp: %#v\n\n\tgot: %#v\n\n", filepath.Base(file), line, $1, $2)
|
fmt.Printf("%s:%d:\n\n\texp: %#v\n\n\tgot: %#v\n\n", filepath.Base(file), line, $1, $2)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
snippet hf
|
||||||
|
abbr http.HandlerFunc
|
||||||
|
func ${1:handler}(w http.ResponseWriter, r *http.Request) {
|
||||||
|
${0:fmt.Fprintf(w, "hello world")}
|
||||||
|
}
|
||||||
|
|
||||||
|
snippet hhf
|
||||||
|
abbr mux.HandleFunc(...)
|
||||||
|
${1:http}.HandleFunc("${2:/}", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
${0:fmt.Fprintf(w, "hello world")}
|
||||||
|
})
|
||||||
|
|||||||
@ -75,4 +75,4 @@ function! GoIndent(lnum)
|
|||||||
return ind
|
return ind
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
@ -30,15 +30,17 @@ function! GetGoHTMLTmplIndent(lnum)
|
|||||||
|
|
||||||
" If need to indent based on last line
|
" If need to indent based on last line
|
||||||
let last_line = getline(a:lnum-1)
|
let last_line = getline(a:lnum-1)
|
||||||
if last_line =~ '^\s*{{\s*\%(if\|else\|range\|with\|define\|block\).*}}'
|
if last_line =~ '^\s*{{-\=\s*\%(if\|else\|range\|with\|define\|block\).*}}'
|
||||||
let ind += sw
|
let ind += sw
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" End of FuncMap block
|
" End of FuncMap block
|
||||||
let current_line = getline(a:lnum)
|
let current_line = getline(a:lnum)
|
||||||
if current_line =~ '^\s*{{\s*\%(else\|end\).*}}'
|
if current_line =~ '^\s*{{-\=\s*\%(else\|end\).*}}'
|
||||||
let ind -= sw
|
let ind -= sw
|
||||||
endif
|
endif
|
||||||
|
|
||||||
return ind
|
return ind
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
|
|||||||
225
plugin/go.vim
225
plugin/go.vim
@ -4,43 +4,74 @@ if exists("g:go_loaded_install")
|
|||||||
endif
|
endif
|
||||||
let g:go_loaded_install = 1
|
let g:go_loaded_install = 1
|
||||||
|
|
||||||
|
" Not using the has('patch-7.4.1689') syntax because that wasn't added until
|
||||||
|
" 7.4.237, and we want to be sure this works for everyone (this is also why
|
||||||
|
" we're not using utils#EchoError()).
|
||||||
|
"
|
||||||
|
" Version 7.4.1689 was chosen because that's what the most recent Ubuntu LTS
|
||||||
|
" release (16.04) uses.
|
||||||
|
if
|
||||||
|
\ get(g:, 'go_version_warning', 1) != 0 &&
|
||||||
|
\ (v:version < 704 || (v:version == 704 && !has('patch1689')))
|
||||||
|
\ && !has('nvim')
|
||||||
|
echohl Error
|
||||||
|
echom "vim-go requires Vim 7.4.1689 or Neovim, but you're using an older version."
|
||||||
|
echom "Please update your Vim for the best vim-go experience."
|
||||||
|
echom "If you really want to continue you can set this to make the error go away:"
|
||||||
|
echom " let g:go_version_warning = 0"
|
||||||
|
echom "Note that some features may error out or behave incorrectly."
|
||||||
|
echom "Please do not report bugs unless you're using Vim 7.4.1689 or newer."
|
||||||
|
echohl None
|
||||||
|
|
||||||
|
" Make sure people see this.
|
||||||
|
sleep 2
|
||||||
|
endif
|
||||||
|
|
||||||
" these packages are used by vim-go and can be automatically installed if
|
" these packages are used by vim-go and can be automatically installed if
|
||||||
" needed by the user with GoInstallBinaries
|
" needed by the user with GoInstallBinaries
|
||||||
let s:packages = [
|
let s:packages = {
|
||||||
\ "github.com/nsf/gocode",
|
\ 'asmfmt': ['github.com/klauspost/asmfmt/cmd/asmfmt'],
|
||||||
\ "github.com/alecthomas/gometalinter",
|
\ 'errcheck': ['github.com/kisielk/errcheck'],
|
||||||
\ "golang.org/x/tools/cmd/goimports",
|
\ 'fillstruct': ['github.com/davidrjenni/reftools/cmd/fillstruct'],
|
||||||
\ "github.com/rogpeppe/godef",
|
\ 'gocode': ['github.com/nsf/gocode', {'windows': '-ldflags -H=windowsgui'}],
|
||||||
\ "golang.org/x/tools/cmd/oracle",
|
\ 'godef': ['github.com/rogpeppe/godef'],
|
||||||
\ "golang.org/x/tools/cmd/gorename",
|
\ 'gogetdoc': ['github.com/zmb3/gogetdoc'],
|
||||||
\ "github.com/golang/lint/golint",
|
\ 'goimports': ['golang.org/x/tools/cmd/goimports'],
|
||||||
\ "github.com/kisielk/errcheck",
|
\ 'golint': ['github.com/golang/lint/golint'],
|
||||||
\ "github.com/jstemmer/gotags",
|
\ 'gometalinter': ['github.com/alecthomas/gometalinter'],
|
||||||
\ "github.com/klauspost/asmfmt/cmd/asmfmt",
|
\ 'gomodifytags': ['github.com/fatih/gomodifytags'],
|
||||||
\ "github.com/fatih/motion",
|
\ 'gorename': ['golang.org/x/tools/cmd/gorename'],
|
||||||
\ ]
|
\ 'gotags': ['github.com/jstemmer/gotags'],
|
||||||
|
\ 'guru': ['golang.org/x/tools/cmd/guru'],
|
||||||
|
\ 'impl': ['github.com/josharian/impl'],
|
||||||
|
\ 'keyify': ['github.com/dominikh/go-tools/cmd/keyify'],
|
||||||
|
\ 'motion': ['github.com/fatih/motion'],
|
||||||
|
\ }
|
||||||
|
|
||||||
" These commands are available on any filetypes
|
" These commands are available on any filetypes
|
||||||
command! GoInstallBinaries call s:GoInstallBinaries(-1)
|
command! -nargs=* -complete=customlist,s:complete GoInstallBinaries call s:GoInstallBinaries(-1, <f-args>)
|
||||||
command! GoUpdateBinaries call s:GoInstallBinaries(1)
|
command! -nargs=* -complete=customlist,s:complete GoUpdateBinaries call s:GoInstallBinaries(1, <f-args>)
|
||||||
command! -nargs=? -complete=dir GoPath call go#path#GoPath(<f-args>)
|
command! -nargs=? -complete=dir GoPath call go#path#GoPath(<f-args>)
|
||||||
|
|
||||||
|
fun! s:complete(lead, cmdline, cursor)
|
||||||
|
return filter(keys(s:packages), 'strpart(v:val, 0, len(a:lead)) == a:lead')
|
||||||
|
endfun
|
||||||
|
|
||||||
" GoInstallBinaries downloads and install all necessary binaries stated in the
|
" GoInstallBinaries downloads and installs binaries defined in s:packages to
|
||||||
" packages variable. It uses by default $GOBIN or $GOPATH/bin as the binary
|
" $GOBIN or $GOPATH/bin. GoInstallBinaries will update already installed
|
||||||
" target install directory. GoInstallBinaries doesn't install binaries if they
|
" binaries only if updateBinaries = 1. By default, all packages in s:packages
|
||||||
" exist, to update current binaries pass 1 to the argument.
|
" will be installed, but the set can be limited by passing the desired
|
||||||
function! s:GoInstallBinaries(updateBinaries)
|
" packages in the unnamed arguments.
|
||||||
if $GOPATH == ""
|
function! s:GoInstallBinaries(updateBinaries, ...)
|
||||||
echohl Error
|
let err = s:CheckBinaries()
|
||||||
echomsg "vim.go: $GOPATH is not set"
|
if err != 0
|
||||||
echohl None
|
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let err = s:CheckBinaries()
|
if go#path#Default() == ""
|
||||||
if err != 0
|
echohl Error
|
||||||
|
echomsg "vim.go: $GOPATH is not set and 'go env GOPATH' returns empty"
|
||||||
|
echohl None
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -53,7 +84,7 @@ function! s:GoInstallBinaries(updateBinaries)
|
|||||||
let old_path = $PATH
|
let old_path = $PATH
|
||||||
|
|
||||||
" vim's executable path is looking in PATH so add our go_bin path to it
|
" vim's executable path is looking in PATH so add our go_bin path to it
|
||||||
let $PATH = $PATH . go#util#PathListSep() .go_bin_path
|
let $PATH = go_bin_path . go#util#PathListSep() . $PATH
|
||||||
|
|
||||||
" when shellslash is set on MS-* systems, shellescape puts single quotes
|
" when shellslash is set on MS-* systems, shellescape puts single quotes
|
||||||
" around the output string. cmd on Windows does not handle single quotes
|
" around the output string. cmd on Windows does not handle single quotes
|
||||||
@ -65,35 +96,59 @@ function! s:GoInstallBinaries(updateBinaries)
|
|||||||
set noshellslash
|
set noshellslash
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let cmd = "go get -u -v "
|
let cmd = "go get -v "
|
||||||
|
if get(g:, "go_get_update", 1) != 0
|
||||||
|
let cmd .= "-u "
|
||||||
|
endif
|
||||||
|
|
||||||
let s:go_version = matchstr(system("go version"), '\d.\d.\d')
|
let s:go_version = matchstr(go#util#System("go version"), '\d.\d.\d')
|
||||||
|
|
||||||
" https://github.com/golang/go/issues/10791
|
" https://github.com/golang/go/issues/10791
|
||||||
if s:go_version > "1.4.0" && s:go_version < "1.5.0"
|
if s:go_version > "1.4.0" && s:go_version < "1.5.0"
|
||||||
let cmd .= "-f "
|
let cmd .= "-f "
|
||||||
endif
|
endif
|
||||||
|
|
||||||
for pkg in s:packages
|
" Filter packages from arguments (if any).
|
||||||
let basename = fnamemodify(pkg, ":t")
|
let l:packages = {}
|
||||||
let binname = "go_" . basename . "_bin"
|
if a:0 > 0
|
||||||
|
for l:bin in a:000
|
||||||
|
let l:pkg = get(s:packages, l:bin, [])
|
||||||
|
if len(l:pkg) == 0
|
||||||
|
call go#util#EchoError('unknown binary: ' . l:bin)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
let l:packages[l:bin] = l:pkg
|
||||||
|
endfor
|
||||||
|
else
|
||||||
|
let l:packages = s:packages
|
||||||
|
endif
|
||||||
|
|
||||||
let bin = basename
|
let l:platform = ''
|
||||||
|
if go#util#IsWin()
|
||||||
|
let l:platform = 'windows'
|
||||||
|
endif
|
||||||
|
|
||||||
|
for [binary, pkg] in items(l:packages)
|
||||||
|
let l:importPath = pkg[0]
|
||||||
|
let l:goGetFlags = len(pkg) > 1 ? get(pkg[1], l:platform, '') : ''
|
||||||
|
|
||||||
|
let binname = "go_" . binary . "_bin"
|
||||||
|
|
||||||
|
let bin = binary
|
||||||
if exists("g:{binname}")
|
if exists("g:{binname}")
|
||||||
let bin = g:{binname}
|
let bin = g:{binname}
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if !executable(bin) || a:updateBinaries == 1
|
if !executable(bin) || a:updateBinaries == 1
|
||||||
if a:updateBinaries == 1
|
if a:updateBinaries == 1
|
||||||
echo "vim-go: Updating ". basename .". Reinstalling ". pkg . " to folder " . go_bin_path
|
echo "vim-go: Updating " . binary . ". Reinstalling ". importPath . " to folder " . go_bin_path
|
||||||
else
|
else
|
||||||
echo "vim-go: ". basename ." not found. Installing ". pkg . " to folder " . go_bin_path
|
echo "vim-go: ". binary ." not found. Installing ". importPath . " to folder " . go_bin_path
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
let out = go#util#System(printf('%s %s %s', cmd, l:goGetFlags, shellescape(importPath)))
|
||||||
let out = system(cmd . shellescape(pkg))
|
if go#util#ShellError() != 0
|
||||||
if v:shell_error
|
echom "Error installing " . importPath . ": " . out
|
||||||
echo "Error installing ". pkg . ": " . out
|
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
endfor
|
endfor
|
||||||
@ -123,6 +178,10 @@ endfunction
|
|||||||
" ============================================================================
|
" ============================================================================
|
||||||
"
|
"
|
||||||
function! s:echo_go_info()
|
function! s:echo_go_info()
|
||||||
|
if !get(g:, "go_echo_go_info", 1)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
if !exists('v:completed_item') || empty(v:completed_item)
|
if !exists('v:completed_item') || empty(v:completed_item)
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
@ -139,35 +198,81 @@ function! s:echo_go_info()
|
|||||||
redraws! | echo "vim-go: " | echohl Function | echon item.info | echohl None
|
redraws! | echo "vim-go: " | echohl Function | echon item.info | echohl None
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
function! s:auto_type_info()
|
||||||
|
" GoInfo automatic update
|
||||||
|
if get(g:, "go_auto_type_info", 0)
|
||||||
|
call go#tool#Info(1)
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:auto_sameids()
|
||||||
|
" GoSameId automatic update
|
||||||
|
if get(g:, "go_auto_sameids", 0)
|
||||||
|
call go#guru#SameIds()
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:fmt_autosave()
|
||||||
|
" Go code formatting on save
|
||||||
|
if get(g:, "go_fmt_autosave", 1)
|
||||||
|
call go#fmt#Format(-1)
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:asmfmt_autosave()
|
||||||
|
" Go asm formatting on save
|
||||||
|
if get(g:, "go_asmfmt_autosave", 0)
|
||||||
|
call go#asmfmt#Format()
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:metalinter_autosave()
|
||||||
|
" run gometalinter on save
|
||||||
|
if get(g:, "go_metalinter_autosave", 0)
|
||||||
|
call go#lint#Gometa(1)
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:template_autocreate()
|
||||||
|
" create new template from scratch
|
||||||
|
if get(g:, "go_template_autocreate", 1)
|
||||||
|
call go#template#create()
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
augroup vim-go
|
augroup vim-go
|
||||||
autocmd!
|
autocmd!
|
||||||
|
|
||||||
" GoInfo automatic update
|
autocmd CursorHold *.go call s:auto_type_info()
|
||||||
if get(g:, "go_auto_type_info", 0)
|
autocmd CursorHold *.go call s:auto_sameids()
|
||||||
autocmd CursorHold *.go nested call go#complete#Info(1)
|
|
||||||
endif
|
|
||||||
|
|
||||||
" Echo the identifier information when completion is done. Useful to see
|
" Echo the identifier information when completion is done. Useful to see
|
||||||
" the signature of a function, etc...
|
" the signature of a function, etc...
|
||||||
if exists('##CompleteDone')
|
if exists('##CompleteDone')
|
||||||
autocmd CompleteDone *.go nested call s:echo_go_info()
|
autocmd CompleteDone *.go call s:echo_go_info()
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" Go code formatting on save
|
autocmd BufWritePre *.go call s:fmt_autosave()
|
||||||
if get(g:, "go_fmt_autosave", 1)
|
autocmd BufWritePre *.s call s:asmfmt_autosave()
|
||||||
autocmd BufWritePre *.go call go#fmt#Format(-1)
|
autocmd BufWritePost *.go call s:metalinter_autosave()
|
||||||
endif
|
autocmd BufNewFile *.go call s:template_autocreate()
|
||||||
|
" clear SameIds when the buffer is unloaded so that loading another buffer
|
||||||
|
" in the same window doesn't highlight the most recently matched
|
||||||
|
" identifier's positions.
|
||||||
|
autocmd BufWinEnter *.go call go#guru#ClearSameIds()
|
||||||
|
|
||||||
" Go asm formatting on save
|
autocmd BufEnter *.go
|
||||||
if get(g:, "go_asmfmt_autosave", 1)
|
\ if get(g:, 'go_autodetect_gopath', 0) && !exists('b:old_gopath')
|
||||||
autocmd BufWritePre *.s call go#asmfmt#Format()
|
\| let b:old_gopath = exists('$GOPATH') ? $GOPATH : -1
|
||||||
endif
|
\| let $GOPATH = go#path#Detect()
|
||||||
|
\| endif
|
||||||
|
autocmd BufLeave *.go
|
||||||
|
\ if exists('b:old_gopath')
|
||||||
|
\| if b:old_gopath isnot -1
|
||||||
|
\| let $GOPATH = b:old_gopath
|
||||||
|
\| endif
|
||||||
|
\| unlet b:old_gopath
|
||||||
|
\| endif
|
||||||
|
augroup end
|
||||||
|
|
||||||
" run gometalinter on save
|
" vim: sw=2 ts=2 et
|
||||||
if get(g:, "go_metalinter_autosave", 0)
|
|
||||||
autocmd BufWritePost *.go call go#lint#Gometa(1)
|
|
||||||
endif
|
|
||||||
augroup END
|
|
||||||
|
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
|
||||||
|
|||||||
93
rplugin/python3/denite/source/decls.py
Normal file
93
rplugin/python3/denite/source/decls.py
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
# ============================================================================
|
||||||
|
# FILE: decls.py
|
||||||
|
# AUTHOR: delphinus <delphinus@remora.cx>
|
||||||
|
# License: MIT license
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import json
|
||||||
|
import denite.util
|
||||||
|
from .base import Base
|
||||||
|
|
||||||
|
DECLS_SYNTAX_HIGHLIGHT = [
|
||||||
|
{'name': 'FilePath', 're': r'[^:]*\ze:', 'link': 'Comment'},
|
||||||
|
{'name': 'Line', 're': r'\d\+\ze :', 'link': 'LineNr'},
|
||||||
|
{'name': 'WholeFunction', 're': r'\vfunc %(\([^)]+\) )?[^(]+'},
|
||||||
|
{'name': 'Function', 'parent': 'WholeFunction',
|
||||||
|
're': r'\S\+\ze(', 'link': 'Function'},
|
||||||
|
{'name': 'WholeType', 're': r'type \S\+'},
|
||||||
|
{'name': 'Type', 'parent': 'WholeType',
|
||||||
|
're': r'\v( )@<=\S+', 'link': 'Type'},
|
||||||
|
{'name': 'Separator', 're': r':', 'conceal': True},
|
||||||
|
{'name': 'SeparatorFunction', 'parent': 'WholeFunction',
|
||||||
|
're': r'func ', 'conceal': True},
|
||||||
|
{'name': 'SeparatorType', 'parent': 'WholeType',
|
||||||
|
're': r'type ', 'conceal': True},
|
||||||
|
]
|
||||||
|
|
||||||
|
class Source(Base):
|
||||||
|
|
||||||
|
def __init__(self, vim):
|
||||||
|
super().__init__(vim)
|
||||||
|
|
||||||
|
self.name = 'decls'
|
||||||
|
self.kind = 'file'
|
||||||
|
|
||||||
|
def gather_candidates(self, context):
|
||||||
|
bin_path = self.vim.call('go#path#CheckBinPath', 'motion')
|
||||||
|
if bin_path == '':
|
||||||
|
return []
|
||||||
|
|
||||||
|
expand = context['args'][0] if context['args'] else '%:p:h'
|
||||||
|
target = self.vim.funcs.expand(expand)
|
||||||
|
|
||||||
|
if os.path.isdir(target):
|
||||||
|
mode = 'dir'
|
||||||
|
elif os.path.isfile(target):
|
||||||
|
mode = 'file'
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
|
if self.vim.funcs.exists('g:go_decls_includes'):
|
||||||
|
include = self.vim.eval('g:go_decls_includes')
|
||||||
|
else:
|
||||||
|
include = 'func,type'
|
||||||
|
|
||||||
|
command = [bin_path, '-mode', 'decls', '-include', include,
|
||||||
|
'-' + mode, target]
|
||||||
|
|
||||||
|
try:
|
||||||
|
cmd = subprocess.run(command, stdout=subprocess.PIPE, check=True)
|
||||||
|
except subprocess.CalledProcessError as err:
|
||||||
|
denite.util.error(self.vim,
|
||||||
|
'command returned invalid response: ' + str(err))
|
||||||
|
return []
|
||||||
|
|
||||||
|
txt = cmd.stdout.decode('utf-8')
|
||||||
|
output = json.loads(txt, encoding='utf-8')
|
||||||
|
|
||||||
|
def make_candidates(row):
|
||||||
|
name = self.vim.funcs.fnamemodify(row['filename'], ':~:.')
|
||||||
|
return {
|
||||||
|
'word': '{0} :{1} :{2}'.format(name, row['line'], row['full']),
|
||||||
|
'action__path': row['filename'],
|
||||||
|
'action__line': row['line'],
|
||||||
|
'action__col': row['col'],
|
||||||
|
}
|
||||||
|
return list(map(make_candidates, output['decls']))
|
||||||
|
|
||||||
|
def highlight(self):
|
||||||
|
for syn in DECLS_SYNTAX_HIGHLIGHT:
|
||||||
|
containedin = self.syntax_name
|
||||||
|
containedin += '_' + syn['parent'] if 'parent' in syn else ''
|
||||||
|
conceal = ' conceal' if 'conceal' in syn else ''
|
||||||
|
|
||||||
|
self.vim.command(
|
||||||
|
'syntax match {0}_{1} /{2}/ contained containedin={3}{4}'
|
||||||
|
.format(self.syntax_name, syn['name'], syn['re'],
|
||||||
|
containedin, conceal))
|
||||||
|
|
||||||
|
if 'link' in syn:
|
||||||
|
self.vim.command('highlight default link {0}_{1} {2}'.format(
|
||||||
|
self.syntax_name, syn['name'], syn['link']))
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user