├── LICENSE ├── README.md ├── denops ├── @ddc-github │ ├── deps.ts │ ├── issue.ts │ ├── pull_request.ts │ ├── types.ts │ └── util.ts └── @ddc-sources │ ├── github_issue.ts │ └── github_pull_request.ts └── doc └── ddc-github.txt /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Hibiki 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ddc-github 2 | 3 | GitHub completion for ddc.vim via gh 4 | 5 | These sources collect something related to GitHub (e.g. issues, pull requests) 6 | via gh, which is GitHub’s official command line tool. 7 | 8 | Now ddc-github provides below sources: 9 | 10 | - `github_issue` 11 | - `github_pull_request` 12 | 13 | Please read [help](doc/ddc-github.txt) for details. 14 | 15 | ## Requirements 16 | 17 | - [gh](https://github.com/cli/cli) 18 | - [denops.vim](https://github.com/vim-denops/denops.vim) 19 | - [ddc.vim](https://github.com/Shougo/ddc.vim) 20 | 21 | ## Configuration 22 | 23 | ```vim 24 | " Use github sources 25 | call ddc#custom#patch_global('sources', ['github_issue', 'github_pull_request']) 26 | 27 | " Change source options 28 | call ddc#custom#patch_global('souceOptions', { 29 | \ 'github_issue': { 30 | \ 'mark': 'issue', 31 | \ 'forceCompletionPattern': '#\d*', 32 | \ }, 33 | \ }) 34 | 35 | " Use on specific filetype 36 | call ddc#custom#patch_filetype(['gitcommit'], { 37 | \ 'sources': ['github_issue', 'github_pull_request'], 38 | \ 'keywordPattern': '[a-zA-Z_:#]\k*', 39 | \ }) 40 | 41 | " Use on `gh (issue|pr) create` buffer 42 | function! s:on_gh() abort 43 | " Check whether the file is gh's buffer 44 | let tmpdir = empty($TMPDIR) ? '/tmp' : expand('$TMPDIR') 45 | if fnamemodify(bufname(), ':h') != tmpdir || getcwd() == tmpdir 46 | return 47 | endif 48 | " Over sources 49 | call ddc#custom#patch_buffer({ 50 | \ 'sources': ['github_issue', 'github_pull_request'], 51 | \ 'keywordPattern': '[a-zA-Z_:#]\k*', 52 | \ }) 53 | inoremap 54 | \ ddc#map#manual_complete('github_issue', 'github_pull_request') 55 | endfunction 56 | autocmd FileType markdown call on_gh() 57 | ``` 58 | -------------------------------------------------------------------------------- /denops/@ddc-github/deps.ts: -------------------------------------------------------------------------------- 1 | export type { 2 | GatherArguments, 3 | OnInitArguments, 4 | } from "https://deno.land/x/ddc_vim@v2.2.0/base/source.ts"; 5 | export type { Item } from "https://deno.land/x/ddc_vim@v2.2.0/types.ts"; 6 | export { BaseSource } from "https://deno.land/x/ddc_vim@v2.2.0/types.ts"; 7 | -------------------------------------------------------------------------------- /denops/@ddc-github/issue.ts: -------------------------------------------------------------------------------- 1 | import { defaultRepository, runGh } from "./util.ts"; 2 | import type { Issue, Repository } from "./types.ts"; 3 | 4 | export async function getIssue( 5 | options: { 6 | repo?: Repository; 7 | state?: "all" | "closed" | "open"; 8 | cwd?: string; 9 | }, 10 | ): Promise { 11 | const { name, owner } = options.repo ?? await defaultRepository(options.cwd); 12 | const issues: Issue[] | null = await runGh( 13 | [ 14 | "issue", 15 | "list", 16 | "--state", 17 | options.state ?? "all", 18 | "--repo", 19 | `${owner}/${name}`, 20 | ], 21 | ["number", "title", "state", "body"], 22 | options.cwd, 23 | ); 24 | if (!issues) { 25 | throw new Error(`Cannot get issue list from ${owner}/${name}`); 26 | } 27 | return issues; 28 | } 29 | -------------------------------------------------------------------------------- /denops/@ddc-github/pull_request.ts: -------------------------------------------------------------------------------- 1 | import { defaultRepository, runGh } from "./util.ts"; 2 | import type { PullRequest, Repository } from "./pull_request.ts"; 3 | 4 | export async function getPullRequest( 5 | options: { 6 | repo?: Repository; 7 | state?: "all" | "closed" | "merged" | "open"; 8 | cwd?: string; 9 | }, 10 | ): Promise { 11 | const { name, owner } = options.repo ?? await defaultRepository(options.cwd); 12 | const pullRequests: PullRequest[] | null = await runGh( 13 | [ 14 | "pr", 15 | "list", 16 | "--state", 17 | options.state ?? "all", 18 | "--repo", 19 | `${owner}/${name}`, 20 | ], 21 | ["number", "title", "state", "body"], 22 | options.cwd, 23 | ); 24 | if (!pullRequests) { 25 | throw new Error(`Cannot get pull-request list from ${owner}/${name}`); 26 | } 27 | return pullRequests; 28 | } 29 | -------------------------------------------------------------------------------- /denops/@ddc-github/types.ts: -------------------------------------------------------------------------------- 1 | export interface Repository { 2 | name: string; 3 | owner: string; 4 | } 5 | 6 | export interface Issue { 7 | number: number; 8 | title: string; 9 | state: "CLOSED" | "OPEN"; 10 | body: string; 11 | } 12 | 13 | export interface PullRequest { 14 | number: number; 15 | title: string; 16 | state: "CLOSED" | "OPEN" | "MERGED"; 17 | body: string; 18 | } 19 | -------------------------------------------------------------------------------- /denops/@ddc-github/util.ts: -------------------------------------------------------------------------------- 1 | import type { Repository } from "./types.ts"; 2 | 3 | export async function runGh( 4 | subcmds: string[], 5 | fields: A, 6 | cwd?: string, 7 | ): Promise | Record[] | null> { 8 | const proc = Deno.run({ 9 | cmd: ["gh", ...subcmds, ...(fields.flatMap((i) => ["--json", i]))], 10 | stderr: "piped", 11 | stdout: "piped", 12 | stdin: "null", 13 | cwd: cwd ?? Deno.cwd(), 14 | }); 15 | const [status, stdout, stderr] = await Promise.all([ 16 | proc.status(), 17 | proc.output(), 18 | proc.stderrOutput(), 19 | ]); 20 | proc.close(); 21 | if (status.success) { 22 | const output = new TextDecoder().decode(stdout); 23 | return JSON.parse(output); 24 | } 25 | console.error(new TextDecoder().decode(stderr)); 26 | return null; 27 | } 28 | 29 | export async function defaultRepository(cwd?: string): Promise { 30 | const repo: Repository | null = await runGh( 31 | [ 32 | "repo", 33 | "view", 34 | "--jq", 35 | ".owner |= .login", 36 | ], 37 | ["name", "owner"], 38 | cwd, 39 | ); 40 | if (!repo) { 41 | throw new Error("Cannnot get remote repository information"); 42 | } 43 | return repo; 44 | } 45 | -------------------------------------------------------------------------------- /denops/@ddc-sources/github_issue.ts: -------------------------------------------------------------------------------- 1 | import { 2 | BaseSource, 3 | GatherArguments, 4 | Item, 5 | OnInitArguments, 6 | } from "../@ddc-github/deps.ts"; 7 | import { getIssue } from "../@ddc-github/issue.ts"; 8 | import type { Issue } from "../@ddc-github/types.ts"; 9 | 10 | interface Params { 11 | state: "all" | "closed" | "open"; 12 | menuItem: "state" | "title" | "body"; 13 | infoItem: "state" | "title" | "body"; 14 | } 15 | 16 | export class Source extends BaseSource { 17 | private issues: Issue[] = []; 18 | 19 | async onInit(args: OnInitArguments): Promise { 20 | this.issues = await getIssue({ 21 | state: args.sourceParams.state, 22 | cwd: await args.denops.call("getcwd"), 23 | }); 24 | } 25 | 26 | gather(args: GatherArguments): Promise { 27 | return Promise.resolve(this.issues.map((i) => ({ 28 | word: `#${i.number}`, 29 | menu: i[args.sourceParams.menuItem].replaceAll("\r\n", "\n"), 30 | info: i[args.sourceParams.infoItem].replaceAll("\r\n", "\n"), 31 | }))); 32 | } 33 | 34 | params(): Params { 35 | return { 36 | state: "all", 37 | menuItem: "title", 38 | infoItem: "body", 39 | }; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /denops/@ddc-sources/github_pull_request.ts: -------------------------------------------------------------------------------- 1 | import { 2 | BaseSource, 3 | GatherArguments, 4 | Item, 5 | OnInitArguments, 6 | } from "../@ddc-github/deps.ts"; 7 | import { getPullRequest } from "../@ddc-github/pull_request.ts"; 8 | import type { PullRequest } from "../@ddc-github/types.ts"; 9 | 10 | interface Params { 11 | state: "all" | "closed" | "merged" | "open"; 12 | menuItem: "state" | "title" | "body"; 13 | infoItem: "state" | "title" | "body"; 14 | } 15 | 16 | export class Source extends BaseSource { 17 | private pullRequests: PullRequest[] = []; 18 | 19 | async onInit(args: OnInitArguments): Promise { 20 | this.pullRequests = await getPullRequest({ 21 | state: args.sourceParams.state, 22 | cwd: await args.denops.call("getcwd"), 23 | }); 24 | } 25 | 26 | gather(args: GatherArguments): Promise { 27 | return Promise.resolve(this.pullRequests.map((i) => ({ 28 | word: `#${i.number}`, 29 | menu: i[args.sourceParams.menuItem].replaceAll("\r\n", "\n"), 30 | info: i[args.sourceParams.infoItem].replaceAll("\r\n", "\n"), 31 | }))); 32 | } 33 | 34 | params(): Params { 35 | return { 36 | state: "all", 37 | menuItem: "title", 38 | infoItem: "body", 39 | }; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /doc/ddc-github.txt: -------------------------------------------------------------------------------- 1 | *ddc-github.txt* GitHub completion for ddc.vim via gh 2 | 3 | Author: Hibiki 4 | License: MIT License 5 | URL: https://github.com/4513ECHO/ddc-github 6 | Last change: 2023 May 16 7 | 8 | ============================================================================== 9 | CONTENTS *ddc-github-contents* 10 | 11 | Introduction |ddc-github-introduction| 12 | Install |ddc-github-install| 13 | Examples |ddc-github-examples| 14 | Params |ddc-github-params| 15 | github_issue |ddc-github_issue-params| 16 | github_pull_request |ddc-github_pull_request-params| 17 | About |ddc-github-about| 18 | 19 | ============================================================================== 20 | INTRODUCTION *ddc-github-introduction* 21 | 22 | These sources collect something related to GitHub (e.g. issues, pull requests) 23 | via gh, which is GitHub’s official command line tool. 24 | 25 | Now *ddc-github* provides below sources: 26 | 27 | github_issue *ddc-github_issue* 28 | github_pull_request *ddc-github_pull_request* 29 | 30 | ============================================================================== 31 | INSTALL *ddc-github-install* 32 | 33 | Please install "gh", "|ddc|.vim" and "|denops.vim|". 34 | 35 | https://github.com/cli/cli (gh) 36 | https://github.com/Shougo/ddc.vim 37 | https://github.com/vim-denops/denops.vim 38 | 39 | ============================================================================== 40 | EXAMPLES *ddc-github-examples* 41 | 42 | > 43 | " Use github sources 44 | call ddc#custom#patch_global('sources', ['github_issue', 'github_pull_request']) 45 | 46 | " Change source options 47 | call ddc#custom#patch_global('souceOptions', { 48 | \ 'github_issue': { 49 | \ 'mark': 'issue', 50 | \ 'forceCompletionPattern': '#\d*', 51 | \ }, 52 | \ }) 53 | 54 | " Use on specific filetype 55 | call ddc#custom#patch_filetype(['gitcommit'], { 56 | \ 'sources': ['github_issue', 'github_pull_request'], 57 | \ 'keywordPattern': '[a-zA-Z_:#]\k*', 58 | \ }) 59 | 60 | " Use on `gh (issue|pr) create` buffer 61 | function! s:on_gh() abort 62 | " Check whether the file is gh's buffer 63 | let tmpdir = empty($TMPDIR) ? '/tmp' : expand('$TMPDIR') 64 | if fnamemodify(bufname(), ':h') != tmpdir || getcwd() == tmpdir 65 | return 66 | endif 67 | " Over sources 68 | call ddc#custom#patch_buffer({ 69 | \ 'sources': ['github_issue', 'github_pull_request'], 70 | \ 'keywordPattern': '[a-zA-Z_:#]\k*', 71 | \ }) 72 | inoremap 73 | \ ddc#map#manual_complete('github_issue', 'github_pull_request') 74 | endfunction 75 | autocmd FileType markdown call on_gh() 76 | < 77 | 78 | ============================================================================== 79 | PARAMS *ddc-github-params* 80 | 81 | ------------------------------------------------------------------------------ 82 | GITHUB_ISSUE *ddc-github_issue-params* 83 | 84 | state "all" | "closed" | "open" (default: "all") 85 | Filter of issue state. 86 | 87 | menuItem "state" | "title" | "body" (default: "title") 88 | Displayed item in |ddc-item-attribute-menu|. Following values are 89 | available: 90 | 91 | value description~ 92 | "state" issue state 93 | "title" issue title 94 | "body" issue doby 95 | 96 | infoItem "state" | "title" | "body" (default: "body") 97 | Displayed item in |ddc-item-attribute-info|. Following values are same 98 | as `menuItem`. 99 | 100 | ------------------------------------------------------------------------------ 101 | GITHUB_PULL_REQUEST *ddc-github_pull_request-params* 102 | 103 | state "all" | "closed" | "merged" | "open" (default: "all") 104 | Filter of pull request state. 105 | 106 | menuItem "state" | "title" | "body" (default: "title") 107 | Displayed item in |ddc-item-attribute-menu|. Following values are 108 | available: 109 | 110 | value description~ 111 | "state" pull request state 112 | "title" pull request title 113 | "body" pull request doby 114 | 115 | infoItem "state" | "title" | "body" (default: "body") 116 | Displayed item in |ddc-item-attribute-info|. Following values are same 117 | as `menuItem`. 118 | 119 | ============================================================================== 120 | ABOUT *ddc-github-about* 121 | 122 | |ddc-github| is developed by Hibiki(4513ECHO) and licensed under the 123 | MIT License. Visit the project page for the latest version: 124 | 125 | https://github.com/4513ECHO/ddc-github 126 | 127 | ============================================================================== 128 | vim:tw=78:ts=8:ft=help:norl:noet:fen: 129 | --------------------------------------------------------------------------------