Skip to content

Commit

Permalink
Rename command
Browse files Browse the repository at this point in the history
  • Loading branch information
goswinr committed Dec 14, 2024
1 parent 38a6507 commit 645a592
Show file tree
Hide file tree
Showing 14 changed files with 157 additions and 64 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/releaseStandalone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ jobs:
draft: false
prerelease: false
body: |
Don't forget to **unblock** the zip file before extracting.
> [!IMPORTANT]
> Don't forget to **unblock** the zip file before extracting.
After extracting save at any location and just run `Fesh.exe` to start.
Changes:
[View Changelog](https://github.com/goswinr/Fesh/blob/main/CHANGELOG.md)
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- command for opening a file in VS Code
- command for closing and deleting a file
- command for renaming files
### Changed
- location of SettingsFolder
- simplify type signature of C# style optional args in tooltips

## [0.15.0] - 2024-11-22
### Added
Expand Down
2 changes: 1 addition & 1 deletion Src/Config/AutoCompleteStatistic.fs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ open Fesh.Model
type AutoCompleteStatistic ( runContext:RunContext) =

let customPriorities = [
// first item wil have highest priority
// first item will have highest priority
"true"
"false"
"printfn"
Expand Down
4 changes: 3 additions & 1 deletion Src/Config/Config.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
open Fesh.Model




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

let runContext = new RunContext (startUpData)
let settings = new Fittings.PersistentSettings (runContext.SettingsFileInfo,IFeshLog.printError)
let settings = new Fittings.PersistentSettings (runContext.SettingsFileInfo, IFeshLog.printError)
let recentlyUsedFiles = new RecentlyUsedFiles (runContext)
let openTabs = new OpenTabs (runContext, startupArgs)
let defaultCode = new DefaultCode (runContext)
Expand Down
15 changes: 11 additions & 4 deletions Src/Config/FsiArguments.fs
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,32 @@ open Fesh.Model

type FsiArguments ( runContext:RunContext) =

let filePath0 = runContext.GetPathToSaveAppData("FsiArguments .txt")
let filePath0 = runContext.GetPathToSaveAppData("FsiArguments.txt")
let writer = SaveReadWriter(filePath0,IFeshLog.printError)

let defaultArgs =
if runContext.IsHosted then
if runContext.IsHosted then // dec 2024, F# 9, on net48 hosted in Rhino --multiemit- is needed to enable multiple evaluations, line numbers for errors don't work though.
[| "first arg must be there but is ignored" ; "--langversion:preview" ; "--exec"; "--debug+"; "--debug:full" ;"--optimize+" ; "--gui+" ; "--nologo"; "--multiemit-"|]
else // Standalone for net48 too --multiemit is always there on netCore
[| "first arg must be there but is ignored" ; "--langversion:preview" ; "--exec"; "--debug+"; "--debug:full" ;"--optimize+" ; "--gui+" ; "--nologo"; "--multiemit+" |]


// Standalone with "--multiemit" to have line numbers in error messages see https://github.com/dotnet/fsharp/discussions/13293
// Hosted without "--multiemit", error line numbers don't work there anyway, and in addition accessing previously emited assemblies might fail with a TypeLoadException.
// see: https://fsharp.github.io/fsharp-compiler-docs/fsi-emit.html and https://github.com/dotnet/fsharp/blob/main/src/Compiler/Interactive/fsi.fs#L1171
// Hosted without "--multiemit", error line numbers don't work there anyway, and in addition accessing previously emitted assemblies might fail with a TypeLoadException.
// see: https://fsharp.github.io/fsharp-compiler-docs/fsi-emit.html
// and https://github.com/dotnet/fsharp/blob/main/src/Compiler/Interactive/fsi.fs#L1171
// https://github.com/dotnet/fsharp/discussions/13293

// first arg is ignored: https://github.com/fsharp/FSharp.Compiler.Service/issues/420
// and https://github.com/fsharp/FSharp.Compiler.Service/issues/877
// and https://github.com/fsharp/FSharp.Compiler.Service/issues/878

// use "--gui+" to enable winforms event loop ( on by default) check if fixed: https://github.com/dotnet/fsharp/issues/13473

// use "--exec" instead of "--noninteractive" see https://github.com/dotnet/fsharp/blob/7b46dad60df8da830dcc398c0d4a66f6cdf75cb1/src/Compiler/Interactive/fsi.fs#L937
// TODO: use --noninteractive flag instead of accessing controlled execution via reflection:
// https://github.com/dotnet/fsharp/pull/15184

// "--shadowcopyreferences" is ignored https://github.com/fsharp/FSharp.Compiler.Service/issues/292

let defaultArgsText = defaultArgs|> String.concat Environment.NewLine
Expand Down
59 changes: 50 additions & 9 deletions Src/Config/RunContext.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

open System
open Fesh.Model
open System.IO



/// hostName: a string for the name of the hosting App (will be used for settings file name an displayed in the Title Bar.
/// mainWindowHandle: Pointer to main window(nativeInt),
Expand All @@ -15,24 +18,59 @@ type HostedStartUpData = {
defaultCode:option<string>
}

module Folders =
let appData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)


let validHost(n:string)=
let mutable n = n
for c in IO.Path.GetInvalidFileNameChars() do
n <- n.Replace(c, '_') // make sure host name is a valid file name
n


// restore settings files from version 0.15.0 or lower
let restoreSettingsFolderFromOldLocation(newFolder:string, startUpData:HostedStartUpData option) =
try
let oldPath =
match startUpData with
|None -> IO.Path.Combine(appData, "Fesh") // Standalone
|Some sd -> IO.Path.Combine(appData, "Fesh", validHost sd.hostName)
let oldSett = IO.Path.Combine(oldPath, "Settings.txt")
let newSett = IO.Path.Combine(newFolder, "Settings.txt")
if IO.File.Exists oldSett && not ( IO.File.Exists newSett) then
for f in [| "AutoCompleteStatistic.txt"
"CurrentlyOpenFiles.txt"
"DefaultCode.fsx"
"FoldingStatus.txt"
"FsiArguments.txt"
"PositionedWindow.txt"
"RecentlyUsedFiles.txt"
"Settings.txt"
|] do
let oldFile= IO.Path.Combine(oldPath, f)
let newFile = IO.Path.Combine(newFolder, f)
if IO.File.Exists oldFile && not (IO.File.Exists newFile) then
IO.File.Move(oldFile,newFile)
with e ->
IFeshLog.log.PrintfnIOErrorMsg $"Error while trying to restore old settings file: {e}"


open Folders

/// A class to hold the current App Run context (Standalone or Hosted)
type RunContext (startUpData:HostedStartUpData option) =

let isRunningOnDotNetCore =
Runtime.InteropServices.RuntimeInformation.FrameworkDescription.StartsWith(".NET Framework", StringComparison.OrdinalIgnoreCase) |> not
//Type.GetType("System.Runtime.Loader.AssemblyLoadContext") <> null // https://github.com/dotnet/runtime/issues/22779#issuecomment-315527735


let settingsFolder =
let appData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
let path =
match startUpData with
|None ->
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", "Settings", host)

|None -> IO.Path.Combine(appData, "Fesh", "Settings", "Standalone") // Standalone
|Some sd -> IO.Path.Combine(appData,"Fesh", "Settings", validHost sd.hostName)
IO.Directory.CreateDirectory(path) |> ignore
path

Expand All @@ -44,11 +82,14 @@ type RunContext (startUpData:HostedStartUpData option) =
IO.Path.Combine(settingsFolder, "PositionedWindow.txt")
|> IO.FileInfo

do
restoreSettingsFolderFromOldLocation(settingsFolder,startUpData)

/// To get a path where to save the setting files, give file name including extension
member this.GetPathToSaveAppData (fileNameInclExt:string) =
IO.Path.Combine(settingsFolder, fileNameInclExt )

member this.SettingsFolder = settingsFolder
// member this.SettingsFolder = settingsFolder

member this.SettingsFileInfo = settingsFileInfo

Expand Down
14 changes: 7 additions & 7 deletions Src/Editor/Checker.fs
Original file line number Diff line number Diff line change
Expand Up @@ -306,13 +306,13 @@ type Checker private () =
static member GetDeclarations (posX:PositionInCodeEx, res:FullCheckResults ) =
// IFeshLog.log.PrintfnDebugMsg "*2.0 GetCompletions for:\r\n%A" posX
// Symbols are only for finding out if an argument is optional
let symUse = res.checkRes.GetDeclarationListSymbols(
Some res.parseRes // ParsedFileResultsOpt
, posX.lineIdx // line
, posX.lineToCaret // lineText
, posX.partLoName // PartialLongName
//, (fun () -> Checker.GetAllEntities(res, true)) // getAllEntities: (unit -> AssemblySymbol list) // TODO use that too like FsAutocomplete does ???
)
// let symUse = res.checkRes.GetDeclarationListSymbols(
// Some res.parseRes // ParsedFileResultsOpt
// , posX.lineIdx // line
// , posX.lineToCaret // lineText
// , posX.partLoName // PartialLongName
// //, (fun () -> Checker.GetAllEntities(res, true)) // getAllEntities: (unit -> AssemblySymbol list) // TODO use that too like FsAutocomplete does ???
// )

// for auto completion
let decls = res.checkRes.GetDeclarationListInfo(
Expand Down
4 changes: 2 additions & 2 deletions Src/Editor/Completions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ type Completions(state: InteractionState) =

let mutable willInsert = false // to track if window closed without inserting ( e.g pressing esc)

let empty = ResizeArray<string>()
//let empty = ResizeArray<string>()

let selectedCompletionText ()=
match win with
Expand Down Expand Up @@ -208,7 +208,7 @@ type Completions(state: InteractionState) =
let getToolTip (it:DeclarationListItem) : obj =
async{
let ttText = it.Description
let structured = TypeInfo.makeFeshToolTipDataList (ttText, it.FullName, empty)
let structured = TypeInfo.makeFeshToolTipDataList (ttText, it.FullName)
// if Checker.OptArgsDict.ContainsKey it.FullName then TypeInfo.makeFeshToolTipDataList (ttText, it.FullName, Checker.OptArgsDict.[it.FullName])
// else TypeInfo.makeFeshToolTipDataList (ttText, it.FullName, empty)
do! Async.SwitchToContext Fittings.SyncWpf.context
Expand Down
21 changes: 12 additions & 9 deletions Src/Editor/TypeInfo.fs
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,8 @@ type TypeInfo private () =
static let darkblue = Brushes.DarkSlateBlue |> darker 20 |> freeze
static let white = Brushes.White |> darker 5 |> freeze

static let codeRun (td:ToolTipData) (code:string) : seq<Run>=
// static let codeRun (td:ToolTipData) (code:string) : seq<Run> =
static let codeRun (code:string) : seq<Run> =
let tx = code.TrimEnd()
[
new Run(" ")
Expand Down Expand Up @@ -319,7 +320,8 @@ type TypeInfo private () =
n.attrs.Head.value = (match n.children.Head with Text t -> t |Node _ -> "")
)

static let mainXmlBlock (node:XmlParser.Child, td:ToolTipData): TextBlockSelectable =
// static let mainXmlBlock (node:XmlParser.Child, td:ToolTipData): TextBlockSelectable =
static let mainXmlBlock (node:XmlParser.Child): TextBlockSelectable =
let tb = new TextBlockSelectable()
tb.FontSize <- StyleState.fontSize * 1.0
tb.FontFamily <- StyleState.fontToolTip
Expand Down Expand Up @@ -352,7 +354,7 @@ type TypeInfo private () =
tb.Inlines.Add( new Run(fixName n.name, Foreground = darkGray)) //FontWeight = FontWeights.Bold, // Summary header, Parameter header ....
tb.Inlines.Add( new LineBreak())
for at in n.attrs do // there is normally just one ! like param:name, paramref:name typeparam:name
tb.Inlines.AddRange( at.value |> fixTypeName|> codeRun td )
tb.Inlines.AddRange( at.value |> fixTypeName|> codeRun )
tb.Inlines.Add( new Run(": ", Foreground = black))

let childs = n.children |> Array.ofList
Expand All @@ -373,8 +375,8 @@ type TypeInfo private () =
// e.g. for: <returns> <see langword="true" /> if <paramref name="objA" /> is the same instance as <paramref name="objB" /> or if both are null; otherwise, <see langword="false" />.</returns>
for at in n.attrs do
//printfn $"{n.name} {at.name}:{at.value }"
if at.name="cref" then tb.Inlines.AddRange( at.value |> fixTypeName |> codeRun td)
else tb.Inlines.AddRange( at.value |> codeRun td)
if at.name="cref" then tb.Inlines.AddRange( at.value |> fixTypeName |> codeRun )
else tb.Inlines.AddRange( at.value |> codeRun )
//tb.Inlines.Add( new Run(" "))

else
Expand All @@ -388,7 +390,7 @@ type TypeInfo private () =

and addCode (this:XmlParser.Child) depth =
match this with
|Text t -> tb.Inlines.AddRange(codeRun td t) // done in codeRun: tb.Inlines.Add(" ")
|Text t -> tb.Inlines.AddRange(codeRun t) // done in codeRun: tb.Inlines.Add(" ")
|Node n -> loop this n.name false Trim.No depth


Expand Down Expand Up @@ -469,7 +471,7 @@ type TypeInfo private () =
if ass <> "" then assemblies.Add(ass) |> ignore
//if ass.Length > 10 then assemblies.Add("\r\n" + ass) |> ignore // it may be from more than one assembly? because of type extensions?
//else assemblies.Add(ass) |> ignore
subAdd <| mainXmlBlock (node, td)
subAdd <| mainXmlBlock (node)
|Error errTxt ->
subAdd<| TextBlockSelectable(Text = errTxt, TextWrapping = TextWrapping.Wrap, FontSize = StyleState.fontSize * 0.70 , Foreground = errMsgGray)//,FontFamily = StyleState.fontToolTip )

Expand Down Expand Up @@ -630,14 +632,15 @@ type TypeInfo private () =

//static member namesOfOptionalArgs(fsu:FSharpSymbolUse) = namesOfOptnlArgs(fsu)

static member makeFeshToolTipDataList (sdtt: ToolTipText, fullName:string, optArgs:ResizeArray<string>) = makeToolTipDataList (sdtt, fullName) //, optArgs)
static member makeFeshToolTipDataList (sdtt: ToolTipText, fullName:string) = //, optArgs:ResizeArray<string>) =
makeToolTipDataList (sdtt, fullName) //, optArgs)

static member getPanel (tds:ToolTipData list, ed:ToolTipExtraData) =
cachedToolTipData <- tds
cachedExtraData <- ed
makeToolTipPanel (tds, ed, true)

/// regenerates a view of the last created panel so it can be used again in the popout window
/// regenerates a view of the last created panel so it can be used again in the pop-out window
static member getPanelCached () =
makeToolTipPanel (cachedToolTipData, cachedExtraData, false)

Expand Down
8 changes: 6 additions & 2 deletions Src/Fsi.fs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ type Fsi private (config:Config) =
// will point to the token in https://github.com/dotnet/fsharp/blob/main/src/Compiler/Interactive/ControlledExecution.fs
let mutable fscCancellationToken : CancellationTokenSource voption = ValueNone

// TODO: use non-interactive flag instead of accessing controlled execution via reflection:
// https://github.com/dotnet/fsharp/pull/15184

let setAControlledExecutionCancellationToken()=
if config.RunContext.IsRunningOnDotNetCore then
Expand All @@ -132,7 +134,7 @@ type Fsi private (config:Config) =
with e ->
IFeshLog.log.PrintfnFsiErrorMsg "Getting FSI token via reflection form Fsharp.Compiler.Service failed"


/// returns tru if something was aborted
let getControlledExecutionAborter(thread:Thread) : unit -> bool =
if config.RunContext.IsRunningOnDotNetCore then
match sessionOpt with
Expand Down Expand Up @@ -162,7 +164,9 @@ type Fsi private (config:Config) =
fun () ->
#if NETFRAMEWORK
thread.Abort()
true
match state with
| Ready | Initializing | NotLoaded -> false
| Compiling | Evaluating -> true
#else
ignore thread // to avoid warning when NETFRAMEWORK is not defined
false
Expand Down
5 changes: 3 additions & 2 deletions Src/Views/Commands.fs
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,9 @@ type Commands (grid:TabsAndLog, statusBar:FeshStatusBar) =
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 Rename = {name= "Rename/Move" ;gesture= "" ;cmd= mkCmdSimple (fun _ -> tabs.Rename(tabs.Current) |> ignore) ;tip="Shows a dialog to Rename and/or Move the file." }
member val Export = {name= "Duplicate/Export" ;gesture= "" ;cmd= mkCmdSimple (fun _ -> tabs.Export(tabs.Current) |> ignore) ;tip="Shows a dialog to duplicate 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.(Keeping the old file at the current name and location.)" }
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 default tab will be shown."}
Expand Down
Loading

0 comments on commit 645a592

Please sign in to comment.