zoukankan      html  css  js  c++  java
  • Make Notepad++ auto close HTML/XML tags after the slash(the Dreamweaver way)

    I've been looking for a Notepad++ plugin that can close HTML/XML tags after a slash just like the way Dreamweaver does for a long time.
    The only things I could find(TextFX, XML Tools etc.) close the tags right after ">" is typed in, which was not what I wanted.
    A couple days ago I found a plugin called Automation Scripts. It allows me to write scripts in C#, so I don't have to spend time learning how to write Notepad++ plugins.
    So here you go:

    //npp_shortcut Ctrl+Shift+Z
    
    //Automation Scripts plugin needs to be installed for this to work
    using System.Collections.Generic;
    using System.Text.RegularExpressions;
    using System.Text;
    using System;
    using System.Windows.Forms;
    using NppScripts;
    
    public class Script : NppScript
    {
        public Script()
        {
            this.OnNotification = (notification) =>
            {
                if(notification.nmhdr.code == (uint)SciMsg.SCN_CHARADDED)
                {
                    doInsertHtmlCloseTag((char)notification.ch);
                }
            };
        }
    
        public override void Run()
        {
            checkInsertHtmlCloseTag();
        }
    
        bool doCloseTag;
    
        void checkInsertHtmlCloseTag()
        {
            doCloseTag = !doCloseTag;
            Win32.SendMessage(Npp.NppHandle, NppMsg.NPPM_SETMENUITEMCHECK, Plugin.FuncItems.Items[this.ScriptId]._cmdID, doCloseTag ? 1 : 0);
        }
    
        string GetStartTagName(string input)
        {
            Regex regex=new Regex(@"<[A-Za-z][A-Za-z0-9]*[^>]*[^/]>|<[A-Za-z]>");
            if(!regex.IsMatch(input)) return "";
            StringBuilder result=new StringBuilder();
            int i=1;
            while(input[i]!=' ' && input[i]!='>' & i<input.Length)
            {
                result.Append(input[i]);
                i++;
            }
            return result.ToString();
        }
    
        string GetEndTagName(string input)
        {
            Regex regex=new Regex(@"</[A-Za-z][A-Za-z0-9]*[^>]*>");
            if(!regex.IsMatch(input)) return "";
            StringBuilder result=new StringBuilder();
            int i=2;
            while(input[i]!=' ' && input[i]!='>' & i<input.Length)
            {
                result.Append(input[i]);
                i++;
            }
            return result.ToString();
        }
        
        string GetSelection()
        {
            IntPtr hCurrentEditView = Npp.CurrentScintilla;
            StringBuilder result=new StringBuilder();
            Win32.SendMessage(hCurrentEditView,SciMsg.SCI_GETSELTEXT,0,result);
            return result.ToString();
        }
        
        int FindNextTag(int pos)
        {
            IntPtr hCurrentEditView = Npp.CurrentScintilla;
            string pattern=@"</?[A-Za-z][A-Za-z0-9]*[^>]*[^/]>|</?[A-Za-z]>";
            Win32.SendMessage(hCurrentEditView, SciMsg.SCI_SETSEL, pos, pos);
            Win32.SendMessage(hCurrentEditView,SciMsg.SCI_SEARCHANCHOR,0,0);
            return (int)Win32.SendMessage(hCurrentEditView,SciMsg.SCI_SEARCHPREV,(int)SciMsg.SCFIND_REGEXP,pattern);
        }
        
        void doInsertHtmlCloseTag(char newChar)
        {
            LangType docType = LangType.L_TEXT;
            Win32.SendMessage(Npp.NppHandle, NppMsg.NPPM_GETCURRENTLANGTYPE, 0, ref docType);
            bool isDocTypeHTML = (docType == LangType.L_HTML || docType == LangType.L_XML || docType == LangType.L_PHP);
            if (doCloseTag && isDocTypeHTML && newChar=='/')
            {
                IntPtr hCurrentEditView = Npp.CurrentScintilla;
                int currentPos = (int)Win32.SendMessage(hCurrentEditView, SciMsg.SCI_GETCURRENTPOS, 0, 0);
                char lastChar=(char)Win32.SendMessage(hCurrentEditView,SciMsg.SCI_GETCHARAT,currentPos-2,0);
                StringBuilder insertString=new StringBuilder();
                if(lastChar=='<')
                {
                    int pos=currentPos;
                    Stack<string> stack=new Stack<string>();
                    string tag;
                    while(true)
                    {
                        pos=FindNextTag(pos);
                        if(pos==-1)
                        {
                            Win32.SendMessage(hCurrentEditView, SciMsg.SCI_SETSEL, currentPos, currentPos);
                            return;
                        }
                        tag=GetSelection();
                        if(tag[1]=='/')
                        {
                            stack.Push(GetEndTagName(tag));
                        }
                        else
                        {
                            tag=GetStartTagName(tag);
                            if(stack.Count==0) 
                                break;
                            else
                            {
                                string endTag=stack.Pop();
                                while(tag!=endTag && stack.Count>0)
                                {
                                    endTag=stack.Pop();
                                }
                                if(tag!=endTag) break;
                            }
                        }
                    }
                    insertString.Append(tag+">");
                    Win32.SendMessage(hCurrentEditView, SciMsg.SCI_BEGINUNDOACTION, 0, 0);
                    Win32.SendMessage(hCurrentEditView, SciMsg.SCI_SETSEL, currentPos, currentPos);
                    Win32.SendMessage(hCurrentEditView, SciMsg.SCI_REPLACESEL, 0, insertString);
                    Win32.SendMessage(hCurrentEditView, SciMsg.SCI_SETSEL, currentPos+insertString.Length, currentPos+insertString.Length);
                    Win32.SendMessage(hCurrentEditView, SciMsg.SCI_ENDUNDOACTION, 0, 0);
                }
            }
        }
    }
  • 相关阅读:
    VMware NAT 静态IP模式下上网
    无法连接虚拟设备 ide1:0
    C# ContainsKey与TryGetValue方法探究
    深入讲解以太坊的数据存储
    sqlserver之查询数据插入新建表@已存在表(oracle)
    python之列表、元祖、字典和数组的使用
    python之列表、元组、字典、数组对比
    python之ConfigParser介绍
    从业人员证券交易行为合规管理测试
    window系统自动设置时间同步脚本
  • 原文地址:https://www.cnblogs.com/amonw/p/5503844.html
Copyright © 2011-2022 走看看