2

I need a vim shortcut to display all non-duplicate struct names in the file being edited. I have made this C program which does this, however I have to leave the editor and execute the program in bash and return back to editing.

Lets say the file being edited is linux/drivers/net/ethernet/smsc/smsc911x.c. The output should be like following:

 0. smsc911x_data
 1. smsc911x_ops
 2. smsc911x_platform_config
 3. phy_device
 4. mii_bus
 5. net_device
 6. napi_struct
 7. regulator_bulk_data
 8. clk
 9. platform_device
10. sk_buff
11. net_device_stats
12. netdev_hw_addr
13. sockaddr
14. ethtool_drvinfo
15. ethtool_eeprom
16. ethtool_ops
17. net_device_ops
18. resource
19. device_node
20. dev_pm_ops
21. of_device_id
22. platform_driver

EDIT: The Parse() vim routine defined in the answer posted below doesn't prints all the struct names. It's output:

0. clk
1. device_node
2. ethtool_drvinfo
3. ethtool_eeprom
4. mii_bus
5. napi_struct
6. net_device
7. netdev_hw_addr
8. phy_device
9. regulator_bulk_data
10. resource
11. sk_buff
12. smsc911x_data
13. smsc911x_platform_config
14. sockaddr

I guess its because it is not able to handle cases like struct { ... } name;

  • 1
    Can't you just run :!./find_structs %? – muru Jul 5 '15 at 14:17
  • Yes, but i want it to be inside vim so that i can run other operations like jump to struct definition using ctags. – manav m-n Jul 5 '15 at 14:21
  • 2
    A plugin like this one might be more convenient: majutsushi.github.io/tagbar – muru Jul 5 '15 at 14:27
  • @muru: i would prefer a custom vim script than depending on an external plugin especially when you are running vim in an embedded environment. – manav m-n Jul 6 '15 at 9:46
  • Did you try with some search/substitute/sort commands ? – nobe4 Jul 8 '15 at 13:55
3
:e smsc911x.c
:new
:read !grep -o "struct [^ ;,)]\+" # | awk '{print $2}' | sort -u

Explaining:

  • grep -o: returns only the match chars (useful for multiple match on one line)
  • [^ ;,)]: remove characters non part of struct name
  • #: use alternate file (smsc911x.c in this case)

See this gets even more results than your program -once removed that numbered order that I don't know where it comes from-

diff --git 1/your_result 2/my_result
index 0bee24a..90d7ce4 100644
--- 1/your_result
+++ 2/my_result
@@ -1,9 +1,13 @@
 clk
+device
 device_node
 dev_pm_ops
+ethtool_cmd
 ethtool_drvinfo
 ethtool_eeprom
 ethtool_ops
+ethtool_regs
+ifreq
 mii_bus
 napi_struct
 netdev_hw_addr

Save this to a mapping or function if you feel you will use it from time to time

3

Here you are :

function! Parse()
  " keep only the struct definitions
  v/\v.*(\s|\()struct (\w+).*/d
  " keep only the names of the structs
  %s/\v.*(\s|\()struct (\w+).*/\2/
  " sort and keep non-duplicate lines
  %sort u
  " add line numbers
  %s/^/\=printf('%-d. ', line('.')-1)
endfunction

On your file use it with :

:call Parse()

In the file you provided I didn't match as results as you (but I didn't found any smsc911x_data for example).

If you want detailed explanation about how I did just ask :)

  • 1
    Remove the semicolons from the beginning of the commands, that is invalid syntax. – EvergreenTree Jul 8 '15 at 17:40
  • 2
    @EvergreenTree No, it's not invalid to have the : in vimscript. Vim just ignores it. You can have as many leading : as you want. – jamessan Jul 8 '15 at 19:20
  • I didn't realize that. I always though it designated a one-liner that the user would type out manually. Interesting! – EvergreenTree Jul 8 '15 at 19:23
  • I was confused because it worked, but I find it cleaner without – nobe4 Jul 8 '15 at 19:25
  • @Nobe4: Your function displays only 15 out of the 23 struct names shown in the question's example. It missed out the other 9 struct names. – manav m-n Jul 8 '15 at 21:55
3
+50

I'd still suggest using the program that you wrote. You can save its output to a scratch buffer and then use tag navigation. Something like (hat-tip to Nobe4):

function! Parse()
    let command = "%!/path/to/find_structs " . shellescape(expand('%'))
    new
    " http://vim.wikia.com/wiki/Vim_buffer_FAQ 
    " (How is a scratch (temporary) buffer created?)
    setlocal buftype=nofile
    setlocal bufhidden=hide
    setlocal noswapfile
    set nobuflisted
    execute command
endfunction

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.