1
0
mirror of https://github.com/taigrr/wtf synced 2025-01-18 04:03:14 -08:00

go mod vendor update

Signed-off-by: Chris Cummer <chriscummer@me.com>
This commit is contained in:
Chris Cummer 2019-12-14 08:52:34 -08:00
parent 703619bf0a
commit 3d4059de02
665 changed files with 104373 additions and 59789 deletions

View File

@ -227,9 +227,6 @@ func InternalIP() (string, error) { return defaultClient.InternalIP() }
// ExternalIP returns the instance's primary external (public) IP address.
func ExternalIP() (string, error) { return defaultClient.ExternalIP() }
// Email calls Client.Email on the default client.
func Email(serviceAccount string) (string, error) { return defaultClient.Email(serviceAccount) }
// Hostname returns the instance's hostname. This will be of the form
// "<instanceID>.c.<projID>.internal".
func Hostname() (string, error) { return defaultClient.Hostname() }
@ -370,16 +367,6 @@ func (c *Client) InternalIP() (string, error) {
return c.getTrimmed("instance/network-interfaces/0/ip")
}
// Email returns the email address associated with the service account.
// The account may be empty or the string "default" to use the instance's
// main account.
func (c *Client) Email(serviceAccount string) (string, error) {
if serviceAccount == "" {
serviceAccount = "default"
}
return c.getTrimmed("instance/service-accounts/" + serviceAccount + "/email")
}
// ExternalIP returns the instance's primary external (public) IP address.
func (c *Client) ExternalIP() (string, error) {
return c.getTrimmed("instance/network-interfaces/0/access-configs/0/external-ip")

View File

@ -18,11 +18,15 @@ const (
MEGABYTE
GIGABYTE
TERABYTE
PETABYTE
EXABYTE
)
var invalidByteQuantityError = errors.New("byte quantity must be a positive integer with a unit of measurement like M, MB, MiB, G, GiB, or GB")
// ByteSize returns a human-readable byte string of the form 10M, 12.5K, and so forth. The following units are available:
// E: Exabyte
// P: Petabyte
// T: Terabyte
// G: Gigabyte
// M: Megabyte
@ -34,6 +38,12 @@ func ByteSize(bytes uint64) string {
value := float64(bytes)
switch {
case bytes >= EXABYTE:
unit = "E"
value = value / EXABYTE
case bytes >= PETABYTE:
unit = "P"
value = value / PETABYTE
case bytes >= TERABYTE:
unit = "T"
value = value / TERABYTE
@ -49,7 +59,7 @@ func ByteSize(bytes uint64) string {
case bytes >= BYTE:
unit = "B"
case bytes == 0:
return "0"
return "0B"
}
result := strconv.FormatFloat(value, 'f', 1, 64)
@ -72,6 +82,8 @@ func ToMegabytes(s string) (uint64, error) {
// MB = M = MiB = 1024 * K
// GB = G = GiB = 1024 * M
// TB = T = TiB = 1024 * G
// PB = P = PiB = 1024 * T
// EB = E = EiB = 1024 * P
func ToBytes(s string) (uint64, error) {
s = strings.TrimSpace(s)
s = strings.ToUpper(s)
@ -84,11 +96,15 @@ func ToBytes(s string) (uint64, error) {
bytesString, multiple := s[:i], s[i:]
bytes, err := strconv.ParseFloat(bytesString, 64)
if err != nil || bytes <= 0 {
if err != nil || bytes < 0 {
return 0, invalidByteQuantityError
}
switch multiple {
case "E", "EB", "EIB":
return uint64(bytes * EXABYTE), nil
case "P", "PB", "PIB":
return uint64(bytes * PETABYTE), nil
case "T", "TB", "TIB":
return uint64(bytes * TERABYTE), nil
case "G", "GB", "GIB":

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1454,7 +1454,7 @@ type GitPullRequestCompletionOptions struct {
MergeCommitMessage *string `json:"mergeCommitMessage,omitempty"`
// Specify the strategy used to merge the pull request during completion. If MergeStrategy is not set to any value, a no-FF merge will be created if SquashMerge == false. If MergeStrategy is not set to any value, the pull request commits will be squash if SquashMerge == true. The SquashMerge member is deprecated. It is recommended that you explicitly set MergeStrategy in all cases. If an explicit value is provided for MergeStrategy, the SquashMerge member will be ignored.
MergeStrategy *GitPullRequestMergeStrategy `json:"mergeStrategy,omitempty"`
// SquashMerge is deprecated. You should explicity set the value of MergeStrategy. If MergeStrategy is set to any value, the SquashMerge value will be ignored. If MergeStrategy is not set, the merge strategy will be no-fast-forward if this flag is false, or squash if true.
// SquashMerge is deprecated. You should explicitly set the value of MergeStrategy. If MergeStrategy is set to any value, the SquashMerge value will be ignored. If MergeStrategy is not set, the merge strategy will be no-fast-forward if this flag is false, or squash if true.
SquashMerge *bool `json:"squashMerge,omitempty"`
// If true, we will attempt to transition any work items linked to the pull request into the next logical state (i.e. Active -> Resolved)
TransitionWorkItems *bool `json:"transitionWorkItems,omitempty"`
@ -2162,7 +2162,7 @@ type GitTemplate struct {
type GitTreeDiff struct {
// ObjectId of the base tree of this diff.
BaseTreeId *string `json:"baseTreeId,omitempty"`
// List of tree entries that differ between the base and target tree. Renames and object type changes are returned as a delete for the old object and add for the new object. If a continuation token is returned in the response header, some tree entries are yet to be processed and may yeild more diff entries. If the continuation token is not returned all the diff entries have been included in this response.
// List of tree entries that differ between the base and target tree. Renames and object type changes are returned as a delete for the old object and add for the new object. If a continuation token is returned in the response header, some tree entries are yet to be processed and may yield more diff entries. If the continuation token is not returned all the diff entries have been included in this response.
DiffEntries *[]GitTreeDiffEntry `json:"diffEntries,omitempty"`
// ObjectId of the target tree of this diff.
TargetTreeId *string `json:"targetTreeId,omitempty"`
@ -2518,7 +2518,7 @@ var PullRequestStatusValues = pullRequestStatusValuesType{
Abandoned: "abandoned",
// Pull request is completed.
Completed: "completed",
// Used in pull request search criterias to include all statuses.
// Used in pull request search criteria to include all statuses.
All: "all",
}

File diff suppressed because it is too large Load Diff

View File

@ -16,19 +16,24 @@ import (
"net/url"
)
type Client struct {
type Client interface {
// Gets an operation from the the operationId using the given pluginId.
GetOperation(context.Context, GetOperationArgs) (*Operation, error)
}
type ClientImpl struct {
Client azuredevops.Client
}
func NewClient(ctx context.Context, connection *azuredevops.Connection) *Client {
func NewClient(ctx context.Context, connection *azuredevops.Connection) Client {
client := connection.GetClientByUrl(connection.BaseUrl)
return &Client{
return &ClientImpl{
Client: *client,
}
}
// Gets an operation from the the operationId using the given pluginId.
func (client *Client) GetOperation(ctx context.Context, args GetOperationArgs) (*Operation, error) {
func (client *ClientImpl) GetOperation(ctx context.Context, args GetOperationArgs) (*Operation, error) {
routeValues := make(map[string]string)
if args.OperationId == nil {
return nil, &azuredevops.ArgumentNilError{ArgumentName: "args.OperationId"}

View File

@ -21,22 +21,49 @@ import (
var ResourceAreaId, _ = uuid.Parse("fb13a388-40dd-4a04-b530-013a739c72ef")
type Client struct {
type Client interface {
// Create a policy configuration of a given policy type.
CreatePolicyConfiguration(context.Context, CreatePolicyConfigurationArgs) (*PolicyConfiguration, error)
// Delete a policy configuration by its ID.
DeletePolicyConfiguration(context.Context, DeletePolicyConfigurationArgs) error
// Get a policy configuration by its ID.
GetPolicyConfiguration(context.Context, GetPolicyConfigurationArgs) (*PolicyConfiguration, error)
// Retrieve a specific revision of a given policy by ID.
GetPolicyConfigurationRevision(context.Context, GetPolicyConfigurationRevisionArgs) (*PolicyConfiguration, error)
// Retrieve all revisions for a given policy.
GetPolicyConfigurationRevisions(context.Context, GetPolicyConfigurationRevisionsArgs) (*[]PolicyConfiguration, error)
// Get a list of policy configurations in a project.
GetPolicyConfigurations(context.Context, GetPolicyConfigurationsArgs) (*GetPolicyConfigurationsResponseValue, error)
// [Preview API] Gets the present evaluation state of a policy.
GetPolicyEvaluation(context.Context, GetPolicyEvaluationArgs) (*PolicyEvaluationRecord, error)
// [Preview API] Retrieves a list of all the policy evaluation statuses for a specific pull request.
GetPolicyEvaluations(context.Context, GetPolicyEvaluationsArgs) (*[]PolicyEvaluationRecord, error)
// Retrieve a specific policy type by ID.
GetPolicyType(context.Context, GetPolicyTypeArgs) (*PolicyType, error)
// Retrieve all available policy types.
GetPolicyTypes(context.Context, GetPolicyTypesArgs) (*[]PolicyType, error)
// [Preview API] Requeue the policy evaluation.
RequeuePolicyEvaluation(context.Context, RequeuePolicyEvaluationArgs) (*PolicyEvaluationRecord, error)
// Update a policy configuration by its ID.
UpdatePolicyConfiguration(context.Context, UpdatePolicyConfigurationArgs) (*PolicyConfiguration, error)
}
type ClientImpl struct {
Client azuredevops.Client
}
func NewClient(ctx context.Context, connection *azuredevops.Connection) (*Client, error) {
func NewClient(ctx context.Context, connection *azuredevops.Connection) (Client, error) {
client, err := connection.GetClientByResourceAreaId(ctx, ResourceAreaId)
if err != nil {
return nil, err
}
return &Client{
return &ClientImpl{
Client: *client,
}, nil
}
// Create a policy configuration of a given policy type.
func (client *Client) CreatePolicyConfiguration(ctx context.Context, args CreatePolicyConfigurationArgs) (*PolicyConfiguration, error) {
func (client *ClientImpl) CreatePolicyConfiguration(ctx context.Context, args CreatePolicyConfigurationArgs) (*PolicyConfiguration, error) {
if args.Configuration == nil {
return nil, &azuredevops.ArgumentNilError{ArgumentName: "args.Configuration"}
}
@ -75,7 +102,7 @@ type CreatePolicyConfigurationArgs struct {
}
// Delete a policy configuration by its ID.
func (client *Client) DeletePolicyConfiguration(ctx context.Context, args DeletePolicyConfigurationArgs) error {
func (client *ClientImpl) DeletePolicyConfiguration(ctx context.Context, args DeletePolicyConfigurationArgs) error {
routeValues := make(map[string]string)
if args.Project == nil || *args.Project == "" {
return &azuredevops.ArgumentNilOrEmptyError{ArgumentName: "args.Project"}
@ -104,7 +131,7 @@ type DeletePolicyConfigurationArgs struct {
}
// Get a policy configuration by its ID.
func (client *Client) GetPolicyConfiguration(ctx context.Context, args GetPolicyConfigurationArgs) (*PolicyConfiguration, error) {
func (client *ClientImpl) GetPolicyConfiguration(ctx context.Context, args GetPolicyConfigurationArgs) (*PolicyConfiguration, error) {
routeValues := make(map[string]string)
if args.Project == nil || *args.Project == "" {
return nil, &azuredevops.ArgumentNilOrEmptyError{ArgumentName: "args.Project"}
@ -134,8 +161,87 @@ type GetPolicyConfigurationArgs struct {
ConfigurationId *int
}
// Retrieve a specific revision of a given policy by ID.
func (client *ClientImpl) GetPolicyConfigurationRevision(ctx context.Context, args GetPolicyConfigurationRevisionArgs) (*PolicyConfiguration, error) {
routeValues := make(map[string]string)
if args.Project == nil || *args.Project == "" {
return nil, &azuredevops.ArgumentNilOrEmptyError{ArgumentName: "args.Project"}
}
routeValues["project"] = *args.Project
if args.ConfigurationId == nil {
return nil, &azuredevops.ArgumentNilError{ArgumentName: "args.ConfigurationId"}
}
routeValues["configurationId"] = strconv.Itoa(*args.ConfigurationId)
if args.RevisionId == nil {
return nil, &azuredevops.ArgumentNilError{ArgumentName: "args.RevisionId"}
}
routeValues["revisionId"] = strconv.Itoa(*args.RevisionId)
locationId, _ := uuid.Parse("fe1e68a2-60d3-43cb-855b-85e41ae97c95")
resp, err := client.Client.Send(ctx, http.MethodGet, locationId, "5.1", routeValues, nil, nil, "", "application/json", nil)
if err != nil {
return nil, err
}
var responseValue PolicyConfiguration
err = client.Client.UnmarshalBody(resp, &responseValue)
return &responseValue, err
}
// Arguments for the GetPolicyConfigurationRevision function
type GetPolicyConfigurationRevisionArgs struct {
// (required) Project ID or project name
Project *string
// (required) The policy configuration ID.
ConfigurationId *int
// (required) The revision ID.
RevisionId *int
}
// Retrieve all revisions for a given policy.
func (client *ClientImpl) GetPolicyConfigurationRevisions(ctx context.Context, args GetPolicyConfigurationRevisionsArgs) (*[]PolicyConfiguration, error) {
routeValues := make(map[string]string)
if args.Project == nil || *args.Project == "" {
return nil, &azuredevops.ArgumentNilOrEmptyError{ArgumentName: "args.Project"}
}
routeValues["project"] = *args.Project
if args.ConfigurationId == nil {
return nil, &azuredevops.ArgumentNilError{ArgumentName: "args.ConfigurationId"}
}
routeValues["configurationId"] = strconv.Itoa(*args.ConfigurationId)
queryParams := url.Values{}
if args.Top != nil {
queryParams.Add("$top", strconv.Itoa(*args.Top))
}
if args.Skip != nil {
queryParams.Add("$skip", strconv.Itoa(*args.Skip))
}
locationId, _ := uuid.Parse("fe1e68a2-60d3-43cb-855b-85e41ae97c95")
resp, err := client.Client.Send(ctx, http.MethodGet, locationId, "5.1", routeValues, queryParams, nil, "", "application/json", nil)
if err != nil {
return nil, err
}
var responseValue []PolicyConfiguration
err = client.Client.UnmarshalCollectionBody(resp, &responseValue)
return &responseValue, err
}
// Arguments for the GetPolicyConfigurationRevisions function
type GetPolicyConfigurationRevisionsArgs struct {
// (required) Project ID or project name
Project *string
// (required) The policy configuration ID.
ConfigurationId *int
// (optional) The number of revisions to retrieve.
Top *int
// (optional) The number of revisions to ignore. For example, to retrieve results 101-150, set top to 50 and skip to 100.
Skip *int
}
// Get a list of policy configurations in a project.
func (client *Client) GetPolicyConfigurations(ctx context.Context, args GetPolicyConfigurationsArgs) (*GetPolicyConfigurationsResponseValue, error) {
func (client *ClientImpl) GetPolicyConfigurations(ctx context.Context, args GetPolicyConfigurationsArgs) (*GetPolicyConfigurationsResponseValue, error) {
routeValues := make(map[string]string)
if args.Project == nil || *args.Project == "" {
return nil, &azuredevops.ArgumentNilOrEmptyError{ArgumentName: "args.Project"}
@ -146,6 +252,12 @@ func (client *Client) GetPolicyConfigurations(ctx context.Context, args GetPolic
if args.Scope != nil {
queryParams.Add("scope", *args.Scope)
}
if args.Top != nil {
queryParams.Add("$top", strconv.Itoa(*args.Top))
}
if args.ContinuationToken != nil {
queryParams.Add("continuationToken", *args.ContinuationToken)
}
if args.PolicyType != nil {
queryParams.Add("policyType", (*args.PolicyType).String())
}
@ -167,6 +279,10 @@ type GetPolicyConfigurationsArgs struct {
Project *string
// (optional) [Provided for legacy reasons] The scope on which a subset of policies is defined.
Scope *string
// (optional) Maximum number of policies to return.
Top *int
// (optional) The continuation token used for pagination.
ContinuationToken *string
// (optional) Filter returned policies to only this type
PolicyType *uuid.UUID
}
@ -178,48 +294,8 @@ type GetPolicyConfigurationsResponseValue struct {
ContinuationToken string
}
// Update a policy configuration by its ID.
func (client *Client) UpdatePolicyConfiguration(ctx context.Context, args UpdatePolicyConfigurationArgs) (*PolicyConfiguration, error) {
if args.Configuration == nil {
return nil, &azuredevops.ArgumentNilError{ArgumentName: "args.Configuration"}
}
routeValues := make(map[string]string)
if args.Project == nil || *args.Project == "" {
return nil, &azuredevops.ArgumentNilOrEmptyError{ArgumentName: "args.Project"}
}
routeValues["project"] = *args.Project
if args.ConfigurationId == nil {
return nil, &azuredevops.ArgumentNilError{ArgumentName: "args.ConfigurationId"}
}
routeValues["configurationId"] = strconv.Itoa(*args.ConfigurationId)
body, marshalErr := json.Marshal(*args.Configuration)
if marshalErr != nil {
return nil, marshalErr
}
locationId, _ := uuid.Parse("dad91cbe-d183-45f8-9c6e-9c1164472121")
resp, err := client.Client.Send(ctx, http.MethodPut, locationId, "5.1", routeValues, nil, bytes.NewReader(body), "application/json", "application/json", nil)
if err != nil {
return nil, err
}
var responseValue PolicyConfiguration
err = client.Client.UnmarshalBody(resp, &responseValue)
return &responseValue, err
}
// Arguments for the UpdatePolicyConfiguration function
type UpdatePolicyConfigurationArgs struct {
// (required) The policy configuration to update.
Configuration *PolicyConfiguration
// (required) Project ID or project name
Project *string
// (required) ID of the existing policy configuration to be updated.
ConfigurationId *int
}
// [Preview API] Gets the present evaluation state of a policy.
func (client *Client) GetPolicyEvaluation(ctx context.Context, args GetPolicyEvaluationArgs) (*PolicyEvaluationRecord, error) {
func (client *ClientImpl) GetPolicyEvaluation(ctx context.Context, args GetPolicyEvaluationArgs) (*PolicyEvaluationRecord, error) {
routeValues := make(map[string]string)
if args.Project == nil || *args.Project == "" {
return nil, &azuredevops.ArgumentNilOrEmptyError{ArgumentName: "args.Project"}
@ -249,39 +325,8 @@ type GetPolicyEvaluationArgs struct {
EvaluationId *uuid.UUID
}
// [Preview API] Requeue the policy evaluation.
func (client *Client) RequeuePolicyEvaluation(ctx context.Context, args RequeuePolicyEvaluationArgs) (*PolicyEvaluationRecord, error) {
routeValues := make(map[string]string)
if args.Project == nil || *args.Project == "" {
return nil, &azuredevops.ArgumentNilOrEmptyError{ArgumentName: "args.Project"}
}
routeValues["project"] = *args.Project
if args.EvaluationId == nil {
return nil, &azuredevops.ArgumentNilError{ArgumentName: "args.EvaluationId"}
}
routeValues["evaluationId"] = (*args.EvaluationId).String()
locationId, _ := uuid.Parse("46aecb7a-5d2c-4647-897b-0209505a9fe4")
resp, err := client.Client.Send(ctx, http.MethodPatch, locationId, "5.1-preview.1", routeValues, nil, nil, "", "application/json", nil)
if err != nil {
return nil, err
}
var responseValue PolicyEvaluationRecord
err = client.Client.UnmarshalBody(resp, &responseValue)
return &responseValue, err
}
// Arguments for the RequeuePolicyEvaluation function
type RequeuePolicyEvaluationArgs struct {
// (required) Project ID or project name
Project *string
// (required) ID of the policy evaluation to be retrieved.
EvaluationId *uuid.UUID
}
// [Preview API] Retrieves a list of all the policy evaluation statuses for a specific pull request.
func (client *Client) GetPolicyEvaluations(ctx context.Context, args GetPolicyEvaluationsArgs) (*[]PolicyEvaluationRecord, error) {
func (client *ClientImpl) GetPolicyEvaluations(ctx context.Context, args GetPolicyEvaluationsArgs) (*[]PolicyEvaluationRecord, error) {
routeValues := make(map[string]string)
if args.Project == nil || *args.Project == "" {
return nil, &azuredevops.ArgumentNilOrEmptyError{ArgumentName: "args.Project"}
@ -327,87 +372,8 @@ type GetPolicyEvaluationsArgs struct {
Skip *int
}
// Retrieve a specific revision of a given policy by ID.
func (client *Client) GetPolicyConfigurationRevision(ctx context.Context, args GetPolicyConfigurationRevisionArgs) (*PolicyConfiguration, error) {
routeValues := make(map[string]string)
if args.Project == nil || *args.Project == "" {
return nil, &azuredevops.ArgumentNilOrEmptyError{ArgumentName: "args.Project"}
}
routeValues["project"] = *args.Project
if args.ConfigurationId == nil {
return nil, &azuredevops.ArgumentNilError{ArgumentName: "args.ConfigurationId"}
}
routeValues["configurationId"] = strconv.Itoa(*args.ConfigurationId)
if args.RevisionId == nil {
return nil, &azuredevops.ArgumentNilError{ArgumentName: "args.RevisionId"}
}
routeValues["revisionId"] = strconv.Itoa(*args.RevisionId)
locationId, _ := uuid.Parse("fe1e68a2-60d3-43cb-855b-85e41ae97c95")
resp, err := client.Client.Send(ctx, http.MethodGet, locationId, "5.1", routeValues, nil, nil, "", "application/json", nil)
if err != nil {
return nil, err
}
var responseValue PolicyConfiguration
err = client.Client.UnmarshalBody(resp, &responseValue)
return &responseValue, err
}
// Arguments for the GetPolicyConfigurationRevision function
type GetPolicyConfigurationRevisionArgs struct {
// (required) Project ID or project name
Project *string
// (required) The policy configuration ID.
ConfigurationId *int
// (required) The revision ID.
RevisionId *int
}
// Retrieve all revisions for a given policy.
func (client *Client) GetPolicyConfigurationRevisions(ctx context.Context, args GetPolicyConfigurationRevisionsArgs) (*[]PolicyConfiguration, error) {
routeValues := make(map[string]string)
if args.Project == nil || *args.Project == "" {
return nil, &azuredevops.ArgumentNilOrEmptyError{ArgumentName: "args.Project"}
}
routeValues["project"] = *args.Project
if args.ConfigurationId == nil {
return nil, &azuredevops.ArgumentNilError{ArgumentName: "args.ConfigurationId"}
}
routeValues["configurationId"] = strconv.Itoa(*args.ConfigurationId)
queryParams := url.Values{}
if args.Top != nil {
queryParams.Add("$top", strconv.Itoa(*args.Top))
}
if args.Skip != nil {
queryParams.Add("$skip", strconv.Itoa(*args.Skip))
}
locationId, _ := uuid.Parse("fe1e68a2-60d3-43cb-855b-85e41ae97c95")
resp, err := client.Client.Send(ctx, http.MethodGet, locationId, "5.1", routeValues, queryParams, nil, "", "application/json", nil)
if err != nil {
return nil, err
}
var responseValue []PolicyConfiguration
err = client.Client.UnmarshalCollectionBody(resp, &responseValue)
return &responseValue, err
}
// Arguments for the GetPolicyConfigurationRevisions function
type GetPolicyConfigurationRevisionsArgs struct {
// (required) Project ID or project name
Project *string
// (required) The policy configuration ID.
ConfigurationId *int
// (optional) The number of revisions to retrieve.
Top *int
// (optional) The number of revisions to ignore. For example, to retrieve results 101-150, set top to 50 and skip to 100.
Skip *int
}
// Retrieve a specific policy type by ID.
func (client *Client) GetPolicyType(ctx context.Context, args GetPolicyTypeArgs) (*PolicyType, error) {
func (client *ClientImpl) GetPolicyType(ctx context.Context, args GetPolicyTypeArgs) (*PolicyType, error) {
routeValues := make(map[string]string)
if args.Project == nil || *args.Project == "" {
return nil, &azuredevops.ArgumentNilOrEmptyError{ArgumentName: "args.Project"}
@ -438,7 +404,7 @@ type GetPolicyTypeArgs struct {
}
// Retrieve all available policy types.
func (client *Client) GetPolicyTypes(ctx context.Context, args GetPolicyTypesArgs) (*[]PolicyType, error) {
func (client *ClientImpl) GetPolicyTypes(ctx context.Context, args GetPolicyTypesArgs) (*[]PolicyType, error) {
routeValues := make(map[string]string)
if args.Project == nil || *args.Project == "" {
return nil, &azuredevops.ArgumentNilOrEmptyError{ArgumentName: "args.Project"}
@ -461,3 +427,74 @@ type GetPolicyTypesArgs struct {
// (required) Project ID or project name
Project *string
}
// [Preview API] Requeue the policy evaluation.
func (client *ClientImpl) RequeuePolicyEvaluation(ctx context.Context, args RequeuePolicyEvaluationArgs) (*PolicyEvaluationRecord, error) {
routeValues := make(map[string]string)
if args.Project == nil || *args.Project == "" {
return nil, &azuredevops.ArgumentNilOrEmptyError{ArgumentName: "args.Project"}
}
routeValues["project"] = *args.Project
if args.EvaluationId == nil {
return nil, &azuredevops.ArgumentNilError{ArgumentName: "args.EvaluationId"}
}
routeValues["evaluationId"] = (*args.EvaluationId).String()
locationId, _ := uuid.Parse("46aecb7a-5d2c-4647-897b-0209505a9fe4")
resp, err := client.Client.Send(ctx, http.MethodPatch, locationId, "5.1-preview.1", routeValues, nil, nil, "", "application/json", nil)
if err != nil {
return nil, err
}
var responseValue PolicyEvaluationRecord
err = client.Client.UnmarshalBody(resp, &responseValue)
return &responseValue, err
}
// Arguments for the RequeuePolicyEvaluation function
type RequeuePolicyEvaluationArgs struct {
// (required) Project ID or project name
Project *string
// (required) ID of the policy evaluation to be retrieved.
EvaluationId *uuid.UUID
}
// Update a policy configuration by its ID.
func (client *ClientImpl) UpdatePolicyConfiguration(ctx context.Context, args UpdatePolicyConfigurationArgs) (*PolicyConfiguration, error) {
if args.Configuration == nil {
return nil, &azuredevops.ArgumentNilError{ArgumentName: "args.Configuration"}
}
routeValues := make(map[string]string)
if args.Project == nil || *args.Project == "" {
return nil, &azuredevops.ArgumentNilOrEmptyError{ArgumentName: "args.Project"}
}
routeValues["project"] = *args.Project
if args.ConfigurationId == nil {
return nil, &azuredevops.ArgumentNilError{ArgumentName: "args.ConfigurationId"}
}
routeValues["configurationId"] = strconv.Itoa(*args.ConfigurationId)
body, marshalErr := json.Marshal(*args.Configuration)
if marshalErr != nil {
return nil, marshalErr
}
locationId, _ := uuid.Parse("dad91cbe-d183-45f8-9c6e-9c1164472121")
resp, err := client.Client.Send(ctx, http.MethodPut, locationId, "5.1", routeValues, nil, bytes.NewReader(body), "application/json", "application/json", nil)
if err != nil {
return nil, err
}
var responseValue PolicyConfiguration
err = client.Client.UnmarshalBody(resp, &responseValue)
return &responseValue, err
}
// Arguments for the UpdatePolicyConfiguration function
type UpdatePolicyConfigurationArgs struct {
// (required) The policy configuration to update.
Configuration *PolicyConfiguration
// (required) Project ID or project name
Project *string
// (required) ID of the existing policy configuration to be updated.
ConfigurationId *int
}

File diff suppressed because it is too large Load Diff

View File

@ -238,7 +238,7 @@ type CloneOperationInformation struct {
SourcePlan *ShallowReference `json:"sourcePlan,omitempty"`
// Shallow reference of the source
SourceProject *ShallowReference `json:"sourceProject,omitempty"`
// Current state of the operation. When State reaches Suceeded or Failed, the operation is complete
// Current state of the operation. When State reaches Succeeded or Failed, the operation is complete
State *CloneOperationState `json:"state,omitempty"`
// Url for getting the clone information
Url *string `json:"url,omitempty"`

View File

@ -1,5 +1,192 @@
Copyright:: Copyright (c) 2016 PagerDuty, Inc.
License:: Apache License, Version 2.0
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2017 PagerDuty, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@ -5,15 +5,27 @@ go-pagerduty is a CLI and [go](https://golang.org/) client library for the [Page
## Installation
```
First, download the source code
```cli
go get github.com/PagerDuty/go-pagerduty
```
Next build the application.
```cli
cd $GOPATH/src/github.com/PagerDuty/go-pagerduty
go build -o $GOPATH/bin/pd command/*
```
If you do not have the dependencies necessary to build the project, run this in the project root and try again
```cli
go get ./...
```
## Usage
### CLI
The CLI requires an [authentication token](https://v2.developer.pagerduty.com/docs/authentication), which can be sepcified in `.pd.yml`
The CLI requires an [authentication token](https://v2.developer.pagerduty.com/docs/authentication), which can be specified in `.pd.yml`
file in the home directory of the user, or passed as a command-line argument.
Example of config file:
@ -22,12 +34,6 @@ Example of config file:
authtoken: fooBar
```
#### Install
```cli
cd $GOPATH/github.com/PagerDuty/go-pagerduty
go build -o $GOPATH/bin/pd command/*
```
#### Commands
`pd` command provides a single entrypoint for all the API endpoints, with individual
API represented by their own sub commands. For an exhaustive list of sub-commands, try:
@ -57,20 +63,22 @@ var authtoken = "" // Set your auth token here
func main() {
var opts pagerduty.ListEscalationPoliciesOptions
client := pagerduty.NewClient(authtoken)
if eps, err := client.ListEscalationPolicies(opts); err != nil {
eps, err := client.ListEscalationPolicies(opts)
if err != nil {
panic(err)
} else {
}
for _, p := range eps.EscalationPolicies {
fmt.Println(p.Name)
}
}
}
```
The PagerDuty API client also exposes its HTTP client as the `HTTPClient` field.
If you need to use your own HTTP client, for doing things like defining your own
transport settings, you can replace the default HTTP client with your own by
simply by setting a new value in the `HTTPClient` field.
## License
[Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0)
## Contributing

View File

@ -86,6 +86,7 @@ var defaultHTTPClient HTTPClient = newDefaultHTTPClient()
// Client wraps http client
type Client struct {
authToken string
apiEndpoint string
// HTTPClient is the HTTP client used for making requests against the
// PagerDuty API. You can use either *http.Client here, or your own
@ -97,6 +98,7 @@ type Client struct {
func NewClient(authToken string) *Client {
return &Client{
authToken: authToken,
apiEndpoint: apiEndpoint,
HTTPClient: defaultHTTPClient,
}
}
@ -130,7 +132,7 @@ func (c *Client) get(path string) (*http.Response, error) {
}
func (c *Client) do(method, path string, body io.Reader, headers *map[string]string) (*http.Response, error) {
endpoint := apiEndpoint + path
endpoint := c.apiEndpoint + path
req, _ := http.NewRequest(method, endpoint, body)
req.Header.Set("Accept", "application/vnd.pagerduty+json;version=2")
if headers != nil {

View File

@ -23,9 +23,9 @@ type EscalationPolicy struct {
APIObject
Name string `json:"name,omitempty"`
EscalationRules []EscalationRule `json:"escalation_rules,omitempty"`
Services []APIReference `json:"services,omitempty"`
Services []APIObject `json:"services,omitempty"`
NumLoops uint `json:"num_loops,omitempty"`
Teams []APIReference `json:"teams,omitempty"`
Teams []APIReference `json:"teams"`
Description string `json:"description,omitempty"`
RepeatEnabled bool `json:"repeat_enabled,omitempty"`
}

View File

@ -14,6 +14,7 @@ type V2Event struct {
Action string `json:"event_action"`
DedupKey string `json:"dedup_key,omitempty"`
Images []interface{} `json:"images,omitempty"`
Links []interface{} `json:"links,omitempty"`
Client string `json:"client,omitempty"`
ClientURL string `json:"client_url,omitempty"`
Payload *V2Payload `json:"payload,omitempty"`

View File

@ -7,28 +7,56 @@ import (
"github.com/google/go-querystring/query"
)
// Acknowledgement is the data structure of an acknoledgement of an incident.
// Acknowledgement is the data structure of an acknowledgement of an incident.
type Acknowledgement struct {
At string
Acknowledger APIObject
At string `json:"at,omitempty"`
Acknowledger APIObject `json:"acknowledger,omitempty"`
}
// PendingAction is the data structure for any pending actions on an incident.
type PendingAction struct {
Type string
At string
Type string `json:"type,omitempty"`
At string `json:"at,omitempty"`
}
// Assignment is the data structure for an assignment of an incident
type Assignment struct {
At string
Assignee APIObject
At string `json:"at,omitempty"`
Assignee APIObject `json:"assignee,omitempty"`
}
// AlertCounts is the data structure holding a summary of the number of alerts by status of an incident.
type AlertCounts struct {
Triggered uint `json:"triggered,omitempty"`
Resolved uint `json:"resolved,omitempty"`
All uint `json:"all,omitempty"`
}
// Priority is the data structure describing the priority of an incident.
type Priority struct {
APIObject
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
}
// Resolve reason is the data structure describing the reason an incident was resolved
type ResolveReason struct {
Type string `json:"type,omitempty"`
Incident APIObject `json:"incident"`
}
// IncidentBody is the datastructure containing data describing the incident.
type IncidentBody struct {
Type string `json:"type,omitempty"`
Details string `json:"details,omitempty"`
}
// Incident is a normalized, de-duplicated event generated by a PagerDuty integration.
type Incident struct {
APIObject
IncidentNumber uint `json:"incident_number,omitempty"`
Title string `json:"title,omitempty"`
Description string `json:"description,omitempty"`
CreatedAt string `json:"created_at,omitempty"`
PendingActions []PendingAction `json:"pending_actions,omitempty"`
IncidentKey string `json:"incident_key,omitempty"`
@ -40,10 +68,14 @@ type Incident struct {
FirstTriggerLogEntry APIObject `json:"first_trigger_log_entry,omitempty"`
EscalationPolicy APIObject `json:"escalation_policy,omitempty"`
Teams []APIObject `json:"teams,omitempty"`
Priority *Priority `json:"priority,omitempty"`
Urgency string `json:"urgency,omitempty"`
Status string `json:"status,omitempty"`
Id string `json:"id,omitempty"`
Priority APIObject `json:"priority,omitempty"`
ResolveReason ResolveReason `json:"resolve_reason,omitempty"`
AlertCounts AlertCounts `json:"alert_counts,omitempty"`
Body IncidentBody `json:"body,omitempty"`
IsMergeable bool `json:"is_mergeable,omitempty"`
}
// ListIncidentsResponse is the response structure when calling the ListIncident API endpoint.
@ -83,32 +115,29 @@ func (c *Client) ListIncidents(o ListIncidentsOptions) (*ListIncidentsResponse,
return &result, c.decodeJSON(resp, &result)
}
// CreateIncident is the structure POST'd to the incidents endpoint. It wraps a CreateIncidentValue
type CreateIncident struct {
Incident CreateIncidentOptions `json:"incident"`
}
// createIncidentResponse is returned from the API when creating a response.
type createIncidentResponse struct {
Incident Incident `json:incident`
Incident Incident `json:"incident"`
}
// CreateIncidentOptions is the structure used when POSTing to the CreateIncident API endpoint.
type CreateIncidentOptions struct {
Type string `json:"type"`
Title string `json:"title"`
Service APIReference `json:"service"`
Priority APIReference `json:"priority"`
IncidentKey string `json:"incident_key"`
Body APIDetails `json:"body"`
EscalationPolicy APIReference `json:"escalation_policy"`
Service *APIReference `json:"service"`
Priority *APIReference `json:"priority,omitempty"`
IncidentKey string `json:"incident_key,omitempty"`
Body *APIDetails `json:"body,omitempty"`
EscalationPolicy *APIReference `json:"escalation_policy,omitempty"`
}
// CreateIncident creates an incident synchronously without a corresponding event from a monitoring service.
func (c *Client) CreateIncident(from string, i *CreateIncident) (*Incident, error) {
func (c *Client) CreateIncident(from string, o *CreateIncidentOptions) (*Incident, error) {
headers := make(map[string]string)
headers["From"] = from
resp, e := c.post("/incidents", i, &headers)
data := make(map[string]*CreateIncidentOptions)
data["incident"] = o
resp, e := c.post("/incidents", data, &headers)
if e != nil {
return nil, e
}
@ -132,6 +161,16 @@ func (c *Client) ManageIncidents(from string, incidents []Incident) error {
return e
}
// MergeIncidents a list of source incidents into a specified incident.
func (c *Client) MergeIncidents(from string, id string, incidents []Incident) error {
r := make(map[string][]Incident)
r["source_incidents"] = incidents
headers := make(map[string]string)
headers["From"] = from
_, e := c.put("/incidents/"+id+"/merge", r, &headers)
return e
}
// GetIncident shows detailed information about an incident.
func (c *Client) GetIncident(id string) (*Incident, error) {
resp, err := c.get("/incidents/" + id)
@ -176,34 +215,43 @@ func (c *Client) ListIncidentNotes(id string) ([]IncidentNote, error) {
// IncidentAlert is a alert for the specified incident.
type IncidentAlert struct {
ID string `json:"id,omitempty"`
Summary string `json:"summary,omitempty"`
APIObject
CreatedAt string `json:"created_at,omitempty"`
Status string `json:"status,omitempty"`
AlertKey string `json:"alert_key,omitempty"`
Service APIObject `json:"service,omitempty"`
Body map[string]interface{} `json:"body,omitempty"`
Incident APIReference `json:"incident,omitempty"`
Suppressed bool `json:"suppressed,omitempty"`
Severity string `json:"severity,omitempty"`
Integration APIObject `json:"integration,omitempty"`
}
// ListAlertsResponse is the response structure when calling the ListAlert API endpoint.
type ListAlertsResponse struct {
APIListObject
Alerts []IncidentAlert `json:"alerts,omitempty"`
}
// ListIncidentAlerts lists existing alerts for the specified incident.
func (c *Client) ListIncidentAlerts(id string) ([]IncidentAlert, error) {
func (c *Client) ListIncidentAlerts(id string) (*ListAlertsResponse, error) {
resp, err := c.get("/incidents/" + id + "/alerts")
if err != nil {
return nil, err
}
var result map[string][]IncidentAlert
if err := c.decodeJSON(resp, &result); err != nil {
return nil, err
}
alerts, ok := result["alerts"]
if !ok {
return nil, fmt.Errorf("JSON response does not have alerts field")
}
return alerts, nil
var result ListAlertsResponse
return &result, c.decodeJSON(resp, &result)
}
// CreateIncidentNote creates a new note for the specified incident.
func (c *Client) CreateIncidentNote(id string, note IncidentNote) error {
data := make(map[string]IncidentNote)
headers := make(map[string]string)
headers["From"] = note.User.Summary
data["note"] = note
_, err := c.post("/incidents/"+id+"/notes", data, nil)
_, err := c.post("/incidents/"+id+"/notes", data, &headers)
return err
}
@ -242,3 +290,18 @@ func (c *Client) ListIncidentLogEntries(id string, o ListIncidentLogEntriesOptio
var result ListIncidentLogEntriesResponse
return &result, c.decodeJSON(resp, &result)
}
// Alert is a list of all of the alerts that happened to an incident.
type Alert struct {
APIObject
Service APIObject `json:"service,omitempty"`
CreatedAt string `json:"created_at,omitempty"`
Status string `json:"status,omitempty"`
AlertKey string `json:"alert_key,omitempty"`
Incident APIObject `json:"incident,omitempty"`
}
type ListAlertResponse struct {
APIListObject
Alerts []Alert `json:"alerts,omitempty"`
}

View File

@ -68,7 +68,7 @@ func (c *Client) ListLogEntries(o ListLogEntriesOptions) (*ListLogEntryResponse,
// GetLogEntryOptions is the data structure used when calling the GetLogEntry API endpoint.
type GetLogEntryOptions struct {
TimeZone string `url:"timezone,omitempty"`
TimeZone string `url:"time_zone,omitempty"`
Includes []string `url:"include,omitempty,brackets"`
}

View File

@ -49,14 +49,25 @@ func (c *Client) ListMaintenanceWindows(o ListMaintenanceWindowsOptions) (*ListM
return &result, c.decodeJSON(resp, &result)
}
// CreateMaintenanceWindows creates a new maintenance window for the specified services.
func (c *Client) CreateMaintenanceWindows(m MaintenanceWindow) (*MaintenanceWindow, error) {
// CreateMaintenanceWindow creates a new maintenance window for the specified services.
func (c *Client) CreateMaintenanceWindow(from string, o MaintenanceWindow) (*MaintenanceWindow, error) {
data := make(map[string]MaintenanceWindow)
data["maintenance_window"] = m
resp, err := c.post("/maintenance_windows", data, nil)
o.Type = "maintenance_window"
data["maintenance_window"] = o
headers := make(map[string]string)
if from != "" {
headers["From"] = from
}
resp, err := c.post("/maintenance_windows", data, &headers)
return getMaintenanceWindowFromResponse(c, resp, err)
}
// CreateMaintenanceWindows creates a new maintenance window for the specified services.
// Deprecated: Use `CreateMaintenanceWindow` instead.
func (c *Client) CreateMaintenanceWindows(o MaintenanceWindow) (*MaintenanceWindow, error) {
return c.CreateMaintenanceWindow("", o)
}
// DeleteMaintenanceWindow deletes an existing maintenance window if it's in the future, or ends it if it's currently on-going.
func (c *Client) DeleteMaintenanceWindow(id string) error {
_, err := c.delete("/maintenance_windows/" + id)

View File

@ -6,9 +6,9 @@ import (
// OnCall represents a contiguous unit of time for which a user will be on call for a given escalation policy and escalation rule.
type OnCall struct {
User APIObject `json:"user,omitempty"`
Schedule APIObject `json:"schedule,omitempty"`
EscalationPolicy APIObject `json:"escalation_policy,omitempty"`
User User `json:"user,omitempty"`
Schedule Schedule `json:"schedule,omitempty"`
EscalationPolicy EscalationPolicy `json:"escalation_policy,omitempty"`
EscalationLevel uint `json:"escalation_level,omitempty"`
Start string `json:"start,omitempty"`
End string `json:"end,omitempty"`

View File

@ -7,42 +7,51 @@ import (
"github.com/google/go-querystring/query"
)
// ContactMethod is a way of contacting the user.
type ContactMethod struct {
ID string
Label string
Address string
Type string
SendShortEmail bool `json:"send_short_email"`
}
// NotificationRule is a rule for notifying the user.
type NotificationRule struct {
ID string
ID string `json:"id"`
StartDelayInMinutes uint `json:"start_delay_in_minutes"`
CreatedAt string `json:"created_at"`
ContactMethod ContactMethod `json:"contact_method"`
Urgency string
Type string
Urgency string `json:"urgency"`
Type string `json:"type"`
}
// User is a member of a PagerDuty account that has the ability to interact with incidents and other data on the account.
type User struct {
APIObject
Type string `json:"type"`
Name string `json:"name"`
Summary string `json:"summary"`
Email string `json:"email"`
Timezone string `json:"timezone,omitempty"`
Timezone string `json:"time_zone,omitempty"`
Color string `json:"color,omitempty"`
Role string `json:"role,omitempty"`
AvatarURL string `json:"avatar_url,omitempty"`
Description string `json:"description,omitempty"`
InvitationSent bool
InvitationSent bool `json:"invitation_sent,omitempty"`
ContactMethods []ContactMethod `json:"contact_methods"`
NotificationRules []NotificationRule `json:"notification_rules"`
JobTitle string `json:"job_title,omitempty"`
Teams []Team
}
// ContactMethod is a way of contacting the user.
type ContactMethod struct {
ID string `json:"id"`
Type string `json:"type"`
Summary string `json:"summary"`
Self string `json:"self"`
Label string `json:"label"`
Address string `json:"address"`
SendShortEmail bool `json:"send_short_email,omitempty"`
SendHTMLEmail bool `json:"send_html_email,omitempty"`
Blacklisted bool `json:"blacklisted,omitempty"`
CountryCode int `json:"country_code,omitempty"`
Enabled bool `json:"enabled,omitempty"`
HTMLUrl string `json:"html_url"`
}
// ListUsersResponse is the data structure returned from calling the ListUsers API endpoint.
type ListUsersResponse struct {
APIListObject
@ -57,6 +66,12 @@ type ListUsersOptions struct {
Includes []string `url:"include,omitempty,brackets"`
}
// ListContactMethodResponse is the data structure returned from calling the GetUserContactMethod API endpoint.
type ListContactMethodsResponse struct {
APIListObject
ContactMethods []ContactMethod `json:"contact_methods"`
}
// GetUserOptions is the data structure used when calling the GetUser API endpoint.
type GetUserOptions struct {
Includes []string `url:"include,omitempty,brackets"`
@ -123,3 +138,35 @@ func getUserFromResponse(c *Client, resp *http.Response, err error) (*User, erro
}
return &t, nil
}
// ListUserContactMethod fetches contact methods of the existing user.
func (c *Client) ListUserContactMethods(userId string) (*ListContactMethodsResponse, error) {
resp, err := c.get("/users/" + userId + "/contact_methods")
if err != nil {
return nil, err
}
var result ListContactMethodsResponse
return &result, c.decodeJSON(resp, &result)
}
// GetContactMethod gets details about a contact method.
func (c *Client) GetUserContactMethod(userID, id string) (*ContactMethod, error) {
resp, err := c.get("/users/" + userID + "/contact_methods/" + id)
return getContactMethodFromResponse(c, resp, err)
}
func getContactMethodFromResponse(c *Client, resp *http.Response, err error) (*ContactMethod, error) {
if err != nil {
return nil, err
}
var target map[string]ContactMethod
if dErr := c.decodeJSON(resp, &target); dErr != nil {
return nil, fmt.Errorf("Could not decode JSON response: %v", dErr)
}
rootNode := "contact_method"
t, nodeOK := target[rootNode]
if !nodeOK {
return nil, fmt.Errorf("JSON response does not have %s field", rootNode)
}
return &t, nil
}

View File

@ -19,6 +19,9 @@ type Vendor struct {
ThumbnailURL string `json:"thumbnail_url,omitempty"`
GenericServiceType string `json:"generic_service_type,omitempty"`
IntegrationGuideURL string `json:"integration_guide_url,omitempty"`
AlertCreationDefault string `json:"alert_creation_default,omitempty"`
AlertCreationEditable bool `json:"alert_creation_editable,omitempty"`
IsPDCEF bool `json:"is_pd_cef,omitempty"`
}
// ListVendorResponse is the data structure returned from calling the ListVendors API endpoint.

View File

@ -4,5 +4,3 @@ require (
github.com/andybalholm/cascadia v1.0.0
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a
)
go 1.13

View File

@ -4,7 +4,6 @@ import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
@ -21,85 +20,208 @@ type ArticlesResource struct {
// can be narrowed down, filtered or enhanced using query
// parameters as specified on the documentation.
// See: https://docs.dev.to/api/#tag/articles/paths/~1articles/get
func (ar *ArticlesResource) List(ctx context.Context, opt ArticleListOptions) ([]Article, error) {
var l []Article
func (ar *ArticlesResource) List(ctx context.Context, opt ArticleListOptions) ([]ListedArticle, error) {
q, err := query.Values(opt)
if err != nil {
return nil, err
}
req, _ := ar.API.NewRequest(http.MethodGet, fmt.Sprintf("api/articles?%s", q.Encode()), nil)
res, _ := ar.API.HTTPClient.Do(req)
cont, err := ioutil.ReadAll(res.Body)
req, err := ar.API.NewRequest(http.MethodGet, fmt.Sprintf("api/articles?%s", q.Encode()), nil)
if err != nil {
return nil, err
}
json.Unmarshal(cont, &l)
return l, nil
res, err := ar.API.HTTPClient.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
if nonSuccessfulResponse(res) {
return nil, unmarshalErrorResponse(res)
}
var articles []ListedArticle
if err := json.NewDecoder(res.Body).Decode(&articles); err != nil {
return nil, err
}
return articles, nil
}
// ListForTag is a convenience method for retrieving articles
// for a particular tag, calling the base List method.
func (ar *ArticlesResource) ListForTag(ctx context.Context, tag string, page int) ([]ListedArticle, error) {
return ar.List(ctx, ArticleListOptions{Tags: tag, Page: page})
}
// ListForUser is a convenience method for retrieving articles
// written by a particular user, calling the base List method.
func (ar *ArticlesResource) ListForUser(ctx context.Context, username string, page int) ([]ListedArticle, error) {
return ar.List(ctx, ArticleListOptions{Username: username, Page: page})
}
// ListMyPublishedArticles lists all published articles
// written by the user authenticated with this client,
// erroring if the caller is not authenticated. Articles in
// the response will be listed in reverse chronological order
// by their publication times.
//
// If opts is nil, then no query parameters will be sent; the
// page number will be 1 and the page size will be 30
// articles.
func (ar *ArticlesResource) ListMyPublishedArticles(ctx context.Context, opts *MyArticlesOptions) ([]ListedArticle, error) {
return ar.listMyArticles(ctx, "api/articles/me/published", opts)
}
// ListMyUnpublishedArticles lists all unpublished articles
// written by the user authenticated with this client,
// erroring if the caller is not authenticated. Articles in
// the response will be listed in reverse chronological order
// by their creation times.
//
// If opts is nil, then no query parameters will be sent; the
// page number will be 1 and the page size will be 30
// articles.
func (ar *ArticlesResource) ListMyUnpublishedArticles(ctx context.Context, opts *MyArticlesOptions) ([]ListedArticle, error) {
return ar.listMyArticles(ctx, "api/articles/me/unpublished", opts)
}
// ListAllMyArticles lists all articles written by the user
// authenticated with this client, erroring if the caller is
// not authenticated. Articles in the response will be listed
// in reverse chronological order by their creation times,
// with unpublished articles listed before published articles.
//
// If opts is nil, then no query parameters will be sent; the
// page number will be 1 and the page size will be 30
// articles.
func (ar *ArticlesResource) ListAllMyArticles(ctx context.Context, opts *MyArticlesOptions) ([]ListedArticle, error) {
return ar.listMyArticles(ctx, "api/articles/me/all", opts)
}
// listMyArticles serves for handling roundtrips to the
// /api/articles/me/* endpoints, requesting articles from the
// endpoint passed in, and returning a list of articles.
func (ar *ArticlesResource) listMyArticles(
ctx context.Context,
endpoint string,
opts *MyArticlesOptions,
) ([]ListedArticle, error) {
if ar.API.Config.InsecureOnly {
return nil, ErrProtectedEndpoint
}
req, err := ar.API.NewRequest(http.MethodGet, endpoint, nil)
if err != nil {
return nil, err
}
req.Header.Add(APIKeyHeader, ar.API.Config.APIKey)
if opts != nil {
q, err := query.Values(opts)
if err != nil {
return nil, err
}
req.URL.RawQuery = q.Encode()
}
res, err := ar.API.HTTPClient.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
if nonSuccessfulResponse(res) {
return nil, unmarshalErrorResponse(res)
}
var articles []ListedArticle
if err := json.NewDecoder(res.Body).Decode(&articles); err != nil {
return nil, err
}
return articles, nil
}
// Find will retrieve an Article matching the ID passed.
func (ar *ArticlesResource) Find(ctx context.Context, id uint32) (Article, error) {
var art Article
req, _ := ar.API.NewRequest(http.MethodGet, fmt.Sprintf("api/articles/%d", id), nil)
req, err := ar.API.NewRequest(http.MethodGet, fmt.Sprintf("api/articles/%d", id), nil)
if err != nil {
return Article{}, err
}
res, err := ar.API.HTTPClient.Do(req)
if err != nil {
return art, err
return Article{}, err
}
cont, err := ioutil.ReadAll(res.Body)
if err != nil {
return art, err
defer res.Body.Close()
if nonSuccessfulResponse(res) {
return Article{}, unmarshalErrorResponse(res)
}
var art Article
if err := json.NewDecoder(res.Body).Decode(&art); err != nil {
return Article{}, err
}
json.Unmarshal(cont, &art)
return art, nil
}
// New will create a new article on dev.to
func (ar *ArticlesResource) New(ctx context.Context, a Article) (Article, error) {
func (ar *ArticlesResource) New(ctx context.Context, u ArticleUpdate) (Article, error) {
if ar.API.Config.InsecureOnly {
return a, ErrProtectedEndpoint
return Article{}, ErrProtectedEndpoint
}
cont, err := json.Marshal(a)
cont, err := json.Marshal(&u)
if err != nil {
return a, err
return Article{}, err
}
req, err := ar.API.NewRequest(http.MethodPost, "api/articles", strings.NewReader(string(cont)))
if err != nil {
return a, err
return Article{}, err
}
req.Header.Add(APIKeyHeader, ar.API.Config.APIKey)
res, err := ar.API.HTTPClient.Do(req)
if err != nil {
return a, err
return Article{}, err
}
content, err := ioutil.ReadAll(res.Body)
if err != nil {
return a, err
defer res.Body.Close()
if nonSuccessfulResponse(res) {
return Article{}, unmarshalErrorResponse(res)
}
var a Article
if err := json.NewDecoder(res.Body).Decode(&a); err != nil {
return Article{}, err
}
json.Unmarshal(content, &a)
return a, nil
}
func (ar *ArticlesResource) Update(ctx context.Context, a Article) (Article, error) {
// Update will mutate the resource by id, and all the changes
// performed to the Article will be applied, thus validation
// on the API side.
func (ar *ArticlesResource) Update(ctx context.Context, u ArticleUpdate, id uint32) (Article, error) {
if ar.API.Config.InsecureOnly {
return a, ErrProtectedEndpoint
return Article{}, ErrProtectedEndpoint
}
cont, err := json.Marshal(a)
cont, err := json.Marshal(&u)
if err != nil {
return a, err
return Article{}, err
}
req, err := ar.API.NewRequest(http.MethodPut, fmt.Sprintf("api/articles/%d", a.ID), strings.NewReader(string(cont)))
req, err := ar.API.NewRequest(http.MethodPut, fmt.Sprintf("api/articles/%d", id), strings.NewReader(string(cont)))
if err != nil {
return a, err
return Article{}, err
}
req.Header.Add(APIKeyHeader, ar.API.Config.APIKey)
res, err := ar.API.HTTPClient.Do(req)
if err != nil {
return a, err
return Article{}, err
}
content, err := ioutil.ReadAll(res.Body)
if err != nil {
return a, err
defer res.Body.Close()
if nonSuccessfulResponse(res) {
return Article{}, unmarshalErrorResponse(res)
}
var a Article
if err := json.NewDecoder(res.Body).Decode(&a); err != nil {
return Article{}, err
}
json.Unmarshal(content, &a)
return a, nil
}

View File

@ -2,7 +2,7 @@ package devto
import "errors"
//Confugration errors
// Configuration errors
var (
ErrMissingRequiredParameter = errors.New("a required parameter is missing")
)
@ -19,7 +19,7 @@ type Config struct {
//
// It takes a boolean (p) as first parameter to indicate if
// you need access to endpoints which require authentication,
//and a API key as second paramenter, if p is set to true and
// and a API key as second parameter, if p is set to true and
// you don't provide an API key, it will return an error.
func NewConfig(p bool, k string) (c *Config, err error) {
if p == true && k == "" {

View File

@ -54,7 +54,10 @@ func NewClient(ctx context.Context, conf *Config, bc httpClient, bu string) (dev
bu = BaseURL
}
u, _ := url.Parse(bu)
u, err := url.Parse(bu)
if err != nil {
return nil, err
}
c := &Client{
Context: ctx,

View File

@ -0,0 +1,10 @@
// Package devto is a wrapper around dev.to REST API
//
// Where programmers share ideas and help each other grow.
// It is an online community for sharing and discovering great ideas,
// having debates, and making friends. Anyone can share articles,
// questions, discussions, etc. as long as they have the rights to the
// words they are sharing. Cross-posting from your own blog is welcome.
//
// See: https://docs.dev.to/api
package devto

View File

@ -1,6 +1,8 @@
package devto
import (
"encoding/json"
"fmt"
"net/url"
"strings"
"time"
@ -27,9 +29,115 @@ type Organization struct {
ProfileImage90 *WebURL `json:"profile_image_90,omitempty"`
}
// FlareTag represents an article's flare tag, if the article
// has one.
type FlareTag struct {
Name string `json:"name"`
BGColorHex string `json:"bg_color_hex"`
TextColorHex string `json:"text_color_hex"`
}
// Tags are a group of topics related to an article
type Tags []string
// This deserialization logic is so that if a listed article
// originates from the /articles endpoint instead of
// /articles/me/*, its Published field is returned as true,
// since /articles exclusively returns articles that have been
// published.
type listedArticleJSON struct {
TypeOf string `json:"type_of,omitempty"`
ID uint32 `json:"id,omitempty"`
Title string `json:"title,omitempty"`
Description string `json:"description,omitempty"`
CoverImage *WebURL `json:"cover_image,omitempty"`
PublishedAt *time.Time `json:"published_at,omitempty"`
PublishedTimestamp string `json:"published_timestamp,omitempty"`
TagList Tags `json:"tag_list,omitempty"`
Slug string `json:"slug,omitempty"`
Path string `json:"path,omitempty"`
URL *WebURL `json:"url,omitempty"`
CanonicalURL *WebURL `json:"canonical_url,omitempty"`
CommentsCount uint `json:"comments_count,omitempty"`
PositiveReactionsCount uint `json:"positive_reactions_count,omitempty"`
User User `json:"user,omitempty"`
Organization *Organization `json:"organization,omitempty"`
FlareTag *FlareTag `json:"flare_tag,omitempty"`
BodyMarkdown string `json:"body_markdown,omitempty"`
Published *bool `json:"published,omitempty"`
}
func (j *listedArticleJSON) listedArticle() ListedArticle {
a := ListedArticle{
TypeOf: j.TypeOf,
ID: j.ID,
Title: j.Title,
Description: j.Description,
CoverImage: j.CoverImage,
PublishedAt: j.PublishedAt,
PublishedTimestamp: j.PublishedTimestamp,
TagList: j.TagList,
Slug: j.Slug,
Path: j.Path,
URL: j.URL,
CanonicalURL: j.CanonicalURL,
CommentsCount: j.CommentsCount,
PositiveReactionsCount: j.PositiveReactionsCount,
User: j.User,
Organization: j.Organization,
FlareTag: j.FlareTag,
BodyMarkdown: j.BodyMarkdown,
}
if j.Published != nil {
a.Published = *j.Published
} else {
// "published" currently is included in the API
// response for dev.to's /articles/me/* endpoints,
// but not in /articles, so we are setting this
// to true since /articles only returns articles
// that are published.
a.Published = true
}
return a
}
// ListedArticle represents an article returned from one of
// the list articles endpoints (/articles, /articles/me/*).
type ListedArticle struct {
TypeOf string `json:"type_of,omitempty"`
ID uint32 `json:"id,omitempty"`
Title string `json:"title,omitempty"`
Description string `json:"description,omitempty"`
CoverImage *WebURL `json:"cover_image,omitempty"`
PublishedAt *time.Time `json:"published_at,omitempty"`
PublishedTimestamp string `json:"published_timestamp,omitempty"`
TagList Tags `json:"tag_list,omitempty"`
Slug string `json:"slug,omitempty"`
Path string `json:"path,omitempty"`
URL *WebURL `json:"url,omitempty"`
CanonicalURL *WebURL `json:"canonical_url,omitempty"`
CommentsCount uint `json:"comments_count,omitempty"`
PositiveReactionsCount uint `json:"positive_reactions_count,omitempty"`
User User `json:"user,omitempty"`
Organization *Organization `json:"organization,omitempty"`
FlareTag *FlareTag `json:"flare_tag,omitempty"`
// Only present in "/articles/me/*" endpoints
BodyMarkdown string `json:"body_markdown,omitempty"`
Published bool `json:"published,omitempty"`
}
// UnmarshalJSON implements the JSON Unmarshaler interface.
func (a *ListedArticle) UnmarshalJSON(b []byte) error {
var j listedArticleJSON
if err := json.Unmarshal(b, &j); err != nil {
return err
}
*a = j.listedArticle()
return nil
}
// Article contains all the information related to a single
// information resource from devto.
type Article struct {
@ -39,24 +147,39 @@ type Article struct {
Description string `json:"description,omitempty"`
CoverImage *WebURL `json:"cover_image,omitempty"`
SocialImage *WebURL `json:"social_image,omitempty"`
ReadablePublishDate string `json:"readable_publish_date"`
Published bool `json:"published,omitempty"`
PublishedAt *time.Time `json:"published_at,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"`
EditedAt *time.Time `json:"edited_at,omitempty"`
CrossPostedAt *time.Time `json:"crossposted_at,omitempty"`
LastCommentAt *time.Time `json:"last_comment_at,omitempty"`
TagList Tags `json:"tag_list,omitempty"`
Tags string `json:"tags,omitempty"`
TagList string `json:"tag_list,omitempty"`
Tags Tags `json:"tags,omitempty"`
Slug string `json:"slug,omitempty"`
Path *WebURL `json:"path,omitempty"`
URL *WebURL `json:"url,omitempty"`
CanonicalURL *WebURL `json:"canonical_url,omitempty"`
CommentsCount uint `json:"comments_count,omitempty"`
PositiveReactionsCount uint `json:"positive_reactions_count,omitempty"`
PublishedTimestamp *time.Time `json:"published_timestamp,omitempty"`
User User `json:"user,omitempty"`
Organization Organization `json:"organization,omitempty"`
BodyHTML string `json:"body_html,omitempty"`
BodyMarkdown string `json:"body_markdown,omitempty"`
Published bool `json:"published,omitempty"`
}
// ArticleUpdate represents an update to an article; it is
// used as the payload in POST and PUT requests for writing
// articles.
type ArticleUpdate struct {
Title string `json:"title"`
BodyMarkdown string `json:"body_markdown"`
Published bool `json:"published"`
Series *string `json:"series"`
MainImage string `json:"main_image,omitempty"`
CanonicalURL string `json:"canonical_url,omitempty"`
Description string `json:"description,omitempty"`
Tags []string `json:"tags,omitempty"`
OrganizationID int32 `json:"organization_id,omitempty"`
}
// ArticleListOptions holds the query values to pass as
@ -69,6 +192,15 @@ type ArticleListOptions struct {
Page int `url:"page,omitempty"`
}
// MyArticlesOptions defines pagination options used as query
// params in the dev.to "list my articles" endpoints.
type MyArticlesOptions struct {
Page int `url:"page,omitempty"`
PerPage int `url:"per_page,omitempty"`
}
// WebURL is a class embed to override default unmarshal
// behavior.
type WebURL struct {
*url.URL
}
@ -85,3 +217,14 @@ func (s *WebURL) UnmarshalJSON(b []byte) error {
s.URL = uri
return nil
}
// ErrorResponse is an error returned from a dev.to API
// endpoint.
type ErrorResponse struct {
ErrorMessage string `json:"error"`
Status int `json:"status"`
}
func (e *ErrorResponse) Error() string {
return fmt.Sprintf(`%d error: "%s"`, e.Status, e.ErrorMessage)
}

View File

@ -0,0 +1,38 @@
package devto
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
// nonSuccessfulResponse indicates that the status code for
// the HTTP response passed in was not one of the "success"
// (2XX) status codes
func nonSuccessfulResponse(res *http.Response) bool { return res.StatusCode/100 != 2 }
// attempt to deserialize the error response; if it succeeds,
// the error will be an ErrorResponse, otherwise it will be
// an error indicating that the error response could not be
// deserialized.
func unmarshalErrorResponse(res *http.Response) error {
var e ErrorResponse
if err := json.NewDecoder(res.Body).Decode(&e); err != nil {
return fmt.Errorf(
`unexpected error deserializing %d response: "%v"`,
res.StatusCode,
err,
)
}
return &e
}
func decodeResponse(r *http.Response) []byte {
c, err := ioutil.ReadAll(r.Body)
if err != nil {
return []byte("")
}
defer r.Body.Close()
return c
}

View File

@ -20,6 +20,7 @@ type Board struct {
Closed bool `json:"closed"`
IDOrganization string `json:"idOrganization"`
Pinned bool `json:"pinned"`
Starred bool `json:"starred"`
URL string `json:"url"`
ShortURL string `json:"shortUrl"`
Prefs struct {
@ -42,6 +43,7 @@ type Board struct {
CanBePrivate bool `json:"canBePrivate"`
CanInvite bool `json:"canInvite"`
} `json:"prefs"`
Subscribed bool `json:"subscribed"`
LabelNames struct {
Black string `json:"black,omitempty"`
Blue string `json:"blue,omitempty"`
@ -85,7 +87,7 @@ func (b *Board) CreatedAt() time.Time {
}
// CreateBoard creates a board remote.
// Attribute currently supported as exra argument: powerUps.
// Attribute currently supported as exra argument: defaultLists, powerUps.
// Attributes currently known to be unsupported: idBoardSource, keepFromSource.
//
// API Docs: https://developers.trello.com/reference/#boardsid
@ -118,6 +120,10 @@ func (c *Client) CreateBoard(board *Board, extraArgs Arguments) error {
args["prefs_cardAging"] = board.Prefs.CardAging
}
// Expects "true" or "false"
if defaultLists, ok := extraArgs["defaultLists"]; ok {
args["defaultLists"] = defaultLists
}
// Expects one of "all", "calendar", "cardAging", "recap", or "voting".
if powerUps, ok := extraArgs["powerUps"]; ok {
args["powerUps"] = powerUps
@ -130,6 +136,12 @@ func (c *Client) CreateBoard(board *Board, extraArgs Arguments) error {
return err
}
// Update PUTs the supported board attributes remote and updates
// the struct from the returned values.
func (b *Board) Update(extraArgs Arguments) error {
return b.client.PutBoard(b, extraArgs)
}
// Delete makes a DELETE call for the receiver Board.
func (b *Board) Delete(extraArgs Arguments) error {
path := fmt.Sprintf("boards/%s", b.ID)
@ -162,6 +174,49 @@ func (m *Member) GetBoards(args Arguments) (boards []*Board, err error) {
err = m.client.Get(path, args, &boards)
for i := range boards {
boards[i].client = m.client
for j := range boards[i].Lists {
boards[i].Lists[j].client = m.client
}
}
return
}
// PutBoard PUTs a board remote. Extra arguments are currently unsupported.
//
// API Docs: https://developers.trello.com/reference#idnext
func (c *Client) PutBoard(board *Board, extraArgs Arguments) error {
path := fmt.Sprintf("boards/%s", board.ID)
args := Arguments{
"desc": board.Desc,
"name": board.Name,
"prefs/selfJoin": fmt.Sprintf("%t", board.Prefs.SelfJoin),
"prefs/cardCovers": fmt.Sprintf("%t", board.Prefs.CardCovers),
"idOrganization": board.IDOrganization,
}
if board.Prefs.Voting != "" {
args["prefs/voting"] = board.Prefs.Voting
}
if board.Prefs.PermissionLevel != "" {
args["prefs/permissionLevel"] = board.Prefs.PermissionLevel
}
if board.Prefs.Comments != "" {
args["prefs/comments"] = board.Prefs.Comments
}
if board.Prefs.Invitations != "" {
args["prefs/invitations"] = board.Prefs.Invitations
}
if board.Prefs.Background != "" {
args["prefs/background"] = board.Prefs.Background
}
if board.Prefs.CardAging != "" {
args["prefs/cardAging"] = board.Prefs.CardAging
}
err := c.Put(path, args, &board)
if err == nil {
board.client = c
}
return err
}

View File

@ -91,6 +91,7 @@ func (c *Card) CreatedAt() time.Time {
return t
}
// CustomFields returns the card's custom fields.
func (c *Card) CustomFields(boardCustomFields []*CustomField) map[string]interface{} {
@ -99,14 +100,16 @@ func (c *Card) CustomFields(boardCustomFields []*CustomField) map[string]interfa
if cfm == nil {
cfm = &(map[string]interface{}{})
// bcfOptionNames[CustomField ID] = Custom Field Name
bcfOptionNames := map[string]string{}
// bcfNames[CustomFieldItem ID] = Custom Field Name
bcfNames := map[string]string{}
// bcfOptionsMap[CustomField ID][ID of the option] = Value of the option
bcfOptionsMap := map[string]map[string]interface{}{}
for _, bcf := range boardCustomFields {
bcfOptionNames[bcf.ID] = bcf.Name
bcfNames[bcf.ID] = bcf.Name
//Options for Dropbox field
for _, cf := range bcf.Options {
// create 2nd level map when not available yet
map2, ok := bcfOptionsMap[cf.IDCustomField]
@ -120,8 +123,10 @@ func (c *Card) CustomFields(boardCustomFields []*CustomField) map[string]interfa
}
for _, cf := range c.CustomFieldItems {
name := bcfOptionNames[cf.IDCustomField]
if name, ok := bcfNames[cf.IDCustomField]; ok {
if cf.Value.Get() != nil {
(*cfm)[name] = cf.Value.Get()
} else { // Dropbox
// create 2nd level map when not available yet
map2, ok := bcfOptionsMap[cf.IDCustomField]
if !ok {
@ -133,7 +138,8 @@ func (c *Card) CustomFields(boardCustomFields []*CustomField) map[string]interfa
(*cfm)[name] = value
}
}
c.customFieldMap = cfm
}
}
}
return *cfm
}

View File

@ -6,7 +6,6 @@
package trello
import (
"bytes"
"context"
"encoding/json"
"fmt"
@ -95,22 +94,7 @@ func (c *Client) Get(path string, args Arguments, target interface{}) error {
}
req = req.WithContext(c.ctx)
resp, err := c.Client.Do(req)
if err != nil {
return errors.Wrapf(err, "HTTP request failure on %s", url)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return makeHTTPClientError(url, resp)
}
decoder := json.NewDecoder(resp.Body)
err = decoder.Decode(target)
if err != nil {
return errors.Wrapf(err, "JSON decode failed on %s", url)
}
return nil
return c.do(req, url, target)
}
// Put takes a path, Arguments, and a target interface (e.g. Board or Card).
@ -141,22 +125,7 @@ func (c *Client) Put(path string, args Arguments, target interface{}) error {
return errors.Wrapf(err, "Invalid PUT request %s", url)
}
resp, err := c.Client.Do(req)
if err != nil {
return errors.Wrapf(err, "HTTP request failure on %s", url)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return makeHTTPClientError(url, resp)
}
decoder := json.NewDecoder(resp.Body)
err = decoder.Decode(target)
if err != nil {
return errors.Wrapf(err, "JSON decode failed on %s", url)
}
return nil
return c.do(req, url, target)
}
// Post takes a path, Arguments, and a target interface (e.g. Board or Card).
@ -187,26 +156,7 @@ func (c *Client) Post(path string, args Arguments, target interface{}) error {
return errors.Wrapf(err, "Invalid POST request %s", url)
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
resp, err := c.Client.Do(req)
if err != nil {
return errors.Wrapf(err, "HTTP request failure on %s", url)
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return errors.Wrapf(err, "HTTP Read error on response for %s", url)
}
decoder := json.NewDecoder(bytes.NewBuffer(b))
err = decoder.Decode(target)
if err != nil {
return errors.Wrapf(err, "JSON decode failed on %s:\n%s", url, string(b))
}
return nil
return c.do(req, url, target)
}
// Delete takes a path, Arguments, and a target interface (e.g. Board or Card).
@ -236,24 +186,7 @@ func (c *Client) Delete(path string, args Arguments, target interface{}) error {
return errors.Wrapf(err, "Invalid DELETE request %s", url)
}
resp, err := c.Client.Do(req)
if err != nil {
return errors.Wrapf(err, "HTTP request failure on %s", url)
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return errors.Wrapf(err, "HTTP Read error on response for %s", url)
}
decoder := json.NewDecoder(bytes.NewBuffer(b))
err = decoder.Decode(target)
if err != nil {
return errors.Wrapf(err, "JSON decode failed on %s:\n%s", url, string(b))
}
return nil
return c.do(req, url, target)
}
func (c *Client) log(format string, args ...interface{}) {
@ -261,3 +194,24 @@ func (c *Client) log(format string, args ...interface{}) {
c.Logger.Debugf(format, args...)
}
}
func (c *Client) do(req *http.Request, url string, target interface{}) error {
resp, err := c.Client.Do(req)
if err != nil {
return errors.Wrapf(err, "HTTP request failure on %s", url)
}
defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode > 299 {
return makeHTTPClientError(url, resp)
}
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return errors.Wrapf(err, "HTTP Read error on response for %s", url)
}
err = json.Unmarshal(b, target)
if err != nil {
return errors.Wrapf(err, "JSON decode failed on %s:\n%s", url, string(b))
}
return nil
}

View File

@ -1,15 +1,109 @@
package trello
import "fmt"
import (
"database/sql/driver"
"encoding/json"
"fmt"
"strconv"
"time"
)
// CustomFieldItem represents the custom field items of Trello a trello card.
type CustomFieldItem struct {
ID string `json:"id"`
IDValue string `json:"idValue"`
IDCustomField string `json:"idCustomField"`
IDModel string `json:"idModel"`
ID string `json:"id,omitempty"`
Value CustomFieldValue `json:"value,omitempty"`
IDValue string `json:"idValue,omitempty"`
IDCustomField string `json:"idCustomField,omitempty"`
IDModel string `json:"idModel,omitempty"`
IDModelType string `json:"modelType,omitempty"`
}
type CustomFieldValue struct {
val interface{}
}
type cfval struct {
Text string `json:"text,omitempty"`
Number string `json:"number,omitempty"`
Date string `json:"date,omitempty"`
Checked string `json:"checked,omitempty"`
}
func NewCustomFieldValue(val interface{}) CustomFieldValue {
return CustomFieldValue{val: val}
}
const timeFmt = "2006-01-02T15:04:05Z"
func (v CustomFieldValue) Get() interface{} {
return v.val
}
func (v CustomFieldValue) String() string {
return fmt.Sprintf("%s", v.val)
}
func (v CustomFieldValue) MarshalJSON() ([]byte, error) {
val := v.val
switchVal:
switch v := val.(type) {
case driver.Valuer:
var err error
val, err = v.Value()
if err != nil {
return nil, err
}
goto switchVal
case string:
return json.Marshal(cfval{Text: v})
case int, int64:
return json.Marshal(cfval{Number: fmt.Sprintf("%d", v)})
case float64:
return json.Marshal(cfval{Number: fmt.Sprintf("%f", v)})
case bool:
if v {
return json.Marshal(cfval{Checked: "true"})
} else {
return json.Marshal(cfval{Checked: "false"})
}
case time.Time:
return json.Marshal(cfval{Date: v.Format(timeFmt)})
default:
return nil, fmt.Errorf("unsupported type")
}
}
func (v *CustomFieldValue) UnmarshalJSON(b []byte) error {
cfval := cfval{}
err := json.Unmarshal(b, &cfval)
if err != nil {
return err
}
if cfval.Text != "" {
v.val = cfval.Text
}
if cfval.Date != "" {
v.val, err = time.Parse(timeFmt, cfval.Date)
if err != nil {
return err
}
}
if cfval.Checked != "" {
v.val = cfval.Checked == "true"
}
if cfval.Number != "" {
v.val, err = strconv.Atoi(cfval.Number)
if err != nil {
v.val, err = strconv.ParseFloat(cfval.Number, 64)
if err != nil {
v.val, err = strconv.ParseFloat(cfval.Number, 32)
if err != nil {
v.val, err = strconv.ParseInt(cfval.Number, 10, 64)
if err != nil {
return fmt.Errorf("cannot convert %s to number", cfval.Number)
}
}
}
}
}
return nil
}
// CustomField represents Trello's custom fields: "extra bits of structured data
// attached to cards when our users need a bit more than what Trello provides."

View File

@ -19,6 +19,7 @@ type List struct {
IDBoard string `json:"idBoard,omitempty"`
Closed bool `json:"closed"`
Pos float32 `json:"pos,omitempty"`
Subscribed bool `json:"subscribed"`
Board *Board `json:"board,omitempty"`
Cards []*Card `json:"cards,omitempty"`
}
@ -55,7 +56,6 @@ func (b *Board) GetLists(args Arguments) (lists []*List, err error) {
return
}
// CreateList creates a list.
// Attribute currently supported as extra argument: pos.
// Attributes currently known to be unsupported: idListSource.
@ -89,3 +89,10 @@ func (c *Client) CreateList(onBoard *Board, name string, extraArgs Arguments) (l
func (b *Board) CreateList(name string, extraArgs Arguments) (list *List, err error) {
return b.client.CreateList(b, name, extraArgs)
}
// Update UPDATEs the list's attributes.
// API Docs: https://developers.trello.com/reference/#listsid-1
func (l *List) Update(args Arguments) error {
path := fmt.Sprintf("lists/%s", l.ID)
return l.client.Put(path, args, l)
}

View File

@ -61,7 +61,7 @@ func (c *Client) CreateWebhook(webhook *Webhook) error {
return err
}
// DeleteWebhook takes a webhook and deletes it
// Delete takes a webhook and deletes it
func (w *Webhook) Delete(args Arguments) error {
path := fmt.Sprintf("webhooks/%s", w.ID)
return w.client.Delete(path, Arguments{}, w)

View File

@ -14,6 +14,10 @@ linters:
- lll
- gocyclo
- dupl
- gochecknoglobals
- funlen
- godox
- wsl
linters-settings:
govet:
@ -42,3 +46,6 @@ issues:
- 'Potential file inclusion via variable'
- 'should have comment or be unexported'
- 'comment on exported var .* should be of the form'
- 'at least one file in a package should have a package comment'
- 'string literal contains the Unicode'
- 'methods on the same type should have the same receiver name'

View File

@ -2,9 +2,9 @@ sudo: false
language: go
script:
- go test -v ./...
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s v1.10.2
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s v1.20.0
- ./bin/golangci-lint run
- git clean -fdx .
after_success:
go get github.com/goreleaser/goreleaser && goreleaser
curl -sL https://git.io/goreleaser | bash && goreleaser

View File

@ -8,57 +8,68 @@ highlighted HTML, ANSI-coloured text, etc.
Chroma is based heavily on [Pygments](http://pygments.org/), and includes
translators for Pygments lexers and styles.
<a id="markdown-table-of-contents" name="table-of-contents"></a>
## Table of Contents
<!-- MarkdownTOC -->
<!-- TOC -->
1. [Supported languages](#supported-languages)
1. [Using the library](#using-the-library)
1. [Table of Contents](#table-of-contents)
2. [Supported languages](#supported-languages)
3. [Try it](#try-it)
4. [Using the library](#using-the-library)
1. [Quick start](#quick-start)
1. [Identifying the language](#identifying-the-language)
1. [Formatting the output](#formatting-the-output)
1. [The HTML formatter](#the-html-formatter)
1. [More detail](#more-detail)
2. [Identifying the language](#identifying-the-language)
3. [Formatting the output](#formatting-the-output)
4. [The HTML formatter](#the-html-formatter)
5. [More detail](#more-detail)
1. [Lexers](#lexers)
1. [Formatters](#formatters)
1. [Styles](#styles)
1. [Command-line interface](#command-line-interface)
1. [What's missing compared to Pygments?](#whats-missing-compared-to-pygments)
2. [Formatters](#formatters)
3. [Styles](#styles)
6. [Command-line interface](#command-line-interface)
7. [What's missing compared to Pygments?](#whats-missing-compared-to-pygments)
<!-- /MarkdownTOC -->
<!-- /TOC -->
<a id="markdown-supported-languages" name="supported-languages"></a>
## Supported languages
Prefix | Language
:----: | --------
A | ABNF, ActionScript, ActionScript 3, Ada, Angular2, ANTLR, ApacheConf, APL, AppleScript, Arduino, Awk
A | ABAP, ABNF, ActionScript, ActionScript 3, Ada, Angular2, ANTLR, ApacheConf, APL, AppleScript, Arduino, Awk
B | Ballerina, Base Makefile, Bash, Batchfile, BlitzBasic, BNF, Brainfuck
C | C, C#, C++, Cassandra CQL, CFEngine3, cfstatement/ColdFusion, CMake, COBOL, CSS, Cap'n Proto, Ceylon, ChaiScript, Cheetah, Clojure, CoffeeScript, Common Lisp, Coq, Crystal, Cython
D | Dart, Diff, Django/Jinja, Docker, DTD
C | C, C#, C++, Cap'n Proto, Cassandra CQL, Ceylon, CFEngine3, cfstatement, ChaiScript, Cheetah, Clojure, CMake, COBOL, CoffeeScript, Common Lisp, Coq, Crystal, CSS, Cython
D | D, Dart, Diff, Django/Jinja, Docker, DTD
E | EBNF, Elixir, Elm, EmacsLisp, Erlang
F | Factor, Fish, Forth, Fortran, FSharp
G | GAS, GDScript, GLSL, Genshi, Genshi HTML, Genshi Text, Gnuplot, Go, Go HTML Template, Go Text Template, GraphQL, Groovy
H | Handlebars, Haskell, Haxe, Hexdump, HTML, HTTP, Hy
G | GAS, GDScript, Genshi, Genshi HTML, Genshi Text, GLSL, Gnuplot, Go, Go HTML Template, Go Text Template, GraphQL, Groovy
H | Handlebars, Haskell, Haxe, HCL, Hexdump, HTML, HTTP, Hy
I | Idris, INI, Io
J | Java, JavaScript, JSON, Jsx, Julia, Jungle
J | J, Java, JavaScript, JSON, Julia, Jungle
K | Kotlin
L | Lighttpd configuration file, LLVM, Lua
M | Mako, Markdown, Mason, Mathematica, MiniZinc, Modula-2, MonkeyC, MorrowindScript, Myghty, MySQL
M | Mako, markdown, Mason, Mathematica, Matlab, MiniZinc, Modula-2, MonkeyC, MorrowindScript, Myghty, MySQL
N | NASM, Newspeak, Nginx configuration file, Nim, Nix
O | Objective-C, OCaml, Octave, OpenSCAD, Org Mode
P | PacmanConf, Perl, PHP, Pig, PkgConfig, Plaintext, PL/pgSQL, PostgreSQL SQL dialect, PostScript, POVRay, PowerShell, Prolog, Protocol Buffer, Puppet, Python, Python 3
P | PacmanConf, Perl, PHP, Pig, PkgConfig, PL/pgSQL, plaintext, PostgreSQL SQL dialect, PostScript, POVRay, PowerShell, Prolog, Protocol Buffer, Puppet, Python, Python 3
Q | QBasic
R | R, Racket, Ragel, reg, reStructuredText, Rexx, Ruby, Rust
S | Sass, Scala, Scheme, Scilab, SCSS, Smalltalk, Smarty, Snobol, Solidity, SPARQL, SQL, SquidConf, Swift, systemd, Systemverilog
T | TASM, Tcl, Tcsh, Termcap, Terminfo, Terraform, TeX, Thrift, TOML, TradingView, Transact-SQL, Turtle, Twig, TypeScript, TypoScript, TypoScriptCssData, TypoScriptHtmlData
V | verilog, VHDL, VimL
R | R, Racket, Ragel, react, reg, reStructuredText, Rexx, Ruby, Rust
S | Sass, Scala, Scheme, Scilab, SCSS, Smalltalk, Smarty, Snobol, Solidity, SPARQL, SQL, SquidConf, Swift, SYSTEMD, systemverilog
T | TASM, Tcl, Tcsh, Termcap, Terminfo, Terraform, TeX, Thrift, TOML, TradingView, Transact-SQL, Turing, Turtle, Twig, TypeScript, TypoScript, TypoScriptCssData, TypoScriptHtmlData
V | VB.net, verilog, VHDL, VimL, vue
W | WDTE
X | XML, Xorg
Y | YAML
_I will attempt to keep this section up to date, but an authoritative list can be
displayed with `chroma --list`._
<a id="markdown-try-it" name="try-it"></a>
## Try it
Try out various languages and styles on the [Chroma Playground](https://swapoff.org/chroma/playground/).
<a id="markdown-using-the-library" name="using-the-library"></a>
## Using the library
Chroma, like Pygments, has the concepts of
@ -79,6 +90,7 @@ In all cases, if a lexer, formatter or style can not be determined, `nil` will
be returned. In this situation you may want to default to the `Fallback`
value in each respective package, which provides sane defaults.
<a id="markdown-quick-start" name="quick-start"></a>
### Quick start
A convenience function exists that can be used to simply format some source
@ -88,6 +100,7 @@ text, without any effort:
err := quick.Highlight(os.Stdout, someSourceCode, "go", "html", "monokai")
```
<a id="markdown-identifying-the-language" name="identifying-the-language"></a>
### Identifying the language
To highlight code, you'll first have to identify what language the code is
@ -127,6 +140,7 @@ token types into a single token:
lexer = chroma.Coalesce(lexer)
```
<a id="markdown-formatting-the-output" name="formatting-the-output"></a>
### Formatting the output
Once a language is identified you will need to pick a formatter and a style (theme).
@ -155,6 +169,7 @@ And finally, format the tokens from the iterator:
err := formatter.Format(w, style, iterator)
```
<a id="markdown-the-html-formatter" name="the-html-formatter"></a>
### The HTML formatter
By default the `html` registered formatter generates standalone HTML with
@ -178,8 +193,10 @@ formatter := html.New(html.WithClasses())
err := formatter.WriteCSS(w, style)
```
<a id="markdown-more-detail" name="more-detail"></a>
## More detail
<a id="markdown-lexers" name="lexers"></a>
### Lexers
See the [Pygments documentation](http://pygments.org/docs/lexerdevelopment/)
@ -200,6 +217,7 @@ python3 ~/Projects/chroma/_tools/pygments2chroma.py \
See notes in [pygments-lexers.go](https://github.com/alecthomas/chroma/blob/master/pygments-lexers.txt)
for a list of lexers, and notes on some of the issues importing them.
<a id="markdown-formatters" name="formatters"></a>
### Formatters
Chroma supports HTML output, as well as terminal output in 8 colour, 256 colour, and true-colour.
@ -207,6 +225,7 @@ Chroma supports HTML output, as well as terminal output in 8 colour, 256 colour,
A `noop` formatter is included that outputs the token text only, and a `tokens`
formatter outputs raw tokens. The latter is useful for debugging lexers.
<a id="markdown-styles" name="styles"></a>
### Styles
Chroma styles use the [same syntax](http://pygments.org/docs/styles/) as Pygments.
@ -225,6 +244,7 @@ Also, token types in a style file are hierarchical. For instance, when `CommentS
For a quick overview of the available styles and how they look, check out the [Chroma Style Gallery](https://xyproto.github.io/splash/docs/).
<a id="markdown-command-line-interface" name="command-line-interface"></a>
## Command-line interface
A command-line interface to Chroma is included. It can be installed with:
@ -233,6 +253,7 @@ A command-line interface to Chroma is included. It can be installed with:
go get -u github.com/alecthomas/chroma/cmd/chroma
```
<a id="markdown-whats-missing-compared-to-pygments" name="whats-missing-compared-to-pygments"></a>
## What's missing compared to Pygments?
- Quite a few lexers, for various reasons (pull-requests welcome):

View File

@ -34,7 +34,7 @@ type insertion struct {
tokens []Token
}
func (d *delegatingLexer) Tokenise(options *TokeniseOptions, text string) (Iterator, error) {
func (d *delegatingLexer) Tokenise(options *TokeniseOptions, text string) (Iterator, error) { // nolint: gocognit
tokens, err := Tokenise(Coalesce(d.language), options, text)
if err != nil {
return nil, err

View File

@ -6,6 +6,7 @@ import (
"github.com/alecthomas/chroma"
"github.com/alecthomas/chroma/formatters/html"
"github.com/alecthomas/chroma/formatters/svg"
)
var (
@ -19,7 +20,8 @@ var (
return nil
}))
// Default HTML formatter outputs self-contained HTML.
htmlFull = Register("html", html.New(html.Standalone(), html.WithClasses())) // nolint
htmlFull = Register("html", html.New(html.Standalone(true), html.WithClasses(true))) // nolint
SVG = Register("svg", svg.New(svg.EmbedFont("Liberation Mono", svg.FontLiberationMono, svg.WOFF)))
)
// Fallback formatter.

View File

@ -14,32 +14,47 @@ import (
type Option func(f *Formatter)
// Standalone configures the HTML formatter for generating a standalone HTML document.
func Standalone() Option { return func(f *Formatter) { f.standalone = true } }
func Standalone(b bool) Option { return func(f *Formatter) { f.standalone = b } }
// ClassPrefix sets the CSS class prefix.
func ClassPrefix(prefix string) Option { return func(f *Formatter) { f.prefix = prefix } }
// WithClasses emits HTML using CSS classes, rather than inline styles.
func WithClasses() Option { return func(f *Formatter) { f.Classes = true } }
func WithClasses(b bool) Option { return func(f *Formatter) { f.Classes = b } }
// TabWidth sets the number of characters for a tab. Defaults to 8.
func TabWidth(width int) Option { return func(f *Formatter) { f.tabWidth = width } }
// PreventSurroundingPre prevents the surrounding pre tags around the generated code
func PreventSurroundingPre() Option { return func(f *Formatter) { f.preventSurroundingPre = true } }
// PreventSurroundingPre prevents the surrounding pre tags around the generated code.
func PreventSurroundingPre(b bool) Option {
return func(f *Formatter) {
if b {
f.preWrapper = nopPreWrapper
} else {
f.preWrapper = defaultPreWrapper
}
}
}
// WithPreWrapper allows control of the surrounding pre tags.
func WithPreWrapper(wrapper PreWrapper) Option {
return func(f *Formatter) {
f.preWrapper = wrapper
}
}
// WithLineNumbers formats output with line numbers.
func WithLineNumbers() Option {
func WithLineNumbers(b bool) Option {
return func(f *Formatter) {
f.lineNumbers = true
f.lineNumbers = b
}
}
// LineNumbersInTable will, when combined with WithLineNumbers, separate the line numbers
// and code in table td's, which make them copy-and-paste friendly.
func LineNumbersInTable() Option {
func LineNumbersInTable(b bool) Option {
return func(f *Formatter) {
f.lineNumbersInTable = true
f.lineNumbersInTable = b
}
}
@ -64,6 +79,7 @@ func BaseLineNumber(n int) Option {
func New(options ...Option) *Formatter {
f := &Formatter{
baseLineNumber: 1,
preWrapper: defaultPreWrapper,
}
for _, option := range options {
option(f)
@ -71,12 +87,52 @@ func New(options ...Option) *Formatter {
return f
}
// PreWrapper defines the operations supported in WithPreWrapper.
type PreWrapper interface {
// Start is called to write a start <pre> element.
// The code flag tells whether this block surrounds
// highlighted code. This will be false when surrounding
// line numbers.
Start(code bool, styleAttr string) string
// End is called to write the end </pre> element.
End(code bool) string
}
type preWrapper struct {
start func(code bool, styleAttr string) string
end func(code bool) string
}
func (p preWrapper) Start(code bool, styleAttr string) string {
return p.start(code, styleAttr)
}
func (p preWrapper) End(code bool) string {
return p.end(code)
}
var (
nopPreWrapper = preWrapper{
start: func(code bool, styleAttr string) string { return "" },
end: func(code bool) string { return "" },
}
defaultPreWrapper = preWrapper{
start: func(code bool, styleAttr string) string {
return fmt.Sprintf("<pre%s>", styleAttr)
},
end: func(code bool) string {
return "</pre>"
},
}
)
// Formatter that generates HTML.
type Formatter struct {
standalone bool
prefix string
Classes bool // Exported field to detect when classes are being used
preventSurroundingPre bool
preWrapper PreWrapper
tabWidth int
lineNumbers bool
lineNumbersInTable bool
@ -91,11 +147,6 @@ func (h highlightRanges) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h highlightRanges) Less(i, j int) bool { return h[i][0] < h[j][0] }
func (f *Formatter) Format(w io.Writer, style *chroma.Style, iterator chroma.Iterator) (err error) {
defer func() {
if perr := recover(); perr != nil {
err = perr.(error)
}
}()
return f.writeHTML(w, style, iterator.Tokens())
}
@ -134,9 +185,7 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
fmt.Fprintf(w, "<div%s>\n", f.styleAttr(css, chroma.Background))
fmt.Fprintf(w, "<table%s><tr>", f.styleAttr(css, chroma.LineTable))
fmt.Fprintf(w, "<td%s>\n", f.styleAttr(css, chroma.LineTableTD))
if !f.preventSurroundingPre {
fmt.Fprintf(w, "<pre%s>", f.styleAttr(css, chroma.Background))
}
fmt.Fprintf(w, f.preWrapper.Start(false, f.styleAttr(css, chroma.Background)))
for index := range lines {
line := f.baseLineNumber + index
highlight, next := f.shouldHighlight(highlightIndex, line)
@ -153,16 +202,13 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
fmt.Fprintf(w, "</span>")
}
}
if !f.preventSurroundingPre {
fmt.Fprint(w, "</pre>")
}
fmt.Fprint(w, f.preWrapper.End(false))
fmt.Fprint(w, "</td>\n")
fmt.Fprintf(w, "<td%s>\n", f.styleAttr(css, chroma.LineTableTD))
fmt.Fprintf(w, "<td%s>\n", f.styleAttr(css, chroma.LineTableTD, "width:100%"))
}
if !f.preventSurroundingPre {
fmt.Fprintf(w, "<pre%s>", f.styleAttr(css, chroma.Background))
}
fmt.Fprintf(w, f.preWrapper.Start(true, f.styleAttr(css, chroma.Background)))
highlightIndex = 0
for index, tokens := range lines {
// 1-based line number.
@ -192,9 +238,7 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
}
}
if !f.preventSurroundingPre {
fmt.Fprint(w, "</pre>")
}
fmt.Fprintf(w, f.preWrapper.End(true))
if wrapInTable {
fmt.Fprint(w, "</td></tr></table>\n")
@ -240,7 +284,7 @@ func (f *Formatter) class(t chroma.TokenType) string {
return ""
}
func (f *Formatter) styleAttr(styles map[chroma.TokenType]string, tt chroma.TokenType) string {
func (f *Formatter) styleAttr(styles map[chroma.TokenType]string, tt chroma.TokenType, extraCSS ...string) string {
if f.Classes {
cls := f.class(tt)
if cls == "" {
@ -257,7 +301,9 @@ func (f *Formatter) styleAttr(styles map[chroma.TokenType]string, tt chroma.Toke
}
}
}
return fmt.Sprintf(` style="%s"`, styles[tt])
css := []string{styles[tt]}
css = append(css, extraCSS...)
return fmt.Sprintf(` style="%s"`, strings.Join(css, ";"))
}
func (f *Formatter) tabWidthStyle() string {

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,222 @@
// Package svg contains an SVG formatter.
package svg
import (
"encoding/base64"
"errors"
"fmt"
"io"
"io/ioutil"
"path"
"strings"
"github.com/alecthomas/chroma"
)
// Option sets an option of the SVG formatter.
type Option func(f *Formatter)
// FontFamily sets the font-family.
func FontFamily(fontFamily string) Option { return func(f *Formatter) { f.fontFamily = fontFamily } }
// EmbedFontFile embeds given font file
func EmbedFontFile(fontFamily string, fileName string) (option Option, err error) {
var format FontFormat
switch path.Ext(fileName) {
case ".woff":
format = WOFF
case ".woff2":
format = WOFF2
case ".ttf":
format = TRUETYPE
default:
return nil, errors.New("unexpected font file suffix")
}
var content []byte
if content, err = ioutil.ReadFile(fileName); err == nil {
option = EmbedFont(fontFamily, base64.StdEncoding.EncodeToString(content), format)
}
return
}
// EmbedFont embeds given base64 encoded font
func EmbedFont(fontFamily string, font string, format FontFormat) Option {
return func(f *Formatter) { f.fontFamily = fontFamily; f.embeddedFont = font; f.fontFormat = format }
}
// New SVG formatter.
func New(options ...Option) *Formatter {
f := &Formatter{fontFamily: "Consolas, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace"}
for _, option := range options {
option(f)
}
return f
}
// Formatter that generates SVG.
type Formatter struct {
fontFamily string
embeddedFont string
fontFormat FontFormat
}
func (f *Formatter) Format(w io.Writer, style *chroma.Style, iterator chroma.Iterator) (err error) {
f.writeSVG(w, style, iterator.Tokens())
return err
}
var svgEscaper = strings.NewReplacer(
`&`, "&amp;",
`<`, "&lt;",
`>`, "&gt;",
`"`, "&quot;",
` `, "&#160;",
` `, "&#160;&#160;&#160;&#160;",
)
// EscapeString escapes special characters.
func escapeString(s string) string {
return svgEscaper.Replace(s)
}
func (f *Formatter) writeSVG(w io.Writer, style *chroma.Style, tokens []chroma.Token) { // nolint: gocyclo
svgStyles := f.styleToSVG(style)
lines := chroma.SplitTokensIntoLines(tokens)
fmt.Fprint(w, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
fmt.Fprint(w, "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\n")
fmt.Fprintf(w, "<svg width=\"%dpx\" height=\"%dpx\" xmlns=\"http://www.w3.org/2000/svg\">\n", 8*maxLineWidth(lines), 10+int(16.8*float64(len(lines)+1)))
if f.embeddedFont != "" {
f.writeFontStyle(w)
}
fmt.Fprintf(w, "<rect width=\"100%%\" height=\"100%%\" fill=\"%s\"/>\n", style.Get(chroma.Background).Background.String())
fmt.Fprintf(w, "<g font-family=\"%s\" font-size=\"14px\" fill=\"%s\">\n", f.fontFamily, style.Get(chroma.Text).Colour.String())
f.writeTokenBackgrounds(w, lines, style)
for index, tokens := range lines {
fmt.Fprintf(w, "<text x=\"0\" y=\"%fem\" xml:space=\"preserve\">", 1.2*float64(index+1))
for _, token := range tokens {
text := escapeString(token.String())
attr := f.styleAttr(svgStyles, token.Type)
if attr != "" {
text = fmt.Sprintf("<tspan %s>%s</tspan>", attr, text)
}
fmt.Fprint(w, text)
}
fmt.Fprint(w, "</text>")
}
fmt.Fprint(w, "\n</g>\n")
fmt.Fprint(w, "</svg>\n")
}
func maxLineWidth(lines [][]chroma.Token) int {
maxWidth := 0
for _, tokens := range lines {
length := 0
for _, token := range tokens {
length += len(strings.Replace(token.String(), ` `, " ", -1))
}
if length > maxWidth {
maxWidth = length
}
}
return maxWidth
}
// There is no background attribute for text in SVG so simply calculate the position and text
// of tokens with a background color that differs from the default and add a rectangle for each before
// adding the token.
func (f *Formatter) writeTokenBackgrounds(w io.Writer, lines [][]chroma.Token, style *chroma.Style) {
for index, tokens := range lines {
lineLength := 0
for _, token := range tokens {
length := len(strings.Replace(token.String(), ` `, " ", -1))
tokenBackground := style.Get(token.Type).Background
if tokenBackground.IsSet() && tokenBackground != style.Get(chroma.Background).Background {
fmt.Fprintf(w, "<rect id=\"%s\" x=\"%dch\" y=\"%fem\" width=\"%dch\" height=\"1.2em\" fill=\"%s\" />\n", escapeString(token.String()), lineLength, 1.2*float64(index)+0.25, length, style.Get(token.Type).Background.String())
}
lineLength += length
}
}
}
type FontFormat int
// https://transfonter.org/formats
const (
WOFF FontFormat = iota
WOFF2
TRUETYPE
)
var fontFormats = [...]string{
"woff",
"woff2",
"truetype",
}
func (f *Formatter) writeFontStyle(w io.Writer) {
fmt.Fprintf(w, `<style>
@font-face {
font-family: '%s';
src: url(data:application/x-font-%s;charset=utf-8;base64,%s) format('%s');'
font-weight: normal;
font-style: normal;
}
</style>`, f.fontFamily, fontFormats[f.fontFormat], f.embeddedFont, fontFormats[f.fontFormat])
}
func (f *Formatter) styleAttr(styles map[chroma.TokenType]string, tt chroma.TokenType) string {
if _, ok := styles[tt]; !ok {
tt = tt.SubCategory()
if _, ok := styles[tt]; !ok {
tt = tt.Category()
if _, ok := styles[tt]; !ok {
return ""
}
}
}
return styles[tt]
}
func (f *Formatter) styleToSVG(style *chroma.Style) map[chroma.TokenType]string {
converted := map[chroma.TokenType]string{}
bg := style.Get(chroma.Background)
// Convert the style.
for t := range chroma.StandardTypes {
entry := style.Get(t)
if t != chroma.Background {
entry = entry.Sub(bg)
}
if entry.IsZero() {
continue
}
converted[t] = StyleEntryToSVG(entry)
}
return converted
}
// StyleEntryToSVG converts a chroma.StyleEntry to SVG attributes.
func StyleEntryToSVG(e chroma.StyleEntry) string {
var styles []string
if e.Colour.IsSet() {
styles = append(styles, "fill=\""+e.Colour.String()+"\"")
}
if e.Bold == chroma.Yes {
styles = append(styles, "font-weight=\"bold\"")
}
if e.Italic == chroma.Yes {
styles = append(styles, "font-style=\"italic\"")
}
if e.Underline == chroma.Yes {
styles = append(styles, "text-decoration=\"underline\"")
}
return strings.Join(styles, " ")
}

View File

@ -174,6 +174,9 @@ func entryToEscapeSequence(table *ttyTable, entry chroma.StyleEntry) string {
if entry.Underline == chroma.Yes {
out += "\033[4m"
}
if entry.Italic == chroma.Yes {
out += "\033[3m"
}
if entry.Colour.IsSet() {
out += table.foreground[findClosest(table, entry.Colour)]
}
@ -197,6 +200,7 @@ func findClosest(table *ttyTable, seeking chroma.Colour) chroma.Colour {
}
func styleToEscapeSequence(table *ttyTable, style *chroma.Style) map[chroma.TokenType]string {
style = clearBackground(style)
out := map[chroma.TokenType]string{}
for _, ttype := range style.Types() {
entry := style.Get(ttype)
@ -205,16 +209,22 @@ func styleToEscapeSequence(table *ttyTable, style *chroma.Style) map[chroma.Toke
return out
}
// Clear the background colour.
func clearBackground(style *chroma.Style) *chroma.Style {
builder := style.Builder()
bg := builder.Get(chroma.Background)
bg.Background = 0
bg.NoInherit = true
builder.AddEntry(chroma.Background, bg)
style, _ = builder.Build()
return style
}
type indexedTTYFormatter struct {
table *ttyTable
}
func (c *indexedTTYFormatter) Format(w io.Writer, style *chroma.Style, it chroma.Iterator) (err error) {
defer func() {
if perr := recover(); perr != nil {
err = perr.(error)
}
}()
theme := styleToEscapeSequence(c.table, style)
for token := it(); token != chroma.EOF; token = it() {
// TODO: Cache token lookups?

View File

@ -11,6 +11,7 @@ import (
var TTY16m = Register("terminal16m", chroma.FormatterFunc(trueColourFormatter))
func trueColourFormatter(w io.Writer, style *chroma.Style, it chroma.Iterator) error {
style = clearBackground(style)
for token := it(); token != chroma.EOF; token = it() {
entry := style.Get(token.Type)
if !entry.IsZero() {
@ -21,6 +22,9 @@ func trueColourFormatter(w io.Writer, style *chroma.Style, it chroma.Iterator) e
if entry.Underline == chroma.Yes {
out += "\033[4m"
}
if entry.Italic == chroma.Yes {
out += "\033[3m"
}
if entry.Colour.IsSet() {
out += fmt.Sprintf("\033[38;2;%d;%d;%dm", entry.Colour.Red(), entry.Colour.Green(), entry.Colour.Blue())
}

View File

@ -1,14 +1,24 @@
module github.com/alecthomas/chroma
require (
github.com/GeertJohan/go.rice v1.0.0
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 // indirect
github.com/alecthomas/kong v0.1.15
github.com/alecthomas/kong v0.2.1-0.20190708041108-0548c6b1afae
github.com/alecthomas/kong-hcl v0.1.8-0.20190615233001-b21fea9723c8
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 // indirect
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964
github.com/dlclark/regexp2 v1.1.6
github.com/gorilla/csrf v1.6.0
github.com/gorilla/handlers v1.4.1
github.com/gorilla/mux v1.7.3
github.com/mattn/go-colorable v0.0.9
github.com/mattn/go-isatty v0.0.4
github.com/sergi/go-diff v1.0.0 // indirect
github.com/stretchr/testify v1.3.0 // indirect
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35 // indirect
)
replace github.com/GeertJohan/go.rice => github.com/alecthomas/go.rice v1.0.1-0.20190719113735-961b99d742e7
go 1.13

View File

@ -1,26 +1,58 @@
github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0=
github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U=
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI=
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 h1:JHZL0hZKJ1VENNfmXvHbgYlbUOvpzYzvy2aZU5gXVeo=
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0=
github.com/alecthomas/kong v0.1.15 h1:IWBg+KrLvoHBicD50OzMI8fKjrtAa1okMR9g38HVM/s=
github.com/alecthomas/kong v0.1.15/go.mod h1:0m2VYms8rH0qbCqVB2gvGHk74bqLIq0HXjCs5bNbNQU=
github.com/alecthomas/go.rice v1.0.1-0.20190719113735-961b99d742e7 h1:0cMlP9evwgTzs5JUe2C/3rLttYjmRm0kbz9fdGBIV1E=
github.com/alecthomas/go.rice v1.0.1-0.20190719113735-961b99d742e7/go.mod h1:af5vUNlDNkCjOZeSGFgIJxDje9qdjsO6hshx0gTmZt4=
github.com/alecthomas/kong v0.1.17-0.20190424132513-439c674f7ae0/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI=
github.com/alecthomas/kong v0.2.1-0.20190708041108-0548c6b1afae h1:C4Q9m+oXOxcSWwYk9XzzafY2xAVAaeubZbUHJkw3PlY=
github.com/alecthomas/kong v0.2.1-0.20190708041108-0548c6b1afae/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI=
github.com/alecthomas/kong-hcl v0.1.8-0.20190615233001-b21fea9723c8 h1:atLL+K8Hg0e8863K2X+k7qu+xz3M2a/mWFIACAPf55M=
github.com/alecthomas/kong-hcl v0.1.8-0.20190615233001-b21fea9723c8/go.mod h1:MRgZdU3vrFd05IQ89AxUZ0aYdF39BYoNFa324SodPCA=
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 h1:p9Sln00KOTlrYkxI1zYWl1QLnEqAqEARBEYa8FQnQcY=
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
github.com/daaku/go.zipexe v1.0.0 h1:VSOgZtH418pH9L16hC/JrgSNJbbAL26pj7lmD1+CGdY=
github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dlclark/regexp2 v1.1.6 h1:CqB4MjHw0MFCDj+PHHjiESmHX+N7t0tJzKvC6M97BRg=
github.com/dlclark/regexp2 v1.1.6/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/gorilla/csrf v1.6.0 h1:60oN1cFdncCE8tjwQ3QEkFND5k37lQPcRjnlvm7CIJ0=
github.com/gorilla/csrf v1.6.0/go.mod h1:7tSf8kmjNYr7IWDCYhd3U8Ck34iQ/Yw5CJu7bAkHEGI=
github.com/gorilla/handlers v1.4.1 h1:BHvcRGJe/TrL+OqFxoKQGddTgeibiOjaBssV5a/N9sw=
github.com/gorilla/handlers v1.4.1/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/nkovacs/streamquote v1.0.0/go.mod h1:BN+NaZ2CmdKqUuTUXUEm9j95B2TRbpOWpxbJYzzgUsc=
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35 h1:YAFjXN64LMvktoUZH9zgY4lGc/msGN7HQfoSuKCgaDU=
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=

View File

@ -7,13 +7,31 @@ that its output matches `<name>.exported`.
Run the tests as normal:
```go
go run ./lexers
go test ./lexers
```
## Updating the existing tests
## Update existing tests
When you add a new test data file (`*.actual`), you need to regenerate all tests. That's how Chroma creates the `*.expected` test file based on the corresponding lexer.
You can regenerate all the test outputs
To regenerate all tests, type in your terminal:
```go
RECORD=true go test ./lexers
```
This first sets the `RECORD` environment variable to `true`. Then it runs `go test` on the `./lexers` directory of the Chroma project.
(That environment variable tells Chroma it needs to output test data. After running `go test ./lexers` you can remove or reset that variable.)
### Windows users
Windows users will find that the `RECORD=true go test ./lexers` command fails in both the standard command prompt terminal and in PowerShell.
Instead we have to perform both steps separately:
- Set the `RECORD` environment variable to `true`.
+ In the regular command prompt window, the `set` command sets an environment variable for the current session: `set RECORD=true`. See [this page](https://superuser.com/questions/212150/how-to-set-env-variable-in-windows-cmd-line) for more.
+ In PowerShell, you can use the `$env:RECORD = 'true'` command for that. See [this article](https://mcpmag.com/articles/2019/03/28/environment-variables-in-powershell.aspx) for more.
+ You can also make a persistent environment variable by hand in the Windows computer settings. See [this article](https://www.computerhope.com/issues/ch000549.htm) for how.
- When the environment variable is set, run `go tests ./lexers`.
Chroma will now regenerate the test files and print its results to the console window.

56
vendor/github.com/alecthomas/chroma/lexers/a/abap.go generated vendored Normal file
View File

@ -0,0 +1,56 @@
package a
import (
. "github.com/alecthomas/chroma" // nolint
"github.com/alecthomas/chroma/lexers/internal"
)
// ABAP lexer.
var Abap = internal.Register(MustNewLexer(
&Config{
Name: "ABAP",
Aliases: []string{"abap"},
Filenames: []string{"*.abap", "*.ABAP"},
MimeTypes: []string{"text/x-abap"},
CaseInsensitive: true,
},
Rules{
"common": {
{`\s+`, Text, nil},
{`^\*.*$`, CommentSingle, nil},
{`\".*?\n`, CommentSingle, nil},
{`##\w+`, CommentSpecial, nil},
},
"variable-names": {
{`<\S+>`, NameVariable, nil},
{`\w[\w~]*(?:(\[\])|->\*)?`, NameVariable, nil},
},
"root": {
Include("common"),
{`CALL\s+(?:BADI|CUSTOMER-FUNCTION|FUNCTION)`, Keyword, nil},
{`(CALL\s+(?:DIALOG|SCREEN|SUBSCREEN|SELECTION-SCREEN|TRANSACTION|TRANSFORMATION))\b`, Keyword, nil},
{`(FORM|PERFORM)(\s+)(\w+)`, ByGroups(Keyword, Text, NameFunction), nil},
{`(PERFORM)(\s+)(\()(\w+)(\))`, ByGroups(Keyword, Text, Punctuation, NameVariable, Punctuation), nil},
{`(MODULE)(\s+)(\S+)(\s+)(INPUT|OUTPUT)`, ByGroups(Keyword, Text, NameFunction, Text, Keyword), nil},
{`(METHOD)(\s+)([\w~]+)`, ByGroups(Keyword, Text, NameFunction), nil},
{`(\s+)([\w\-]+)([=\-]>)([\w\-~]+)`, ByGroups(Text, NameVariable, Operator, NameFunction), nil},
{`(?<=(=|-)>)([\w\-~]+)(?=\()`, NameFunction, nil},
{`(TEXT)(-)(\d{3})`, ByGroups(Keyword, Punctuation, LiteralNumberInteger), nil},
{`(TEXT)(-)(\w{3})`, ByGroups(Keyword, Punctuation, NameVariable), nil},
{`(ADD-CORRESPONDING|AUTHORITY-CHECK|CLASS-DATA|CLASS-EVENTS|CLASS-METHODS|CLASS-POOL|DELETE-ADJACENT|DIVIDE-CORRESPONDING|EDITOR-CALL|ENHANCEMENT-POINT|ENHANCEMENT-SECTION|EXIT-COMMAND|FIELD-GROUPS|FIELD-SYMBOLS|FUNCTION-POOL|INTERFACE-POOL|INVERTED-DATE|LOAD-OF-PROGRAM|LOG-POINT|MESSAGE-ID|MOVE-CORRESPONDING|MULTIPLY-CORRESPONDING|NEW-LINE|NEW-PAGE|NEW-SECTION|NO-EXTENSION|OUTPUT-LENGTH|PRINT-CONTROL|SELECT-OPTIONS|START-OF-SELECTION|SUBTRACT-CORRESPONDING|SYNTAX-CHECK|SYSTEM-EXCEPTIONS|TYPE-POOL|TYPE-POOLS|NO-DISPLAY)\b`, Keyword, nil},
{`(?<![-\>])(CREATE\s+(PUBLIC|PRIVATE|DATA|OBJECT)|(PUBLIC|PRIVATE|PROTECTED)\s+SECTION|(TYPE|LIKE)\s+((LINE\s+OF|REF\s+TO|(SORTED|STANDARD|HASHED)\s+TABLE\s+OF))?|FROM\s+(DATABASE|MEMORY)|CALL\s+METHOD|(GROUP|ORDER) BY|HAVING|SEPARATED BY|GET\s+(BADI|BIT|CURSOR|DATASET|LOCALE|PARAMETER|PF-STATUS|(PROPERTY|REFERENCE)\s+OF|RUN\s+TIME|TIME\s+(STAMP)?)?|SET\s+(BIT|BLANK\s+LINES|COUNTRY|CURSOR|DATASET|EXTENDED\s+CHECK|HANDLER|HOLD\s+DATA|LANGUAGE|LEFT\s+SCROLL-BOUNDARY|LOCALE|MARGIN|PARAMETER|PF-STATUS|PROPERTY\s+OF|RUN\s+TIME\s+(ANALYZER|CLOCK\s+RESOLUTION)|SCREEN|TITLEBAR|UPADTE\s+TASK\s+LOCAL|USER-COMMAND)|CONVERT\s+((INVERTED-)?DATE|TIME|TIME\s+STAMP|TEXT)|(CLOSE|OPEN)\s+(DATASET|CURSOR)|(TO|FROM)\s+(DATA BUFFER|INTERNAL TABLE|MEMORY ID|DATABASE|SHARED\s+(MEMORY|BUFFER))|DESCRIBE\s+(DISTANCE\s+BETWEEN|FIELD|LIST|TABLE)|FREE\s(MEMORY|OBJECT)?|PROCESS\s+(BEFORE\s+OUTPUT|AFTER\s+INPUT|ON\s+(VALUE-REQUEST|HELP-REQUEST))|AT\s+(LINE-SELECTION|USER-COMMAND|END\s+OF|NEW)|AT\s+SELECTION-SCREEN(\s+(ON(\s+(BLOCK|(HELP|VALUE)-REQUEST\s+FOR|END\s+OF|RADIOBUTTON\s+GROUP))?|OUTPUT))?|SELECTION-SCREEN:?\s+((BEGIN|END)\s+OF\s+((TABBED\s+)?BLOCK|LINE|SCREEN)|COMMENT|FUNCTION\s+KEY|INCLUDE\s+BLOCKS|POSITION|PUSHBUTTON|SKIP|ULINE)|LEAVE\s+(LIST-PROCESSING|PROGRAM|SCREEN|TO LIST-PROCESSING|TO TRANSACTION)(ENDING|STARTING)\s+AT|FORMAT\s+(COLOR|INTENSIFIED|INVERSE|HOTSPOT|INPUT|FRAMES|RESET)|AS\s+(CHECKBOX|SUBSCREEN|WINDOW)|WITH\s+(((NON-)?UNIQUE)?\s+KEY|FRAME)|(BEGIN|END)\s+OF|DELETE(\s+ADJACENT\s+DUPLICATES\sFROM)?|COMPARING(\s+ALL\s+FIELDS)?|(INSERT|APPEND)(\s+INITIAL\s+LINE\s+(IN)?TO|\s+LINES\s+OF)?|IN\s+((BYTE|CHARACTER)\s+MODE|PROGRAM)|END-OF-(DEFINITION|PAGE|SELECTION)|WITH\s+FRAME(\s+TITLE)|(REPLACE|FIND)\s+((FIRST|ALL)\s+OCCURRENCES?\s+OF\s+)?(SUBSTRING|REGEX)?|MATCH\s+(LENGTH|COUNT|LINE|OFFSET)|(RESPECTING|IGNORING)\s+CASE|IN\s+UPDATE\s+TASK|(SOURCE|RESULT)\s+(XML)?|REFERENCE\s+INTO|AND\s+(MARK|RETURN)|CLIENT\s+SPECIFIED|CORRESPONDING\s+FIELDS\s+OF|IF\s+FOUND|FOR\s+EVENT|INHERITING\s+FROM|LEAVE\s+TO\s+SCREEN|LOOP\s+AT\s+(SCREEN)?|LOWER\s+CASE|MATCHCODE\s+OBJECT|MODIF\s+ID|MODIFY\s+SCREEN|NESTING\s+LEVEL|NO\s+INTERVALS|OF\s+STRUCTURE|RADIOBUTTON\s+GROUP|RANGE\s+OF|REF\s+TO|SUPPRESS DIALOG|TABLE\s+OF|UPPER\s+CASE|TRANSPORTING\s+NO\s+FIELDS|VALUE\s+CHECK|VISIBLE\s+LENGTH|HEADER\s+LINE|COMMON\s+PART)\b`, Keyword, nil},
{`(^|(?<=(\s|\.)))(ABBREVIATED|ABSTRACT|ADD|ALIASES|ALIGN|ALPHA|ASSERT|AS|ASSIGN(ING)?|AT(\s+FIRST)?|BACK|BLOCK|BREAK-POINT|CASE|CATCH|CHANGING|CHECK|CLASS|CLEAR|COLLECT|COLOR|COMMIT|CREATE|COMMUNICATION|COMPONENTS?|COMPUTE|CONCATENATE|CONDENSE|CONSTANTS|CONTEXTS|CONTINUE|CONTROLS|COUNTRY|CURRENCY|DATA|DATE|DECIMALS|DEFAULT|DEFINE|DEFINITION|DEFERRED|DEMAND|DETAIL|DIRECTORY|DIVIDE|DO|DUMMY|ELSE(IF)?|ENDAT|ENDCASE|ENDCATCH|ENDCLASS|ENDDO|ENDFORM|ENDFUNCTION|ENDIF|ENDINTERFACE|ENDLOOP|ENDMETHOD|ENDMODULE|ENDSELECT|ENDTRY|ENDWHILE|ENHANCEMENT|EVENTS|EXACT|EXCEPTIONS?|EXIT|EXPONENT|EXPORT|EXPORTING|EXTRACT|FETCH|FIELDS?|FOR|FORM|FORMAT|FREE|FROM|FUNCTION|HIDE|ID|IF|IMPORT|IMPLEMENTATION|IMPORTING|IN|INCLUDE|INCLUDING|INDEX|INFOTYPES|INITIALIZATION|INTERFACE|INTERFACES|INTO|LANGUAGE|LEAVE|LENGTH|LINES|LOAD|LOCAL|JOIN|KEY|NEXT|MAXIMUM|MESSAGE|METHOD[S]?|MINIMUM|MODULE|MODIFIER|MODIFY|MOVE|MULTIPLY|NODES|NUMBER|OBLIGATORY|OBJECT|OF|OFF|ON|OTHERS|OVERLAY|PACK|PAD|PARAMETERS|PERCENTAGE|POSITION|PROGRAM|PROVIDE|PUBLIC|PUT|PF\d\d|RAISE|RAISING|RANGES?|READ|RECEIVE|REDEFINITION|REFRESH|REJECT|REPORT|RESERVE|RESUME|RETRY|RETURN|RETURNING|RIGHT|ROLLBACK|REPLACE|SCROLL|SEARCH|SELECT|SHIFT|SIGN|SINGLE|SIZE|SKIP|SORT|SPLIT|STATICS|STOP|STYLE|SUBMATCHES|SUBMIT|SUBTRACT|SUM(?!\()|SUMMARY|SUMMING|SUPPLY|TABLE|TABLES|TIMESTAMP|TIMES?|TIMEZONE|TITLE|\??TO|TOP-OF-PAGE|TRANSFER|TRANSLATE|TRY|TYPES|ULINE|UNDER|UNPACK|UPDATE|USING|VALUE|VALUES|VIA|VARYING|VARY|WAIT|WHEN|WHERE|WIDTH|WHILE|WITH|WINDOW|WRITE|XSD|ZERO)\b`, Keyword, nil},
{`(abs|acos|asin|atan|boolc|boolx|bit_set|char_off|charlen|ceil|cmax|cmin|condense|contains|contains_any_of|contains_any_not_of|concat_lines_of|cos|cosh|count|count_any_of|count_any_not_of|dbmaxlen|distance|escape|exp|find|find_end|find_any_of|find_any_not_of|floor|frac|from_mixed|insert|lines|log|log10|match|matches|nmax|nmin|numofchar|repeat|replace|rescale|reverse|round|segment|shift_left|shift_right|sign|sin|sinh|sqrt|strlen|substring|substring_after|substring_from|substring_before|substring_to|tan|tanh|to_upper|to_lower|to_mixed|translate|trunc|xstrlen)(\()\b`, ByGroups(NameBuiltin, Punctuation), nil},
{`&[0-9]`, Name, nil},
{`[0-9]+`, LiteralNumberInteger, nil},
{`(?<=(\s|.))(AND|OR|EQ|NE|GT|LT|GE|LE|CO|CN|CA|NA|CS|NOT|NS|CP|NP|BYTE-CO|BYTE-CN|BYTE-CA|BYTE-NA|BYTE-CS|BYTE-NS|IS\s+(NOT\s+)?(INITIAL|ASSIGNED|REQUESTED|BOUND))\b`, OperatorWord, nil},
Include("variable-names"),
{`[?*<>=\-+&]`, Operator, nil},
{`'(''|[^'])*'`, LiteralStringSingle, nil},
{"`([^`])*`", LiteralStringSingle, nil},
{`([|}])([^{}|]*?)([|{])`, ByGroups(Punctuation, LiteralStringSingle, Punctuation), nil},
{`[/;:()\[\],.]`, Punctuation, nil},
{`(!)(\w+)`, ByGroups(Operator, Name), nil},
},
},
))

View File

@ -31,7 +31,7 @@ var Applescript = internal.Register(MustNewLexer(
{`\b(as )(alias |application |boolean |class |constant |date |file |integer |list |number |POSIX file |real |record |reference |RGB color |script |text |unit types|(?:Unicode )?text|string)\b`, ByGroups(Keyword, NameClass), nil},
{`\b(AppleScript|current application|false|linefeed|missing value|pi|quote|result|return|space|tab|text item delimiters|true|version)\b`, NameConstant, nil},
{`\b(ASCII (character|number)|activate|beep|choose URL|choose application|choose color|choose file( name)?|choose folder|choose from list|choose remote application|clipboard info|close( access)?|copy|count|current date|delay|delete|display (alert|dialog)|do shell script|duplicate|exists|get eof|get volume settings|info for|launch|list (disks|folder)|load script|log|make|mount volume|new|offset|open( (for access|location))?|path to|print|quit|random number|read|round|run( script)?|say|scripting components|set (eof|the clipboard to|volume)|store script|summarize|system attribute|system info|the clipboard|time to GMT|write|quoted form)\b`, NameBuiltin, nil},
{`\b(considering|else|error|exit|from|if|ignoring|in|repeat|tell|then|times|to|try|until|using terms from|while|whith|with timeout( of)?|with transaction|by|continue|end|its?|me|my|return|of|as)\b`, Keyword, nil},
{`\b(considering|else|error|exit|from|if|ignoring|in|repeat|tell|then|times|to|try|until|using terms from|while|with|with timeout( of)?|with transaction|by|continue|end|its?|me|my|return|of|as)\b`, Keyword, nil},
{`\b(global|local|prop(erty)?|set|get)\b`, Keyword, nil},
{`\b(but|put|returning|the)\b`, NameBuiltin, nil},
{`\b(attachment|attribute run|character|day|month|paragraph|word|year)s?\b`, NameBuiltin, nil},

View File

@ -25,7 +25,7 @@ var Ballerina = internal.Register(MustNewLexer(
{`(annotation|bind|but|endpoint|error|function|object|private|public|returns|service|type|var|with|worker)\b`, KeywordDeclaration, nil},
{`(boolean|byte|decimal|float|int|json|map|nil|record|string|table|xml)\b`, KeywordType, nil},
{`(true|false|null)\b`, KeywordConstant, nil},
{`import(\s+)`, ByGroups(KeywordNamespace, Text), Push("import")},
{`(import)(\s+)`, ByGroups(KeywordNamespace, Text), Push("import")},
{`"(\\\\|\\"|[^"])*"`, LiteralString, nil},
{`'\\.'|'[^\\]'|'\\u[0-9a-fA-F]{4}'`, LiteralStringChar, nil},
{`(\.)((?:[^\W\d]|\$)[\w$]*)`, ByGroups(Operator, NameAttribute), nil},

View File

@ -53,7 +53,7 @@ var Bash = internal.Register(MustNewLexer(
{`&`, Punctuation, nil},
{`\|`, Punctuation, nil},
{`\s+`, Text, nil},
{`\d+\b`, LiteralNumber, nil},
{`\d+(?= |$)`, LiteralNumber, nil},
{"[^=\\s\\[\\]{}()$\"\\'`\\\\<&|;]+", Text, nil},
{`<`, Text, nil},
},

76
vendor/github.com/alecthomas/chroma/lexers/b/bibtex.go generated vendored Normal file
View File

@ -0,0 +1,76 @@
package b
import (
. "github.com/alecthomas/chroma" // nolint
"github.com/alecthomas/chroma/lexers/internal"
)
// Bibtex lexer.
var Bibtex = internal.Register(MustNewLexer(
&Config{
Name: "BibTeX",
Aliases: []string{"bib", "bibtex"},
Filenames: []string{"*.bib"},
MimeTypes: []string{"text/x-bibtex"},
NotMultiline: true,
CaseInsensitive: true,
},
Rules{
"root": {
Include("whitespace"),
{`@comment`, Comment, nil},
{`@preamble`, NameClass, Push("closing-brace", "value", "opening-brace")},
{`@string`, NameClass, Push("closing-brace", "field", "opening-brace")},
{"@[a-z_@!$&*+\\-./:;<>?\\[\\\\\\]^`|~][\\w@!$&*+\\-./:;<>?\\[\\\\\\]^`|~]*", NameClass, Push("closing-brace", "command-body", "opening-brace")},
{`.+`, Comment, nil},
},
"opening-brace": {
Include("whitespace"),
{`[{(]`, Punctuation, Pop(1)},
},
"closing-brace": {
Include("whitespace"),
{`[})]`, Punctuation, Pop(1)},
},
"command-body": {
Include("whitespace"),
{`[^\s\,\}]+`, NameLabel, Push("#pop", "fields")},
},
"fields": {
Include("whitespace"),
{`,`, Punctuation, Push("field")},
Default(Pop(1)),
},
"field": {
Include("whitespace"),
{"[a-z_@!$&*+\\-./:;<>?\\[\\\\\\]^`|~][\\w@!$&*+\\-./:;<>?\\[\\\\\\]^`|~]*", NameAttribute, Push("value", "=")},
Default(Pop(1)),
},
"=": {
Include("whitespace"),
{`=`, Punctuation, Pop(1)},
},
"value": {
Include("whitespace"),
{"[a-z_@!$&*+\\-./:;<>?\\[\\\\\\]^`|~][\\w@!$&*+\\-./:;<>?\\[\\\\\\]^`|~]*", NameVariable, nil},
{`"`, LiteralString, Push("quoted-string")},
{`\{`, LiteralString, Push("braced-string")},
{`[\d]+`, LiteralNumber, nil},
{`#`, Punctuation, nil},
Default(Pop(1)),
},
"quoted-string": {
{`\{`, LiteralString, Push("braced-string")},
{`"`, LiteralString, Pop(1)},
{`[^\{\"]+`, LiteralString, nil},
},
"braced-string": {
{`\{`, LiteralString, Push()},
{`\}`, LiteralString, Pop(1)},
{`[^\{\}]+`, LiteralString, nil},
},
"whitespace": {
{`\s+`, Text, nil},
},
},
))

View File

@ -5,8 +5,232 @@ import (
"github.com/alecthomas/chroma/lexers/internal"
)
var (
clBuiltinFunctions = []string{
"<", "<=", "=", ">", ">=", "-", "/", "/=", "*", "+", "1-", "1+",
"abort", "abs", "acons", "acos", "acosh", "add-method", "adjoin",
"adjustable-array-p", "adjust-array", "allocate-instance",
"alpha-char-p", "alphanumericp", "append", "apply", "apropos",
"apropos-list", "aref", "arithmetic-error-operands",
"arithmetic-error-operation", "array-dimension", "array-dimensions",
"array-displacement", "array-element-type", "array-has-fill-pointer-p",
"array-in-bounds-p", "arrayp", "array-rank", "array-row-major-index",
"array-total-size", "ash", "asin", "asinh", "assoc", "assoc-if",
"assoc-if-not", "atan", "atanh", "atom", "bit", "bit-and", "bit-andc1",
"bit-andc2", "bit-eqv", "bit-ior", "bit-nand", "bit-nor", "bit-not",
"bit-orc1", "bit-orc2", "bit-vector-p", "bit-xor", "boole",
"both-case-p", "boundp", "break", "broadcast-stream-streams",
"butlast", "byte", "byte-position", "byte-size", "caaaar", "caaadr",
"caaar", "caadar", "caaddr", "caadr", "caar", "cadaar", "cadadr",
"cadar", "caddar", "cadddr", "caddr", "cadr", "call-next-method", "car",
"cdaaar", "cdaadr", "cdaar", "cdadar", "cdaddr", "cdadr", "cdar",
"cddaar", "cddadr", "cddar", "cdddar", "cddddr", "cdddr", "cddr", "cdr",
"ceiling", "cell-error-name", "cerror", "change-class", "char", "char<",
"char<=", "char=", "char>", "char>=", "char/=", "character",
"characterp", "char-code", "char-downcase", "char-equal",
"char-greaterp", "char-int", "char-lessp", "char-name",
"char-not-equal", "char-not-greaterp", "char-not-lessp", "char-upcase",
"cis", "class-name", "class-of", "clear-input", "clear-output",
"close", "clrhash", "code-char", "coerce", "compile",
"compiled-function-p", "compile-file", "compile-file-pathname",
"compiler-macro-function", "complement", "complex", "complexp",
"compute-applicable-methods", "compute-restarts", "concatenate",
"concatenated-stream-streams", "conjugate", "cons", "consp",
"constantly", "constantp", "continue", "copy-alist", "copy-list",
"copy-pprint-dispatch", "copy-readtable", "copy-seq", "copy-structure",
"copy-symbol", "copy-tree", "cos", "cosh", "count", "count-if",
"count-if-not", "decode-float", "decode-universal-time", "delete",
"delete-duplicates", "delete-file", "delete-if", "delete-if-not",
"delete-package", "denominator", "deposit-field", "describe",
"describe-object", "digit-char", "digit-char-p", "directory",
"directory-namestring", "disassemble", "documentation", "dpb",
"dribble", "echo-stream-input-stream", "echo-stream-output-stream",
"ed", "eighth", "elt", "encode-universal-time", "endp",
"enough-namestring", "ensure-directories-exist",
"ensure-generic-function", "eq", "eql", "equal", "equalp", "error",
"eval", "evenp", "every", "exp", "export", "expt", "fboundp",
"fceiling", "fdefinition", "ffloor", "fifth", "file-author",
"file-error-pathname", "file-length", "file-namestring",
"file-position", "file-string-length", "file-write-date",
"fill", "fill-pointer", "find", "find-all-symbols", "find-class",
"find-if", "find-if-not", "find-method", "find-package", "find-restart",
"find-symbol", "finish-output", "first", "float", "float-digits",
"floatp", "float-precision", "float-radix", "float-sign", "floor",
"fmakunbound", "force-output", "format", "fourth", "fresh-line",
"fround", "ftruncate", "funcall", "function-keywords",
"function-lambda-expression", "functionp", "gcd", "gensym", "gentemp",
"get", "get-decoded-time", "get-dispatch-macro-character", "getf",
"gethash", "get-internal-real-time", "get-internal-run-time",
"get-macro-character", "get-output-stream-string", "get-properties",
"get-setf-expansion", "get-universal-time", "graphic-char-p",
"hash-table-count", "hash-table-p", "hash-table-rehash-size",
"hash-table-rehash-threshold", "hash-table-size", "hash-table-test",
"host-namestring", "identity", "imagpart", "import",
"initialize-instance", "input-stream-p", "inspect",
"integer-decode-float", "integer-length", "integerp",
"interactive-stream-p", "intern", "intersection",
"invalid-method-error", "invoke-debugger", "invoke-restart",
"invoke-restart-interactively", "isqrt", "keywordp", "last", "lcm",
"ldb", "ldb-test", "ldiff", "length", "lisp-implementation-type",
"lisp-implementation-version", "list", "list*", "list-all-packages",
"listen", "list-length", "listp", "load",
"load-logical-pathname-translations", "log", "logand", "logandc1",
"logandc2", "logbitp", "logcount", "logeqv", "logical-pathname",
"logical-pathname-translations", "logior", "lognand", "lognor",
"lognot", "logorc1", "logorc2", "logtest", "logxor", "long-site-name",
"lower-case-p", "machine-instance", "machine-type", "machine-version",
"macroexpand", "macroexpand-1", "macro-function", "make-array",
"make-broadcast-stream", "make-concatenated-stream", "make-condition",
"make-dispatch-macro-character", "make-echo-stream", "make-hash-table",
"make-instance", "make-instances-obsolete", "make-list",
"make-load-form", "make-load-form-saving-slots", "make-package",
"make-pathname", "make-random-state", "make-sequence", "make-string",
"make-string-input-stream", "make-string-output-stream", "make-symbol",
"make-synonym-stream", "make-two-way-stream", "makunbound", "map",
"mapc", "mapcan", "mapcar", "mapcon", "maphash", "map-into", "mapl",
"maplist", "mask-field", "max", "member", "member-if", "member-if-not",
"merge", "merge-pathnames", "method-combination-error",
"method-qualifiers", "min", "minusp", "mismatch", "mod",
"muffle-warning", "name-char", "namestring", "nbutlast", "nconc",
"next-method-p", "nintersection", "ninth", "no-applicable-method",
"no-next-method", "not", "notany", "notevery", "nreconc", "nreverse",
"nset-difference", "nset-exclusive-or", "nstring-capitalize",
"nstring-downcase", "nstring-upcase", "nsublis", "nsubst", "nsubst-if",
"nsubst-if-not", "nsubstitute", "nsubstitute-if", "nsubstitute-if-not",
"nth", "nthcdr", "null", "numberp", "numerator", "nunion", "oddp",
"open", "open-stream-p", "output-stream-p", "package-error-package",
"package-name", "package-nicknames", "packagep",
"package-shadowing-symbols", "package-used-by-list", "package-use-list",
"pairlis", "parse-integer", "parse-namestring", "pathname",
"pathname-device", "pathname-directory", "pathname-host",
"pathname-match-p", "pathname-name", "pathnamep", "pathname-type",
"pathname-version", "peek-char", "phase", "plusp", "position",
"position-if", "position-if-not", "pprint", "pprint-dispatch",
"pprint-fill", "pprint-indent", "pprint-linear", "pprint-newline",
"pprint-tab", "pprint-tabular", "prin1", "prin1-to-string", "princ",
"princ-to-string", "print", "print-object", "probe-file", "proclaim",
"provide", "random", "random-state-p", "rassoc", "rassoc-if",
"rassoc-if-not", "rational", "rationalize", "rationalp", "read",
"read-byte", "read-char", "read-char-no-hang", "read-delimited-list",
"read-from-string", "read-line", "read-preserving-whitespace",
"read-sequence", "readtable-case", "readtablep", "realp", "realpart",
"reduce", "reinitialize-instance", "rem", "remhash", "remove",
"remove-duplicates", "remove-if", "remove-if-not", "remove-method",
"remprop", "rename-file", "rename-package", "replace", "require",
"rest", "restart-name", "revappend", "reverse", "room", "round",
"row-major-aref", "rplaca", "rplacd", "sbit", "scale-float", "schar",
"search", "second", "set", "set-difference",
"set-dispatch-macro-character", "set-exclusive-or",
"set-macro-character", "set-pprint-dispatch", "set-syntax-from-char",
"seventh", "shadow", "shadowing-import", "shared-initialize",
"short-site-name", "signal", "signum", "simple-bit-vector-p",
"simple-condition-format-arguments", "simple-condition-format-control",
"simple-string-p", "simple-vector-p", "sin", "sinh", "sixth", "sleep",
"slot-boundp", "slot-exists-p", "slot-makunbound", "slot-missing",
"slot-unbound", "slot-value", "software-type", "software-version",
"some", "sort", "special-operator-p", "sqrt", "stable-sort",
"standard-char-p", "store-value", "stream-element-type",
"stream-error-stream", "stream-external-format", "streamp", "string",
"string<", "string<=", "string=", "string>", "string>=", "string/=",
"string-capitalize", "string-downcase", "string-equal",
"string-greaterp", "string-left-trim", "string-lessp",
"string-not-equal", "string-not-greaterp", "string-not-lessp",
"stringp", "string-right-trim", "string-trim", "string-upcase",
"sublis", "subseq", "subsetp", "subst", "subst-if", "subst-if-not",
"substitute", "substitute-if", "substitute-if-not", "subtypep", "svref",
"sxhash", "symbol-function", "symbol-name", "symbolp", "symbol-package",
"symbol-plist", "symbol-value", "synonym-stream-symbol", "syntax:",
"tailp", "tan", "tanh", "tenth", "terpri", "third",
"translate-logical-pathname", "translate-pathname", "tree-equal",
"truename", "truncate", "two-way-stream-input-stream",
"two-way-stream-output-stream", "type-error-datum",
"type-error-expected-type", "type-of", "typep", "unbound-slot-instance",
"unexport", "unintern", "union", "unread-char", "unuse-package",
"update-instance-for-different-class",
"update-instance-for-redefined-class", "upgraded-array-element-type",
"upgraded-complex-part-type", "upper-case-p", "use-package",
"user-homedir-pathname", "use-value", "values", "values-list", "vector",
"vectorp", "vector-pop", "vector-push", "vector-push-extend", "warn",
"wild-pathname-p", "write", "write-byte", "write-char", "write-line",
"write-sequence", "write-string", "write-to-string", "yes-or-no-p",
"y-or-n-p", "zerop",
}
clSpecialForms = []string{
"block", "catch", "declare", "eval-when", "flet", "function", "go", "if",
"labels", "lambda", "let", "let*", "load-time-value", "locally", "macrolet",
"multiple-value-call", "multiple-value-prog1", "progn", "progv", "quote",
"return-from", "setq", "symbol-macrolet", "tagbody", "the", "throw",
"unwind-protect",
}
clMacros = []string{
"and", "assert", "call-method", "case", "ccase", "check-type", "cond",
"ctypecase", "decf", "declaim", "defclass", "defconstant", "defgeneric",
"define-compiler-macro", "define-condition", "define-method-combination",
"define-modify-macro", "define-setf-expander", "define-symbol-macro",
"defmacro", "defmethod", "defpackage", "defparameter", "defsetf",
"defstruct", "deftype", "defun", "defvar", "destructuring-bind", "do",
"do*", "do-all-symbols", "do-external-symbols", "dolist", "do-symbols",
"dotimes", "ecase", "etypecase", "formatter", "handler-bind",
"handler-case", "ignore-errors", "incf", "in-package", "lambda", "loop",
"loop-finish", "make-method", "multiple-value-bind", "multiple-value-list",
"multiple-value-setq", "nth-value", "or", "pop",
"pprint-exit-if-list-exhausted", "pprint-logical-block", "pprint-pop",
"print-unreadable-object", "prog", "prog*", "prog1", "prog2", "psetf",
"psetq", "push", "pushnew", "remf", "restart-bind", "restart-case",
"return", "rotatef", "setf", "shiftf", "step", "time", "trace", "typecase",
"unless", "untrace", "when", "with-accessors", "with-compilation-unit",
"with-condition-restarts", "with-hash-table-iterator",
"with-input-from-string", "with-open-file", "with-open-stream",
"with-output-to-string", "with-package-iterator", "with-simple-restart",
"with-slots", "with-standard-io-syntax",
}
clLambdaListKeywords = []string{
"&allow-other-keys", "&aux", "&body", "&environment", "&key", "&optional",
"&rest", "&whole",
}
clDeclarations = []string{
"dynamic-extent", "ignore", "optimize", "ftype", "inline", "special",
"ignorable", "notinline", "type",
}
clBuiltinTypes = []string{
"atom", "boolean", "base-char", "base-string", "bignum", "bit",
"compiled-function", "extended-char", "fixnum", "keyword", "nil",
"signed-byte", "short-float", "single-float", "double-float", "long-float",
"simple-array", "simple-base-string", "simple-bit-vector", "simple-string",
"simple-vector", "standard-char", "unsigned-byte",
// Condition Types
"arithmetic-error", "cell-error", "condition", "control-error",
"division-by-zero", "end-of-file", "error", "file-error",
"floating-point-inexact", "floating-point-overflow",
"floating-point-underflow", "floating-point-invalid-operation",
"parse-error", "package-error", "print-not-readable", "program-error",
"reader-error", "serious-condition", "simple-condition", "simple-error",
"simple-type-error", "simple-warning", "stream-error", "storage-condition",
"style-warning", "type-error", "unbound-variable", "unbound-slot",
"undefined-function", "warning",
}
clBuiltinClasses = []string{
"array", "broadcast-stream", "bit-vector", "built-in-class", "character",
"class", "complex", "concatenated-stream", "cons", "echo-stream",
"file-stream", "float", "function", "generic-function", "hash-table",
"integer", "list", "logical-pathname", "method-combination", "method",
"null", "number", "package", "pathname", "ratio", "rational", "readtable",
"real", "random-state", "restart", "sequence", "standard-class",
"standard-generic-function", "standard-method", "standard-object",
"string-stream", "stream", "string", "structure-class", "structure-object",
"symbol", "synonym-stream", "t", "two-way-stream", "vector",
}
)
// Common Lisp lexer.
var CommonLisp = internal.Register(MustNewLexer(
var CommonLisp = internal.Register(TypeRemappingLexer(MustNewLexer(
&Config{
Name: "Common Lisp",
Aliases: []string{"common-lisp", "cl", "lisp"},
@ -71,4 +295,12 @@ var CommonLisp = internal.Register(MustNewLexer(
{`\)`, Punctuation, Pop(1)},
},
},
))
), TypeMapping{
{NameVariable, NameFunction, clBuiltinFunctions},
{NameVariable, Keyword, clSpecialForms},
{NameVariable, NameBuiltin, clMacros},
{NameVariable, Keyword, clLambdaListKeywords},
{NameVariable, Keyword, clDeclarations},
{NameVariable, KeywordType, clBuiltinTypes},
{NameVariable, NameClass, clBuiltinClasses},
}))

View File

@ -16,26 +16,28 @@ var CPP = internal.Register(MustNewLexer(
},
Rules{
"statements": {
{Words(``, `\b`, `catch`, `const_cast`, `delete`, `dynamic_cast`, `explicit`, `export`, `friend`, `mutable`, `namespace`, `new`, `operator`, `private`, `protected`, `public`, `reinterpret_cast`, `restrict`, `static_cast`, `template`, `this`, `throw`, `throws`, `try`, `typeid`, `typename`, `using`, `virtual`, `constexpr`, `nullptr`, `decltype`, `thread_local`, `alignas`, `alignof`, `static_assert`, `noexcept`, `override`, `final`), Keyword, nil},
{`char(16_t|32_t)\b`, KeywordType, nil},
{`(class)\b`, ByGroups(Keyword, Text), Push("classname")},
{Words(``, `\b`, `catch`, `const_cast`, `delete`, `dynamic_cast`, `explicit`, `export`, `friend`, `mutable`, `namespace`, `new`, `operator`, `private`, `protected`, `public`, `reinterpret_cast`, `restrict`, `static_cast`, `template`, `this`, `throw`, `throws`, `try`, `typeid`, `typename`, `using`, `virtual`, `constexpr`, `nullptr`, `decltype`, `thread_local`, `alignas`, `alignof`, `static_assert`, `noexcept`, `override`, `final`, `concept`, `requires`, `consteval`, `co_await`, `co_return`, `co_yield`), Keyword, nil},
{`(enum)\b(\s+)(class)\b(\s*)`, ByGroups(Keyword, Text, Keyword, Text), Push("classname")},
{`(class|struct|enum|union)\b(\s*)`, ByGroups(Keyword, Text), Push("classname")},
{`\[\[.+\]\]`, NameAttribute, nil},
{`(R)(")([^\\()\s]{,16})(\()((?:.|\n)*?)(\)\3)(")`, ByGroups(LiteralStringAffix, LiteralString, LiteralStringDelimiter, LiteralStringDelimiter, LiteralString, LiteralStringDelimiter, LiteralString), nil},
{`(u8|u|U)(")`, ByGroups(LiteralStringAffix, LiteralString), Push("string")},
{`(L?)(")`, ByGroups(LiteralStringAffix, LiteralString), Push("string")},
{`(L?)(')(\\.|\\[0-7]{1,3}|\\x[a-fA-F0-9]{1,2}|[^\\\'\n])(')`, ByGroups(LiteralStringAffix, LiteralStringChar, LiteralStringChar, LiteralStringChar), nil},
{`(\d+\.\d*|\.\d+|\d+)[eE][+-]?\d+[LlUu]*`, LiteralNumberFloat, nil},
{`(\d+\.\d*|\.\d+|\d+[fF])[fF]?`, LiteralNumberFloat, nil},
{`0x[0-9a-fA-F]+[LlUu]*`, LiteralNumberHex, nil},
{`0[0-7]+[LlUu]*`, LiteralNumberOct, nil},
{`\d+[LlUu]*`, LiteralNumberInteger, nil},
{`0[xX]([0-9A-Fa-f]('?[0-9A-Fa-f]+)*)[LlUu]*`, LiteralNumberHex, nil},
{`0('?[0-7]+)+[LlUu]*`, LiteralNumberOct, nil},
{`0[Bb][01]('?[01]+)*[LlUu]*`, LiteralNumberBin, nil},
{`[0-9]('?[0-9]+)*[LlUu]*`, LiteralNumberInteger, nil},
{`\*/`, Error, nil},
{`[~!%^&*+=|?:<>/-]`, Operator, nil},
{`[()\[\],.]`, Punctuation, nil},
{Words(``, `\b`, `asm`, `auto`, `break`, `case`, `const`, `continue`, `default`, `do`, `else`, `enum`, `extern`, `for`, `goto`, `if`, `register`, `restricted`, `return`, `sizeof`, `static`, `struct`, `switch`, `typedef`, `union`, `volatile`, `while`), Keyword, nil},
{`(bool|int|long|float|short|double|char|unsigned|signed|void)\b`, KeywordType, nil},
{`(bool|int|long|float|short|double|char((8|16|32)_t)?|wchar_t|unsigned|signed|void|u?int(_fast|_least|)(8|16|32|64)_t)\b`, KeywordType, nil},
{Words(``, `\b`, `inline`, `_inline`, `__inline`, `naked`, `restrict`, `thread`, `typename`), KeywordReserved, nil},
{`(__m(128i|128d|128|64))\b`, KeywordReserved, nil},
{Words(`__`, `\b`, `asm`, `int8`, `based`, `except`, `int16`, `stdcall`, `cdecl`, `fastcall`, `int32`, `declspec`, `finally`, `int64`, `try`, `leave`, `wchar_t`, `w64`, `unaligned`, `raise`, `noop`, `identifier`, `forceinline`, `assume`), KeywordReserved, nil},
{Words(`__`, `\b`, `asm`, `int8`, `based`, `except`, `int16`, `stdcall`, `cdecl`, `fastcall`, `int32`, `declspec`, `finally`, `int64`, `try`, `leave`, `w64`, `unaligned`, `raise`, `noop`, `identifier`, `forceinline`, `assume`), KeywordReserved, nil},
{`(true|false|NULL)\b`, NameBuiltin, nil},
{`([a-zA-Z_]\w*)(\s*)(:)(?!:)`, ByGroups(NameLabel, Text, Punctuation), nil},
{`[a-zA-Z_]\w*`, Name, nil},
@ -49,8 +51,9 @@ var CPP = internal.Register(MustNewLexer(
{`__(offload|blockingoffload|outer)\b`, KeywordPseudo, nil},
},
"classname": {
{`(\[\[.+\]\])(\s*)`, ByGroups(NameAttribute, Text), nil},
{`[a-zA-Z_]\w*`, NameClass, Pop(1)},
{`\s*(?=>)`, Text, Pop(1)},
{`\s*(?=[>{])`, Text, Pop(1)},
},
"whitespace": {
{`^#if\s+0`, CommentPreproc, Push("if0")},
@ -67,8 +70,8 @@ var CPP = internal.Register(MustNewLexer(
"statement": {
Include("whitespace"),
Include("statements"),
{`[{}]`, Punctuation, nil},
{`;`, Punctuation, Pop(1)},
{`[{]`, Punctuation, Push("root")},
{`[;}]`, Punctuation, Pop(1)},
},
"function": {
Include("whitespace"),

69
vendor/github.com/alecthomas/chroma/lexers/d/d.go generated vendored Normal file
View File

@ -0,0 +1,69 @@
package d
import (
. "github.com/alecthomas/chroma" // nolint
"github.com/alecthomas/chroma/lexers/internal"
)
// D lexer. https://dlang.org/spec/lex.html
var D = internal.Register(MustNewLexer(
&Config{
Name: "D",
Aliases: []string{"d"},
Filenames: []string{"*.d", "*.di"},
MimeTypes: []string{"text/x-d"},
EnsureNL: true,
},
Rules{
"root": {
{`[^\S\n]+`, Text, nil},
// https://dlang.org/spec/lex.html#comment
{`//.*?\n`, CommentSingle, nil},
{`/\*.*?\*/`, CommentMultiline, nil},
{`/\+.*?\+/`, CommentMultiline, nil},
// https://dlang.org/spec/lex.html#keywords
{`(asm|assert|body|break|case|cast|catch|continue|default|debug|delete|deprecated|do|else|finally|for|foreach|foreach_reverse|goto|if|in|invariant|is|macro|mixin|new|out|pragma|return|super|switch|this|throw|try|version|while|with)\b`, Keyword, nil},
{`__(FILE|FILE_FULL_PATH|MODULE|LINE|FUNCTION|PRETTY_FUNCTION|DATE|EOF|TIME|TIMESTAMP|VENDOR|VERSION)__\b`, NameBuiltin, nil},
{`__(traits|vector|parameters)\b`, NameBuiltin, nil},
{`((?:(?:[^\W\d]|\$)[\w.\[\]$<>]*\s+)+?)((?:[^\W\d]|\$)[\w$]*)(\s*)(\()`, ByGroups(UsingSelf("root"), NameFunction, Text, Operator), nil},
// https://dlang.org/spec/attribute.html#uda
{`@[\w.]*`, NameDecorator, nil},
{`(abstract|auto|alias|align|const|delegate|enum|export|final|function|inout|lazy|nothrow|override|package|private|protected|public|pure|static|synchronized|template|volatile|__gshared)\b`, KeywordDeclaration, nil},
// https://dlang.org/spec/type.html#basic-data-types
{`(void|bool|byte|ubyte|short|ushort|int|uint|long|ulong|cent|ucent|float|double|real|ifloat|idouble|ireal|cfloat|cdouble|creal|char|wchar|dchar|string|wstring|dstring)\b`, KeywordType, nil},
{`(module)(\s+)`, ByGroups(KeywordNamespace, Text), Push("import")},
{`(true|false|null)\b`, KeywordConstant, nil},
{`(class|interface|struct|template|union)(\s+)`, ByGroups(KeywordDeclaration, Text), Push("class")},
{`(import)(\s+)`, ByGroups(KeywordNamespace, Text), Push("import")},
// https://dlang.org/spec/lex.html#string_literals
// TODO support delimited strings
{`[qr]?"(\\\\|\\"|[^"])*"[cwd]?`, LiteralString, nil},
{"(`)([^`]*)(`)[cwd]?", LiteralString, nil},
{`'\\.'|'[^\\]'|'\\u[0-9a-fA-F]{4}'`, LiteralStringChar, nil},
{`(\.)((?:[^\W\d]|\$)[\w$]*)`, ByGroups(Operator, NameAttribute), nil},
{`^\s*([^\W\d]|\$)[\w$]*:`, NameLabel, nil},
// https://dlang.org/spec/lex.html#floatliteral
{`([0-9][0-9_]*\.([0-9][0-9_]*)?|\.[0-9][0-9_]*)([eE][+\-]?[0-9][0-9_]*)?[fFL]?i?|[0-9][eE][+\-]?[0-9][0-9_]*[fFL]?|[0-9]([eE][+\-]?[0-9][0-9_]*)?[fFL]|0[xX]([0-9a-fA-F][0-9a-fA-F_]*\.?|([0-9a-fA-F][0-9a-fA-F_]*)?\.[0-9a-fA-F][0-9a-fA-F_]*)[pP][+\-]?[0-9][0-9_]*[fFL]?`, LiteralNumberFloat, nil},
// https://dlang.org/spec/lex.html#integerliteral
{`0[xX][0-9a-fA-F][0-9a-fA-F_]*[lL]?`, LiteralNumberHex, nil},
{`0[bB][01][01_]*[lL]?`, LiteralNumberBin, nil},
{`0[0-7_]+[lL]?`, LiteralNumberOct, nil},
{`0|[1-9][0-9_]*[lL]?`, LiteralNumberInteger, nil},
{`([~^*!%&\[\](){}<>|+=:;,./?-]|q{)`, Operator, nil},
{`([^\W\d]|\$)[\w$]*`, Name, nil},
{`\n`, Text, nil},
},
"class": {
{`([^\W\d]|\$)[\w$]*`, NameClass, Pop(1)},
},
"import": {
{`[\w.]+\*?`, NameNamespace, Pop(1)},
},
},
))

View File

@ -2,8 +2,9 @@ package d
import (
. "github.com/alecthomas/chroma" // nolint
. "github.com/alecthomas/chroma/lexers/b"
"github.com/alecthomas/chroma/lexers/b"
"github.com/alecthomas/chroma/lexers/internal"
"github.com/alecthomas/chroma/lexers/j"
)
// Docker lexer.
@ -17,11 +18,14 @@ var Docker = internal.Register(MustNewLexer(
},
Rules{
"root": {
{`^(ONBUILD)(\s+)((?:FROM|MAINTAINER|CMD|EXPOSE|ENV|ADD|ENTRYPOINT|VOLUME|WORKDIR))\b`, ByGroups(NameKeyword, TextWhitespace, Keyword), nil},
{`^((?:FROM|MAINTAINER|CMD|EXPOSE|ENV|ADD|ENTRYPOINT|VOLUME|WORKDIR))\b(.*)`, ByGroups(Keyword, LiteralString), nil},
{`#.*`, Comment, nil},
{`RUN`, Keyword, nil},
{`(.*\\\n)*.+`, Using(Bash), nil},
{`(ONBUILD)((?:\s*\\?\s*))`, ByGroups(Keyword, Using(b.Bash)), nil},
{`(HEALTHCHECK)(((?:\s*\\?\s*)--\w+=\w+(?:\s*\\?\s*))*)`, ByGroups(Keyword, Using(b.Bash)), nil},
{`(VOLUME|ENTRYPOINT|CMD|SHELL)((?:\s*\\?\s*))(\[.*?\])`, ByGroups(Keyword, Using(b.Bash), Using(j.JSON)), nil},
{`(LABEL|ENV|ARG)((?:(?:\s*\\?\s*)\w+=\w+(?:\s*\\?\s*))*)`, ByGroups(Keyword, Using(b.Bash)), nil},
{`((?:FROM|MAINTAINER|EXPOSE|WORKDIR|USER|STOPSIGNAL)|VOLUME)\b(.*)`, ByGroups(Keyword, LiteralString), nil},
{`((?:RUN|CMD|ENTRYPOINT|ENV|ARG|LABEL|ADD|COPY))`, Keyword, nil},
{`(.*\\\n)*.+`, Using(b.Bash), nil},
},
},
))

View File

@ -10,7 +10,7 @@ var Forth = internal.Register(MustNewLexer(
&Config{
Name: "Forth",
Aliases: []string{"forth"},
Filenames: []string{"*.frt", "*.fs"},
Filenames: []string{"*.frt", "*.fth", "*.fs"},
MimeTypes: []string{"application/x-forth"},
CaseInsensitive: true,
},

View File

@ -619,13 +619,14 @@ func haxePreProcMutator(state *LexerState) error {
}
proc := state.Groups[2]
if proc == "if" {
switch proc {
case "if":
stack = append(stack, state.Stack)
} else if proc == "else" || proc == "elseif" {
case "else", "elseif":
if len(stack) > 0 {
state.Stack = stack[len(stack)-1]
}
} else if proc == "end" {
case "end":
stack = stack[:len(stack)-1]
}

69
vendor/github.com/alecthomas/chroma/lexers/h/hcl.go generated vendored Normal file
View File

@ -0,0 +1,69 @@
package h
import (
. "github.com/alecthomas/chroma" // nolint
"github.com/alecthomas/chroma/lexers/internal"
)
// HCL lexer.
var HCL = internal.Register(MustNewLexer(
&Config{
Name: "HCL",
Aliases: []string{"hcl"},
Filenames: []string{"*.hcl"},
MimeTypes: []string{"application/x-hcl"},
},
Rules{
"root": {
Include("string"),
Include("punctuation"),
Include("curly"),
Include("basic"),
Include("whitespace"),
{`[0-9]+`, LiteralNumber, nil},
},
"basic": {
{Words(`\b`, `\b`, `true`, `false`), KeywordType, nil},
{`\s*/\*`, CommentMultiline, Push("comment")},
{`\s*#.*\n`, CommentSingle, nil},
{`(.*?)(\s*)(=)`, ByGroups(Name, Text, Operator), nil},
{`\d+`, Number, nil},
{`\b\w+\b`, Keyword, nil},
{`\$\{`, LiteralStringInterpol, Push("var_builtin")},
},
"function": {
{`(\s+)(".*")(\s+)`, ByGroups(Text, LiteralString, Text), nil},
Include("punctuation"),
Include("curly"),
},
"var_builtin": {
{`\$\{`, LiteralStringInterpol, Push()},
{Words(`\b`, `\b`, `concat`, `file`, `join`, `lookup`, `element`), NameBuiltin, nil},
Include("string"),
Include("punctuation"),
{`\s+`, Text, nil},
{`\}`, LiteralStringInterpol, Pop(1)},
},
"string": {
{`(".*")`, ByGroups(LiteralStringDouble), nil},
},
"punctuation": {
{`[\[\](),.]`, Punctuation, nil},
},
"curly": {
{`\{`, TextPunctuation, nil},
{`\}`, TextPunctuation, nil},
},
"comment": {
{`[^*/]`, CommentMultiline, nil},
{`/\*`, CommentMultiline, Push()},
{`\*/`, CommentMultiline, Pop(1)},
{`[*/]`, CommentMultiline, nil},
},
"whitespace": {
{`\n`, Text, nil},
{`\s+`, Text, nil},
{`\\\n`, Text, nil},
},
},
))

View File

@ -38,7 +38,6 @@ func httpContentBlock(groups []string, lexer Lexer) Iterator {
{Generic, groups[0]},
}
return Literator(tokens...)
}
func httpHeaderBlock(groups []string, lexer Lexer) Iterator {
@ -66,7 +65,7 @@ func httpBodyContentTypeLexer(lexer Lexer) Lexer { return &httpBodyContentTyper{
type httpBodyContentTyper struct{ Lexer }
func (d *httpBodyContentTyper) Tokenise(options *TokeniseOptions, text string) (Iterator, error) {
func (d *httpBodyContentTyper) Tokenise(options *TokeniseOptions, text string) (Iterator, error) { // nolint: gocognit
var contentType string
var isContentType bool
var subIterator Iterator
@ -123,9 +122,7 @@ func (d *httpBodyContentTyper) Tokenise(options *TokeniseOptions, text string) (
return EOF
}
}
}
return token
}, nil
}

32
vendor/github.com/alecthomas/chroma/lexers/i/igor.go generated vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,4 @@
// Package internal contains common API functions and structures shared between lexer packages.
package internal
import (

73
vendor/github.com/alecthomas/chroma/lexers/j/j.go generated vendored Normal file
View File

@ -0,0 +1,73 @@
package j
import (
. "github.com/alecthomas/chroma" // nolint
"github.com/alecthomas/chroma/lexers/internal"
)
// J lexer.
var J = internal.Register(MustNewLexer(
&Config{
Name: "J",
Aliases: []string{"j"},
Filenames: []string{"*.ijs"},
MimeTypes: []string{"text/x-j"},
},
Rules{
"root": {
{`#!.*$`, CommentPreproc, nil},
{`NB\..*`, CommentSingle, nil},
{`\n+\s*Note`, CommentMultiline, Push("comment")},
{`\s*Note.*`, CommentSingle, nil},
{`\s+`, Text, nil},
{`'`, LiteralString, Push("singlequote")},
{`0\s+:\s*0|noun\s+define\s*$`, NameEntity, Push("nounDefinition")},
{`(([1-4]|13)\s+:\s*0|(adverb|conjunction|dyad|monad|verb)\s+define)\b`, NameFunction, Push("explicitDefinition")},
{Words(``, `\b[a-zA-Z]\w*\.`, `for_`, `goto_`, `label_`), NameLabel, nil},
{Words(``, `\.`, `assert`, `break`, `case`, `catch`, `catchd`, `catcht`, `continue`, `do`, `else`, `elseif`, `end`, `fcase`, `for`, `if`, `return`, `select`, `throw`, `try`, `while`, `whilst`), NameLabel, nil},
{`\b[a-zA-Z]\w*`, NameVariable, nil},
{Words(``, ``, `ARGV`, `CR`, `CRLF`, `DEL`, `Debug`, `EAV`, `EMPTY`, `FF`, `JVERSION`, `LF`, `LF2`, `Note`, `TAB`, `alpha17`, `alpha27`, `apply`, `bind`, `boxopen`, `boxxopen`, `bx`, `clear`, `cutLF`, `cutopen`, `datatype`, `def`, `dfh`, `drop`, `each`, `echo`, `empty`, `erase`, `every`, `evtloop`, `exit`, `expand`, `fetch`, `file2url`, `fixdotdot`, `fliprgb`, `getargs`, `getenv`, `hfd`, `inv`, `inverse`, `iospath`, `isatty`, `isutf8`, `items`, `leaf`, `list`, `nameclass`, `namelist`, `names`, `nc`, `nl`, `on`, `pick`, `rows`, `script`, `scriptd`, `sign`, `sminfo`, `smoutput`, `sort`, `split`, `stderr`, `stdin`, `stdout`, `table`, `take`, `timespacex`, `timex`, `tmoutput`, `toCRLF`, `toHOST`, `toJ`, `tolower`, `toupper`, `type`, `ucp`, `ucpcount`, `usleep`, `utf8`, `uucp`), NameFunction, nil},
{`=[.:]`, Operator, nil},
{"[-=+*#$%@!~`^&\";:.,<>{}\\[\\]\\\\|/]", Operator, nil},
{`[abCdDeEfHiIjLMoprtT]\.`, KeywordReserved, nil},
{`[aDiLpqsStux]\:`, KeywordReserved, nil},
{`(_[0-9])\:`, KeywordConstant, nil},
{`\(`, Punctuation, Push("parentheses")},
Include("numbers"),
},
"comment": {
{`[^)]`, CommentMultiline, nil},
{`^\)`, CommentMultiline, Pop(1)},
{`[)]`, CommentMultiline, nil},
},
"explicitDefinition": {
{`\b[nmuvxy]\b`, NameDecorator, nil},
Include("root"),
{`[^)]`, Name, nil},
{`^\)`, NameLabel, Pop(1)},
{`[)]`, Name, nil},
},
"numbers": {
{`\b_{1,2}\b`, LiteralNumber, nil},
{`_?\d+(\.\d+)?(\s*[ejr]\s*)_?\d+(\.?=\d+)?`, LiteralNumber, nil},
{`_?\d+\.(?=\d+)`, LiteralNumberFloat, nil},
{`_?\d+x`, LiteralNumberIntegerLong, nil},
{`_?\d+`, LiteralNumberInteger, nil},
},
"nounDefinition": {
{`[^)]`, LiteralString, nil},
{`^\)`, NameLabel, Pop(1)},
{`[)]`, LiteralString, nil},
},
"parentheses": {
{`\)`, Punctuation, Pop(1)},
Include("explicitDefinition"),
Include("root"),
},
"singlequote": {
{`[^']`, LiteralString, nil},
{`''`, LiteralString, nil},
{`'`, LiteralString, Pop(1)},
},
},
))

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -21,12 +21,13 @@ var Julia = internal.Register(MustNewLexer(
{`#.*$`, Comment, nil},
{`[\[\]{}(),;]`, Punctuation, nil},
{`in\b`, KeywordPseudo, nil},
{`isa\b`, KeywordPseudo, nil},
{`(true|false)\b`, KeywordConstant, nil},
{`(local|global|const)\b`, KeywordDeclaration, nil},
{Words(``, `\b`, `function`, `type`, `typealias`, `abstract`, `immutable`, `mutable`, `struct`, `baremodule`, `begin`, `bitstype`, `break`, `catch`, `ccall`, `continue`, `do`, `else`, `elseif`, `end`, `export`, `finally`, `for`, `if`, `import`, `importall`, `let`, `macro`, `module`, `quote`, `return`, `try`, `using`, `while`), Keyword, nil},
{Words(``, `\b`, `ANY`, `ASCIIString`, `AbstractArray`, `AbstractChannel`, `AbstractFloat`, `AbstractMatrix`, `AbstractRNG`, `AbstractSparseArray`, `AbstractSparseMatrix`, `AbstractSparseVector`, `AbstractString`, `AbstractVecOrMat`, `AbstractVector`, `Any`, `ArgumentError`, `Array`, `AssertionError`, `Associative`, `Base64DecodePipe`, `Base64EncodePipe`, `Bidiagonal`, `BigFloat`, `BigInt`, `BitArray`, `BitMatrix`, `BitVector`, `Bool`, `BoundsError`, `Box`, `BufferStream`, `CapturedException`, `CartesianIndex`, `CartesianRange`, `Cchar`, `Cdouble`, `Cfloat`, `Channel`, `Char`, `Cint`, `Cintmax_t`, `Clong`, `Clonglong`, `ClusterManager`, `Cmd`, `Coff_t`, `Colon`, `Complex`, `Complex128`, `Complex32`, `Complex64`, `CompositeException`, `Condition`, `Cptrdiff_t`, `Cshort`, `Csize_t`, `Cssize_t`, `Cstring`, `Cuchar`, `Cuint`, `Cuintmax_t`, `Culong`, `Culonglong`, `Cushort`, `Cwchar_t`, `Cwstring`, `DataType`, `Date`, `DateTime`, `DenseArray`, `DenseMatrix`, `DenseVecOrMat`, `DenseVector`, `Diagonal`, `Dict`, `DimensionMismatch`, `Dims`, `DirectIndexString`, `Display`, `DivideError`, `DomainError`, `EOFError`, `EachLine`, `Enum`, `Enumerate`, `ErrorException`, `Exception`, `Expr`, `Factorization`, `FileMonitor`, `FileOffset`, `Filter`, `Float16`, `Float32`, `Float64`, `FloatRange`, `Function`, `GenSym`, `GlobalRef`, `GotoNode`, `HTML`, `Hermitian`, `IO`, `IOBuffer`, `IOStream`, `IPv4`, `IPv6`, `InexactError`, `InitError`, `Int`, `Int128`, `Int16`, `Int32`, `Int64`, `Int8`, `IntSet`, `Integer`, `InterruptException`, `IntrinsicFunction`, `InvalidStateException`, `Irrational`, `KeyError`, `LabelNode`, `LambdaStaticData`, `LinSpace`, `LineNumberNode`, `LoadError`, `LocalProcess`, `LowerTriangular`, `MIME`, `Matrix`, `MersenneTwister`, `Method`, `MethodError`, `MethodTable`, `Module`, `NTuple`, `NewvarNode`, `NullException`, `Nullable`, `Number`, `ObjectIdDict`, `OrdinalRange`, `OutOfMemoryError`, `OverflowError`, `Pair`, `ParseError`, `PartialQuickSort`, `Pipe`, `PollingFileWatcher`, `ProcessExitedException`, `ProcessGroup`, `Ptr`, `QuoteNode`, `RandomDevice`, `Range`, `Rational`, `RawFD`, `ReadOnlyMemoryError`, `Real`, `ReentrantLock`, `Ref`, `Regex`, `RegexMatch`, `RemoteException`, `RemoteRef`, `RepString`, `RevString`, `RopeString`, `RoundingMode`, `SegmentationFault`, `SerializationState`, `Set`, `SharedArray`, `SharedMatrix`, `SharedVector`, `Signed`, `SimpleVector`, `SparseMatrixCSC`, `StackOverflowError`, `StatStruct`, `StepRange`, `StridedArray`, `StridedMatrix`, `StridedVecOrMat`, `StridedVector`, `SubArray`, `SubString`, `SymTridiagonal`, `Symbol`, `SymbolNode`, `Symmetric`, `SystemError`, `TCPSocket`, `Task`, `Text`, `TextDisplay`, `Timer`, `TopNode`, `Tridiagonal`, `Tuple`, `Type`, `TypeConstructor`, `TypeError`, `TypeName`, `TypeVar`, `UDPSocket`, `UInt`, `UInt128`, `UInt16`, `UInt32`, `UInt64`, `UInt8`, `UTF16String`, `UTF32String`, `UTF8String`, `UndefRefError`, `UndefVarError`, `UnicodeError`, `UniformScaling`, `Union`, `UnitRange`, `Unsigned`, `UpperTriangular`, `Val`, `Vararg`, `VecOrMat`, `Vector`, `VersionNumber`, `Void`, `WString`, `WeakKeyDict`, `WeakRef`, `WorkerConfig`, `Zip`), KeywordType, nil},
{Words(``, `\b`, `function`, `abstract type`, `primitive type`, `baremodule`, `begin`, `bitstype`, `break`, `catch`, `ccall`, `continue`, `do`, `else`, `elseif`, `end`, `export`, `finally`, `for`, `if`, `import`, `let`, `macro`, `module`, `mutable`, `quote`, `return`, `struct`, `try`, `using`, `while`), Keyword, nil},
{Words(``, `\b`, `ASCIIString`, `AbstractArray`, `AbstractChannel`, `AbstractDict`, `AbstractFloat`, `AbstractMatrix`, `AbstractRNG`, `AbstractSparseArray`, `AbstractSparseMatrix`, `AbstractSparseVector`, `AbstractString`, `AbstractVecOrMat`, `AbstractVector`, `Any`, `ArgumentError`, `Array`, `AssertionError`, `Base64DecodePipe`, `Base64EncodePipe`, `Bidiagonal`, `BigFloat`, `BigInt`, `BitArray`, `BitMatrix`, `BitVector`, `Bool`, `BoundsError`, `Box`, `BufferStream`, `CapturedException`, `CartesianIndex`, `CartesianRange`, `Cchar`, `Cdouble`, `Cfloat`, `Channel`, `Char`, `Cint`, `Cintmax_t`, `Clong`, `Clonglong`, `ClusterManager`, `Cmd`, `Coff_t`, `Colon`, `Complex`, `Complex128`, `Complex32`, `Complex64`, `CompositeException`, `Condition`, `Cptrdiff_t`, `Cshort`, `Csize_t`, `Cssize_t`, `Cstring`, `Cuchar`, `Cuint`, `Cuintmax_t`, `Culong`, `Culonglong`, `Cushort`, `Cwchar_t`, `Cwstring`, `DataType`, `Date`, `DateTime`, `DenseArray`, `DenseMatrix`, `DenseVecOrMat`, `DenseVector`, `Diagonal`, `Dict`, `DimensionMismatch`, `Dims`, `DirectIndexString`, `Display`, `DivideError`, `DomainError`, `EOFError`, `EachLine`, `Enum`, `Enumerate`, `ErrorException`, `Exception`, `Expr`, `Factorization`, `FileMonitor`, `FileOffset`, `Filter`, `Float16`, `Float32`, `Float64`, `FloatRange`, `Function`, `GenSym`, `GlobalRef`, `GotoNode`, `HTML`, `Hermitian`, `IO`, `IOBuffer`, `IOStream`, `IPv4`, `IPv6`, `InexactError`, `InitError`, `Int`, `Int128`, `Int16`, `Int32`, `Int64`, `Int8`, `IntSet`, `Integer`, `InterruptException`, `IntrinsicFunction`, `InvalidStateException`, `Irrational`, `KeyError`, `LabelNode`, `LambdaStaticData`, `LinSpace`, `LineNumberNode`, `LoadError`, `LocalProcess`, `LowerTriangular`, `MIME`, `Matrix`, `MersenneTwister`, `Method`, `MethodError`, `MethodTable`, `Module`, `NTuple`, `NewvarNode`, `NullException`, `Nullable`, `Number`, `ObjectIdDict`, `OrdinalRange`, `OutOfMemoryError`, `OverflowError`, `Pair`, `ParseError`, `PartialQuickSort`, `Pipe`, `PollingFileWatcher`, `ProcessExitedException`, `ProcessGroup`, `Ptr`, `QuoteNode`, `RandomDevice`, `Range`, `Rational`, `RawFD`, `ReadOnlyMemoryError`, `Real`, `ReentrantLock`, `Ref`, `Regex`, `RegexMatch`, `RemoteException`, `RemoteRef`, `RepString`, `RevString`, `RopeString`, `RoundingMode`, `SegmentationFault`, `SerializationState`, `Set`, `SharedArray`, `SharedMatrix`, `SharedVector`, `Signed`, `SimpleVector`, `SparseMatrixCSC`, `StackOverflowError`, `StatStruct`, `StepRange`, `StridedArray`, `StridedMatrix`, `StridedVecOrMat`, `StridedVector`, `SubArray`, `SubString`, `SymTridiagonal`, `Symbol`, `SymbolNode`, `Symmetric`, `SystemError`, `TCPSocket`, `Task`, `Text`, `TextDisplay`, `Timer`, `TopNode`, `Tridiagonal`, `Tuple`, `Type`, `TypeConstructor`, `TypeError`, `TypeName`, `TypeVar`, `UDPSocket`, `UInt`, `UInt128`, `UInt16`, `UInt32`, `UInt64`, `UInt8`, `UTF16String`, `UTF32String`, `UTF8String`, `UndefRefError`, `UndefVarError`, `UnicodeError`, `UniformScaling`, `Union`, `UnitRange`, `Unsigned`, `UpperTriangular`, `Val`, `Vararg`, `VecOrMat`, `Vector`, `VersionNumber`, `Void`, `WString`, `WeakKeyDict`, `WeakRef`, `WorkerConfig`, `Zip`), KeywordType, nil},
{Words(``, `\b`, `ARGS`, `CPU_CORES`, `C_NULL`, `DevNull`, `ENDIAN_BOM`, `ENV`, `I`, `Inf`, `Inf16`, `Inf32`, `Inf64`, `InsertionSort`, `JULIA_HOME`, `LOAD_PATH`, `MergeSort`, `NaN`, `NaN16`, `NaN32`, `NaN64`, `OS_NAME`, `QuickSort`, `RoundDown`, `RoundFromZero`, `RoundNearest`, `RoundNearestTiesAway`, `RoundNearestTiesUp`, `RoundToZero`, `RoundUp`, `STDERR`, `STDIN`, `STDOUT`, `VERSION`, `WORD_SIZE`, `catalan`, `e`, `eu`, `eulergamma`, `golden`, `im`, `nothing`, `pi`, `γ`, `π`, `φ`), NameBuiltin, nil},
{Words(``, ``, `=`, `:=`, `+=`, `-=`, `*=`, `/=`, `//=`, `.//=`, `.*=`, `./=`, `\=`, `.\=`, `^=`, `.^=`, `÷=`, `.÷=`, `%=`, `.%=`, `|=`, `&=`, `$=`, `=>`, `<<=`, `>>=`, `>>>=`, `~`, `.+=`, `.-=`, `?`, `--`, `-->`, `||`, `&&`, `>`, `<`, `>=`, ``, `<=`, ``, `==`, `===`, ``, `!=`, ``, `!==`, ``, `.>`, `.<`, `.>=`, `.≥`, `.<=`, `.≤`, `.==`, `.!=`, `.≠`, `.=`, `.!`, `<:`, `>:`, ``, ``, ``, ``, ``, ``, ``, ``, ``, `|>`, `<|`, `:`, `+`, `-`, `.+`, `.-`, `|`, ``, `$`, `<<`, `>>`, `>>>`, `.<<`, `.>>`, `.>>>`, `*`, `/`, `./`, `÷`, ``, `%`, ``, `.%`, `.*`, `\`, `.\`, `&`, ``, `//`, `.//`, `^`, `.^`, `::`, `.`, `+`, `-`, `!`, `~`, ``, ``, ``), Operator, nil},
{Words(``, ``, `=`, `:=`, `+=`, `-=`, `*=`, `/=`, `//=`, `.//=`, `.*=`, `./=`, `\=`, `.\=`, `^=`, `.^=`, `÷=`, `.÷=`, `%=`, `.%=`, `|=`, `&=`, `$=`, `=>`, `<<=`, `>>=`, `>>>=`, `~`, `.+=`, `.-=`, `?`, `--`, `-->`, `||`, `&&`, `>`, `<`, `>=`, ``, `<=`, ``, `==`, `===`, ``, `!=`, ``, `!==`, ``, `.>`, `.<`, `.>=`, `.≥`, `.<=`, `.≤`, `.==`, `.!=`, `.≠`, `.=`, `.!`, `<:`, `>:`, ``, ``, ``, ``, ``, ``, ``, ``, ``, `|>`, `<|`, `:`, `+`, `-`, `.+`, `.-`, `|`, ``, `$`, `<<`, `>>`, `>>>`, `.<<`, `.>>`, `.>>>`, `*`, `/`, `./`, `÷`, ``, `%`, ``, `.%`, `.*`, `\`, `.\`, `&`, ``, `//`, `.//`, `^`, `.^`, `::`, `.`, `+`, `-`, `!`, ``, ``, ``), Operator, nil},
{`'(\\.|\\[0-7]{1,3}|\\x[a-fA-F0-9]{1,3}|\\u[a-fA-F0-9]{1,4}|\\U[a-fA-F0-9]{1,6}|[^\\\'\n])'`, LiteralStringChar, nil},
{`(?<=[.\w)\]])\'+`, Operator, nil},
{`"""`, LiteralString, Push("tqstring")},
@ -34,8 +35,8 @@ var Julia = internal.Register(MustNewLexer(
{`r"""`, LiteralStringRegex, Push("tqregex")},
{`r"`, LiteralStringRegex, Push("regex")},
{"`", LiteralStringBacktick, Push("command")},
{`(?:[a-zA-Z_¡-￿]|[𐀀-􏿿])(?:[a-zA-Z_0-9¡-￿]|[𐀀-􏿿])*!*`, Name, nil},
{`@(?:[a-zA-Z_¡-￿]|[𐀀-􏿿])(?:[a-zA-Z_0-9¡-￿]|[𐀀-􏿿])*!*`, NameDecorator, nil},
{`((?:[a-zA-Z_¡-￿]|[𐀀-􏿿])(?:[a-zA-Z_0-9¡-￿]|[𐀀-􏿿])*!*)(')?`, ByGroups(Name, Operator), nil},
{`(@(?:[a-zA-Z_¡-￿]|[𐀀-􏿿])(?:[a-zA-Z_0-9¡-￿]|[𐀀-􏿿])*!*)(')?`, ByGroups(NameDecorator, Operator), nil},
{`(\d+(_\d+)+\.\d*|\d*\.\d+(_\d+)+)([eEf][+-]?[0-9]+)?`, LiteralNumberFloat, nil},
{`(\d+\.\d*|\d*\.\d+)([eEf][+-]?[0-9]+)?`, LiteralNumberFloat, nil},
{`\d+(_\d+)+[eEf][+-]?[0-9]+`, LiteralNumberFloat, nil},

View File

@ -26,7 +26,7 @@ var MySQL = internal.Register(MustNewLexer(
{`((?:_[a-z0-9]+)?)(")`, ByGroups(LiteralStringAffix, LiteralStringDouble), Push("double-string")},
{"[+*/<>=~!@#%^&|`?-]", Operator, nil},
{`\b(tinyint|smallint|mediumint|int|integer|bigint|date|datetime|time|bit|bool|tinytext|mediumtext|longtext|text|tinyblob|mediumblob|longblob|blob|float|double|double\s+precision|real|numeric|dec|decimal|timestamp|year|char|varchar|varbinary|varcharacter|enum|set)(\b\s*)(\()?`, ByGroups(KeywordType, Text, Punctuation), nil},
{`\b(add|all|alter|analyze|and|as|asc|asensitive|before|between|bigint|binary|blob|both|by|call|cascade|case|change|char|character|check|collate|column|condition|constraint|continue|convert|create|cross|current_date|current_time|current_timestamp|current_user|cursor|database|databases|day_hour|day_microsecond|day_minute|day_second|dec|decimal|declare|default|delayed|delete|desc|describe|deterministic|distinct|distinctrow|div|double|drop|dual|each|else|elseif|enclosed|escaped|exists|exit|explain|fetch|flush|float|float4|float8|for|force|foreign|from|fulltext|grant|group|having|high_priority|hour_microsecond|hour_minute|hour_second|if|ignore|in|index|infile|inner|inout|insensitive|insert|int|int1|int2|int3|int4|int8|integer|interval|into|is|iterate|join|key|keys|kill|leading|leave|left|like|limit|lines|load|localtime|localtimestamp|lock|long|loop|low_priority|match|minute_microsecond|minute_second|mod|modifies|natural|no_write_to_binlog|not|numeric|on|optimize|option|optionally|or|order|out|outer|outfile|precision|primary|procedure|purge|raid0|read|reads|real|references|regexp|release|rename|repeat|replace|require|restrict|return|revoke|right|rlike|schema|schemas|second_microsecond|select|sensitive|separator|set|show|smallint|soname|spatial|specific|sql|sql_big_result|sql_calc_found_rows|sql_small_result|sqlexception|sqlstate|sqlwarning|ssl|starting|straight_join|table|terminated|then|to|trailing|trigger|undo|union|unique|unlock|unsigned|update|usage|use|using|utc_date|utc_time|utc_timestamp|values|varying|when|where|while|with|write|x509|xor|year_month|zerofill)\b`, Keyword, nil},
{`\b(add|all|alter|analyze|and|as|asc|asensitive|before|between|bigint|binary|blob|both|by|call|cascade|case|change|char|character|check|collate|column|condition|constraint|continue|convert|create|cross|current_date|current_time|current_timestamp|current_user|cursor|database|databases|day_hour|day_microsecond|day_minute|day_second|dec|decimal|declare|default|delayed|delete|desc|describe|deterministic|distinct|distinctrow|div|double|drop|dual|each|else|elseif|enclosed|escaped|exists|exit|explain|fetch|flush|float|float4|float8|for|force|foreign|from|fulltext|grant|group|having|high_priority|hour_microsecond|hour_minute|hour_second|identified|if|ignore|in|index|infile|inner|inout|insensitive|insert|int|int1|int2|int3|int4|int8|integer|interval|into|is|iterate|join|key|keys|kill|leading|leave|left|like|limit|lines|load|localtime|localtimestamp|lock|long|loop|low_priority|match|minute_microsecond|minute_second|mod|modifies|natural|no_write_to_binlog|not|numeric|on|optimize|option|optionally|or|order|out|outer|outfile|precision|primary|privileges|procedure|purge|raid0|read|reads|real|references|regexp|release|rename|repeat|replace|require|restrict|return|revoke|right|rlike|schema|schemas|second_microsecond|select|sensitive|separator|set|show|smallint|soname|spatial|specific|sql|sql_big_result|sql_calc_found_rows|sql_small_result|sqlexception|sqlstate|sqlwarning|ssl|starting|straight_join|table|terminated|then|to|trailing|trigger|undo|union|unique|unlock|unsigned|update|usage|use|user|using|utc_date|utc_time|utc_timestamp|values|varying|when|where|while|with|write|x509|xor|year_month|zerofill)\b`, Keyword, nil},
{`\b(auto_increment|engine|charset|tables)\b`, KeywordPseudo, nil},
{`(true|false|null)`, NameConstant, nil},
{`([a-z_]\w*)(\s*)(\()`, ByGroups(NameFunction, Text, Punctuation), nil},

View File

@ -16,6 +16,7 @@ var Nim = internal.Register(MustNewLexer(
},
Rules{
"root": {
{`#\[[\s\S]*?\]#`, CommentMultiline, nil},
{`##.*$`, LiteralStringDoc, nil},
{`#.*$`, Comment, nil},
{`[*=><+\-/@$~&%!?|\\\[\]]`, Operator, nil},

View File

@ -15,7 +15,6 @@ var Prolog = internal.Register(MustNewLexer(
},
Rules{
"root": {
{`^#.*`, CommentSingle, nil},
{`/\*`, CommentMultiline, Push("nested-comment")},
{`%.*`, CommentSingle, nil},
{`0\'.`, LiteralStringChar, nil},

File diff suppressed because one or more lines are too long

View File

@ -80,7 +80,7 @@ var Scss = internal.Register(MustNewLexer(
{`[\w-]+`, NameTag, nil},
{`#\{`, LiteralStringInterpol, Push("interpolation")},
{`&`, Keyword, nil},
{`[~^*!&\[\]()<>|+=@:;,./?-]`, Operator, nil},
{`[~^*!&\[\]()<>|+=@:,./?-]`, Operator, nil},
{`"`, LiteralStringDouble, Push("string-double")},
{`'`, LiteralStringSingle, Push("string-single")},
{`\n`, Text, nil},
@ -92,9 +92,9 @@ var Scss = internal.Register(MustNewLexer(
{`"`, LiteralStringDouble, Pop(1)},
},
"string-single": {
{`(\\.|#(?=[^\n{])|[^\n'#])+`, LiteralStringDouble, nil},
{`(\\.|#(?=[^\n{])|[^\n'#])+`, LiteralStringSingle, nil},
{`#\{`, LiteralStringInterpol, Push("interpolation")},
{`'`, LiteralStringDouble, Pop(1)},
{`'`, LiteralStringSingle, Pop(1)},
},
"string-url": {
{`(\\#|#(?=[^\n{])|[^\n#)])+`, LiteralStringOther, nil},

File diff suppressed because one or more lines are too long

View File

@ -5,7 +5,7 @@ import (
"github.com/alecthomas/chroma/lexers/internal"
)
// TradingView lexer.
// TradingView lexer
var TradingView = internal.Register(MustNewLexer(
&Config{
Name: "TradingView",
@ -26,10 +26,12 @@ var TradingView = internal.Register(MustNewLexer(
{`'\\.'|'[^\\]'`, LiteralString, nil},
{`[0-9](\.[0-9]*)?([eE][+-][0-9]+)?`, LiteralNumber, nil},
{`#[a-fA-F0-9]{8}|#[a-fA-F0-9]{6}|#[a-fA-F0-9]{3}`, LiteralStringOther, nil},
{`(abs|acos|alertcondition|alma|asin|atan|atr|avg|barcolor|barssince|bgcolor|cci|ceil|change|cog|correlation|cos|crossover|crossunder|cum|dev|ema|exp|falling|fill|fixnan|floor|heikinashi|highest|highestbars|hline|iff|input|kagi|linebreak|linreg|log|log10|lowest|lowestbars|macd|max|min|mom|nz|percentile_(linear_interpolation|nearest_rank)|percentrank|pivothigh|pivotlow|plot|plotarrow|plotbar|plotcandle|plotchar|plotshape|pointfigure|pow|renko|rising|rma|roc|round|rsi|sar|security|sign|sin|sma|sqrt|stdev|stoch|study|sum|swma|tan|timestamp|tostring|tsi|valuewhen|variance|vwma|wma|strategy\.(cancel|cancel_all|close|close_all|entry|exit|order|risk\.(allow_entry_in|max_cons_loss_days|max_drawdown|max_intraday_filled_orders|max_intraday_loss|max_position_size)))\b`, NameFunction, nil},
{`\b(cross|dayofmonth|dayofweek|hour|minute|month|na|offset|second|strategy|tickerid|time|tr|vwap|weekofyear|year)(\()`, ByGroups(NameFunction, Text), nil}, // functions that can also be variable
{`(accdist|adjustment\.(dividends|none|splits)|aqua|area|areabr|black|blue|bool|circles|close|columns|currency\.(AUD|CAD|CHF|EUR|GBP|HKD|JPY|NOK|NONE|NZD|RUB|SEK|SGD|TRY|USD|ZAR)|dashed|dotted|float|friday|fuchsia|gray|green|high|histogram|hl2|hlc3|integer|interval|isdaily|isdwm|isintraday|ismonthly|isweekly|lime|line|linebr|location\.(abovebar|absolute|belowbar|bottom|top)|low|maroon|monday|n|navy|ohlc4|olive|open|orange|period|purple|red|resolution|saturday|scale\.(left|none|right)|session|session\.(extended|regular)|silver|size\.(auto|huge|large|normal|small|tiny)|solid|source|stepline|string|sunday|symbol|syminfo\.(mintick|pointvalue|prefix|root|session|timezone)|teal|thursday|ticker|timenow|tuesday|volume|wednesday|white|yellow|strategy\.(cash|closedtrades|commission\.(cash_per_contract|cash_per_order|percent)|direction\.(all|long|short)|equity|eventrades|fixed|grossloss|grossprofit|initial_capital|long|losstrades|max_contracts_held_(all|long|short)|max_drawdown|netprofit|oca\.(cancel|none|reduce)|openprofit|opentrades|percent_of_equity|position_avg_price|position_entry_name|position_size|short|wintrades)|shape\.(arrowdown|arrowup|circle|cross|diamond|flag|labeldown|labelup|square|triangledown|triangleup|xcross)|barstate\.is(first|history|last|new|realtime)|barmerge\.(gaps_on|gaps_off|lookahead_on|lookahead_off))\b`, NameVariable, nil},
{`(abs|acos|alertcondition|alma|asin|atan|atr|avg|barcolor|barssince|bgcolor|cci|ceil|change|cog|color\.new|correlation|cos|crossover|crossunder|cum|dev|ema|exp|falling|fill|fixnan|floor|heikinashi|highest|highestbars|hline|iff|kagi|label\.(delete|get_text|get_x|get_y|new|set_color|set_size|set_style|set_text|set_textcolor|set_x|set_xloc|set_xy|set_y|set_yloc)|line\.(new|delete|get_x1|get_x2|get_y1|get_y2|set_color|set_width|set_style|set_extend|set_xy1|set_xy2|set_x1|set_x2|set_y1|set_y2|set_xloc)|linebreak|linreg|log|log10|lowest|lowestbars|macd|max|max_bars_back|min|mom|nz|percentile_(linear_interpolation|nearest_rank)|percentrank|pivothigh|pivotlow|plot|plotarrow|plotbar|plotcandle|plotchar|plotshape|pointfigure|pow|renko|rising|rma|roc|round|rsi|sar|security|sign|sin|sma|sqrt|stdev|stoch|study|sum|swma|tan|timestamp|tostring|tsi|valuewhen|variance|vwma|wma|strategy\.(cancel|cancel_all|close|close_all|entry|exit|order|risk\.(allow_entry_in|max_cons_loss_days|max_drawdown|max_intraday_filled_orders|max_intraday_loss|max_position_size)))\b`, NameFunction, nil},
{`\b(bool|color|cross|dayofmonth|dayofweek|float|hour|input|int|label|line|minute|month|na|offset|second|strategy|string|tickerid|time|tr|vwap|weekofyear|year)(\()`, ByGroups(NameFunction, Text), nil}, // functions that can also be variable
{`(accdist|adjustment\.(dividends|none|splits)|aqua|area|areabr|bar_index|black|blue|bool|circles|close|columns|currency\.(AUD|CAD|CHF|EUR|GBP|HKD|JPY|NOK|NONE|NZD|RUB|SEK|SGD|TRY|USD|ZAR)|color\.(aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow)|dashed|dotted|dayofweek\.(monday|tuesday|wednesday|thursday|friday|saturday|sunday)|extend\.(both|left|right|none)|float|format\.(inherit|price|volume)|friday|fuchsia|gray|green|high|histogram|hl2|hlc3|hline\.style_(dotted|solid|dashed)|input\.(bool|float|integer|resolution|session|source|string|symbol)|integer|interval|isdaily|isdwm|isintraday|ismonthly|isweekly|label\.style_(arrowdown|arrowup|circle|cross|diamond|flag|labeldown|labelup|none|square|triangledown|triangleup|xcross)|lime|line\.style_(dashed|dotted|solid|arrow_both|arrow_left|arrow_right)|linebr|location\.(abovebar|absolute|belowbar|bottom|top)|low|maroon|monday|n|navy|ohlc4|olive|open|orange|period|plot\.style_(area|areabr|circles|columns|cross|histogram|line|linebr|stepline)|purple|red|resolution|saturday|scale\.(left|none|right)|session|session\.(extended|regular)|silver|size\.(auto|huge|large|normal|small|tiny)|solid|source|stepline|string|sunday|symbol|syminfo\.(mintick|pointvalue|prefix|root|session|ticker|tickerid|timezone)|teal|thursday|ticker|timeframe\.(isdaily|isdwm|isintraday|ismonthly|isweekly|multiplier|period)|timenow|tuesday|volume|wednesday|white|yellow|strategy\.(cash|closedtrades|commission\.(cash_per_contract|cash_per_order|percent)|direction\.(all|long|short)|equity|eventrades|fixed|grossloss|grossprofit|initial_capital|long|losstrades|max_contracts_held_(all|long|short)|max_drawdown|netprofit|oca\.(cancel|none|reduce)|openprofit|opentrades|percent_of_equity|position_avg_price|position_entry_name|position_size|short|wintrades)|shape\.(arrowdown|arrowup|circle|cross|diamond|flag|labeldown|labelup|square|triangledown|triangleup|xcross)|barstate\.is(first|history|last|new|realtime)|barmerge\.(gaps_on|gaps_off|lookahead_on|lookahead_off)|xloc\.bar_(index|time)|yloc\.(abovebar|belowbar|price))\b`, NameVariable, nil},
{`(cross|dayofmonth|dayofweek|hour|minute|month|na|second|tickerid|time|tr|vwap|weekofyear|year)(\b[^\(])`, ByGroups(NameVariable, Text), nil}, // variables that can also be function
{`(int|float|bool|color|string|label|line)(\b[^\(=.])`, ByGroups(KeywordType, Text), nil}, // types that can also be a function
{`(var)\b`, KeywordType, nil},
{`(true|false)\b`, KeywordConstant, nil},
{`(and|or|not|if|else|for|to)\b`, OperatorWord, nil},
{`@?[_a-zA-Z]\w*`, Text, nil},

View File

@ -13,6 +13,7 @@ var TypeScript = internal.Register(MustNewLexer(
Filenames: []string{"*.ts", "*.tsx"},
MimeTypes: []string{"text/x-typescript"},
DotAll: true,
EnsureNL: true,
},
Rules{
"commentsandwhitespace": {

107
vendor/github.com/alecthomas/chroma/lexers/v/vue.go generated vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -34,10 +34,14 @@ func (e EmitterFunc) Emit(groups []string, lexer Lexer) Iterator { return e(grou
func ByGroups(emitters ...Emitter) Emitter {
return EmitterFunc(func(groups []string, lexer Lexer) Iterator {
iterators := make([]Iterator, 0, len(groups)-1)
// NOTE: If this panics, there is a mismatch with groups
if len(emitters) != len(groups)-1 {
iterators = append(iterators, Error.Emit(groups, lexer))
// panic(errors.Errorf("number of groups %q does not match number of emitters %v", groups, emitters))
} else {
for i, group := range groups[1:] {
iterators = append(iterators, emitters[i].Emit([]string{group}, lexer))
}
}
return Concaterator(iterators...)
})
}
@ -241,6 +245,7 @@ type LexerState struct {
// Custum context for mutators.
MutatorContext map[interface{}]interface{}
iteratorStack []Iterator
options *TokeniseOptions
}
// Set mutator context.
@ -254,7 +259,7 @@ func (l *LexerState) Get(key interface{}) interface{} {
}
// Iterator returns the next Token from the lexer.
func (l *LexerState) Iterator() Token {
func (l *LexerState) Iterator() Token { // nolint: gocognit
for l.Pos < len(l.Text) && len(l.Stack) > 0 {
// Exhaust the iterator stack, if any.
for len(l.iteratorStack) > 0 {
@ -275,9 +280,19 @@ func (l *LexerState) Iterator() Token {
if !ok {
panic("unknown state " + l.State)
}
ruleIndex, rule, groups := matchRules(l.Text[l.Pos:], selectedRule)
ruleIndex, rule, groups := matchRules(l.Text, l.Pos, selectedRule)
// No match.
if groups == nil {
// From Pygments :\
//
// If the RegexLexer encounters a newline that is flagged as an error token, the stack is
// emptied and the lexer continues scanning in the 'root' state. This can help producing
// error-tolerant highlighting for erroneous input, e.g. when a single-line string is not
// closed.
if l.Text[l.Pos] == '\n' && l.State != l.options.State {
l.Stack = []string{l.options.State}
continue
}
l.Pos++
return Token{Error, string(l.Text[l.Pos-1 : l.Pos])}
}
@ -352,7 +367,12 @@ func (r *RegexLexer) maybeCompile() (err error) {
for state, rules := range r.rules {
for i, rule := range rules {
if rule.Regexp == nil {
rule.Regexp, err = regexp2.Compile("^(?"+rule.flags+")(?:"+rule.Pattern+")", 0)
pattern := "(?:" + rule.Pattern + ")"
if rule.flags != "" {
pattern = "(?" + rule.flags + ")" + pattern
}
pattern = `\G` + pattern
rule.Regexp, err = regexp2.Compile(pattern, 0)
if err != nil {
return fmt.Errorf("failed to compile rule %s.%d: %s", state, i, err)
}
@ -394,6 +414,7 @@ func (r *RegexLexer) Tokenise(options *TokeniseOptions, text string) (Iterator,
text += "\n"
}
state := &LexerState{
options: options,
Lexer: r,
Text: []rune(text),
Stack: []string{options.State},
@ -403,10 +424,10 @@ func (r *RegexLexer) Tokenise(options *TokeniseOptions, text string) (Iterator,
return state.Iterator, nil
}
func matchRules(text []rune, rules []*CompiledRule) (int, *CompiledRule, []string) {
func matchRules(text []rune, pos int, rules []*CompiledRule) (int, *CompiledRule, []string) {
for i, rule := range rules {
match, err := rule.Regexp.FindRunesMatch(text)
if match != nil && err == nil {
match, err := rule.Regexp.FindRunesMatchStartingAt(text, pos)
if match != nil && err == nil && match.Index == pos {
groups := []string{}
for _, g := range match.Groups() {
groups = append(groups, g.String())

View File

@ -66,7 +66,6 @@ func TypeRemappingLexer(lexer Lexer, mapping TypeMapping) Lexer {
km[k] = rt.To
}
}
}
return RemappingLexer(lexer, func(t Token) []Token {
if k, ok := lut[t.Type]; ok {

View File

@ -5,7 +5,7 @@ import (
)
// Pygments default theme.
var Pygments = Register(chroma.MustNewStyle("pygments", map[chroma.TokenType]string{
var Pygments = Register(chroma.MustNewStyle("pygments", chroma.StyleEntries{
chroma.Whitespace: "#bbbbbb",
chroma.Comment: "italic #408080",
chroma.CommentPreproc: "noitalic #BC7A00",

View File

@ -5,7 +5,7 @@ import (
)
// SwapOff theme.
var SwapOff = Register(chroma.MustNewStyle("swapoff", map[chroma.TokenType]string{
var SwapOff = Register(chroma.MustNewStyle("swapoff", chroma.StyleEntries{
chroma.Background: "#lightgray bg:#black",
chroma.Number: "bold #ansiyellow",
chroma.Comment: "#ansiteal",

15
vendor/github.com/alecthomas/chroma/table.py generated vendored Normal file
View File

@ -0,0 +1,15 @@
#!/usr/bin/env python3
from collections import defaultdict
from subprocess import check_output
lines = check_output(["go", "run", "./cmd/chroma/main.go", "--list"]).decode('utf-8').splitlines()
lines = [line.strip() for line in lines if line.startswith(" ") and not line.startswith(" ")]
lines = sorted(lines, key=lambda l: l.lower())
table = defaultdict(list)
for line in lines:
table[line[0].upper()].append(line)
for key, value in table.items():
print("{} | {}".format(key, ', '.join(value)))

View File

@ -4,6 +4,107 @@ package chroma
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[Background - -1]
_ = x[LineNumbers - -2]
_ = x[LineNumbersTable - -3]
_ = x[LineHighlight - -4]
_ = x[LineTable - -5]
_ = x[LineTableTD - -6]
_ = x[Error - -7]
_ = x[Other - -8]
_ = x[None - -9]
_ = x[EOFType-0]
_ = x[Keyword-1000]
_ = x[KeywordConstant-1001]
_ = x[KeywordDeclaration-1002]
_ = x[KeywordNamespace-1003]
_ = x[KeywordPseudo-1004]
_ = x[KeywordReserved-1005]
_ = x[KeywordType-1006]
_ = x[Name-2000]
_ = x[NameAttribute-2001]
_ = x[NameBuiltin-2002]
_ = x[NameBuiltinPseudo-2003]
_ = x[NameClass-2004]
_ = x[NameConstant-2005]
_ = x[NameDecorator-2006]
_ = x[NameEntity-2007]
_ = x[NameException-2008]
_ = x[NameFunction-2009]
_ = x[NameFunctionMagic-2010]
_ = x[NameKeyword-2011]
_ = x[NameLabel-2012]
_ = x[NameNamespace-2013]
_ = x[NameOperator-2014]
_ = x[NameOther-2015]
_ = x[NamePseudo-2016]
_ = x[NameProperty-2017]
_ = x[NameTag-2018]
_ = x[NameVariable-2019]
_ = x[NameVariableAnonymous-2020]
_ = x[NameVariableClass-2021]
_ = x[NameVariableGlobal-2022]
_ = x[NameVariableInstance-2023]
_ = x[NameVariableMagic-2024]
_ = x[Literal-3000]
_ = x[LiteralDate-3001]
_ = x[LiteralOther-3002]
_ = x[LiteralString-3100]
_ = x[LiteralStringAffix-3101]
_ = x[LiteralStringAtom-3102]
_ = x[LiteralStringBacktick-3103]
_ = x[LiteralStringBoolean-3104]
_ = x[LiteralStringChar-3105]
_ = x[LiteralStringDelimiter-3106]
_ = x[LiteralStringDoc-3107]
_ = x[LiteralStringDouble-3108]
_ = x[LiteralStringEscape-3109]
_ = x[LiteralStringHeredoc-3110]
_ = x[LiteralStringInterpol-3111]
_ = x[LiteralStringName-3112]
_ = x[LiteralStringOther-3113]
_ = x[LiteralStringRegex-3114]
_ = x[LiteralStringSingle-3115]
_ = x[LiteralStringSymbol-3116]
_ = x[LiteralNumber-3200]
_ = x[LiteralNumberBin-3201]
_ = x[LiteralNumberFloat-3202]
_ = x[LiteralNumberHex-3203]
_ = x[LiteralNumberInteger-3204]
_ = x[LiteralNumberIntegerLong-3205]
_ = x[LiteralNumberOct-3206]
_ = x[Operator-4000]
_ = x[OperatorWord-4001]
_ = x[Punctuation-5000]
_ = x[Comment-6000]
_ = x[CommentHashbang-6001]
_ = x[CommentMultiline-6002]
_ = x[CommentSingle-6003]
_ = x[CommentSpecial-6004]
_ = x[CommentPreproc-6100]
_ = x[CommentPreprocFile-6101]
_ = x[Generic-7000]
_ = x[GenericDeleted-7001]
_ = x[GenericEmph-7002]
_ = x[GenericError-7003]
_ = x[GenericHeading-7004]
_ = x[GenericInserted-7005]
_ = x[GenericOutput-7006]
_ = x[GenericPrompt-7007]
_ = x[GenericStrong-7008]
_ = x[GenericSubheading-7009]
_ = x[GenericTraceback-7010]
_ = x[GenericUnderline-7011]
_ = x[Text-8000]
_ = x[TextWhitespace-8001]
_ = x[TextSymbol-8002]
_ = x[TextPunctuation-8003]
}
const _TokenType_name = "NoneOtherErrorLineTableTDLineTableLineHighlightLineNumbersTableLineNumbersBackgroundEOFTypeKeywordKeywordConstantKeywordDeclarationKeywordNamespaceKeywordPseudoKeywordReservedKeywordTypeNameNameAttributeNameBuiltinNameBuiltinPseudoNameClassNameConstantNameDecoratorNameEntityNameExceptionNameFunctionNameFunctionMagicNameKeywordNameLabelNameNamespaceNameOperatorNameOtherNamePseudoNamePropertyNameTagNameVariableNameVariableAnonymousNameVariableClassNameVariableGlobalNameVariableInstanceNameVariableMagicLiteralLiteralDateLiteralOtherLiteralStringLiteralStringAffixLiteralStringAtomLiteralStringBacktickLiteralStringBooleanLiteralStringCharLiteralStringDelimiterLiteralStringDocLiteralStringDoubleLiteralStringEscapeLiteralStringHeredocLiteralStringInterpolLiteralStringNameLiteralStringOtherLiteralStringRegexLiteralStringSingleLiteralStringSymbolLiteralNumberLiteralNumberBinLiteralNumberFloatLiteralNumberHexLiteralNumberIntegerLiteralNumberIntegerLongLiteralNumberOctOperatorOperatorWordPunctuationCommentCommentHashbangCommentMultilineCommentSingleCommentSpecialCommentPreprocCommentPreprocFileGenericGenericDeletedGenericEmphGenericErrorGenericHeadingGenericInsertedGenericOutputGenericPromptGenericStrongGenericSubheadingGenericTracebackGenericUnderlineTextTextWhitespaceTextSymbolTextPunctuation"
var _TokenType_map = map[TokenType]string{

View File

@ -158,6 +158,15 @@ type ReviewInfo struct {
Labels map[string]int `json:"labels"`
}
// ReviewerUpdateInfo entity contains information about updates
// to change's reviewers set.
type ReviewerUpdateInfo struct {
Updated Timestamp `json:"updated"` // Timestamp of the update.
UpdatedBy AccountInfo `json:"updated_by"` // The account which modified state of the reviewer in question.
Reviewer AccountInfo `json:"reviewer"` // The reviewer account added or removed from the change.
State string `json:"state"` // The reviewer state, one of "REVIEWER", "CC" or "REMOVED".
}
// ReviewResult entity contains information regarding the updates that were
// made to a review.
type ReviewResult struct {
@ -359,12 +368,14 @@ type ChangeInfo struct {
PermittedLabels map[string][]string `json:"permitted_labels,omitempty"`
RemovableReviewers []AccountInfo `json:"removable_reviewers,omitempty"`
Reviewers map[string][]AccountInfo `json:"reviewers,omitempty"`
ReviewerUpdates []ReviewerUpdateInfo `json:"reviewer_updates,omitempty"`
Messages []ChangeMessageInfo `json:"messages,omitempty"`
CurrentRevision string `json:"current_revision,omitempty"`
Revisions map[string]RevisionInfo `json:"revisions,omitempty"`
MoreChanges bool `json:"_more_changes,omitempty"`
Problems []ProblemInfo `json:"problems,omitempty"`
BaseChange string `json:"base_change,omitempty"`
Submittable bool `json:"submittable,omitempty"`
}
// LabelInfo entity contains information about a label on a change, always corresponding to the current patch set.

View File

@ -1,3 +0,0 @@
module github.com/cenkalti/backoff
go 1.12

1
vendor/github.com/digitalocean/godo/.gitignore generated vendored Normal file
View File

@ -0,0 +1 @@
vendor/

15
vendor/github.com/digitalocean/godo/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,15 @@
language: go
go:
- 1.7.x
- 1.8.x
- 1.9.x
- 1.10.x
- 1.11.x
- 1.12.x
- 1.13.x
- tip
matrix:
allow_failures:
- go: tip

168
vendor/github.com/digitalocean/godo/CHANGELOG.md generated vendored Normal file
View File

@ -0,0 +1,168 @@
# Change Log
## [v1.22.0] - 2019-09-24
- #259 Add Kubernetes GetCredentials method - @snormore
## [v1.21.1] - 2019-09-19
- #257 Upgrade to Go 1.13 - @bentranter
## [v1.21.0] - 2019-09-16
- #255 Add DropletID to Kubernetes Node instance - @snormore
- #254 Add tags to Database, DatabaseReplica - @Zyqsempai
## [v1.20.0] - 2019-09-06
- #252 Add Kubernetes autoscale config fields - @snormore
- #251 Support unset fields on Kubernetes cluster and node pool updates - @snormore
- #250 Add Kubernetes GetUser method - @snormore
## [v1.19.0] - 2019-07-19
- #244 dbaas: add private-network-uuid field to create request
## [v1.18.0] - 2019-07-17
- #241 Databases: support for custom VPC UUID on migrate @mikejholly
- #240 Add the ability to get URN for a Database @stack72
- #236 Fix omitempty typos in JSON struct tags @amccarthy1
## [v1.17.0] - 2019-06-21
- #238 Add support for Redis eviction policy in Databases @mikejholly
## [v1.16.0] - 2019-06-04
- #233 Add Kubernetes DeleteNode method, deprecate RecycleNodePoolNodes @bouk
## [v1.15.0] - 2019-05-13
- #231 Add private connection fields to Databases - @mikejholly
- #223 Introduce Go modules - @andreiavrammsd
## [v1.14.0] - 2019-05-13
- #229 Add support for upgrading Kubernetes clusters - @adamwg
## [v1.13.0] - 2019-04-19
- #213 Add tagging support for volume snapshots - @jcodybaker
## [v1.12.0] - 2019-04-18
- #224 Add maintenance window support for Kubernetes- @fatih
## [v1.11.1] - 2019-04-04
- #222 Fix Create Database Pools json fields - @sunny-b
## [v1.11.0] - 2019-04-03
- #220 roll out vpc functionality - @jheimann
## [v1.10.1] - 2019-03-27
- #219 Fix Database Pools json field - @sunny-b
## [v1.10.0] - 2019-03-20
- #215 Add support for Databases - @mikejholly
## [v1.9.0] - 2019-03-18
- #214 add support for enable_proxy_protocol. - @mregmi
## [v1.8.0] - 2019-03-13
- #210 Expose tags on storage volume create/list/get. - @jcodybaker
## [v1.7.5] - 2019-03-04
- #207 Add support for custom subdomains for Spaces CDN [beta] - @xornivore
## [v1.7.4] - 2019-02-08
- #202 Allow tagging volumes - @mchitten
## [v1.7.3] - 2018-12-18
- #196 Expose tag support for creating Load Balancers.
## [v1.7.2] - 2018-12-04
- #192 Exposes more options for Kubernetes clusters.
## [v1.7.1] - 2018-11-27
- #190 Expose constants for the state of Kubernetes clusters.
## [v1.7.0] - 2018-11-13
- #188 Kubernetes support [beta] - @aybabtme
## [v1.6.0] - 2018-10-16
- #185 Projects support [beta] - @mchitten
## [v1.5.0] - 2018-10-01
- #181 Adding tagging images support - @hugocorbucci
## [v1.4.2] - 2018-08-30
- #178 Allowing creating domain records with weight of 0 - @TFaga
- #177 Adding `VolumeLimit` to account - @lxfontes
## [v1.4.1] - 2018-08-23
- #176 Fix cdn flush cache API endpoint - @sunny-b
## [v1.4.0] - 2018-08-22
- #175 Add support for Spaces CDN - @sunny-b
## [v1.3.0] - 2018-05-24
- #170 Add support for volume formatting - @adamwg
## [v1.2.0] - 2018-05-08
- #166 Remove support for Go 1.6 - @iheanyi
- #165 Add support for Let's Encrypt Certificates - @viola
## [v1.1.3] - 2018-03-07
- #156 Handle non-json errors from the API - @aknuds1
- #158 Update droplet example to use latest instance type - @dan-v
## [v1.1.2] - 2018-03-06
- #157 storage: list volumes should handle only name or only region params - @andrewsykim
- #154 docs: replace first example with fully-runnable example - @xmudrii
- #152 Handle flags & tag properties of domain record - @jaymecd
## [v1.1.1] - 2017-09-29
- #151 Following user agent field recommendations - @joonas
- #148 AsRequest method to create load balancers requests - @lukegb
## [v1.1.0] - 2017-06-06
### Added
- #145 Add FirewallsService for managing Firewalls with the DigitalOcean API. - @viola
- #139 Add TTL field to the Domains. - @xmudrii
### Fixed
- #143 Fix oauth2.NoContext depreciation. - @jbowens
- #141 Fix DropletActions on tagged resources. - @xmudrii
## [v1.0.0] - 2017-03-10
### Added
- #130 Add Convert to ImageActionsService. - @xmudrii
- #126 Add CertificatesService for managing certificates with the DigitalOcean API. - @viola
- #125 Add LoadBalancersService for managing load balancers with the DigitalOcean API. - @viola
- #122 Add GetVolumeByName to StorageService. - @protochron
- #113 Add context.Context to all calls. - @aybabtme

54
vendor/github.com/digitalocean/godo/CONTRIBUTING.md generated vendored Normal file
View File

@ -0,0 +1,54 @@
# Contributing
If you submit a pull request, please keep the following guidelines in mind:
1. Code should be `go fmt` compliant.
2. Types, structs and funcs should be documented.
3. Tests pass.
## Getting set up
Assuming your `$GOPATH` is set up according to your desires, run:
```sh
go get github.com/digitalocean/godo
go get -u github.com/stretchr/testify/assert
```
If outside `$GOPATH`, just clone the repository:
```sh
git clone github.com/digitalocean/godo
```
## Running tests
When working on code in this repository, tests can be run via:
```sh
go test .
```
## Versioning
Godo follows [semver](https://www.semver.org) versioning semantics. New functionality should be accompanied by increment to the minor version number. The current strategy is to release often. Any code which is complete, tested, reviewed, and merged to master is worthy of release.
## Releasing
Releasing a new version of godo is currently a manual process.
1. Update the `CHANGELOG.md` with your changes. If a version header for the next (unreleased) version does not exist, create one. Include one bullet point for each piece of new functionality in the release, including the pull request ID, description, and author(s).
```
## [v1.8.0] - 2019-03-13
- #210 Expose tags on storage volume create/list/get. - @jcodybaker
- #123 Update test dependencies - @digitalocean
```
2. Update the `libraryVersion` number in `godo.go`.
3. Make a pull request with these changes. This PR should be separate from the PR containing the godo changes.
4. Once the pull request has been merged, [draft a new release](https://github.com/digitalocean/godo/releases/new).
5. Update the `Tag version` and `Release title` field with the new godo version. Be sure the version has a `v` prefixed in both places. Ex `v1.8.0`.
6. Copy the changelog bullet points to the description field.
7. Publish the release.

55
vendor/github.com/digitalocean/godo/LICENSE.txt generated vendored Normal file
View File

@ -0,0 +1,55 @@
Copyright (c) 2014-2016 The godo AUTHORS. All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
======================
Portions of the client are based on code at:
https://github.com/google/go-github/
Copyright (c) 2013 The go-github AUTHORS. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

159
vendor/github.com/digitalocean/godo/README.md generated vendored Normal file
View File

@ -0,0 +1,159 @@
# Godo
[![Build Status](https://travis-ci.org/digitalocean/godo.svg)](https://travis-ci.org/digitalocean/godo)
[![GoDoc](https://godoc.org/github.com/digitalocean/godo?status.svg)](https://godoc.org/github.com/digitalocean/godo)
Godo is a Go client library for accessing the DigitalOcean V2 API.
You can view the client API docs here: [http://godoc.org/github.com/digitalocean/godo](http://godoc.org/github.com/digitalocean/godo)
You can view DigitalOcean API docs here: [https://developers.digitalocean.com/documentation/v2/](https://developers.digitalocean.com/documentation/v2/)
## Install
```sh
go get github.com/digitalocean/godo@vX.Y.Z
```
where X.Y.Z is the [version](https://github.com/digitalocean/godo/releases) you need.
or
```sh
go get github.com/digitalocean/godo
```
for non Go modules usage or latest version.
## Usage
```go
import "github.com/digitalocean/godo"
```
Create a new DigitalOcean client, then use the exposed services to
access different parts of the DigitalOcean API.
### Authentication
Currently, Personal Access Token (PAT) is the only method of
authenticating with the API. You can manage your tokens
at the DigitalOcean Control Panel [Applications Page](https://cloud.digitalocean.com/settings/applications).
You can then use your token to create a new client:
```go
package main
import (
"context"
"github.com/digitalocean/godo"
"golang.org/x/oauth2"
)
const (
pat = "mytoken"
)
type TokenSource struct {
AccessToken string
}
func (t *TokenSource) Token() (*oauth2.Token, error) {
token := &oauth2.Token{
AccessToken: t.AccessToken,
}
return token, nil
}
func main() {
tokenSource := &TokenSource{
AccessToken: pat,
}
oauthClient := oauth2.NewClient(context.Background(), tokenSource)
client := godo.NewClient(oauthClient)
}
```
## Examples
To create a new Droplet:
```go
dropletName := "super-cool-droplet"
createRequest := &godo.DropletCreateRequest{
Name: dropletName,
Region: "nyc3",
Size: "s-1vcpu-1gb",
Image: godo.DropletCreateImage{
Slug: "ubuntu-14-04-x64",
},
}
ctx := context.TODO()
newDroplet, _, err := client.Droplets.Create(ctx, createRequest)
if err != nil {
fmt.Printf("Something bad happened: %s\n\n", err)
return err
}
```
### Pagination
If a list of items is paginated by the API, you must request pages individually. For example, to fetch all Droplets:
```go
func DropletList(ctx context.Context, client *godo.Client) ([]godo.Droplet, error) {
// create a list to hold our droplets
list := []godo.Droplet{}
// create options. initially, these will be blank
opt := &godo.ListOptions{}
for {
droplets, resp, err := client.Droplets.List(ctx, opt)
if err != nil {
return nil, err
}
// append the current page's droplets to our list
for _, d := range droplets {
list = append(list, d)
}
// if we are at the last page, break out the for loop
if resp.Links == nil || resp.Links.IsLastPage() {
break
}
page, err := resp.Links.CurrentPage()
if err != nil {
return nil, err
}
// set the page we want for the next request
opt.Page = page + 1
}
return list, nil
}
```
## Versioning
Each version of the client is tagged and the version is updated accordingly.
To see the list of past versions, run `git tag`.
## Documentation
For a comprehensive list of examples, check out the [API documentation](https://developers.digitalocean.com/documentation/v2/).
For details on all the functionality in this library, see the [GoDoc](http://godoc.org/github.com/digitalocean/godo) documentation.
## Contributing
We love pull requests! Please see the [contribution guidelines](CONTRIBUTING.md).

60
vendor/github.com/digitalocean/godo/account.go generated vendored Normal file
View File

@ -0,0 +1,60 @@
package godo
import (
"context"
"net/http"
)
// AccountService is an interface for interfacing with the Account
// endpoints of the DigitalOcean API
// See: https://developers.digitalocean.com/documentation/v2/#account
type AccountService interface {
Get(context.Context) (*Account, *Response, error)
}
// AccountServiceOp handles communication with the Account related methods of
// the DigitalOcean API.
type AccountServiceOp struct {
client *Client
}
var _ AccountService = &AccountServiceOp{}
// Account represents a DigitalOcean Account
type Account struct {
DropletLimit int `json:"droplet_limit,omitempty"`
FloatingIPLimit int `json:"floating_ip_limit,omitempty"`
VolumeLimit int `json:"volume_limit,omitempty"`
Email string `json:"email,omitempty"`
UUID string `json:"uuid,omitempty"`
EmailVerified bool `json:"email_verified,omitempty"`
Status string `json:"status,omitempty"`
StatusMessage string `json:"status_message,omitempty"`
}
type accountRoot struct {
Account *Account `json:"account"`
}
func (r Account) String() string {
return Stringify(r)
}
// Get DigitalOcean account info
func (s *AccountServiceOp) Get(ctx context.Context) (*Account, *Response, error) {
path := "v2/account"
req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(accountRoot)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Account, resp, err
}

104
vendor/github.com/digitalocean/godo/action.go generated vendored Normal file
View File

@ -0,0 +1,104 @@
package godo
import (
"context"
"fmt"
"net/http"
)
const (
actionsBasePath = "v2/actions"
// ActionInProgress is an in progress action status
ActionInProgress = "in-progress"
//ActionCompleted is a completed action status
ActionCompleted = "completed"
)
// ActionsService handles communction with action related methods of the
// DigitalOcean API: https://developers.digitalocean.com/documentation/v2#actions
type ActionsService interface {
List(context.Context, *ListOptions) ([]Action, *Response, error)
Get(context.Context, int) (*Action, *Response, error)
}
// ActionsServiceOp handles communition with the image action related methods of the
// DigitalOcean API.
type ActionsServiceOp struct {
client *Client
}
var _ ActionsService = &ActionsServiceOp{}
type actionsRoot struct {
Actions []Action `json:"actions"`
Links *Links `json:"links"`
}
type actionRoot struct {
Event *Action `json:"action"`
}
// Action represents a DigitalOcean Action
type Action struct {
ID int `json:"id"`
Status string `json:"status"`
Type string `json:"type"`
StartedAt *Timestamp `json:"started_at"`
CompletedAt *Timestamp `json:"completed_at"`
ResourceID int `json:"resource_id"`
ResourceType string `json:"resource_type"`
Region *Region `json:"region,omitempty"`
RegionSlug string `json:"region_slug,omitempty"`
}
// List all actions
func (s *ActionsServiceOp) List(ctx context.Context, opt *ListOptions) ([]Action, *Response, error) {
path := actionsBasePath
path, err := addOptions(path, opt)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(actionsRoot)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
if l := root.Links; l != nil {
resp.Links = l
}
return root.Actions, resp, err
}
// Get an action by ID.
func (s *ActionsServiceOp) Get(ctx context.Context, id int) (*Action, *Response, error) {
if id < 1 {
return nil, nil, NewArgError("id", "cannot be less than 1")
}
path := fmt.Sprintf("%s/%d", actionsBasePath, id)
req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(actionRoot)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Event, resp, err
}
func (a Action) String() string {
return Stringify(a)
}

214
vendor/github.com/digitalocean/godo/cdn.go generated vendored Normal file
View File

@ -0,0 +1,214 @@
package godo
import (
"context"
"fmt"
"net/http"
"time"
)
const cdnBasePath = "v2/cdn/endpoints"
// CDNService is an interface for managing Spaces CDN with the DigitalOcean API.
type CDNService interface {
List(context.Context, *ListOptions) ([]CDN, *Response, error)
Get(context.Context, string) (*CDN, *Response, error)
Create(context.Context, *CDNCreateRequest) (*CDN, *Response, error)
UpdateTTL(context.Context, string, *CDNUpdateTTLRequest) (*CDN, *Response, error)
UpdateCustomDomain(context.Context, string, *CDNUpdateCustomDomainRequest) (*CDN, *Response, error)
FlushCache(context.Context, string, *CDNFlushCacheRequest) (*Response, error)
Delete(context.Context, string) (*Response, error)
}
// CDNServiceOp handles communication with the CDN related methods of the
// DigitalOcean API.
type CDNServiceOp struct {
client *Client
}
var _ CDNService = &CDNServiceOp{}
// CDN represents a DigitalOcean CDN
type CDN struct {
ID string `json:"id"`
Origin string `json:"origin"`
Endpoint string `json:"endpoint"`
CreatedAt time.Time `json:"created_at"`
TTL uint32 `json:"ttl"`
CertificateID string `json:"certificate_id,omitempty"`
CustomDomain string `json:"custom_domain,omitempty"`
}
// CDNRoot represents a response from the DigitalOcean API
type cdnRoot struct {
Endpoint *CDN `json:"endpoint"`
}
type cdnsRoot struct {
Endpoints []CDN `json:"endpoints"`
Links *Links `json:"links"`
}
// CDNCreateRequest represents a request to create a CDN.
type CDNCreateRequest struct {
Origin string `json:"origin"`
TTL uint32 `json:"ttl"`
CustomDomain string `json:"custom_domain,omitempty"`
CertificateID string `json:"certificate_id,omitempty"`
}
// CDNUpdateTTLRequest represents a request to update the ttl of a CDN.
type CDNUpdateTTLRequest struct {
TTL uint32 `json:"ttl"`
}
// CDNUpdateCustomDomainRequest represents a request to update the custom domain of a CDN.
type CDNUpdateCustomDomainRequest struct {
CustomDomain string `json:"custom_domain"`
CertificateID string `json:"certificate_id"`
}
// CDNFlushCacheRequest represents a request to flush cache of a CDN.
type CDNFlushCacheRequest struct {
Files []string `json:"files"`
}
// List all CDN endpoints
func (c CDNServiceOp) List(ctx context.Context, opt *ListOptions) ([]CDN, *Response, error) {
path, err := addOptions(cdnBasePath, opt)
if err != nil {
return nil, nil, err
}
req, err := c.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(cdnsRoot)
resp, err := c.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
if l := root.Links; l != nil {
resp.Links = l
}
return root.Endpoints, resp, err
}
// Get individual CDN. It requires a non-empty cdn id.
func (c CDNServiceOp) Get(ctx context.Context, id string) (*CDN, *Response, error) {
if len(id) == 0 {
return nil, nil, NewArgError("id", "cannot be an empty string")
}
path := fmt.Sprintf("%s/%s", cdnBasePath, id)
req, err := c.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(cdnRoot)
resp, err := c.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Endpoint, resp, err
}
// Create a new CDN
func (c CDNServiceOp) Create(ctx context.Context, createRequest *CDNCreateRequest) (*CDN, *Response, error) {
if createRequest == nil {
return nil, nil, NewArgError("createRequest", "cannot be nil")
}
req, err := c.client.NewRequest(ctx, http.MethodPost, cdnBasePath, createRequest)
if err != nil {
return nil, nil, err
}
root := new(cdnRoot)
resp, err := c.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Endpoint, resp, err
}
// UpdateTTL updates the ttl of an individual CDN
func (c CDNServiceOp) UpdateTTL(ctx context.Context, id string, updateRequest *CDNUpdateTTLRequest) (*CDN, *Response, error) {
return c.update(ctx, id, updateRequest)
}
// UpdateCustomDomain sets or removes the custom domain of an individual CDN
func (c CDNServiceOp) UpdateCustomDomain(ctx context.Context, id string, updateRequest *CDNUpdateCustomDomainRequest) (*CDN, *Response, error) {
return c.update(ctx, id, updateRequest)
}
func (c CDNServiceOp) update(ctx context.Context, id string, updateRequest interface{}) (*CDN, *Response, error) {
if updateRequest == nil {
return nil, nil, NewArgError("updateRequest", "cannot be nil")
}
if len(id) == 0 {
return nil, nil, NewArgError("id", "cannot be an empty string")
}
path := fmt.Sprintf("%s/%s", cdnBasePath, id)
req, err := c.client.NewRequest(ctx, http.MethodPut, path, updateRequest)
if err != nil {
return nil, nil, err
}
root := new(cdnRoot)
resp, err := c.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Endpoint, resp, err
}
// FlushCache flushes the cache of an individual CDN. Requires a non-empty slice of file paths and/or wildcards
func (c CDNServiceOp) FlushCache(ctx context.Context, id string, flushCacheRequest *CDNFlushCacheRequest) (*Response, error) {
if flushCacheRequest == nil {
return nil, NewArgError("flushCacheRequest", "cannot be nil")
}
if len(id) == 0 {
return nil, NewArgError("id", "cannot be an empty string")
}
path := fmt.Sprintf("%s/%s/cache", cdnBasePath, id)
req, err := c.client.NewRequest(ctx, http.MethodDelete, path, flushCacheRequest)
if err != nil {
return nil, err
}
resp, err := c.client.Do(ctx, req, nil)
return resp, err
}
// Delete an individual CDN
func (c CDNServiceOp) Delete(ctx context.Context, id string) (*Response, error) {
if len(id) == 0 {
return nil, NewArgError("id", "cannot be an empty string")
}
path := fmt.Sprintf("%s/%s", cdnBasePath, id)
req, err := c.client.NewRequest(ctx, http.MethodDelete, path, nil)
if err != nil {
return nil, err
}
resp, err := c.client.Do(ctx, req, nil)
return resp, err
}

126
vendor/github.com/digitalocean/godo/certificates.go generated vendored Normal file
View File

@ -0,0 +1,126 @@
package godo
import (
"context"
"net/http"
"path"
)
const certificatesBasePath = "/v2/certificates"
// CertificatesService is an interface for managing certificates with the DigitalOcean API.
// See: https://developers.digitalocean.com/documentation/v2/#certificates
type CertificatesService interface {
Get(context.Context, string) (*Certificate, *Response, error)
List(context.Context, *ListOptions) ([]Certificate, *Response, error)
Create(context.Context, *CertificateRequest) (*Certificate, *Response, error)
Delete(context.Context, string) (*Response, error)
}
// Certificate represents a DigitalOcean certificate configuration.
type Certificate struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
DNSNames []string `json:"dns_names,omitempty"`
NotAfter string `json:"not_after,omitempty"`
SHA1Fingerprint string `json:"sha1_fingerprint,omitempty"`
Created string `json:"created_at,omitempty"`
State string `json:"state,omitempty"`
Type string `json:"type,omitempty"`
}
// CertificateRequest represents configuration for a new certificate.
type CertificateRequest struct {
Name string `json:"name,omitempty"`
DNSNames []string `json:"dns_names,omitempty"`
PrivateKey string `json:"private_key,omitempty"`
LeafCertificate string `json:"leaf_certificate,omitempty"`
CertificateChain string `json:"certificate_chain,omitempty"`
Type string `json:"type,omitempty"`
}
type certificateRoot struct {
Certificate *Certificate `json:"certificate"`
}
type certificatesRoot struct {
Certificates []Certificate `json:"certificates"`
Links *Links `json:"links"`
}
// CertificatesServiceOp handles communication with certificates methods of the DigitalOcean API.
type CertificatesServiceOp struct {
client *Client
}
var _ CertificatesService = &CertificatesServiceOp{}
// Get an existing certificate by its identifier.
func (c *CertificatesServiceOp) Get(ctx context.Context, cID string) (*Certificate, *Response, error) {
urlStr := path.Join(certificatesBasePath, cID)
req, err := c.client.NewRequest(ctx, http.MethodGet, urlStr, nil)
if err != nil {
return nil, nil, err
}
root := new(certificateRoot)
resp, err := c.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Certificate, resp, nil
}
// List all certificates.
func (c *CertificatesServiceOp) List(ctx context.Context, opt *ListOptions) ([]Certificate, *Response, error) {
urlStr, err := addOptions(certificatesBasePath, opt)
if err != nil {
return nil, nil, err
}
req, err := c.client.NewRequest(ctx, http.MethodGet, urlStr, nil)
if err != nil {
return nil, nil, err
}
root := new(certificatesRoot)
resp, err := c.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
if l := root.Links; l != nil {
resp.Links = l
}
return root.Certificates, resp, nil
}
// Create a new certificate with provided configuration.
func (c *CertificatesServiceOp) Create(ctx context.Context, cr *CertificateRequest) (*Certificate, *Response, error) {
req, err := c.client.NewRequest(ctx, http.MethodPost, certificatesBasePath, cr)
if err != nil {
return nil, nil, err
}
root := new(certificateRoot)
resp, err := c.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Certificate, resp, nil
}
// Delete a certificate by its identifier.
func (c *CertificatesServiceOp) Delete(ctx context.Context, cID string) (*Response, error) {
urlStr := path.Join(certificatesBasePath, cID)
req, err := c.client.NewRequest(ctx, http.MethodDelete, urlStr, nil)
if err != nil {
return nil, err
}
return c.client.Do(ctx, req, nil)
}

671
vendor/github.com/digitalocean/godo/databases.go generated vendored Normal file
View File

@ -0,0 +1,671 @@
package godo
import (
"context"
"fmt"
"net/http"
"time"
)
const (
databaseBasePath = "/v2/databases"
databaseSinglePath = databaseBasePath + "/%s"
databaseResizePath = databaseBasePath + "/%s/resize"
databaseMigratePath = databaseBasePath + "/%s/migrate"
databaseMaintenancePath = databaseBasePath + "/%s/maintenance"
databaseBackupsPath = databaseBasePath + "/%s/backups"
databaseUsersPath = databaseBasePath + "/%s/users"
databaseUserPath = databaseBasePath + "/%s/users/%s"
databaseDBPath = databaseBasePath + "/%s/dbs/%s"
databaseDBsPath = databaseBasePath + "/%s/dbs"
databasePoolPath = databaseBasePath + "/%s/pools/%s"
databasePoolsPath = databaseBasePath + "/%s/pools"
databaseReplicaPath = databaseBasePath + "/%s/replicas/%s"
databaseReplicasPath = databaseBasePath + "/%s/replicas"
evictionPolicyPath = databaseBasePath + "/%s/eviction_policy"
)
// DatabasesService is an interface for interfacing with the databases endpoints
// of the DigitalOcean API.
// See: https://developers.digitalocean.com/documentation/v2#databases
type DatabasesService interface {
List(context.Context, *ListOptions) ([]Database, *Response, error)
Get(context.Context, string) (*Database, *Response, error)
Create(context.Context, *DatabaseCreateRequest) (*Database, *Response, error)
Delete(context.Context, string) (*Response, error)
Resize(context.Context, string, *DatabaseResizeRequest) (*Response, error)
Migrate(context.Context, string, *DatabaseMigrateRequest) (*Response, error)
UpdateMaintenance(context.Context, string, *DatabaseUpdateMaintenanceRequest) (*Response, error)
ListBackups(context.Context, string, *ListOptions) ([]DatabaseBackup, *Response, error)
GetUser(context.Context, string, string) (*DatabaseUser, *Response, error)
ListUsers(context.Context, string, *ListOptions) ([]DatabaseUser, *Response, error)
CreateUser(context.Context, string, *DatabaseCreateUserRequest) (*DatabaseUser, *Response, error)
DeleteUser(context.Context, string, string) (*Response, error)
ListDBs(context.Context, string, *ListOptions) ([]DatabaseDB, *Response, error)
CreateDB(context.Context, string, *DatabaseCreateDBRequest) (*DatabaseDB, *Response, error)
GetDB(context.Context, string, string) (*DatabaseDB, *Response, error)
DeleteDB(context.Context, string, string) (*Response, error)
ListPools(context.Context, string, *ListOptions) ([]DatabasePool, *Response, error)
CreatePool(context.Context, string, *DatabaseCreatePoolRequest) (*DatabasePool, *Response, error)
GetPool(context.Context, string, string) (*DatabasePool, *Response, error)
DeletePool(context.Context, string, string) (*Response, error)
GetReplica(context.Context, string, string) (*DatabaseReplica, *Response, error)
ListReplicas(context.Context, string, *ListOptions) ([]DatabaseReplica, *Response, error)
CreateReplica(context.Context, string, *DatabaseCreateReplicaRequest) (*DatabaseReplica, *Response, error)
DeleteReplica(context.Context, string, string) (*Response, error)
GetEvictionPolicy(context.Context, string) (string, *Response, error)
SetEvictionPolicy(context.Context, string, string) (*Response, error)
}
// DatabasesServiceOp handles communication with the Databases related methods
// of the DigitalOcean API.
type DatabasesServiceOp struct {
client *Client
}
var _ DatabasesService = &DatabasesServiceOp{}
// Database represents a DigitalOcean managed database product. These managed databases
// are usually comprised of a cluster of database nodes, a primary and 0 or more replicas.
// The EngineSlug is a string which indicates the type of database service. Some examples are
// "pg", "mysql" or "redis". A Database also includes connection information and other
// properties of the service like region, size and current status.
type Database struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
EngineSlug string `json:"engine,omitempty"`
VersionSlug string `json:"version,omitempty"`
Connection *DatabaseConnection `json:"connection,omitempty"`
PrivateConnection *DatabaseConnection `json:"private_connection,omitempty"`
Users []DatabaseUser `json:"users,omitempty"`
NumNodes int `json:"num_nodes,omitempty"`
SizeSlug string `json:"size,omitempty"`
DBNames []string `json:"db_names,omitempty"`
RegionSlug string `json:"region,omitempty"`
Status string `json:"status,omitempty"`
MaintenanceWindow *DatabaseMaintenanceWindow `json:"maintenance_window,omitempty"`
CreatedAt time.Time `json:"created_at,omitempty"`
PrivateNetworkUUID string `json:"private_network_uuid,omitempty"`
Tags []string `json:"tags,omitempty"`
}
// DatabaseConnection represents a database connection
type DatabaseConnection struct {
URI string `json:"uri,omitempty"`
Database string `json:"database,omitempty"`
Host string `json:"host,omitempty"`
Port int `json:"port,omitempty"`
User string `json:"user,omitempty"`
Password string `json:"password,omitempty"`
SSL bool `json:"ssl,omitempty"`
}
// DatabaseUser represents a user in the database
type DatabaseUser struct {
Name string `json:"name,omitempty"`
Role string `json:"role,omitempty"`
Password string `json:"password,omitempty"`
}
// DatabaseMaintenanceWindow represents the maintenance_window of a database
// cluster
type DatabaseMaintenanceWindow struct {
Day string `json:"day,omitempty"`
Hour string `json:"hour,omitempty"`
Pending bool `json:"pending,omitempty"`
Description []string `json:"description,omitempty"`
}
// DatabaseBackup represents a database backup.
type DatabaseBackup struct {
CreatedAt time.Time `json:"created_at,omitempty"`
SizeGigabytes float64 `json:"size_gigabytes,omitempty"`
}
// DatabaseCreateRequest represents a request to create a database cluster
type DatabaseCreateRequest struct {
Name string `json:"name,omitempty"`
EngineSlug string `json:"engine,omitempty"`
Version string `json:"version,omitempty"`
SizeSlug string `json:"size,omitempty"`
Region string `json:"region,omitempty"`
NumNodes int `json:"num_nodes,omitempty"`
PrivateNetworkUUID string `json:"private_network_uuid"`
Tags []string `json:"tags,omitempty"`
}
// DatabaseResizeRequest can be used to initiate a database resize operation.
type DatabaseResizeRequest struct {
SizeSlug string `json:"size,omitempty"`
NumNodes int `json:"num_nodes,omitempty"`
}
// DatabaseMigrateRequest can be used to initiate a database migrate operation.
type DatabaseMigrateRequest struct {
Region string `json:"region,omitempty"`
PrivateNetworkUUID string `json:"private_network_uuid"`
}
// DatabaseUpdateMaintenanceRequest can be used to update the database's maintenance window.
type DatabaseUpdateMaintenanceRequest struct {
Day string `json:"day,omitempty"`
Hour string `json:"hour,omitempty"`
}
// DatabaseDB represents an engine-specific database created within a database cluster. For SQL
// databases like PostgreSQL or MySQL, a "DB" refers to a database created on the RDBMS. For instance,
// a PostgreSQL database server can contain many database schemas, each with it's own settings, access
// permissions and data. ListDBs will return all databases present on the server.
type DatabaseDB struct {
Name string `json:"name"`
}
// DatabaseReplica represents a read-only replica of a particular database
type DatabaseReplica struct {
Name string `json:"name"`
Connection *DatabaseConnection `json:"connection"`
PrivateConnection *DatabaseConnection `json:"private_connection,omitempty"`
Region string `json:"region"`
Status string `json:"status"`
CreatedAt time.Time `json:"created_at"`
PrivateNetworkUUID string `json:"private_network_uuid,omitempty"`
Tags []string `json:"tags,omitempty"`
}
// DatabasePool represents a database connection pool
type DatabasePool struct {
User string `json:"user"`
Name string `json:"name"`
Size int `json:"size"`
Database string `json:"db"`
Mode string `json:"mode"`
Connection *DatabaseConnection `json:"connection"`
PrivateConnection *DatabaseConnection `json:"private_connection,omitempty"`
}
// DatabaseCreatePoolRequest is used to create a new database connection pool
type DatabaseCreatePoolRequest struct {
User string `json:"user"`
Name string `json:"name"`
Size int `json:"size"`
Database string `json:"db"`
Mode string `json:"mode"`
}
// DatabaseCreateUserRequest is used to create a new database user
type DatabaseCreateUserRequest struct {
Name string `json:"name"`
}
// DatabaseCreateDBRequest is used to create a new engine-specific database within the cluster
type DatabaseCreateDBRequest struct {
Name string `json:"name"`
}
// DatabaseCreateReplicaRequest is used to create a new read-only replica
type DatabaseCreateReplicaRequest struct {
Name string `json:"name"`
Region string `json:"region"`
Size string `json:"size"`
PrivateNetworkUUID string `json:"private_network_uuid"`
Tags []string `json:"tags,omitempty"`
}
type databaseUserRoot struct {
User *DatabaseUser `json:"user"`
}
type databaseUsersRoot struct {
Users []DatabaseUser `json:"users"`
}
type databaseDBRoot struct {
DB *DatabaseDB `json:"db"`
}
type databaseDBsRoot struct {
DBs []DatabaseDB `json:"dbs"`
}
type databasesRoot struct {
Databases []Database `json:"databases"`
}
type databaseRoot struct {
Database *Database `json:"database"`
}
type databaseBackupsRoot struct {
Backups []DatabaseBackup `json:"backups"`
}
type databasePoolRoot struct {
Pool *DatabasePool `json:"pool"`
}
type databasePoolsRoot struct {
Pools []DatabasePool `json:"pools"`
}
type databaseReplicaRoot struct {
Replica *DatabaseReplica `json:"replica"`
}
type databaseReplicasRoot struct {
Replicas []DatabaseReplica `json:"replicas"`
}
type evictionPolicyRoot struct {
EvictionPolicy string `json:"eviction_policy"`
}
func (d Database) URN() string {
return ToURN("dbaas", d.ID)
}
// List returns a list of the Databases visible with the caller's API token
func (svc *DatabasesServiceOp) List(ctx context.Context, opts *ListOptions) ([]Database, *Response, error) {
path := databaseBasePath
path, err := addOptions(path, opts)
if err != nil {
return nil, nil, err
}
req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(databasesRoot)
resp, err := svc.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Databases, resp, nil
}
// Get retrieves the details of a database cluster
func (svc *DatabasesServiceOp) Get(ctx context.Context, databaseID string) (*Database, *Response, error) {
path := fmt.Sprintf(databaseSinglePath, databaseID)
req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(databaseRoot)
resp, err := svc.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Database, resp, nil
}
// Create creates a database cluster
func (svc *DatabasesServiceOp) Create(ctx context.Context, create *DatabaseCreateRequest) (*Database, *Response, error) {
path := databaseBasePath
req, err := svc.client.NewRequest(ctx, http.MethodPost, path, create)
if err != nil {
return nil, nil, err
}
root := new(databaseRoot)
resp, err := svc.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Database, resp, nil
}
// Delete deletes a database cluster. There is no way to recover a cluster once
// it has been destroyed.
func (svc *DatabasesServiceOp) Delete(ctx context.Context, databaseID string) (*Response, error) {
path := fmt.Sprintf("%s/%s", databaseBasePath, databaseID)
req, err := svc.client.NewRequest(ctx, http.MethodDelete, path, nil)
if err != nil {
return nil, err
}
resp, err := svc.client.Do(ctx, req, nil)
if err != nil {
return resp, err
}
return resp, nil
}
// Resize resizes a database cluster by number of nodes or size
func (svc *DatabasesServiceOp) Resize(ctx context.Context, databaseID string, resize *DatabaseResizeRequest) (*Response, error) {
path := fmt.Sprintf(databaseResizePath, databaseID)
req, err := svc.client.NewRequest(ctx, http.MethodPut, path, resize)
if err != nil {
return nil, err
}
resp, err := svc.client.Do(ctx, req, nil)
if err != nil {
return resp, err
}
return resp, nil
}
// Migrate migrates a database cluster to a new region
func (svc *DatabasesServiceOp) Migrate(ctx context.Context, databaseID string, migrate *DatabaseMigrateRequest) (*Response, error) {
path := fmt.Sprintf(databaseMigratePath, databaseID)
req, err := svc.client.NewRequest(ctx, http.MethodPut, path, migrate)
if err != nil {
return nil, err
}
resp, err := svc.client.Do(ctx, req, nil)
if err != nil {
return resp, err
}
return resp, nil
}
// UpdateMaintenance updates the maintenance window on a cluster
func (svc *DatabasesServiceOp) UpdateMaintenance(ctx context.Context, databaseID string, maintenance *DatabaseUpdateMaintenanceRequest) (*Response, error) {
path := fmt.Sprintf(databaseMaintenancePath, databaseID)
req, err := svc.client.NewRequest(ctx, http.MethodPut, path, maintenance)
if err != nil {
return nil, err
}
resp, err := svc.client.Do(ctx, req, nil)
if err != nil {
return resp, err
}
return resp, nil
}
// ListBackups returns a list of the current backups of a database
func (svc *DatabasesServiceOp) ListBackups(ctx context.Context, databaseID string, opts *ListOptions) ([]DatabaseBackup, *Response, error) {
path := fmt.Sprintf(databaseBackupsPath, databaseID)
path, err := addOptions(path, opts)
if err != nil {
return nil, nil, err
}
req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(databaseBackupsRoot)
resp, err := svc.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Backups, resp, nil
}
// GetUser returns the database user identified by userID
func (svc *DatabasesServiceOp) GetUser(ctx context.Context, databaseID, userID string) (*DatabaseUser, *Response, error) {
path := fmt.Sprintf(databaseUserPath, databaseID, userID)
req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(databaseUserRoot)
resp, err := svc.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.User, resp, nil
}
// ListUsers returns all database users for the database
func (svc *DatabasesServiceOp) ListUsers(ctx context.Context, databaseID string, opts *ListOptions) ([]DatabaseUser, *Response, error) {
path := fmt.Sprintf(databaseUsersPath, databaseID)
path, err := addOptions(path, opts)
if err != nil {
return nil, nil, err
}
req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(databaseUsersRoot)
resp, err := svc.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Users, resp, nil
}
// CreateUser will create a new database user
func (svc *DatabasesServiceOp) CreateUser(ctx context.Context, databaseID string, createUser *DatabaseCreateUserRequest) (*DatabaseUser, *Response, error) {
path := fmt.Sprintf(databaseUsersPath, databaseID)
req, err := svc.client.NewRequest(ctx, http.MethodPost, path, createUser)
if err != nil {
return nil, nil, err
}
root := new(databaseUserRoot)
resp, err := svc.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.User, resp, nil
}
// DeleteUser will delete an existing database user
func (svc *DatabasesServiceOp) DeleteUser(ctx context.Context, databaseID, userID string) (*Response, error) {
path := fmt.Sprintf(databaseUserPath, databaseID, userID)
req, err := svc.client.NewRequest(ctx, http.MethodDelete, path, nil)
if err != nil {
return nil, err
}
resp, err := svc.client.Do(ctx, req, nil)
if err != nil {
return resp, err
}
return resp, nil
}
// ListDBs returns all databases for a given database cluster
func (svc *DatabasesServiceOp) ListDBs(ctx context.Context, databaseID string, opts *ListOptions) ([]DatabaseDB, *Response, error) {
path := fmt.Sprintf(databaseDBsPath, databaseID)
path, err := addOptions(path, opts)
if err != nil {
return nil, nil, err
}
req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(databaseDBsRoot)
resp, err := svc.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.DBs, resp, nil
}
// GetDB returns a single database by name
func (svc *DatabasesServiceOp) GetDB(ctx context.Context, databaseID, name string) (*DatabaseDB, *Response, error) {
path := fmt.Sprintf(databaseDBPath, databaseID, name)
req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(databaseDBRoot)
resp, err := svc.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.DB, resp, nil
}
// CreateDB will create a new database
func (svc *DatabasesServiceOp) CreateDB(ctx context.Context, databaseID string, createDB *DatabaseCreateDBRequest) (*DatabaseDB, *Response, error) {
path := fmt.Sprintf(databaseDBsPath, databaseID)
req, err := svc.client.NewRequest(ctx, http.MethodPost, path, createDB)
if err != nil {
return nil, nil, err
}
root := new(databaseDBRoot)
resp, err := svc.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.DB, resp, nil
}
// DeleteDB will delete an existing database
func (svc *DatabasesServiceOp) DeleteDB(ctx context.Context, databaseID, name string) (*Response, error) {
path := fmt.Sprintf(databaseDBPath, databaseID, name)
req, err := svc.client.NewRequest(ctx, http.MethodDelete, path, nil)
if err != nil {
return nil, err
}
resp, err := svc.client.Do(ctx, req, nil)
if err != nil {
return resp, err
}
return resp, nil
}
// ListPools returns all connection pools for a given database cluster
func (svc *DatabasesServiceOp) ListPools(ctx context.Context, databaseID string, opts *ListOptions) ([]DatabasePool, *Response, error) {
path := fmt.Sprintf(databasePoolsPath, databaseID)
path, err := addOptions(path, opts)
if err != nil {
return nil, nil, err
}
req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(databasePoolsRoot)
resp, err := svc.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Pools, resp, nil
}
// GetPool returns a single database connection pool by name
func (svc *DatabasesServiceOp) GetPool(ctx context.Context, databaseID, name string) (*DatabasePool, *Response, error) {
path := fmt.Sprintf(databasePoolPath, databaseID, name)
req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(databasePoolRoot)
resp, err := svc.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Pool, resp, nil
}
// CreatePool will create a new database connection pool
func (svc *DatabasesServiceOp) CreatePool(ctx context.Context, databaseID string, createPool *DatabaseCreatePoolRequest) (*DatabasePool, *Response, error) {
path := fmt.Sprintf(databasePoolsPath, databaseID)
req, err := svc.client.NewRequest(ctx, http.MethodPost, path, createPool)
if err != nil {
return nil, nil, err
}
root := new(databasePoolRoot)
resp, err := svc.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Pool, resp, nil
}
// DeletePool will delete an existing database connection pool
func (svc *DatabasesServiceOp) DeletePool(ctx context.Context, databaseID, name string) (*Response, error) {
path := fmt.Sprintf(databasePoolPath, databaseID, name)
req, err := svc.client.NewRequest(ctx, http.MethodDelete, path, nil)
if err != nil {
return nil, err
}
resp, err := svc.client.Do(ctx, req, nil)
if err != nil {
return resp, err
}
return resp, nil
}
// GetReplica returns a single database replica
func (svc *DatabasesServiceOp) GetReplica(ctx context.Context, databaseID, name string) (*DatabaseReplica, *Response, error) {
path := fmt.Sprintf(databaseReplicaPath, databaseID, name)
req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(databaseReplicaRoot)
resp, err := svc.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Replica, resp, nil
}
// ListReplicas returns all read-only replicas for a given database cluster
func (svc *DatabasesServiceOp) ListReplicas(ctx context.Context, databaseID string, opts *ListOptions) ([]DatabaseReplica, *Response, error) {
path := fmt.Sprintf(databaseReplicasPath, databaseID)
path, err := addOptions(path, opts)
if err != nil {
return nil, nil, err
}
req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(databaseReplicasRoot)
resp, err := svc.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Replicas, resp, nil
}
// CreateReplica will create a new database connection pool
func (svc *DatabasesServiceOp) CreateReplica(ctx context.Context, databaseID string, createReplica *DatabaseCreateReplicaRequest) (*DatabaseReplica, *Response, error) {
path := fmt.Sprintf(databaseReplicasPath, databaseID)
req, err := svc.client.NewRequest(ctx, http.MethodPost, path, createReplica)
if err != nil {
return nil, nil, err
}
root := new(databaseReplicaRoot)
resp, err := svc.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Replica, resp, nil
}
// DeleteReplica will delete an existing database replica
func (svc *DatabasesServiceOp) DeleteReplica(ctx context.Context, databaseID, name string) (*Response, error) {
path := fmt.Sprintf(databaseReplicaPath, databaseID, name)
req, err := svc.client.NewRequest(ctx, http.MethodDelete, path, nil)
if err != nil {
return nil, err
}
resp, err := svc.client.Do(ctx, req, nil)
if err != nil {
return resp, err
}
return resp, nil
}
// GetEvictionPolicy loads the eviction policy for a given Redis cluster.
func (svc *DatabasesServiceOp) GetEvictionPolicy(ctx context.Context, databaseID string) (string, *Response, error) {
path := fmt.Sprintf(evictionPolicyPath, databaseID)
req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return "", nil, err
}
root := new(evictionPolicyRoot)
resp, err := svc.client.Do(ctx, req, root)
if err != nil {
return "", resp, err
}
return root.EvictionPolicy, resp, nil
}
// SetEvictionPolicy updates the eviction policy for a given Redis cluster.
func (svc *DatabasesServiceOp) SetEvictionPolicy(ctx context.Context, databaseID, policy string) (*Response, error) {
path := fmt.Sprintf(evictionPolicyPath, databaseID)
root := &evictionPolicyRoot{EvictionPolicy: policy}
req, err := svc.client.NewRequest(ctx, http.MethodPut, path, root)
if err != nil {
return nil, err
}
resp, err := svc.client.Do(ctx, req, nil)
if err != nil {
return resp, err
}
return resp, nil
}

11
vendor/github.com/digitalocean/godo/doc.go generated vendored Normal file
View File

@ -0,0 +1,11 @@
// Package godo is the DigtalOcean API v2 client for Go
//
// Databases
//
// The Databases service provides access to the DigitalOcean managed database
// suite of products. Customers can create new database clusters, migrate them
// between regions, create replicas and interact with their configurations.
// Each database service is refered to as a Database. A SQL database service
// can have multiple databases residing in the system. To help make these
// entities distinct from Databases in godo, we refer to them here as DatabaseDBs.
package godo

337
vendor/github.com/digitalocean/godo/domains.go generated vendored Normal file
View File

@ -0,0 +1,337 @@
package godo
import (
"context"
"fmt"
"net/http"
)
const domainsBasePath = "v2/domains"
// DomainsService is an interface for managing DNS with the DigitalOcean API.
// See: https://developers.digitalocean.com/documentation/v2#domains and
// https://developers.digitalocean.com/documentation/v2#domain-records
type DomainsService interface {
List(context.Context, *ListOptions) ([]Domain, *Response, error)
Get(context.Context, string) (*Domain, *Response, error)
Create(context.Context, *DomainCreateRequest) (*Domain, *Response, error)
Delete(context.Context, string) (*Response, error)
Records(context.Context, string, *ListOptions) ([]DomainRecord, *Response, error)
Record(context.Context, string, int) (*DomainRecord, *Response, error)
DeleteRecord(context.Context, string, int) (*Response, error)
EditRecord(context.Context, string, int, *DomainRecordEditRequest) (*DomainRecord, *Response, error)
CreateRecord(context.Context, string, *DomainRecordEditRequest) (*DomainRecord, *Response, error)
}
// DomainsServiceOp handles communication with the domain related methods of the
// DigitalOcean API.
type DomainsServiceOp struct {
client *Client
}
var _ DomainsService = &DomainsServiceOp{}
// Domain represents a DigitalOcean domain
type Domain struct {
Name string `json:"name"`
TTL int `json:"ttl"`
ZoneFile string `json:"zone_file"`
}
// domainRoot represents a response from the DigitalOcean API
type domainRoot struct {
Domain *Domain `json:"domain"`
}
type domainsRoot struct {
Domains []Domain `json:"domains"`
Links *Links `json:"links"`
}
// DomainCreateRequest respresents a request to create a domain.
type DomainCreateRequest struct {
Name string `json:"name"`
IPAddress string `json:"ip_address,omitempty"`
}
// DomainRecordRoot is the root of an individual Domain Record response
type domainRecordRoot struct {
DomainRecord *DomainRecord `json:"domain_record"`
}
// DomainRecordsRoot is the root of a group of Domain Record responses
type domainRecordsRoot struct {
DomainRecords []DomainRecord `json:"domain_records"`
Links *Links `json:"links"`
}
// DomainRecord represents a DigitalOcean DomainRecord
type DomainRecord struct {
ID int `json:"id,float64,omitempty"`
Type string `json:"type,omitempty"`
Name string `json:"name,omitempty"`
Data string `json:"data,omitempty"`
Priority int `json:"priority"`
Port int `json:"port,omitempty"`
TTL int `json:"ttl,omitempty"`
Weight int `json:"weight"`
Flags int `json:"flags"`
Tag string `json:"tag,omitempty"`
}
// DomainRecordEditRequest represents a request to update a domain record.
type DomainRecordEditRequest struct {
Type string `json:"type,omitempty"`
Name string `json:"name,omitempty"`
Data string `json:"data,omitempty"`
Priority int `json:"priority"`
Port int `json:"port,omitempty"`
TTL int `json:"ttl,omitempty"`
Weight int `json:"weight"`
Flags int `json:"flags"`
Tag string `json:"tag,omitempty"`
}
func (d Domain) String() string {
return Stringify(d)
}
func (d Domain) URN() string {
return ToURN("Domain", d.Name)
}
// List all domains.
func (s DomainsServiceOp) List(ctx context.Context, opt *ListOptions) ([]Domain, *Response, error) {
path := domainsBasePath
path, err := addOptions(path, opt)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(domainsRoot)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
if l := root.Links; l != nil {
resp.Links = l
}
return root.Domains, resp, err
}
// Get individual domain. It requires a non-empty domain name.
func (s *DomainsServiceOp) Get(ctx context.Context, name string) (*Domain, *Response, error) {
if len(name) < 1 {
return nil, nil, NewArgError("name", "cannot be an empty string")
}
path := fmt.Sprintf("%s/%s", domainsBasePath, name)
req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(domainRoot)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Domain, resp, err
}
// Create a new domain
func (s *DomainsServiceOp) Create(ctx context.Context, createRequest *DomainCreateRequest) (*Domain, *Response, error) {
if createRequest == nil {
return nil, nil, NewArgError("createRequest", "cannot be nil")
}
path := domainsBasePath
req, err := s.client.NewRequest(ctx, http.MethodPost, path, createRequest)
if err != nil {
return nil, nil, err
}
root := new(domainRoot)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Domain, resp, err
}
// Delete domain
func (s *DomainsServiceOp) Delete(ctx context.Context, name string) (*Response, error) {
if len(name) < 1 {
return nil, NewArgError("name", "cannot be an empty string")
}
path := fmt.Sprintf("%s/%s", domainsBasePath, name)
req, err := s.client.NewRequest(ctx, http.MethodDelete, path, nil)
if err != nil {
return nil, err
}
resp, err := s.client.Do(ctx, req, nil)
return resp, err
}
// Converts a DomainRecord to a string.
func (d DomainRecord) String() string {
return Stringify(d)
}
// Converts a DomainRecordEditRequest to a string.
func (d DomainRecordEditRequest) String() string {
return Stringify(d)
}
// Records returns a slice of DomainRecords for a domain
func (s *DomainsServiceOp) Records(ctx context.Context, domain string, opt *ListOptions) ([]DomainRecord, *Response, error) {
if len(domain) < 1 {
return nil, nil, NewArgError("domain", "cannot be an empty string")
}
path := fmt.Sprintf("%s/%s/records", domainsBasePath, domain)
path, err := addOptions(path, opt)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(domainRecordsRoot)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
if l := root.Links; l != nil {
resp.Links = l
}
return root.DomainRecords, resp, err
}
// Record returns the record id from a domain
func (s *DomainsServiceOp) Record(ctx context.Context, domain string, id int) (*DomainRecord, *Response, error) {
if len(domain) < 1 {
return nil, nil, NewArgError("domain", "cannot be an empty string")
}
if id < 1 {
return nil, nil, NewArgError("id", "cannot be less than 1")
}
path := fmt.Sprintf("%s/%s/records/%d", domainsBasePath, domain, id)
req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
record := new(domainRecordRoot)
resp, err := s.client.Do(ctx, req, record)
if err != nil {
return nil, resp, err
}
return record.DomainRecord, resp, err
}
// DeleteRecord deletes a record from a domain identified by id
func (s *DomainsServiceOp) DeleteRecord(ctx context.Context, domain string, id int) (*Response, error) {
if len(domain) < 1 {
return nil, NewArgError("domain", "cannot be an empty string")
}
if id < 1 {
return nil, NewArgError("id", "cannot be less than 1")
}
path := fmt.Sprintf("%s/%s/records/%d", domainsBasePath, domain, id)
req, err := s.client.NewRequest(ctx, http.MethodDelete, path, nil)
if err != nil {
return nil, err
}
resp, err := s.client.Do(ctx, req, nil)
return resp, err
}
// EditRecord edits a record using a DomainRecordEditRequest
func (s *DomainsServiceOp) EditRecord(ctx context.Context,
domain string,
id int,
editRequest *DomainRecordEditRequest,
) (*DomainRecord, *Response, error) {
if len(domain) < 1 {
return nil, nil, NewArgError("domain", "cannot be an empty string")
}
if id < 1 {
return nil, nil, NewArgError("id", "cannot be less than 1")
}
if editRequest == nil {
return nil, nil, NewArgError("editRequest", "cannot be nil")
}
path := fmt.Sprintf("%s/%s/records/%d", domainsBasePath, domain, id)
req, err := s.client.NewRequest(ctx, http.MethodPut, path, editRequest)
if err != nil {
return nil, nil, err
}
root := new(domainRecordRoot)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.DomainRecord, resp, err
}
// CreateRecord creates a record using a DomainRecordEditRequest
func (s *DomainsServiceOp) CreateRecord(ctx context.Context,
domain string,
createRequest *DomainRecordEditRequest) (*DomainRecord, *Response, error) {
if len(domain) < 1 {
return nil, nil, NewArgError("domain", "cannot be empty string")
}
if createRequest == nil {
return nil, nil, NewArgError("createRequest", "cannot be nil")
}
path := fmt.Sprintf("%s/%s/records", domainsBasePath, domain)
req, err := s.client.NewRequest(ctx, http.MethodPost, path, createRequest)
if err != nil {
return nil, nil, err
}
d := new(domainRecordRoot)
resp, err := s.client.Do(ctx, req, d)
if err != nil {
return nil, resp, err
}
return d.DomainRecord, resp, err
}

329
vendor/github.com/digitalocean/godo/droplet_actions.go generated vendored Normal file
View File

@ -0,0 +1,329 @@
package godo
import (
"context"
"fmt"
"net/http"
"net/url"
)
// ActionRequest reprents DigitalOcean Action Request
type ActionRequest map[string]interface{}
// DropletActionsService is an interface for interfacing with the Droplet actions
// endpoints of the DigitalOcean API
// See: https://developers.digitalocean.com/documentation/v2#droplet-actions
type DropletActionsService interface {
Shutdown(context.Context, int) (*Action, *Response, error)
ShutdownByTag(context.Context, string) ([]Action, *Response, error)
PowerOff(context.Context, int) (*Action, *Response, error)
PowerOffByTag(context.Context, string) ([]Action, *Response, error)
PowerOn(context.Context, int) (*Action, *Response, error)
PowerOnByTag(context.Context, string) ([]Action, *Response, error)
PowerCycle(context.Context, int) (*Action, *Response, error)
PowerCycleByTag(context.Context, string) ([]Action, *Response, error)
Reboot(context.Context, int) (*Action, *Response, error)
Restore(context.Context, int, int) (*Action, *Response, error)
Resize(context.Context, int, string, bool) (*Action, *Response, error)
Rename(context.Context, int, string) (*Action, *Response, error)
Snapshot(context.Context, int, string) (*Action, *Response, error)
SnapshotByTag(context.Context, string, string) ([]Action, *Response, error)
EnableBackups(context.Context, int) (*Action, *Response, error)
EnableBackupsByTag(context.Context, string) ([]Action, *Response, error)
DisableBackups(context.Context, int) (*Action, *Response, error)
DisableBackupsByTag(context.Context, string) ([]Action, *Response, error)
PasswordReset(context.Context, int) (*Action, *Response, error)
RebuildByImageID(context.Context, int, int) (*Action, *Response, error)
RebuildByImageSlug(context.Context, int, string) (*Action, *Response, error)
ChangeKernel(context.Context, int, int) (*Action, *Response, error)
EnableIPv6(context.Context, int) (*Action, *Response, error)
EnableIPv6ByTag(context.Context, string) ([]Action, *Response, error)
EnablePrivateNetworking(context.Context, int) (*Action, *Response, error)
EnablePrivateNetworkingByTag(context.Context, string) ([]Action, *Response, error)
Get(context.Context, int, int) (*Action, *Response, error)
GetByURI(context.Context, string) (*Action, *Response, error)
}
// DropletActionsServiceOp handles communication with the Droplet action related
// methods of the DigitalOcean API.
type DropletActionsServiceOp struct {
client *Client
}
var _ DropletActionsService = &DropletActionsServiceOp{}
// Shutdown a Droplet
func (s *DropletActionsServiceOp) Shutdown(ctx context.Context, id int) (*Action, *Response, error) {
request := &ActionRequest{"type": "shutdown"}
return s.doAction(ctx, id, request)
}
// ShutdownByTag shuts down Droplets matched by a Tag.
func (s *DropletActionsServiceOp) ShutdownByTag(ctx context.Context, tag string) ([]Action, *Response, error) {
request := &ActionRequest{"type": "shutdown"}
return s.doActionByTag(ctx, tag, request)
}
// PowerOff a Droplet
func (s *DropletActionsServiceOp) PowerOff(ctx context.Context, id int) (*Action, *Response, error) {
request := &ActionRequest{"type": "power_off"}
return s.doAction(ctx, id, request)
}
// PowerOffByTag powers off Droplets matched by a Tag.
func (s *DropletActionsServiceOp) PowerOffByTag(ctx context.Context, tag string) ([]Action, *Response, error) {
request := &ActionRequest{"type": "power_off"}
return s.doActionByTag(ctx, tag, request)
}
// PowerOn a Droplet
func (s *DropletActionsServiceOp) PowerOn(ctx context.Context, id int) (*Action, *Response, error) {
request := &ActionRequest{"type": "power_on"}
return s.doAction(ctx, id, request)
}
// PowerOnByTag powers on Droplets matched by a Tag.
func (s *DropletActionsServiceOp) PowerOnByTag(ctx context.Context, tag string) ([]Action, *Response, error) {
request := &ActionRequest{"type": "power_on"}
return s.doActionByTag(ctx, tag, request)
}
// PowerCycle a Droplet
func (s *DropletActionsServiceOp) PowerCycle(ctx context.Context, id int) (*Action, *Response, error) {
request := &ActionRequest{"type": "power_cycle"}
return s.doAction(ctx, id, request)
}
// PowerCycleByTag power cycles Droplets matched by a Tag.
func (s *DropletActionsServiceOp) PowerCycleByTag(ctx context.Context, tag string) ([]Action, *Response, error) {
request := &ActionRequest{"type": "power_cycle"}
return s.doActionByTag(ctx, tag, request)
}
// Reboot a Droplet
func (s *DropletActionsServiceOp) Reboot(ctx context.Context, id int) (*Action, *Response, error) {
request := &ActionRequest{"type": "reboot"}
return s.doAction(ctx, id, request)
}
// Restore an image to a Droplet
func (s *DropletActionsServiceOp) Restore(ctx context.Context, id, imageID int) (*Action, *Response, error) {
requestType := "restore"
request := &ActionRequest{
"type": requestType,
"image": float64(imageID),
}
return s.doAction(ctx, id, request)
}
// Resize a Droplet
func (s *DropletActionsServiceOp) Resize(ctx context.Context, id int, sizeSlug string, resizeDisk bool) (*Action, *Response, error) {
requestType := "resize"
request := &ActionRequest{
"type": requestType,
"size": sizeSlug,
"disk": resizeDisk,
}
return s.doAction(ctx, id, request)
}
// Rename a Droplet
func (s *DropletActionsServiceOp) Rename(ctx context.Context, id int, name string) (*Action, *Response, error) {
requestType := "rename"
request := &ActionRequest{
"type": requestType,
"name": name,
}
return s.doAction(ctx, id, request)
}
// Snapshot a Droplet.
func (s *DropletActionsServiceOp) Snapshot(ctx context.Context, id int, name string) (*Action, *Response, error) {
requestType := "snapshot"
request := &ActionRequest{
"type": requestType,
"name": name,
}
return s.doAction(ctx, id, request)
}
// SnapshotByTag snapshots Droplets matched by a Tag.
func (s *DropletActionsServiceOp) SnapshotByTag(ctx context.Context, tag string, name string) ([]Action, *Response, error) {
requestType := "snapshot"
request := &ActionRequest{
"type": requestType,
"name": name,
}
return s.doActionByTag(ctx, tag, request)
}
// EnableBackups enables backups for a Droplet.
func (s *DropletActionsServiceOp) EnableBackups(ctx context.Context, id int) (*Action, *Response, error) {
request := &ActionRequest{"type": "enable_backups"}
return s.doAction(ctx, id, request)
}
// EnableBackupsByTag enables backups for Droplets matched by a Tag.
func (s *DropletActionsServiceOp) EnableBackupsByTag(ctx context.Context, tag string) ([]Action, *Response, error) {
request := &ActionRequest{"type": "enable_backups"}
return s.doActionByTag(ctx, tag, request)
}
// DisableBackups disables backups for a Droplet.
func (s *DropletActionsServiceOp) DisableBackups(ctx context.Context, id int) (*Action, *Response, error) {
request := &ActionRequest{"type": "disable_backups"}
return s.doAction(ctx, id, request)
}
// DisableBackupsByTag disables backups for Droplet matched by a Tag.
func (s *DropletActionsServiceOp) DisableBackupsByTag(ctx context.Context, tag string) ([]Action, *Response, error) {
request := &ActionRequest{"type": "disable_backups"}
return s.doActionByTag(ctx, tag, request)
}
// PasswordReset resets the password for a Droplet.
func (s *DropletActionsServiceOp) PasswordReset(ctx context.Context, id int) (*Action, *Response, error) {
request := &ActionRequest{"type": "password_reset"}
return s.doAction(ctx, id, request)
}
// RebuildByImageID rebuilds a Droplet from an image with a given id.
func (s *DropletActionsServiceOp) RebuildByImageID(ctx context.Context, id, imageID int) (*Action, *Response, error) {
request := &ActionRequest{"type": "rebuild", "image": imageID}
return s.doAction(ctx, id, request)
}
// RebuildByImageSlug rebuilds a Droplet from an Image matched by a given Slug.
func (s *DropletActionsServiceOp) RebuildByImageSlug(ctx context.Context, id int, slug string) (*Action, *Response, error) {
request := &ActionRequest{"type": "rebuild", "image": slug}
return s.doAction(ctx, id, request)
}
// ChangeKernel changes the kernel for a Droplet.
func (s *DropletActionsServiceOp) ChangeKernel(ctx context.Context, id, kernelID int) (*Action, *Response, error) {
request := &ActionRequest{"type": "change_kernel", "kernel": kernelID}
return s.doAction(ctx, id, request)
}
// EnableIPv6 enables IPv6 for a Droplet.
func (s *DropletActionsServiceOp) EnableIPv6(ctx context.Context, id int) (*Action, *Response, error) {
request := &ActionRequest{"type": "enable_ipv6"}
return s.doAction(ctx, id, request)
}
// EnableIPv6ByTag enables IPv6 for Droplets matched by a Tag.
func (s *DropletActionsServiceOp) EnableIPv6ByTag(ctx context.Context, tag string) ([]Action, *Response, error) {
request := &ActionRequest{"type": "enable_ipv6"}
return s.doActionByTag(ctx, tag, request)
}
// EnablePrivateNetworking enables private networking for a Droplet.
func (s *DropletActionsServiceOp) EnablePrivateNetworking(ctx context.Context, id int) (*Action, *Response, error) {
request := &ActionRequest{"type": "enable_private_networking"}
return s.doAction(ctx, id, request)
}
// EnablePrivateNetworkingByTag enables private networking for Droplets matched by a Tag.
func (s *DropletActionsServiceOp) EnablePrivateNetworkingByTag(ctx context.Context, tag string) ([]Action, *Response, error) {
request := &ActionRequest{"type": "enable_private_networking"}
return s.doActionByTag(ctx, tag, request)
}
func (s *DropletActionsServiceOp) doAction(ctx context.Context, id int, request *ActionRequest) (*Action, *Response, error) {
if id < 1 {
return nil, nil, NewArgError("id", "cannot be less than 1")
}
if request == nil {
return nil, nil, NewArgError("request", "request can't be nil")
}
path := dropletActionPath(id)
req, err := s.client.NewRequest(ctx, http.MethodPost, path, request)
if err != nil {
return nil, nil, err
}
root := new(actionRoot)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Event, resp, err
}
func (s *DropletActionsServiceOp) doActionByTag(ctx context.Context, tag string, request *ActionRequest) ([]Action, *Response, error) {
if tag == "" {
return nil, nil, NewArgError("tag", "cannot be empty")
}
if request == nil {
return nil, nil, NewArgError("request", "request can't be nil")
}
path := dropletActionPathByTag(tag)
req, err := s.client.NewRequest(ctx, http.MethodPost, path, request)
if err != nil {
return nil, nil, err
}
root := new(actionsRoot)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Actions, resp, err
}
// Get an action for a particular Droplet by id.
func (s *DropletActionsServiceOp) Get(ctx context.Context, dropletID, actionID int) (*Action, *Response, error) {
if dropletID < 1 {
return nil, nil, NewArgError("dropletID", "cannot be less than 1")
}
if actionID < 1 {
return nil, nil, NewArgError("actionID", "cannot be less than 1")
}
path := fmt.Sprintf("%s/%d", dropletActionPath(dropletID), actionID)
return s.get(ctx, path)
}
// GetByURI gets an action for a particular Droplet by id.
func (s *DropletActionsServiceOp) GetByURI(ctx context.Context, rawurl string) (*Action, *Response, error) {
u, err := url.Parse(rawurl)
if err != nil {
return nil, nil, err
}
return s.get(ctx, u.Path)
}
func (s *DropletActionsServiceOp) get(ctx context.Context, path string) (*Action, *Response, error) {
req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(actionRoot)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Event, resp, err
}
func dropletActionPath(dropletID int) string {
return fmt.Sprintf("v2/droplets/%d/actions", dropletID)
}
func dropletActionPathByTag(tag string) string {
return fmt.Sprintf("v2/droplets/actions?tag_name=%s", tag)
}

573
vendor/github.com/digitalocean/godo/droplets.go generated vendored Normal file
View File

@ -0,0 +1,573 @@
package godo
import (
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
)
const dropletBasePath = "v2/droplets"
var errNoNetworks = errors.New("no networks have been defined")
// DropletsService is an interface for interfacing with the Droplet
// endpoints of the DigitalOcean API
// See: https://developers.digitalocean.com/documentation/v2#droplets
type DropletsService interface {
List(context.Context, *ListOptions) ([]Droplet, *Response, error)
ListByTag(context.Context, string, *ListOptions) ([]Droplet, *Response, error)
Get(context.Context, int) (*Droplet, *Response, error)
Create(context.Context, *DropletCreateRequest) (*Droplet, *Response, error)
CreateMultiple(context.Context, *DropletMultiCreateRequest) ([]Droplet, *Response, error)
Delete(context.Context, int) (*Response, error)
DeleteByTag(context.Context, string) (*Response, error)
Kernels(context.Context, int, *ListOptions) ([]Kernel, *Response, error)
Snapshots(context.Context, int, *ListOptions) ([]Image, *Response, error)
Backups(context.Context, int, *ListOptions) ([]Image, *Response, error)
Actions(context.Context, int, *ListOptions) ([]Action, *Response, error)
Neighbors(context.Context, int) ([]Droplet, *Response, error)
}
// DropletsServiceOp handles communication with the Droplet related methods of the
// DigitalOcean API.
type DropletsServiceOp struct {
client *Client
}
var _ DropletsService = &DropletsServiceOp{}
// Droplet represents a DigitalOcean Droplet
type Droplet struct {
ID int `json:"id,float64,omitempty"`
Name string `json:"name,omitempty"`
Memory int `json:"memory,omitempty"`
Vcpus int `json:"vcpus,omitempty"`
Disk int `json:"disk,omitempty"`
Region *Region `json:"region,omitempty"`
Image *Image `json:"image,omitempty"`
Size *Size `json:"size,omitempty"`
SizeSlug string `json:"size_slug,omitempty"`
BackupIDs []int `json:"backup_ids,omitempty"`
NextBackupWindow *BackupWindow `json:"next_backup_window,omitempty"`
SnapshotIDs []int `json:"snapshot_ids,omitempty"`
Features []string `json:"features,omitempty"`
Locked bool `json:"locked,bool,omitempty"`
Status string `json:"status,omitempty"`
Networks *Networks `json:"networks,omitempty"`
Created string `json:"created_at,omitempty"`
Kernel *Kernel `json:"kernel,omitempty"`
Tags []string `json:"tags,omitempty"`
VolumeIDs []string `json:"volume_ids"`
VPCUUID string `json:"vpc_uuid,omitempty"`
}
// PublicIPv4 returns the public IPv4 address for the Droplet.
func (d *Droplet) PublicIPv4() (string, error) {
if d.Networks == nil {
return "", errNoNetworks
}
for _, v4 := range d.Networks.V4 {
if v4.Type == "public" {
return v4.IPAddress, nil
}
}
return "", nil
}
// PrivateIPv4 returns the private IPv4 address for the Droplet.
func (d *Droplet) PrivateIPv4() (string, error) {
if d.Networks == nil {
return "", errNoNetworks
}
for _, v4 := range d.Networks.V4 {
if v4.Type == "private" {
return v4.IPAddress, nil
}
}
return "", nil
}
// PublicIPv6 returns the public IPv6 address for the Droplet.
func (d *Droplet) PublicIPv6() (string, error) {
if d.Networks == nil {
return "", errNoNetworks
}
for _, v6 := range d.Networks.V6 {
if v6.Type == "public" {
return v6.IPAddress, nil
}
}
return "", nil
}
// Kernel object
type Kernel struct {
ID int `json:"id,float64,omitempty"`
Name string `json:"name,omitempty"`
Version string `json:"version,omitempty"`
}
// BackupWindow object
type BackupWindow struct {
Start *Timestamp `json:"start,omitempty"`
End *Timestamp `json:"end,omitempty"`
}
// Convert Droplet to a string
func (d Droplet) String() string {
return Stringify(d)
}
func (d Droplet) URN() string {
return ToURN("Droplet", d.ID)
}
// DropletRoot represents a Droplet root
type dropletRoot struct {
Droplet *Droplet `json:"droplet"`
Links *Links `json:"links,omitempty"`
}
type dropletsRoot struct {
Droplets []Droplet `json:"droplets"`
Links *Links `json:"links"`
}
type kernelsRoot struct {
Kernels []Kernel `json:"kernels,omitempty"`
Links *Links `json:"links"`
}
type dropletSnapshotsRoot struct {
Snapshots []Image `json:"snapshots,omitempty"`
Links *Links `json:"links"`
}
type backupsRoot struct {
Backups []Image `json:"backups,omitempty"`
Links *Links `json:"links"`
}
// DropletCreateImage identifies an image for the create request. It prefers slug over ID.
type DropletCreateImage struct {
ID int
Slug string
}
// MarshalJSON returns either the slug or id of the image. It returns the id
// if the slug is empty.
func (d DropletCreateImage) MarshalJSON() ([]byte, error) {
if d.Slug != "" {
return json.Marshal(d.Slug)
}
return json.Marshal(d.ID)
}
// DropletCreateVolume identifies a volume to attach for the create request. It
// prefers Name over ID,
type DropletCreateVolume struct {
ID string
Name string
}
// MarshalJSON returns an object with either the name or id of the volume. It
// returns the id if the name is empty.
func (d DropletCreateVolume) MarshalJSON() ([]byte, error) {
if d.Name != "" {
return json.Marshal(struct {
Name string `json:"name"`
}{Name: d.Name})
}
return json.Marshal(struct {
ID string `json:"id"`
}{ID: d.ID})
}
// DropletCreateSSHKey identifies a SSH Key for the create request. It prefers fingerprint over ID.
type DropletCreateSSHKey struct {
ID int
Fingerprint string
}
// MarshalJSON returns either the fingerprint or id of the ssh key. It returns
// the id if the fingerprint is empty.
func (d DropletCreateSSHKey) MarshalJSON() ([]byte, error) {
if d.Fingerprint != "" {
return json.Marshal(d.Fingerprint)
}
return json.Marshal(d.ID)
}
// DropletCreateRequest represents a request to create a Droplet.
type DropletCreateRequest struct {
Name string `json:"name"`
Region string `json:"region"`
Size string `json:"size"`
Image DropletCreateImage `json:"image"`
SSHKeys []DropletCreateSSHKey `json:"ssh_keys"`
Backups bool `json:"backups"`
IPv6 bool `json:"ipv6"`
PrivateNetworking bool `json:"private_networking"`
Monitoring bool `json:"monitoring"`
UserData string `json:"user_data,omitempty"`
Volumes []DropletCreateVolume `json:"volumes,omitempty"`
Tags []string `json:"tags"`
VPCUUID string `json:"vpc_uuid,omitempty"`
}
// DropletMultiCreateRequest is a request to create multiple Droplets.
type DropletMultiCreateRequest struct {
Names []string `json:"names"`
Region string `json:"region"`
Size string `json:"size"`
Image DropletCreateImage `json:"image"`
SSHKeys []DropletCreateSSHKey `json:"ssh_keys"`
Backups bool `json:"backups"`
IPv6 bool `json:"ipv6"`
PrivateNetworking bool `json:"private_networking"`
Monitoring bool `json:"monitoring"`
UserData string `json:"user_data,omitempty"`
Tags []string `json:"tags"`
VPCUUID string `json:"vpc_uuid,omitempty"`
}
func (d DropletCreateRequest) String() string {
return Stringify(d)
}
func (d DropletMultiCreateRequest) String() string {
return Stringify(d)
}
// Networks represents the Droplet's Networks.
type Networks struct {
V4 []NetworkV4 `json:"v4,omitempty"`
V6 []NetworkV6 `json:"v6,omitempty"`
}
// NetworkV4 represents a DigitalOcean IPv4 Network.
type NetworkV4 struct {
IPAddress string `json:"ip_address,omitempty"`
Netmask string `json:"netmask,omitempty"`
Gateway string `json:"gateway,omitempty"`
Type string `json:"type,omitempty"`
}
func (n NetworkV4) String() string {
return Stringify(n)
}
// NetworkV6 represents a DigitalOcean IPv6 network.
type NetworkV6 struct {
IPAddress string `json:"ip_address,omitempty"`
Netmask int `json:"netmask,omitempty"`
Gateway string `json:"gateway,omitempty"`
Type string `json:"type,omitempty"`
}
func (n NetworkV6) String() string {
return Stringify(n)
}
// Performs a list request given a path.
func (s *DropletsServiceOp) list(ctx context.Context, path string) ([]Droplet, *Response, error) {
req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(dropletsRoot)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
if l := root.Links; l != nil {
resp.Links = l
}
return root.Droplets, resp, err
}
// List all Droplets.
func (s *DropletsServiceOp) List(ctx context.Context, opt *ListOptions) ([]Droplet, *Response, error) {
path := dropletBasePath
path, err := addOptions(path, opt)
if err != nil {
return nil, nil, err
}
return s.list(ctx, path)
}
// ListByTag lists all Droplets matched by a Tag.
func (s *DropletsServiceOp) ListByTag(ctx context.Context, tag string, opt *ListOptions) ([]Droplet, *Response, error) {
path := fmt.Sprintf("%s?tag_name=%s", dropletBasePath, tag)
path, err := addOptions(path, opt)
if err != nil {
return nil, nil, err
}
return s.list(ctx, path)
}
// Get individual Droplet.
func (s *DropletsServiceOp) Get(ctx context.Context, dropletID int) (*Droplet, *Response, error) {
if dropletID < 1 {
return nil, nil, NewArgError("dropletID", "cannot be less than 1")
}
path := fmt.Sprintf("%s/%d", dropletBasePath, dropletID)
req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(dropletRoot)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Droplet, resp, err
}
// Create Droplet
func (s *DropletsServiceOp) Create(ctx context.Context, createRequest *DropletCreateRequest) (*Droplet, *Response, error) {
if createRequest == nil {
return nil, nil, NewArgError("createRequest", "cannot be nil")
}
path := dropletBasePath
req, err := s.client.NewRequest(ctx, http.MethodPost, path, createRequest)
if err != nil {
return nil, nil, err
}
root := new(dropletRoot)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
if l := root.Links; l != nil {
resp.Links = l
}
return root.Droplet, resp, err
}
// CreateMultiple creates multiple Droplets.
func (s *DropletsServiceOp) CreateMultiple(ctx context.Context, createRequest *DropletMultiCreateRequest) ([]Droplet, *Response, error) {
if createRequest == nil {
return nil, nil, NewArgError("createRequest", "cannot be nil")
}
path := dropletBasePath
req, err := s.client.NewRequest(ctx, http.MethodPost, path, createRequest)
if err != nil {
return nil, nil, err
}
root := new(dropletsRoot)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
if l := root.Links; l != nil {
resp.Links = l
}
return root.Droplets, resp, err
}
// Performs a delete request given a path
func (s *DropletsServiceOp) delete(ctx context.Context, path string) (*Response, error) {
req, err := s.client.NewRequest(ctx, http.MethodDelete, path, nil)
if err != nil {
return nil, err
}
resp, err := s.client.Do(ctx, req, nil)
return resp, err
}
// Delete Droplet.
func (s *DropletsServiceOp) Delete(ctx context.Context, dropletID int) (*Response, error) {
if dropletID < 1 {
return nil, NewArgError("dropletID", "cannot be less than 1")
}
path := fmt.Sprintf("%s/%d", dropletBasePath, dropletID)
return s.delete(ctx, path)
}
// DeleteByTag deletes Droplets matched by a Tag.
func (s *DropletsServiceOp) DeleteByTag(ctx context.Context, tag string) (*Response, error) {
if tag == "" {
return nil, NewArgError("tag", "cannot be empty")
}
path := fmt.Sprintf("%s?tag_name=%s", dropletBasePath, tag)
return s.delete(ctx, path)
}
// Kernels lists kernels available for a Droplet.
func (s *DropletsServiceOp) Kernels(ctx context.Context, dropletID int, opt *ListOptions) ([]Kernel, *Response, error) {
if dropletID < 1 {
return nil, nil, NewArgError("dropletID", "cannot be less than 1")
}
path := fmt.Sprintf("%s/%d/kernels", dropletBasePath, dropletID)
path, err := addOptions(path, opt)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(kernelsRoot)
resp, err := s.client.Do(ctx, req, root)
if l := root.Links; l != nil {
resp.Links = l
}
return root.Kernels, resp, err
}
// Actions lists the actions for a Droplet.
func (s *DropletsServiceOp) Actions(ctx context.Context, dropletID int, opt *ListOptions) ([]Action, *Response, error) {
if dropletID < 1 {
return nil, nil, NewArgError("dropletID", "cannot be less than 1")
}
path := fmt.Sprintf("%s/%d/actions", dropletBasePath, dropletID)
path, err := addOptions(path, opt)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(actionsRoot)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
if l := root.Links; l != nil {
resp.Links = l
}
return root.Actions, resp, err
}
// Backups lists the backups for a Droplet.
func (s *DropletsServiceOp) Backups(ctx context.Context, dropletID int, opt *ListOptions) ([]Image, *Response, error) {
if dropletID < 1 {
return nil, nil, NewArgError("dropletID", "cannot be less than 1")
}
path := fmt.Sprintf("%s/%d/backups", dropletBasePath, dropletID)
path, err := addOptions(path, opt)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(backupsRoot)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
if l := root.Links; l != nil {
resp.Links = l
}
return root.Backups, resp, err
}
// Snapshots lists the snapshots available for a Droplet.
func (s *DropletsServiceOp) Snapshots(ctx context.Context, dropletID int, opt *ListOptions) ([]Image, *Response, error) {
if dropletID < 1 {
return nil, nil, NewArgError("dropletID", "cannot be less than 1")
}
path := fmt.Sprintf("%s/%d/snapshots", dropletBasePath, dropletID)
path, err := addOptions(path, opt)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(dropletSnapshotsRoot)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
if l := root.Links; l != nil {
resp.Links = l
}
return root.Snapshots, resp, err
}
// Neighbors lists the neighbors for a Droplet.
func (s *DropletsServiceOp) Neighbors(ctx context.Context, dropletID int) ([]Droplet, *Response, error) {
if dropletID < 1 {
return nil, nil, NewArgError("dropletID", "cannot be less than 1")
}
path := fmt.Sprintf("%s/%d/neighbors", dropletBasePath, dropletID)
req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(dropletsRoot)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Droplets, resp, err
}
func (s *DropletsServiceOp) dropletActionStatus(ctx context.Context, uri string) (string, error) {
action, _, err := s.client.DropletActions.GetByURI(ctx, uri)
if err != nil {
return "", err
}
return action.Status, nil
}

24
vendor/github.com/digitalocean/godo/errors.go generated vendored Normal file
View File

@ -0,0 +1,24 @@
package godo
import "fmt"
// ArgError is an error that represents an error with an input to godo. It
// identifies the argument and the cause (if possible).
type ArgError struct {
arg string
reason string
}
var _ error = &ArgError{}
// NewArgError creates an InputError.
func NewArgError(arg, reason string) *ArgError {
return &ArgError{
arg: arg,
reason: reason,
}
}
func (e *ArgError) Error() string {
return fmt.Sprintf("%s is invalid because %s", e.arg, e.reason)
}

Some files were not shown because too many files have changed in this diff Show More