@@ -3,45 +3,78 @@ package main
33import (
44 "fmt"
55 "os/exec"
6+ "path/filepath"
7+ "strings"
68
79 "github.com/spf13/cobra"
810 "github.com/stuartleeks/devcontainer-cli/internal/pkg/devcontainers"
911 "github.com/stuartleeks/devcontainer-cli/internal/pkg/wsl"
1012)
1113
1214func createOpenInCodeCommand () * cobra.Command {
15+ var subFolder string
1316 cmd := & cobra.Command {
1417 Use : "open-in-code <path>" ,
1518 Short : "open the specified path devcontainer project in VS Code" ,
1619 Long : "Open the specified path (containing a .devcontainer folder in VS Code" ,
1720 RunE : func (cmd * cobra.Command , args []string ) error {
18- return launchDevContainer (cmd , "code" , args )
21+ return launchDevContainer (cmd , "code" , args , subFolder )
1922 },
2023 }
24+ cmd .Flags ().StringVarP (& subFolder , "sub-folder" , "s" , "" , "sub-folder within the devcontainer to open" )
2125 return cmd
2226}
2327func createOpenInCodeInsidersCommand () * cobra.Command {
28+ var subFolder string
2429 cmd := & cobra.Command {
2530 Use : "open-in-code-insiders <path>" ,
2631 Short : "open the specified path devcontainer project in VS Code Insiders" ,
2732 Long : "Open the specified path (containing a .devcontainer folder in VS Code Insiders" ,
2833 RunE : func (cmd * cobra.Command , args []string ) error {
29- return launchDevContainer (cmd , "code-insiders" , args )
34+ return launchDevContainer (cmd , "code-insiders" , args , subFolder )
3035 },
3136 }
37+ cmd .Flags ().StringVarP (& subFolder , "sub-folder" , "s" , "" , "sub-folder within the devcontainer to open" )
3238 return cmd
3339}
3440
35- func launchDevContainer (cmd * cobra.Command , appBase string , args []string ) error {
41+ func launchDevContainer (cmd * cobra.Command , appBase string , args []string , subFolder string ) error {
3642 if len (args ) > 1 {
3743 return cmd .Usage ()
3844 }
3945 path := "." // default to current directory
40- if len (args ) = = 1 {
46+ if len (args ) > = 1 {
4147 path = args [0 ]
4248 }
4349
44- launchURI , err := devcontainers .GetDevContainerURI (path )
50+ // allow the command to be invoked from a subfolder of the folder containing the devcontainer.json by searching ancestor paths for a devcontainer.json
51+ devcontainerPath , err := devcontainers .FindDevContainerInAncestorPaths (path )
52+ if err != nil {
53+ return fmt .Errorf ("error finding devcontainer.json: %s" , err )
54+ }
55+ fmt .Printf ("Found devcontainer.json at %s\n " , devcontainerPath )
56+
57+ // If subFolder is not empty then use that as the path to open in VS Code (note it should be relative to the folder containing the devcontainer.json/.devcontainer folder)
58+ // If subFolder is empty and the current folder is contained within the folder containing the devcontainer.json, then open the current folder in VS Code, otherwise open the folder containing the devcontainer.json in VS Code
59+ if subFolder == "" {
60+ absDevContainerPath , err := filepath .Abs (devcontainerPath )
61+ if err != nil {
62+ return fmt .Errorf ("error getting absolute path: %s" , err )
63+ }
64+ absCurrentPath , err := filepath .Abs (path )
65+ if err != nil {
66+ return fmt .Errorf ("error getting absolute path: %s" , err )
67+ }
68+ if absCurrentPath != absDevContainerPath && strings .HasPrefix (absCurrentPath , absDevContainerPath ) {
69+ subFolder , err = filepath .Rel (absDevContainerPath , absCurrentPath )
70+ if err != nil {
71+ return fmt .Errorf ("error getting relative path: %s" , err )
72+ }
73+ fmt .Printf ("Opening subfolder %s within devcontainer\n " , subFolder )
74+ }
75+ }
76+
77+ launchURI , err := devcontainers .GetDevContainerURI (devcontainerPath , subFolder )
4578 if err != nil {
4679 return err
4780 }
0 commit comments