tests/bundled/lh-vim-lib/autoload/lh/graph/tsort.vim @ c839b22aa015
defer "can't load gundo" warning
Only inform that gundo didn't load when an attempt is made to invoke it.
Too many hosts still don't have vim 7.3, but I'd like to do a straight
update of my vimfiles from my dvcs without needing any fiddly
conditionals in order to load vim without a warning message.
author |
Seth Milliken <seth@janrain.com> |
date |
Wed, 29 Dec 2010 15:16:33 -0800 |
parents |
2b3d5ee5c4a4 |
children |
(none) |
"=============================================================================
" $Id: tsort.vim 246 2010-09-19 22:40:58Z luc.hermitte $
" File: autoload/lh/tsort.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 21st Apr 2008
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
"------------------------------------------------------------------------
" Description: Library functions for Topological Sort
"
"------------------------------------------------------------------------
" Drop the file into {rtp}/autoload/lh/graph
" History: «history»
" TODO: «missing features»
" }}}1
"=============================================================================
let s:cpo_save=&cpo
set cpo&vim
"------------------------------------------------------------------------
" ## Debug {{{1
function! lh#graph#tsort#verbose(level)
let s:verbose = a:level
endfunction
function! s:Verbose(expr)
if exists('s:verbose') && s:verbose
echomsg a:expr
endif
endfunction
function! lh#graph#tsort#debug(expr)
return eval(a:expr)
endfunction
"------------------------------------------------------------------------
"## Helper functions {{{1
"# s:Successors_fully_defined(node) {{{2
function! s:Successors_fully_defined(node) dict
if has_key(self.table, a:node)
return self.table[a:node]
else
return []
endif
endfunction
"# s:Successors_lazy(node) {{{2
function! s:Successors_lazy(node) dict
if !has_key(self.table, a:node)
let nodes = self.fetch(a:node)
let self.table[a:node] = nodes
" if len(nodes) > 0
" let self.nb += 1
" endif
return nodes
else
return self.table[a:node]
endif
endfunction
"# s:PrepareDAG(dag) {{{2
function! s:PrepareDAG(dag)
if type(a:dag) == type(function('has_key'))
let dag = {
\ 'successors': function('s:Successors_lazy'),
\ 'fetch' : a:dag,
\ 'table' : {}
\}
else
let dag = {
\ 'successors': function('s:Successors_fully_defined'),
\ 'table' : deepcopy(a:dag)
\}
endif
return dag
endfunction
"## Depth-first search (recursive) {{{1
" Do not detect cyclic graphs
"# lh#graph#tsort#depth(dag, start_nodes) {{{2
function! lh#graph#tsort#depth(dag, start_nodes)
let dag = s:PrepareDAG(a:dag)
let results = []
let visited_nodes = { 'Visited':function('s:Visited')}
call s:RecursiveDTSort(dag, a:start_nodes, results, visited_nodes)
call reverse(results)
return results
endfunction
"# The real, recursive, T-Sort {{{2
"see boost.graph for a non recursive implementation
function! s:RecursiveDTSort(dag, start_nodes, results, visited_nodes)
for node in a:start_nodes
let visited = a:visited_nodes.Visited(node)
if visited == 1 | continue " done
elseif visited == 2 | throw "Tsort: cyclic graph detected: ".node
endif
let a:visited_nodes[node] = 2 " visiting
let succs = a:dag.successors(node)
try
call s:RecursiveDTSort(a:dag, succs, a:results, a:visited_nodes)
catch /Tsort:/
throw v:exception.'>'.node
endtry
let a:visited_nodes[node] = 1 " visited
call add(a:results, node)
endfor
endfunction
function! s:Visited(node) dict
return has_key(self, a:node) ? self[a:node] : 0
endfunction
"## Breadth-first search (non recursive) {{{1
"# lh#graph#tsort#breadth(dag, start_nodes) {{{2
" warning: This implementation does not work with lazy dag, but only with fully
" defined ones
function! lh#graph#tsort#breadth(dag, start_nodes)
let result = []
let dag = s:PrepareDAG(a:dag)
let queue = deepcopy(a:start_nodes)
while len(queue) > 0
let node = remove(queue, 0)
" echomsg "result <- ".node
call add(result, node)
let successors = dag.successors(node)
while len(successors) > 0
let m = s:RemoveEdgeFrom(dag, node)
" echomsg "graph loose ".node."->".m
if !s:HasIncomingEgde(dag, m)
" echomsg "queue <- ".m
call add(queue, m)
endif
endwhile
endwhile
if !s:Empty(dag)
throw "Tsort: cyclic graph detected: "
endif
return result
endfunction
function! s:HasIncomingEgde(dag, node)
for node in keys(a:dag.table)
if type(a:dag.table[node]) != type([])
continue
endif
if index(a:dag.table[node], a:node) != -1
return 1
endif
endfor
return 0
endfunction
function! s:RemoveEdgeFrom(dag, node)
let successors = a:dag.successors(a:node)
if len(successors) > 0
let successor = remove(successors, 0)
if len(successors) == 0
" echomsg "finished with ->".a:node
call remove(a:dag.table, a:node)
endif
return successor
endif
throw "No more edges from ".a:node
endfunction
function! s:Empty(dag)
" echomsg "len="len(a:dag.table)
return len(a:dag.table) == 0
endfunction
" }}}1
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker