Skip to content

Commit

Permalink
add open in vscode command
Browse files Browse the repository at this point in the history
  • Loading branch information
goswinr committed Dec 8, 2024
1 parent 5afbe11 commit b6507b9
Show file tree
Hide file tree
Showing 14 changed files with 89 additions and 39 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/releaseHosting.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
dotnet-version: '9.0.x'

- name: Build
run: dotnet build FeshHosting.fsproj --configuration Release
run: dotnet build FeshStandalone.fsproj --configuration Release

- name: Publish NuGet package
run: dotnet nuget push ./bin/hosting/Fesh.${{ github.ref_name }}.symbols.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0


## [Unreleased]

## [0.16.0] - 2024-12-14
### Added
- command for opening a file in VS Code
- command for closing and deleting a file

## [0.15.0] - 2024-11-22
### Added
- Support for F# 9.0
Expand Down Expand Up @@ -51,7 +57,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- first public release

[Unreleased]: https://github.com/goswinr/Fesh/compare/0.14.3...HEAD
[Unreleased]: https://github.com/goswinr/Fesh/compare/0.16.0...HEAD
[0.16.0]: https://github.com/goswinr/Fesh/compare/0.15.0...0.16.0
[0.15.0]: https://github.com/goswinr/Fesh/compare/0.14.3...0.15.0
[0.14.3]: https://github.com/goswinr/Fesh/compare/0.14.2...0.14.3
[0.14.2]: https://github.com/goswinr/Fesh/compare/0.14.0...0.14.2
[0.14.0]: https://github.com/goswinr/Fesh/compare/0.13.0...0.14.0
Expand Down
3 changes: 2 additions & 1 deletion FeshHosting.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers; buildtransitive" />
<PackageReference Include="Ionide.KeepAChangelog.Tasks" Version="0.1.8" PrivateAssets="all" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="System.Net.Http" Version="4.3.4" /> <!-- to check for updates -->
<PackageReference Include="Microsoft.VisualBasic" Version="10.3.0" /> <!-- to move files to the recycle bin instead of deleting them -->
<PackageReference Include="FSharp.Compiler.Service" Version="43.9.100" />
<!-- normally don't include FSharp.Core in a library, but Update to latest version is needed for latest FSharp.Compiler.Service-->
<PackageReference Update="FSharp.Core" Version="9.0.100" />
Expand Down
9 changes: 4 additions & 5 deletions FeshStandalone.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@
<Title>Fesh</Title>
<Product>Fesh</Product>

<!-- <Version>0.14.2</Version> done by Ionide.KeepAChangelog.Tasks
<AssemblyVersion>0.14.2</AssemblyVersion>
<FileVersion>0.14.2</FileVersion> -->
<!-- <Version>0.14.2</Version> taken from CHANGELOG.md by Ionide.KeepAChangelog.Tasks -->

<Company>Goswin Rothenthal</Company> <!-- <Company> shows up on file preview on fesh.exe in windows file explorer-->
<Authors>GoswinR</Authors>
Expand All @@ -41,13 +39,14 @@

<OutputPath>bin/standalone</OutputPath>
<OtherFlags>$(OtherFlags) --warnon:1182</OtherFlags> <!-- 1182: warn on unused variables -->
<ChangelogFile>CHANGELOG.md</ChangelogFile>
<ChangelogFile>CHANGELOG.md</ChangelogFile> <!-- for Ionide.KeepAChangelog.Tasks -->
<Configurations>Release</Configurations>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Ionide.KeepAChangelog.Tasks" Version="0.1.8" PrivateAssets="all" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="System.Net.Http" Version="4.3.4" /> <!-- to check for updates -->
<PackageReference Include="Microsoft.VisualBasic" Version="10.3.0" /> <!-- to move files to the recycle bin instead of deleting them -->
<PackageReference Include="FSharp.Compiler.Service" Version="43.9.100" />
<PackageReference Update="FSharp.Core" Version="9.0.100" GeneratePathProperty="true"/>
<PackageReference Include="System.Private.Uri" Version="4.3.2" /> <!-- warning NU1903: Package 'System.Private.Uri' 4.3.0 has a known high severity vulnerability, https://github.com/advisories/GHSA-5f2m-466j-3848 -->
Expand Down
3 changes: 1 addition & 2 deletions Src/App.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ open System
open System.Windows
open Fesh.Config


module App =

/// To statically access the currently running instance.
Expand Down Expand Up @@ -38,7 +37,7 @@ module App =
try
app.Run(fesh.Window)
with e ->
eprintfn "Application.Run Error:\r\n{e}"
eprintfn "Fesh Application.Run Error:\r\n{e}"
1


1 change: 0 additions & 1 deletion Src/Config/Config.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
open Fesh.Model



type Config (log:IFeshLog, startUpData:HostedStartUpData option, startupArgs:string[]) =

let runContext = new RunContext (startUpData)
Expand Down
4 changes: 2 additions & 2 deletions Src/Config/RunContext.fs
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ type RunContext (startUpData:HostedStartUpData option) =
let path =
match startUpData with
|None ->
IO.Path.Combine(appData,"Fesh") // Standalone
IO.Path.Combine(appData, "Fesh", "Settings", "Standalone") // Standalone
|Some sd ->
let mutable host = sd.hostName
for c in IO.Path.GetInvalidFileNameChars() do host <- host.Replace(c, '_') // make sure host name is a valid file name
IO.Path.Combine(appData,"Fesh",host)
IO.Path.Combine(appData,"Fesh", "Settings", host)

IO.Directory.CreateDirectory(path) |> ignore
path
Expand Down
28 changes: 15 additions & 13 deletions Src/Editor/AutoFixErrors.fs
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ module AutoFixErrors =
let asked = HashSet<string>()
let askedAgain = HashSet<string>()

let mutable isMessageBoxOpen = false // because msg box would appear behind completion window and type info
let mutable isMessageBoxOpen = false // because errMsg box would appear behind completion window and type info

let ask(msg:string,ass:string) =
// it is actually better to stat the message box from another thread ?
let ask(errMsg:string,assemblyName:string) =
// it is actually better to start the message box from another thread ?
isMessageBoxOpen <- true
async{
do! Async.SwitchToContext SyncWpf.context
match MessageBox.Show(
IEditor.mainWindow,
$"Do you want to add a reference to\r\n\r\n{ass}.dll\r\n\r\non the first line of the script? \r\n\r\nTo fix this Error:\r\n{msg}" ,
$"Fesh | Add a reference to {ass} ?",
$"Do you want to add a reference to\r\n\r\n{assemblyName}.dll\r\n\r\non the first line of the script? \r\n\r\nTo fix this Error:\r\n{errMsg}" ,
$"Fesh | Add a reference to {assemblyName} ?",
MessageBoxButton.YesNo,
MessageBoxImage.Question,
MessageBoxResult.Yes,// default result
Expand All @@ -31,21 +31,23 @@ module AutoFixErrors =
do! Async.SwitchToContext SyncWpf.context
match IEditor.current with
|Some ied ->
ied.AvaEdit.Document.Insert(0, $"#r \"{ass}\" // auto added\r\n")
ied.AvaEdit.Document.Insert(0, $"#r \"{assemblyName}\" // auto added\r\n")
|None -> ()
| _ -> ()

isMessageBoxOpen <- false
}|> Async.Start

let check(msg) =
match Util.Str.between "add a reference to assembly '" "," msg with //assembly name with version number
|Some ass ->
if asked.Add msg || askedAgain.Add msg then ask(msg,ass)
let check(errMsg) =
match Util.Str.between "add a reference to assembly '" "," errMsg with //assembly name with version number
|Some assemblyName ->
let n = assemblyName.Trim().Split(' ').[0] // remove version number
if asked.Add n || askedAgain.Add n then ask(errMsg,n)
|None ->
match Util.Str.between "add a reference to assembly '" "'" msg with //assembly name without version number
|Some ass ->
if asked.Add msg || askedAgain.Add msg then ask(msg,ass)
match Util.Str.between "add a reference to assembly '" "'" errMsg with //assembly name without version number
|Some assemblyName ->
let n = assemblyName.Trim()
if asked.Add n || askedAgain.Add n then ask(errMsg,n)
|None -> ()


Expand Down
3 changes: 2 additions & 1 deletion Src/Editor/XshdHighlighting.fs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ module SyntaxHighlighting =
let assemblyLocation = IO.Path.GetDirectoryName(Reflection.Assembly.GetExecutingAssembly().Location)
let path = Path.Combine(assemblyLocation,"SyntaxHighlightingFSharp.xshd")
filePath <- path
let stream = new StreamReader(path)//will be copied there after compiling recompiling
let stream = new StreamReader(path) //will be copied there after compiling recompiling
use reader = new Xml.XmlTextReader(stream)
let fsh = Xshd.HighlightingLoader.Load(reader, HighlightingManager.Instance)
fsHighlighting <- Some fsh
Expand Down Expand Up @@ -73,6 +73,7 @@ module SyntaxHighlighting =
let inQuotes = "\"" + filePath + "\""
psi.Arguments <- String.concat " " [inQuotes; "--reuse-window"]
psi.WindowStyle <- Diagnostics.ProcessWindowStyle.Hidden
psi.UseShellExecute <- true
Diagnostics.Process.Start(psi) |> ignore
watch(FileInfo filePath, ed)
else
Expand Down
2 changes: 0 additions & 2 deletions Src/Initialize.fs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ open Fesh.Config
open Fesh.Util
open System.Net.Http



module Initialize =

let mutable feshInstanceForDebug :Fesh = Unchecked.defaultof<Fesh>
Expand Down
14 changes: 9 additions & 5 deletions Src/Views/Commands.fs
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,18 @@ type Commands (grid:TabsAndLog, statusBar:FeshStatusBar) =

// File menu:
member val NewTab = {name= "New File" ;gesture= "Ctrl + N" ;cmd= mkCmdSimple (fun _ -> tabs.AddTab(new Tab(Editor.New(config)),true)) ;tip="Creates a new script file." }
member val OpenTemplateFile = {name= "Edit Template File" ;gesture= "" ;cmd= mkCmdSimple (fun _ -> tabs.AddFile(config.DefaultCode.FileInfo,true)|> ignore) ;tip="Opens the template file that is used when creating a New File ( Ctrl + N)." }
member val OpenFile = {name= "Open File" ;gesture= "Ctrl + O" ;cmd= mkCmdSimple (fun _ -> tabs.OpenFile()) ;tip="Opens a script file." }
member val OpenInVSCode = {name= "Open in VS Code" ;gesture= "Ctrl + Shift + O" ;cmd= mkCmdSimple (fun _ -> tabs.OpenInVSCode()) ;tip="Saves changes and opens the current script file in VS Code. You can change the file there. Fesh wil prompt you to load changes back." }
member val OpenTemplateFile = {name= "Edit Template File" ;gesture= "" ;cmd= mkCmdSimple (fun _ -> tabs.AddFile(config.DefaultCode.FileInfo,true)|> ignore) ;tip="Opens the template file that is used when creating a New File ( Ctrl + N)." }
member val Save = {name= "Save" ;gesture= "Ctrl + S" ;cmd= mkCmdSimple (fun _ -> tabs.Save(tabs.Current) |> ignore ) ;tip="Saves the file. Shows a dialog only if the open file does not exist anymore." }
member val Export = {name= "Export" ;gesture= "" ;cmd= mkCmdSimple (fun _ -> tabs.Export(tabs.Current) |> ignore) ;tip="Shows a dialog to export the file at a new path or name. But keeps the file open at previous location." }
member val SaveAs = {name= "Save As" ;gesture= "Ctrl + Alt + S" ;cmd= mkCmdSimple (fun _ -> tabs.SaveAs(tabs.Current) |> ignore) ;tip="Shows a dialog to save the file at a new path or name." }
member val SaveIncrementing = {name= "Save Incrementing" ;gesture= "" ;cmd= mkCmdSimple (fun _ -> tabs.SaveIncremental(tabs.Current) |> ignore) ;tip="Saves with increased last character of filename.\r\nCan be alphabetic or numeric ( e.g. d->e or 5->6).\r\nDoes not overwrite any existing file."}
member val SaveAll = {name= "Save All" ;gesture= "Ctrl + Shift + S";cmd=mkCmdSimple (fun _ -> for t in tabs.AllTabs do tabs.Save(t) |> ignore);tip="Saves all tabs. Shows a dialog only if the open file does not exist on disk." }
member val Close = {name= "Close File" ;gesture= "Ctrl + F4" ;cmd= mkCmdSimple (fun _ -> tabs.CloseTab(tabs.Current)) ;tip="Closes the current tab, if there is only one tab then the window will be closed."}
member val SaveLog = {name= "Save Text in Log" ;gesture= "" ;cmd= mkCmdSimple (fun _ -> log.SaveAllText(curr().FilePath)) ;tip="Saves all text from Log Window." }
member val SaveLogSel = {name= "Save Selected Text in Log" ;gesture= "" ;cmd= mkCmd isLse (fun _ -> log.SaveSelectedText(curr().FilePath)) ;tip="Saves selected text from Log Window." }
member val SaveAll = {name= "Save All" ;gesture= "Ctrl + Shift + S";cmd=mkCmdSimple (fun _ -> for t in tabs.AllTabs do tabs.Save(t) |> ignore) ;tip="Saves all tabs. Shows a dialog only if the open file does not exist on disk." }
member val Close = {name= "Close File" ;gesture= "Ctrl + F4" ;cmd= mkCmdSimple (fun _ -> tabs.CloseTab(tabs.Current)) ;tip="Closes the current tab, if there is only one tab then the default tab will be shown."}
member val CloseDelete = {name= "Close and Delete File" ;gesture= "" ;cmd= mkCmdSimple (fun _ -> tabs.CloseDelete(tabs.Current)) ;tip="Closes the current tab and deletes the file to the recycle bin, if there is only one tab then the default tab will be shown."}
member val SaveLog = {name= "Save Text in Log" ;gesture= "" ;cmd= mkCmdSimple (fun _ -> log.SaveAllText(curr().FilePath)) ;tip="Saves all text from Log Window." }
member val SaveLogSel = {name= "Save Selected Text in Log" ;gesture= "" ;cmd= mkCmd isLse (fun _ -> log.SaveSelectedText(curr().FilePath)) ;tip="Saves selected text from Log Window." }

// Edit menu:
member val Comment = {name= "Comment" ;gesture= "Ctrl + K" ;cmd = mkCmdSimple (fun _ -> Commenting.comment tabs.CurrAvaEdit) ;tip="Removes '//' at the beginning of current line, \r\nor from all line touched by current selection" }
Expand Down Expand Up @@ -173,13 +175,15 @@ type Commands (grid:TabsAndLog, statusBar:FeshStatusBar) =
let allCustomCommands = [| //for setting up Key gestures below, excluding the ones already provided by avalonedit
this.NewTab
this.OpenFile
this.OpenInVSCode
//this.OpenTemplateFile
this.Save
//this.Export
this.SaveAs
//this.SaveIncrementing
this.SaveAll
this.Close
// this.CloseDelete
//this.SaveLog
//this.SaveLogSel
this.Comment
Expand Down
2 changes: 2 additions & 0 deletions Src/Views/Menu.fs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ type Menu (config:Config,cmds:Commands, tabs:Tabs, statusBar:FeshStatusBar, log:
fileMenu,[
menuItem cmds.NewTab
menuItem cmds.OpenFile
menuItem cmds.OpenInVSCode
menuItem cmds.OpenTemplateFile
sep()
menuItem cmds.Save
Expand All @@ -270,6 +271,7 @@ type Menu (config:Config,cmds:Commands, tabs:Tabs, statusBar:FeshStatusBar, log:
menuItem cmds.SaveIncrementing
menuItem cmds.SaveAll
menuItem cmds.Close
menuItem cmds.CloseDelete
sep()
menuItem cmds.SaveLog
menuItem cmds.SaveLogSel
Expand Down
38 changes: 37 additions & 1 deletion Src/Views/Tabs.fs
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,20 @@ type Tabs(config:Config, log:Log,feshWin:FeshWindow) =
/// also saves currently open files
member this.CloseTab(t) = closeTab(t)

member this.CloseDelete(t:Tab) =
closeTab(t)
match t.Editor.FilePath with
|NotSet _
|Deleted _ -> ()
|SetTo fi ->
try
fi.Refresh()
if fi.Exists then
Microsoft.VisualBasic.FileIO.FileSystem.DeleteFile( fi.FullName, Microsoft.VisualBasic.FileIO.UIOption.OnlyErrorDialogs, Microsoft.VisualBasic.FileIO.RecycleOption.SendToRecycleBin )
with e ->
log.PrintfnIOErrorMsg $"Failed to move file to recycle bin: {e.Message}"


/// Returns true if saving operation was not canceled
member this.Save(t:Tab) = trySave(t)

Expand Down Expand Up @@ -546,6 +560,28 @@ type Tabs(config:Config, log:Log,feshWin:FeshWindow) =
false



/// Opens the file in the Visual Studio Code editor
member this.OpenInVSCode() =
match current.Editor.FilePath with
|SetTo fi ->
let t = this.Current
fi.Refresh()
try
if fi.Exists && ( t.IsCodeSaved || saveAt(t, fi, SaveInPlace) )then
let psi = new Diagnostics.ProcessStartInfo()
psi.FileName <- "code"
let inQuotes = "\"" + fi.FullName + "\""
psi.Arguments <- String.concat " " [inQuotes; "--new-window"]
psi.WindowStyle <- Diagnostics.ProcessWindowStyle.Hidden
psi.UseShellExecute <- true
Diagnostics.Process.Start(psi) |> ignore
else
IFeshLog.log.PrintfnIOErrorMsg $"Open in VS Code: File reading or saving error {fi.FullName}"
with e ->
IFeshLog.log.PrintfnIOErrorMsg $"Open in VS Code: failed: {e}"
|Deleted fi ->
log.PrintfnIOErrorMsg $"Open in VS Code: File {fi.FullName} does not exist on drive anymore. Please save first"
|NotSet n ->
log.PrintfnAppErrorMsg $"Open in VS Code: The file {n} should be saved first!"


9 changes: 5 additions & 4 deletions Src/XmlParser.fs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ open Fesh.Model


/// The only reason to build my own XML parser is to make it error tolerant.
/// To fix https://github.com/dotnet/fsharp/issues/12702 , this might have affected a few nuget packages.
/// To fix https://github.com/dotnet/fsharp/issues/12702
/// While this issue was fixed fast, it took a few month to be release in the official sdk.
/// So this might have affected a few nuget packages.
/// The performance is actually comparable to Xml.Linq.XDocument.Parse()
/// https://stackoverflow.com/questions/4081425/error-tolerant-xml-reader
module XmlParser =
Expand Down Expand Up @@ -55,8 +57,7 @@ module XmlParser =
sb.Clear() |> ignore
s


let inline isWhite c = c=' ' || c='\r' || c= '\n'
let inline isWhite c = c=' ' || c='\r' || c= '\n' || c= '\t'

/// appends Text node from String builder. includes starting and ending whitespace.
/// skips appending if text is only whitespace, but always clears the string builder
Expand Down Expand Up @@ -292,7 +293,7 @@ module XmlParser =
skipSpace()
appendText sb cs //trimAppendText sb cs
|> readNodes
| z -> failwithf $"untracked xml tag '<!{z}' in xml docstring"
| z -> failwithf $"unrecognized xml tag '<!{z}' in xml docstring"

| '/' -> // probably node closing , TODO read name to be sure its the right closing ?
if x[i+2] = '>' && x[i+1] = 'p' then // a </p> in netstandard.xml to skip
Expand Down

0 comments on commit b6507b9

Please sign in to comment.