My dotfiles. Period.

tsort.vim 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. "=============================================================================
  2. " $Id: tsort.vim 520 2012-03-19 18:09:15Z luc.hermitte $
  3. " File: autoload/lh/tsort.vim {{{1
  4. " Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
  5. " <URL:http://code.google.com/p/lh-vim/>
  6. " License: GPLv3 with exceptions
  7. " <URL:http://code.google.com/p/lh-vim/wiki/License>
  8. " Version: 3.0.0
  9. " Created: 21st Apr 2008
  10. " Last Update: $Date: 2012-03-19 19:09:15 +0100 (Mon, 19 Mar 2012) $
  11. "------------------------------------------------------------------------
  12. " Description: Library functions for Topological Sort
  13. "
  14. "------------------------------------------------------------------------
  15. " Drop the file into {rtp}/autoload/lh/graph
  16. " History: «history»
  17. " TODO: «missing features»
  18. " }}}1
  19. "=============================================================================
  20. let s:cpo_save=&cpo
  21. set cpo&vim
  22. "------------------------------------------------------------------------
  23. " ## Debug {{{1
  24. function! lh#graph#tsort#verbose(level)
  25. let s:verbose = a:level
  26. endfunction
  27. function! s:Verbose(expr)
  28. if exists('s:verbose') && s:verbose
  29. echomsg a:expr
  30. endif
  31. endfunction
  32. function! lh#graph#tsort#debug(expr)
  33. return eval(a:expr)
  34. endfunction
  35. "------------------------------------------------------------------------
  36. "## Helper functions {{{1
  37. "# s:Successors_fully_defined(node) {{{2
  38. function! s:Successors_fully_defined(node) dict
  39. if has_key(self.table, a:node)
  40. return self.table[a:node]
  41. else
  42. return []
  43. endif
  44. endfunction
  45. "# s:Successors_lazy(node) {{{2
  46. function! s:Successors_lazy(node) dict
  47. if !has_key(self.table, a:node)
  48. let nodes = self.fetch(a:node)
  49. let self.table[a:node] = nodes
  50. " if len(nodes) > 0
  51. " let self.nb += 1
  52. " endif
  53. return nodes
  54. else
  55. return self.table[a:node]
  56. endif
  57. endfunction
  58. "# s:PrepareDAG(dag) {{{2
  59. function! s:PrepareDAG(dag)
  60. if type(a:dag) == type(function('has_key'))
  61. let dag = {
  62. \ 'successors': function('s:Successors_lazy'),
  63. \ 'fetch' : a:dag,
  64. \ 'table' : {}
  65. \}
  66. else
  67. let dag = {
  68. \ 'successors': function('s:Successors_fully_defined'),
  69. \ 'table' : deepcopy(a:dag)
  70. \}
  71. endif
  72. return dag
  73. endfunction
  74. "## Depth-first search (recursive) {{{1
  75. " Do not detect cyclic graphs
  76. "# lh#graph#tsort#depth(dag, start_nodes) {{{2
  77. function! lh#graph#tsort#depth(dag, start_nodes)
  78. let dag = s:PrepareDAG(a:dag)
  79. let results = []
  80. let visited_nodes = { 'Visited':function('s:Visited')}
  81. call s:RecursiveDTSort(dag, a:start_nodes, results, visited_nodes)
  82. call reverse(results)
  83. return results
  84. endfunction
  85. "# The real, recursive, T-Sort {{{2
  86. "see boost.graph for a non recursive implementation
  87. function! s:RecursiveDTSort(dag, start_nodes, results, visited_nodes)
  88. for node in a:start_nodes
  89. let visited = a:visited_nodes.Visited(node)
  90. if visited == 1 | continue " done
  91. elseif visited == 2 | throw "Tsort: cyclic graph detected: ".node
  92. endif
  93. let a:visited_nodes[node] = 2 " visiting
  94. let succs = a:dag.successors(node)
  95. try
  96. call s:RecursiveDTSort(a:dag, succs, a:results, a:visited_nodes)
  97. catch /Tsort:/
  98. throw v:exception.'>'.node
  99. endtry
  100. let a:visited_nodes[node] = 1 " visited
  101. call add(a:results, node)
  102. endfor
  103. endfunction
  104. function! s:Visited(node) dict
  105. return has_key(self, a:node) ? self[a:node] : 0
  106. endfunction
  107. "## Breadth-first search (non recursive) {{{1
  108. "# lh#graph#tsort#breadth(dag, start_nodes) {{{2
  109. " warning: This implementation does not work with lazy dag, but only with fully
  110. " defined ones
  111. function! lh#graph#tsort#breadth(dag, start_nodes)
  112. let result = []
  113. let dag = s:PrepareDAG(a:dag)
  114. let queue = deepcopy(a:start_nodes)
  115. while len(queue) > 0
  116. let node = remove(queue, 0)
  117. " echomsg "result <- ".node
  118. call add(result, node)
  119. let successors = dag.successors(node)
  120. while len(successors) > 0
  121. let m = s:RemoveEdgeFrom(dag, node)
  122. " echomsg "graph loose ".node."->".m
  123. if !s:HasIncomingEgde(dag, m)
  124. " echomsg "queue <- ".m
  125. call add(queue, m)
  126. endif
  127. endwhile
  128. endwhile
  129. if !s:Empty(dag)
  130. throw "Tsort: cyclic graph detected: "
  131. endif
  132. return result
  133. endfunction
  134. function! s:HasIncomingEgde(dag, node)
  135. for node in keys(a:dag.table)
  136. if type(a:dag.table[node]) != type([])
  137. continue
  138. endif
  139. if index(a:dag.table[node], a:node) != -1
  140. return 1
  141. endif
  142. endfor
  143. return 0
  144. endfunction
  145. function! s:RemoveEdgeFrom(dag, node)
  146. let successors = a:dag.successors(a:node)
  147. if len(successors) > 0
  148. let successor = remove(successors, 0)
  149. if len(successors) == 0
  150. " echomsg "finished with ->".a:node
  151. call remove(a:dag.table, a:node)
  152. endif
  153. return successor
  154. endif
  155. throw "No more edges from ".a:node
  156. endfunction
  157. function! s:Empty(dag)
  158. " echomsg "len="len(a:dag.table)
  159. return len(a:dag.table) == 0
  160. endfunction
  161. " }}}1
  162. "------------------------------------------------------------------------
  163. let &cpo=s:cpo_save
  164. "=============================================================================
  165. " vim600: set fdm=marker