Refactoring ใน Vim


100

แน่นอนความจริงที่ว่าคุณสามารถ refactor บน IDE ได้นั้นไม่มีค่าสำหรับหลาย ๆ คนฉันแทบจะไม่เคยทำเลยเมื่อฉันเขียนโค้ด แต่ฉันอาจลองทำเมื่อแก้ไขแหล่งที่มาของคนอื่น คุณจะทำงานที่ไม่สำคัญเช่นนี้ในหลายไฟล์ใน Vim ได้อย่างไร?

ฉันพบปลั๊กอินนี้สำหรับการปรับโครงสร้าง Ruby แต่ภาษา "ใดก็ได้" ล่ะ


2
การปรับโครงสร้างเป็นภาษาที่เฉพาะเจาะจงมาก คุณต้องมองหาส่วนเสริมเฉพาะสำหรับแต่ละภาษาที่คุณสนใจคุณน่าจะพบส่วนเสริมสำหรับบางภาษาไม่ใช่สำหรับภาษาอื่น หากมีสิ่งที่คุณต้องการและหาไม่พบหากคุณรู้สึกทะเยอทะยานคุณอาจลองเขียนขึ้นมาโดยใช้โปรแกรมเสริมที่มีอยู่สำหรับภาษาอื่นที่คล้ายคลึงกันเป็นจุดเริ่มต้น
Steve Jorgensen

2
VIM ได้รับการออกแบบมาเพื่อแก้ไขไฟล์เดียวและอาจเป็นไฟล์ภายใต้ไดเร็กทอรีไม่ใช่โปรเจ็กต์ Refactorings ที่รองรับ IDE จำนวนมากจะส่งผลกระทบต่อไฟล์ทั่วทั้งโปรเจ็กต์ (เช่นการเปลี่ยนชื่อคลาส) ฉันคิดว่ามันคงเป็นเรื่องยากที่จะทำให้ "ถูกต้อง" ด้วยตัวแก้ไขเช่น (g) VI (m) จนถึงจุดที่ฉันคิดว่า บริษัท หรือโครงการใหญ่ ๆ จะต้องดำเนินการต่อไป โดยพื้นฐานแล้วพวกเขาจะต้องแยกวิเคราะห์แต่ละภาษาเพื่อหลีกเลี่ยงการแทนที่สตริงอย่างง่ายและมีแนวโน้มที่จะเกิดข้อผิดพลาด (ctag ให้บางส่วนของสิ่งนี้) รวมถึงประเภทโครงการที่เกี่ยวข้อง (เพื่อให้ทราบว่าไฟล์ใดที่ต้องแก้ไข)
Merlyn Morgan-Graham

1
ขอบคุณสำหรับความคิดเห็นฉันคิดว่านี่คือจุดที่สิ่งต่างๆเริ่มยุ่งยากและการพยายามดัด VIM เป็น IDE นั้นไม่ใช่วิธีแก้ปัญหาที่หรูหราในการใช้โปรแกรมเพียงโปรแกรมเดียวเพื่อแก้ไขหลายภาษา ฉันไม่ต้องการยอมแพ้กับ VIM อย่างแท้จริงเนื่องจากคุณลักษณะ "ขั้นสูง" บางอย่างที่มีอยู่ใน IDE
Helmut Granda

@ MerlynMorgan-Graham - บางคนก็เก็บรหัสไว้ในไฟล์ไม่กี่ไฟล์ (ขนาดใหญ่ซึ่งอาจเป็น) หลีกเลี่ยงปัญหานี้โดยสิ้นเชิง
Rook

7
@ldigas: นั่นจะช่วยแก้ปัญหาได้ แต่มันค่อนข้างขัดต่อแนวทางปฏิบัติที่แนะนำสำหรับบางภาษา (เช่น Java) โดยพื้นฐานแล้วการดัดโค้ดเพื่อให้เหมาะกับความต้องการของเครื่องมือในเมื่อมันควรจะเป็นไปในทางอื่น
Merlyn Morgan-Graham

คำตอบ:


78

ฉันเห็นด้วยกับกระบวนทัศน์ "Vim ไม่ใช่ IDE" แต่ก็มีหลายครั้งที่ไม่มี IDE นี่คือสิ่งที่ฉันใช้ในสถานการณ์เหล่านั้น:

: grep,: vimgrep,: Ag,: Ggrep

การรีแฟคเตอร์ที่เกี่ยวข้องกับการแทนที่ปกติฉันมักจะใช้: grepบนแผนผังโครงการของฉันแล้วบันทึกมาโครเพื่อทำการรีแฟคเตอร์ -: g และ: s ไม่ใช่เกมง่ายๆ โดยปกติแล้วมันจะช่วยให้ฉันแก้ไขไฟล์จำนวนมากได้อย่างรวดเร็วโดยใช้ความพยายามเพียงเล็กน้อย สุจริตฉันใช้วิธีนี้มากกว่าวิธีอื่น ๆ

ขึ้นอยู่กับเวิร์กโฟลว์ของคุณคำสั่งในตัวอาจช้า / ไม่สะดวก หากคุณใช้คอมไพล์คุณจะต้องใช้ปลั๊กอินFugitive ที่ยอดเยี่ยมและ:Ggrepคำสั่งเพื่อค้นหาเฉพาะไฟล์ที่ตรวจสอบในคอมไพล์ ฉันยังชอบSilver Searcherสำหรับความรวดเร็ว

: argdo,: cdo และ: bufdo

: cdoและ: argdoมีประโยชน์ในการดำเนินการคำสั่ง vim ในชุดไฟล์

บรรทัดคำสั่ง

เมื่อการกำหนดรายการไฟล์ที่ต้องการการเปลี่ยนแปลงทำได้ยากขึ้น:vimgrepฉันใช้คำสั่ง grep / find สำหรับบรรทัดคำสั่งเพื่อดูแลรายการไฟล์ที่ฉันต้องการ refactor อย่างใกล้ชิดมากขึ้น บันทึกรายการลงในไฟล์ข้อความและใช้:eและผสมการบันทึกมาโครเพื่อทำการเปลี่ยนแปลงที่ฉันต้องทำ

ฉันพบว่ายิ่งสนิมน้อยเท่าไหร่ฉันก็ยิ่งมีทักษะในการบันทึกมาโครมากขึ้นเท่านั้นฉันก็พบว่า Vim สำหรับการปรับโครงสร้างใหม่: รู้สึกสะดวกสบายในการบันทึก / กู้คืนจากรีจิสเตอร์การเพิ่ม / ลดตัวแปรตัวนับรีจิสเตอร์การล้าง / บันทึกการบันทึกมาโครลงในไฟล์เพื่อใช้ในภายหลังเป็นต้น


อัปเดต

เนื่องจากการเขียนวิดีโอเพิ่มเติมสำหรับวิธีการที่ฉันอธิบายได้รับการเผยแพร่บน vimcasts.org (ฉันขอแนะนำให้คุณดูVimcasts ทั้งหมด! ) สำหรับการปรับโครงสร้างใหม่ให้ดูสิ่งเหล่านี้:

Vimgolfยังเป็นวิธีที่ยอดเยี่ยมในการฝึกฝน

ความแพร่หลายของเซิร์ฟเวอร์ Language Server Protocol ตั้งแต่ฉันเขียนคำตอบนี้ได้นำความสามารถในการปรับโครงสร้างใหม่มาสู่ Vim (และบรรณาธิการอื่น ๆ ) IMO เป็นวิธีที่ยาวนานจากความสามารถในการปรับโครงสร้างใหม่ที่คุณจะเห็นใน IDE ที่สร้างขึ้นโดยเฉพาะ (ฉันใช้มันและชอบ coc และ ALE) ดูคำตอบอื่น ๆ สำหรับคำถามนี้สำหรับข้อมูลเพิ่มเติม!


12
การปรับโครงสร้างใหม่เป็นวิธีที่มากกว่าการจับคู่รูปแบบนั่นเป็นเหตุผลที่ IDE จำเป็นในการทำให้สิ่งนี้เป็นไปโดยอัตโนมัติอย่างปลอดภัย เห็นได้ชัดว่าคุณสามารถทำได้ด้วยตนเอง แต่เมื่อพิจารณาจากตัวเลือกที่มีอยู่และส่วนใหญ่แล้วการทำด้วยตนเองจะปลอดภัยกว่าทำไมคุณถึงพิจารณาตัวเลือกอื่น ๆ
Cutberto Ocampo

1
@CutbertoOcampo ฉันเห็นด้วยกับคุณในระดับหนึ่ง: ขึ้นอยู่กับแง่มุมมากมายของโครงการ (โครงสร้างภาษาทักษะของพนักงานและทรัพยากรเพื่อชื่อไม่กี่อย่าง) อาจเป็นเครื่องมือปรับโครงสร้างที่ยอดเยี่ยมสำหรับปัญหาของคุณ คำตอบของฉันใช้กับสถานการณ์ที่ไม่เป็นความจริงและคุณต้องการจัดการปัญหาใน Vim
dsummersl

2
ไม่เป็นไรฉันเข้าใจว่าผู้คนอาจรู้สึกสบายใจมากขึ้นในการทำสิ่งต่างๆโดยใช้เครื่องมือที่ต้องการมานานและมีแฮ็กบางอย่างที่สามารถทำงานได้ดีจริง ๆ อาจจะดีกว่า IDE ใด ๆ ที่มีอยู่ แต่สำหรับการใช้งานนอกสถานที่ โซลูชัน -box ฉันว่า IDE จริงจะทำงานได้ดีกว่าสำหรับผู้ใช้ส่วนใหญ่ ฉันกำลังคิดเกี่ยวกับสถานการณ์แบบ 80-20% (ยิ่งไปกว่านั้นด้วยความสมดุลของ IDE)
Cutberto Ocampo

1
มีอุดมคติสำหรับการใช้งานจริงทุกภาษา การพยายามปรับโครงสร้างใหม่ด้วย vim หรือ regex นั้นฟังดูบ้ามาก ทำไมคุณถึงลอง?
ม้วน

1
@rolls มีศักยภาพเพียงพอที่จะคว้าเครื่องจักรที่ต้องการของเพื่อนร่วมงานแบบสุ่มโดยไม่ใช้ความคิดของคุณหรือ cfg อะไรก็ตามที่คุณสามารถอยู่ได้และทิ้งความประทับใจไว้รอบ ๆ (ไม่ใช่เพื่อ "ความประทับใจ" แต่เพื่อชื่อเสียงและตำแหน่งในอนาคต
bloody

28

โปรโตคอลเซิร์ฟเวอร์ภาษา (LSP)

โปรโตคอลเซิร์ฟเวอร์ภาษามีคุณลักษณะสำหรับการเปลี่ยนชื่อสัญลักษณ์อย่างชาญฉลาดในโครงการ:

https://microsoft.github.io//language-server-protocol/specifications/specification-3-14/#textDocument_rename

ตัวอย่างเช่นเซิร์ฟเวอร์ภาษาต่อไปนี้สนับสนุนสิ่งนี้:

คุณสามารถค้นหาเซิร์ฟเวอร์ภาษามากขึ้นภายใต้https://langserver.org/

เป็นกลุ่ม

ไคลเอ็นต์ตัวแก้ไขเป็นกลุ่มจำเป็นต้องใช้ภายในกลุ่ม มีตัวเลือกต่อไปนี้:

  1. LanguageClient-neovim (ต้องการสนิม) แนะนำการทำแผนที่:

    nnoremap <silent> <F2> :call LanguageClient_textDocument_rename()<CR>
    
  2. coc.nvim (ต้องใช้ node.js) แนะนำการแมป:

    " Remap for rename current word
    nmap <leader>rn <Plug>(coc-rename)
    
  3. Aleมี

    nnoremap <silent> <Plug>(ale_rename) :ALERename<Return>
    

    Ale ไม่ได้กำหนดการเชื่อมโยงคีย์ใด ๆ สิ่งนี้จะต้องดำเนินการโดยผู้ใช้

  4. vim-lspจัดเตรียมคำสั่งต่อไปนี้

    :LspRename
    

    คล้ายกับ Ale ไม่แนะนำให้ทำแผนที่ อย่างไรก็ตามแน่นอนคุณสามารถกำหนดได้ดังต่อไปนี้

    nmap <leader>r <plug>(lsp-rename)
    

    ( <leader>rจะถูกแทนที่ด้วยตัวเลือกของคุณฉันไม่ทราบว่าปลั๊กอินส่วนใหญ่เห็นด้วย)

  5. vim-lscมีการแมปเริ่มต้น:

    'Rename': 'gR'
    

ดูYouCompleteMeที่อำนวยความสะดวก LSPs ด้วย

นีโอวิม

Neovim ได้รับการสนับสนุนในตัวสำหรับ lsp ตั้งแต่13.11.2019

ดูการกำหนดค่าทั่วไปของ LSPs https://github.com/neovim/nvim-lsp

อย่างไรก็ตามฉันไม่สามารถเข้าใจได้ว่าการเปลี่ยนชื่ออย่างชาญฉลาดทำงานอย่างไร หากมีใครรู้โปรดอัปเดตส่วนนี้

Refactorings อื่น ๆ

ฉันไม่รู้ว่ามีแผนสำหรับโปรโตคอล LSP เพื่อรองรับการปรับโครงสร้างที่ซับซ้อนมากขึ้นหรือไม่เช่นการเปลี่ยนโครงสร้างคลาสการเพิ่มพารามิเตอร์ให้กับวิธีการ / ฟังก์ชันหรือการย้ายเมธอดไปยังคลาสอื่น สำหรับรายชื่อของ refactorings ดูhttps://refactoring.com/catalog/


น่าเสียดายที่การสนับสนุนการปรับโครงสร้างใหม่ใน LSP ในขณะนี้ค่อนข้างอ่อนแอเมื่อเทียบกับความทันสมัย github.com/Microsoft/language-server-protocol/issues/61
Mickael

2
AFAIK ที่เปลี่ยนชื่อเพื่อcoc-renameใช้งานได้กับบัฟเฟอร์ปัจจุบันเท่านั้น ไม่ได้อัปเดตการใช้ชื่อที่ส่งออกทั่วโลกในโครงการ (ข้ามไฟล์)
oligofren

16

Python

สำหรับภาษาpythonปลั๊กอินต่อไปนี้ให้ความสามารถในการเปลี่ยนชื่อ 'smart' สำหรับ vim:

  • jedi-vim( github )<leader>r
  • ropevim( github )CTRL-c r r
  • python-mode( github ):h pymode-rope-refactoring

13

ซี - แฟมิลี่

  1. ลองใช้ปลั๊กอินClighterเพื่อเปลี่ยนชื่อ refactoring สำหรับตระกูล c มันขึ้นอยู่กับเสียงดัง แต่มีข้อ จำกัด และปลั๊กอินถูกทำเครื่องหมายว่าเลิกใช้แล้ว

    การแมปที่แนะนำโดยClighterคือ

     nmap <silent> <Leader>r :call clighter#Rename()<CR>
    

    หมายเหตุ, ปลั๊กอินทายาทclighter8ได้ลบออกฟังก์ชั่นการเปลี่ยนชื่อในการกระทำ 24927db42

  2. ถ้าคุณใช้ neovim คุณสามารถดูที่ปลั๊กอินยึด มันแนะนำ

     nmap <silent> <Leader>r :call ClampRename()<CR>
    

5

ฉันเขียนปลั๊กอินนี้สำหรับการปรับโครงสร้างทั่วไป ยังต้องมีการปรับปรุงอีกมากมาย บางครั้งในอนาคตฉันจะพยายามละทิ้ง ctags เพื่อสนับสนุนการส่งเสียงดังสำหรับการปรับแต่ง C & C ++


5

ปลั๊กอินYouCompleteMe (YCM) (20k ดาวบน github)

http://ycm-core.github.io/YouCompleteMe/#the-refactorrename-new-name-subcommand

:h RefactorRename-new-name

ในประเภทไฟล์ที่รองรับคำสั่งนี้จะพยายามเปลี่ยนชื่อตัวระบุตามความหมายภายใต้เคอร์เซอร์ ซึ่งรวมถึงการเปลี่ยนชื่อการประกาศคำจำกัดความและการใช้งานของตัวระบุหรือการดำเนินการอื่น ๆ ที่เหมาะสมกับภาษา พฤติกรรมเฉพาะถูกกำหนดโดยกลไกความหมายที่ใช้อยู่

คล้ายกับFixItคำสั่งนี้ใช้การแก้ไขอัตโนมัติกับไฟล์ต้นฉบับของคุณ การดำเนินการเปลี่ยนชื่ออาจเกี่ยวข้องกับการเปลี่ยนแปลงไฟล์หลายไฟล์ซึ่งอาจเปิดหรือไม่เปิดใน Vim บัฟเฟอร์ในขณะนั้น YouCompleteMe จัดการทั้งหมดนี้ให้คุณ ลักษณะการทำงานได้อธิบายไว้ในส่วนต่อไปนี้

สนับสนุนในประเภทไฟล์: c, cpp, objc, objcpp, cuda, java, javascript, typescript, rust, cs

โดยค่าเริ่มต้นจะไม่มีการแมป


ตอนนี้ใช้งานได้เฉพาะกับ javascript, typescript และ java?
อาร์

เพื่อให้สามารถใช้งานได้กับหลายไฟล์บน C-Family (โดยใช้ clangd) คุณต้องเพิ่มสิ่งนี้ใน. vimrc: let g: ycm_clangd_args = ['-cross-file-rename']
jav

4

อาจไม่ใช่วิธีแก้ปัญหาที่หรูหราที่สุด แต่ฉันพบว่ามีประโยชน์มาก: ฉันใช้ECLIMเพื่อเชื่อมต่อ VIM และ Eclipse แน่นอนการแก้ไขซอร์สโค้ดทั้งหมดของฉันทำได้ใน VIM แต่เมื่อถึงเวลาที่ต้อง refactor เราสามารถใช้ประโยชน์จากความสามารถที่เหนือกว่าของ Eclipse ในเรื่องนี้

ให้มันลอง.


3

Plugin Factorus

มีอีกกลุ่มปลั๊กอินเฉพาะสำหรับ refactoring เรียกfactorusซึ่งมีอยู่ในGitHub

ปัจจุบัน (2017-12) รองรับภาษา

  • ค,
  • java และ
  • หลาม

2

วางเคอร์เซอร์ไว้ที่ชื่อเพื่อ refactor และพิมพ์

gd (หรือ gDถ้าคุณกำลัง refactoring ตัวแปรส่วนกลาง)

แล้ว

cgn new_name esc

และ

. อย่างน้อยหนึ่งครั้งเพื่อ refactor เหตุการณ์ถัดไป

หรือ

:%norm . เพื่อ refactor เหตุการณ์ทั้งหมดในบัฟเฟอร์ในครั้งเดียว


1

ฉันเขียนโค้ด C / C ++ จำนวนมากเป็นกลุ่ม การปรับโครงสร้างใหม่ที่ฉันทำบ่อยที่สุดคือการเปลี่ยนชื่อตัวแปรชื่อคลาส ฯลฯ โดยปกติแล้วฉัน:bufdo :%s/source/dest/gจะใช้เพื่อค้นหา / แทนที่ในไฟล์ซึ่งเกือบจะเหมือนกับการเปลี่ยนชื่อโดย IDE ขนาดใหญ่
อย่างไรก็ตามในกรณีของฉันฉันพบว่าโดยปกติฉันจะเปลี่ยนชื่อเอนทิตีที่คล้ายกันโดยสะกดในหลายกรณี (เช่น CamelCase, snake_case เป็นต้น) ดังนั้นฉันจึงตัดสินใจเขียนยูทิลิตี้ขนาดเล็กเพื่อช่วยในการค้นหา "smart-case" ประเภทนี้ / แทนที่มันจะเป็นเจ้าภาพที่นี่ เป็นยูทิลิตี้บรรทัดคำสั่งไม่ใช่ปลั๊กอินสำหรับกลุ่มฉันหวังว่าคุณจะพบว่ามีประโยชน์


0

สำหรับการปรับโครงสร้างใหม่หากคุณใช้Unite (และคุณควร) คุณสามารถใช้vim-qfreplaceและทำให้ง่ายมาก ตรวจสอบวิดีโอนี้ที่สาธิตวิธีการทำงาน เมื่อตั้งค่าเวิร์กโฟลว์ของคุณแล้วคุณสามารถสร้างการแมปบางอย่างเพื่อเพิ่มประสิทธิภาพได้ (แทนที่จะพิมพ์สิ่งต่างๆเช่นในวิดีโอ)


0

การรวมกันของปลั๊กอินสองตัว: vim-ripgrepเพื่อค้นหาไฟล์ต่างๆและใส่ผลลัพธ์ในหน้าต่างQuickfixและตัวสะท้อนภาพด่วนเพื่อบันทึกการเปลี่ยนแปลงในหน้าต่าง Quickfix และบันทึกการเปลี่ยนแปลงแต่ละไฟล์โดยอัตโนมัติ


0

ฉันจะพิจารณาใช้ emacs เวอร์ชัน spacemacs ใช้โหมดเดียวกันและการกดแป้นพิมพ์ส่วนใหญ่เป็น Vim แต่มีส่วนเสริมอื่น ๆ อีกมากมายเนื่องจากเป็นเสียงกระเพื่อม หากคุณต้องการตั้งโปรแกรมใน C ++ คุณเพียงแค่เพิ่มเลเยอร์ c ++ และ IDE ส่วนใหญ่ได้รับการตั้งค่าสำหรับคุณแล้ว สำหรับภาษาที่ตีความหมายอื่น ๆ เช่น python หรือ bash คุณไม่จำเป็นต้องเว้นวรรคเพื่อใช้งาน พวกเขายังมีวิธีเรียกใช้บล็อกโค้ดภายในข้อความของคุณโดยตรงซึ่งใช้งานได้ดีเยี่ยมสำหรับการเขียนโปรแกรมแบบรู้หนังสือหรือการเขียนโปรแกรมที่ทำซ้ำได้โดยที่โค้ดและข้อมูลอยู่ในไฟล์เดียวกัน ทั้งสองแบบเป็นข้อความ

Spacemacs นั้นหนักกว่ามากในการโหลดครั้งแรก แต่สิ่งเพิ่มเติมที่คุณสามารถทำได้ก็คุ้มค่ากับต้นทุนการเริ่มต้นเพียงไม่กี่วินาที โหมดองค์กรชั้นเดียวคุ้มค่าที่จะลองดู เป็นเครื่องมือจัดทำโครงร่างโปรแกรมเมอร์ตัวจับเวลาวัน / สิ่งที่ต้องทำที่ดีที่สุดที่ฉันเคยใช้


0

ไป

  1. เครื่องมือgodoctor ( github ) รองรับความสามารถในการปรับโครงสร้างใหม่หลายประการ
  • เปลี่ยนชื่อ
  • แยกฟังก์ชัน
  • แยกตัวแปรท้องถิ่น
  • สลับ var ⇔: =
  • เพิ่มต้นขั้ว Godoc

มีปลั๊กอินกลุ่มhttps://github.com/godoctor/godoctor.vimซึ่งทำให้พร้อมใช้งาน

ด้วยเคอร์เซอร์ในสิ่งที่จะเปลี่ยนชื่อ:

:Rename <newname>

ไฮไลต์บล็อกที่จะแยก:

:Refactor extract newfunc
  1. เป็นกลุ่ม

    • การเปลี่ยนชื่อระบุประเภทปลอดภัยอย่างแม่นยำด้วย:GoRename.
  2. เซิร์ฟเวอร์ภาษา gopls

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.