def cache_build(self):
        self.load_preferences()

        valid_extensions = []
        if 'valid_extensions' in self.prefs:
            for extension in self.prefs['valid_extensions']:
                if extension == '*':
                    valid_extensions = True
                    break
                elif extension == '':
                    valid_extensions.append('')
                elif extension[0] != '.':
                    extension = '.' + extension
                valid_extensions.append(extension.lower())

        applications = []

        # Holds what binaries have been found
        binaries = []

        # Holds the directly searchable "# Htop (htop;)" lines
        aliased_items = []

        # Holds the [command, name] pairs for future lookup
        aliases = []

        # If we're going to include the applications or we want them for
        # filtering purposes, scan the .desktop files and get the applications
        if self.prefs['include_applications'] or self.prefs['filter_binaries']:
            applications = self.scan_applications()

        # Do we want to add binaries into the cache?
        if self.prefs['include_binaries'] is True:
            if self.prefs['filter_binaries'] is True:
                binaries_raw = self.scan_binaries()
                filterlist = [x['command'] for x in applications] + [x['descriptor'] for x in applications]
                for item in filterlist:
                    if item in binaries_raw:
                        binaries.append(item)
            else:
                binaries = self.scan_binaries()

        binaries = list(set(binaries))

        # Do we want to add applications from .desktop files into the cache?
        if self.prefs['include_applications']:
            if self.prefs['alias_applications']:
                if os.path.exists(file_cache_aliases):
                    os.remove(file_cache_aliases)
                for app in applications:
                    command = app['command']
                    if app['terminal']:
                        command += ';'
                    if app['name'].lower() != app['command'].lower():
                        title = self.format_alias(app['name'], command)
                        self.try_remove(app['command'], binaries)
                        aliased_items.append(title)
                        aliases.append([title, command])
                    else:
                        binaries.append(command)
                    if app['terminal']:
                        # Remove any non-terminal invoking versions from cache
                        self.try_remove(app['command'], binaries)
            else:
                for app in applications:
                    command = app['command']
                    # Add the "run in terminal" indicator to the command
                    if app['terminal']:
                        command += ';'
                    binaries.append(command)
                    # Remove any non-terminal invoking versions from cache
                    if app['terminal']:
                        self.try_remove(app['command'], binaries)

        binaries = list(set(binaries))

        watch_folders = []
        if 'watch_folders' in self.prefs:
            watch_folders = self.prefs['watch_folders']
        watch_folders = map(lambda x: x.replace('~', os.path.expanduser('~')), watch_folders)

        if self.debug:
            print('Done!')
            print('Watch folders:')
            print('Loading the list of folders to be excluded from the index...')

        ignore_folders = []

        if 'ignore_folders' in self.prefs:
            for exclude_folder in self.prefs['ignore_folders']:
                ignore_folders.append(exclude_folder.replace('~', os.path.expanduser('~')))

        if self.debug:
            print('Done!')
            print('Excluded folders:')
            print('First 5 items: ')
            print(ignore_folders[:5])
            print(str(len(ignore_folders)) + ' ignore_folders loaded in total')
            print('')

        filenames = []
        foldernames = []

        follow_symlinks = False
        try:
            if 'follow_symlinks' in self.prefs:
                follow_symlinks = self.prefs['follow_symlinks']
        except:
            pass

        if self.debug:
            if follow_symlinks:
                print('Indexing will not follow linked folders')
            else:
                print('Indexing will follow linked folders')

            print('Scanning files and folders, this may take a while...')

        for watchdir in watch_folders:
            for root, dirs , files in os.walk(watchdir, followlinks=follow_symlinks):
                dirs[:] = [d for d in dirs if os.path.join(root,d) not in ignore_folders]

                if self.prefs['scan_hidden_folders'] or root.find('/.')  == -1:
                    for name in files:
                        if self.prefs['include_hidden_files'] or name.startswith('.') == False:
                            if valid_extensions == True or os.path.splitext(name)[1].lower() in valid_extensions:
                                filenames.append(os.path.join(root,name))
                    for name in dirs:
                        if self.prefs['include_hidden_folders'] or name.startswith('.') == False:
                            foldernames.append(os.path.join(root,name) + '/')

        foldernames = list(filter(lambda x: x not in ignore_folders, foldernames))

        include_items = []

        if 'include_items' in self.prefs:
            include_items = []
            for item in self.prefs['include_items']:
                if type(item) == list:
                    if len(item) > 1:
                        title = self.prefs['indicator_alias']
                        title += ' ' + item[0]
                        aliased_items.append(title)
                        aliases.append([title, item[1]])
                    else:
                        if self.debug:
                            print("There are aliased items in the configuration with no command.")
                else:
                    include_items.append(item)
        else:
            include_items = []

        # Remove any manually added include items differing by a colon
        # e.g. ["htop", "htop;"] becomes just ["htop;"]
        for item in include_items:
            if item[-1] == ';' and item[0:-1] in binaries:
                binaries.remove(item[0:-1])

        plugins = self.plugins_available()

        # Save the alias lookup file and aliased_items
        self.save_json(file_cache_aliasesLookup, aliases)
        self.cache_save(aliased_items, file_cache_aliases)
        self.cache_save(binaries, file_cache_binaries)
        self.cache_save(foldernames, file_cache_folders)
        self.cache_save(filenames, file_cache_files)

        other = self.sort_shortest(include_items + aliased_items + binaries + foldernames + filenames)

        if 'exclude_items' in self.prefs:
            for item in self.prefs['exclude_items']:
                try:
                    other.remove(item)
                except __HOLE__:
                    pass

        other += ['rebuild cache']
        self.cache_save(other, file_cache)

        out = plugins
        out += other

        if self.debug:
            print('Done!')
            print('Cache building has finished.')
            print('')

        return out
dataset/ETHPy150Open markjones112358/dmenu-extended/dmenu_extended.py/dmenu.cache_build