My dotfiles. Period.

list.vim 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. "=============================================================================
  2. " $Id: list.vim 520 2012-03-19 18:09:15Z luc.hermitte $
  3. " File: autoload/lh/list.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: 17th Apr 2007
  10. " Last Update: $Date: 2012-03-19 19:09:15 +0100 (Mon, 19 Mar 2012) $ (17th Apr 2007)
  11. "------------------------------------------------------------------------
  12. " Description:
  13. " Defines functions related to |Lists|
  14. "
  15. "------------------------------------------------------------------------
  16. " Installation:
  17. " Drop it into {rtp}/autoload/lh/
  18. " Vim 7+ required.
  19. " History:
  20. " v3.0.0:
  21. " (*) GPLv3
  22. " v2.2.2:
  23. " (*) new functions: lh#list#remove(), lh#list#matches(),
  24. " lh#list#not_found().
  25. " v2.2.1:
  26. " (*) use :unlet in :for loop to support heterogeneous lists
  27. " (*) binary search algorithms (upper_bound, lower_bound, equal_range)
  28. " v2.2.0:
  29. " (*) new functions: lh#list#accumulate, lh#list#transform,
  30. " lh#list#transform_if, lh#list#find_if, lh#list#copy_if,
  31. " lh#list#subset, lh#list#intersect
  32. " (*) the functions are compatible with lh#function functors
  33. " v2.1.1:
  34. " (*) unique_sort
  35. " v2.0.7:
  36. " (*) Bug fix: lh#list#Match()
  37. " v2.0.6:
  38. " (*) lh#list#Find_if() supports search predicate, and start index
  39. " (*) lh#list#Match() supports start index
  40. " v2.0.0:
  41. " TODO: «missing features»
  42. " }}}1
  43. "=============================================================================
  44. "=============================================================================
  45. let s:cpo_save=&cpo
  46. set cpo&vim
  47. "------------------------------------------------------------------------
  48. " ## Functions {{{1
  49. " # Debug {{{2
  50. function! lh#list#verbose(level)
  51. let s:verbose = a:level
  52. endfunction
  53. function! s:Verbose(expr)
  54. if exists('s:verbose') && s:verbose
  55. echomsg a:expr
  56. endif
  57. endfunction
  58. function! lh#list#debug(expr)
  59. return eval(a:expr)
  60. endfunction
  61. "------------------------------------------------------------------------
  62. " # Public {{{2
  63. " Function: lh#list#Transform(input, output, action) {{{3
  64. " deprecated version
  65. function! lh#list#Transform(input, output, action)
  66. let new = map(copy(a:input), a:action)
  67. let res = extend(a:output,new)
  68. return res
  69. for element in a:input
  70. let action = substitute(a:action, 'v:val','element', 'g')
  71. let res = eval(action)
  72. call add(a:output, res)
  73. unlet element " for heterogeneous lists
  74. endfor
  75. return a:output
  76. endfunction
  77. function! lh#list#transform(input, output, action)
  78. for element in a:input
  79. let res = lh#function#execute(a:action, element)
  80. call add(a:output, res)
  81. unlet element " for heterogeneous lists
  82. endfor
  83. return a:output
  84. endfunction
  85. function! lh#list#transform_if(input, output, action, predicate)
  86. for element in a:input
  87. if lh#function#execute(a:predicate, element)
  88. let res = lh#function#execute(a:action, element)
  89. call add(a:output, res)
  90. endif
  91. unlet element " for heterogeneous lists
  92. endfor
  93. return a:output
  94. endfunction
  95. function! lh#list#copy_if(input, output, predicate)
  96. for element in a:input
  97. if lh#function#execute(a:predicate, element)
  98. call add(a:output, element)
  99. endif
  100. unlet element " for heterogeneous lists
  101. endfor
  102. return a:output
  103. endfunction
  104. function! lh#list#accumulate(input, transformation, accumulator)
  105. let transformed = lh#list#transform(a:input, [], a:transformation)
  106. let res = lh#function#execute(a:accumulator, transformed)
  107. return res
  108. endfunction
  109. " Function: lh#list#match(list, to_be_matched [, idx]) {{{3
  110. function! lh#list#match(list, to_be_matched, ...)
  111. let idx = (a:0>0) ? a:1 : 0
  112. while idx < len(a:list)
  113. if match(a:list[idx], a:to_be_matched) != -1
  114. return idx
  115. endif
  116. let idx += 1
  117. endwhile
  118. return -1
  119. endfunction
  120. function! lh#list#Match(list, to_be_matched, ...)
  121. let idx = (a:0>0) ? a:1 : 0
  122. return lh#list#match(a:list, a:to_be_matched, idx)
  123. endfunction
  124. " Function: lh#list#matches(list, to_be_matched [,idx]) {{{3
  125. " Return the list of indices that match {to_be_matched}
  126. function! lh#list#matches(list, to_be_matched, ...)
  127. let res = []
  128. let idx = (a:0>0) ? a:1 : 0
  129. while idx < len(a:list)
  130. if match(a:list[idx], a:to_be_matched) != -1
  131. let res += [idx]
  132. endif
  133. let idx += 1
  134. endwhile
  135. return res
  136. endfunction
  137. " Function: lh#list#Find_if(list, predicate [, predicate-arguments] [, start-pos]) {{{3
  138. function! lh#list#Find_if(list, predicate, ...)
  139. " Parameters
  140. let idx = 0
  141. let args = []
  142. if a:0 == 2
  143. let idx = a:2
  144. let args = a:1
  145. elseif a:0 == 1
  146. if type(a:1) == type([])
  147. let args = a:1
  148. elseif type(a:1) == type(42)
  149. let idx = a:1
  150. else
  151. throw "lh#list#Find_if: unexpected argument type"
  152. endif
  153. elseif a:0 != 0
  154. throw "lh#list#Find_if: unexpected number of arguments: lh#list#Find_if(list, predicate [, predicate-arguments] [, start-pos])"
  155. endif
  156. " The search loop
  157. while idx != len(a:list)
  158. let predicate = substitute(a:predicate, 'v:val', 'a:list['.idx.']', 'g')
  159. let predicate = substitute(predicate, 'v:\(\d\+\)_', 'args[\1-1]', 'g')
  160. let res = eval(predicate)
  161. " echomsg string(predicate) . " --> " . res
  162. if res | return idx | endif
  163. let idx += 1
  164. endwhile
  165. return -1
  166. endfunction
  167. " Function: lh#list#find_if(list, predicate [, predicate-arguments] [, start-pos]) {{{3
  168. function! lh#list#find_if(list, predicate, ...)
  169. " Parameters
  170. let idx = 0
  171. let args = []
  172. if a:0 == 1
  173. let idx = a:1
  174. elseif a:0 != 0
  175. throw "lh#list#find_if: unexpected number of arguments: lh#list#find_if(list, predicate [, start-pos])"
  176. endif
  177. " The search loop
  178. while idx != len(a:list)
  179. " let predicate = substitute(a:predicate, 'v:val', 'a:list['.idx.']', 'g')
  180. let res = lh#function#execute(a:predicate, a:list[idx])
  181. if res | return idx | endif
  182. let idx += 1
  183. endwhile
  184. return -1
  185. endfunction
  186. " Function: lh#list#lower_bound(sorted_list, value [, first[, last]]) {{{3
  187. function! lh#list#lower_bound(list, val, ...)
  188. let first = 0
  189. let last = len(a:list)
  190. if a:0 >= 1 | let first = a:1
  191. elseif a:0 >= 2 | let last = a:2
  192. elseif a:0 > 2
  193. throw "lh#list#lower_bound: unexpected number of arguments: lh#list#lower_bound(sorted_list, value [, first[, last]])"
  194. endif
  195. let len = last - first
  196. while len > 0
  197. let half = len / 2
  198. let middle = first + half
  199. if a:list[middle] < a:val
  200. let first = middle + 1
  201. let len -= half + 1
  202. else
  203. let len = half
  204. endif
  205. endwhile
  206. return first
  207. endfunction
  208. " Function: lh#list#upper_bound(sorted_list, value [, first[, last]]) {{{3
  209. function! lh#list#upper_bound(list, val, ...)
  210. let first = 0
  211. let last = len(a:list)
  212. if a:0 >= 1 | let first = a:1
  213. elseif a:0 >= 2 | let last = a:2
  214. elseif a:0 > 2
  215. throw "lh#list#upper_bound: unexpected number of arguments: lh#list#upper_bound(sorted_list, value [, first[, last]])"
  216. endif
  217. let len = last - first
  218. while len > 0
  219. let half = len / 2
  220. let middle = first + half
  221. if a:val < a:list[middle]
  222. let len = half
  223. else
  224. let first = middle + 1
  225. let len -= half + 1
  226. endif
  227. endwhile
  228. return first
  229. endfunction
  230. " Function: lh#list#equal_range(sorted_list, value [, first[, last]]) {{{3
  231. " @return [f, l], where
  232. " f : First position where {value} could be inserted
  233. " l : Last position where {value} could be inserted
  234. function! lh#list#equal_range(list, val, ...)
  235. let first = 0
  236. let last = len(a:list)
  237. " Parameters
  238. if a:0 >= 1 | let first = a:1
  239. elseif a:0 >= 2 | let last = a:2
  240. elseif a:0 > 2
  241. throw "lh#list#equal_range: unexpected number of arguments: lh#list#equal_range(sorted_list, value [, first[, last]])"
  242. endif
  243. " The search loop ( == STLPort's equal_range)
  244. let len = last - first
  245. while len > 0
  246. let half = len / 2
  247. let middle = first + half
  248. if a:list[middle] < a:val
  249. let first = middle + 1
  250. let len -= half + 1
  251. elseif a:val < a:list[middle]
  252. let len = half
  253. else
  254. let left = lh#list#lower_bound(a:list, a:val, first, middle)
  255. let right = lh#list#upper_bound(a:list, a:val, middle+1, first+len)
  256. return [left, right]
  257. endif
  258. " let predicate = substitute(a:predicate, 'v:val', 'a:list['.idx.']', 'g')
  259. " let res = lh#function#execute(a:predicate, a:list[idx])
  260. endwhile
  261. return [first, first]
  262. endfunction
  263. " Function: lh#list#not_found(range) {{{3
  264. " @return whether the range returned from equal_range is empty (i.e. element not fount)
  265. function! lh#list#not_found(range)
  266. return a:range[0] == a:range[1]
  267. endfunction
  268. " Function: lh#list#unique_sort(list [, func]) {{{3
  269. " See also http://vim.wikia.com/wiki/Unique_sorting
  270. "
  271. " Works like sort(), optionally taking in a comparator (just like the
  272. " original), except that duplicate entries will be removed.
  273. " todo: support another argument that act as an equality predicate
  274. function! lh#list#unique_sort(list, ...)
  275. let dictionary = {}
  276. for i in a:list
  277. let dictionary[string(i)] = i
  278. endfor
  279. let result = []
  280. " echo join(values(dictionary),"\n")
  281. if ( exists( 'a:1' ) )
  282. let result = sort( values( dictionary ), a:1 )
  283. else
  284. let result = sort( values( dictionary ) )
  285. endif
  286. return result
  287. endfunction
  288. function! lh#list#unique_sort2(list, ...)
  289. let list = copy(a:list)
  290. if ( exists( 'a:1' ) )
  291. call sort(list, a:1 )
  292. else
  293. call sort(list)
  294. endif
  295. if len(list) <= 1 | return list | endif
  296. let result = [ list[0] ]
  297. let last = list[0]
  298. let i = 1
  299. while i < len(list)
  300. if last != list[i]
  301. let last = list[i]
  302. call add(result, last)
  303. endif
  304. let i += 1
  305. endwhile
  306. return result
  307. endfunction
  308. " Function: lh#list#subset(list, indices) {{{3
  309. function! lh#list#subset(list, indices)
  310. let result=[]
  311. for e in a:indices
  312. call add(result, a:list[e])
  313. endfor
  314. return result
  315. endfunction
  316. " Function: lh#list#remove(list, indices) {{{3
  317. function! lh#list#remove(list, indices)
  318. " assert(is_sorted(indices))
  319. let idx = reverse(copy(a:indices))
  320. for i in idx
  321. call remove(a:list, i)
  322. endfor
  323. return a:list
  324. endfunction
  325. " Function: lh#list#intersect(list1, list2) {{{3
  326. function! lh#list#intersect(list1, list2)
  327. let result = copy(a:list1)
  328. call filter(result, 'index(a:list2, v:val) >= 0')
  329. return result
  330. for e in a:list1
  331. if index(a:list2, e) > 0
  332. call result(result, e)
  333. endif
  334. endfor
  335. endfunction
  336. " Functions }}}1
  337. "------------------------------------------------------------------------
  338. let &cpo=s:cpo_save
  339. "=============================================================================
  340. " vim600: set fdm=marker: