Some improvements in bash configuration importer script

This commit is contained in:
Siteshwar Vashisht 2012-06-10 16:55:25 +05:30
parent 631d27f7a8
commit 602109bd8d
2 changed files with 421 additions and 226 deletions

195
share/tools/bash_converter.py Executable file
View File

@ -0,0 +1,195 @@
#!/usr/bin/env python
IN_WORD, IN_SINGLE_QUOTES, IN_DOUBLE_QUOTES = 0, 1, 2
global IN_BACKTICK
IN_BACKTICK = False
#Find outside quotes
def contains_outside_quotes(input, ch):
in_quotes = False
i = 0
while i < len(input):
if input[i] == ch and in_quotes == False:
return True
elif input[i] == '\\' and in_quotes == True:
i = i+1
elif input[i] == '"':
in_quotes = not in_quotes
elif input[i] == "'" and not in_quotes:
i = i + 1
while input[i] != "'":
i = i + 1
i = i + 1
return False
#Replace characters outside double quotes
def replace_outside_quotes(input, oldchar, newchar, change_all = True):
in_quotes = False
newstr = []
i = 0
while i < len(input):
if input[i] == oldchar and in_quotes == False:
newstr.append(newchar)
i = i+1
if change_all == True:
continue
else:
while i < len(input):
newstr.append(input[i])
i = i + 1
#Break loop and return all the characters in list by joining them
break
elif input[i] == '\\' and in_quotes == True:
newstr.append(input[i])
i = i+1
elif input[i] == '"':
in_quotes=not in_quotes
elif input[i] == "'" and not in_quotes:
newstr.append(input[i])
i = i + 1
while input[i] != "'":
newstr.append(input[i])
i = i + 1
newstr.append(input[i])
i = i + 1
return ''.join(newstr)
def export_handler(tokens):
# print "Export Handler: ", tokens
if contains_outside_quotes(tokens[0], "="):
tokens[0] = replace_outside_quotes(tokens[0], "=", " ", False)
args = ' '.join(tokens)
return "set -gx " + args
global bash_builtins
bash_builtins = {
"export" : export_handler
}
def process_builtin(tokens):
builtin_name = tokens[0]
# print "Builtin name is: ", builtin_name
return (bash_builtins[builtin_name])(tokens[1:])
def process_command(tokens):
cmd = ' '.join(tokens)
return cmd
def parse_input(input, output_buff):
i = 0
state = IN_WORD
tokens = []
current_value = ""
while (i<len(input)):
if state == IN_WORD:
if input[i] == " ":
if len(current_value) > 0:
tokens.append(current_value)
current_value = ""
elif input[i] == "'":
state = IN_SINGLE_QUOTES
current_value = current_value + input[i]
elif input[i] == '"':
state = IN_DOUBLE_QUOTES
current_value = current_value + input[i]
elif input[i] == "`":
global IN_BACKTICK
if IN_BACKTICK == True:
current_value = current_value + ")"
else:
current_value = current_value + "("
IN_BACKTICK = not IN_BACKTICK
elif input[i] == ";":
if len(current_value) > 0:
tokens.append(current_value)
# print tokens
if contains_outside_quotes(tokens[0], "="):
tokens[0] = replace_outside_quotes(tokens[0], "=", " ", False)
args = ' '.join(tokens)
output_buff += "\n\tset " + args
elif tokens[0] in bash_builtins.keys():
output_buff += "\n\t" + process_builtin(tokens)
else:
output_buff += "\n\t" + process_command(tokens)
current_value = ""
del tokens[:]
elif input[i] == "&":
if input[i+1] == "&":
current_value = current_value + "and"
i = i + 1
else:
current_value = current_value + input[i]
elif input[i] == "{":
value_len = len(current_value)
if (value_len > 0 and current_value[value_len - 1] == "$"):
current_value = current_value[:value_len - 1]
current_value = current_value + "{"
current_value = current_value + "$"
else:
current_value = current_value + input[i]
elif state == IN_DOUBLE_QUOTES:
current_value = current_value + input[i]
# print current_value
if input[i] == '"':
state = IN_WORD
tokens.append(current_value)
current_value = ""
#Let's ignore escaped characters
elif input[i] == "\\":
# print "In backslash"
i = i + 1
current_value = current_value + input[i]
elif state == IN_SINGLE_QUOTES:
current_value = current_value + input[i]
if input[i] == "'":
state = IN_WORD
tokens.append(current_value)
current_value = ""
i = i + 1
if len(current_value) > 0:
tokens.append(current_value)
# print tokens
if contains_outside_quotes(tokens[0], "="):
tokens[0] = replace_outside_quotes(tokens[0], "=", " ", False)
args = ' '.join(tokens)
output_buff += "\n\tset " + args
elif tokens[0] in bash_builtins.keys():
output_buff += "\n\t" + process_builtin(tokens)
else:
output_buff += "\n\t" + process_command(tokens)
return output_buff
if __name__ == "__main__":
import sys
data = sys.stdin.read()
# data = 'echo "This is a message\\"'
# data = "export a=b; export c=d; `echo 'HI'`; a=b; echo ${abc} "
parse_input(data)

View File

@ -16,7 +16,10 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
import os, sys, re
import bash_converter
config_file = None
output_buff = ""
prompt_buff = ""
i = 0
quote_started = False
@ -24,276 +27,273 @@ bash_builtins = ["export"]
#Remove leading and trailing single quotes from a string
def remove_single_quotes(input):
start = 0
end = len(input)
if input[0] == "'":
start = 1
if input[end-1] == "'":
end = end - 1
return input[start:end]
start = 0
end = len(input)
if input[0] == "'":
start = 1
if input[end-1] == "'":
end = end - 1
return input[start:end]
#Find outside quotes
def contains_outside_quotes(input, ch):
in_quotes = False
in_quotes = False
i = 0
while i < len(input):
if input[i] == ch and in_quotes == False:
return True
elif input[i] == '\\' and in_quotes == True:
i = i+1
elif input[i] == '"':
in_quotes = not in_quotes
elif input[i] == "'" and not in_quotes:
i = i + 1
while input[i] != "'":
i = i + 1
i = 0
while i < len(input):
if input[i] == ch and in_quotes == False:
return True
elif input[i] == '\\' and in_quotes == True:
i = i+1
elif input[i] == '"':
in_quotes = not in_quotes
elif input[i] == "'" and not in_quotes:
i = i + 1
while input[i] != "'":
i = i + 1
i = i + 1
i = i + 1
return False
return False
#Replace characters outside double quotes
def replace_outside_quotes(input, oldchar, newchar, change_all = True):
in_quotes = False
newstr = []
in_quotes = False
newstr = []
i = 0
while i < len(input):
if input[i] == oldchar and in_quotes == False:
newstr.append(newchar)
i = i+1
i = 0
while i < len(input):
if input[i] == oldchar and in_quotes == False:
newstr.append(newchar)
i = i+1
if change_all == True:
continue
else:
while i < len(input):
newstr.append(input[i])
i = i + 1
#Break loop and return all the characters in list by joining them
break
elif input[i] == '\\' and in_quotes == True:
newstr.append(input[i])
i = i+1
elif input[i] == '"':
in_quotes=not in_quotes
elif input[i] == "'" and not in_quotes:
newstr.append(input[i])
i = i + 1
while input[i] != "'":
newstr.append(input[i])
i = i + 1
if change_all == True:
continue
else:
while i < len(input):
newstr.append(input[i])
i = i + 1
#Break loop and return all the characters in list by joining them
break
elif input[i] == '\\' and in_quotes == True:
newstr.append(input[i])
i = i+1
elif input[i] == '"':
in_quotes=not in_quotes
elif input[i] == "'" and not in_quotes:
newstr.append(input[i])
i = i + 1
while input[i] != "'":
newstr.append(input[i])
i = i + 1
newstr.append(input[i])
i = i + 1
newstr.append(input[i])
i = i + 1
return ''.join(newstr)
return ''.join(newstr)
#Parse input passed to the script
def parse_input(input):
env_regex = re.compile("(.*?)=(.*)")
env_regex_matched = re.search(env_regex, input)
global output_buff
env_regex = re.compile("(.*?)=(.*)")
env_regex_matched = re.search(env_regex, input)
while env_regex_matched != None:
env_name = env_regex_matched.group(1)
env_value = env_regex_matched.group(2)
env_var = env_regex_matched.group(0)
while env_regex_matched != None:
env_name = env_regex_matched.group(1)
env_value = env_regex_matched.group(2)
env_var = env_regex_matched.group(0)
if env_name[:5] == "alias":
add_alias(env_name[6:], env_value)
elif env_name == "PS1":
parse_bash_prompt(env_value)
elif env_name == "PATH":
config_file.write("set -x " + env_name + ' ' + env_value.replace(":"," ") )
else:
config_file.write("set_default " + env_name + ' "' + env_value + '"')
#Move to next line
config_file.write("\n")
input = input[env_regex_matched.end():]
env_regex_matched = re.search(env_regex, input)
if env_name[:5] == "alias":
add_alias(env_name[6:], env_value)
input = input[env_regex_matched.end():]
elif env_name == "PS1":
if len(env_value) > 0:
parse_bash_prompt(env_value)
input = input[env_regex_matched.end():]
elif env_name == "PATH":
output_buff += "set -x " + env_name + ' ' + env_value.replace(":"," ")
input = input[env_regex_matched.end():]
else:
full_value = env_value
input = input[env_regex_matched.end():]
while len(env_value) > 0 and env_value[len(env_value)-1] == "\\":
one_line_regex = re.compile("\n.*")
one_line_matched = re.search(one_line_regex, input)
env_value = one_line_matched.group(0)
full_value = full_value + env_value
input = input[one_line_matched.end():]
output_buff += "set_default " + env_name + ' "' + full_value + '"'
#Move to next line
output_buff += "\n"
config_file.write(output_buff)
output_buff = ""
env_regex_matched = re.search(env_regex, input)
#Add an alias as a function in fish
def add_alias(alias_name, alias_value):
alias_value = remove_single_quotes(alias_value)
global output_buff
alias_value = remove_single_quotes(alias_value)
while contains_outside_quotes(alias_value,"`"):
alias_value = replace_outside_quotes(alias_value, '`', '(', False)
alias_value = replace_outside_quotes(alias_value, '`', ')', False)
config_file.write("function " + alias_name)
for line in alias_value.split(";"):
line = line.strip()
tokens = line.split(' ')
first_token = tokens[0].strip()
if first_token in bash_builtins:
sys.stderr.write("{0} is a bash builtin".format(first_token, ))
if first_token == "export":
var_regex = re.compile("(.*?)=(.*)")
var_regex_matched = re.search(var_regex, line[7:])
if var_regex_matched != None:
stripped_name = var_regex_matched.group(1).strip()
config_file.write("\n\tset -gx " + var_regex_matched.group(1).strip() + " " + var_regex_matched.group(2).strip())
else:
export_name = line[6:].strip()
config_file.write("\n\tset -gx " + export_name + " $" + export_name )
elif "=" in first_token:
var_regex = re.compile("(.*?)=(.*)")
var_regex_matched = re.search(var_regex, line)
if var_regex_matched != None:
stripped_name = var_regex_matched.group(1).strip()
config_file.write("\n\tset " + var_regex_matched.group(1).strip() + " " + var_regex_matched.group(2).strip() )
else:
if len(line.strip()) > 0:
config_file.write( "\n\t" + line.strip() )
config_file.write(" $argv\nend;\n")
output_buff += "function " + alias_name
output_buff = bash_converter.parse_input(alias_value, output_buff)
output_buff += " $argv\nend;\n"
def parse_control_sequence():
ch = next_prompt_char()
ch2 = None
while (ch != ""):
if ch == "\\":
ch2 = next_prompt_char()
if (ch2 == "]"):
return
ch = next_prompt_char()
ch = next_prompt_char()
ch2 = None
while (ch != ""):
if ch == "\\":
ch2 = next_prompt_char()
if (ch2 == "]"):
return
ch = next_prompt_char()
def is_digit(ch):
if ch>='0' and ch<='9':
return True
return False
if ch>='0' and ch<='9':
return True
return False
def set_prompt_buff(value):
global i, buff
i = 0
buff = value
global i, buff
i = 0
buff = value
def next_prompt_char():
global i, buff
if (i < len(buff)):
next = buff[i]
i = i+1
else:
next = ""
return next
global i, buff
if (i < len(buff)):
next = buff[i]
i = i+1
else:
next = ""
return next
def unget_prompt_char():
global i
i = i - 1
global i
i = i - 1
def add_to_echo(str, is_special=True):
global quote_started
if (is_special == True):
if (quote_started == True):
config_file.write('"')
quote_started = False
else:
if (quote_started == False):
config_file.write('"')
quote_started = True
global quote_started
if (is_special == True):
if (quote_started == True):
config_file.write('"')
quote_started = False
else:
if (quote_started == False):
config_file.write('"')
quote_started = True
config_file.write(str)
config_file.write(str)
def check_end_quote():
global quote_started
global quote_started
if quote_started == True:
config_file.write('"')
if quote_started == True:
# print "Ending quote",
config_file.write('"')
def parse_bash_prompt(bash_prompt):
set_prompt_buff(bash_prompt)
config_file.write("function fish_prompt\n")
set_prompt_buff(bash_prompt)
if ("\\$" in bash_prompt):
config_file.write("\tif test (id -u) -eq \"0\"\n")
config_file.write("\t\tset uid_prompt \"#\"\n")
config_file.write("\telse\n")
config_file.write("\t\tset uid_prompt \"\\$\"\n")
config_file.write("\tend;\n")
config_file.write("function fish_prompt\n")
config_file.write('\techo -n ')
if ("\\$" in bash_prompt):
config_file.write("\tif test (id -u) -eq \"0\"\n")
config_file.write("\t\tset uid_prompt \"#\"\n")
config_file.write("\telse\n")
config_file.write("\t\tset uid_prompt \"\\$\"\n")
config_file.write("\tend;\n")
ch = next_prompt_char()
ch2 = None
while (ch != ""):
if ( ch == "\\"):
ch2 = next_prompt_char()
if (ch2 == ""):
continue
elif (ch2 == "a"):
add_to_echo('\\a')
elif (ch2 == "d"):
add_to_echo('(date +"%a %b %d")')
elif (ch2 == "e"):
sys.std.out.write('\e')
elif (ch2 == "h"):
add_to_echo("(hostname | cut -d\".\" -f1)")
elif (ch2 == "H"):
add_to_echo("(hostname)")
elif (ch2 == "j"):
add_to_echo("(jobs | wc -l)")
elif (ch2 == "l"):
add_to_echo("basename (tty)")
elif (ch2 == "n"):
add_to_echo(' \\n ')
elif (ch2 == "r"):
add_to_echo(' \\r ')
elif (ch2 == "s"):
add_to_echo("fish", False)
elif (ch2 == "t"):
add_to_echo('(date +"%H:%M:%S")')
elif (ch2 == "T"):
add_to_echo('(date +"%I:%M:%S")')
elif (ch2 == "@"):
add_to_echo('(date +"%I:%M %p")')
elif (ch2 == "u"):
add_to_echo("$USER")
elif (ch2 == "w"):
add_to_echo("(pwd)")
elif (ch2 == "W"):
add_to_echo("(basename ( pwd ) )")
elif (ch2 == "$"):
add_to_echo(" $uid_prompt ")
elif (is_digit(ch2)):
temp = int(ch2)
ch = next_prompt_char()
if (is_digit(ch)):
temp = (temp*8) + int(ch)
else:
add_to_echo(chr(temp), False)
unget_prompt_char()
ch = next_prompt_char()
if (is_digit(ch)):
temp = ((temp/10)*64) + ((temp%10)*8) + int(ch)
add_to_echo(chr(temp), False)
else:
add_to_echo(chr(temp), False)
unget_prompt_char()
elif (ch2 == "\\"):
add_to_echo("\\")
elif (ch2 == "["):
parse_control_sequence()
elif (ch2 == "]"):
print("Unexpected ]")
elif (ch2 == "v" or ch2 == "V"):
add_to_echo("(fish -v 2>| cut -d\" \" -f3)")
else:
print("Unknown escape character")
else:
add_to_echo(ch,False)
ch = next_prompt_char()
check_end_quote()
config_file.write("\nend\n")
config_file.write('\techo -n ')
ch = next_prompt_char()
ch2 = None
while (ch != ""):
if ( ch == "\\"):
ch2 = next_prompt_char()
if (ch2 == ""):
continue
elif (ch2 == "a"):
add_to_echo('\\a')
elif (ch2 == "d"):
add_to_echo(' (date +"%a %b %d")')
elif (ch2 == "e"):
add_to_echo('\e')
elif (ch2 == "h"):
add_to_echo("(hostname | cut -d\".\" -f1)")
elif (ch2 == "H"):
add_to_echo("(hostname)")
elif (ch2 == "j"):
add_to_echo("(jobs | wc -l)")
elif (ch2 == "l"):
add_to_echo("basename (tty)")
elif (ch2 == "n"):
add_to_echo(' \\n ')
elif (ch2 == "r"):
add_to_echo(' \\r ')
elif (ch2 == "s"):
add_to_echo("fish", False)
elif (ch2 == "t"):
add_to_echo('(date +"%H:%M:%S")')
elif (ch2 == "T"):
add_to_echo('(date +"%I:%M:%S")')
elif (ch2 == "@"):
add_to_echo('(date +"%I:%M %p")')
elif (ch2 == "u"):
add_to_echo("$USER")
elif (ch2 == "w"):
add_to_echo("(pwd)")
elif (ch2 == "W"):
add_to_echo("(basename ( pwd ) )")
elif (ch2 == "$"):
add_to_echo("$uid_prompt ")
elif (is_digit(ch2)):
temp = int(ch2)
ch = next_prompt_char()
if (is_digit(ch)):
temp = (temp*8) + int(ch)
else:
add_to_echo(chr(temp), False)
unget_prompt_char()
ch = next_prompt_char()
if (is_digit(ch)):
temp = ((temp/10)*64) + ((temp%10)*8) + int(ch)
add_to_echo(chr(temp), False)
else:
add_to_echo(chr(temp), False)
unget_prompt_char()
elif (ch2 == "\\"):
add_to_echo("\\")
elif (ch2 == "["):
parse_control_sequence()
elif (ch2 == "]"):
# print "Unexpected ]"
pass
elif (ch2 == "v" or ch2 == "V"):
add_to_echo("(fish -v 2>| cut -d\" \" -f3)")
else:
# print "Unknown escape character"
pass
else:
if (ch == "$"):
add_to_echo("\\", False)
add_to_echo(ch,False)
ch = next_prompt_char()
check_end_quote()
config_file.write("\nend\n")
if __name__ == "__main__":
input = sys.stdin.read()
config_file = open("{0}/.config/fish/bash_config.fish".format(os.environ["HOME"]),"a")
parse_input(input)
input = sys.stdin.read()
config_file = open("{0}/.config/fish/bash_config.fish".format(os.environ["HOME"]),"a")
parse_input(input)