Skip to content

Commit

Permalink
Merge pull request #36 from cacoco/supportLoading
Browse files Browse the repository at this point in the history
[feature] support loading file as base for codemeta editing
  • Loading branch information
cacoco authored Feb 6, 2024
2 parents eb484c5 + d6552b1 commit 7c48331
Show file tree
Hide file tree
Showing 6 changed files with 213 additions and 121 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@ codemetagenerator new
```

This will walk you through an interactive session and will store an "in-progress" `codemeta.json` file. The expectation is that
you will continue to add more metadata, e.g., `author`, `contributor`, or `keyword`.
you will continue to add more metadata, e.g., `author`, `contributor`, or `keyword`.

Optionally, the `--input` (or `-i`) can be passed with a path to a file to load as the new in-progress `codemeta.json` file. This
allows for editing and updating an existing file which you can then choose to generate back into the original location.

#### Add
Add helps with the addition of 3 specific fields: `author`, `contributor`, or `keyword`. The command provides a wizard for adding these values.
Expand Down
14 changes: 7 additions & 7 deletions cmd/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"github.com/spf13/cobra"
)

func generate(basedir string, writer utils.Writer, outputPath string) error {
func generate(basedir string, writer utils.Writer, outFile string) error {
inProgressFilePath := utils.GetInProgressFilePath(basedir)

json, err := utils.ReadJSON(inProgressFilePath)
Expand All @@ -14,11 +14,11 @@ func generate(basedir string, writer utils.Writer, outputPath string) error {
return writer.Errorf("unable to read codemeta.inprogress.json file, ensure you have run `codemetagenerator new` at least once")
}

if outputPath != "" {
err = utils.WriteJSON(outputPath, *json)
if outFile != "" {
err = utils.WriteJSON(outFile, *json)
if err != nil {
handleErr(writer, err)
return writer.Errorf("unable to write codemeta.json file to output file %s", outputPath)
return writer.Errorf("unable to write codemeta.json file to output file %s", outFile)
}
} else {
writer.Println(*json)
Expand All @@ -27,7 +27,7 @@ func generate(basedir string, writer utils.Writer, outputPath string) error {
return nil
}

var codeMetaFilePath string
var outputFile string

// generateCmd represents the generate command
var generateCmd = &cobra.Command{
Expand All @@ -40,12 +40,12 @@ Generate the resultant 'codemeta.json' file from the in-progress file.
Output can be written to a file [-o | --output <path/to/codemeta.json>] or
printed to the console.`,
RunE: func(cmd *cobra.Command, args []string) error {
return generate(utils.UserHomeDir, &utils.StdoutWriter{}, codeMetaFilePath)
return generate(utils.UserHomeDir, &utils.StdoutWriter{}, outputFile)
},
}

func init() {
rootCmd.AddCommand(generateCmd)

generateCmd.Flags().StringVarP(&codeMetaFilePath, "output", "o", "", "The path to the output 'codemeta.json' file. If not specified, the output will be printed to the console.")
generateCmd.Flags().StringVarP(&outputFile, "output", "o", "", "The path to the output 'codemeta.json' file. If not specified, the output will be printed to the console.")
}
244 changes: 135 additions & 109 deletions cmd/new.go
Original file line number Diff line number Diff line change
@@ -1,147 +1,169 @@
package cmd

import (
"fmt"
"os"
"path/filepath"

"github.com/cacoco/codemetagenerator/internal/model"
"github.com/cacoco/codemetagenerator/internal/utils"
"github.com/manifoldco/promptui"
"github.com/spf13/cobra"
)

func new(basedir string, reader utils.Reader, writer utils.Writer) error {
func new(basedir string, reader utils.Reader, writer utils.Writer, inFile string) error {
stdin := reader.Stdin()
stdout := writer.Stdout()

// clean up any previous file
inProgressFilePath := utils.GetInProgressFilePath(basedir)
utils.DeleteFile(inProgressFilePath)

var result = make(map[string]any)
var successMsg string = "⭐ Successfully created new in-progress codemeta.json file."
if inFile != "" {
bytes, err := utils.LoadFile(inFile)
if err != nil {
handleErr(writer, err)
return writer.Errorf("unable to read input file %s", inFile)
}
err = os.WriteFile(inProgressFilePath, bytes, 0644)
if err != nil {
handleErr(writer, err)
return writer.Errorf("unable to write in-progress codemeta.json file")
}

identifier, err := utils.MkPrompt(&stdin, &stdout, "Enter a unique identifier for your software source code", utils.Nop)
if err != nil {
handleErr(writer, err)
return writer.Errorf("unable to create new identifier")
}
fileBase := filepath.Base(inFile)
successMsg = fmt.Sprintf("⭐ Successfully loaded '%s' as new in-progress codemeta.json file.", fileBase)
} else {
var result = make(map[string]any)

name, err := utils.MkPrompt(&stdin, &stdout, "Enter a name for your software source code", utils.Nop)
if err != nil {
handleErr(writer, err)
return writer.Errorf("unable to create new name")
}
identifier, err := utils.MkPrompt(&stdin, &stdout, "Enter a unique identifier for your software source code", utils.Nop)
if err != nil {
handleErr(writer, err)
return writer.Errorf("unable to create new identifier")
}

description, err := utils.MkPrompt(&stdin, &stdout, "Enter a description for your software source code", utils.Nop)
if err != nil {
handleErr(writer, err)
return writer.Errorf("unable to create new description")
}
name, err := utils.MkPrompt(&stdin, &stdout, "Enter a name for your software source code", utils.Nop)
if err != nil {
handleErr(writer, err)
return writer.Errorf("unable to create new name")
}

developmentStatusOptions := []model.MenuOption{
{Name: "Abandoned", Type: "abandoned"},
{Name: "Active", Type: "active"},
{Name: "Concept", Type: "concept"},
{Name: "Inactive", Type: "inactive"},
{Name: "Moved", Type: "moved"},
{Name: "Suspended", Type: "suspended"},
{Name: "Unsupported", Type: "unsupported"},
{Name: "WIP", Type: "wip"},
}
description, err := utils.MkPrompt(&stdin, &stdout, "Enter a description for your software source code", utils.Nop)
if err != nil {
handleErr(writer, err)
return writer.Errorf("unable to create new description")
}

developmentStatusOptions := []model.MenuOption{
{Name: "Abandoned", Type: "abandoned"},
{Name: "Active", Type: "active"},
{Name: "Concept", Type: "concept"},
{Name: "Inactive", Type: "inactive"},
{Name: "Moved", Type: "moved"},
{Name: "Suspended", Type: "suspended"},
{Name: "Unsupported", Type: "unsupported"},
{Name: "WIP", Type: "wip"},
}

templates := &promptui.SelectTemplates{
Label: "{{ . }}",
Active: "➞ {{ .Name | cyan }}",
Inactive: " {{ .Name | cyan }}",
Selected: `{{ "Select a development status (see: https://www.repostatus.org/):" | faint}} {{ .Name | faint }}`,
Details: `--------- Status ----------
templates := &promptui.SelectTemplates{
Label: "{{ . }}",
Active: "➞ {{ .Name | cyan }}",
Inactive: " {{ .Name | cyan }}",
Selected: `{{ "Select a development status (see: https://www.repostatus.org/):" | faint}} {{ .Name | faint }}`,
Details: `--------- Status ----------
{{ "Name:" | faint }} {{ .Name }}`,
}
}

prompt := promptui.Select{
Label: "Select a development status from the list below (see: https://www.repostatus.org/)",
Items: developmentStatusOptions,
Templates: templates,
Size: 8,
Searcher: nil,
Stdin: reader.Stdin(),
Stdout: writer.Stdout(),
}
prompt := promptui.Select{
Label: "Select a development status from the list below (see: https://www.repostatus.org/)",
Items: developmentStatusOptions,
Templates: templates,
Size: 8,
Searcher: nil,
Stdin: reader.Stdin(),
Stdout: writer.Stdout(),
}

i, _, err := prompt.Run()
if err != nil {
return err
}
developmentStatus := developmentStatusOptions[i].Name
i, _, err := prompt.Run()
if err != nil {
return err
}
developmentStatus := developmentStatusOptions[i].Name

codeRepository, err := utils.MkPrompt(&stdin, &stdout, "Enter the URL of the code repository for the project", utils.ValidUrl)
if err != nil {
return err
}
codeRepository, err := utils.MkPrompt(&stdin, &stdout, "Enter the URL of the code repository for the project", utils.ValidUrl)
if err != nil {
return err
}

programmingLanguageName, err := utils.MkPrompt(&stdin, &stdout, "Enter the name of the programming language of the project", utils.Nop)
if err != nil {
return err
}
programmingLanguageURL, err := utils.MkPrompt(&stdin, &stdout, "Enter the URL of the programming language of the project", utils.ValidUrl)
if err != nil {
return err
}
programmingLanguage := model.NewProgrammingLanguage(programmingLanguageName, programmingLanguageURL)
programmingLanguageName, err := utils.MkPrompt(&stdin, &stdout, "Enter the name of the programming language of the project", utils.Nop)
if err != nil {
return err
}
programmingLanguageURL, err := utils.MkPrompt(&stdin, &stdout, "Enter the URL of the programming language of the project", utils.ValidUrl)
if err != nil {
return err
}
programmingLanguage := model.NewProgrammingLanguage(programmingLanguageName, programmingLanguageURL)

runtimePlatform, err := utils.MkPrompt(&stdin, &stdout, "Enter the name of the runtime platform of the project", utils.Nop)
if err != nil {
return err
}
runtimePlatform, err := utils.MkPrompt(&stdin, &stdout, "Enter the name of the runtime platform of the project", utils.Nop)
if err != nil {
return err
}

version, err := utils.MkPrompt(&stdin, &stdout, "Enter the version of the project", utils.Nop)
if err != nil {
return err
}
version, err := utils.MkPrompt(&stdin, &stdout, "Enter the version of the project", utils.Nop)
if err != nil {
return err
}

validateFn := validateLicenseId(basedir)
license, err := utils.MkPrompt(&stdin, &stdout, "Enter the SPDX license ID for the project (see: https://spdx.org/licenses/)", validateFn)
if err != nil {
return err
}
validateFn := validateLicenseId(basedir)
license, err := utils.MkPrompt(&stdin, &stdout, "Enter the SPDX license ID for the project (see: https://spdx.org/licenses/)", validateFn)
if err != nil {
return err
}

var licenseDetailsUrl string
if (*license) != "" {
referenceUrl, err := getLicenseReference(basedir, *license)
if err != nil {
handleErr(writer, err)
return writer.Errorf("unable to create new license details URL")
}
licenseDetailsUrl = *referenceUrl
}

var licenseDetailsUrl string
if (*license) != "" {
referenceUrl, err := getLicenseReference(basedir, *license)
readme, err := utils.MkPrompt(&stdin, &stdout, "Enter the URL of the README file for the project", utils.ValidUrl)
if err != nil {
handleErr(writer, err)
return writer.Errorf("unable to create new license details URL")
return err
}
licenseDetailsUrl = *referenceUrl
}

readme, err := utils.MkPrompt(&stdin, &stdout, "Enter the URL of the README file for the project", utils.ValidUrl)
if err != nil {
return err
}
maintainer, err := utils.NewPersonOrOrganizationPrompt(&reader, &writer, "Maintainer")
if err != nil {
return err
}

maintainer, err := utils.NewPersonOrOrganizationPrompt(&reader, &writer, "Maintainer")
if err != nil {
return err
result[model.Identifier] = identifier
result[model.Name] = name
result[model.Description] = description
result[model.Version] = version
result[model.Maintainer] = maintainer
result[model.ProgrammingLanguage] = programmingLanguage
result[model.DevelopmentStatus] = developmentStatus
result[model.License] = licenseDetailsUrl
result[model.RuntimePlatform] = runtimePlatform
result[model.CodeRepository] = codeRepository
result[model.Readme] = readme

codemeta := model.NewCodemeta(&result)

err = utils.Marshal(inProgressFilePath, codemeta)
if err != nil {
handleErr(writer, err)
return writer.Errorf("unable to save in-progress codemeta.json file after editing")
}
}

result[model.Identifier] = identifier
result[model.Name] = name
result[model.Description] = description
result[model.Version] = version
result[model.Maintainer] = maintainer
result[model.ProgrammingLanguage] = programmingLanguage
result[model.DevelopmentStatus] = developmentStatus
result[model.License] = licenseDetailsUrl
result[model.RuntimePlatform] = runtimePlatform
result[model.CodeRepository] = codeRepository
result[model.Readme] = readme

codemeta := model.NewCodemeta(&result)

err = utils.Marshal(inProgressFilePath, codemeta)
if err != nil {
handleErr(writer, err)
return writer.Errorf("unable to save in-progress codemeta.json file after editing")
}
writer.Println("⭐ Successfully created new in-progress codemeta.json file.")
writer.Println(successMsg)
writer.Println("👇 You can now add authors, contributors, keywords, and other fields to the in-progress codemeta.json file.")
writer.Println("➡️ To add/remove authors, contributors or keywords, run the following commands:")
writer.Println("\tcodemetagenerator add author")
Expand All @@ -158,6 +180,8 @@ func new(basedir string, reader utils.Reader, writer utils.Writer) error {
return nil
}

var inputFile string

// newCmd represents the new command
var newCmd = &cobra.Command{
Use: "new",
Expand All @@ -174,12 +198,14 @@ codemetagenerator generate
to generate the resultant 'codemeta.json' file, optionally selecting the file destination.`,
RunE: func(cmd *cobra.Command, args []string) error {
return new(utils.UserHomeDir, &utils.StdinReader{}, &utils.StdoutWriter{})
return new(utils.UserHomeDir, &utils.StdinReader{}, &utils.StdoutWriter{}, inputFile)
},
}

func init() {
rootCmd.AddCommand(newCmd)

utils.MkHomeDir(utils.UserHomeDir)

newCmd.Flags().StringVarP(&inputFile, "input", "i", "", "The path to an input 'codemeta.json' file. If not specified, a new file will be started.")
}
Loading

0 comments on commit 7c48331

Please sign in to comment.