-
Notifications
You must be signed in to change notification settings - Fork 9
/
TermiC.sh
executable file
·125 lines (119 loc) · 6.17 KB
/
TermiC.sh
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
#!/bin/bash
# Copyright (C) 2022 Yusuf Kağan Hanoğlu
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
lang="c"
extension="c"
compiler="gcc"
addInclude=""
versiontxt="1.3.0V"
helptxt="TermiC $versiontxt \nLicensed under GPLv3\
\n--help -h: \t Shows this help menu
\n--version -v: \t Shows the version number
\n\nC Mode: \ttermic\
\nCPP Mode: \ttermic cpp\
\n\t\ttermic++
\nCPP 2017 Mode: \ttermic cpp17\
\nCPP 2020 Mode: \ttermic cpp20\
\nTCC Mode: \ttermic tcc\
\n\nCommands:\
\nhelp: \t\tShows this help menu\nabort: \t\tAborts inline prompt mode which are entered by curly bracket\
\nshow: \t\tPrints last successfully compiled source file\nshowtmp: \tPrints last compiled source file with deleted edits\
\nsave: \t\tSaves source file to working directory\nsavebin: \tSaves binary file to working directory\
\nclear: \t\tDeletes all declared functions, classes etc. and resets shell\
\nexit: \t\tDeletes created temp files and exits program\
\n\nAuthors:\nYusuf Kagan Hanoglu\nMax Schillinger"
[[ $1 == "-h" || $1 == "--help" ]] && echo -e $helptxt && exit
[[ $1 == "-v" || $1 == "--version" ]] && echo $versiontxt && exit
[[ $1 == "tcc" ]] && compiler="tcc"
[[ $1 == "cpp" ]] || [[ $0 =~ \+\+ ]] && lang="c++" && compiler="g++ -fpermissive" && extension="cpp" && addInclude="#include <iostream>\nusing namespace std;\n"
[[ $1 == "cpp17" ]] || [[ $0 =~ \+\+ ]] && lang="c++" && compiler="g++ -fpermissive -std=c++17" && extension="cpp" && addInclude="#include <iostream>\nusing namespace std;\n"
[[ $1 == "cpp20" ]] || [[ $0 =~ \+\+ ]] && lang="c++" && compiler="g++ -fpermissive -std=c++2a" && extension="cpp" && addInclude="#include <iostream>\nusing namespace std;\n"
command -v bat > /dev/null 2>&1 && catcmd="bat -p -l $lang" || catcmd=cat
echo TermiC $versiontxt
echo Language: $lang
echo Compiler: $compiler
echo Type \'help\' for additional information
oldPWD=`pwd`
cd /tmp
sourceFile=`mktemp termic-XXXXXXXX.$extension`
binaryFile=`basename $sourceFile .$extension`
cacheDir="${XDG_CACHE_HOME:-$HOME/.cache}/termic"
[[ -d $cacheDir ]] || mkdir -p "$cacheDir"
historyFile="$cacheDir/${extension}_history"
history -r "$historyFile"
# disable filename completion on tab
bind -r "\C-i" 2> /dev/null
fullPrompt=""
inlineCounter=0
promptPS1=">> "
initSource="#include \"stdio.h\"\n#include \"stdlib.h\"\n${addInclude}int main() {"
echo -e $initSource > $sourceFile
trap "echo -e '\nKeyboardInterrupt'" SIGINT
while true;do
[[ $inlineCounter -gt 0 ]] && promptPS1=" " || promptPS1=">> "
prompt=$(read -rep "$promptPS1"$(echo $(yes ... | head -n $inlineCounter) | sed 's/ //g') prompt || { [[ $inlineCounter -gt 0 ]] || prompt="exit"; } ; echo $prompt)
[[ $prompt == "" ]] && continue
history -s "$prompt"
[[ $prompt == "exit" ]] && break
[[ $prompt == "clear" ]] && :> $sourceFile && :> $sourceFile.tmp && :> $binaryFile && fullPrompt="" && inlineCounter=0 && echo -e $initSource > $sourceFile && continue
[[ $prompt == "abort" ]] && fullPrompt="" && inlineCounter=0 && continue
[[ $prompt == "show" ]] && $catcmd $sourceFile && continue
[[ $prompt == "showtmp" ]] && { [[ -f $sourceFile.tmp ]] && $catcmd $sourceFile.tmp || echo "No .tmp file!"; continue; }
[[ $prompt == "save" ]] && cp $sourceFile $oldPWD && echo "}" >> $oldPWD/$sourceFile && echo "Source file saved to $oldPWD/$sourceFile" && continue
[[ $prompt == "savebin" ]] && cp $binaryFile $oldPWD && echo "Binary file saved to $oldPWD/$binaryFile" && continue
[[ $prompt == "help" ]] && echo -e "$helptxt" && continue
fullPrompt=`echo "$fullPrompt"; echo "$prompt"`
fullPrompt=`echo "$fullPrompt" | sed '/^[[:blank:]]*$/d'`
inlineOpen=`echo $fullPrompt | grep -o '{\|#ifdef' | wc -l`
inlineClose=`echo $fullPrompt | grep -o '}\|#endif' | wc -l`
inlineCounter=$((inlineOpen-inlineClose))
if [[ $inlineOpen -gt $inlineClose ]];then
:
else
addOutsideMain=false
addToBeginning=false
addSemicolon=";"
# If include statement
[[ $prompt == "#include "* ]] && addToBeginning=true && addSemicolon=""
# If definition
[[ $prompt == "#define "* ]] && addOutsideMain=true && addSemicolon=""
# If ifdef/elif/else/endif
[[ $prompt == "#ifdef"* || $prompt == "#elif"* || $prompt == "#else" || $prompt == "#endif" ]] && addToBeginning=true && addSemicolon=""
# If function declaration
[[ $fullPrompt =~ ^.?[[:alnum:]\*:]+[[:blank:]]*[[:alnum:]\*:]*[[:blank:]]*[[:alnum:]\*:]*[[:blank:]]*[[:alnum:]:]+\(.*\)[[:blank:]]*.*\{ ]] && addOutsideMain=true && addSemicolon=""
# If namespace/class/struct declaration
[[ $fullPrompt =~ ^.?[[:alnum:]\*:]*[[:blank:]]*(namespace|class|struct)[[:blank:]]*[[:alnum:]\*:]*[[:blank:]]*.*\{ ]] && addOutsideMain=true
# If if/else if/else/switch/while/do while/for/try/catch
[[ $fullPrompt =~ ^.?[[:blank:]]*(if|else if|else|switch|while|do|for|try|catch).*\{ ]] && addOutsideMain=false && addToBeginning=false && addSemicolon=""
[[ $fullPrompt == *";" ]] && addSemicolon=""
if $addToBeginning;then
echo "$fullPrompt"$addSemicolon > $sourceFile.tmp
echo "`cat $sourceFile`" >> $sourceFile.tmp
elif $addOutsideMain;then
fullPrompt=`printf "%s" "$fullPrompt" | sed -e 's/[&\\]/\\\&/g'`
fullPrompt=`echo $fullPrompt`
sed "/^int main() {/i$fullPrompt$addSemicolon" $sourceFile > $sourceFile.tmp
else
cp $sourceFile $sourceFile.tmp
echo "$fullPrompt$addSemicolon" >> $sourceFile.tmp
fi
fullPrompt=""
compiledSuccessfully=false
$compiler -w -x$lang <(echo "`cat $sourceFile.tmp`}") -o $binaryFile && compiledSuccessfully=true
if $compiledSuccessfully;then
retval=`./$binaryFile 2>&1`
[[ $retval == "" ]] && mv $sourceFile.tmp $sourceFile || echo "$retval"
fi
fi
done
history -a "$historyFile"
rm $sourceFile* &> /dev/null
rm $binaryFile &> /dev/null