Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
413 changes: 0 additions & 413 deletions TeXmacs/plugins/julia/julia/MoganJulia.jl

This file was deleted.

145 changes: 145 additions & 0 deletions TeXmacs/plugins/julia/julia/julia.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
#
# MoganJulia.jl
Comment thread
Copilot marked this conversation as resolved.
Outdated
# A Mogan plugin for the Julia language
# (c) 2021 Massimiliano Gubinelli <mgubi@mac.com>
# 2026 Tianyou Liu <tianyou@liii.pro>
#
# This software falls under the GNU general public license version 3 or later.
# It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
# in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
#

module MoganJulia

# Imports
using REPL
using Markdown
using UUIDs
import Base: AbstractDisplay, display, redisplay, catch_stack, show
import REPL: helpmode
import REPL.REPLCompletions: completions, completion_text
import Base.Libc: flush_cstdio

const current_module = Ref{Module}(Main)
const orig_stdout = Ref{IO}(stdout)
const orig_stderr = Ref{IO}(stderr)

# Resolve include path relative to the directory containing this file
const julia_plugin_dir = @__DIR__

# Include submodules/files
include(joinpath(julia_plugin_dir, "tmjl", "protocol.jl"))
include(joinpath(julia_plugin_dir, "tmjl", "capture.jl"))
include(joinpath(julia_plugin_dir, "tmjl", "display.jl"))
include(joinpath(julia_plugin_dir, "tmjl", "completion.jl"))

#=============================================================================#
### Some utilities

function banner()
io = IOBuffer()
# the Julia banner is in REPL in Julia >1.11, and in Base before that
# so we need to do a little chasing
if isdefined(REPL,:banner)
REPL.banner(io)
elseif isdefined(Base,:banner)
Base.banner(io)
else
write(io, "Cannot find the startup banner, sorry!\n");
end
write(io, "Julia plugin for Mogan STEM.\n");
tm_out(String(take!(io)))
end

#=============================================================================#
### Main loop

# we do not want to exit on SIGINT
# we can then catch InterruptException
Base.exit_on_sigint(false)

local read_stdout, read_stderr
# redirect output/error
read_stdout, = redirect_stdout()
redirect_stdout(TMJuliaStdio(stdout,read_stdout,"stdout"))
read_stderr, = redirect_stderr()
redirect_stderr(TMJuliaStdio(stderr,read_stderr,"stderr"))
#redirect_stdin(TMJuliaStdio(stdin,"stdin"))

# redirect display
pushdisplay(InlineDisplay())

# print banner
tm_begin()
banner()
tm_out(PROMPT,">>> ")
tm_end()

# go
n = 0 # execution counter
ans = nothing # record last successful answer in ans

while true
line = readline(stdin)
if length(line) == 0 && eof(stdin)
break
end
length(line) == 0 && continue
if line[1] == DATA_COMMAND
# is tab completion the only possible command?
do_tab_complete(line)
continue
end
lines = []
while line != "<EOF>"
push!(lines, line)
line = readline(stdin)
end
local code = join(lines,"\n")
local result = nothing
local err = nothing
global ans = nothing
tm_begin()
try
global n += 1
# "; ..." cells are interpreted as shell commands for run
code = replace(code, r"^\s*;.*$" =>
m -> string(replace(m, r"^\s*;" => "Base.repl_cmd(`"),
"`, stdout)"))
# a cell beginning with "? ..." is interpreted as a help request
hcode = replace(code, r"^\s*\?" => "")
# Let's try to run the input
if hcode != code # help request
buf = IOBuffer()
help = Core.eval(Main, helpmode(buf, hcode))
#flush_output()
tm_out("HELP: $(String(take!(buf)))\n")
display(help)
else
# finally run the code!
result = include_string(current_module[], code, "In[$n]")
REPL.ends_with_semicolon(code) ? result = nothing : ans = result
end
catch e
err = e
result = catch_stack()
end

# output
try
if err != nothing
Base.invokelatest(Base.display_error, stderr, result)
elseif result != nothing
Base.invokelatest(display, result)
#show(stdout, result) # display the result as string
end
catch e
write(stdout, "Error showing values $(e)");
Base.invokelatest(Base.display_error, stderr, catch_stack())
end
flush_all() # send all to mogan
# flush_output() # send all to mogan
tm_end()
end # while true

end # module MoganJulia
74 changes: 74 additions & 0 deletions TeXmacs/plugins/julia/julia/tmjl/capture.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#
# capture.jl
# Standard stream capturing and redirection for Mogan Julia plugin
# (c) 2021 Massimiliano Gubinelli <mgubi@mac.com>
# 2026 Tianyou Liu <tianyou@liii.pro>
#
# This software falls under the GNU general public license version 3 or later.
# It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
# in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
#

import Base.Libc: flush_cstdio

#=============================================================================#
### Flush all redirected streams to Mogan

function flush_all()
flush_cstdio() # flush writes to stdout/stderr by external C code
flush(stdout)
flush(stderr)
end

#=============================================================================#
### Stream redirection (from IJulia)

# create a wrapper type around redirected stdio streams,
# both for overloading things like `flush` and so that we
# can set properties like `color`.
struct TMJuliaStdio{IO_t <: IO} <: Base.AbstractPipe
io::IOContext{IO_t}
read_stream::Base.PipeEndpoint
end

TMJuliaStdio(io::IO, read_stream::Base.PipeEndpoint, stream::AbstractString="unknown") =
TMJuliaStdio{typeof(io)}(IOContext(io, :color=>false,
:mogan_stream=>stream,
:displaysize=>displaysize()), read_stream)
Base.pipe_reader(io::TMJuliaStdio) = io.io.io
Base.pipe_writer(io::TMJuliaStdio) = io.io.io
Base.lock(io::TMJuliaStdio) = lock(io.io.io)
Base.unlock(io::TMJuliaStdio) = unlock(io.io.io)
Base.in(key_value::Pair, io::TMJuliaStdio) = in(key_value, io.io)
Base.haskey(io::TMJuliaStdio, key) = haskey(io.io, key)
Base.getindex(io::TMJuliaStdio, key) = getindex(io.io, key)
Base.get(io::TMJuliaStdio, key, default) = get(io.io, key, default)
Base.displaysize(io::TMJuliaStdio) = displaysize(io.io)
Base.unwrapcontext(io::TMJuliaStdio) = Base.unwrapcontext(io.io)
Base.setup_stdio(io::TMJuliaStdio, readable::Bool) = Base.setup_stdio(io.io.io, readable)

Base.flush(io::TMJuliaStdio) = begin
#write(orig_stdout[],"FLUSHING $(get(io.io, :mogan_stream, "error"))\n")
Base.flush(io.io.io)
# add one more char so that we do not block on readavailable later
write(io.io.io,"!")
local buf = chop(String(readavailable(io.read_stream)));
buf == "" && return
if get(io.io, :mogan_stream, "error") == "stdout"
tm_out(buf * "\n")
elseif get(io.io, :mogan_stream, "error") == "stderr"
tm_err(VERBATIM, buf)
end
end

if VERSION < v"1.7.0-DEV.254"
for s in ("stdout", "stderr", "stdin")
f = Symbol("redirect_", s)
sq = QuoteNode(Symbol(s))
@eval function Base.$f(io::TMJuliaStdio)
io[:mogan_stream] != $s && throw(ArgumentError(string("expecting ", $s, " stream")))
Core.eval(Base, Expr(:(=), $sq, io))
return io
end
end
end
28 changes: 28 additions & 0 deletions TeXmacs/plugins/julia/julia/tmjl/completion.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#
# completion.jl
# Autocompletion protocol implementation for Mogan Julia plugin
# (c) 2021 Massimiliano Gubinelli <mgubi@mac.com>
# 2026 Tianyou Liu <tianyou@liii.pro>
#
# This software falls under the GNU general public license version 3 or later.
# It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
# in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
#

import REPL.REPLCompletions: completions, completion_text

function do_tab_complete(cmd::AbstractString)
# syntax [DATA_COMMAND](complete [STRING] [CURSOR])
try
pos = 12
arg1,pos = Meta.parse(cmd,pos; greedy=false) # [STRING]
arg2,pos = Meta.parse(cmd,pos; greedy=false) # [CURSOR]
if isa(arg1,AbstractString) && isa(arg2,Integer)
ret,range,shouldcomplete = completions(arg1,arg2)
compls = join(unique!(map(x -> "\"$(completion_text(x)[range.stop+2-range.start:end])\"",ret))," ")
tm_out("scheme:", "(tuple \"$(arg1[range])\" $(compls))")
Comment on lines +22 to +23
end
catch e
# ignore errors
end
end
Loading
Loading