22// Licensed under the MIT license. 
33
44import  *  as  fse  from  "fs-extra" ; 
5+ import  *  as  path  from  "path" ; 
56import  *  as  vscode  from  "vscode" ; 
67import  {  LeetCodeNode  }  from  "../explorer/LeetCodeNode" ; 
8+ import  {  leetCodeChannel  }  from  "../leetCodeChannel" ; 
79import  {  leetCodeExecutor  }  from  "../leetCodeExecutor" ; 
810import  {  leetCodeManager  }  from  "../leetCodeManager" ; 
911import  {  IProblem ,  IQuickItemEx ,  languages ,  ProblemState  }  from  "../shared" ; 
@@ -16,15 +18,15 @@ export async function showProblem(node?: LeetCodeNode): Promise<void> {
1618    if  ( ! node )  { 
1719        return ; 
1820    } 
19-     await  showProblemInternal ( node . id ) ; 
21+     await  showProblemInternal ( node ) ; 
2022} 
2123
2224export  async  function  searchProblem ( ) : Promise < void >  { 
2325    if  ( ! leetCodeManager . getUser ( ) )  { 
2426        promptForSignIn ( ) ; 
2527        return ; 
2628    } 
27-     const  choice : IQuickItemEx < string >  |  undefined  =  await  vscode . window . showQuickPick ( 
29+     const  choice : IQuickItemEx < IProblem >  |  undefined  =  await  vscode . window . showQuickPick ( 
2830        parseProblemsToPicks ( list . listProblems ( ) ) , 
2931        { 
3032            matchOnDetail : true , 
@@ -37,7 +39,7 @@ export async function searchProblem(): Promise<void> {
3739    await  showProblemInternal ( choice . value ) ; 
3840} 
3941
40- async  function  showProblemInternal ( id :  string ) : Promise < void >  { 
42+ async  function  showProblemInternal ( node :  IProblem ) : Promise < void >  { 
4143    try  { 
4244        const  leetCodeConfig : vscode . WorkspaceConfiguration  =  vscode . workspace . getConfiguration ( "leetcode" ) ; 
4345        let  defaultLanguage : string  |  undefined  =  leetCodeConfig . get < string > ( "defaultLanguage" ) ; 
@@ -49,9 +51,21 @@ async function showProblemInternal(id: string): Promise<void> {
4951            return ; 
5052        } 
5153
52-         const  outDir : string  =  await  selectWorkspaceFolder ( ) ; 
54+         let  outDir : string  =  await  selectWorkspaceFolder ( ) ; 
55+         let  relativePath : string  =  ( leetCodeConfig . get < string > ( "outputFolder" )  ||  "" ) . trim ( ) ; 
56+         const  matchResult : RegExpMatchArray  |  null  =  relativePath . match ( / \$ \{ ( .* ?) \} / ) ; 
57+         if  ( matchResult )  { 
58+             const  resolvedPath : string  |  undefined  =  await  resolveRelativePath ( matchResult [ 1 ] . toLocaleLowerCase ( ) ,  node ,  language ) ; 
59+             if  ( ! resolvedPath )  { 
60+                 leetCodeChannel . appendLine ( "Showing problem canceled by user." ) ; 
61+                 return ; 
62+             } 
63+             relativePath  =  resolvedPath ; 
64+         } 
65+ 
66+         outDir  =  path . join ( outDir ,  relativePath ) ; 
5367        await  fse . ensureDir ( outDir ) ; 
54-         const  result : string  =  await  leetCodeExecutor . showProblem ( id ,  language ,  outDir ) ; 
68+         const  result : string  =  await  leetCodeExecutor . showProblem ( node . id ,  language ,  outDir ) ; 
5569        const  reg : RegExp  =  / \*   S o u r c e   C o d e : \s * ( .* ) / ; 
5670        const  match : RegExpMatchArray  |  null  =  result . match ( reg ) ; 
5771        if  ( match  &&  match . length  >=  2 )  { 
@@ -76,17 +90,17 @@ async function showProblemInternal(id: string): Promise<void> {
7690            } 
7791        } 
7892    }  catch  ( error )  { 
79-         await  promptForOpenOutputChannel ( "Failed to fetch  the problem information . Please open the output channel for details." ,  DialogType . error ) ; 
93+         await  promptForOpenOutputChannel ( "Failed to show  the problem. Please open the output channel for details." ,  DialogType . error ) ; 
8094    } 
8195} 
8296
83- async  function  parseProblemsToPicks ( p : Promise < IProblem [ ] > ) : Promise < Array < IQuickItemEx < string > > >  { 
84-     return  new  Promise ( async  ( resolve : ( res : Array < IQuickItemEx < string > > )  =>  void ) : Promise < void >  =>  { 
85-         const  picks : Array < IQuickItemEx < string > >  =  ( await  p ) . map ( ( problem : IProblem )  =>  Object . assign ( { } ,  { 
97+ async  function  parseProblemsToPicks ( p : Promise < IProblem [ ] > ) : Promise < Array < IQuickItemEx < IProblem > > >  { 
98+     return  new  Promise ( async  ( resolve : ( res : Array < IQuickItemEx < IProblem > > )  =>  void ) : Promise < void >  =>  { 
99+         const  picks : Array < IQuickItemEx < IProblem > >  =  ( await  p ) . map ( ( problem : IProblem )  =>  Object . assign ( { } ,  { 
86100            label : `${ parseProblemDecorator ( problem . state ,  problem . locked ) } ${ problem . id }  .${ problem . name }  ` , 
87101            description : "" , 
88102            detail : `AC rate: ${ problem . passRate }  , Difficulty: ${ problem . difficulty }  ` , 
89-             value : problem . id , 
103+             value : problem , 
90104        } ) ) ; 
91105        resolve ( picks ) ; 
92106    } ) ; 
@@ -102,3 +116,28 @@ function parseProblemDecorator(state: ProblemState, locked: boolean): string {
102116            return  locked  ? "$(lock) "  : "" ; 
103117    } 
104118} 
119+ 
120+ async  function  resolveRelativePath ( value : string ,  node : IProblem ,  selectedLanguage : string ) : Promise < string  |  undefined >  { 
121+     switch  ( value )  { 
122+         case  "tag" :
123+             if  ( node . tags . length  ===  1 )  { 
124+                 return  node . tags [ 0 ] ; 
125+             } 
126+             return  await  vscode . window . showQuickPick ( 
127+                 node . tags , 
128+                 { 
129+                     matchOnDetail : true , 
130+                     placeHolder : "Multiple tags available, please select one" , 
131+                     ignoreFocusOut : true , 
132+                 } , 
133+             ) ; 
134+         case  "language" :
135+             return  selectedLanguage ; 
136+         case  "difficulty" :
137+             return  node . difficulty ; 
138+         default :
139+             const  errorMsg : string  =  `The config '${ value }  ' is not supported.` ; 
140+             leetCodeChannel . appendLine ( errorMsg ) ; 
141+             throw  new  Error ( errorMsg ) ; 
142+     } 
143+ } 
0 commit comments