Community

    • Login
    • Search
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search

    File/tab specific word wrap (vs. global enable) -- THREAD REBOOT

    General Discussion
    1
    2
    86
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Alan Kilborn
      Alan Kilborn last edited by Alan Kilborn

      I thought it might be time to “freshen” the title topic, as it is something that comes up from time to time, and existing references (see the script HERE in the first two postings of the thread) are a little dated – coming up on 7 years old!

      Also, the script provided in that thread is a bit awkward, perhaps because it is so old, I don’t know…

      Anyway, if you’ve ever wanted the Word wrap setting on the View menu to be in effect on certain file tabs that you have open, and not on others, well, that’s currently a limitation of Notepad++ (the setting is currently “global” to all of your tabs). But with a script, we can do better than that, and achieve true tab-level control of what is wrapped and what isn’t.

      With each run of the script, the state of wrapping for the active file will be “toggled” – if wrap was “off” when the script was run, it will be turned “on”; if wrap was “on” at script running, it will be turned “off”.

      A note about using the script: If you use it, you need to totally forget and ignore the View menu’s command for Word wrap. Just…forget it; use (by running) the script exclusively to toggle the current setting for the active file/tab. Don’t count on the View menu entry to show you the current state, either – it will often lie to you if you are using the script.

      I call the script WordWrapToggleForActiveTab.py and here is its listing:

      # -*- coding: utf-8 -*-
      
      # references:
      #  https://community.notepad-plus-plus.org/topic/23855/file-tab-specific-word-wrap-vs-global-enable-thread-reboot
      #  https://community.notepad-plus-plus.org/topic/10985/file-specific-word-wrap-vs-global-enable
      #  https://github.com/notepad-plus-plus/notepad-plus-plus/issues/5232
      
      from Npp import *
      
      #-------------------------------------------------------------------------------
      
      class WWTFAT(object):
      
          def __init__(self):
              self.wrap_by_buffer_id_dict = {}
              notepad.callback(self.bufferactivated_callback, [NOTIFICATION.BUFFERACTIVATED])
      
          def bufferactivated_callback(self, args):
              bid = args['bufferID']
              editor.setWrapMode(self.wrap_by_buffer_id_dict[bid] if bid in self.wrap_by_buffer_id_dict else 0)
      
          def toggle_wrap_mode(self):
              bid = notepad.getCurrentBufferID()
              if bid in self.wrap_by_buffer_id_dict:
                  self.wrap_by_buffer_id_dict[bid] = 1 if self.wrap_by_buffer_id_dict[bid] == 0 else 0  # toggle
              else:
                  self.wrap_by_buffer_id_dict[bid] = 1  # turn wrap on for current file
              editor.setWrapMode(self.wrap_by_buffer_id_dict[bid])
              self.sb_output('Wrapping is {} for active tab'.format('ON' if self.wrap_by_buffer_id_dict[bid] else 'OFF'))
      
          def sb_output(self, *args):  # output to N++'s status bar (will be overwritten by N++ e.g. when active tab is changed)
              notepad.setStatusBar(STATUSBARSECTION.DOCTYPE, ' '.join(map(str, args)))
      
      #-------------------------------------------------------------------------------
      
      # to run via another file, e.g., startup.py, put these lines (uncommented and unindented) in that file:
      #  import WordWrapToggleForActiveTab
      #  wwtfat = wwtfat.WWTFAT()
      
      # when this script is run interactively, it will toggle the wrap setting on the currently active tab
      
      if __name__ == '__main__':
          try:
              wwtfat
          except NameError:
              wwtfat = WWTFAT()
          wwtfat.toggle_wrap_mode()
      

      For easy access, I like to assign the script to the keycombo Ctrl+Alt+w, and I also have it on the editor right-click context menu:

      aec5af23-1d66-42be-a103-88f787927b31-image.png

      I achieve the entry on the context menu by putting this line in the appropriate file (see “setting up and using…”) below:

      <Item PluginEntryName = "Python Script" PluginCommandItemName = "WordWrapToggleForActiveTab" ItemNameAs = "Toggle wrap on/off for this file           Ctrl+Alt+w" />
      

      When the wrap state is changed via the script, the Notepad++ status bar will show the current state, example:

      23c97418-0b1c-42e5-8eac-82abc42df4b1-image.png

      For info on setting up and using a script, see HERE.

      1 Reply Last reply Reply Quote 2
      • Referenced by  Alan Kilborn Alan Kilborn 
      • Alan Kilborn
        Alan Kilborn last edited by

        In the time since I rebooted the topic, someone has found it useful, but they have asked for the wrap state of files in the default session to be remembered across runs of Notepad++.

        Here’s WordWrapToggleForActiveTabWithPersistence.py:

        # -*- coding: utf-8 -*-
        from __future__ import print_function
        
        # references:
        #  https://community.notepad-plus-plus.org/topic/23855/file-tab-specific-word-wrap-vs-global-enable-thread-reboot
        #  https://community.notepad-plus-plus.org/topic/10985/file-specific-word-wrap-vs-global-enable
        #  https://github.com/notepad-plus-plus/notepad-plus-plus/issues/5232
        
        from Npp import *
        import os
        import inspect
        import json
        
        #-------------------------------------------------------------------------------
        
        class WWTFATWP(object):
        
            def __init__(self):
                self.debug = True if 0 else False
                self.this_script_name = inspect.getframeinfo(inspect.currentframe()).filename.split(os.sep)[-1].rsplit('.', 1)[0]
                self.wrap_by_buffer_id_dict = {}
                self.pathname_by_buffer_id_dict = {}
                self.this_script_path_without_ext = inspect.getframeinfo(inspect.currentframe()).filename.rsplit('.', 1)[0]
                self.settings_json_file_path = self.this_script_path_without_ext + '.json'
                # read settings written the last time Notepad++ was shut down:
                pathnames_with_wrap_on_list = []
                if os.path.isfile(self.settings_json_file_path):
                    self.dprint('json file found')
                    try:
                        with open(self.settings_json_file_path) as f:
                            pathnames_with_wrap_on_list = json.load(f)['wrap_on_list']
                    except:
                        self.dprint('problem opening/reading json file')
                self.dprint('pathnames_with_wrap_on_list:', pathnames_with_wrap_on_list)
                for (pathname, buffer_id, index, view) in notepad.getFiles():
                    self.wrap_by_buffer_id_dict[buffer_id] = 1 if pathname in pathnames_with_wrap_on_list else 0
                    self.pathname_by_buffer_id_dict[buffer_id] = pathname
                self.dprint('wrap_by_buffer_id_dict:', self.wrap_by_buffer_id_dict)
                self.dprint('pathname_by_buffer_id_dict:', self.pathname_by_buffer_id_dict)
                notepad.callback(self.bufferactivated_callback, [NOTIFICATION.BUFFERACTIVATED])
                notepad.callback(self.shutdown_notify, [NOTIFICATION.SHUTDOWN])
                editor.callback(self.updateui_callback, [SCINTILLANOTIFICATION.UPDATEUI])
                self.bufferactivated_callback(None)  # artificial call to get the wrap mode set for the current file
        
            def updateui_callback(self, args):
                # this is mainly useful for when a tab is renamed; so that it gets "noticed" by our logic asap
                self.bufferactivated_callback(None)
        
            def bufferactivated_callback(self, args):
                curr_bid = args['bufferID'] if args else notepad.getCurrentBufferID()
                curr_pathname = notepad.getCurrentFilename()
                editor.setWrapMode(self.wrap_by_buffer_id_dict[curr_bid] if curr_bid in self.wrap_by_buffer_id_dict else 0)
                self.pathname_by_buffer_id_dict[curr_bid] = curr_pathname  # maintain link between constant bid and possibly changing pathname
        
            def shutdown_notify(self, args):
                # write settings so they persist between runs of N++
                pathnames_with_wrap_on_list = []
                for bid in self.pathname_by_buffer_id_dict:
                    pathname_for_buffer_id = self.pathname_by_buffer_id_dict[bid]
                    if bid in self.wrap_by_buffer_id_dict:
                        wrap_for_buffer_id = self.wrap_by_buffer_id_dict[bid]
                        if wrap_for_buffer_id == 1:
                            # only save state for paths that have wrap turned on
                            if pathname_for_buffer_id not in pathnames_with_wrap_on_list:
                                pathnames_with_wrap_on_list.append(pathname_for_buffer_id)
                    else:
                        pass  # this part of the code will be reached for the renegade "new x" document that isn't visible!
                try:
                    with open(self.settings_json_file_path, 'w') as f:
                        f.write(json.dumps({ 'wrap_on_list' : pathnames_with_wrap_on_list }, sort_keys=True, indent=1, default=str))
                except:
                    pass
        
            def toggle_wrap_mode(self):
                curr_bid = notepad.getCurrentBufferID()
                curr_pathname = notepad.getCurrentFilename()
                if curr_bid in self.wrap_by_buffer_id_dict:
                    self.wrap_by_buffer_id_dict[curr_bid] = 1 if self.wrap_by_buffer_id_dict[curr_bid] == 0 else 0  # toggle
                else:
                    self.wrap_by_buffer_id_dict[curr_bid] = 1  # turn wrap on for current file
                editor.setWrapMode(self.wrap_by_buffer_id_dict[curr_bid])
                self.sb_output('Wrapping is {} for active tab'.format('ON' if self.wrap_by_buffer_id_dict[curr_bid] else 'OFF'))
                self.pathname_by_buffer_id_dict[curr_bid] = curr_pathname  # maintain link between constant bid and possibly changing pathname
        
            def print(self, *args, **kwargs):
                try:
                    self.print_first
                except AttributeError:
                    self.print_first = True
                if self.print_first:
                    console.show()      # this will put input focus in the PS console window, at the >>> prompt
                    #console.clear()
                    editor.grabFocus()  # put input focus back into the editor window
                    self.print_first = False
                d_tag = '<DBG>' if 'debug' in kwargs else ''
                if 'debug' in kwargs: del kwargs['debug']
                print(self.__class__.__name__ + d_tag + ':', *args, **kwargs)
        
            def dprint(self, *args, **kwargs):  # debug print function
                if self.debug:
                    kwargs['debug'] = True
                    self.print(*args, **kwargs)
        
            def sb_output(self, *args):  # output to N++'s status bar (will be overwritten by N++ e.g. when active tab is changed)
                notepad.setStatusBar(STATUSBARSECTION.DOCTYPE, ' '.join(map(str, args)))
        
        #-------------------------------------------------------------------------------
        
        # to run via another file, e.g., startup.py, put these lines (uncommented and unindented) in that file:
        #  import WordWrapToggleForActiveTabWithPersistence
        #  wwtfatwp = WordWrapToggleForActiveTabWithPersistence.WWTFATWP()
        
        if __name__ == '__main__':
        
            try:
                wwtfatwp
            except NameError:
                wwtfatwp = WWTFATWP()
        
            # when this script is run interactively, it will toggle the wrap setting on the currently active tab
            wwtfatwp.toggle_wrap_mode()
        
        1 Reply Last reply Reply Quote 1
        • Referenced by  Alan Kilborn Alan Kilborn 
        • First post
          Last post
        Copyright © 2014 NodeBB Forums | Contributors