-
Notifications
You must be signed in to change notification settings - Fork 30
/
getopt.fs
158 lines (138 loc) · 4.99 KB
/
getopt.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
module FVim.getopt
open common
open System.Net
type NeovimRemoteEndpoint =
| Tcp of endpoint: IPEndPoint
| NamedPipe of address: string
type FVimRemoteVerb =
| AttachTo of id: int
| NewSession of args: string list
| AttachFirst
// | Interactive
type FVimRemoteTransport =
| Local
| Remote of prog: string * args: string list
type ServerOptions =
| Embedded of prog: string * args: string list * stderrenc: System.Text.Encoding
| NeovimRemote of addr: NeovimRemoteEndpoint * files: string list
| FVimRemote of serverName: string option * transport: FVimRemoteTransport * verb: FVimRemoteVerb * files: string list
type Intent =
| Start of serveropts: ServerOptions * norc: bool * remoteinit: bool
| Setup
| Uninstall
| Daemon of pipe: string option * nvim: string * stderrenc: System.Text.Encoding
type Options =
{
intent: Intent
logToStdout: bool
logToFile: bool
logPatterns: string option
}
let parseOptions (args: string[]) =
let args = ResizeArray(args)
let eat1 opt =
if args.Contains(opt)
then args.Remove(opt)
else false
let eat2 opt =
let idx = args.IndexOf(opt)
if idx >= 0 then
let res = Some args.[idx+1]
args.RemoveRange(idx, 2)
res
else None
let eat2d opt defaultValue =
match eat2 opt with
| None -> if eat1 opt then Some defaultValue else None
| x -> x
// startup options
let nvim = eat2 "--nvim" |> Option.defaultValue "nvim"
let terminal = eat1 "--terminal"
let termcmd = eat2 "--terminal-cmd"
// remoting
let ssh = eat2 "--ssh"
let wsl = eat1 "--wsl"
let nvr = eat2 "--nvr"
let fvr = eat2d "--fvr" "new"
// shell
let setup = eat1 "--setup"
let uninstall = eat1 "--uninstall"
let daemon = eat1 "--daemon"
let pipe = eat2 "--pipe"
// debug & tracing
let trace_to_stdout = eat1 "--trace-to-stdout"
let trace_to_file = eat1 "--trace-to-file"
let trace_patterns = eat2 "--trace-patterns"
if wsl && ssh.IsSome then
failwith "--wsl and --ssh cannot be used together."
if nvr.IsSome && (wsl || ssh.IsSome || fvr.IsSome) then
failwith "--nvr cannot be used with --fvr, --wsl or --ssh."
let norc =
args
|> Seq.pairwise
|> Seq.exists( (=) ("-u", "NORC") )
if terminal then
let set x = "+\"set " + x + "\""
// fvim --wsl -u NORC +"set noshowmode" +"set laststatus=0" +"set noruler" +"set noshowcmd" +"set mouse=a" +terminal
args.AddRange([
"-u"; "NORC"
set "noshowmode"
set "laststatus=0"
set "noruler"
set "noshowcmd"
set "mouse=a"
])
match termcmd with
| Some cmd -> "+\"terminal " + cmd + "\""
| None -> "+terminal"
|> args.Add
let enc =
if wsl then System.Text.Encoding.Unicode
else System.Text.Encoding.UTF8
// stop altering the args list now
let argsL = List.ofSeq args
let intent =
if setup then Setup
elif uninstall then Uninstall
elif daemon then Daemon(pipe, nvim, enc)
else
let serveropts, remoteinit =
match fvr, nvr with
| Some fvrVerb, _ ->
let transport =
// TODO
if wsl then Remote("wsl", ["bash"; "-l"; "-c"; "nc"; "-U"])
elif ssh.IsSome then Remote("ssh", [ssh.Value; "nc"; "-U"])
else Local
let verb =
match fvrVerb.ToLowerInvariant() with
| "attach" | "a" -> AttachFirst
| "new" | "n" -> NewSession(argsL)
| v -> AttachTo(int v)
let files =
match verb with
| NewSession _ -> []
| _ -> argsL
FVimRemote(pipe, transport, verb, files),true
| _, Some nvrAddr ->
match nvrAddr.Split(":") with
| [| ParseIp ipaddr; ParseUInt16 port |] -> NeovimRemote(Tcp <| IPEndPoint(ipaddr, int port), argsL),true
| _ -> NeovimRemote(NamedPipe nvrAddr, argsL),true
| None, None ->
let prog, args, r =
if wsl then
"wsl", ["bash"; "-l"; "-c"; $"nvim --embed {args |> escapeArgs |> join}"], true
elif ssh.IsSome then
"ssh", [ssh.Value; nvim; "--embed"] @ argsL, true
else
nvim, ["--embed"] @ argsL, false
in
Embedded(prog, args, enc),r
in
Start(serveropts, norc, remoteinit)
{
logToStdout = trace_to_stdout
logToFile = trace_to_file
logPatterns = trace_patterns
intent = intent
}