首页 > 其他分享 >vim的verilog补全插件更新(支持变量名补全)

vim的verilog补全插件更新(支持变量名补全)

时间:2024-11-22 11:45:26浏览次数:3  
标签:插件 word 补全 module vim let letter endif line

本文是 vim使用的verilog补全插件(即插即用)_vim verilog插件-CSDN博客 的后续,请先阅读这篇文章后再查看

这篇文章更新了一些功能同时修复了插件的使用的bug

新增功能

1:支持变量名称补全,如果变量端口超过1提供中括号补全推荐

2: 简单的识别补全场景功能(比如assign 后面只推荐变量名补全,只会推荐模块内的变量名)

3:更正确的按键功能切换场景判断

和之前的文章一样,没什么时间写代码解释

直接上代码吧

用下面的代码代替上一篇中对应的文件内容

补全函数autocomplete.vim

let g:external_word_list = []
let g:external_module_list = []
let g:external_variable_list = []
let g:external_module_IO = {}


function! s:LoadWordsFromFile(filepath)"抓常用词的函数
    let g:external_word_list = []
    if !filereadable(a:filepath)
        echo "文件未找到:"  . a:filepath
        return
    endif
    let l:content = readfile(a:filepath)
    let l:words = []
    for l:line in l:content
        let l:words += filter(split(l:line, '[^a-zA-Z0-9$_]+'),'v:val != "" && v:val != " "')
    endfor
    let g:external_word_list = uniq(sort(l:words))
endfunction

function! LoadMoudlesFromFile()"抓模块的函数和变量
    silent! execute '!~/.vim/plugin/verilog_module ' . expand('%') . ' ' . line('.')
    silent! redraw!

    let g:external_module_list = []
    let g:external_module_IO = {}
    if !filereadable("./tmp")
        return
    endif
    let l:content = readfile("./tmp")
    let l:words = []
    for l:line in l:content
        if l:line !~ '[()]'
           call add(l:words,l:line)
        else 
            let line_tmp = ' ' . line
            let l:function_name = matchstr(l:line_tmp,'\v^([^\(]+)',1) 
            let l:line = substitute(l:line,'\v^[a-zA-Z$_0-9]+','','')
            let g:external_module_IO[l:function_name] = l:line
        endif
    endfor
    let g:external_module_list = uniq(sort(l:words))
    silent! execute '!rm tmp'

    let g:external_variable_list = []
    let l:content = readfile("./tmp_variable")
    let l:words = []
    for l:line in l:content
        let l:words += filter(split(l:line, '[^a-zA-Z0-9$_]+'),'v:val != "" && v:val != " "')
    endfor
    let g:external_variable_list = uniq(sort(l:words))
    silent! execute '!rm tmp_variable'
endfunction


function! s:AutoComplete(findstart, base)          "把模糊搜索的补全词语放入补全库的函数
    let first_word = matchstr(getline('.'),'\w\+') "行首词语,检测这里是否需要实例化模块
    if a:findstart == 1                            "模式1,用于返回光标所在字符第一个字母位置
        let l:start = col('.') - 1
        while l:start > 0 && getline('.')[l:start - 1] =~ '\k'
            let l:start -= 1
        endwhile
        return l:start
    else
        let l:matches = []
        let l:base = substitute(a:base, '\s\+', '', 'g') 
        let letter_count = {}
        let letter_count_in = LetterCount(l:base)
        
        if CheckWord(1)
            return l:matches
        endif

        for l:word in g:external_module_list      "优先加载模块,模块里除了变量,其他不进行补全
            let letter_count = LetterCount(l:word)
            if first_word == l:word
                let l:matches = []
                if IsCursorInParens()
                    for l:variable in g:external_variable_list
                        let variable_count = LetterCount(l:variable)
                        if CheckLetterCount(variable_count,letter_count_in) == 1 
                            call add(l:matches,l:variable)
                        endif
                    endfor
                    return l:matches
                endif
                call add(l:matches,l:base . g:external_module_IO[l:word])
                return l:matches
            endif
            if CheckLetterCount(letter_count,letter_count_in) == 1 
                call add(l:matches,l:word)
            endif
        endfor

        if CheckWord(0)
            let l:matches = []
        endif


        for l:variable in g:external_variable_list "加载变量,只包括光标所在模块的变量
            let variable_count = LetterCount(l:variable)
            if CheckLetterCount(variable_count,letter_count_in) == 1 
                call add(l:matches,l:variable)
            endif
        endfor

        if CheckWord(0)
            return l:matches
        endif

        for l:word in g:external_word_list "加载补全单词
            let letter_count = LetterCount(l:word)
            if CheckLetterCount(letter_count,letter_count_in) == 1 
                call add(l:matches,l:word)
            endif
        endfor
        return l:matches
    endif
endfunction

command! -nargs=1 LoadCompletionFile call s:LoadWordsFromFile(<f-args>)

function! TriggerAutoComplete(mode)"加入补全列表,还有判断是否需要调用补全函数(return 0就是不需要)
    let is_complete = 0
    let words = ""
    let l:matches = []
    if expand('%:e') != 'v'
        return 0
    "elseif getline('.')[col('.') - 2] !~ '\w' && getline('.')[col('.') - 3] !~ ')'&& getline('.')[col('.') - 2] !~ ']'
    elseif !pumvisible() && a:mode == 0
        return 0
    endif
    if col('.') > 1
        let l:line = getline('.')
        let l:col = col('.')
        let l:word_start = l:col - 1 
        while strcharpart(getline('.'),l:word_start - 1,1) =~ '\k' && l:word_start >= 0
            let l:word_start -= 1 
        endwhile 
        let words = matchstr(l:line, '\k\+', l:word_start)
        let l:matches = s:AutoComplete(0,words )
        let l:start = s:AutoComplete(1,words)
        if len(l:matches) > 0
            if a:mode == 1
                call complete(l:start+1,l:matches)
            endif
            return 1
        else 
            return 0 
        endif
    else
        return 0
    endif

endfunction

function! Verilogformat()
    silent! execute '!touch tmp_format;
                \verible-verilog-format %>tmp_format;
                \cat tmp_format>%;
                \rm tmp_format;'
    redraw!
endfunction




function! LetterCount(word)
  let letter_count = {}
  for i in range(len(a:word))
    let letter = a:word[i]
    if letter =~# '^[A-Z]$'
        let letter = tolower(letter)
    endif
    if has_key(letter_count, letter)
      let letter_count[letter] += 1
    else
      let letter_count[letter] = 1
    endif
  endfor
  return letter_count
endfunction

function! CheckLetterCount(arr1, arr2)
  for [letter, letter_count] in items(a:arr2)
    if !has_key(a:arr1, letter) || a:arr1[letter] < letter_count
      return 0
    endif
  endfor
  return 1
endfunction

function! CheckWord(mode)
    let first_word = matchstr(getline('.'),'\w\+') "行首词语
    let first_word_list_1 = ['input','output','inout','reg','wire']
    let first_word_list_2 = ['posedge','negedge']
    let l:pos = getcurpos()
    let l:search_pos = search('\w\+', 'bW')
    call search('\w\+','bW')
    let before_word = expand('<cword>')
    call setpos('.',l:pos)
    if a:mode == 1
        for l:word in first_word_list_1
            if first_word =~ l:word
                return 1
            endif
        endfor
        return 0
    elseif a:mode == 0
        for l:word in first_word_list_2
            if IsCursorInParens() && before_word =~ l:word || first_word =~ 'assign'
                return 1
            endif
        endfor

        return 0
    else 
        return 0
    endif
endfunction

function! IsCursorInParens()
  let line = getline('.')
  let col = col('.')
  let before_cursor = strpart(line, 0, col-1)
  let after_cursor = strpart(line, col-1)

  if match(before_cursor, '[({[]') != -1 && match(after_cursor, '[)}\]]') != -1
    return 1 " 光标在括号内
  else
    return 0 " 光标不在括号内
  endif
endfunction



augroup MyAutoGroup
  autocmd!
  autocmd TextChangedI *.v call MyAutoFunction()
augroup END

function! MyAutoFunction()
  let line = getline('.')
  let col = col('.')
  let char_before_cursor = strpart(line, col-2, 1)
  if char_before_cursor =~ '\w' || char_before_cursor == "\b"
      call TriggerAutoComplete(1)
  endif
endfunction

提取模块和变量的函数verilog_module

#!/bin/fish
set input_file $argv[1]
set line_number $argv[2]
cat $input_file > tmp
perl -0777 -ne ' 
    my $first = 1; 
    while (/module\s+(\S[\s\S]*?\))/g) { 
        my $module = $1; 

        if ($first) { 
            $first = 0; 
            next; 
        } 

        $module =~ s/input/./g; 
        $module =~ s/output/\@output\@/g; 
        $module =~ s/^module\s+//; 
        $module =~ s/\s//g; 
        $module =~ s/\)/()\);/g; 
        $module =~ s/,/(),/g; 
        print "$module
"; 
    } 
' tmp | sed 's/\@output\@/%/' > tmp2; 

perl -0777 -ne ' 
    s/output/./g; 
    s/%/ \/\*<-i | o->\*\/ ./g; 
    s/\@//g; 
    print $_; 
' tmp2 | sed -E "s/.(\[[0-9:]+\])([^\(]+)\(\)/.\2()\/\*\1\*\/ /g" > tmp
cat tmp2 | sed -E 's/^([A-Za-z_0-9$]+)\(.*/\1/g'>>tmp
rm tmp2

set target_line (sed -n "$line_number p" $input_file)
set start_line (sed -n "1,$line_number p" $input_file | tac | grep -m 1 -n 'module' | cut -d: -f1)
set end_line (sed -n "$line_number,\$ p" $input_file | grep -m 1 -n 'endmodule' | cut -d: -f1)

if test -n "$start_line" -a -n "$end_line"
    set start_line (math $line_number - $start_line + 1)
    set end_line (math $line_number + $end_line - 1)
    sed -n "$start_line,$end_line p" $input_file\
    | awk '/module/{flag=1;next} /endmodule/{flag=0} flag' \
    | grep -E 'input|output|reg|wire' | sed -E 's/(input|output|reg|wire)//g' \
    | sed -E 's/(\[.*\])//g' \
    | tr -s ';,[]' '\n' \
    | awk '{print $1}' \
    | sort | uniq -c \
    | awk '{print $2}'>tmp_variable

    sed -n "$start_line,$end_line p" $input_file\
    | awk '/module/{flag=1;next} /endmodule/{flag=0} flag' \
    | grep -E 'input|output|reg|wire' \
    | sed -E 's/(input|output|reg|wire)//g' \
    | sort | awk '{$1=$1}1' \
    | grep '\[' | sed -E 's/\[.*\]//g' \
    | sed -E 's/( )+//g' \
    | sed -E 's/([A-Za-z$0-9]+)/\1[:]/g' \
    | tr -s ',;' '\n'>>tmp_variable
else
cat $input_file \
    | awk '/module/{flag=1;next} /endmodule/{flag=0} flag' \
    | grep -E 'input|output|reg|wire' | sed -E 's/(input|output|reg|wire)//g' \
    | sed -E 's/(\[.*\])//g' \
    | tr -s ';,[]' '\n' \
    | awk '{print $1}' \
    | sort | uniq -c \
    | awk '{print $2}'>tmp_variable

cat $input_file \
     | awk '/module/{flag=1;next} /endmodule/{flag=0} flag' \
     | grep -E 'input|output|reg|wire' \
     | sed -E 's/(input|output|reg|wire)//g' \
     | sort | awk '{$1=$1}1' \
     | grep '\[' | sed -E 's/\[.*\]//g' \
     | sed -E 's/( )+//g' \
     | sed -E 's/([A-Za-z$0-9]+)/\1[:]/g' \
     | tr -s ',;' '\n'>>tmp_variable
end

其他内容不需要修改

至于autoinstall,在写了在写了(创建文件夹ing...)

标签:插件,word,补全,module,vim,let,letter,endif,line
From: https://blog.csdn.net/2401_83148007/article/details/143967620

相关文章

  • jQuery标签插件sTags
    在线预览 下载sTags是一款jQuery标签插件。该插件可以生成不同颜色的标签,可以对标签进行搜索过滤,添加和删除等。 使用方法在页面中引入jquery.sTags.css,jquery和jquery.sTags.js。<linkrel="stylesheet"href="jquery.sTags.css"><scriptsrc="jquery.min.js"><......
  • 视频流媒体播放器EasyPlayer.js无插件直播流媒体音视频播放器Android端webview全屏调
    流媒体播放器的核心技术与发展趋势正在不断推动着行业的变革。未来,随着技术的不断进步和应用场景的不断拓展,流媒体播放器将为用户带来更加便捷、高效、个性化的观看体验。同时,流媒体播放器也会成为数字娱乐产业的重要组成部分,为整个行业的繁荣发展贡献更多的力量。Android端webvi......
  • 可视化CSS3渐变背景颜色代码生成插件
    在线预览 特效下载 这是一款可以在线生成CSS3渐变背景颜色代码的可视化插件。你可以通过调节界面上给出的颜色、色相、饱和度和亮度滑块,以及渐变方向滑块来生成各种线性渐变,屏幕上会给出相应的CSS3线性渐变代码。该渐变背景颜色插件可以设置的选项有:BaseColor:Hue:色相......
  • 「Chromeg谷歌浏览器/Edge浏览器」篡改猴Tempermongkey插件的安装与使用
    1.谷歌浏览器安装及使用流程1.1准备篡改猴扩展程序包。    因为谷歌浏览器的扩展商城打不开,所以需要准备一个篡改猴压缩包。          其他浏览器只需打开扩展商城搜索篡改猴即可。    没有压缩包的可以进我主页下载。        也可......
  • VIM的下载使用与基本指令【入门级别操作】
    VIM——超级文本编辑器在当今时代,功能极其复杂的代码编辑器和集成开发环境(IDE)有很多。但如果只想要一个超轻量级的代码编辑器,用于Unix、C或其他语言/系统,而不需要那些华而不实的功能,该怎么办呢?这个时候,VIM就闪亮登场了!Vim的全称是ViIMproved(增强版Vi)。由BramMoo......
  • 鸿蒙开发Hvigor插件动态生成代码
    Hvigor允许开发者实现自己的插件,开发者可以定义自己的构建逻辑,并与他人共享。Hvigor主要提供了两种方式来实现插件:基于hvigorfile脚本开发插件、基于typescript项目开发。下面以基于hvigorfile脚本开发插件进行介绍。基于hvigorfile脚本开发基于hvigorfile.ts脚本开发的方式,其优......
  • H.264/H.265播放器EasyPlayer.js无插件H5播放器:关于国标GB28181 PTZ的指令操作摄像头
    近年来,流媒体播放器的发展趋势呈现出多元化和创新化的特点。一方面,流媒体消费呈现出向大屏迁移的趋势,智能电视等大屏设备成为了流媒体播放的主要平台。这促使流媒体播放器不断提升在大屏设备上的表现,优化用户体验。EasyPlayer无插件H5播放器是TSINGSEE青犀流媒体组件系列中关注......
  • 博客园-awescnb插件-geek皮肤优化-links优化
    简介博客园-awescnb插件-geek皮肤下,对自定义链接(links)优化将自定义链接添加至原主链接下,同时适配移动端场景效果实现定义自定义HTML:博客园->管理->设置->页脚HTML代码添加相关代码//生成链接functioncreateLinks(){for(letitemofconfig.links){......
  • linux之vim命令
    vim命令1、touch创建文件2、vim或vi编辑文件3、vim文件名4、vim编辑器共分为三种模式:(1)命令模式esc或ctrl+c(2)编辑模式按i键(3)底层命令模式先进入命令模式=shift+:=输入命令5、快捷键(1)enter键换行(2)backspce退格键,删除光标前一......
  • 博客园-awescnb插件-geek皮肤优化-样式优化
    ......