nimsuggest: first version
This commit is contained in:
parent
217390d181
commit
26b853923c
21 changed files with 364 additions and 218 deletions
187
compiler/nimsuggest/nimsuggest.nim
Normal file
187
compiler/nimsuggest/nimsuggest.nim
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
#
|
||||
#
|
||||
# The Nim Compiler
|
||||
# (c) Copyright 2015 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## Nimsuggest is a tool that helps to give editors IDE like capabilities.
|
||||
|
||||
import strutils, os, parseopt, parseUtils
|
||||
import options, commands, modules, sem, passes, passaux, msgs, nimconf,
|
||||
extccomp, condsyms, lists, net, rdstdin
|
||||
|
||||
const Usage = """
|
||||
Nimsuggest - Tool to give every editor IDE like capabilities for Nim
|
||||
Usage:
|
||||
nimsuggest [options] projectfile.nim
|
||||
|
||||
Options:
|
||||
--port:PORT port, by default 6000
|
||||
--address:HOST binds to that address, by default ""
|
||||
--stdin read commands from stdin and write results to
|
||||
stdout instead of using sockets
|
||||
|
||||
The server then listens to the connection and takes line-based commands.
|
||||
|
||||
In addition, all command line options of Nim that do not affect code generation
|
||||
are supported.
|
||||
"""
|
||||
|
||||
var
|
||||
gPort = 6000.Port
|
||||
gAddress = ""
|
||||
gUseStdin: bool
|
||||
|
||||
const
|
||||
seps = {':', ';', ' ', '\t'}
|
||||
Help = "usage: sug|con|def|use dirtybuffer.nim[;originalfile.nim]:line:col\n"&
|
||||
"type 'quit' to quit\n" &
|
||||
"type 'debug' to toggle debug mode on/off\n" &
|
||||
"type 'terse' to toggle terse mode on/off"
|
||||
|
||||
proc parseQuoted(cmd: string; outp: var string; start: int): int =
|
||||
var i = start
|
||||
i += skipWhitespace(cmd, i)
|
||||
if cmd[i] == '"':
|
||||
i += parseUntil(cmd, outp, '"', i+1)+1
|
||||
else:
|
||||
i += parseUntil(cmd, outp, seps, i)
|
||||
result = i
|
||||
|
||||
proc action(cmd: string) =
|
||||
template toggle(sw) =
|
||||
if sw in gGlobalOptions:
|
||||
excl(gGlobalOptions, sw)
|
||||
else:
|
||||
incl(gGlobalOptions, sw)
|
||||
return
|
||||
|
||||
var opc = ""
|
||||
var i = parseIdent(cmd, opc, 0)
|
||||
case opc.normalize
|
||||
of "sug": gIdeCmd = ideSug
|
||||
of "con": gIdeCmd = ideCon
|
||||
of "def": gIdeCmd = ideDef
|
||||
of "use":
|
||||
modules.resetAllModules()
|
||||
gIdeCmd = ideUse
|
||||
of "quit": quit()
|
||||
of "debug": toggle optIdeDebug
|
||||
of "terse": toggle optIdeTerse
|
||||
else:
|
||||
echo Help
|
||||
return
|
||||
var dirtyfile = ""
|
||||
var orig = ""
|
||||
i = parseQuoted(cmd, dirtyfile, i)
|
||||
if cmd[i] == ';':
|
||||
i = parseQuoted(cmd, orig, i+1)
|
||||
i += skipWhile(cmd, seps, i)
|
||||
var line, col = -1
|
||||
i += parseInt(cmd, line, i)
|
||||
i += skipWhile(cmd, seps, i)
|
||||
i += parseInt(cmd, col, i)
|
||||
if dirtyfile.len != 0:
|
||||
gDirtyBufferIdx = dirtyfile.fileInfoIdx
|
||||
gDirtyOriginalIdx = if orig.len != 0: orig.fileInfoIdx else: gDirtyBufferIdx
|
||||
else:
|
||||
discard "use the same filename as in the last command"
|
||||
resetModule gDirtyBufferIdx
|
||||
if gDirtyBufferIdx != gProjectMainIdx:
|
||||
resetModule gProjectMainIdx
|
||||
gTrackPos = newLineInfo(gDirtyBufferIdx, line, col)
|
||||
#echo dirtyfile, gDirtyBufferIdx, " project ", gProjectMainIdx
|
||||
gErrorCounter = 0
|
||||
compileProject()
|
||||
|
||||
proc serve() =
|
||||
gDirtyBufferIdx = gProjectMainIdx
|
||||
gDirtyOriginalIdx = gProjectMainIdx
|
||||
# do not stop after the first error:
|
||||
msgs.gErrorMax = high(int)
|
||||
if gUseStdin:
|
||||
echo Help
|
||||
var line = ""
|
||||
while readLineFromStdin("> ", line):
|
||||
action line
|
||||
echo ""
|
||||
flushFile(stdout)
|
||||
else:
|
||||
var server = newSocket()
|
||||
server.bindAddr(gPort, gAddress)
|
||||
var inp = "".TaintedString
|
||||
server.listen()
|
||||
var stdoutSocket = newSocket()
|
||||
msgs.writelnHook = proc (line: string) =
|
||||
stdoutSocket.send(line & "\c\L")
|
||||
while true:
|
||||
accept(server, stdoutSocket)
|
||||
stdoutSocket.readLine(inp)
|
||||
action inp.string
|
||||
stdoutSocket.send("\c\L")
|
||||
stdoutSocket.close()
|
||||
|
||||
proc mainCommand =
|
||||
registerPass verbosePass
|
||||
registerPass semPass
|
||||
gCmd = cmdIdeTools
|
||||
incl gGlobalOptions, optCaasEnabled
|
||||
isServing = true
|
||||
wantMainModule()
|
||||
appendStr(searchPaths, options.libpath)
|
||||
if gProjectFull.len != 0:
|
||||
# current path is always looked first for modules
|
||||
prependStr(searchPaths, gProjectPath)
|
||||
|
||||
serve()
|
||||
|
||||
proc processCmdLine*(pass: TCmdLinePass, cmd: string) =
|
||||
var p = parseopt.initOptParser(cmd)
|
||||
while true:
|
||||
parseopt.next(p)
|
||||
case p.kind
|
||||
of cmdEnd: break
|
||||
of cmdLongoption, cmdShortOption:
|
||||
case p.key.normalize
|
||||
of "port": gPort = parseInt(p.val).Port
|
||||
of "address": gAddress = p.val
|
||||
of "stdin": gUseStdin = true
|
||||
else: processSwitch(pass, p)
|
||||
of cmdArgument:
|
||||
options.gProjectName = unixToNativePath(p.key)
|
||||
# if processArgument(pass, p, argsCount): break
|
||||
|
||||
proc handleCmdLine() =
|
||||
if paramCount() == 0:
|
||||
stdout.writeln(Usage)
|
||||
else:
|
||||
processCmdLine(passCmd1, "")
|
||||
if gProjectName != "":
|
||||
try:
|
||||
gProjectFull = canonicalizePath(gProjectName)
|
||||
except OSError:
|
||||
gProjectFull = gProjectName
|
||||
var p = splitFile(gProjectFull)
|
||||
gProjectPath = p.dir
|
||||
gProjectName = p.name
|
||||
else:
|
||||
gProjectPath = getCurrentDir()
|
||||
loadConfigs(DefaultConfig) # load all config files
|
||||
# now process command line arguments again, because some options in the
|
||||
# command line can overwite the config file's settings
|
||||
extccomp.initVars()
|
||||
processCmdLine(passCmd2, "")
|
||||
mainCommand()
|
||||
|
||||
when false:
|
||||
proc quitCalled() {.noconv.} =
|
||||
writeStackTrace()
|
||||
|
||||
addQuitProc(quitCalled)
|
||||
|
||||
condsyms.initDefines()
|
||||
defineSymbol "nimsuggest"
|
||||
handleCmdline()
|
||||
Loading…
Add table
Add a link
Reference in a new issue