using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
namespace jsCodeFormater
{
/// <summary>
/// 代码格式化工具 V 0.1
/// Author:hcmfys@163.com 小光棍
/// 2008-11-11 光棍节
/// 还有错误
/// </summary>
public class CodeFormater
{
private Hashtable _choiceElement;
private Hashtable _singleEyeElement;
private Hashtable _quotation;
private Hashtable _function;
private Hashtable _blockElement;
private int _tabNum = 0;
private string _wordDelimiters = " ,.?!;:\\/<>(){}[]\"'\r\n\t=+-|*%@#$^&";
private bool _deleteComment = false;
//是否大小写敏感
private bool _caseSensitive = true;
//本行括号内分号不做换行
private string _isFor = "for";
private string _beginBlock = "{";
private string _endBlock = "}";
//得到分割字符
//引用字符
//行注释字符
private string _lineComment = "//";
//转义字符
private string _escape = "\\";
//多行引用开始
private string _commentOn = "/*";
//多行引用结束
private string _commentOff = "*/";
//行结束词
private string _rowEnd = ";";
private string _in = "in";
private bool isCompress = false;
private int style = 0;
private bool quote_opened = false; //引用标记
private bool slash_slash_comment_opened = false; //单行注释标记
private int line_num = 1; //行号
private string quote_char = ""; //引用标记类型
private bool slash_star_comment_opened = false;
private string _ignore = "";
public string CodeFormat(string code)
{
bool bracket_open = false;
bool for_open = false;
bool function_opened = false;
//可以后面加块语句的关键字
this._blockElement = this.str2hashtable("switch,if,while,try,finally");
//是函数申明
this._function = this.str2hashtable("function");
this._choiceElement = this.str2hashtable("else,catch");
this._singleEyeElement = this.str2hashtable("var,new,return,else,delete,in,case");
this._quotation = this.str2hashtable("\",'");
ArrayList codeArr = new ArrayList();
int word_index = 0;
StringBuilder htmlTxt = new StringBuilder();
if (this.isCompress)
{
this._deleteComment = true;
}
// codeArr.Capacity = code.Length;
//得到分割字符数组(分词)
for (int i = 0; i < code.Length; i++)
{
if (this._wordDelimiters.ToString().IndexOf(code.Substring(i, 1)) == -1)
{ //找不到关键字
if (word_index == 0 || codeArr[word_index] == null)
{
// codeArr[word_index] = "";
codeArr.Add("");
}
codeArr.Add("");
codeArr[word_index] += code.Substring(i, 1);
}
else
{
if (!string.IsNullOrEmpty(codeArr[word_index] + "") && codeArr[word_index].ToString().Length > 0)
{
word_index++;
codeArr.Add("");
}
codeArr[word_index++] = code.Substring(i, 1);
// codeArr.Add(code.Substring(i, 1));
}
}
//按分割字,分块显示
for (int i = 0; i < word_index; i++)
{
//处理空行(由于转义带来)
if (string.IsNullOrEmpty(codeArr[i] + "") || codeArr[i].ToString().Length == 0)
{
continue;
}
else if (codeArr[i].ToString() == " " || codeArr[i].ToString() == "\t")
{
if (slash_slash_comment_opened || slash_star_comment_opened)
{
if (!this._deleteComment)
{
htmlTxt.Append(codeArr[i]);
}
}
if (quote_opened)
{
htmlTxt.Append(codeArr[i]);
}
}
else if (codeArr[i].ToString() == "\n")
{
//处理换行
}
else if (codeArr[i].ToString() == "\r")
{
slash_slash_comment_opened = false;
quote_opened = false;
line_num++;
if (!this.isCompress)
{
htmlTxt.Append("\r\n" + this.getIdent());
}
//处理function里的参数标记
}
else if (!slash_slash_comment_opened && !slash_star_comment_opened && !quote_opened && isFunction(codeArr[i].ToString()))
{
htmlTxt.Append(codeArr[i]);
function_opened = true;
}
else if (!slash_slash_comment_opened && !slash_star_comment_opened && !quote_opened && codeArr[i].ToString() == this._isFor)
{
htmlTxt.Append(codeArr[i]);
for_open = true;
}
else if (!slash_slash_comment_opened && !slash_star_comment_opened && !quote_opened && codeArr[i].ToString() == "(")
{
bracket_open = true;
htmlTxt.Append(codeArr[i]);
}
else if (!slash_slash_comment_opened && !slash_star_comment_opened && !quote_opened && codeArr[i].ToString() == ")")
{
bracket_open = false;
htmlTxt.Append(codeArr[i]);
}
else if (!slash_slash_comment_opened && !slash_star_comment_opened && !quote_opened && codeArr[i].ToString() == this._rowEnd)
{
if (!this.isCompress)
{
if (!for_open)
{
if (i < word_index && (codeArr[i + 1].ToString() != "\r" && codeArr[i + 1].ToString() != "\n"))
{
htmlTxt.Append(codeArr[i] + "\n" + this.getIdent());
}
else
{
htmlTxt.Append(codeArr[i] + this.getIdent());
}
}
else
{
htmlTxt.Append(codeArr[i]);
}
}
else
{
htmlTxt.Append(codeArr[i]);
}
}
else if (!slash_slash_comment_opened && !slash_star_comment_opened && !quote_opened && codeArr[i].ToString() == this._beginBlock)
{
for_open = false;
if (!this.isCompress)
{
switch (this.style)
{
case 0:
this._tabNum++;
htmlTxt.Append(codeArr[i] + "\n" + this.getIdent());
break;
case 1:
htmlTxt.Append("\n" + this.getIdent());
this._tabNum++;
htmlTxt.Append(codeArr[i] + "\n" + this.getIdent());
break;
default:
this._tabNum++;
htmlTxt.Append(codeArr[i]);
break;
}
}
else
{
htmlTxt.Append(codeArr[i]);
}
}
else if (!slash_slash_comment_opened && !slash_star_comment_opened && !quote_opened && codeArr[i].ToString() == this._endBlock)
{
if (!this.isCompress)
{
this._tabNum--;
if (i < word_index && codeArr[i + 1].ToString() != this._rowEnd)
{
htmlTxt.Append("\n" + this.getIdent() + codeArr[i]);
}
else
{
htmlTxt.Append("\n" + this.getIdent() + codeArr[i]);
}
}
else
{
if (i < word_index && codeArr[i + 1].ToString() != this._rowEnd)
{
htmlTxt.Append(codeArr[i] + this._rowEnd);
}
else
{
htmlTxt.Append(codeArr[i]);
}
}
//处理关键字
}
else if (!slash_slash_comment_opened && !slash_star_comment_opened && !quote_opened && isBlockElement(codeArr[i].ToString()))
{
htmlTxt.Append(codeArr[i]);
//处理内置对象(后面加一个空格)
}
else if (!slash_slash_comment_opened && !slash_star_comment_opened && !quote_opened && isSingleEyeElement(codeArr[i].ToString()))
{
if (codeArr[i].ToString() == this._in)
{
htmlTxt.Append(" ");
}
htmlTxt.Append(codeArr[i] + " ");
//处理双引号(引号前不能为转义字符)
}
else if (!slash_star_comment_opened && !slash_slash_comment_opened && _quotation.Contains(codeArr[i]))
{
if (quote_opened)
{
//是相应的引号
if (quote_char == codeArr[i].ToString())
{
htmlTxt.Append(codeArr[i]);
quote_opened = false;
quote_char = "";
}
else
{
htmlTxt.Append(codeArr[i]);
}
}
else
{
htmlTxt.Append(codeArr[i]);
quote_opened = true;
quote_char = codeArr[i] + "";
}
//处理转义字符
}
else if (codeArr[i].ToString() == this._escape)
{
htmlTxt.Append(codeArr[i]);
if (i < word_index - 1)
{
if (char.Parse(codeArr[i + 1].ToString().Trim()) >= 32 && char.Parse(codeArr[i + 1].ToString().Trim()) <= 127)
{
htmlTxt.Append(codeArr[i + 1].ToString().Substring(0, 1));
htmlTxt.Append(codeArr[i + 1].ToString().Substring(0, 1));
i = i + 1;
}
}
//处理多行注释的开始
}
else if (!slash_slash_comment_opened && !slash_star_comment_opened && !quote_opened &&
isStartWith(_commentOn, codeArr, i))
{
slash_star_comment_opened = true;
if (!this._deleteComment)
{
htmlTxt.Append(this._commentOn);
}
i = i + this.getSkipLength(this._commentOn);
//处理单行注释
}
else if (!slash_slash_comment_opened && !slash_star_comment_opened && !
quote_opened && isStartWith(_lineComment, codeArr, i))
{
slash_slash_comment_opened = true;
if (!this._deleteComment)
{
htmlTxt.Append(this._lineComment);
}
i = i + this.getSkipLength(this._lineComment);
//处理忽略词
}
else if (!slash_slash_comment_opened && !slash_star_comment_opened && !quote_opened && isStartWith(this._ignore, codeArr, i))
{
slash_slash_comment_opened = true;
htmlTxt.Append(this._ignore);
i = i + this.getSkipLength(this._ignore);
//处理多行注释结束
}
else if (!quote_opened && !slash_slash_comment_opened && isStartWith(_commentOff, codeArr, i))
{
if (slash_star_comment_opened)
{
slash_star_comment_opened = false;
if (!this._deleteComment)
{
htmlTxt.Append(this._commentOff);
}
i = i + this.getSkipLength(this._commentOff);
}
}
else
{
//不是在字符串中
if (!quote_opened)
{
//如果不是在注释重
if (!slash_slash_comment_opened && !slash_star_comment_opened)
{
htmlTxt.Append(codeArr[i]);
//注释中
}
else
{
if (!this._deleteComment)
{
htmlTxt.Append(codeArr[i]);
}
}
}
else
{
htmlTxt.Append(codeArr[i]);
}
}
}
return htmlTxt.ToString();
}
private Hashtable str2hashtable(string str)
{
Hashtable ht = new Hashtable();
string[] strArray = str.Split(',');
foreach (string _str in strArray)
{
ht.Add(_str, _str);
}
return ht;
}
private bool isStartWith(string str, ArrayList code, int index)
{
if (!string.IsNullOrEmpty(str) && str.Length > 0)
{
StringBuilder cc = new StringBuilder();
for (int i = index; i < index + str.Length; i++)
{
cc.Append(code[i]);
}
string c = cc.ToString();
if (this._caseSensitive)
{
if (str.Length >= cc.Length && c.IndexOf(str) == 0)
{
return true;
}
}
else
{
if (str.Length >= cc.Length && c.ToLower().IndexOf(str.ToLower()) == 0)
{
return true;
}
}
return false;
}
else
{
return false;
}
}
private bool isFunction(string val)
{
return this._function.Contains((this._caseSensitive ? val : val.ToLower()));
}
private bool isBlockElement(string val)
{
return this._blockElement.Contains(this._caseSensitive ? val : val.ToLower());
}
private bool isChoiceElement(string val)
{
return this._choiceElement.Contains(this._caseSensitive ? val : val.ToLower());
}
private bool isSingleEyeElement(string val)
{
return this._singleEyeElement.Contains(this._caseSensitive ? val : val.ToLower());
}
private bool isNextElement(int from, string word)
{
for (int i = from; i < word.Length; i++)
{
if (word[i] != ' ' && word[i] != '\t' && word[i] != '\r' && word[i] != '\n')
{
return this.isChoiceElement(word[i] + "");
}
}
return false;
}
private int getSkipLength(string val)
{
int count = 0;
for (int i = 0; i < val.Length; i++)
{
if (this._wordDelimiters.IndexOf(val.Substring(i, 1)) >= 0)
{
count++;
}
}
if (count > 0)
{
count = count - 1;
}
return count;
}
private string getIdent()
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < this._tabNum; i++)
{
sb.Append("\t");
}
return sb.ToString();
}
}
}