Temporary registers, SSH Port, Bug Fixes (#251)
- allows SSH Gitlab connection to have custom port - introduces temporary registers - fixes issue w/ quitting the popup on MR creation This is a #MINOR release
This commit is contained in:
committed by
GitHub
parent
36f512cd6d
commit
7c3ee0530b
13
README.md
13
README.md
@@ -127,6 +127,7 @@ require("gitlab").setup({
|
|||||||
pipeline = nil,
|
pipeline = nil,
|
||||||
reply = nil,
|
reply = nil,
|
||||||
squash_message = nil,
|
squash_message = nil,
|
||||||
|
temp_registers = {}, -- List of registers for backing up popup content (see `:h gitlab.nvim.temp-registers`)
|
||||||
},
|
},
|
||||||
discussion_tree = { -- The discussion tree that holds all comments
|
discussion_tree = { -- The discussion tree that holds all comments
|
||||||
auto_open = true, -- Automatically open when the reviewer is opened
|
auto_open = true, -- Automatically open when the reviewer is opened
|
||||||
@@ -169,8 +170,12 @@ require("gitlab").setup({
|
|||||||
"conflicts",
|
"conflicts",
|
||||||
"assignees",
|
"assignees",
|
||||||
"reviewers",
|
"reviewers",
|
||||||
"branch",
|
|
||||||
"pipeline",
|
"pipeline",
|
||||||
|
"branch",
|
||||||
|
"target_branch",
|
||||||
|
"delete_branch",
|
||||||
|
"squash",
|
||||||
|
"labels",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
discussion_signs = {
|
discussion_signs = {
|
||||||
@@ -195,13 +200,11 @@ require("gitlab").setup({
|
|||||||
success = "✓",
|
success = "✓",
|
||||||
failed = "",
|
failed = "",
|
||||||
},
|
},
|
||||||
merge = { -- The default behaviors when merging an MR, see "Merging an MR"
|
|
||||||
squash = false,
|
|
||||||
delete_branch = false,
|
|
||||||
},
|
|
||||||
create_mr = {
|
create_mr = {
|
||||||
target = nil, -- Default branch to target when creating an MR
|
target = nil, -- Default branch to target when creating an MR
|
||||||
template_file = nil, -- Default MR template in .gitlab/merge_request_templates
|
template_file = nil, -- Default MR template in .gitlab/merge_request_templates
|
||||||
|
delete_branch = false, -- Whether the source branch will be marked for deletion
|
||||||
|
squash = false, -- Whether the commits will be marked for squashing
|
||||||
title_input = { -- Default settings for MR title input window
|
title_input = { -- Default settings for MR title input window
|
||||||
width = 40,
|
width = 40,
|
||||||
border = "rounded",
|
border = "rounded",
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ type CreateMrRequest struct {
|
|||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
TargetBranch string `json:"target_branch"`
|
TargetBranch string `json:"target_branch"`
|
||||||
|
DeleteBranch bool `json:"delete_branch"`
|
||||||
|
Squash bool `json:"squash"`
|
||||||
}
|
}
|
||||||
|
|
||||||
/* createMr creates a merge request */
|
/* createMr creates a merge request */
|
||||||
@@ -49,10 +51,12 @@ func (a *api) createMr(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
opts := gitlab.CreateMergeRequestOptions{
|
opts := gitlab.CreateMergeRequestOptions{
|
||||||
Title: &createMrRequest.Title,
|
Title: &createMrRequest.Title,
|
||||||
Description: &createMrRequest.Description,
|
Description: &createMrRequest.Description,
|
||||||
TargetBranch: &createMrRequest.TargetBranch,
|
TargetBranch: &createMrRequest.TargetBranch,
|
||||||
SourceBranch: &a.gitInfo.BranchName,
|
SourceBranch: &a.gitInfo.BranchName,
|
||||||
|
RemoveSourceBranch: &createMrRequest.DeleteBranch,
|
||||||
|
Squash: &createMrRequest.Squash,
|
||||||
}
|
}
|
||||||
|
|
||||||
_, res, err := a.client.CreateMergeRequest(a.projectInfo.ProjectId, &opts)
|
_, res, err := a.client.CreateMergeRequest(a.projectInfo.ProjectId, &opts)
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ func TestCreateMr(t *testing.T) {
|
|||||||
Title: "Some title",
|
Title: "Some title",
|
||||||
Description: "Some description",
|
Description: "Some description",
|
||||||
TargetBranch: "main",
|
TargetBranch: "main",
|
||||||
|
DeleteBranch: false,
|
||||||
|
Squash: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
request := makeRequest(t, http.MethodPost, "/create_mr", body)
|
request := makeRequest(t, http.MethodPost, "/create_mr", body)
|
||||||
@@ -48,6 +50,8 @@ func TestCreateMr(t *testing.T) {
|
|||||||
Title: "Some title",
|
Title: "Some title",
|
||||||
Description: "Some description",
|
Description: "Some description",
|
||||||
TargetBranch: "main",
|
TargetBranch: "main",
|
||||||
|
DeleteBranch: false,
|
||||||
|
Squash: false,
|
||||||
}
|
}
|
||||||
request := makeRequest(t, http.MethodPost, "/create_mr", body)
|
request := makeRequest(t, http.MethodPost, "/create_mr", body)
|
||||||
server, _ := createRouterAndApi(fakeClient{createMrFn: createMrFnErr})
|
server, _ := createRouterAndApi(fakeClient{createMrFn: createMrFnErr})
|
||||||
@@ -60,6 +64,8 @@ func TestCreateMr(t *testing.T) {
|
|||||||
Title: "Some title",
|
Title: "Some title",
|
||||||
Description: "Some description",
|
Description: "Some description",
|
||||||
TargetBranch: "main",
|
TargetBranch: "main",
|
||||||
|
DeleteBranch: false,
|
||||||
|
Squash: false,
|
||||||
}
|
}
|
||||||
request := makeRequest(t, http.MethodPost, "/create_mr", body)
|
request := makeRequest(t, http.MethodPost, "/create_mr", body)
|
||||||
server, _ := createRouterAndApi(fakeClient{createMrFn: createMrFnNon200})
|
server, _ := createRouterAndApi(fakeClient{createMrFn: createMrFnNon200})
|
||||||
@@ -72,6 +78,8 @@ func TestCreateMr(t *testing.T) {
|
|||||||
Title: "",
|
Title: "",
|
||||||
Description: "Some description",
|
Description: "Some description",
|
||||||
TargetBranch: "main",
|
TargetBranch: "main",
|
||||||
|
DeleteBranch: false,
|
||||||
|
Squash: false,
|
||||||
}
|
}
|
||||||
request := makeRequest(t, http.MethodPost, "/create_mr", body)
|
request := makeRequest(t, http.MethodPost, "/create_mr", body)
|
||||||
server, _ := createRouterAndApi(fakeClient{createMrFn: createMrFn})
|
server, _ := createRouterAndApi(fakeClient{createMrFn: createMrFn})
|
||||||
@@ -86,6 +94,8 @@ func TestCreateMr(t *testing.T) {
|
|||||||
Title: "Some title",
|
Title: "Some title",
|
||||||
Description: "Some description",
|
Description: "Some description",
|
||||||
TargetBranch: "",
|
TargetBranch: "",
|
||||||
|
DeleteBranch: false,
|
||||||
|
Squash: false,
|
||||||
}
|
}
|
||||||
request := makeRequest(t, http.MethodPost, "/create_mr", body)
|
request := makeRequest(t, http.MethodPost, "/create_mr", body)
|
||||||
server, _ := createRouterAndApi(fakeClient{createMrFn: createMrFn})
|
server, _ := createRouterAndApi(fakeClient{createMrFn: createMrFn})
|
||||||
|
|||||||
@@ -28,14 +28,12 @@ it to the client for initialization. The current directory must be a valid
|
|||||||
Gitlab project and the branch must be a feature branch
|
Gitlab project and the branch must be a feature branch
|
||||||
*/
|
*/
|
||||||
func extractGitInfo(refreshGitInfo func() error, getProjectRemoteUrl func() (string, error), getCurrentBranchName func() (string, error)) (GitProjectInfo, error) {
|
func extractGitInfo(refreshGitInfo func() error, getProjectRemoteUrl func() (string, error), getCurrentBranchName func() (string, error)) (GitProjectInfo, error) {
|
||||||
|
|
||||||
err := refreshGitInfo()
|
err := refreshGitInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return GitProjectInfo{}, fmt.Errorf("Could not get latest information from remote: %v", err)
|
return GitProjectInfo{}, fmt.Errorf("Could not get latest information from remote: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
url, err := getProjectRemoteUrl()
|
url, err := getProjectRemoteUrl()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return GitProjectInfo{}, fmt.Errorf("Could not get project Url: %v", err)
|
return GitProjectInfo{}, fmt.Errorf("Could not get project Url: %v", err)
|
||||||
}
|
}
|
||||||
@@ -52,7 +50,7 @@ func extractGitInfo(refreshGitInfo func() error, getProjectRemoteUrl func() (str
|
|||||||
https://git@gitlab.com/namespace/subnamespace/dummy-test-repo.git
|
https://git@gitlab.com/namespace/subnamespace/dummy-test-repo.git
|
||||||
git@git@gitlab.com:namespace/subnamespace/dummy-test-repo.git
|
git@git@gitlab.com:namespace/subnamespace/dummy-test-repo.git
|
||||||
*/
|
*/
|
||||||
re := regexp.MustCompile(`(?:^https?:\/\/|^ssh:\/\/|^git@)(?:[^\/:]+)[\/:](.*)\/([^\/]+?)(?:\.git)?$`)
|
re := regexp.MustCompile(`(?:^https?:\/\/|^ssh:\/\/|^git@)(?:[^\/:]+)(?::\d+)?[\/:](.*)\/([^\/]+?)(?:\.git)?$`)
|
||||||
matches := re.FindStringSubmatch(url)
|
matches := re.FindStringSubmatch(url)
|
||||||
if len(matches) != 3 {
|
if len(matches) != 3 {
|
||||||
return GitProjectInfo{}, fmt.Errorf("Invalid Git URL format: %s", url)
|
return GitProjectInfo{}, fmt.Errorf("Invalid Git URL format: %s", url)
|
||||||
|
|||||||
@@ -102,6 +102,18 @@ func TestExtractGitInfo_Success(t *testing.T) {
|
|||||||
Namespace: "namespace-1/namespace-2/namespace-3",
|
Namespace: "namespace-1/namespace-2/namespace-3",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "Project configured in SSH:// and have a custom port",
|
||||||
|
getProjectRemoteUrl: func() (string, error) {
|
||||||
|
return "ssh://custom-gitlab.com:2222/namespace-1/project-name", nil
|
||||||
|
},
|
||||||
|
expected: GitProjectInfo{
|
||||||
|
RemoteUrl: "ssh://custom-gitlab.com:2222/namespace-1/project-name",
|
||||||
|
BranchName: "feature/abc",
|
||||||
|
ProjectName: "project-name",
|
||||||
|
Namespace: "namespace-1",
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "Project configured in HTTP and under a single folder without .git extension",
|
desc: "Project configured in HTTP and under a single folder without .git extension",
|
||||||
getProjectRemoteUrl: func() (string, error) {
|
getProjectRemoteUrl: func() (string, error) {
|
||||||
|
|||||||
@@ -11,10 +11,11 @@ Table of Contents *gitlab.nvim.table-of-contents*
|
|||||||
- Usage |gitlab.nvim.usage|
|
- Usage |gitlab.nvim.usage|
|
||||||
- The Summary view |gitlab.nvim.the-summary-view|
|
- The Summary view |gitlab.nvim.the-summary-view|
|
||||||
- Reviewing an MR |gitlab.nvim.reviewing-an-mr|
|
- Reviewing an MR |gitlab.nvim.reviewing-an-mr|
|
||||||
|
- Temporary registers |gitlab.nvim.temp-registers|
|
||||||
- Discussions and Notes |gitlab.nvim.discussions-and-notes|
|
- Discussions and Notes |gitlab.nvim.discussions-and-notes|
|
||||||
- Labels |gitlab.nvim.labels|
|
- Labels |gitlab.nvim.labels|
|
||||||
- Signs and diagnostics |gitlab.nvim.signs-and-diagnostics|
|
- Signs and diagnostics |gitlab.nvim.signs-and-diagnostics|
|
||||||
- Emojis gitlab.nvim.emojis
|
- Emojis |gitlab.nvim.emojis|
|
||||||
- Uploading Files |gitlab.nvim.uploading-files|
|
- Uploading Files |gitlab.nvim.uploading-files|
|
||||||
- MR Approvals |gitlab.nvim.mr-approvals|
|
- MR Approvals |gitlab.nvim.mr-approvals|
|
||||||
- Merging an MR |gitlab.nvim.merging-an-mr|
|
- Merging an MR |gitlab.nvim.merging-an-mr|
|
||||||
@@ -26,6 +27,7 @@ Table of Contents *gitlab.nvim.table-of-contents*
|
|||||||
- Troubleshooting |gitlab.nvim.troubleshooting|
|
- Troubleshooting |gitlab.nvim.troubleshooting|
|
||||||
- Api |gitlab.nvim.api|
|
- Api |gitlab.nvim.api|
|
||||||
|
|
||||||
|
|
||||||
OVERVIEW *gitlab.nvim.overview*
|
OVERVIEW *gitlab.nvim.overview*
|
||||||
|
|
||||||
This Neovim plugin is designed to make it easy to review Gitlab MRs from within
|
This Neovim plugin is designed to make it easy to review Gitlab MRs from within
|
||||||
@@ -39,6 +41,7 @@ the editor. This means you can do things like:
|
|||||||
- View and manage pipeline Jobs
|
- View and manage pipeline Jobs
|
||||||
- Upload files, jump to the browser, and a lot more!
|
- Upload files, jump to the browser, and a lot more!
|
||||||
|
|
||||||
|
|
||||||
REQUIREMENTS *gitlab.nvim.requirements*
|
REQUIREMENTS *gitlab.nvim.requirements*
|
||||||
|
|
||||||
- Go >= v1.19
|
- Go >= v1.19
|
||||||
@@ -56,7 +59,6 @@ QUICK START *gitlab.nvim.quick-start*
|
|||||||
INSTALLATION *gitlab.nvim.installation*
|
INSTALLATION *gitlab.nvim.installation*
|
||||||
|
|
||||||
With Lazy:
|
With Lazy:
|
||||||
|
|
||||||
>lua
|
>lua
|
||||||
return {
|
return {
|
||||||
"harrisoncramer/gitlab.nvim",
|
"harrisoncramer/gitlab.nvim",
|
||||||
@@ -74,9 +76,7 @@ With Lazy:
|
|||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
<
|
<
|
||||||
|
|
||||||
And with Packer:
|
And with Packer:
|
||||||
|
|
||||||
>lua
|
>lua
|
||||||
use {
|
use {
|
||||||
'harrisoncramer/gitlab.nvim',
|
'harrisoncramer/gitlab.nvim',
|
||||||
@@ -94,7 +94,6 @@ And with Packer:
|
|||||||
}
|
}
|
||||||
<
|
<
|
||||||
|
|
||||||
|
|
||||||
CONNECTING TO GITLAB *gitlab.nvim.connecting-to-gitlab*
|
CONNECTING TO GITLAB *gitlab.nvim.connecting-to-gitlab*
|
||||||
|
|
||||||
This plugin requires an auth token to connect to Gitlab. The token can be set
|
This plugin requires an auth token to connect to Gitlab. The token can be set
|
||||||
@@ -106,19 +105,15 @@ Optionally provide a GITLAB_URL environment variable (or gitlab_url value in
|
|||||||
the `.gitlab.nvim` file) to connect to a self-hosted Gitlab instance. This is
|
the `.gitlab.nvim` file) to connect to a self-hosted Gitlab instance. This is
|
||||||
optional, use ONLY for self-hosted instances. Here’s what they’d look like
|
optional, use ONLY for self-hosted instances. Here’s what they’d look like
|
||||||
as environment variables:
|
as environment variables:
|
||||||
|
|
||||||
>bash
|
>bash
|
||||||
export GITLAB_TOKEN="your_gitlab_token"
|
export GITLAB_TOKEN="your_gitlab_token"
|
||||||
export GITLAB_URL="https://my-personal-gitlab-instance.com/"
|
export GITLAB_URL="https://my-personal-gitlab-instance.com/"
|
||||||
<
|
<
|
||||||
|
|
||||||
And as a `.gitlab.nvim` file:
|
And as a `.gitlab.nvim` file:
|
||||||
|
|
||||||
>
|
>
|
||||||
auth_token=your_gitlab_token
|
auth_token=your_gitlab_token
|
||||||
gitlab_url=https://my-personal-gitlab-instance.com/
|
gitlab_url=https://my-personal-gitlab-instance.com/
|
||||||
<
|
<
|
||||||
|
|
||||||
The plugin will look for the `.gitlab.nvim` file in the root of the current
|
The plugin will look for the `.gitlab.nvim` file in the root of the current
|
||||||
project by default. However, you may provide a custom path to the configuration
|
project by default. However, you may provide a custom path to the configuration
|
||||||
file via the `config_path` option. This must be an absolute path to the
|
file via the `config_path` option. This must be an absolute path to the
|
||||||
@@ -127,11 +122,11 @@ directory that holds your `.gitlab.nvim` file.
|
|||||||
The `connection_settings` block in the `state.lua` file will be used to
|
The `connection_settings` block in the `state.lua` file will be used to
|
||||||
configure your connection to Gitlab.
|
configure your connection to Gitlab.
|
||||||
|
|
||||||
|
|
||||||
CONFIGURING THE PLUGIN *gitlab.nvim.configuring-the-plugin*
|
CONFIGURING THE PLUGIN *gitlab.nvim.configuring-the-plugin*
|
||||||
|
|
||||||
Here is the default setup function. All of these values are optional, and if
|
Here is the default setup function. All of these values are optional, and if
|
||||||
you call this function with no values the defaults will be used:
|
you call this function with no values the defaults will be used:
|
||||||
|
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").setup({
|
require("gitlab").setup({
|
||||||
port = nil, -- The port of the Go server, which runs in the background, if omitted or `nil` the port will be chosen automatically
|
port = nil, -- The port of the Go server, which runs in the background, if omitted or `nil` the port will be chosen automatically
|
||||||
@@ -158,6 +153,7 @@ you call this function with no values the defaults will be used:
|
|||||||
pipeline = nil,
|
pipeline = nil,
|
||||||
reply = nil,
|
reply = nil,
|
||||||
squash_message = nil,
|
squash_message = nil,
|
||||||
|
temp_registers = {}, -- List of registers for backing up popup content (see `:h gitlab.nvim.temp-registers`)
|
||||||
},
|
},
|
||||||
discussion_tree = { -- The discussion tree that holds all comments
|
discussion_tree = { -- The discussion tree that holds all comments
|
||||||
auto_open = true, -- Automatically open when the reviewer is opened
|
auto_open = true, -- Automatically open when the reviewer is opened
|
||||||
@@ -198,22 +194,24 @@ you call this function with no values the defaults will be used:
|
|||||||
"conflicts",
|
"conflicts",
|
||||||
"assignees",
|
"assignees",
|
||||||
"reviewers",
|
"reviewers",
|
||||||
|
"pipeline",
|
||||||
"branch",
|
"branch",
|
||||||
"target_branch",
|
"target_branch",
|
||||||
"pipeline",
|
"delete_branch",
|
||||||
|
"squash",
|
||||||
"labels",
|
"labels",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
discussion_signs = {
|
discussion_signs = {
|
||||||
enabled = true, -- Show diagnostics for gitlab comments in the reviewer
|
enabled = true, -- Show diagnostics for gitlab comments in the reviewer
|
||||||
skip_resolved_discussion = false, -- Show diagnostics for resolved discussions
|
skip_resolved_discussion = false, -- Show diagnostics for resolved discussions
|
||||||
severity = vim.diagnostic.severity.INFO, -- ERROR, WARN, INFO, or HINT
|
severity = vim.diagnostic.severity.INFO, -- ERROR, WARN, INFO, or HINT
|
||||||
virtual_text = false, -- Whether to show the comment text inline as floating virtual text
|
virtual_text = false, -- Whether to show the comment text inline as floating virtual text
|
||||||
priority = 100, -- Higher will override LSP warnings, etc
|
priority = 100, -- Higher will override LSP warnings, etc
|
||||||
icons = {
|
icons = {
|
||||||
comment = "→|",
|
comment = "→|",
|
||||||
range = " |",
|
range = " |",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
pipeline = {
|
pipeline = {
|
||||||
created = "",
|
created = "",
|
||||||
@@ -226,13 +224,11 @@ you call this function with no values the defaults will be used:
|
|||||||
success = "✓",
|
success = "✓",
|
||||||
failed = "",
|
failed = "",
|
||||||
},
|
},
|
||||||
merge = { -- The default behaviors when merging an MR, see "Merging an MR"
|
|
||||||
squash = false,
|
|
||||||
delete_branch = false,
|
|
||||||
},
|
|
||||||
create_mr = {
|
create_mr = {
|
||||||
target = nil, -- Default branch to target when creating an MR
|
target = nil, -- Default branch to target when creating an MR
|
||||||
template_file = nil, -- Default MR template in .gitlab/merge_request_templates
|
template_file = nil, -- Default MR template in .gitlab/merge_request_templates
|
||||||
|
delete_branch = false, -- Whether the source branch will be marked for deletion
|
||||||
|
squash = false, -- Whether the commits will be marked for squashing
|
||||||
title_input = { -- Default settings for MR title input window
|
title_input = { -- Default settings for MR title input window
|
||||||
width = 40,
|
width = 40,
|
||||||
border = "rounded",
|
border = "rounded",
|
||||||
@@ -251,27 +247,22 @@ you call this function with no values the defaults will be used:
|
|||||||
})
|
})
|
||||||
<
|
<
|
||||||
|
|
||||||
|
|
||||||
USAGE *gitlab.nvim.usage*
|
USAGE *gitlab.nvim.usage*
|
||||||
|
|
||||||
First, check out the branch that you want to review locally.
|
First, check out the branch that you want to review locally:
|
||||||
|
|
||||||
>
|
>
|
||||||
git checkout feature-branch
|
git checkout feature-branch
|
||||||
<
|
<
|
||||||
|
|
||||||
Then open Neovim. To begin, try running the `summary` command or the `review`
|
Then open Neovim. To begin, try running the `summary` command or the `review`
|
||||||
command.
|
command.
|
||||||
|
|
||||||
|
|
||||||
THE SUMMARY VIEW *gitlab.nvim.the-summary-view*
|
THE SUMMARY VIEW *gitlab.nvim.the-summary-view*
|
||||||
|
|
||||||
The `summary` action will open the MR title and description.
|
The `summary` action will open the MR title and description:
|
||||||
|
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").summary()
|
require("gitlab").summary()
|
||||||
<
|
<
|
||||||
|
|
||||||
After editing the description or title, you may save your changes via the
|
After editing the description or title, you may save your changes via the
|
||||||
`settings.popup.perform_action` keybinding.
|
`settings.popup.perform_action` keybinding.
|
||||||
|
|
||||||
@@ -286,15 +277,13 @@ REVIEWING AN MR *gitlab.nvim.reviewing-an-mr*
|
|||||||
The `review` action will open a diff of the changes. You can leave comments
|
The `review` action will open a diff of the changes. You can leave comments
|
||||||
using the `create_comment` action. In visual mode, add multiline comments with
|
using the `create_comment` action. In visual mode, add multiline comments with
|
||||||
the `create_multiline_comment` command, and add suggested changes with the
|
the `create_multiline_comment` command, and add suggested changes with the
|
||||||
`create_comment_suggestion` command.
|
`create_comment_suggestion` command:
|
||||||
|
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").review()
|
require("gitlab").review()
|
||||||
require("gitlab").create_comment()
|
require("gitlab").create_comment()
|
||||||
require("gitlab").create_multiline_comment()
|
require("gitlab").create_multiline_comment()
|
||||||
require("gitlab").create_comment_suggestion()
|
require("gitlab").create_comment_suggestion()
|
||||||
<
|
<
|
||||||
|
|
||||||
For suggesting changes you can use `create_comment_suggestion` in visual mode
|
For suggesting changes you can use `create_comment_suggestion` in visual mode
|
||||||
which works similar to `create_multiline_comment` but prefills the comment
|
which works similar to `create_multiline_comment` but prefills the comment
|
||||||
window with Gitlab’s suggest changes
|
window with Gitlab’s suggest changes
|
||||||
@@ -303,13 +292,32 @@ code block with prefilled code from the visual selection.
|
|||||||
Just like the summary, all the different kinds of comments are saved via the
|
Just like the summary, all the different kinds of comments are saved via the
|
||||||
`settings.popup.perform_action` keybinding.
|
`settings.popup.perform_action` keybinding.
|
||||||
|
|
||||||
|
TEMPORARY REGISTERS *gitlab.nvim.temp-registers*
|
||||||
|
|
||||||
|
While writing a note/comment/suggestion/reply, you may need to interrupt the
|
||||||
|
work, do something else (e.g., read something in another file, etc.), and then
|
||||||
|
get back to your work on the comment. For occasions like this, you can set
|
||||||
|
`settings.popup.temp_registers` to a list of writable registers (see |registers|)
|
||||||
|
to which the contents of the popup window will be saved just before quitting.
|
||||||
|
|
||||||
|
A possible setting is, e.g., `settings.popup.backup_register = {'"', "+", "g"}`
|
||||||
|
which saves to the so called unnamed register (see |quotequote|), the system
|
||||||
|
clipboard register (see |quoteplus|), as well as to the "g" register. This lets
|
||||||
|
you easily paste the text back in with |p| or |P| (from the unnamed register),
|
||||||
|
or with `"gp` or `"gP` if the unnamed register gets overwritten with something
|
||||||
|
else. Using the clipboard register lets you easily use the text outside of
|
||||||
|
nvim.
|
||||||
|
|
||||||
|
NOTE: The `temp_registers` are also filled with the contents of the popup when
|
||||||
|
pressing the `settings.popup.perform_action` keybinding, even if the action
|
||||||
|
that was supposed to be performed fails.
|
||||||
|
|
||||||
DISCUSSIONS AND NOTES *gitlab.nvim.discussions-and-notes*
|
DISCUSSIONS AND NOTES *gitlab.nvim.discussions-and-notes*
|
||||||
|
|
||||||
Gitlab groups threads of comments together into "discussions."
|
Gitlab groups threads of comments together into "discussions."
|
||||||
|
|
||||||
To display all discussions for the current MR, use the `toggle_discussions`
|
To display all discussions for the current MR, use the `toggle_discussions`
|
||||||
action, which will show the discussions in a split window.
|
action, which will show the discussions in a split window:
|
||||||
|
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").toggle_discussions()
|
require("gitlab").toggle_discussions()
|
||||||
<
|
<
|
||||||
@@ -324,7 +332,6 @@ Within the discussion tree, you can delete/edit/reply to comments with the
|
|||||||
If you’d like to create a note in an MR (like a comment, but not linked to a
|
If you’d like to create a note in an MR (like a comment, but not linked to a
|
||||||
specific line) use the `create_note` action. The same keybindings for
|
specific line) use the `create_note` action. The same keybindings for
|
||||||
delete/edit/reply are available on the note tree.
|
delete/edit/reply are available on the note tree.
|
||||||
|
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").create_note()
|
require("gitlab").create_note()
|
||||||
<
|
<
|
||||||
@@ -339,7 +346,7 @@ $XDG_CONFIG_HOME/nvim/after/ftplugin/gitlab.lua with the following contents:
|
|||||||
vim.o.breakindent = true
|
vim.o.breakindent = true
|
||||||
<
|
<
|
||||||
|
|
||||||
LABELS *gitlab.nvim.labels*
|
LABELS *gitlab.nvim.labels*
|
||||||
|
|
||||||
You can add or remove labels from the current MR.
|
You can add or remove labels from the current MR.
|
||||||
>lua
|
>lua
|
||||||
@@ -349,6 +356,7 @@ You can add or remove labels from the current MR.
|
|||||||
These labels will be visible in the summary panel, as long as you provide the
|
These labels will be visible in the summary panel, as long as you provide the
|
||||||
"fields" string in your setup function under the `setting.info.fields` block.
|
"fields" string in your setup function under the `setting.info.fields` block.
|
||||||
|
|
||||||
|
|
||||||
SIGNS AND DIAGNOSTICS *gitlab.nvim.signs-and-diagnostics*
|
SIGNS AND DIAGNOSTICS *gitlab.nvim.signs-and-diagnostics*
|
||||||
|
|
||||||
By default when reviewing files, you will see diagnostics for comments that
|
By default when reviewing files, you will see diagnostics for comments that
|
||||||
@@ -376,7 +384,8 @@ You may skip resolved discussions by toggling `discussion_signs.skip_resolved_di
|
|||||||
in your setup function to true. By default, discussions from this plugin
|
in your setup function to true. By default, discussions from this plugin
|
||||||
are shown at the INFO severity level (see :h vim.diagnostic.severity).
|
are shown at the INFO severity level (see :h vim.diagnostic.severity).
|
||||||
|
|
||||||
EMOJIS *gitlab.nvim.emojis*
|
|
||||||
|
EMOJIS *gitlab.nvim.emojis*
|
||||||
|
|
||||||
You can add or remove emojis from a note or comment in the discussion tree.
|
You can add or remove emojis from a note or comment in the discussion tree.
|
||||||
|
|
||||||
@@ -401,42 +410,34 @@ Use the `settings.popup.perform_action` to send the changes to Gitlab.
|
|||||||
MR APPROVALS *gitlab.nvim.mr-approvals*
|
MR APPROVALS *gitlab.nvim.mr-approvals*
|
||||||
|
|
||||||
You can approve or revoke approval for an MR with the `approve` and `revoke`
|
You can approve or revoke approval for an MR with the `approve` and `revoke`
|
||||||
actions respectively.
|
actions respectively:
|
||||||
|
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").approve()
|
require("gitlab").approve()
|
||||||
require("gitlab").revoke()
|
require("gitlab").revoke()
|
||||||
<
|
<
|
||||||
|
|
||||||
|
|
||||||
MERGING AN MR *gitlab.nvim.merging-an-mr*
|
MERGING AN MR *gitlab.nvim.merging-an-mr*
|
||||||
|
|
||||||
The `merge` action will merge an MR. The MR must be in a "mergeable" state for
|
The `merge` action will merge an MR. The MR must be in a "mergeable" state for
|
||||||
this command to work.
|
this command to work.
|
||||||
|
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").merge()
|
require("gitlab").merge()
|
||||||
require("gitlab").merge({ squash = false, delete_branch = false })
|
require("gitlab").merge({ squash = false, delete_branch = false })
|
||||||
<
|
<
|
||||||
|
See |gitlab.nvim.merge| for more help on this function.
|
||||||
You can configure default behaviors via the setup function, values passed into
|
|
||||||
the `merge` action will override the defaults.
|
|
||||||
|
|
||||||
If you enable `squash` you will be prompted for a squash message. To use the
|
|
||||||
default message, leave the popup empty. Use the `settings.popup.perform_action`
|
|
||||||
to merge the MR with your message.
|
|
||||||
|
|
||||||
|
|
||||||
CREATING AN MR *gitlab.nvim.creating-an-mr*
|
CREATING AN MR *gitlab.nvim.creating-an-mr*
|
||||||
|
|
||||||
To create an MR for the current branch, make sure you have the branch checked
|
To create an MR for the current branch, make sure you have the branch checked
|
||||||
out. Then, use the `create_mr` action. See `:h gitlab.nvim.create_mr` for more
|
out. Then, use the `create_mr` action. See |gitlab.nvim.create_mr| for more
|
||||||
help on this function
|
help on this function
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").create_mr()
|
require("gitlab").create_mr()
|
||||||
require("gitlab").create_mr({ target = "main" })
|
require("gitlab").create_mr({ target = "main" })
|
||||||
require("gitlab").create_mr({ target = "main", template_file = "my-template.md" })
|
require("gitlab").create_mr({ template_file = "my-template.md", title = "Fix bug XYZ" })
|
||||||
<
|
<
|
||||||
|
|
||||||
PIPELINES *gitlab.nvim.pipelines*
|
PIPELINES *gitlab.nvim.pipelines*
|
||||||
|
|
||||||
You can view the status of the pipeline for the current MR with the `pipeline`
|
You can view the status of the pipeline for the current MR with the `pipeline`
|
||||||
@@ -449,22 +450,20 @@ To re-trigger failed jobs in the pipeline manually, use the
|
|||||||
new Neovim buffer, use your `settings.popup.perform_linewise_action`
|
new Neovim buffer, use your `settings.popup.perform_linewise_action`
|
||||||
keybinding.
|
keybinding.
|
||||||
|
|
||||||
|
|
||||||
REVIEWERS AND ASSIGNEES *gitlab.nvim.reviewers-and-assignees*
|
REVIEWERS AND ASSIGNEES *gitlab.nvim.reviewers-and-assignees*
|
||||||
|
|
||||||
The `add_reviewer` and `delete_reviewer` actions, as well as the `add_assignee`
|
The `add_reviewer` and `delete_reviewer` actions, as well as the `add_assignee`
|
||||||
and `delete_assignee` functions, will let you choose from a list of users who
|
and `delete_assignee` functions, will let you choose from a list of users who
|
||||||
are available in the current project:
|
are available in the current project:
|
||||||
|
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").add_reviewer()
|
require("gitlab").add_reviewer()
|
||||||
require("gitlab").delete_reviewer()
|
require("gitlab").delete_reviewer()
|
||||||
require("gitlab").add_assignee()
|
require("gitlab").add_assignee()
|
||||||
require("gitlab").delete_assignee()
|
require("gitlab").delete_assignee()
|
||||||
<
|
<
|
||||||
|
|
||||||
These actions use Neovim’s built in picker, which is much nicer if you
|
These actions use Neovim’s built in picker, which is much nicer if you
|
||||||
install dressing. If you use Dressing, please enable it:
|
install `dressing.nvim`. If you use Dressing, please enable it:
|
||||||
|
|
||||||
>lua
|
>lua
|
||||||
require("dressing").setup({
|
require("dressing").setup({
|
||||||
input = {
|
input = {
|
||||||
@@ -473,21 +472,18 @@ install dressing. If you use Dressing, please enable it:
|
|||||||
})
|
})
|
||||||
<
|
<
|
||||||
|
|
||||||
|
|
||||||
RESTARTING OR SHUTTING DOWN *gitlab.nvim.restarting-or-shutting-down*
|
RESTARTING OR SHUTTING DOWN *gitlab.nvim.restarting-or-shutting-down*
|
||||||
|
|
||||||
The `gitlab.nvim` server will shut down automatically when you exit Neovim.
|
The `gitlab.nvim` server will shut down automatically when you exit Neovim.
|
||||||
However, if you would like to manage this yourself (for instance, restart the
|
However, if you would like to manage this yourself (for instance, restart the
|
||||||
server when you check out a new branch) you may do so via the `restart`
|
server when you check out a new branch) you may do so via the `restart`
|
||||||
command, or `shutdown` commands, which both accept callbacks.
|
command, or `shutdown` commands, which both accept callbacks:
|
||||||
|
|
||||||
>lua
|
>lua
|
||||||
require("gitlab.server").restart()
|
require("gitlab.server").restart()
|
||||||
|
require("gitlab.server").shutdown()
|
||||||
<
|
<
|
||||||
|
|
||||||
For instance you could set up the following keybinding to close and reopen the
|
For instance you could set up the following keybinding to close and reopen the
|
||||||
reviewer when checking out a new branch:
|
reviewer when checking out a new branch:
|
||||||
|
|
||||||
>lua
|
>lua
|
||||||
local gitlab = require("gitlab")
|
local gitlab = require("gitlab")
|
||||||
vim.keymap.set("n", "glB", function ()
|
vim.keymap.set("n", "glB", function ()
|
||||||
@@ -498,14 +494,12 @@ reviewer when checking out a new branch:
|
|||||||
end)
|
end)
|
||||||
<
|
<
|
||||||
|
|
||||||
|
|
||||||
KEYBINDINGS *gitlab.nvim.keybindings*
|
KEYBINDINGS *gitlab.nvim.keybindings*
|
||||||
|
|
||||||
The plugin does not set up any keybindings outside of the special buffers it
|
The plugin does not set up any keybindings outside of the special buffers it
|
||||||
creates, you need to set them up yourself. Here’s what I’m using (note that
|
creates, you need to set them up yourself. Here’s what I’m using (note that
|
||||||
the `<leader>` prefix is not necessary, as `gl` does not have a special meaning
|
the `<leader>` prefix is not necessary, as `gl` does not have a special meaning
|
||||||
in normal mode):
|
in normal mode):
|
||||||
|
|
||||||
>lua
|
>lua
|
||||||
local gitlab = require("gitlab")
|
local gitlab = require("gitlab")
|
||||||
local gitlab_server = require("gitlab.server")
|
local gitlab_server = require("gitlab.server")
|
||||||
@@ -529,35 +523,35 @@ in normal mode):
|
|||||||
vim.keymap.set("n", "glM", gitlab.merge)
|
vim.keymap.set("n", "glM", gitlab.merge)
|
||||||
<
|
<
|
||||||
|
|
||||||
|
|
||||||
TROUBLESHOOTING *gitlab.nvim.troubleshooting*
|
TROUBLESHOOTING *gitlab.nvim.troubleshooting*
|
||||||
|
|
||||||
**To check that the current settings of the plugin are configured correctly,
|
To check that the current settings of the plugin are configured correctly,~
|
||||||
please run: :lua require("gitlab").print_settings()**
|
please run:~
|
||||||
|
>lua
|
||||||
|
require("gitlab").print_settings()
|
||||||
|
<
|
||||||
This plugin uses a Go server to reach out to Gitlab. It’s possible that
|
This plugin uses a Go server to reach out to Gitlab. It’s possible that
|
||||||
something is going wrong when starting that server or connecting with Gitlab.
|
something is going wrong when starting that server or connecting with Gitlab.
|
||||||
The Go server runs outside of Neovim, and can be interacted with directly in
|
The Go server runs outside of Neovim, and can be interacted with directly in
|
||||||
order to troubleshoot. To start the server, check out your feature branch and
|
order to troubleshoot. To start the server, check out your feature branch and
|
||||||
run these commands:
|
run these commands:
|
||||||
|
|
||||||
>lua
|
>lua
|
||||||
:lua require("gitlab.server").build(true)
|
require("gitlab.server").build(true)
|
||||||
:lua require("gitlab.server").start(function() print("Server started") end)
|
require("gitlab.server").start(function() print("Server started") end)
|
||||||
<
|
<
|
||||||
|
|
||||||
The easiest way to debug what’s going wrong is to turn on the `debug` options
|
The easiest way to debug what’s going wrong is to turn on the `debug` options
|
||||||
in your setup function. This will allow you to see requests leaving the Go
|
in your setup function. This will allow you to see requests leaving the Go
|
||||||
server, and the responses coming back from Gitlab. Once the server is running,
|
server, and the responses coming back from Gitlab. Once the server is running,
|
||||||
you can also interact with the Go server like any other process:
|
you can also interact with the Go server like any other process:
|
||||||
|
|
||||||
>
|
>
|
||||||
curl --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" localhost:21036/mr/info
|
curl --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" localhost:21036/mr/info
|
||||||
<
|
<
|
||||||
==============================================================================
|
==============================================================================
|
||||||
Lua API *gitlab.nvim.api*
|
LUA API *gitlab.nvim.api*
|
||||||
|
|
||||||
setup() *gitlab.nvim.setup*
|
*gitlab.nvim.setup*
|
||||||
|
setup() ~
|
||||||
|
|
||||||
Call this first to initialize the plugin. With no arguments, it will use the
|
Call this first to initialize the plugin. With no arguments, it will use the
|
||||||
default arguments outlined under "Configuring the Plugin".
|
default arguments outlined under "Configuring the Plugin".
|
||||||
@@ -567,15 +561,17 @@ default arguments outlined under "Configuring the Plugin".
|
|||||||
require("gitlab").setup({ port = 8392 })
|
require("gitlab").setup({ port = 8392 })
|
||||||
|
|
||||||
require("gitlab").setup({ discussion_tree = { blacklist = { "some_bot"} } })
|
require("gitlab").setup({ discussion_tree = { blacklist = { "some_bot"} } })
|
||||||
|
<
|
||||||
review() *gitlab.nvim.review*
|
*gitlab.nvim.review*
|
||||||
|
review() ~
|
||||||
|
|
||||||
Opens the reviewer pane. Can be used from anywhere within Neovim after the
|
Opens the reviewer pane. Can be used from anywhere within Neovim after the
|
||||||
plugin is loaded. If run twice, will open a second reviewer pane.
|
plugin is loaded. If run twice, will open a second reviewer pane.
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").review()
|
require("gitlab").review()
|
||||||
|
<
|
||||||
summary() *gitlab.nvim.summary*
|
*gitlab.nvim.summary*
|
||||||
|
summary() ~
|
||||||
|
|
||||||
Opens the summary window with information about the current MR, such as the
|
Opens the summary window with information about the current MR, such as the
|
||||||
description, the author, and the title. Can be configured via the `info` field
|
description, the author, and the title. Can be configured via the `info` field
|
||||||
@@ -586,31 +582,35 @@ in the setup call.
|
|||||||
The summary can be edited. Once you have made changes, send them to Gitlab via
|
The summary can be edited. Once you have made changes, send them to Gitlab via
|
||||||
the `settings.popup.perform_action` keybinding.
|
the `settings.popup.perform_action` keybinding.
|
||||||
|
|
||||||
approve() *gitlab.nvim.approve*
|
*gitlab.nvim.approve*
|
||||||
|
approve() ~
|
||||||
|
|
||||||
Approves the current MR. Will error if the current user does not have
|
Approves the current MR. Will error if the current user does not have
|
||||||
permission.
|
permission.
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").approve()
|
require("gitlab").approve()
|
||||||
|
<
|
||||||
gitlab.revoke() *gitlab.nvim.revoke*
|
*gitlab.nvim.revoke*
|
||||||
|
gitlab.revoke() ~
|
||||||
|
|
||||||
Revokes approval for the current MR. Will error if the current user does not
|
Revokes approval for the current MR. Will error if the current user does not
|
||||||
have permission or has not previously approved the MR.
|
have permission or has not previously approved the MR.
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").approve()
|
require("gitlab").approve()
|
||||||
|
<
|
||||||
gitlab.create_comment() *gitlab.nvim.create_comment*
|
*gitlab.nvim.create_comment*
|
||||||
|
gitlab.create_comment() ~
|
||||||
|
|
||||||
Opens a popup to create a comment on the current line. Must be called when focused on the
|
Opens a popup to create a comment on the current line. Must be called when focused on the
|
||||||
reviewer pane (see the gitlab.nvim.review command), otherwise it will error.
|
reviewer pane (see the gitlab.nvim.review command), otherwise it will error.
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").comment()
|
require("gitlab").comment()
|
||||||
|
|
||||||
After the comment is typed, submit it to Gitlab via the |settings.popup.perform_action|
|
After the comment is typed, submit it to Gitlab via the `settings.popup.perform_action`
|
||||||
keybinding, by default `<leader>l`
|
keybinding, by default `<leader>l`.
|
||||||
|
|
||||||
create_multiline_comment() *gitlab.nvim.create_multiline_comment*
|
*gitlab.nvim.create_multiline_comment*
|
||||||
|
create_multiline_comment() ~
|
||||||
|
|
||||||
Opens a popup to create a multi-line comment. May only be called in visual
|
Opens a popup to create a multi-line comment. May only be called in visual
|
||||||
mode, and will use the currently selected lines.
|
mode, and will use the currently selected lines.
|
||||||
@@ -620,7 +620,8 @@ mode, and will use the currently selected lines.
|
|||||||
After the comment is typed, submit it to Gitlab via the |settings.popup.perform_linewise_action|
|
After the comment is typed, submit it to Gitlab via the |settings.popup.perform_linewise_action|
|
||||||
keybinding, by default `<leader>l`.
|
keybinding, by default `<leader>l`.
|
||||||
|
|
||||||
create_comment_suggestion() *gitlab.nvim.create_comment_suggestion*
|
*gitlab.nvim.create_comment_suggestion*
|
||||||
|
create_comment_suggestion() ~
|
||||||
|
|
||||||
Opens a popup to create a comment suggestion (aka a comment that makes a committable
|
Opens a popup to create a comment suggestion (aka a comment that makes a committable
|
||||||
change suggestion to the currently selected lines).
|
change suggestion to the currently selected lines).
|
||||||
@@ -630,23 +631,38 @@ change suggestion to the currently selected lines).
|
|||||||
After the comment is typed, submit it to Gitlab via the |settings.popup.perform_linewise_action|
|
After the comment is typed, submit it to Gitlab via the |settings.popup.perform_linewise_action|
|
||||||
keybinding, by default |<leader>l|
|
keybinding, by default |<leader>l|
|
||||||
|
|
||||||
create_mr({opts}) *gitlab.nvim.create_mr*
|
*gitlab.nvim.create_mr*
|
||||||
|
create_mr({opts}) ~
|
||||||
|
|
||||||
Starts the process of creating an MR for the currently checked out branch.
|
Starts the process of creating an MR for the currently checked out branch.
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").create_mr()
|
require("gitlab").create_mr()
|
||||||
require("gitlab").create_mr({ target = "main" })
|
require("gitlab").create_mr({ target = "main" })
|
||||||
require("gitlab").create_mr({ target = "main", template_file = "my-template.md" })
|
require("gitlab").create_mr({ target = "main", template_file = "my-template.md" })
|
||||||
|
require("gitlab").create_mr({ title = "Fix bug XYZ", description = "Closes #123" })
|
||||||
|
<
|
||||||
|
Parameters: ~
|
||||||
|
• {opts}: (table|nil) Keyword arguments that can be used to skip
|
||||||
|
certain steps in the MR creation process. `target` and
|
||||||
|
`template_file` can also be configured via the `gitlab.setup()`
|
||||||
|
function in the `settings.create_mr` field. If any field is missing,
|
||||||
|
you will be prompted to select a value interactively:
|
||||||
|
• {target}: (string) Name of the target branch.
|
||||||
|
• {template_file}: (string) Name of file (relative to
|
||||||
|
`.gitlab/merge_request_templates`) that will be used for the MR
|
||||||
|
description. See also
|
||||||
|
<https://docs.gitlab.com/ee/user/project/description_templates.html>.
|
||||||
|
• {description}: (string) String used for the MR description.
|
||||||
|
Takes precedence over the {template_file}, if both options are
|
||||||
|
used.
|
||||||
|
• {title}: (string) MR title.
|
||||||
|
• {delete_branch}: (bool) If true, the source branch will be
|
||||||
|
marked for deletion.
|
||||||
|
• {squash}: (bool) If true, the commits will be marked for
|
||||||
|
squashing.
|
||||||
|
|
||||||
Parameters:
|
*gitlab.nvim.move_to_discussion_tree_from_diagnostic*
|
||||||
• {opts} Lua table that can be used to skip certain steps in the MR
|
gitlab.move_to_discussion_tree_from_diagnostic() ~
|
||||||
creation process. If `target` is provided, you will not be prompted for one.
|
|
||||||
If a template_file is provided, it will be used automatically. Must be
|
|
||||||
located in `.gitlab/merge_request_templates`
|
|
||||||
|
|
||||||
These values can also be configured via the `gitlab.setup` function
|
|
||||||
|
|
||||||
gitlab.move_to_discussion_tree_from_diagnostic() *gitlab.nvim.move_to_discussion_tree_from_diagnostic*
|
|
||||||
|
|
||||||
When hovering over a diagnostic in the reviewer pane, jumps to the relevant
|
When hovering over a diagnostic in the reviewer pane, jumps to the relevant
|
||||||
node in the discussion tree.
|
node in the discussion tree.
|
||||||
@@ -655,17 +671,19 @@ node in the discussion tree.
|
|||||||
|
|
||||||
If there are no diagnostics for the current line, shows a warning message.
|
If there are no diagnostics for the current line, shows a warning message.
|
||||||
|
|
||||||
gitlab.create_note() *gitlab.nvim.create_note*
|
*gitlab.nvim.create_note*
|
||||||
|
gitlab.create_note() ~
|
||||||
|
|
||||||
Opens a popup to create a note. Notes are like comments except they are not
|
Opens a popup to create a note. Notes are like comments except they are not
|
||||||
tied to specific changes in an MR.
|
tied to specific changes in an MR.
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").create_note()
|
require("gitlab").create_note()
|
||||||
|
|
||||||
After the comment is typed, submit it to Gitlab via the |settings.popup.perform_action|
|
After the comment is typed, submit it to Gitlab via the `settings.popup.perform_action`
|
||||||
keybinding, by default |<leader>l|
|
keybinding, by default |<leader>l|
|
||||||
|
|
||||||
gitlab.toggle_discussions() *gitlab.nvim.toggle_discussions*
|
*gitlab.nvim.toggle_discussions*
|
||||||
|
gitlab.toggle_discussions() ~
|
||||||
|
|
||||||
Toggles visibility of the discussion tree.
|
Toggles visibility of the discussion tree.
|
||||||
>lua
|
>lua
|
||||||
@@ -675,69 +693,95 @@ Once the discussion tree is open, a number of different keybindings are availabl
|
|||||||
for interacting with different discussions. Please see the `settings.discussion_tree`
|
for interacting with different discussions. Please see the `settings.discussion_tree`
|
||||||
section of the setup call for more information about different keybindings.
|
section of the setup call for more information about different keybindings.
|
||||||
|
|
||||||
gitlab.add_assignee() *gitlab.nvim.add_assignee*
|
*gitlab.nvim.add_assignee*
|
||||||
|
gitlab.add_assignee() ~
|
||||||
|
|
||||||
Opens up a select menu for choosing an assignee for the current merge request.
|
Opens up a select menu for choosing an assignee for the current merge request.
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").add_assignee()
|
require("gitlab").add_assignee()
|
||||||
|
<
|
||||||
gitlab.delete_assignee() *gitlab.nvim.delete_assignee*
|
*gitlab.nvim.delete_assignee*
|
||||||
|
gitlab.delete_assignee() ~
|
||||||
|
|
||||||
Opens up a select menu for removing an existing assignee for the current merge request.
|
Opens up a select menu for removing an existing assignee for the current merge request.
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").delete_assignee()
|
require("gitlab").delete_assignee()
|
||||||
|
<
|
||||||
gitlab.add_reviewer() *gitlab.nvim.add_reviewer*
|
*gitlab.nvim.add_reviewer*
|
||||||
|
gitlab.add_reviewer() ~
|
||||||
|
|
||||||
Opens up a select menu for adding a reviewer for the current merge request.
|
Opens up a select menu for adding a reviewer for the current merge request.
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").add_reviewer()
|
require("gitlab").add_reviewer()
|
||||||
|
<
|
||||||
gitlab.add_label() *gitlab.nvim.add_label*
|
*gitlab.nvim.add_label*
|
||||||
|
gitlab.add_label() ~
|
||||||
|
|
||||||
Opens up a select menu for adding a label to the current merge request.
|
Opens up a select menu for adding a label to the current merge request.
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").add_label()
|
require("gitlab").add_label()
|
||||||
|
<
|
||||||
gitlab.delete_label() *gitlab.nvim.delete_label*
|
*gitlab.nvim.delete_label*
|
||||||
|
gitlab.delete_label() ~
|
||||||
|
|
||||||
Opens up a select menu for removing an existing label from the current merge request.
|
Opens up a select menu for removing an existing label from the current merge request.
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").delete_label()
|
require("gitlab").delete_label()
|
||||||
|
<
|
||||||
gitlab.delete_reviewer() *gitlab.nvim.delete_reviewer*
|
*gitlab.nvim.delete_reviewer*
|
||||||
|
gitlab.delete_reviewer() ~
|
||||||
|
|
||||||
Opens up a select menu for removing an existing reviewer for the current merge request.
|
Opens up a select menu for removing an existing reviewer for the current merge request.
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").delete_reviewer()
|
require("gitlab").delete_reviewer()
|
||||||
|
<
|
||||||
gitlab.pipeline() *gitlab.nvim.pipeline*
|
*gitlab.nvim.pipeline*
|
||||||
|
gitlab.pipeline() ~
|
||||||
|
|
||||||
Opens up a popup with information about the pipeline for the current merge request.
|
Opens up a popup with information about the pipeline for the current merge request.
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").pipeline()
|
require("gitlab").pipeline()
|
||||||
|
<
|
||||||
To re-trigger failed jobs in the pipeline manually, use the `settings.popup.perform_action` keybinding.
|
To re-trigger failed jobs in the pipeline manually, use the `settings.popup.perform_action` keybinding.
|
||||||
To open the log trace of a job in a new Neovim buffer, use your `settings.popup.perform_linewise_action`
|
To open the log trace of a job in a new Neovim buffer, use your `settings.popup.perform_linewise_action`
|
||||||
keybinding.
|
keybinding.
|
||||||
|
|
||||||
gitlab.open_in_browser() *gitlab.nvim.open_in_browser*
|
*gitlab.nvim.open_in_browser*
|
||||||
|
gitlab.open_in_browser() ~
|
||||||
|
|
||||||
Opens the current MR in your default web browser.
|
Opens the current MR in your default web browser.
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").open_in_browser()
|
require("gitlab").open_in_browser()
|
||||||
|
<
|
||||||
|
*gitlab.nvim.merge*
|
||||||
|
gitlab.merge({opts}) ~
|
||||||
|
|
||||||
gitlab.merge() *gitlab.nvim.merge*
|
Merges the merge request into the target branch. When run without any
|
||||||
|
arguments, the `merge` action will respect the "Squash commits" and "Delete
|
||||||
Merges the merge request into the target branch
|
source branch" settings set by `require("gitlab").create_mr()` or set in
|
||||||
|
Gitlab online. You can see the current settings in the Summary view, see
|
||||||
|
|gitlab.nvim.the-summary-view|.
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").merge()
|
require("gitlab").merge()
|
||||||
|
require("gitlab").merge({ squash = false, delete_branch = true })
|
||||||
|
<
|
||||||
|
Parameters: ~
|
||||||
|
• {opts}: (table|nil) Keyword arguments that can be used to override
|
||||||
|
default behavior.
|
||||||
|
• {delete_branch}: (bool) If true, the source branch will be
|
||||||
|
deleted.
|
||||||
|
• {squash}: (bool) If true, the commits will be squashed. If
|
||||||
|
you enable {squash} you will be prompted for a squash
|
||||||
|
message. To use the default message, leave the popup empty.
|
||||||
|
Use the `settings.popup.perform_action` to merge the MR with
|
||||||
|
your message.
|
||||||
|
|
||||||
gitlab.data({ opts }, cb) *gitlab.nvim.data*
|
*gitlab.nvim.data*
|
||||||
|
gitlab.data({resources}, {cb}) ~
|
||||||
|
|
||||||
The data function can be used to integrate `gitlab.nvim` with other plugins and tooling, by fetching
|
The data function can be used to integrate `gitlab.nvim` with other plugins
|
||||||
raw data about the current MR, including the summary information (title, description, etc);
|
and tooling, by fetching raw data about the current MR, including the summary
|
||||||
reviewers, assignees, pipeline status.
|
information (title, description, etc); reviewers, assignees, pipeline status.
|
||||||
>lua
|
>lua
|
||||||
require("gitlab").data({
|
require("gitlab").data({
|
||||||
{ type = "info", refresh = false },
|
{ type = "info", refresh = false },
|
||||||
@@ -750,21 +794,24 @@ If the resources have not yet been fetched from Gitlab, this function will
|
|||||||
perform API calls for them. Once the data has been fetched, the callback will
|
perform API calls for them. Once the data has been fetched, the callback will
|
||||||
execute and passed the data as an argument.
|
execute and passed the data as an argument.
|
||||||
|
|
||||||
Parameters: ~
|
Parameters: ~
|
||||||
• {resources} (table) A list of resource blocks to fetch.
|
• {resources}: (table) A list of {resource} blocks to fetch.
|
||||||
• {resource} (table) A resource to fetch, such as job information, etc.
|
• {resource}: (table) A resource to fetch, such as job
|
||||||
• {resource.type}: (string) The type of resource, either: "user"
|
information, etc. The resource is defined by its {type}:
|
||||||
"labels", "project_members", "pipeline," or "revisions"." The types are:
|
• {type}: (string) The type of resource, either:
|
||||||
• {user}: Information about the currently authenticated user
|
• "user": Information about the currently authenticated
|
||||||
• {labels}: The labels available in the current project
|
user.
|
||||||
• {project_members}: The list of current project members
|
• "labels": The labels available in the current project.
|
||||||
• {revisions}: Revision information about the MR
|
• "project_members": The list of current project members.
|
||||||
• {pipeline}: Information about the current branch's pipeline. Returns
|
• "revisions": Revision information about the MR.
|
||||||
and object with `latest_pipeline` and `jobs` as fields.
|
• "pipeline": Information about the current branch's
|
||||||
• {resource.refresh}: (bool) Whether to re-fetch the data from Gitlab
|
pipeline. Returns and object with `latest_pipeline` and
|
||||||
or use the cached data locally, if available.
|
`jobs` as fields.
|
||||||
• {cb} (function) The callback function that runs after all of the
|
• {refresh}: (bool) Whether to re-fetch the data from Gitlab
|
||||||
resources have been fetched. Will be passed a table with the data,
|
or use the cached data locally, if available.
|
||||||
with each resource as a key-value pair, with the key being it's type.
|
• {cb}: (function) The callback function that runs after all of the
|
||||||
|
resources have been fetched. Will be passed a table with the data,
|
||||||
|
with each resource as a key-value pair, with the key being it's
|
||||||
|
type.
|
||||||
|
|
||||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
vim:tw=78:ts=4:sw=4:expandtab:ft=help:norl:
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ M.create_comment = function()
|
|||||||
comment_popup:mount()
|
comment_popup:mount()
|
||||||
state.set_popup_keymaps(comment_popup, function(text)
|
state.set_popup_keymaps(comment_popup, function(text)
|
||||||
M.confirm_create_comment(text)
|
M.confirm_create_comment(text)
|
||||||
end, miscellaneous.attach_file)
|
end, miscellaneous.attach_file, miscellaneous.editable_popup_opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
---Create multiline comment for the last selection.
|
---Create multiline comment for the last selection.
|
||||||
@@ -48,7 +48,7 @@ M.create_multiline_comment = function()
|
|||||||
comment_popup:mount()
|
comment_popup:mount()
|
||||||
state.set_popup_keymaps(comment_popup, function(text)
|
state.set_popup_keymaps(comment_popup, function(text)
|
||||||
M.confirm_create_comment(text, { start_line = start_line, end_line = end_line })
|
M.confirm_create_comment(text, { start_line = start_line, end_line = end_line })
|
||||||
end, miscellaneous.attach_file)
|
end, miscellaneous.attach_file, miscellaneous.editable_popup_opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
---Create comment prepopulated with gitlab suggestion
|
---Create comment prepopulated with gitlab suggestion
|
||||||
@@ -95,7 +95,7 @@ M.create_comment_suggestion = function()
|
|||||||
else
|
else
|
||||||
M.confirm_create_comment(text, nil)
|
M.confirm_create_comment(text, nil)
|
||||||
end
|
end
|
||||||
end, miscellaneous.attach_file)
|
end, miscellaneous.attach_file, miscellaneous.editable_popup_opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
M.create_note = function()
|
M.create_note = function()
|
||||||
@@ -103,7 +103,7 @@ M.create_note = function()
|
|||||||
note_popup:mount()
|
note_popup:mount()
|
||||||
state.set_popup_keymaps(note_popup, function(text)
|
state.set_popup_keymaps(note_popup, function(text)
|
||||||
M.confirm_create_comment(text, nil, true)
|
M.confirm_create_comment(text, nil, true)
|
||||||
end, miscellaneous.attach_file)
|
end, miscellaneous.attach_file, miscellaneous.editable_popup_opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
---This function (settings.popup.perform_action) will send the comment to the Go server
|
---This function (settings.popup.perform_action) will send the comment to the Go server
|
||||||
|
|||||||
@@ -13,10 +13,9 @@ local miscellaneous = require("gitlab.actions.miscellaneous")
|
|||||||
---@field target? string
|
---@field target? string
|
||||||
---@field title? string
|
---@field title? string
|
||||||
---@field description? string
|
---@field description? string
|
||||||
|
|
||||||
---@class Args
|
|
||||||
---@field target? string
|
|
||||||
---@field template_file? string
|
---@field template_file? string
|
||||||
|
---@field delete_branch boolean?
|
||||||
|
---@field squash boolean?
|
||||||
|
|
||||||
local M = {
|
local M = {
|
||||||
started = false,
|
started = false,
|
||||||
@@ -39,49 +38,9 @@ M.reset_state = function()
|
|||||||
M.mr.description = ""
|
M.mr.description = ""
|
||||||
end
|
end
|
||||||
|
|
||||||
local title_popup_settings = {
|
|
||||||
buf_options = {
|
|
||||||
filetype = "markdown",
|
|
||||||
},
|
|
||||||
focusable = true,
|
|
||||||
border = {
|
|
||||||
style = "rounded",
|
|
||||||
text = {
|
|
||||||
top = "Title",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
local target_popup_settings = {
|
|
||||||
buf_options = {
|
|
||||||
filetype = "markdown",
|
|
||||||
},
|
|
||||||
focusable = true,
|
|
||||||
border = {
|
|
||||||
style = "rounded",
|
|
||||||
text = {
|
|
||||||
top = "Target branch",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
local description_popup_settings = {
|
|
||||||
buf_options = {
|
|
||||||
filetype = "markdown",
|
|
||||||
},
|
|
||||||
enter = true,
|
|
||||||
focusable = true,
|
|
||||||
border = {
|
|
||||||
style = "rounded",
|
|
||||||
text = {
|
|
||||||
top = "Description",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
---1. If the user has already begun writing an MR, prompt them to
|
---1. If the user has already begun writing an MR, prompt them to
|
||||||
--- continue working on it.
|
--- continue working on it.
|
||||||
---@param args? Args
|
---@param args? Mr
|
||||||
M.start = function(args)
|
M.start = function(args)
|
||||||
if M.started then
|
if M.started then
|
||||||
vim.ui.select({ "Yes", "No" }, { prompt = "Continue your previous MR?" }, function(choice)
|
vim.ui.select({ "Yes", "No" }, { prompt = "Continue your previous MR?" }, function(choice)
|
||||||
@@ -99,18 +58,19 @@ M.start = function(args)
|
|||||||
end
|
end
|
||||||
|
|
||||||
---2. Pick the target branch
|
---2. Pick the target branch
|
||||||
---@param args? Args
|
---@param mr? Mr
|
||||||
M.pick_target = function(args)
|
M.pick_target = function(mr)
|
||||||
if not args then
|
if not mr then
|
||||||
args = {}
|
mr = {}
|
||||||
end
|
end
|
||||||
if args.target ~= nil then
|
if mr.target ~= nil then
|
||||||
M.pick_template({ target = args.target }, args)
|
M.pick_template(mr)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if state.settings.create_mr.target ~= nil then
|
if state.settings.create_mr.target ~= nil then
|
||||||
M.pick_template({ target = state.settings.create_mr.target }, args)
|
mr.target = state.settings.create_mr.target
|
||||||
|
M.pick_template(mr)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -119,7 +79,8 @@ M.pick_target = function(args)
|
|||||||
prompt = "Choose target branch for merge",
|
prompt = "Choose target branch for merge",
|
||||||
}, function(choice)
|
}, function(choice)
|
||||||
if choice then
|
if choice then
|
||||||
M.pick_template({ target = choice }, args)
|
mr.target = choice
|
||||||
|
M.pick_template(mr)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@@ -137,22 +98,22 @@ end
|
|||||||
|
|
||||||
---3. Pick template (if applicable). This is used as the description
|
---3. Pick template (if applicable). This is used as the description
|
||||||
---@param mr Mr
|
---@param mr Mr
|
||||||
---@param args Args
|
M.pick_template = function(mr)
|
||||||
M.pick_template = function(mr, args)
|
if mr.description ~= nil then
|
||||||
if not args then
|
M.add_title(mr)
|
||||||
args = {}
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local template_file = args.template_file or state.settings.create_mr.template_file
|
local template_file = mr.template_file or state.settings.create_mr.template_file
|
||||||
if template_file ~= nil then
|
if template_file ~= nil then
|
||||||
local description = u.read_file(make_template_path(template_file))
|
mr.description = u.read_file(make_template_path(template_file))
|
||||||
M.add_title({ target = mr.target, description = description })
|
M.add_title(mr)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local all_templates = u.list_files_in_folder(".gitlab" .. state.settings.file_separator .. "merge_request_templates")
|
local all_templates = u.list_files_in_folder(".gitlab" .. state.settings.file_separator .. "merge_request_templates")
|
||||||
if all_templates == nil then
|
if all_templates == nil then
|
||||||
M.add_title({ target = mr.target })
|
M.add_title(mr)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -163,18 +124,21 @@ M.pick_template = function(mr, args)
|
|||||||
vim.ui.select(opts, {
|
vim.ui.select(opts, {
|
||||||
prompt = "Choose Template",
|
prompt = "Choose Template",
|
||||||
}, function(choice)
|
}, function(choice)
|
||||||
if choice then
|
if choice and choice ~= "Blank Template" then
|
||||||
local description = u.read_file(make_template_path(choice))
|
mr.description = u.read_file(make_template_path(choice))
|
||||||
M.add_title({ target = mr.target, description = description })
|
|
||||||
elseif choice == "Blank Template" then
|
|
||||||
M.add_title({ target = mr.target })
|
|
||||||
end
|
end
|
||||||
|
M.add_title(mr)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
---4. Prompts the user for the title of the MR
|
---4. Prompts the user for the title of the MR
|
||||||
---@param mr Mr
|
---@param mr Mr
|
||||||
M.add_title = function(mr)
|
M.add_title = function(mr)
|
||||||
|
if mr.title ~= nil then
|
||||||
|
M.open_confirmation_popup(mr)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local input = Input({
|
local input = Input({
|
||||||
position = "50%",
|
position = "50%",
|
||||||
relative = "editor",
|
relative = "editor",
|
||||||
@@ -200,8 +164,8 @@ M.add_title = function(mr)
|
|||||||
end
|
end
|
||||||
|
|
||||||
---5. Show the final popup.
|
---5. Show the final popup.
|
||||||
---The function will render a popup containing the MR title and MR description, and
|
---The function will render a popup containing the MR title and MR description,
|
||||||
---target branch. The title and description are editable.
|
---target branch, and the "delete_branch" and "squash" options. All fields are editable.
|
||||||
---@param mr Mr
|
---@param mr Mr
|
||||||
M.open_confirmation_popup = function(mr)
|
M.open_confirmation_popup = function(mr)
|
||||||
M.started = true
|
M.started = true
|
||||||
@@ -211,7 +175,7 @@ M.open_confirmation_popup = function(mr)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local layout, title_popup, description_popup, target_popup = M.create_layout()
|
local layout, title_popup, description_popup, target_popup, delete_branch_popup, squash_popup = M.create_layout()
|
||||||
|
|
||||||
M.layout = layout
|
M.layout = layout
|
||||||
M.layout_buf = layout.bufnr
|
M.layout_buf = layout.bufnr
|
||||||
@@ -220,22 +184,30 @@ M.open_confirmation_popup = function(mr)
|
|||||||
local function exit()
|
local function exit()
|
||||||
local title = vim.fn.trim(u.get_buffer_text(M.title_bufnr))
|
local title = vim.fn.trim(u.get_buffer_text(M.title_bufnr))
|
||||||
local description = u.get_buffer_text(M.description_bufnr)
|
local description = u.get_buffer_text(M.description_bufnr)
|
||||||
local target = vim.fn.trim(u.get_buffer_text(target_popup.bufnr))
|
local target = vim.fn.trim(u.get_buffer_text(M.target_bufnr))
|
||||||
|
local delete_branch = u.string_to_bool(u.get_buffer_text(M.delete_branch_bufnr))
|
||||||
|
local squash = u.string_to_bool(u.get_buffer_text(M.squash_bufnr))
|
||||||
M.mr = {
|
M.mr = {
|
||||||
title = title,
|
title = title,
|
||||||
description = description,
|
description = description,
|
||||||
target = target,
|
target = target,
|
||||||
|
delete_branch = delete_branch,
|
||||||
|
squash = squash,
|
||||||
}
|
}
|
||||||
layout:unmount()
|
layout:unmount()
|
||||||
M.layout_visible = false
|
M.layout_visible = false
|
||||||
end
|
end
|
||||||
|
|
||||||
local description_lines = mr.description and M.build_description_lines(mr.description) or { "" }
|
local description_lines = mr.description and M.build_description_lines(mr.description) or { "" }
|
||||||
|
local delete_branch = u.get_first_non_nil_value({ mr.delete_branch, state.settings.create_mr.delete_branch })
|
||||||
|
local squash = u.get_first_non_nil_value({ mr.squash, state.settings.create_mr.squash })
|
||||||
|
|
||||||
vim.schedule(function()
|
vim.schedule(function()
|
||||||
vim.api.nvim_buf_set_lines(description_popup.bufnr, 0, -1, false, description_lines)
|
vim.api.nvim_buf_set_lines(M.description_bufnr, 0, -1, false, description_lines)
|
||||||
vim.api.nvim_buf_set_lines(title_popup.bufnr, 0, -1, false, { mr.title })
|
vim.api.nvim_buf_set_lines(M.title_bufnr, 0, -1, false, { mr.title })
|
||||||
vim.api.nvim_buf_set_lines(target_popup.bufnr, 0, -1, false, { mr.target })
|
vim.api.nvim_buf_set_lines(M.target_bufnr, 0, -1, false, { mr.target })
|
||||||
|
vim.api.nvim_buf_set_lines(M.delete_branch_bufnr, 0, -1, false, { u.bool_to_string(delete_branch) })
|
||||||
|
vim.api.nvim_buf_set_lines(M.squash_bufnr, 0, -1, false, { u.bool_to_string(squash) })
|
||||||
|
|
||||||
local popup_opts = {
|
local popup_opts = {
|
||||||
cb = exit,
|
cb = exit,
|
||||||
@@ -246,8 +218,10 @@ M.open_confirmation_popup = function(mr)
|
|||||||
state.set_popup_keymaps(description_popup, M.create_mr, miscellaneous.attach_file, popup_opts)
|
state.set_popup_keymaps(description_popup, M.create_mr, miscellaneous.attach_file, popup_opts)
|
||||||
state.set_popup_keymaps(title_popup, M.create_mr, nil, popup_opts)
|
state.set_popup_keymaps(title_popup, M.create_mr, nil, popup_opts)
|
||||||
state.set_popup_keymaps(target_popup, M.create_mr, nil, popup_opts)
|
state.set_popup_keymaps(target_popup, M.create_mr, nil, popup_opts)
|
||||||
|
state.set_popup_keymaps(delete_branch_popup, M.create_mr, nil, popup_opts)
|
||||||
|
state.set_popup_keymaps(squash_popup, M.create_mr, nil, popup_opts)
|
||||||
|
|
||||||
vim.api.nvim_set_current_buf(description_popup.bufnr)
|
vim.api.nvim_set_current_buf(M.description_bufnr)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -268,11 +242,15 @@ M.create_mr = function()
|
|||||||
local description = u.get_buffer_text(M.description_bufnr)
|
local description = u.get_buffer_text(M.description_bufnr)
|
||||||
local title = u.get_buffer_text(M.title_bufnr):gsub("\n", " ")
|
local title = u.get_buffer_text(M.title_bufnr):gsub("\n", " ")
|
||||||
local target = u.get_buffer_text(M.target_bufnr):gsub("\n", " ")
|
local target = u.get_buffer_text(M.target_bufnr):gsub("\n", " ")
|
||||||
|
local delete_branch = u.string_to_bool(u.get_buffer_text(M.delete_branch_bufnr))
|
||||||
|
local squash = u.string_to_bool(u.get_buffer_text(M.squash_bufnr))
|
||||||
|
|
||||||
local body = {
|
local body = {
|
||||||
title = title,
|
title = title,
|
||||||
description = description,
|
description = description,
|
||||||
target_branch = target,
|
target_branch = target,
|
||||||
|
delete_branch = delete_branch,
|
||||||
|
squash = squash,
|
||||||
}
|
}
|
||||||
|
|
||||||
job.run_job("/create_mr", "POST", body, function(data)
|
job.run_job("/create_mr", "POST", body, function(data)
|
||||||
@@ -284,20 +262,30 @@ M.create_mr = function()
|
|||||||
end
|
end
|
||||||
|
|
||||||
M.create_layout = function()
|
M.create_layout = function()
|
||||||
local title_popup = Popup(title_popup_settings)
|
local title_popup = Popup(u.create_box_popup_state("Title", false))
|
||||||
M.title_bufnr = title_popup.bufnr
|
M.title_bufnr = title_popup.bufnr
|
||||||
local description_popup = Popup(description_popup_settings)
|
local description_popup = Popup(u.create_box_popup_state("Description", true))
|
||||||
M.description_bufnr = description_popup.bufnr
|
M.description_bufnr = description_popup.bufnr
|
||||||
local target_branch_popup = Popup(target_popup_settings)
|
local target_branch_popup = Popup(u.create_box_popup_state("Target branch", false))
|
||||||
M.target_bufnr = target_branch_popup.bufnr
|
M.target_bufnr = target_branch_popup.bufnr
|
||||||
|
local delete_title = vim.o.columns > 110 and "Delete source branch" or "Delete source"
|
||||||
|
local delete_branch_popup = Popup(u.create_box_popup_state(delete_title, false))
|
||||||
|
M.delete_branch_bufnr = delete_branch_popup.bufnr
|
||||||
|
local squash_title = vim.o.columns > 110 and "Squash commits" or "Squash"
|
||||||
|
local squash_popup = Popup(u.create_box_popup_state(squash_title, false))
|
||||||
|
M.squash_bufnr = squash_popup.bufnr
|
||||||
|
|
||||||
local internal_layout
|
local internal_layout
|
||||||
internal_layout = Layout.Box({
|
internal_layout = Layout.Box({
|
||||||
Layout.Box({
|
Layout.Box({
|
||||||
Layout.Box(title_popup, { grow = 1 }),
|
Layout.Box(title_popup, { grow = 1 }),
|
||||||
Layout.Box(target_branch_popup, { grow = 1 }),
|
|
||||||
}, { size = 3 }),
|
}, { size = 3 }),
|
||||||
Layout.Box(description_popup, { grow = 1 }),
|
Layout.Box(description_popup, { grow = 1 }),
|
||||||
|
Layout.Box({
|
||||||
|
Layout.Box(delete_branch_popup, { size = { width = #delete_title + 4 } }),
|
||||||
|
Layout.Box(squash_popup, { size = { width = #squash_title + 4 } }),
|
||||||
|
Layout.Box(target_branch_popup, { grow = 1 }),
|
||||||
|
}, { size = 3 }),
|
||||||
}, { dir = "col" })
|
}, { dir = "col" })
|
||||||
|
|
||||||
local layout = Layout({
|
local layout = Layout({
|
||||||
@@ -311,7 +299,7 @@ M.create_layout = function()
|
|||||||
|
|
||||||
layout:mount()
|
layout:mount()
|
||||||
|
|
||||||
return layout, title_popup, description_popup, target_branch_popup
|
return layout, title_popup, description_popup, target_branch_popup, delete_branch_popup, squash_popup
|
||||||
end
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|||||||
@@ -256,7 +256,12 @@ M.reply = function(tree)
|
|||||||
local discussion_node = M.get_root_node(tree, node)
|
local discussion_node = M.get_root_node(tree, node)
|
||||||
local id = tostring(discussion_node.id)
|
local id = tostring(discussion_node.id)
|
||||||
reply_popup:mount()
|
reply_popup:mount()
|
||||||
state.set_popup_keymaps(reply_popup, M.send_reply(tree, id), miscellaneous.attach_file)
|
state.set_popup_keymaps(
|
||||||
|
reply_popup,
|
||||||
|
M.send_reply(tree, id),
|
||||||
|
miscellaneous.attach_file,
|
||||||
|
miscellaneous.editable_popup_opts
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- This function will send the reply to the Go API
|
-- This function will send the reply to the Go API
|
||||||
@@ -331,7 +336,9 @@ M.edit_comment = function(tree, unlinked)
|
|||||||
vim.api.nvim_buf_set_lines(currentBuffer, 0, -1, false, lines)
|
vim.api.nvim_buf_set_lines(currentBuffer, 0, -1, false, lines)
|
||||||
state.set_popup_keymaps(
|
state.set_popup_keymaps(
|
||||||
edit_popup,
|
edit_popup,
|
||||||
M.send_edits(tostring(root_node.id), tonumber(note_node.root_note_id or note_node.id), unlinked)
|
M.send_edits(tostring(root_node.id), tonumber(note_node.root_note_id or note_node.id), unlinked),
|
||||||
|
nil,
|
||||||
|
miscellaneous.editable_popup_opts
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ local Popup = require("nui.popup")
|
|||||||
local state = require("gitlab.state")
|
local state = require("gitlab.state")
|
||||||
local job = require("gitlab.job")
|
local job = require("gitlab.job")
|
||||||
local reviewer = require("gitlab.reviewer")
|
local reviewer = require("gitlab.reviewer")
|
||||||
|
local miscellaneous = require("gitlab.actions.miscellaneous")
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
@@ -17,7 +18,7 @@ end
|
|||||||
|
|
||||||
---@param opts MergeOpts
|
---@param opts MergeOpts
|
||||||
M.merge = function(opts)
|
M.merge = function(opts)
|
||||||
local merge_body = { squash = state.settings.merge.squash, delete_branch = state.settings.merge.delete_branch }
|
local merge_body = { squash = state.INFO.squash, delete_branch = state.INFO.delete_branch }
|
||||||
if opts then
|
if opts then
|
||||||
merge_body.squash = opts.squash ~= nil and opts.squash
|
merge_body.squash = opts.squash ~= nil and opts.squash
|
||||||
merge_body.delete_branch = opts.delete_branch ~= nil and opts.delete_branch
|
merge_body.delete_branch = opts.delete_branch ~= nil and opts.delete_branch
|
||||||
@@ -33,7 +34,7 @@ M.merge = function(opts)
|
|||||||
squash_message_popup:mount()
|
squash_message_popup:mount()
|
||||||
state.set_popup_keymaps(squash_message_popup, function(text)
|
state.set_popup_keymaps(squash_message_popup, function(text)
|
||||||
M.confirm_merge(merge_body, text)
|
M.confirm_merge(merge_body, text)
|
||||||
end)
|
end, nil, miscellaneous.editable_popup_opts)
|
||||||
else
|
else
|
||||||
M.confirm_merge(merge_body)
|
M.confirm_merge(merge_body)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -34,4 +34,8 @@ M.attach_file = function()
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
M.editable_popup_opts = {
|
||||||
|
save_to_temp_register = true,
|
||||||
|
}
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|||||||
@@ -17,43 +17,6 @@ local M = {
|
|||||||
description_bufnr = nil,
|
description_bufnr = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
local title_popup_settings = {
|
|
||||||
buf_options = {
|
|
||||||
filetype = "markdown",
|
|
||||||
},
|
|
||||||
focusable = true,
|
|
||||||
border = {
|
|
||||||
style = "rounded",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
local details_popup_settings = {
|
|
||||||
buf_options = {
|
|
||||||
filetype = "markdown",
|
|
||||||
},
|
|
||||||
focusable = true,
|
|
||||||
border = {
|
|
||||||
style = "rounded",
|
|
||||||
text = {
|
|
||||||
top = "Details",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
local description_popup_settings = {
|
|
||||||
buf_options = {
|
|
||||||
filetype = "markdown",
|
|
||||||
},
|
|
||||||
enter = true,
|
|
||||||
focusable = true,
|
|
||||||
border = {
|
|
||||||
style = "rounded",
|
|
||||||
text = {
|
|
||||||
top = "Description",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
-- The function will render a popup containing the MR title and MR description, and optionally,
|
-- The function will render a popup containing the MR title and MR description, and optionally,
|
||||||
-- any additional metadata that the user wants. The title and description are editable and
|
-- any additional metadata that the user wants. The title and description are editable and
|
||||||
-- can be changed via the local action keybinding, which also closes the popup
|
-- can be changed via the local action keybinding, which also closes the popup
|
||||||
@@ -66,7 +29,7 @@ M.summary = function()
|
|||||||
|
|
||||||
local title = state.INFO.title
|
local title = state.INFO.title
|
||||||
local description_lines = M.build_description_lines()
|
local description_lines = M.build_description_lines()
|
||||||
local info_lines = state.settings.info.enabled and M.build_info_lines() or nil
|
local info_lines = state.settings.info.enabled and M.build_info_lines() or { "" }
|
||||||
|
|
||||||
local layout, title_popup, description_popup, info_popup = M.create_layout(info_lines)
|
local layout, title_popup, description_popup, info_popup = M.create_layout(info_lines)
|
||||||
|
|
||||||
@@ -89,7 +52,7 @@ M.summary = function()
|
|||||||
vim.api.nvim_set_option_value("readonly", false, { buf = info_popup.bufnr })
|
vim.api.nvim_set_option_value("readonly", false, { buf = info_popup.bufnr })
|
||||||
end
|
end
|
||||||
|
|
||||||
M.color_labels(info_popup.bufnr) -- Color labels in details popup
|
M.color_details(info_popup.bufnr) -- Color values in details popup
|
||||||
|
|
||||||
state.set_popup_keymaps(
|
state.set_popup_keymaps(
|
||||||
description_popup,
|
description_popup,
|
||||||
@@ -134,7 +97,9 @@ M.build_info_lines = function()
|
|||||||
reviewers = { title = "Reviewers", content = u.make_readable_list(info.reviewers, "name") },
|
reviewers = { title = "Reviewers", content = u.make_readable_list(info.reviewers, "name") },
|
||||||
branch = { title = "Branch", content = info.source_branch },
|
branch = { title = "Branch", content = info.source_branch },
|
||||||
labels = { title = "Labels", content = table.concat(info.labels, ", ") },
|
labels = { title = "Labels", content = table.concat(info.labels, ", ") },
|
||||||
target_branch = { title = "Target Branch", content = state.INFO.target_branch },
|
target_branch = { title = "Target Branch", content = info.target_branch },
|
||||||
|
delete_branch = { title = "Delete Source Branch", content = (info.force_remove_source_branch and "Yes" or "No") },
|
||||||
|
squash = { title = "Squash Commits", content = (info.squash and "Yes" or "No") },
|
||||||
pipeline = {
|
pipeline = {
|
||||||
title = "Pipeline Status",
|
title = "Pipeline Status",
|
||||||
content = function()
|
content = function()
|
||||||
@@ -196,15 +161,15 @@ M.edit_summary = function()
|
|||||||
end
|
end
|
||||||
|
|
||||||
M.create_layout = function(info_lines)
|
M.create_layout = function(info_lines)
|
||||||
local title_popup = Popup(title_popup_settings)
|
local title_popup = Popup(u.create_box_popup_state(nil, false))
|
||||||
M.title_bufnr = title_popup.bufnr
|
M.title_bufnr = title_popup.bufnr
|
||||||
local description_popup = Popup(description_popup_settings)
|
local description_popup = Popup(u.create_box_popup_state("Description", true))
|
||||||
M.description_bufnr = description_popup.bufnr
|
M.description_bufnr = description_popup.bufnr
|
||||||
local details_popup
|
local details_popup
|
||||||
|
|
||||||
local internal_layout
|
local internal_layout
|
||||||
if state.settings.info.enabled then
|
if state.settings.info.enabled then
|
||||||
details_popup = Popup(details_popup_settings)
|
details_popup = Popup(u.create_box_popup_state("Details", false))
|
||||||
if state.settings.info.horizontal then
|
if state.settings.info.horizontal then
|
||||||
local longest_line = u.get_longest_string(info_lines)
|
local longest_line = u.get_longest_string(info_lines)
|
||||||
internal_layout = Layout.Box({
|
internal_layout = Layout.Box({
|
||||||
@@ -241,8 +206,8 @@ M.create_layout = function(info_lines)
|
|||||||
return layout, title_popup, description_popup, details_popup
|
return layout, title_popup, description_popup, details_popup
|
||||||
end
|
end
|
||||||
|
|
||||||
M.color_labels = function(bufnr)
|
M.color_details = function(bufnr)
|
||||||
local label_namespace = vim.api.nvim_create_namespace("Labels")
|
local details_namespace = vim.api.nvim_create_namespace("Details")
|
||||||
for i, v in ipairs(state.settings.info.fields) do
|
for i, v in ipairs(state.settings.info.fields) do
|
||||||
if v == "labels" then
|
if v == "labels" then
|
||||||
local line_content = u.get_line_content(bufnr, i)
|
local line_content = u.get_line_content(bufnr, i)
|
||||||
@@ -251,9 +216,16 @@ M.color_labels = function(bufnr)
|
|||||||
if start_idx ~= nil and end_idx ~= nil then
|
if start_idx ~= nil and end_idx ~= nil then
|
||||||
vim.cmd("highlight " .. "label" .. j .. " guifg=white")
|
vim.cmd("highlight " .. "label" .. j .. " guifg=white")
|
||||||
vim.api.nvim_set_hl(0, ("label" .. j), { fg = label.Color })
|
vim.api.nvim_set_hl(0, ("label" .. j), { fg = label.Color })
|
||||||
vim.api.nvim_buf_add_highlight(bufnr, label_namespace, ("label" .. j), i - 1, start_idx - 1, end_idx)
|
vim.api.nvim_buf_add_highlight(bufnr, details_namespace, ("label" .. j), i - 1, start_idx - 1, end_idx)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
elseif v == "delete_branch" or v == "squash" or v == "draft" or v == "conflicts" then
|
||||||
|
local line_content = u.get_line_content(bufnr, i)
|
||||||
|
local start_idx, end_idx = line_content:find("%S-$")
|
||||||
|
if start_idx ~= nil and end_idx ~= nil then
|
||||||
|
vim.api.nvim_set_hl(0, "boolean", { link = "Constant" })
|
||||||
|
vim.api.nvim_buf_add_highlight(bufnr, details_namespace, "boolean", i - 1, start_idx - 1, end_idx)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -85,9 +85,14 @@ M.init_popup = function(tree, bufnr)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local cursor_pos = vim.api.nvim_win_get_cursor(0)
|
local cursor_pos = vim.api.nvim_win_get_cursor(0)
|
||||||
|
-- "zyiw on the next line erases the unnamed register. This may interfere with the
|
||||||
|
-- `temp_registers` used for backing up editable popup contents, so let's backup the unnamed
|
||||||
|
-- register.
|
||||||
|
local unnamed_register_contents = vim.fn.getreg('"')
|
||||||
vim.api.nvim_command('normal! "zyiw')
|
vim.api.nvim_command('normal! "zyiw')
|
||||||
vim.api.nvim_win_set_cursor(0, cursor_pos)
|
vim.api.nvim_win_set_cursor(0, cursor_pos)
|
||||||
local word = vim.fn.getreg("z")
|
local word = vim.fn.getreg("z")
|
||||||
|
vim.fn.setreg('"', unnamed_register_contents) -- restore the unnamed register
|
||||||
|
|
||||||
for k, v in pairs(M.emoji_map) do
|
for k, v in pairs(M.emoji_map) do
|
||||||
if v.moji == word then
|
if v.moji == word then
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ M.settings = {
|
|||||||
help = nil,
|
help = nil,
|
||||||
pipeline = nil,
|
pipeline = nil,
|
||||||
squash_message = nil,
|
squash_message = nil,
|
||||||
|
temp_registers = {},
|
||||||
},
|
},
|
||||||
discussion_tree = {
|
discussion_tree = {
|
||||||
auto_open = true,
|
auto_open = true,
|
||||||
@@ -85,13 +86,11 @@ M.settings = {
|
|||||||
return " " .. discussions_content .. " %#Comment#| " .. notes_content .. help
|
return " " .. discussions_content .. " %#Comment#| " .. notes_content .. help
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
merge = {
|
|
||||||
squash = false,
|
|
||||||
delete_branch = false,
|
|
||||||
},
|
|
||||||
create_mr = {
|
create_mr = {
|
||||||
target = nil,
|
target = nil,
|
||||||
template_file = nil,
|
template_file = nil,
|
||||||
|
delete_branch = false,
|
||||||
|
squash = false,
|
||||||
title_input = {
|
title_input = {
|
||||||
width = 40,
|
width = 40,
|
||||||
border = "rounded",
|
border = "rounded",
|
||||||
@@ -112,6 +111,8 @@ M.settings = {
|
|||||||
"pipeline",
|
"pipeline",
|
||||||
"branch",
|
"branch",
|
||||||
"target_branch",
|
"target_branch",
|
||||||
|
"delete_branch",
|
||||||
|
"squash",
|
||||||
"labels",
|
"labels",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -296,9 +297,15 @@ M.set_popup_keymaps = function(popup, action, linewise_action, opts)
|
|||||||
end, { buffer = popup.bufnr, desc = "Perform linewise action" })
|
end, { buffer = popup.bufnr, desc = "Perform linewise action" })
|
||||||
end
|
end
|
||||||
|
|
||||||
vim.api.nvim_create_autocmd("BufUnload", {
|
vim.api.nvim_create_autocmd("BufWinLeave", {
|
||||||
buffer = popup.bufnr,
|
buffer = popup.bufnr,
|
||||||
callback = function()
|
callback = function()
|
||||||
|
if opts.save_to_temp_register then
|
||||||
|
local text = u.get_buffer_text(popup.bufnr)
|
||||||
|
for _, register in ipairs(M.settings.popup.temp_registers) do
|
||||||
|
vim.fn.setreg(register, text)
|
||||||
|
end
|
||||||
|
end
|
||||||
exit(popup, opts)
|
exit(popup, opts)
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -29,6 +29,17 @@ M.get_last_word = function(sentence, divider)
|
|||||||
return words[#words] or ""
|
return words[#words] or ""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---Return the first non-nil value in the input table, or nil
|
||||||
|
---@param values table The list of input values
|
||||||
|
---@return any
|
||||||
|
M.get_first_non_nil_value = function(values)
|
||||||
|
for _, val in pairs(values) do
|
||||||
|
if val ~= nil then
|
||||||
|
return val
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
---Returns whether a string ends with a substring
|
---Returns whether a string ends with a substring
|
||||||
---@param str string
|
---@param str string
|
||||||
---@param ending string
|
---@param ending string
|
||||||
@@ -336,6 +347,30 @@ M.get_buffer_text = function(bufnr)
|
|||||||
return text
|
return text
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---Convert string to corresponding boolean
|
||||||
|
---@param str string
|
||||||
|
---@return boolean
|
||||||
|
M.string_to_bool = function(str)
|
||||||
|
str = vim.fn.trim(str)
|
||||||
|
if str == "true" or str == "True" or str == "TRUE" then
|
||||||
|
return true
|
||||||
|
elseif str == "false" or str == "False" or str == "FALSE" then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
M.notify("Not a valid boolean value `" .. str .. "`. Defaulting to `false`", vim.log.levels.WARN)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
---Convert boolean to corresponding string
|
||||||
|
---@param bool boolean
|
||||||
|
---@return string
|
||||||
|
M.bool_to_string = function(bool)
|
||||||
|
if bool == true then
|
||||||
|
return "true"
|
||||||
|
end
|
||||||
|
return "false"
|
||||||
|
end
|
||||||
|
|
||||||
M.string_starts = function(str, start)
|
M.string_starts = function(str, start)
|
||||||
return str:sub(1, #start) == start
|
return str:sub(1, #start) == start
|
||||||
end
|
end
|
||||||
@@ -431,6 +466,27 @@ M.create_popup_state = function(title, settings, width, height, zindex)
|
|||||||
return view_opts
|
return view_opts
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---Create view_opts for Box popups used inside popup Layouts
|
||||||
|
---@param title string The string to appear on top of the popup
|
||||||
|
---@param enter boolean Whether the pop should be focused after creation
|
||||||
|
---@return table
|
||||||
|
M.create_box_popup_state = function(title, enter)
|
||||||
|
local settings = require("gitlab.state").settings.popup
|
||||||
|
return {
|
||||||
|
buf_options = {
|
||||||
|
filetype = "markdown",
|
||||||
|
},
|
||||||
|
enter = enter or false,
|
||||||
|
focusable = true,
|
||||||
|
border = {
|
||||||
|
style = settings.border,
|
||||||
|
text = {
|
||||||
|
top = title,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
M.read_file = function(file_path, opts)
|
M.read_file = function(file_path, opts)
|
||||||
local file = io.open(file_path, "r")
|
local file = io.open(file_path, "r")
|
||||||
if file == nil then
|
if file == nil then
|
||||||
|
|||||||
Reference in New Issue
Block a user