Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
jesseduffield committed Apr 10, 2020
1 parent 251d760 commit 555dd82
Show file tree
Hide file tree
Showing 30 changed files with 2,200 additions and 92 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/jesseduffield/lazynpm
go 1.14

require (
github.com/buger/jsonparser v0.0.0-20200322175846-f7e751efca13
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21
github.com/creack/pty v1.1.10-0.20191209115840-8ab47f72e854
github.com/fatih/color v1.7.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/buger/jsonparser v0.0.0-20200322175846-f7e751efca13 h1:+qUNY4VRkEH46bLUwxCyUU+iOGJMQBVibAaYzWiwWcg=
github.com/buger/jsonparser v0.0.0-20200322175846-f7e751efca13/go.mod h1:tgcrVJ81GPSF0mz+0nu1Xaz0fazGPrmmJfJtxjbHhUQ=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 h1:tuijfIjZyjZaHq9xDUh0tNitwXshJpbLkqMOJv4H3do=
Expand Down
11 changes: 9 additions & 2 deletions pkg/commands/dependency.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
package commands

type Dependency struct {
Name string
Version string
Name string
Version string
LinkPath string
Present bool
LocalVersion string
}

func (d *Dependency) Linked() bool {
return d.LinkPath != ""
}
53 changes: 50 additions & 3 deletions pkg/commands/npm_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import (
"bytes"
"encoding/json"
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"

"github.com/buger/jsonparser"
"github.com/jesseduffield/lazynpm/pkg/config"
"github.com/jesseduffield/lazynpm/pkg/i18n"
"github.com/jinzhu/copier"
Expand Down Expand Up @@ -118,12 +120,12 @@ func (m *NpmManager) GetPackages(paths []string) ([]*Package, error) {
pkgs := make([]*Package, 0, len(paths))

for _, path := range paths {
packageJsonPath := filepath.Join(path, "package.json")
if !FileExists(packageJsonPath) {
packageConfigPath := filepath.Join(path, "package.json")
if !FileExists(packageConfigPath) {
continue
}

file, err := os.OpenFile(packageJsonPath, os.O_RDONLY, 0644)
file, err := os.OpenFile(packageConfigPath, os.O_RDONLY, 0644)
if err != nil {
m.Log.Error(err)
continue
Expand Down Expand Up @@ -171,3 +173,48 @@ func (m *NpmManager) ChdirToPackageRoot() (bool, error) {
dir = newDir
}
}

func (m *NpmManager) GetDeps(currentPkg *Package) ([]*Dependency, error) {
// for each dep, check whether it's in node modules
deps := currentPkg.SortedDependencies()

for _, dep := range deps {
nodeModulesPath := filepath.Join(currentPkg.Path, "node_modules", dep.Name)
fileInfo, err := os.Lstat(nodeModulesPath)
if err != nil {
// must not be present in node modules
m.Log.Error(err)
continue
}
dep.Present = true

// get the actual version of the package in node modules
packageConfigPath := filepath.Join(nodeModulesPath, "package.json")
bytes, err := ioutil.ReadFile(packageConfigPath)
if err != nil {
m.Log.Error(err)
continue
}

localVersion, err := jsonparser.GetString(bytes, "version")
if err != nil {
// swallowing error
m.Log.Error(err)
} else {
dep.LocalVersion = localVersion
}

isSymlink := fileInfo.Mode()&os.ModeSymlink == os.ModeSymlink
if !isSymlink {
continue
}

linkPath, err := filepath.EvalSymlinks(nodeModulesPath)
if err != nil {
return nil, err
}
dep.LinkPath = linkPath
}

return deps, nil
}
27 changes: 20 additions & 7 deletions pkg/commands/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ type PackageConfigInput struct {
DevDependencies map[string]string `json:"devDependencies"`
PeerDependencies map[string]string `json:"peerDependencies"`
OptionalDependencies map[string]string `json:"optionalDependencies"`
BundleDependencies bool `json:"bundleDependencies"`
BundledDependencies []string `json:"bundleDependencies"`
}

type Author struct {
Expand Down Expand Up @@ -88,23 +88,36 @@ type PackageConfig struct {
DevDependencies map[string]string
PeerDependencies map[string]string
OptionalDependencies map[string]string
BundleDependencies bool
BundledDependencies []string
}

func (p *Package) SortedDeps() []*Dependency {
deps := make([]*Dependency, 0, len(p.Config.Dependencies))
for name, version := range p.Config.Dependencies {
func (p *Package) SortedDepsGeneric(depMap map[string]string) []*Dependency {
deps := make([]*Dependency, 0, len(depMap))
for name, version := range depMap {
deps = append(deps, &Dependency{Name: name, Version: version})
}
sort.Slice(deps, func(i, j int) bool { return strings.Compare(deps[i].Name, deps[j].Name) > 0 })
sort.Slice(deps, func(i, j int) bool { return strings.Compare(deps[i].Name, deps[j].Name) < 0 })
return deps
}

func (p *Package) SortedDependencies() []*Dependency {
return p.SortedDepsGeneric(p.Config.Dependencies)
}
func (p *Package) SortedDevDependencies() []*Dependency {
return p.SortedDepsGeneric(p.Config.DevDependencies)
}
func (p *Package) SortedPeerDependencies() []*Dependency {
return p.SortedDepsGeneric(p.Config.PeerDependencies)
}
func (p *Package) SortedOptionalDependencies() []*Dependency {
return p.SortedDepsGeneric(p.Config.OptionalDependencies)
}

func (p *Package) SortedScripts() []*Script {
scripts := make([]*Script, 0, len(p.Config.Scripts))
for name, command := range p.Config.Scripts {
scripts = append(scripts, &Script{Name: name, Command: command})
}
sort.Slice(scripts, func(i, j int) bool { return strings.Compare(scripts[i].Name, scripts[j].Name) > 0 })
sort.Slice(scripts, func(i, j int) bool { return strings.Compare(scripts[i].Name, scripts[j].Name) < 0 })
return scripts
}
59 changes: 0 additions & 59 deletions pkg/config/app_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,6 @@ func GetDefaultConfig() []byte {
scrollHeight: 2
scrollPastBottom: true
mouseEvents: true
skipUnstageLineWarning: false
sidePanelWidth: 0.3333
theme:
lightTheme: false
Expand All @@ -256,8 +255,6 @@ func GetDefaultConfig() []byte {
- blue
selectedLineBgColor:
- blue
commitLength:
show: true
update:
method: prompt # can be: prompt | background | never
days: 14 # how often a update is checked for
Expand Down Expand Up @@ -301,74 +298,18 @@ keybinding:
scrollUpMain-alt2: '<c-u>'
scrollDownMain-alt2: '<c-d>'
executeCustomCommand: ':'
createRebaseOptionsMenu: 'm'
pushFiles: 'P'
pullFiles: 'p'
refresh: 'R'
createPatchOptionsMenu: '<c-p>'
nextTab: ']'
prevTab: '['
nextScreenMode: '+'
prevScreenMode: '_'
undo: 'z'
redo: '<c-z>'
filteringMenu: <c-s>
diffingMenu: '<c-e>'
status:
checkForUpdate: 'u'
recentRepos: '<enter>'
files:
commitChanges: 'c'
commitChangesWithoutHook: 'w'
amendLastCommit: 'A'
commitChangesWithEditor: 'C'
ignoreFile: 'i'
refreshFiles: 'r'
stashAllChanges: 's'
viewStashOptions: 'S'
toggleStagedAll: 'a'
viewResetOptions: 'D'
fetch: 'f'
branches:
createPullRequest: 'o'
checkoutBranchByName: 'c'
forceCheckoutBranch: 'F'
rebaseBranch: 'r'
renameBranch: 'R'
mergeIntoCurrentBranch: 'M'
viewGitFlowOptions: 'i'
fastForward: 'f'
pushTag: 'P'
setUpstream: 'u'
fetchRemote: 'f'
commits:
squashDown: 's'
renameCommit: 'r'
renameCommitWithEditor: 'R'
viewResetOptions: 'g'
markCommitAsFixup: 'f'
createFixupCommit: 'F'
squashAboveCommits: 'S'
moveDownCommit: '<c-j>'
moveUpCommit: '<c-k>'
amendToCommit: 'A'
pickCommit: 'p'
revertCommit: 't'
cherryPickCopy: 'c'
cherryPickCopyRange: 'C'
pasteCommits: 'v'
tagCommit: 'T'
checkoutCommit: '<space>'
resetCherryPick: '<c-R>'
stash:
popStash: 'g'
commitFiles:
checkoutCommitFile: 'c'
main:
toggleDragSelect: 'v'
toggleDragSelect-alt: 'V'
toggleSelectHunk: 'a'
pickBothHunks: 'b'
`)
}

Expand Down
27 changes: 27 additions & 0 deletions pkg/gui/dependencies_panel.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package gui

import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazynpm/pkg/commands"
)

// list panel functions

func (gui *Gui) getSelectedDependency() *commands.Dependency {
currentPackage := gui.currentPackage()

deps := currentPackage.SortedDependencies()
if len(deps) == 0 {
return nil
}
return deps[gui.State.Panels.Deps.SelectedLine]
}

func (gui *Gui) handleDepSelect(g *gocui.Gui, v *gocui.View) error {
dep := gui.getSelectedDependency()
if dep == nil {
gui.getMainView().Title = ""
return gui.newStringTask("main", gui.Tr.SLocalize("NoDependencies"))
}
return nil
}
21 changes: 16 additions & 5 deletions pkg/gui/gui.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ type searchingState struct {

type guiState struct {
Packages []*commands.Package
Deps []*commands.Dependency
MenuItemCount int // can't store the actual list because it's of interface{} type
PreviousView string
Updating bool
Expand Down Expand Up @@ -306,7 +307,6 @@ func (gui *Gui) loadNewRepo() error {
// updateRecentRepoList registers the fact that we opened lazynpm in this package,
// so that appears in the packages view next time we open the program in another package
func (gui *Gui) updateRecentRepoList() error {
recentPackages := gui.Config.GetAppState().RecentPackages
ok, err := gui.NpmManager.ChdirToPackageRoot()
if err != nil {
return err
Expand All @@ -316,19 +316,30 @@ func (gui *Gui) updateRecentRepoList() error {
if err != nil {
return err
}
isNew, recentPackages := newRecentPackagesList(recentPackages, currentPackagePath)
gui.Config.SetIsNewPackage(isNew)
gui.Config.GetAppState().RecentPackages = recentPackages
return gui.Config.SaveAppState()
return gui.sendPackageToTop(currentPackagePath)
}

recentPackages := gui.Config.GetAppState().RecentPackages
if len(recentPackages) > 0 {
// TODO: ensure this actually contains a package.json file (meaning it won't be filtered out)
return os.Chdir(recentPackages[0])
}
return errors.New("Must open lazynpm in an npm package")
}

func (gui *Gui) sendPackageToTop(path string) error {
// in case we're not already there, chdir to path
if err := os.Chdir(path); err != nil {
return err
}

recentPackages := gui.Config.GetAppState().RecentPackages
isNew, recentPackages := newRecentPackagesList(recentPackages, path)
gui.Config.SetIsNewPackage(isNew)
gui.Config.GetAppState().RecentPackages = recentPackages
return gui.Config.SaveAppState()
}

// newRecentPackagesList returns a new repo list with a new entry but only when it doesn't exist yet
func newRecentPackagesList(recentPackages []string, currentPackage string) (bool, []string) {
isNew := true
Expand Down
6 changes: 6 additions & 0 deletions pkg/gui/keybindings.go
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,12 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
Modifier: gocui.ModNone,
Handler: gui.scrollDownConfirmationPanel,
},
{
ViewName: "packages",
Key: gui.getKey("universal.select"),
Modifier: gocui.ModNone,
Handler: gui.handleCheckoutPackage,
},
}

for _, viewName := range []string{"status", "packages", "deps", "scripts", "menu"} {
Expand Down
19 changes: 19 additions & 0 deletions pkg/gui/list_view.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,5 +134,24 @@ func (gui *Gui) getListViews() []*listView {
gui: gui,
rendersToMainView: true,
},
{
viewName: "deps",
// TODO: handle more dep types
getItemsLength: func() int { return len(gui.currentPackage().SortedDependencies()) },
getSelectedLineIdxPtr: func() *int { return &gui.State.Panels.Deps.SelectedLine },
handleFocus: gui.handleDepSelect,
handleItemSelect: gui.handleDepSelect,
gui: gui,
rendersToMainView: true,
},
{
viewName: "scripts",
getItemsLength: func() int { return len(gui.currentPackage().SortedScripts()) },
getSelectedLineIdxPtr: func() *int { return &gui.State.Panels.Scripts.SelectedLine },
handleFocus: gui.handleScriptSelect,
handleItemSelect: gui.handleScriptSelect,
gui: gui,
rendersToMainView: true,
},
}
}
Loading

0 comments on commit 555dd82

Please sign in to comment.