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: bf390af42c53ae217356d7763ac3e7767f0162a4main
parent
c9ca63a819
commit
c7496b2816
@ -0,0 +1,3 @@
|
|||||||
|
[run]
|
||||||
|
plugins = covimerage
|
||||||
|
data_file = .coverage.covimerage
|
@ -0,0 +1,2 @@
|
|||||||
|
.local/
|
||||||
|
.git/
|
@ -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
|
@ -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.
|
||||||
|
|
||||||
|
@ -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
|
|
||||||
|
|
||||||
|
@ -1 +1,5 @@
|
|||||||
doc/tags
|
.DS_Store
|
||||||
|
/doc/tags
|
||||||
|
/.coverage.covimerage
|
||||||
|
/coverage.xml
|
||||||
|
*.pyc
|
||||||
|
@ -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
|
@ -0,0 +1,7 @@
|
|||||||
|
policies:
|
||||||
|
ProhibitUnnecessaryDoubleQuote:
|
||||||
|
enabled: false
|
||||||
|
ProhibitEqualTildeOperator:
|
||||||
|
enabled: false
|
||||||
|
ProhibitNoAbortFunction:
|
||||||
|
enabled: false
|
File diff suppressed because it is too large
Load Diff
@ -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"]
|
@ -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
|
@ -1,282 +1,71 @@
|
|||||||
# vim-go
|
# vim-go [![Build Status](http://img.shields.io/travis/fatih/vim-go.svg?style=flat-square)](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.
|
|
||||||
|
|
||||||
![vim-go](https://dl.dropboxusercontent.com/u/174404/vim-go-2.png)
|
|
||||||
|
|
||||||
|
|
||||||
|
<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
|
* Compile your package with `:GoBuild`, install it with `:GoInstall` or test it
|
||||||
history
|
with `:GoTest`. Run a single tests with `:GoTestFunc`).
|
||||||
* Go to symbol/declaration with `:GoDef`
|
* Quickly execute your current file(s) with `:GoRun`.
|
||||||
* Look up documentation with `:GoDoc` inside Vim or open it in browser
|
* Improved syntax highlighting and folding.
|
||||||
* Automatically import packages via `:GoImport` or plug it into autosave
|
* Completion support via `gocode`.
|
||||||
* Compile your package with `:GoBuild`, install it with `:GoInstall` or test
|
* `gofmt` or `goimports` on save keeps the cursor position and undo history.
|
||||||
them with `:GoTest` (also supports running single tests via `:GoTestFunc`)
|
* Go to symbol/declaration with `:GoDef`.
|
||||||
* Quickly execute your current file/files with `:GoRun`
|
* Look up documentation with `:GoDoc` or `:GoDocBrowser`.
|
||||||
* Automatic `GOPATH` detection based on the directory structure (i.e. `gb`
|
* Easily import packages via `:GoImport`, remove them via `:GoDrop`.
|
||||||
projects, `godep` vendored projects)
|
* Automatic `GOPATH` detection which works with `gb` and `godep`. Change or
|
||||||
* Change or display `GOPATH` with `:GoPath`
|
display `GOPATH` with `:GoPath`.
|
||||||
* Create a coverage profile and display annotated source code in browser to see
|
* See which code is covered by tests with `:GoCoverage`.
|
||||||
which functions are covered with `:GoCoverage`
|
* Add or remove tags on struct fields with `:GoAddTags` and `:GoRemoveTags`.
|
||||||
* Call `gometalinter` with `:GoMetaLinter`, which invokes all possible linters
|
* Call `gometalinter` with `:GoMetaLinter` to invoke all possible linters
|
||||||
(golint, vet, errcheck, deadcode, etc..) and shows the warnings/errors
|
(`golint`, `vet`, `errcheck`, `deadcode`, etc.) and put the result in the
|
||||||
* Lint your code with `:GoLint`
|
quickfix or location list.
|
||||||
* Run your code through `:GoVet` to catch static errors
|
* Lint your code with `:GoLint`, run your code through `:GoVet` to catch static
|
||||||
* Advanced source analysis tools utilizing oracle, such as `:GoImplements`,
|
errors, or make sure errors are checked with `:GoErrCheck`.
|
||||||
`:GoCallees`, and `:GoReferrers`
|
* Advanced source analysis tools utilizing `guru`, such as `:GoImplements`,
|
||||||
* Precise type-safe renaming of identifiers with `:GoRename`
|
`:GoCallees`, and `:GoReferrers`.
|
||||||
* List all source files and dependencies
|
* Precise type-safe renaming of identifiers with `:GoRename`.
|
||||||
* Unchecked error checking with `:GoErrCheck`
|
* ... and many more! Please see [doc/vim-go.txt](doc/vim-go.txt) for more
|
||||||
* Integrated and improved snippets, supporting `ultisnips` or `neosnippet`
|
information.
|
||||||
* 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
|
|
||||||
|
|
||||||
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!
|
|
||||||
|
|
||||||
[https://www.patreon.com/fatih](https://www.patreon.com/fatih)
|
|
||||||
|
|
||||||
## 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:
|
||||||
|
|
||||||
* [Pathogen](https://github.com/tpope/vim-pathogen)
|
* [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)
|
||||||
* `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
|
|
||||||
|
|
||||||
## Mappings
|
|
||||||
|
|
||||||
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
|
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`).
|
||||||
|
|
||||||
* Go Authors for official vim plugins
|
We also have an [official vim-go tutorial](https://github.com/fatih/vim-go-tutorial).
|
||||||
* 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
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 747 KiB |
Binary file not shown.
After Width: | Height: | Size: 29 KiB |
@ -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 |
@ -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
|
@ -1,365 +1,311 @@
|
|||||||
if !exists("g:go_dispatch_enabled")
|
function! go#cmd#autowrite() abort
|
||||||
let g:go_dispatch_enabled = 0
|
if &autowrite == 1
|
||||||
endif
|
silent! wall
|
||||||
|
endif
|
||||||
function! go#cmd#autowrite()
|
|
||||||
if &autowrite == 1
|
|
||||||
silent wall
|
|
||||||
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)")
|
" compiles multiple packages. So we pass the `errors` package just as an
|
||||||
|
" placeholder with the current folder (indicated with '.'). We also pass -i
|
||||||
" escape all shell arguments before we pass it to make
|
" that tries to install the dependencies, this has the side effect that it
|
||||||
let goargs = go#util#Shelllist(goargs, 1)
|
" caches the build results, so every other build is faster.
|
||||||
|
let args =
|
||||||
|
\ ["build"] +
|
||||||
|
\ map(copy(a:000), "expand(v:val)") +
|
||||||
|
\ ["-i", ".", "errors"]
|
||||||
|
|
||||||
|
" Vim async.
|
||||||
|
if go#util#has_job()
|
||||||
|
if get(g:, 'go_echo_command_info', 1)
|
||||||
|
call go#util#EchoProgress("building dispatched ...")
|
||||||
|
endif
|
||||||
|
|
||||||
" create our command arguments. go build discards any results when it
|
call s:cmd_job({
|
||||||
" compiles multiple packages. So we pass the `errors` package just as an
|
\ 'cmd': ['go'] + args,
|
||||||
" placeholder with the current folder (indicated with '.')
|
\ 'bang': a:bang,
|
||||||
let args = ["build"] + goargs + [".", "errors"]
|
\ 'for': 'GoBuild',
|
||||||
|
\})
|
||||||
|
|
||||||
" if we have nvim, call it asynchronously and return early ;)
|
" Nvim async.
|
||||||
if has('nvim')
|
elseif has('nvim')
|
||||||
call go#util#EchoProgress("building dispatched ...")
|
if get(g:, 'go_echo_command_info', 1)
|
||||||
call go#jobcontrol#Spawn(a:bang, "build", args)
|
call go#util#EchoProgress("building dispatched ...")
|
||||||
return
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let old_gopath = $GOPATH
|
call go#jobcontrol#Spawn(a:bang, "build", "GoBuild", args)
|
||||||
let $GOPATH = go#path#Detect()
|
|
||||||
|
" Vim 7.4 without async
|
||||||
|
else
|
||||||
let default_makeprg = &makeprg
|
let default_makeprg = &makeprg
|
||||||
let &makeprg = "go " . join(args, ' ')
|
let &makeprg = "go " . join(go#util#Shelllist(args), ' ')
|
||||||
|
|
||||||
let l:listtype = go#list#Type("quickfix")
|
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 'lmake!'
|
||||||
silent! exe 'Make'
|
else
|
||||||
elseif l:listtype == "locationlist"
|
silent! exe 'make!'
|
||||||
silent! exe 'lmake!'
|
endif
|
||||||
else
|
redraw!
|
||||||
silent! exe 'make!'
|
|
||||||
endif
|
|
||||||
redraw!
|
|
||||||
finally
|
finally
|
||||||
execute cd . fnameescape(dir)
|
execute cd . fnameescape(dir)
|
||||||
endtry
|
endtry
|
||||||
|
|
||||||
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)
|
call go#list#JumpToFirst(l:listtype)
|
||||||
if !a:bang
|
|
||||||
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
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
" Run runs the current file (and their dependencies if any) in a new terminal.
|
" BuildTags sets or shows the current build tags used for tools
|
||||||
function! go#cmd#RunTerm(bang, mode, files)
|
function! go#cmd#BuildTags(bang, ...) abort
|
||||||
if empty(a:files)
|
if a:0
|
||||||
let cmd = "go run ". go#util#Shelljoin(go#tool#Files())
|
if a:0 == 1 && a:1 == '""'
|
||||||
|
unlet g:go_build_tags
|
||||||
|
call go#util#EchoSuccess("build tags are cleared")
|
||||||
else
|
else
|
||||||
let cmd = "go run ". go#util#Shelljoin(map(copy(a:files), "expand(v:val)"), 1)
|
let g:go_build_tags = a:1
|
||||||
|
call go#util#EchoSuccess("build tags are changed to: ". a:1)
|
||||||
endif
|
endif
|
||||||
call go#term#newmode(a:bang, cmd, a:mode)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Run runs the current file (and their dependencies if any) and outputs it.
|
return
|
||||||
" This is intented to test small programs and play with them. It's not
|
endif
|
||||||
" suitable for long running apps, because vim is blocking by default and
|
|
||||||
" calling long running apps will block the whole UI.
|
|
||||||
function! go#cmd#Run(bang, ...)
|
|
||||||
if has('nvim')
|
|
||||||
call go#cmd#RunTerm(a:bang, '', a:000)
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
|
|
||||||
let old_gopath = $GOPATH
|
if !exists('g:go_build_tags')
|
||||||
let $GOPATH = go#path#Detect()
|
call go#util#EchoSuccess("build tags are not set")
|
||||||
|
else
|
||||||
if go#util#IsWin()
|
call go#util#EchoSuccess("current build tags: ". g:go_build_tags)
|
||||||
exec '!go run ' . go#util#Shelljoin(go#tool#Files())
|
endif
|
||||||
if v:shell_error
|
endfunction
|
||||||
redraws! | echon "vim-go: [run] " | echohl ErrorMsg | echon "FAILED"| echohl None
|
|
||||||
else
|
|
||||||
redraws! | echon "vim-go: [run] " | echohl Function | echon "SUCCESS"| echohl None
|
|
||||||
endif
|
|
||||||
|
|
||||||
let $GOPATH = old_gopath
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
|
|
||||||
" :make expands '%' and '#' wildcards, so they must also be escaped
|
" Run runs the current file (and their dependencies if any) in a new terminal.
|
||||||
let default_makeprg = &makeprg
|
function! go#cmd#RunTerm(bang, mode, files) abort
|
||||||
if a:0 == 0
|
if empty(a:files)
|
||||||
let &makeprg = 'go run ' . go#util#Shelljoin(go#tool#Files(), 1)
|
let cmd = "go run ". go#util#Shelljoin(go#tool#Files())
|
||||||
else
|
else
|
||||||
let &makeprg = "go run " . go#util#Shelljoin(map(copy(a:000), "expand(v:val)"), 1)
|
let cmd = "go run ". go#util#Shelljoin(map(copy(a:files), "expand(v:val)"), 1)
|
||||||
endif
|
endif
|
||||||
|
call go#term#newmode(a:bang, cmd, a:mode)
|
||||||
let l:listtype = go#list#Type("quickfix")
|
endfunction
|
||||||
|
|
||||||
if g:go_dispatch_enabled && exists(':Make') == 2
|
" Run runs the current file (and their dependencies if any) and outputs it.
|
||||||
silent! exe 'Make'
|
" This is intended to test small programs and play with them. It's not
|
||||||
elseif l:listtype == "locationlist"
|
" suitable for long running apps, because vim is blocking by default and
|
||||||
exe 'lmake!'
|
" calling long running apps will block the whole UI.
|
||||||
|
function! go#cmd#Run(bang, ...) abort
|
||||||
|
if has('nvim')
|
||||||
|
call go#cmd#RunTerm(a:bang, '', a:000)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
if go#util#has_job()
|
||||||
|
" 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()
|
||||||
|
exec '!go run ' . go#util#Shelljoin(go#tool#Files())
|
||||||
|
if v:shell_error
|
||||||
|
redraws! | echon "vim-go: [run] " | echohl ErrorMsg | echon "FAILED"| echohl None
|
||||||
else
|
else
|
||||||
exe 'make!'
|
redraws! | echon "vim-go: [run] " | echohl Function | echon "SUCCESS"| echohl None
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let items = go#list#Get(l:listtype)
|
return
|
||||||
let errors = go#tool#FilterValids(items)
|
endif
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
let $GOPATH = old_gopath
|
" :make expands '%' and '#' wildcards, so they must also be escaped
|
||||||
let &makeprg = default_makeprg
|
let default_makeprg = &makeprg
|
||||||
endfunction
|
if a:0 == 0
|
||||||
|
let &makeprg = 'go run ' . go#util#Shelljoin(go#tool#Files(), 1)
|
||||||
|
else
|
||||||
|
let &makeprg = "go run " . go#util#Shelljoin(map(copy(a:000), "expand(v:val)"), 1)
|
||||||
|
endif
|
||||||
|
|
||||||
" Install installs the package by simple calling 'go install'. If any argument
|
let l:listtype = go#list#Type("GoRun")
|
||||||
" is given(which are passed directly to 'go install') it tries to install those
|
|
||||||
" packages. Errors are populated in the location window.
|
|
||||||
function! go#cmd#Install(bang, ...)
|
|
||||||
let default_makeprg = &makeprg
|
|
||||||
|
|
||||||
" :make expands '%' and '#' wildcards, so they must also be escaped
|
if l:listtype == "locationlist"
|
||||||
let goargs = go#util#Shelljoin(map(copy(a:000), "expand(v:val)"), 1)
|
exe 'lmake!'
|
||||||
let &makeprg = "go install " . goargs
|
else
|
||||||
|
exe 'make!'
|
||||||
|
endif
|
||||||
|
|
||||||
let l:listtype = go#list#Type("quickfix")
|
let items = go#list#Get(l:listtype)
|
||||||
" execute make inside the source folder so we can parse the errors
|
let errors = go#tool#FilterValids(items)
|
||||||
" correctly
|
|
||||||
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
|
||||||
let dir = getcwd()
|
|
||||||
try
|
|
||||||
execute cd . fnameescape(expand("%:p:h"))
|
|
||||||
if g:go_dispatch_enabled && exists(':Make') == 2
|
|
||||||
call go#util#EchoProgress("building dispatched ...")
|
|
||||||
silent! exe 'Make'
|
|
||||||
elseif l:listtype == "locationlist"
|
|
||||||
silent! exe 'lmake!'
|
|
||||||
else
|
|
||||||
silent! exe 'make!'
|
|
||||||
endif
|
|
||||||
redraw!
|
|
||||||
finally
|
|
||||||
execute cd . fnameescape(dir)
|
|
||||||
endtry
|
|
||||||
|
|
||||||
let errors = go#list#Get(l:listtype)
|
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)
|
if !empty(errors) && !a:bang
|
||||||
if !a:bang
|
call go#list#JumpToFirst(l:listtype)
|
||||||
call go#list#JumpToFirst(l:listtype)
|
endif
|
||||||
endif
|
|
||||||
else
|
|
||||||
redraws! | echon "vim-go: " | echohl Function | echon "installed to ". $GOPATH | echohl None
|
|
||||||
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
|
" Install installs the package by simple calling 'go install'. If any argument
|
||||||
" compile the tests instead of running them (useful to catch errors in the
|
" is given(which are passed directly to 'go install') it tries to install
|
||||||
" test files). Any other argument is appendend to the final `go test` command
|
" those packages. Errors are populated in the location window.
|
||||||
function! go#cmd#Test(bang, compile, ...)
|
function! go#cmd#Install(bang, ...) abort
|
||||||
let args = ["test"]
|
" use vim's job functionality to call it asynchronously
|
||||||
|
if go#util#has_job()
|
||||||
" don't run the test, only compile it. Useful to capture and fix errors or
|
" expand all wildcards(i.e: '%' to the current file name)
|
||||||
" to create a test binary.
|
let goargs = map(copy(a:000), "expand(v:val)")
|
||||||
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_echo_command_info', 1)
|
||||||
if get(g:, 'go_term_enabled', 0)
|
call go#util#EchoProgress("installing dispatched ...")
|
||||||
call go#term#new(a:bang, ["go"] + args)
|
|
||||||
else
|
|
||||||
call go#jobcontrol#Spawn(a:bang, "test", args)
|
|
||||||
endif
|
|
||||||
return
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
call go#cmd#autowrite()
|
call s:cmd_job({
|
||||||
redraw
|
\ 'cmd': ['go', 'install'] + goargs,
|
||||||
|
\ 'bang': a:bang,
|
||||||
let command = "go " . join(args, ' ')
|
\ 'for': 'GoInstall',
|
||||||
|
\})
|
||||||
let out = go#tool#ExecuteInDir(command)
|
return
|
||||||
|
endif
|
||||||
let l:listtype = "quickfix"
|
|
||||||
|
let default_makeprg = &makeprg
|
||||||
if v:shell_error
|
|
||||||
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
" :make expands '%' and '#' wildcards, so they must also be escaped
|
||||||
let dir = getcwd()
|
let goargs = go#util#Shelljoin(map(copy(a:000), "expand(v:val)"), 1)
|
||||||
try
|
let &makeprg = "go install " . goargs
|
||||||
execute cd fnameescape(expand("%:p:h"))
|
|
||||||
let errors = go#tool#ParseErrors(split(out, '\n'))
|
let l:listtype = go#list#Type("GoInstall")
|
||||||
let errors = go#tool#FilterValids(errors)
|
" execute make inside the source folder so we can parse the errors
|
||||||
finally
|
" correctly
|
||||||
execute cd . fnameescape(dir)
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
||||||
endtry
|
let dir = getcwd()
|
||||||
|
try
|
||||||
call go#list#Populate(l:listtype, errors)
|
execute cd . fnameescape(expand("%:p:h"))
|
||||||
call go#list#Window(l:listtype, len(errors))
|
if l:listtype == "locationlist"
|
||||||
if !empty(errors) && !a:bang
|
silent! exe 'lmake!'
|
||||||
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
|
else
|
||||||
call go#list#Clean(l:listtype)
|
silent! exe 'make!'
|
||||||
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
|
endif
|
||||||
|
redraw!
|
||||||
|
finally
|
||||||
|
execute cd . fnameescape(dir)
|
||||||
|
endtry
|
||||||
|
|
||||||
|
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)
|
||||||
|
else
|
||||||
|
call go#util#EchoSuccess("installed to ". go#path#Default())
|
||||||
|
endif
|
||||||
|
|
||||||
|
let &makeprg = default_makeprg
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Testfunc runs a single test that surrounds the current cursor position.
|
" Generate runs 'go generate' in similar fashion to go#cmd#Build()
|
||||||
" Arguments are passed to the `go test` command.
|
function! go#cmd#Generate(bang, ...) abort
|
||||||
function! go#cmd#TestFunc(bang, ...)
|
let default_makeprg = &makeprg
|
||||||
" search flags legend (used only)
|
|
||||||
" 'b' search backward instead of forward
|
" :make expands '%' and '#' wildcards, so they must also be escaped
|
||||||
" 'c' accept a match at the cursor position
|
let goargs = go#util#Shelljoin(map(copy(a:000), "expand(v:val)"), 1)
|
||||||
" 'n' do Not move the cursor
|
if go#util#ShellError() != 0
|
||||||
" 'W' don't wrap around the end of the file
|
let &makeprg = "go generate " . goargs
|
||||||
"
|
else
|
||||||
" for the full list
|
let gofiles = go#util#Shelljoin(go#tool#Files(), 1)
|
||||||
" :help search
|
let &makeprg = "go generate " . goargs . ' ' . gofiles
|
||||||
let test = search("func Test", "bcnW")
|
endif
|
||||||
|
|
||||||
if test == 0
|
let l:listtype = go#list#Type("GoGenerate")
|
||||||
echo "vim-go: [test] no test found immediate to cursor"
|
|
||||||
return
|
echon "vim-go: " | echohl Identifier | echon "generating ..."| echohl None
|
||||||
end
|
if l:listtype == "locationlist"
|
||||||
|
silent! exe 'lmake!'
|
||||||
let line = getline(test)
|
else
|
||||||
let name = split(split(line, " ")[1], "(")[0]
|
silent! exe 'make!'
|
||||||
let args = [a:bang, 0, "-run", name . "$"]
|
endif
|
||||||
|
redraw!
|
||||||
if a:0
|
|
||||||
call extend(args, a:000)
|
let errors = go#list#Get(l:listtype)
|
||||||
|
call go#list#Window(l:listtype, len(errors))
|
||||||
|
if !empty(errors)
|
||||||
|
if !a:bang
|
||||||
|
call go#list#JumpToFirst(l:listtype)
|
||||||
endif
|
endif
|
||||||
|
else
|
||||||
|
redraws! | echon "vim-go: " | echohl Function | echon "[generate] SUCCESS"| echohl None
|
||||||
|
endif
|
||||||
|
|
||||||
call call('go#cmd#Test', args)
|
let &makeprg = default_makeprg
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Coverage creates a new cover profile with 'go test -coverprofile' and opens
|
" ---------------------
|
||||||
" a new HTML coverage page from that profile.
|
" | Vim job callbacks |
|
||||||
function! go#cmd#Coverage(bang, ...)
|
" ---------------------
|
||||||
let l:tmpname=tempname()
|
|
||||||
|
|
||||||
let command = "go test -coverprofile=" . l:tmpname . ' ' . go#util#Shelljoin(a:000)
|
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",
|
||||||
|
\})
|
||||||
|
|
||||||
let l:listtype = "quickfix"
|
" autowrite is not enabled for jobs
|
||||||
call go#cmd#autowrite()
|
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
|
function! s:error_info_cb(job, exit_status, data) closure abort
|
||||||
call go#tool#ExecuteInDir(openHTML)
|
let status = {
|
||||||
endif
|
\ 'desc': 'last status',
|
||||||
|
\ 'type': a:args.cmd[1],
|
||||||
|
\ 'state': "success",
|
||||||
|
\ }
|
||||||
|
|
||||||
call delete(l:tmpname)
|
if a:exit_status
|
||||||
endfunction
|
let status.state = "failed"
|
||||||
|
endif
|
||||||
|
|
||||||
" Generate runs 'go generate' in similar fashion to go#cmd#Build()
|
let elapsed_time = reltimestr(reltime(started_at))
|
||||||
function! go#cmd#Generate(bang, ...)
|
" strip whitespace
|
||||||
let default_makeprg = &makeprg
|
let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '')
|
||||||
|
let status.state .= printf(" (%ss)", elapsed_time)
|
||||||
|
|
||||||
let old_gopath = $GOPATH
|
call go#statusline#Update(status_dir, status)
|
||||||
let $GOPATH = go#path#Detect()
|
endfunction
|
||||||
|
|
||||||
" :make expands '%' and '#' wildcards, so they must also be escaped
|
let a:args.error_info_cb = funcref('s:error_info_cb')
|
||||||
let goargs = go#util#Shelljoin(map(copy(a:000), "expand(v:val)"), 1)
|
let callbacks = go#job#Spawn(a:args)
|
||||||
if v:shell_error
|
|
||||||
let &makeprg = "go generate " . goargs
|
|
||||||
else
|
|
||||||
let gofiles = go#util#Shelljoin(go#tool#Files(), 1)
|
|
||||||
let &makeprg = "go generate " . goargs . ' ' . gofiles
|
|
||||||
endif
|
|
||||||
|
|
||||||
let l:listtype = go#list#Type("quickfix")
|
let start_options = {
|
||||||
|
\ 'callback': callbacks.callback,
|
||||||
|
\ 'exit_cb': callbacks.exit_cb,
|
||||||
|
\ }
|
||||||
|
|
||||||
echon "vim-go: " | echohl Identifier | echon "generating ..."| echohl None
|
" pre start
|
||||||
if g:go_dispatch_enabled && exists(':Make') == 2
|
let dir = getcwd()
|
||||||
silent! exe 'Make'
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
||||||
elseif l:listtype == "locationlist"
|
let jobdir = fnameescape(expand("%:p:h"))
|
||||||
silent! exe 'lmake!'
|
execute cd . jobdir
|
||||||
else
|
|
||||||
silent! exe 'make!'
|
|
||||||
endif
|
|
||||||
redraw!
|
|
||||||
|
|
||||||
let errors = go#list#Get(l:listtype)
|
call job_start(a:args.cmd, start_options)
|
||||||
call go#list#Window(l:listtype, len(errors))
|
|
||||||
if !empty(errors)
|
|
||||||
if !a:bang
|
|
||||||
call go#list#JumpToFirst(l:listtype)
|
|
||||||
endif
|
|
||||||
else
|
|
||||||
redraws! | echon "vim-go: " | echohl Function | echon "[generate] SUCCESS"| echohl None
|
|
||||||
endif
|
|
||||||
|
|
||||||
let &makeprg = default_makeprg
|
" post start
|
||||||
let $GOPATH = old_gopath
|
execute cd . fnameescape(dir)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
" vim: sw=2 ts=2 et
|
||||||
|
@ -1,170 +1,172 @@
|
|||||||
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
|
||||||
|
let file = tempname()
|
||||||
|
call writefile(go#util#GetLines(), file)
|
||||||
|
return file
|
||||||
|
endfunction
|
||||||
|
|
||||||
fu! s:gocodeCurrentBuffer()
|
function! s:gocodeCommand(cmd, preargs, args) abort
|
||||||
let buf = getline(1, '$')
|
for i in range(0, len(a:args) - 1)
|
||||||
|
let a:args[i] = go#util#Shellescape(a:args[i])
|
||||||
|
endfor
|
||||||
|
for i in range(0, len(a:preargs) - 1)
|
||||||
|
let a:preargs[i] = go#util#Shellescape(a:preargs[i])
|
||||||
|
endfor
|
||||||
|
|
||||||
|
let bin_path = go#path#CheckBinPath("gocode")
|
||||||
|
if empty(bin_path)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
" We might hit cache problems, as gocode doesn't handle different GOPATHs
|
||||||
|
" well. See: https://github.com/nsf/gocode/issues/239
|
||||||
|
let old_goroot = $GOROOT
|
||||||
|
let $GOROOT = go#util#env("goroot")
|
||||||
|
|
||||||
|
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 result = go#util#System(cmd)
|
||||||
|
finally
|
||||||
|
let $GOROOT = old_goroot
|
||||||
|
endtry
|
||||||
|
|
||||||
|
if go#util#ShellError() != 0
|
||||||
|
return "[\"0\", []]"
|
||||||
|
else
|
||||||
if &encoding != 'utf-8'
|
if &encoding != 'utf-8'
|
||||||
let buf = map(buf, 'iconv(v:val, &encoding, "utf-8")')
|
let result = iconv(result, 'utf-8', &encoding)
|
||||||
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
|
endif
|
||||||
let file = tempname()
|
return result
|
||||||
call writefile(buf, file)
|
endif
|
||||||
|
endfunction
|
||||||
return file
|
|
||||||
endf
|
|
||||||
|
|
||||||
if go#vimproc#has_vimproc()
|
|
||||||
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)
|
|
||||||
let a:args[i] = s:gocodeShellescape(a:args[i])
|
|
||||||
endfor
|
|
||||||
for i in range(0, len(a:preargs) - 1)
|
|
||||||
let a:preargs[i] = s:gocodeShellescape(a:preargs[i])
|
|
||||||
endfor
|
|
||||||
|
|
||||||
let bin_path = go#path#CheckBinPath(g:go_gocode_bin)
|
|
||||||
if empty(bin_path)
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
|
|
||||||
" we might hit cache problems, as gocode doesn't handle well different
|
|
||||||
" GOPATHS: https://github.com/nsf/gocode/issues/239
|
|
||||||
let old_gopath = $GOPATH
|
|
||||||
let $GOPATH = go#path#Detect()
|
|
||||||
|
|
||||||
let result = s:system(printf('%s %s %s %s', s:gocodeShellescape(bin_path), join(a:preargs), s:gocodeShellescape(a:cmd), join(a:args)))
|
function! s:gocodeCurrentBufferOpt(filename) abort
|
||||||
|
return '-in=' . a:filename
|
||||||
|
endfunction
|
||||||
|
|
||||||
let $GOPATH = old_gopath
|
let s:optionsEnabled = 0
|
||||||
|
function! s:gocodeEnableOptions() abort
|
||||||
|
if s:optionsEnabled
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
if s:shell_error() != 0
|
let bin_path = go#path#CheckBinPath("gocode")
|
||||||
return "[\"0\", []]"
|
if empty(bin_path)
|
||||||
else
|
return
|
||||||
if &encoding != 'utf-8'
|
endif
|
||||||
let result = iconv(result, 'utf-8', &encoding)
|
|
||||||
endif
|
|
||||||
return result
|
|
||||||
endif
|
|
||||||
endf
|
|
||||||
|
|
||||||
fu! s:gocodeCurrentBufferOpt(filename)
|
let s:optionsEnabled = 1
|
||||||
return '-in=' . a:filename
|
|
||||||
endf
|
|
||||||
|
|
||||||
fu! s:gocodeAutocomplete()
|
call go#util#System(printf('%s set propose-builtins %s', go#util#Shellescape(bin_path), s:toBool(get(g:, 'go_gocode_propose_builtins', 1))))
|
||||||
let filename = s:gocodeCurrentBuffer()
|
call go#util#System(printf('%s set autobuild %s', go#util#Shellescape(bin_path), s:toBool(get(g:, 'go_gocode_autobuild', 1))))
|
||||||
let result = s:gocodeCommand('autocomplete',
|
call go#util#System(printf('%s set unimported-packages %s', go#util#Shellescape(bin_path), s:toBool(get(g:, 'go_gocode_unimported_packages', 0))))
|
||||||
\ [s:gocodeCurrentBufferOpt(filename), '-f=vim'],
|
endfunction
|
||||||
\ [expand('%:p'), go#util#OffsetCursor()])
|
|
||||||
call delete(filename)
|
|
||||||
return result
|
|
||||||
endf
|
|
||||||
|
|
||||||
function! go#complete#GetInfo()
|
function! s:toBool(val) abort
|
||||||
let offset = go#util#OffsetCursor()+1
|
if a:val | return 'true ' | else | return 'false' | endif
|
||||||
let filename = s:gocodeCurrentBuffer()
|
endfunction
|
||||||
let result = s:gocodeCommand('autocomplete',
|
|
||||||
\ [s:gocodeCurrentBufferOpt(filename), '-f=godit'],
|
|
||||||
\ [expand('%:p'), offset])
|
|
||||||
call delete(filename)
|
|
||||||
|
|
||||||
" first line is: Charcount,,NumberOfCandidates, i.e: 8,,1
|
|
||||||
" following lines are candiates, i.e: func foo(name string),,foo(
|
|
||||||
let out = split(result, '\n')
|
|
||||||
|
|
||||||
" no candidates are found
|
|
||||||
if len(out) == 1
|
|
||||||
return ""
|
|
||||||
endif
|
|
||||||
|
|
||||||
" only one candiate is found
|
function! s:gocodeAutocomplete() abort
|
||||||
if len(out) == 2
|
call s:gocodeEnableOptions()
|
||||||
return split(out[1], ',,')[0]
|
|
||||||
endif
|
|
||||||
|
|
||||||
" to many candidates are available, pick one that maches the word under the
|
let filename = s:gocodeCurrentBuffer()
|
||||||
" cursor
|
let result = s:gocodeCommand('autocomplete',
|
||||||
let infos = []
|
\ [s:gocodeCurrentBufferOpt(filename), '-f=vim'],
|
||||||
for info in out[1:]
|
\ [expand('%:p'), go#util#OffsetCursor()])
|
||||||
call add(infos, split(info, ',,')[0])
|
call delete(filename)
|
||||||
endfor
|
return result
|
||||||
|
endfunction
|
||||||
|
|
||||||
let wordMatch = '\<' . expand("<cword>") . '\>'
|
function! go#complete#GetInfo() abort
|
||||||
" escape single quotes in wordMatch before passing it to filter
|
let offset = go#util#OffsetCursor()+1
|
||||||
let wordMatch = substitute(wordMatch, "'", "''", "g")
|
let filename = s:gocodeCurrentBuffer()
|
||||||
let filtered = filter(infos, "v:val =~ '".wordMatch."'")
|
let result = s:gocodeCommand('autocomplete',
|
||||||
|
\ [s:gocodeCurrentBufferOpt(filename), '-f=godit'],
|
||||||
|
\ [expand('%:p'), offset])
|
||||||
|
call delete(filename)
|
||||||
|
|
||||||
if len(filtered) == 1
|
" first line is: Charcount,,NumberOfCandidates, i.e: 8,,1
|
||||||
return filtered[0]
|
" following lines are candiates, i.e: func foo(name string),,foo(
|
||||||
endif
|
let out = split(result, '\n')
|
||||||
|
|
||||||
|
" no candidates are found
|
||||||
|
if len(out) == 1
|
||||||
return ""
|
return ""
|
||||||
|
endif
|
||||||
|
|
||||||
|
" only one candidate is found
|
||||||
|
if len(out) == 2
|
||||||
|
return split(out[1], ',,')[0]
|
||||||
|
endif
|
||||||
|
|
||||||
|
" to many candidates are available, pick one that maches the word under the
|
||||||
|
" cursor
|
||||||
|
let infos = []
|
||||||
|
for info in out[1:]
|
||||||
|
call add(infos, split(info, ',,')[0])
|
||||||
|
endfor
|
||||||
|
|
||||||
|
let wordMatch = '\<' . expand("<cword>") . '\>'
|
||||||
|
" escape single quotes in wordMatch before passing it to filter
|
||||||
|
let wordMatch = substitute(wordMatch, "'", "''", "g")
|
||||||
|
let filtered = filter(infos, "v:val =~ '".wordMatch."'")
|
||||||
|
|
||||||
|
if len(filtered) == 1
|
||||||
|
return filtered[0]
|
||||||
|
endif
|
||||||
|
|
||||||
|
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)
|
||||||
" if auto, and the result is a PANIC by gocode, hide it
|
" if auto, and the result is a PANIC by gocode, hide it
|
||||||
if a:auto && result ==# 'PANIC PANIC PANIC' | return | endif
|
if a:auto && result ==# 'PANIC PANIC PANIC' | return | endif
|
||||||
echo "vim-go: " | echohl Function | echon result | echohl None
|
echo "vim-go: " | echohl Function | echon result | echohl None
|
||||||
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()
|
||||||
return col('.') - g:gocomplete_completions[0] - 1
|
return col('.') - g:gocomplete_completions[0] - 1
|
||||||
"findstart = 0 when we need to return the list of completions
|
"findstart = 0 when we need to return the list of completions
|
||||||
else
|
else
|
||||||
let s = getline(".")[col('.') - 1]
|
let s = getline(".")[col('.') - 1]
|
||||||
if s =~ '[(){}\{\}]'
|
if s =~ '[(){}\{\}]'
|
||||||
return map(copy(g:gocomplete_completions[1]), 's:trim_bracket(v:val)')
|
return map(copy(g:gocomplete_completions[1]), 's:trim_bracket(v:val)')
|
||||||
endif
|
|
||||||
return g:gocomplete_completions[1]
|
|
||||||
endif
|
endif
|
||||||
|
return g:gocomplete_completions[1]
|
||||||
|
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
|
||||||
|
@ -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
|
@ -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
|
|
||||||
|
function! go#def#Jump(mode) abort
|
||||||
if go#vimproc#has_vimproc()
|
let fname = fnamemodify(expand("%"), ':p:gs?\\?/?')
|
||||||
let s:vim_system = get(g:, 'gocomplete#system_function', 'vimproc#system2')
|
|
||||||
else
|
" so guru right now is slow for some people. previously we were using
|
||||||
let s:vim_system = get(g:, 'gocomplete#system_function', 'system')
|
" godef which also has it's own quirks. But this issue come up so many
|
||||||
endif
|
" 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
|
||||||
fu! s:system(str, ...)
|
let bin_name = get(g:, 'go_def_mode', 'guru')
|
||||||
return call(s:vim_system, [a:str] + a:000)
|
if bin_name == 'godef'
|
||||||
endf
|
if &modified
|
||||||
|
" Write current unsaved buffer to a temp file and use the modified content
|
||||||
" modified and improved version of vim-godef
|
let l:tmpname = tempname()
|
||||||
function! go#def#Jump(...)
|
call writefile(go#util#GetLines(), l:tmpname)
|
||||||
if !len(a:000)
|
let fname = l:tmpname
|
||||||
let arg = "-o=" . go#util#OffsetCursor()
|
endif
|
||||||
else
|
|
||||||
let arg = a:1
|
let bin_path = go#path#CheckBinPath("godef")
|
||||||
endif
|
if empty(bin_path)
|
||||||
|
return
|
||||||
let bin_path = go#path#CheckBinPath(g:go_godef_bin)
|
endif
|
||||||
if empty(bin_path)
|
let command = printf("%s -f=%s -o=%s -t", go#util#Shellescape(bin_path),
|
||||||
return
|
\ go#util#Shellescape(fname), go#util#OffsetCursor())
|
||||||
endif
|
let out = go#util#System(command)
|
||||||
|
if exists("l:tmpname")
|
||||||
let old_gopath = $GOPATH
|
call delete(l:tmpname)
|
||||||
let $GOPATH = go#path#Detect()
|
endif
|
||||||
|
elseif bin_name == 'guru'
|
||||||
let fname = fnamemodify(expand("%"), ':p:gs?\\?/?')
|
let bin_path = go#path#CheckBinPath("guru")
|
||||||
let command = bin_path . " -f=" . shellescape(fname) . " -i " . shellescape(arg)
|
if empty(bin_path)
|
||||||
|
return
|
||||||
" get output of godef
|
endif
|
||||||
let out = s:system(command, join(getbufline(bufnr('%'), 1, '$'), go#util#LineEnding()))
|
|
||||||
|
let cmd = [bin_path]
|
||||||
" jump to it
|
let stdin_content = ""
|
||||||
call s:godefJump(out, "")
|
|
||||||
let $GOPATH = old_gopath
|
if &modified
|
||||||
|
let content = join(go#util#GetLines(), "\n")
|
||||||
|
let stdin_content = fname . "\n" . strlen(content) . "\n" . content
|
||||||
|
call add(cmd, "-modified")
|
||||||
|
endif
|
||||||
|
|
||||||
|
if exists('g:go_build_tags')
|
||||||
|
let tags = get(g:, 'go_build_tags')
|
||||||
|
call extend(cmd, ["-tags", tags])
|
||||||
|
endif
|
||||||
|
|
||||||
|
let fname = fname.':#'.go#util#OffsetCursor()
|
||||||
|
call extend(cmd, ["definition", fname])
|
||||||
|
|
||||||
|
if go#util#has_job()
|
||||||
|
let l:spawn_args = {
|
||||||
|
\ 'cmd': cmd,
|
||||||
|
\ 'custom_cb': function('s:jump_to_declaration_cb', [a:mode, bin_name]),
|
||||||
|
\ }
|
||||||
|
|
||||||
|
if &modified
|
||||||
|
let l:spawn_args.input = stdin_content
|
||||||
|
endif
|
||||||
|
|
||||||
|
call go#util#EchoProgress("searching declaration ...")
|
||||||
|
|
||||||
|
call s:def_job(spawn_args)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let command = join(cmd, " ")
|
||||||
|
if &modified
|
||||||
|
let out = go#util#System(command, stdin_content)
|
||||||
|
else
|
||||||
|
let out = go#util#System(command)
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
call go#util#EchoError('go_def_mode value: '. bin_name .' is not valid. Valid values are: [godef, guru]')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
if go#util#ShellError() != 0
|
||||||
|
call go#util#EchoError(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
|
||||||
|
" modes of switchbuf which we need based on the split mode
|
||||||
|
let old_switchbuf = &switchbuf
|
||||||
|
|
||||||
|
normal! m'
|
||||||
|
if filename != fnamemodify(expand("%"), ':p:gs?\\?/?')
|
||||||
|
" jump to existing buffer if, 1. we have enabled it, 2. the buffer is loaded
|
||||||
|
" and 3. there is buffer window number we switch to
|
||||||
|
if get(g:, 'go_def_reuse_buffer', 0) && bufloaded(filename) != 0 && bufwinnr(filename) != -1
|
||||||
|
" jumpt to existing buffer if it exists
|
||||||
|
execute bufwinnr(filename) . 'wincmd w'
|
||||||
|
else
|
||||||
|
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
|
||||||
|
elseif a:mode == "vsplit"
|
||||||
|
vsplit
|
||||||
|
endif
|
||||||
|
|
||||||
|
" open the file and jump to line and column
|
||||||
|
exec cmd fnameescape(fnamemodify(filename, ':.'))
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
call cursor(line, col)
|
||||||
|
|
||||||
|
" also align the line to middle of the view
|
||||||
|
normal! zz
|
||||||
|
|
||||||
|
let &switchbuf = old_switchbuf
|
||||||
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
|
||||||
|
|
||||||
function! go#def#JumpMode(mode)
|
call go#ui#CloseWindow()
|
||||||
let arg = "-o=" . go#util#OffsetCursor()
|
endfunction
|
||||||
|
|
||||||
let bin_path = go#path#CheckBinPath(g:go_godef_bin)
|
function! go#def#StackUI() abort
|
||||||
if empty(bin_path)
|
if len(s:go_stack) == 0
|
||||||
return
|
call go#util#EchoError("godef stack empty")
|
||||||
endif
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
let old_gopath = $GOPATH
|
let stackOut = ['" <Up>,<Down>:navigate <Enter>:jump <Esc>,q:exit']
|
||||||
let $GOPATH = go#path#Detect()
|
|
||||||
|
|
||||||
let fname = fnamemodify(expand("%"), ':p:gs?\\?/?')
|
let i = 0
|
||||||
let command = bin_path . " -f=" . shellescape(fname) . " -i " . shellescape(arg)
|
while i < len(s:go_stack)
|
||||||
|
let entry = s:go_stack[i]
|
||||||
|
let prefix = ""
|
||||||
|
|
||||||
" get output of godef
|
if i == s:go_stack_level
|
||||||
let out = s:system(command, join(getbufline(bufnr('%'), 1, '$'), go#util#LineEnding()))
|
let prefix = ">"
|
||||||
|
else
|
||||||
|
let prefix = " "
|
||||||
|
endif
|
||||||
|
|
||||||
call s:godefJump(out, a:mode)
|
call add(stackOut, printf("%s %d %s|%d col %d|%s",
|
||||||
let $GOPATH = old_gopath
|
\ 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
|
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
|
||||||
|
|
||||||
function! s:getOffset()
|
if !len(a:000)
|
||||||
return "-o=" . go#util#OffsetCursor()
|
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
|
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)
|
||||||
|
|
||||||
function! s:godefJump(out, mode)
|
let start_options = {
|
||||||
let old_errorformat = &errorformat
|
\ 'callback': callbacks.callback,
|
||||||
let &errorformat = "%f:%l:%c"
|
\ 'exit_cb': callbacks.exit_cb,
|
||||||
|
\ }
|
||||||
if a:out =~ 'godef: '
|
|
||||||
let out = substitute(a:out, go#util#LineEnding() . '$', '', '')
|
if &modified
|
||||||
echom out
|
let l:tmpname = tempname()
|
||||||
else
|
call writefile(split(a:args.input, "\n"), l:tmpname, "b")
|
||||||
let parts = split(a:out, ':')
|
let l:start_options.in_io = "file"
|
||||||
" parts[0] contains filename
|
let l:start_options.in_name = l:tmpname
|
||||||
let fileName = parts[0]
|
endif
|
||||||
|
|
||||||
" put the error format into location list so we can jump automatically to
|
call job_start(a:args.cmd, start_options)
|
||||||
" it
|
|
||||||
lgetexpr a:out
|
|
||||||
|
|
||||||
" needed for restoring back user setting this is because there are two
|
|
||||||
" modes of switchbuf which we need based on the split mode
|
|
||||||
let old_switchbuf = &switchbuf
|
|
||||||
|
|
||||||
if a:mode == "tab"
|
|
||||||
let &switchbuf = "usetab"
|
|
||||||
|
|
||||||
if bufloaded(fileName) == 0
|
|
||||||
tab split
|
|
||||||
endif
|
|
||||||
else
|
|
||||||
if a:mode == "split"
|
|
||||||
split
|
|
||||||
elseif a:mode == "vsplit"
|
|
||||||
vsplit
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
" jump to file now
|
|
||||||
sil ll 1
|
|
||||||
normal! zz
|
|
||||||
|
|
||||||
let &switchbuf = old_switchbuf
|
|
||||||
end
|
|
||||||
let &errorformat = old_errorformat
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
|
@ -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,171 +1,229 @@
|
|||||||
" 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
|
||||||
" returns the package and exported name. exported name might be empty.
|
let bin_path = go#path#CheckBinPath('gogetdoc')
|
||||||
" ie: fmt and Println
|
if !empty(bin_path) && exists('*json_decode')
|
||||||
" ie: github.com/fatih/set and New
|
let json_out = s:gogetdoc(1)
|
||||||
function! s:godocWord(args)
|
if go#util#ShellError() != 0
|
||||||
if !executable('godoc')
|
call go#util#EchoError(json_out)
|
||||||
echohl WarningMsg
|
return
|
||||||
echo "godoc command not found."
|
|
||||||
echo " install with: go get golang.org/x/tools/cmd/godoc"
|
|
||||||
echohl None
|
|
||||||
return []
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if !len(a:args)
|
let out = json_decode(json_out)
|
||||||
let oldiskeyword = &iskeyword
|
if type(out) != type({})
|
||||||
setlocal iskeyword+=.
|
call go#util#EchoError("gogetdoc output is malformed")
|
||||||
let word = expand('<cword>')
|
|
||||||
let &iskeyword = oldiskeyword
|
|
||||||
let word = substitute(word, '[^a-zA-Z0-9\\/._~-]', '', 'g')
|
|
||||||
let words = split(word, '\.\ze[^./]\+$')
|
|
||||||
else
|
|
||||||
let words = a:args
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if !len(words)
|
let import = out["import"]
|
||||||
return []
|
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
|
endif
|
||||||
|
|
||||||
let pkg = words[0]
|
let godoc_url .= "/" . import
|
||||||
if len(words) == 1
|
if decl !~ "^package"
|
||||||
let exported_name = ""
|
let godoc_url .= "#" . name
|
||||||
else
|
|
||||||
let exported_name = words[1]
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let packages = go#tool#Imports()
|
echo godoc_url
|
||||||
|
|
||||||
if has_key(packages, pkg)
|
call go#tool#OpenBrowser(godoc_url)
|
||||||
let pkg = packages[pkg]
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
return [pkg, exported_name]
|
let pkgs = s:godocWord(a:000)
|
||||||
endfunction
|
if empty(pkgs)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
function! s:godocNotFound(content)
|
let pkg = pkgs[0]
|
||||||
if len(a:content) == 0
|
let exported_name = pkgs[1]
|
||||||
return 1
|
|
||||||
endif
|
|
||||||
|
|
||||||
return a:content =~# '^.*: no such file or directory\n$'
|
" 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
|
endfunction
|
||||||
|
|
||||||
function! go#doc#OpenBrowser(...)
|
function! go#doc#Open(newmode, mode, ...) abort
|
||||||
let pkgs = s:godocWord(a:000)
|
" With argument: run "godoc [arg]".
|
||||||
if empty(pkgs)
|
if len(a:000)
|
||||||
return
|
if empty(go#path#CheckBinPath(g:go_doc_command[0]))
|
||||||
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let pkg = pkgs[0]
|
let command = printf("%s %s", go#util#Shelljoin(g:go_doc_command), join(a:000, ' '))
|
||||||
let exported_name = pkgs[1]
|
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
|
||||||
|
|
||||||
" example url: https://godoc.org/github.com/fatih/set#Set
|
if go#util#ShellError() != 0
|
||||||
let godoc_url = "https://godoc.org/" . pkg . "#" . exported_name
|
call go#util#EchoError(out)
|
||||||
call go#tool#OpenBrowser(godoc_url)
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
call s:GodocView(a:newmode, a:mode, out)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! go#doc#Open(newmode, mode, ...)
|
function! s:GodocView(newposition, position, content) abort
|
||||||
let pkgs = s:godocWord(a:000)
|
" reuse existing buffer window if it exists otherwise create a new one
|
||||||
if empty(pkgs)
|
let is_visible = bufexists(s:buf_nr) && bufwinnr(s:buf_nr) != -1
|
||||||
return
|
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
|
||||||
|
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
|
||||||
|
|
||||||
let pkg = pkgs[0]
|
function! s:gogetdoc(json) abort
|
||||||
let exported_name = pkgs[1]
|
" check if we have 'gogetdoc' and use it automatically
|
||||||
|
let bin_path = go#path#CheckBinPath('gogetdoc')
|
||||||
|
if empty(bin_path)
|
||||||
|
return -1
|
||||||
|
endif
|
||||||
|
|
||||||
let command = g:go_doc_command . ' ' . g:go_doc_options . ' ' . pkg
|
let cmd = [go#util#Shellescape(bin_path)]
|
||||||
|
|
||||||
silent! let content = system(command)
|
let offset = go#util#OffsetCursor()
|
||||||
if v:shell_error || s:godocNotFound(content)
|
let fname = expand("%:p:gs!\\!/!")
|
||||||
echo 'No documentation found for "' . pkg . '".'
|
let pos = shellescape(fname.':#'.offset)
|
||||||
return -1
|
|
||||||
endif
|
|
||||||
|
|
||||||
call s:GodocView(a:newmode, a:mode, content)
|
let cmd += ["-pos", pos]
|
||||||
|
if a:json
|
||||||
|
let cmd += ["-json"]
|
||||||
|
endif
|
||||||
|
|
||||||
if exported_name == ''
|
let command = join(cmd, " ")
|
||||||
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)
|
if &modified
|
||||||
silent! normal! zt
|
let command .= " -modified"
|
||||||
return -1
|
let out = go#util#System(command, go#util#archive())
|
||||||
endif
|
else
|
||||||
|
let out = go#util#System(command)
|
||||||
|
endif
|
||||||
|
|
||||||
if search('^\%(const\|var\|type\|\s\+\) ' . pkg . '\s\+=\s')
|
return out
|
||||||
silent! normal! zt
|
endfunction
|
||||||
return -1
|
|
||||||
endif
|
|
||||||
|
|
||||||
" nothing found, jump to top
|
" returns the package and exported name. exported name might be empty.
|
||||||
silent! normal! gg
|
" ie: fmt and Println
|
||||||
|
" ie: github.com/fatih/set and New
|
||||||
|
function! s:godocWord(args) abort
|
||||||
|
if !executable('godoc')
|
||||||
|
let msg = "godoc command not found."
|
||||||
|
let msg .= " install with: go get golang.org/x/tools/cmd/godoc"
|
||||||
|
call go#util#EchoWarning(msg)
|
||||||
|
return []
|
||||||
|
endif
|
||||||
|
|
||||||
|
if !len(a:args)
|
||||||
|
let oldiskeyword = &iskeyword
|
||||||
|
setlocal iskeyword+=.
|
||||||
|
let word = expand('<cword>')
|
||||||
|
let &iskeyword = oldiskeyword
|
||||||
|
let word = substitute(word, '[^a-zA-Z0-9\\/._~-]', '', 'g')
|
||||||
|
let words = split(word, '\.\ze[^./]\+$')
|
||||||
|
else
|
||||||
|
let words = a:args
|
||||||
|
endif
|
||||||
|
|
||||||
|
if !len(words)
|
||||||
|
return []
|
||||||
|
endif
|
||||||
|
|
||||||
|
let pkg = words[0]
|
||||||
|
if len(words) == 1
|
||||||
|
let exported_name = ""
|
||||||
|
else
|
||||||
|
let exported_name = words[1]
|
||||||
|
endif
|
||||||
|
|
||||||
|
let packages = go#tool#Imports()
|
||||||
|
|
||||||
|
if has_key(packages, pkg)
|
||||||
|
let pkg = packages[pkg]
|
||||||
|
endif
|
||||||
|
|
||||||
|
return [pkg, exported_name]
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:GodocView(newposition, position, content)
|
function! s:godocNotFound(content) abort
|
||||||
" reuse existing buffer window if it exists otherwise create a new one
|
if len(a:content) == 0
|
||||||
if !bufexists(s:buf_nr)
|
return 1
|
||||||
execute a:newposition
|
endif
|
||||||
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
|
return a:content =~# '^.*: no such file or directory\n$'
|
||||||
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
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
" vim: sw=2 ts=2 et
|
||||||
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -1,199 +1,329 @@
|
|||||||
if !exists("g:go_metalinter_command")
|
if !exists("g:go_metalinter_command")
|
||||||
let g:go_metalinter_command = ""
|
let g:go_metalinter_command = ""
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if !exists("g:go_metalinter_autosave_enabled")
|
if !exists("g:go_metalinter_autosave_enabled")
|
||||||
let g:go_metalinter_autosave_enabled = ['vet', 'golint']
|
let g:go_metalinter_autosave_enabled = ['vet', 'golint']
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if !exists("g:go_metalinter_enabled")
|
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")
|
||||||
let g:go_golint_bin = "golint"
|
let g:go_golint_bin = "golint"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if !exists("g:go_errcheck_bin")
|
if !exists("g:go_errcheck_bin")
|
||||||
let g:go_errcheck_bin = "errcheck"
|
let g:go_errcheck_bin = "errcheck"
|
||||||
endif
|
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
|
||||||
|
|
||||||
|
let bin_path = go#path#CheckBinPath("gometalinter")
|
||||||
|
if empty(bin_path)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let cmd = [bin_path]
|
||||||
|
let cmd += ["--disable-all"]
|
||||||
|
|
||||||
|
if a:autosave || empty(g:go_metalinter_command)
|
||||||
|
" linters
|
||||||
|
let linters = a:autosave ? g:go_metalinter_autosave_enabled : g:go_metalinter_enabled
|
||||||
|
for linter in linters
|
||||||
|
let cmd += ["--enable=".linter]
|
||||||
|
endfor
|
||||||
|
|
||||||
|
for exclude in g:go_metalinter_excludes
|
||||||
|
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
|
||||||
|
let cmd += [expand('%:p:h')]
|
||||||
|
else
|
||||||
|
" the user wants something else, let us use it.
|
||||||
|
let cmd += split(g:go_metalinter_command, " ")
|
||||||
|
endif
|
||||||
|
|
||||||
|
" gometalinter has a default deadline of 5 seconds.
|
||||||
|
"
|
||||||
|
" 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.
|
||||||
|
|
||||||
|
" 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
|
endif
|
||||||
|
|
||||||
let meta_command = "gometalinter --disable-all"
|
call s:lint_job({'cmd': cmd})
|
||||||
if a:autosave || empty(g:go_metalinter_command)
|
return
|
||||||
let bin_path = go#path#CheckBinPath("gometalinter")
|
endif
|
||||||
if empty(bin_path)
|
|
||||||
return
|
" We're calling gometalinter synchronously.
|
||||||
endif
|
|
||||||
|
let cmd += ["--deadline=" . get(g:, 'go_metalinter_deadline', "5s")]
|
||||||
if a:autosave
|
|
||||||
" include only messages for the active buffer
|
if a:autosave
|
||||||
let meta_command .= " --include='^" . expand('%:p') . ".*$'"
|
" include only messages for the active buffer
|
||||||
endif
|
let cmd += ["--include='^" . expand('%:p') . ".*$'"]
|
||||||
|
endif
|
||||||
" linters
|
|
||||||
let linters = a:autosave ? g:go_metalinter_autosave_enabled : g:go_metalinter_enabled
|
|
||||||
for linter in linters
|
let meta_command = join(cmd, " ")
|
||||||
let meta_command .= " --enable=".linter
|
|
||||||
endfor
|
let out = go#util#System(meta_command)
|
||||||
|
|
||||||
" deadline
|
|
||||||
let meta_command .= " --deadline=" . g:go_metalinter_deadline
|
|
||||||
|
|
||||||
" path
|
|
||||||
let meta_command .= " " . goargs
|
|
||||||
else
|
|
||||||
" the user wants something else, let us use it.
|
|
||||||
let meta_command = g:go_metalinter_command
|
|
||||||
endif
|
|
||||||
|
|
||||||
" comment out the following two lines for debugging
|
let l:listtype = go#list#Type("GoMetaLinter")
|
||||||
" echo meta_command
|
if go#util#ShellError() == 0
|
||||||
" return
|
redraw | echo
|
||||||
|
call go#list#Clean(l:listtype)
|
||||||
let out = go#tool#ExecuteInDir(meta_command)
|
call go#list#Window(l:listtype)
|
||||||
|
echon "vim-go: " | echohl Function | echon "[metalinter] PASS" | echohl None
|
||||||
let l:listtype = "quickfix"
|
else
|
||||||
if v:shell_error == 0
|
" GoMetaLinter can output one of the two, so we look for both:
|
||||||
redraw | echo
|
" <file>:<line>:[<column>]: <message> (<linter>)
|
||||||
call go#list#Clean(l:listtype)
|
" <file>:<line>:: <message> (<linter>)
|
||||||
call go#list#Window(l:listtype)
|
" This can be defined by the following errorformat:
|
||||||
echon "vim-go: " | echohl Function | echon "[metalinter] PASS" | echohl None
|
let errformat = "%f:%l:%c:%t%*[^:]:\ %m,%f:%l::%t%*[^:]:\ %m"
|
||||||
else
|
|
||||||
" GoMetaLinter can output one of the two, so we look for both:
|
" Parse and populate our location list
|
||||||
" <file>:<line>:[<column>]: <message> (<linter>)
|
call go#list#ParseFormat(l:listtype, errformat, split(out, "\n"), 'GoMetaLinter')
|
||||||
" <file>:<line>:: <message> (<linter>)
|
|
||||||
" This can be defined by the following errorformat:
|
let errors = go#list#Get(l:listtype)
|
||||||
let errformat = "%f:%l:%c:%t%*[^:]:\ %m,%f:%l::%t%*[^:]:\ %m"
|
call go#list#Window(l:listtype, len(errors))
|
||||||
|
|
||||||
" Parse and populate our location list
|
if !a:autosave
|
||||||
call go#list#ParseFormat(l:listtype, errformat, split(out, "\n"))
|
call go#list#JumpToFirst(l:listtype)
|
||||||
|
|
||||||
let errors = go#list#Get(l:listtype)
|
|
||||||
call go#list#Window(l:listtype, len(errors))
|
|
||||||
|
|
||||||
if !a:autosave
|
|
||||||
call go#list#JumpToFirst(l:listtype)
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Golint calls 'golint' on the current directory. Any warnings are populated in
|
" Golint calls 'golint' on the current directory. Any warnings are populated in
|
||||||
" the location list
|
" the location list
|
||||||
function! go#lint#Golint(...) abort
|
function! go#lint#Golint(...) abort
|
||||||
let bin_path = go#path#CheckBinPath(g:go_golint_bin)
|
let bin_path = go#path#CheckBinPath(g:go_golint_bin)
|
||||||
if empty(bin_path)
|
if empty(bin_path)
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
let bin_path = go#util#Shellescape(bin_path)
|
||||||
if a:0 == 0
|
|
||||||
let goargs = shellescape(expand('%'))
|
if a:0 == 0
|
||||||
else
|
let out = go#util#System(bin_path . " " . go#util#Shellescape(go#package#ImportPath()))
|
||||||
let goargs = go#util#Shelljoin(a:000)
|
else
|
||||||
endif
|
let out = go#util#System(bin_path . " " . go#util#Shelljoin(a:000))
|
||||||
|
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))
|
||||||
call go#list#JumpToFirst(l:listtype)
|
call go#list#JumpToFirst(l:listtype)
|
||||||
endfunction
|
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)
|
||||||
endif
|
|
||||||
echon "vim-go: " | echohl ErrorMsg | echon "[vet] FAIL" | echohl None
|
|
||||||
else
|
|
||||||
call go#list#Clean(l:listtype)
|
|
||||||
call go#list#Window(l:listtype)
|
|
||||||
redraw | echon "vim-go: " | echohl Function | echon "[vet] PASS" | echohl None
|
|
||||||
endif
|
endif
|
||||||
|
echon "vim-go: " | echohl ErrorMsg | echon "[vet] FAIL" | echohl None
|
||||||
|
else
|
||||||
|
call go#list#Clean(l:listtype)
|
||||||
|
call go#list#Window(l:listtype)
|
||||||
|
redraw | echon "vim-go: " | echohl Function | echon "[vet] PASS" | echohl None
|
||||||
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" ErrCheck calls 'errcheck' for the given packages. Any warnings are populated in
|
" ErrCheck calls 'errcheck' for the given packages. Any warnings are populated in
|
||||||
" 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
|
||||||
|
|
||||||
|
let bin_path = go#path#CheckBinPath(g:go_errcheck_bin)
|
||||||
|
if empty(bin_path)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
echon "vim-go: " | echohl Identifier | echon "errcheck analysing ..." | echohl None
|
||||||
|
redraw
|
||||||
|
|
||||||
|
let command = go#util#Shellescape(bin_path) . ' -abspath ' . import_path
|
||||||
|
let out = go#tool#ExecuteInDir(command)
|
||||||
|
|
||||||
|
let l:listtype = go#list#Type("GoErrCheck")
|
||||||
|
if go#util#ShellError() != 0
|
||||||
|
let errformat = "%f:%l:%c:\ %m, %f:%l:%c\ %#%m"
|
||||||
|
|
||||||
|
" Parse and populate our location list
|
||||||
|
call go#list#ParseFormat(l:listtype, errformat, split(out, "\n"), 'Errcheck')
|
||||||
|
|
||||||
|
let errors = go#list#Get(l:listtype)
|
||||||
|
if empty(errors)
|
||||||
|
echohl Error | echomsg "GoErrCheck returned error" | echohl None
|
||||||
|
echo out
|
||||||
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let bin_path = go#path#CheckBinPath(g:go_errcheck_bin)
|
if !empty(errors)
|
||||||
if empty(bin_path)
|
echohl Error | echomsg "GoErrCheck found errors" | echohl None
|
||||||
return
|
call go#list#Populate(l:listtype, errors, 'Errcheck')
|
||||||
|
call go#list#Window(l:listtype, len(errors))
|
||||||
|
if !empty(errors)
|
||||||
|
call go#list#JumpToFirst(l:listtype)
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
else
|
||||||
|
call go#list#Clean(l:listtype)
|
||||||
|
call go#list#Window(l:listtype)
|
||||||
|
echon "vim-go: " | echohl Function | echon "[errcheck] PASS" | echohl None
|
||||||
|
endif
|
||||||
|
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
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))
|
||||||
|
|
||||||
echon "vim-go: " | echohl Identifier | echon "errcheck analysing ..." | echohl None
|
exe l:winnr . "wincmd w"
|
||||||
redraw
|
endfunction
|
||||||
|
|
||||||
let command = bin_path . ' -abspath ' . goargs
|
function! s:exit_cb(job, exitval) closure
|
||||||
let out = go#tool#ExecuteInDir(command)
|
let status = {
|
||||||
|
\ 'desc': 'last status',
|
||||||
let l:listtype = "quickfix"
|
\ 'type': "gometaliner",
|
||||||
if v:shell_error
|
\ 'state': "finished",
|
||||||
let errformat = "%f:%l:%c:\ %m, %f:%l:%c\ %#%m"
|
\ }
|
||||||
|
|
||||||
" Parse and populate our location list
|
if a:exitval
|
||||||
call go#list#ParseFormat(l:listtype, errformat, split(out, "\n"))
|
let status.state = "failed"
|
||||||
|
endif
|
||||||
let errors = go#list#Get(l:listtype)
|
|
||||||
|
let elapsed_time = reltimestr(reltime(started_at))
|
||||||
if empty(errors)
|
" strip whitespace
|
||||||
echohl Error | echomsg "GoErrCheck returned error" | echohl None
|
let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '')
|
||||||
echo out
|
let status.state .= printf(" (%ss)", elapsed_time)
|
||||||
return
|
|
||||||
endif
|
call go#statusline#Update(status_dir, status)
|
||||||
|
|
||||||
if !empty(errors)
|
let errors = go#list#Get(l:listtype)
|
||||||
call go#list#Populate(l:listtype, errors)
|
if empty(errors)
|
||||||
call go#list#Window(l:listtype, len(errors))
|
call go#list#Window(l:listtype, len(errors))
|
||||||
if !empty(errors)
|
elseif has("patch-7.4.2200")
|
||||||
call go#list#JumpToFirst(l:listtype)
|
if l:listtype == 'quickfix'
|
||||||
endif
|
call setqflist([], 'a', {'title': 'GoMetaLinter'})
|
||||||
endif
|
else
|
||||||
else
|
call setloclist(0, [], 'a', {'title': 'GoMetaLinter'})
|
||||||
call go#list#Clean(l:listtype)
|
endif
|
||||||
call go#list#Window(l:listtype)
|
endif
|
||||||
echon "vim-go: " | echohl Function | echon "[errcheck] PASS" | echohl None
|
|
||||||
|
if get(g:, 'go_echo_command_info', 1)
|
||||||
|
call go#util#EchoSuccess("linting finished")
|
||||||
endif
|
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
|
endfunction
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
" vim: sw=2 ts=2 et
|
||||||
|
@ -1,126 +1,169 @@
|
|||||||
if !exists("g:go_list_type")
|
if !exists("g:go_list_type")
|
||||||
let g:go_list_type = ""
|
let g:go_list_type = ""
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" Window opens the list with the given height up to 10 lines maximum.
|
if !exists("g:go_list_type_commands")
|
||||||
" Otherwise g:go_loclist_height is used. If no or zero height is given it
|
let g:go_list_type_commands = {}
|
||||||
" closes the window
|
endif
|
||||||
function! go#list#Window(listtype, ...)
|
|
||||||
let l:listtype = go#list#Type(a:listtype)
|
|
||||||
" 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
|
|
||||||
" for a better user experience. If the number of errors in a current
|
|
||||||
" location list increases/decreases, cwindow will not resize when a new
|
|
||||||
" updated height is passed. lopen in the other hand resizes the screen.
|
|
||||||
if !a:0 || a:1 == 0
|
|
||||||
if l:listtype == "locationlist"
|
|
||||||
lclose
|
|
||||||
else
|
|
||||||
cclose
|
|
||||||
endif
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
|
|
||||||
let height = get(g:, "go_list_height", 0)
|
" Window opens the list with the given height up to 10 lines maximum.
|
||||||
if height == 0
|
" Otherwise g:go_loclist_height is used.
|
||||||
" prevent creating a large location height for a large set of numbers
|
"
|
||||||
if a:1 > 10
|
" If no or zero height is given it closes the window by default.
|
||||||
let height = 10
|
" To prevent this, set g:go_list_autoclose = 0
|
||||||
else
|
function! go#list#Window(listtype, ...) abort
|
||||||
let height = a:1
|
" we don't use lwindow to close the location list as we need also the
|
||||||
endif
|
" 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
|
||||||
|
" location list increases/decreases, cwindow will not resize when a new
|
||||||
|
" updated height is passed. lopen in the other hand resizes the screen.
|
||||||
|
if !a:0 || a:1 == 0
|
||||||
|
let autoclose_window = get(g:, 'go_list_autoclose', 1)
|
||||||
|
if autoclose_window
|
||||||
|
if a:listtype == "locationlist"
|
||||||
|
lclose
|
||||||
|
else
|
||||||
|
cclose
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
if l:listtype == "locationlist"
|
let height = get(g:, "go_list_height", 0)
|
||||||
exe 'lopen ' . height
|
if height == 0
|
||||||
|
" prevent creating a large location height for a large set of numbers
|
||||||
|
if a:1 > 10
|
||||||
|
let height = 10
|
||||||
else
|
else
|
||||||
exe 'copen ' . height
|
let height = a:1
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
if a:listtype == "locationlist"
|
||||||
|
exe 'lopen ' . height
|
||||||
|
else
|
||||||
|
exe 'copen ' . height
|
||||||
|
endif
|
||||||
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')
|
|
||||||
else
|
|
||||||
call setqflist(a:items, 'r')
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! go#list#PopulateWin(winnr, items)
|
" The last argument ({what}) is introduced with 7.4.2200:
|
||||||
call setloclist(a:winnr, a:items, 'r')
|
" https://github.com/vim/vim/commit/d823fa910cca43fec3c31c030ee908a14c272640
|
||||||
|
if has("patch-7.4.2200") | call setloclist(0, [], 'a', {'title': a:title}) | endif
|
||||||
|
else
|
||||||
|
call setqflist(a:items, 'r')
|
||||||
|
if has("patch-7.4.2200") | call setqflist([], 'a', {'title': a:title}) | endif
|
||||||
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Parse parses the given items based on the specified errorformat nad
|
" Parse parses the given items based on the specified errorformat and
|
||||||
" populates the location list.
|
" populates the list.
|
||||||
function! go#list#ParseFormat(listtype, errformat, items)
|
function! go#list#ParseFormat(listtype, errformat, items, title) abort
|
||||||
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
|
try
|
||||||
if l:listtype == "locationlist"
|
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
|
endif
|
||||||
endif
|
|
||||||
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
|
endif
|
||||||
endif
|
|
||||||
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
|
endif
|
||||||
return a:listtype
|
|
||||||
endif
|
return a:listtype
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" 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
|
endfunction
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
" 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
|
|
||||||
"
|
|
@ -1,94 +1,73 @@
|
|||||||
if !exists("g:go_play_open_browser")
|
if !exists("g:go_play_open_browser")
|
||||||
let g:go_play_open_browser = 1
|
let g:go_play_open_browser = 1
|
||||||
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
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let content = join(getline(a:line1, a:line2), "\n")
|
let content = join(getline(a:line1, a:line2), "\n")
|
||||||
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
|
||||||
|
|
||||||
let url = "http://play.golang.org/p/".snippet_id
|
let url = "http://play.golang.org/p/".snippet_id
|
||||||
|
|
||||||
" copy to clipboard
|
" copy to clipboard
|
||||||
if has('unix') && !has('xterm_clipboard') && !has('clipboard')
|
if has('unix') && !has('xterm_clipboard') && !has('clipboard')
|
||||||
let @" = url
|
let @" = url
|
||||||
else
|
else
|
||||||
let @+ = url
|
let @+ = url
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if g:go_play_open_browser != 0
|
if g:go_play_open_browser != 0
|
||||||
call go#tool#OpenBrowser(url)
|
call go#tool#OpenBrowser(url)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
echo "vim-go: snippet uploaded: ".url
|
echo "vim-go: snippet uploaded: ".url
|
||||||
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
|
||||||
let content = @"
|
let content = @"
|
||||||
call setreg('"', save_regcont, save_regtype)
|
call setreg('"', save_regcont, save_regtype)
|
||||||
return content
|
return content
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" modified version of
|
" modified version of
|
||||||
" 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]
|
||||||
|
|
||||||
" check if the the visual mode is used before
|
" check if the the visual mode is used before
|
||||||
if lnum1 == 0 || lnum2 == 0 || col1 == 0 || col2 == 0
|
if lnum1 == 0 || lnum2 == 0 || col1 == 0 || col2 == 0
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let lines = getline(lnum1, lnum2)
|
let lines = getline(lnum1, lnum2)
|
||||||
let lines[-1] = lines[-1][: col2 - (&selection == 'inclusive' ? 1 : 2)]
|
let lines[-1] = lines[-1][: col2 - (&selection == 'inclusive' ? 1 : 2)]
|
||||||
let lines[0] = lines[0][col1 - 1:]
|
let lines[0] = lines[0][col1 - 1:]
|
||||||
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
|
|
||||||
|
@ -1,69 +1,160 @@
|
|||||||
if !exists("g:go_gorename_bin")
|
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()
|
||||||
if a:0 == 0
|
|
||||||
let from = expand("<cword>")
|
let to_identifier = ""
|
||||||
let ask = printf("vim-go: rename '%s' to: ", from)
|
if a:0 == 0
|
||||||
if g:go_gorename_prefill
|
let ask = printf("vim-go: rename '%s' to: ", expand("<cword>"))
|
||||||
let to = input(ask, from)
|
if g:go_gorename_prefill != ''
|
||||||
else
|
let to_identifier = input(ask, eval(g:go_gorename_prefill))
|
||||||
let to = input(ask)
|
|
||||||
endif
|
|
||||||
redraw!
|
|
||||||
if empty(to)
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
else
|
else
|
||||||
let to = a:1
|
let to_identifier = input(ask)
|
||||||
|
endif
|
||||||
|
redraw!
|
||||||
|
if empty(to_identifier)
|
||||||
|
return
|
||||||
endif
|
endif
|
||||||
|
else
|
||||||
|
let to_identifier = a:1
|
||||||
|
endif
|
||||||
|
|
||||||
|
" return with a warning if the bin doesn't exist
|
||||||
|
let bin_path = go#path#CheckBinPath(g:go_gorename_bin)
|
||||||
|
if empty(bin_path)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let fname = expand('%:p')
|
||||||
|
let pos = go#util#OffsetCursor()
|
||||||
|
let offset = printf('%s:#%d', fname, pos)
|
||||||
|
|
||||||
|
" 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)
|
||||||
|
|
||||||
|
let cmd = [bin_path, "-offset", offset, "-to", to_identifier]
|
||||||
|
|
||||||
|
" check for any tags
|
||||||
|
if exists('g:go_build_tags')
|
||||||
|
let tags = get(g:, 'go_build_tags')
|
||||||
|
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
|
||||||
|
|
||||||
"return with a warning if the bin doesn't exist
|
let status_dir = expand('%:p:h')
|
||||||
let bin_path = go#path#CheckBinPath(g:go_gorename_bin)
|
|
||||||
if empty(bin_path)
|
function! s:exit_cb(job, exitval) closure
|
||||||
return
|
let status = {
|
||||||
|
\ 'desc': 'last status',
|
||||||
|
\ 'type': "gorename",
|
||||||
|
\ 'state': "finished",
|
||||||
|
\ }
|
||||||
|
|
||||||
|
if a:exitval
|
||||||
|
let status.state = "failed"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let fname = expand('%:p')
|
call go#statusline#Update(status_dir, status)
|
||||||
let pos = go#util#OffsetCursor()
|
|
||||||
let cmd = printf('%s -offset %s -to %s', shellescape(bin_path), shellescape(printf('%s:#%d', fname, pos)), shellescape(to))
|
call s:parse_errors(a:exitval, a:args.bang, messages)
|
||||||
|
endfunction
|
||||||
let out = go#tool#ExecuteInDir(cmd)
|
|
||||||
|
let start_options = {
|
||||||
" strip out newline on the end that gorename puts. If we don't remove, it
|
\ 'callback': funcref("s:callback"),
|
||||||
" will trigger the 'Hit ENTER to continue' prompt
|
\ 'exit_cb': funcref("s:exit_cb"),
|
||||||
let clean = split(out, '\n')
|
\ }
|
||||||
|
|
||||||
let l:listtype = "quickfix"
|
call go#statusline#Update(status_dir, {
|
||||||
if v:shell_error
|
\ 'desc': "current status",
|
||||||
let errors = go#tool#ParseErrors(split(out, '\n'))
|
\ 'type': "gorename",
|
||||||
call go#list#Populate(l:listtype, errors)
|
\ 'state': "started",
|
||||||
call go#list#Window(l:listtype, len(errors))
|
\})
|
||||||
if !empty(errors) && !a:bang
|
|
||||||
call go#list#JumpToFirst(l:listtype)
|
call job_start(a:args.cmd, start_options)
|
||||||
elseif empty(errors)
|
endfunction
|
||||||
" failed to parse errors, output the original content
|
|
||||||
call go#util#EchoError(out)
|
function s:parse_errors(exit_val, bang, out)
|
||||||
endif
|
" reload all files to reflect the new changes. We explicitly call
|
||||||
return
|
" checktime to trigger a reload of all files. See
|
||||||
else
|
" http://www.mail-archive.com/vim@vim.org/msg05900.html for more info
|
||||||
call go#list#Clean(l:listtype)
|
" about the autoread bug
|
||||||
call go#list#Window(l:listtype)
|
let current_autoread = &autoread
|
||||||
redraw | echon "vim-go: " | echohl Function | echon clean[0] | echohl None
|
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))
|
||||||
|
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(a:out)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" refresh the buffer so we can see the new content
|
return
|
||||||
" TODO(arslan): also find all other buffers and refresh them too. For this
|
endif
|
||||||
" we need a way to get the list of changes from gorename upon an success
|
|
||||||
" change.
|
" strip out newline on the end that gorename puts. If we don't remove, it
|
||||||
silent execute ":e"
|
" will trigger the 'Hit ENTER to continue' prompt
|
||||||
|
call go#list#Clean(l:listtype)
|
||||||
|
call go#list#Window(l:listtype)
|
||||||
|
call go#util#EchoSuccess(a:out[0])
|
||||||
|
|
||||||
|
" refresh the buffer so we can see the new content
|
||||||
|
" TODO(arslan): also find all other buffers and refresh them too. For this
|
||||||
|
" we need a way to get the list of changes from gorename upon an success
|
||||||
|
" change.
|
||||||
|
silent execute ":e"
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" 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
|
endfunction
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
" vim: sw=2 ts=2 et
|
||||||
"
|
|
||||||
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -0,0 +1,7 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("vim-go")
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("vim-go")
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("vim-go")
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Foo(log *logging.TestLogger) {
|
||||||
|
log.Debug("vim-go")
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("vim-go")
|
||||||
|
}
|
@ -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")
|
||||||
|
}
|
@ -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)
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
../imports/
|
@ -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"`
|
||||||
|
}
|
@ -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{}
|
||||||
|
}
|
@ -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{}
|
||||||
|
}
|
@ -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"`
|
||||||
|
}
|
@ -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")
|
||||||
|
}
|
@ -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")
|
||||||
|
}
|
@ -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
|
@ -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
|
@ -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,89 +1,114 @@
|
|||||||
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
|
||||||
" reuse existing buffer window if it exists otherwise create a new one
|
" Ensure there's only one return window in this session/tabpage
|
||||||
if !bufexists(s:buf_nr)
|
call go#util#Windo("unlet! w:vim_go_return_window")
|
||||||
execute 'botright new'
|
" Mark the window we're leaving as such
|
||||||
file `="[" . a:title . "]"`
|
let w:vim_go_return_window = 1
|
||||||
let s:buf_nr = bufnr('%')
|
|
||||||
elseif bufwinnr(s:buf_nr) == -1
|
" reuse existing buffer window if it exists otherwise create a new one
|
||||||
execute 'botright new'
|
if !bufexists(s:buf_nr)
|
||||||
execute s:buf_nr . 'buffer'
|
execute 'botright new'
|
||||||
elseif bufwinnr(s:buf_nr) != bufwinnr('%')
|
file `="[" . a:title . "]"`
|
||||||
execute bufwinnr(s:buf_nr) . 'wincmd w'
|
let s:buf_nr = bufnr('%')
|
||||||
endif
|
elseif bufwinnr(s:buf_nr) == -1
|
||||||
|
execute 'botright new'
|
||||||
|
execute s:buf_nr . 'buffer'
|
||||||
|
elseif bufwinnr(s:buf_nr) != bufwinnr('%')
|
||||||
|
execute bufwinnr(s:buf_nr) . 'wincmd w'
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Resize window to content length
|
||||||
|
exe 'resize' . len(a:content)
|
||||||
|
|
||||||
|
execute "setlocal filetype=".a:filetype
|
||||||
|
|
||||||
|
" some sane default values for a readonly buffer
|
||||||
|
setlocal bufhidden=delete
|
||||||
|
setlocal buftype=nofile
|
||||||
|
setlocal noswapfile
|
||||||
|
setlocal nobuflisted
|
||||||
|
setlocal winfixheight
|
||||||
|
setlocal cursorline " make it easy to distinguish
|
||||||
|
setlocal nonumber
|
||||||
|
setlocal norelativenumber
|
||||||
|
setlocal showbreak=""
|
||||||
|
|
||||||
|
" we need this to purge the buffer content
|
||||||
|
setlocal modifiable
|
||||||
|
|
||||||
|
"delete everything first from the buffer
|
||||||
|
%delete _
|
||||||
|
|
||||||
|
" add the content
|
||||||
|
call append(0, a:content)
|
||||||
|
|
||||||
|
" delete last line that comes from the append call
|
||||||
|
$delete _
|
||||||
|
|
||||||
|
" set it back to non modifiable
|
||||||
|
setlocal nomodifiable
|
||||||
|
|
||||||
|
" Remove the '... [New File]' message line from the command line
|
||||||
|
echon
|
||||||
|
endfunction
|
||||||
|
|
||||||
" Keep minimum height to 10, if there is more just increase it that it
|
function! go#ui#GetReturnWindow() abort
|
||||||
" occupies all results
|
for l:wn in range(1, winnr("$"))
|
||||||
let buffer_height = 10
|
if !empty(getwinvar(l:wn, "vim_go_return_window"))
|
||||||
if len(a:content) < buffer_height
|
return l:wn
|
||||||
exe 'resize ' . buffer_height
|
|
||||||
else
|
|
||||||
exe 'resize ' . len(a:content)
|
|
||||||
endif
|
endif
|
||||||
|
endfor
|
||||||
" some sane default values for a readonly buffer
|
|
||||||
setlocal filetype=vimgo
|
|
||||||
setlocal bufhidden=delete
|
|
||||||
setlocal buftype=nofile
|
|
||||||
setlocal noswapfile
|
|
||||||
setlocal nobuflisted
|
|
||||||
setlocal winfixheight
|
|
||||||
setlocal cursorline " make it easy to distinguish
|
|
||||||
|
|
||||||
" we need this to purge the buffer content
|
|
||||||
setlocal modifiable
|
|
||||||
|
|
||||||
"delete everything first from the buffer
|
|
||||||
%delete _
|
|
||||||
|
|
||||||
" add the content
|
|
||||||
call append(0, a:content)
|
|
||||||
|
|
||||||
" delete last line that comes from the append call
|
|
||||||
$delete _
|
|
||||||
|
|
||||||
" set it back to non modifiable
|
|
||||||
setlocal nomodifiable
|
|
||||||
endfunction
|
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
|
||||||
|
|
||||||
" format: 'interface file:lnum:coln'
|
" format: 'interface file:lnum:coln'
|
||||||
let mx = '^\(^\S*\)\s*\(.\{-}\):\(\d\+\):\(\d\+\)'
|
let mx = '^\(^\S*\)\s*\(.\{-}\):\(\d\+\):\(\d\+\)'
|
||||||
|
|
||||||
" parse it now into the list
|
" parse it now into the list
|
||||||
let tokens = matchlist(curline, mx)
|
let tokens = matchlist(curline, mx)
|
||||||
|
|
||||||
" convert to: 'file:lnum:coln'
|
" convert to: 'file:lnum:coln'
|
||||||
let expr = tokens[2] . ":" . tokens[3] . ":" . tokens[4]
|
let expr = tokens[2] . ":" . tokens[3] . ":" . tokens[4]
|
||||||
|
|
||||||
" jump to it in a new tab, we use explicit lgetexpr so we can later change
|
" jump to it in a new tab, we use explicit lgetexpr so we can later change
|
||||||
" the behaviour via settings (like opening in vsplit instead of tab)
|
" the behaviour via settings (like opening in vsplit instead of tab)
|
||||||
lgetexpr expr
|
lgetexpr expr
|
||||||
tab split
|
tab split
|
||||||
ll 1
|
ll 1
|
||||||
|
|
||||||
" center the word
|
" center the word
|
||||||
norm! zz
|
norm! zz
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
|
@ -1,123 +1,398 @@
|
|||||||
" 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
|
||||||
return '/'
|
return '/'
|
||||||
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
|
||||||
return ":"
|
return ":"
|
||||||
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'
|
||||||
return "\r"
|
return "\r"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
return "\n"
|
||||||
|
endfunction
|
||||||
|
|
||||||
return "\n"
|
" 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
|
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))
|
||||||
return 1
|
return 1
|
||||||
endif
|
endif
|
||||||
endfor
|
endfor
|
||||||
|
|
||||||
|
return 0
|
||||||
|
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
|
||||||
|
|
||||||
return 0
|
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
|
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)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
return a:path
|
return a:path
|
||||||
endfunction
|
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
|
||||||
if a:0
|
if a:0
|
||||||
return join(map(copy(a:arglist), 'shellescape(v:val, ' . a:1 . ')'), ' ')
|
return join(map(copy(a:arglist), 'shellescape(v:val, ' . a:1 . ')'), ' ')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
return join(map(copy(a:arglist), 'shellescape(v:val)'), ' ')
|
return join(map(copy(a:arglist), 'shellescape(v:val)'), ' ')
|
||||||
finally
|
finally
|
||||||
let &shellslash = ssl_save
|
let &shellslash = ssl_save
|
||||||
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
|
||||||
if a:0
|
if a:0
|
||||||
return map(copy(a:arglist), 'shellescape(v:val, ' . a:1 . ')')
|
return map(copy(a:arglist), 'shellescape(v:val, ' . a:1 . ')')
|
||||||
endif
|
endif
|
||||||
return map(copy(a:arglist), 'shellescape(v:val)')
|
return map(copy(a:arglist), 'shellescape(v:val)')
|
||||||
finally
|
finally
|
||||||
let &shellslash = ssl_save
|
let &shellslash = ssl_save
|
||||||
endtry
|
endtry
|
||||||
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)
|
||||||
let buf .= a:col == 1 ? '' : getline('.')[:a:col-2]
|
let buf .= a:col == 1 ? '' : getline('.')[:a:col-2]
|
||||||
return len(iconv(buf, &encoding, 'utf-8'))
|
return len(iconv(buf, &encoding, 'utf-8'))
|
||||||
endif
|
endif
|
||||||
return line2byte(a:line) + (a:col-2)
|
return line2byte(a:line) + (a:col-2)
|
||||||
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
|
||||||
|
|
||||||
function! go#util#EchoSuccess(msg)
|
" snippetcase converts the given word to given preferred snippet setting type
|
||||||
redraws! | echon "vim-go: " | echohl Function | echon a:msg | echohl None
|
" 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
|
endfunction
|
||||||
|
|
||||||
function! go#util#EchoError(msg)
|
" snakecase converts a string to snake case. i.e: FooBar -> foo_bar
|
||||||
redraws! | echon "vim-go: " | echohl ErrorMsg | echon a:msg | echohl None
|
" 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
|
endfunction
|
||||||
|
|
||||||
function! go#util#EchoWarning(msg)
|
" camelcase converts a string to camel case. e.g. FooBar or foo_bar will become
|
||||||
redraws! | echon "vim-go: " | echohl WarningMsg | echon a:msg | echohl None
|
" 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
|
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)
|
||||||
|
call s:echo(a:msg, 'Function')
|
||||||
|
endfunction
|
||||||
|
function! go#util#EchoError(msg)
|
||||||
|
call s:echo(a:msg, 'ErrorMsg')
|
||||||
|
endfunction
|
||||||
|
function! go#util#EchoWarning(msg)
|
||||||
|
call s:echo(a:msg, 'WarningMsg')
|
||||||
|
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
|
||||||
|
|
||||||
|
" 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
|
endfunction
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
" 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
|
|
@ -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
|
@ -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
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,7 @@
|
|||||||
|
if exists("b:did_ftplugin")
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
|
||||||
|
runtime! ftplugin/html.vim
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
@ -0,0 +1,3 @@
|
|||||||
|
if !reflect.DeepEqual({{+got+}}, {{+want+}}) {
|
||||||
|
t.Errorf("\ngot: %#v\nwant: %#v\n", {{+~\~2+}}, {{+~\~2+}})
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
if err != nil {
|
||||||
|
return {{+err+}}
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
{{++}}
|
@ -0,0 +1,3 @@
|
|||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "{{++}}")
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
// {{++}}
|
||||||
|
func {{+~\~1+}}() {
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
fmt.Printf("%#v\n", {{++}})
|
@ -0,0 +1,3 @@
|
|||||||
|
for i := 0; i < {{++}}; i++ {
|
||||||
|
{{++}}
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
// Package {{+~expand('%:p:h:t')+}} {{++}}
|
||||||
|
package {{+~\~2+}}
|
@ -0,0 +1,2 @@
|
|||||||
|
fmt.Sprintf("{{++}}", {{++}})
|
||||||
|
|
@ -1,173 +1,278 @@
|
|||||||
" install necessary Go tools
|
" install necessary Go tools
|
||||||
if exists("g:go_loaded_install")
|
if exists("g:go_loaded_install")
|
||||||
finish
|
finish
|
||||||
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)
|
||||||
" GoInstallBinaries downloads and install all necessary binaries stated in the
|
return filter(keys(s:packages), 'strpart(v:val, 0, len(a:lead)) == a:lead')
|
||||||
" packages variable. It uses by default $GOBIN or $GOPATH/bin as the binary
|
endfun
|
||||||
" target install directory. GoInstallBinaries doesn't install binaries if they
|
|
||||||
" exist, to update current binaries pass 1 to the argument.
|
" GoInstallBinaries downloads and installs binaries defined in s:packages to
|
||||||
function! s:GoInstallBinaries(updateBinaries)
|
" $GOBIN or $GOPATH/bin. GoInstallBinaries will update already installed
|
||||||
if $GOPATH == ""
|
" binaries only if updateBinaries = 1. By default, all packages in s:packages
|
||||||
echohl Error
|
" will be installed, but the set can be limited by passing the desired
|
||||||
echomsg "vim.go: $GOPATH is not set"
|
" packages in the unnamed arguments.
|
||||||
echohl None
|
function! s:GoInstallBinaries(updateBinaries, ...)
|
||||||
return
|
let err = s:CheckBinaries()
|
||||||
endif
|
if err != 0
|
||||||
|
return
|
||||||
let err = s:CheckBinaries()
|
endif
|
||||||
if err != 0
|
|
||||||
|
if go#path#Default() == ""
|
||||||
|
echohl Error
|
||||||
|
echomsg "vim.go: $GOPATH is not set and 'go env GOPATH' returns empty"
|
||||||
|
echohl None
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let go_bin_path = go#path#BinPath()
|
||||||
|
|
||||||
|
" change $GOBIN so go get can automatically install to it
|
||||||
|
let $GOBIN = go_bin_path
|
||||||
|
|
||||||
|
" old_path is used to restore users own path
|
||||||
|
let old_path = $PATH
|
||||||
|
|
||||||
|
" vim's executable path is looking in PATH so add our go_bin path to it
|
||||||
|
let $PATH = go_bin_path . go#util#PathListSep() . $PATH
|
||||||
|
|
||||||
|
" when shellslash is set on MS-* systems, shellescape puts single quotes
|
||||||
|
" around the output string. cmd on Windows does not handle single quotes
|
||||||
|
" correctly. Unsetting shellslash forces shellescape to use double quotes
|
||||||
|
" instead.
|
||||||
|
let resetshellslash = 0
|
||||||
|
if has('win32') && &shellslash
|
||||||
|
let resetshellslash = 1
|
||||||
|
set noshellslash
|
||||||
|
endif
|
||||||
|
|
||||||
|
let cmd = "go get -v "
|
||||||
|
if get(g:, "go_get_update", 1) != 0
|
||||||
|
let cmd .= "-u "
|
||||||
|
endif
|
||||||
|
|
||||||
|
let s:go_version = matchstr(go#util#System("go version"), '\d.\d.\d')
|
||||||
|
|
||||||
|
" https://github.com/golang/go/issues/10791
|
||||||
|
if s:go_version > "1.4.0" && s:go_version < "1.5.0"
|
||||||
|
let cmd .= "-f "
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Filter packages from arguments (if any).
|
||||||
|
let l:packages = {}
|
||||||
|
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
|
return
|
||||||
endif
|
endif
|
||||||
|
let l:packages[l:bin] = l:pkg
|
||||||
let go_bin_path = go#path#BinPath()
|
endfor
|
||||||
|
else
|
||||||
|
let l:packages = s:packages
|
||||||
|
endif
|
||||||
|
|
||||||
" change $GOBIN so go get can automatically install to it
|
let l:platform = ''
|
||||||
let $GOBIN = go_bin_path
|
if go#util#IsWin()
|
||||||
|
let l:platform = 'windows'
|
||||||
|
endif
|
||||||
|
|
||||||
" old_path is used to restore users own path
|
for [binary, pkg] in items(l:packages)
|
||||||
let old_path = $PATH
|
let l:importPath = pkg[0]
|
||||||
|
let l:goGetFlags = len(pkg) > 1 ? get(pkg[1], l:platform, '') : ''
|
||||||
|
|
||||||
" vim's executable path is looking in PATH so add our go_bin path to it
|
let binname = "go_" . binary . "_bin"
|
||||||
let $PATH = $PATH . go#util#PathListSep() .go_bin_path
|
|
||||||
|
|
||||||
" when shellslash is set on MS-* systems, shellescape puts single quotes
|
let bin = binary
|
||||||
" around the output string. cmd on Windows does not handle single quotes
|
if exists("g:{binname}")
|
||||||
" correctly. Unsetting shellslash forces shellescape to use double quotes
|
let bin = g:{binname}
|
||||||
" instead.
|
|
||||||
let resetshellslash = 0
|
|
||||||
if has('win32') && &shellslash
|
|
||||||
let resetshellslash = 1
|
|
||||||
set noshellslash
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let cmd = "go get -u -v "
|
if !executable(bin) || a:updateBinaries == 1
|
||||||
|
if a:updateBinaries == 1
|
||||||
let s:go_version = matchstr(system("go version"), '\d.\d.\d')
|
echo "vim-go: Updating " . binary . ". Reinstalling ". importPath . " to folder " . go_bin_path
|
||||||
|
else
|
||||||
" https://github.com/golang/go/issues/10791
|
echo "vim-go: ". binary ." not found. Installing ". importPath . " to folder " . go_bin_path
|
||||||
if s:go_version > "1.4.0" && s:go_version < "1.5.0"
|
endif
|
||||||
let cmd .= "-f "
|
|
||||||
|
let out = go#util#System(printf('%s %s %s', cmd, l:goGetFlags, shellescape(importPath)))
|
||||||
|
if go#util#ShellError() != 0
|
||||||
|
echom "Error installing " . importPath . ": " . out
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
endfor
|
||||||
|
|
||||||
for pkg in s:packages
|
" restore back!
|
||||||
let basename = fnamemodify(pkg, ":t")
|
let $PATH = old_path
|
||||||
let binname = "go_" . basename . "_bin"
|
if resetshellslash
|
||||||
|
set shellslash
|
||||||
let bin = basename
|
endif
|
||||||
if exists("g:{binname}")
|
|
||||||
let bin = g:{binname}
|
|
||||||
endif
|
|
||||||
|
|
||||||
if !executable(bin) || a:updateBinaries == 1
|
|
||||||
if a:updateBinaries == 1
|
|
||||||
echo "vim-go: Updating ". basename .". Reinstalling ". pkg . " to folder " . go_bin_path
|
|
||||||
else
|
|
||||||
echo "vim-go: ". basename ." not found. Installing ". pkg . " to folder " . go_bin_path
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
let out = system(cmd . shellescape(pkg))
|
|
||||||
if v:shell_error
|
|
||||||
echo "Error installing ". pkg . ": " . out
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
|
|
||||||
" restore back!
|
|
||||||
let $PATH = old_path
|
|
||||||
if resetshellslash
|
|
||||||
set shellslash
|
|
||||||
endif
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" CheckBinaries checks if the necessary binaries to install the Go tool
|
" CheckBinaries checks if the necessary binaries to install the Go tool
|
||||||
" commands are available.
|
" commands are available.
|
||||||
function! s:CheckBinaries()
|
function! s:CheckBinaries()
|
||||||
if !executable('go')
|
if !executable('go')
|
||||||
echohl Error | echomsg "vim-go: go executable not found." | echohl None
|
echohl Error | echomsg "vim-go: go executable not found." | echohl None
|
||||||
return -1
|
return -1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if !executable('git')
|
if !executable('git')
|
||||||
echohl Error | echomsg "vim-go: git executable not found." | echohl None
|
echohl Error | echomsg "vim-go: git executable not found." | echohl None
|
||||||
return -1
|
return -1
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Autocommands
|
" Autocommands
|
||||||
" ============================================================================
|
" ============================================================================
|
||||||
"
|
"
|
||||||
function! s:echo_go_info()
|
function! s:echo_go_info()
|
||||||
if !exists('v:completed_item') || empty(v:completed_item)
|
if !get(g:, "go_echo_go_info", 1)
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
let item = v:completed_item
|
|
||||||
|
|
||||||
if !has_key(item, "info")
|
if !exists('v:completed_item') || empty(v:completed_item)
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
let item = v:completed_item
|
||||||
|
|
||||||
if empty(item.info)
|
if !has_key(item, "info")
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
redraws! | echo "vim-go: " | echohl Function | echon item.info | echohl None
|
if empty(item.info)
|
||||||
endfunction
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
augroup vim-go
|
redraws! | echo "vim-go: " | echohl Function | echon item.info | echohl None
|
||||||
autocmd!
|
endfunction
|
||||||
|
|
||||||
" GoInfo automatic update
|
function! s:auto_type_info()
|
||||||
if get(g:, "go_auto_type_info", 0)
|
" GoInfo automatic update
|
||||||
autocmd CursorHold *.go nested call go#complete#Info(1)
|
if get(g:, "go_auto_type_info", 0)
|
||||||
endif
|
call go#tool#Info(1)
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
" Echo the identifier information when completion is done. Useful to see
|
function! s:auto_sameids()
|
||||||
" the signature of a function, etc...
|
" GoSameId automatic update
|
||||||
if exists('##CompleteDone')
|
if get(g:, "go_auto_sameids", 0)
|
||||||
autocmd CompleteDone *.go nested call s:echo_go_info()
|
call go#guru#SameIds()
|
||||||
endif
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
" Go code formatting on save
|
function! s:fmt_autosave()
|
||||||
if get(g:, "go_fmt_autosave", 1)
|
" Go code formatting on save
|
||||||
autocmd BufWritePre *.go call go#fmt#Format(-1)
|
if get(g:, "go_fmt_autosave", 1)
|
||||||
endif
|
call go#fmt#Format(-1)
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
" Go asm formatting on save
|
function! s:asmfmt_autosave()
|
||||||
if get(g:, "go_asmfmt_autosave", 1)
|
" Go asm formatting on save
|
||||||
autocmd BufWritePre *.s call go#asmfmt#Format()
|
if get(g:, "go_asmfmt_autosave", 0)
|
||||||
endif
|
call go#asmfmt#Format()
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
" run gometalinter on save
|
function! s:metalinter_autosave()
|
||||||
if get(g:, "go_metalinter_autosave", 0)
|
" run gometalinter on save
|
||||||
autocmd BufWritePost *.go call go#lint#Gometa(1)
|
if get(g:, "go_metalinter_autosave", 0)
|
||||||
endif
|
call go#lint#Gometa(1)
|
||||||
augroup END
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:template_autocreate()
|
||||||
|
" create new template from scratch
|
||||||
|
if get(g:, "go_template_autocreate", 1)
|
||||||
|
call go#template#create()
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
" vim:ts=4:sw=4:et
|
augroup vim-go
|
||||||
|
autocmd!
|
||||||
|
|
||||||
|
autocmd CursorHold *.go call s:auto_type_info()
|
||||||
|
autocmd CursorHold *.go call s:auto_sameids()
|
||||||
|
|
||||||
|
" Echo the identifier information when completion is done. Useful to see
|
||||||
|
" the signature of a function, etc...
|
||||||
|
if exists('##CompleteDone')
|
||||||
|
autocmd CompleteDone *.go call s:echo_go_info()
|
||||||
|
endif
|
||||||
|
|
||||||
|
autocmd BufWritePre *.go call s:fmt_autosave()
|
||||||
|
autocmd BufWritePre *.s call s:asmfmt_autosave()
|
||||||
|
autocmd BufWritePost *.go call s:metalinter_autosave()
|
||||||
|
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()
|
||||||
|
|
||||||
|
autocmd BufEnter *.go
|
||||||
|
\ if get(g:, 'go_autodetect_gopath', 0) && !exists('b:old_gopath')
|
||||||
|
\| let b:old_gopath = exists('$GOPATH') ? $GOPATH : -1
|
||||||
|
\| 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
|
||||||
|
|
||||||
|
" vim: sw=2 ts=2 et
|
||||||
|
@ -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